Merge branch 'master' into auth-round
This commit is contained in:
commit
255ec0c139
2
.gitignore
vendored
2
.gitignore
vendored
@ -30,3 +30,5 @@
|
|||||||
|
|
||||||
# Build artifacts
|
# Build artifacts
|
||||||
out/
|
out/
|
||||||
|
|
||||||
|
.vscode
|
||||||
|
101
.gitlab-ci.yml
101
.gitlab-ci.yml
@ -1,4 +1,6 @@
|
|||||||
stages:
|
stages:
|
||||||
|
- test
|
||||||
|
- js-build
|
||||||
- build
|
- build
|
||||||
variables:
|
variables:
|
||||||
GIT_DEPTH: "3"
|
GIT_DEPTH: "3"
|
||||||
@ -7,13 +9,13 @@ variables:
|
|||||||
RUSTFLAGS: ""
|
RUSTFLAGS: ""
|
||||||
CARGOFLAGS: ""
|
CARGOFLAGS: ""
|
||||||
cache:
|
cache:
|
||||||
key: "$CI_BUILD_NAME/$CI_BUILD_REF_NAME"
|
key: "$CI_BUILD_REF_NAME"
|
||||||
untracked: true
|
untracked: true
|
||||||
linux-stable:
|
linux-stable:
|
||||||
stage: build
|
stage: build
|
||||||
image: ethcore/rust:stable
|
image: ethcore/rust:stable
|
||||||
only:
|
only:
|
||||||
- master
|
- $NIGHTLY
|
||||||
- beta
|
- beta
|
||||||
- tags
|
- tags
|
||||||
- stable
|
- stable
|
||||||
@ -43,7 +45,7 @@ linux-stable-14.04:
|
|||||||
stage: build
|
stage: build
|
||||||
image: ethcore/rust-14.04:latest
|
image: ethcore/rust-14.04:latest
|
||||||
only:
|
only:
|
||||||
- master
|
- $NIGHTLY
|
||||||
- beta
|
- beta
|
||||||
- tags
|
- tags
|
||||||
- stable
|
- stable
|
||||||
@ -73,7 +75,7 @@ linux-beta:
|
|||||||
stage: build
|
stage: build
|
||||||
image: ethcore/rust:beta
|
image: ethcore/rust:beta
|
||||||
only:
|
only:
|
||||||
- master
|
- $NIGHTLY
|
||||||
- beta
|
- beta
|
||||||
- tags
|
- tags
|
||||||
- stable
|
- stable
|
||||||
@ -92,7 +94,7 @@ linux-nightly:
|
|||||||
stage: build
|
stage: build
|
||||||
image: ethcore/rust:nightly
|
image: ethcore/rust:nightly
|
||||||
only:
|
only:
|
||||||
- master
|
- $NIGHTLY
|
||||||
- beta
|
- beta
|
||||||
- tags
|
- tags
|
||||||
- stable
|
- stable
|
||||||
@ -111,7 +113,7 @@ linux-centos:
|
|||||||
stage: build
|
stage: build
|
||||||
image: ethcore/rust-centos:latest
|
image: ethcore/rust-centos:latest
|
||||||
only:
|
only:
|
||||||
- master
|
- $NIGHTLY
|
||||||
- beta
|
- beta
|
||||||
- tags
|
- tags
|
||||||
- stable
|
- stable
|
||||||
@ -136,6 +138,7 @@ linux-armv7:
|
|||||||
stage: build
|
stage: build
|
||||||
image: ethcore/rust-armv7:latest
|
image: ethcore/rust-armv7:latest
|
||||||
only:
|
only:
|
||||||
|
- $NIGHTLY
|
||||||
- beta
|
- beta
|
||||||
- tags
|
- tags
|
||||||
- stable
|
- stable
|
||||||
@ -175,6 +178,7 @@ linux-arm:
|
|||||||
stage: build
|
stage: build
|
||||||
image: ethcore/rust-arm:latest
|
image: ethcore/rust-arm:latest
|
||||||
only:
|
only:
|
||||||
|
- $NIGHTLY
|
||||||
- beta
|
- beta
|
||||||
- tags
|
- tags
|
||||||
- stable
|
- stable
|
||||||
@ -214,6 +218,7 @@ linux-armv6:
|
|||||||
stage: build
|
stage: build
|
||||||
image: ethcore/rust-armv6:latest
|
image: ethcore/rust-armv6:latest
|
||||||
only:
|
only:
|
||||||
|
- $NIGHTLY
|
||||||
- beta
|
- beta
|
||||||
- tags
|
- tags
|
||||||
- stable
|
- stable
|
||||||
@ -246,6 +251,7 @@ linux-aarch64:
|
|||||||
stage: build
|
stage: build
|
||||||
image: ethcore/rust-aarch64:latest
|
image: ethcore/rust-aarch64:latest
|
||||||
only:
|
only:
|
||||||
|
- $NIGHTLY
|
||||||
- beta
|
- beta
|
||||||
- tags
|
- tags
|
||||||
- stable
|
- stable
|
||||||
@ -284,6 +290,7 @@ linux-aarch64:
|
|||||||
darwin:
|
darwin:
|
||||||
stage: build
|
stage: build
|
||||||
only:
|
only:
|
||||||
|
- $NIGHTLY
|
||||||
- beta
|
- beta
|
||||||
- tags
|
- tags
|
||||||
- stable
|
- stable
|
||||||
@ -304,6 +311,7 @@ darwin:
|
|||||||
windows:
|
windows:
|
||||||
stage: build
|
stage: build
|
||||||
only:
|
only:
|
||||||
|
- $NIGHTLY
|
||||||
- beta
|
- beta
|
||||||
- tags
|
- tags
|
||||||
- stable
|
- stable
|
||||||
@ -350,49 +358,51 @@ windows:
|
|||||||
- target/release/parity.pdb
|
- target/release/parity.pdb
|
||||||
- nsis/InstallParity.exe
|
- nsis/InstallParity.exe
|
||||||
name: "x86_64-pc-windows-msvc_parity"
|
name: "x86_64-pc-windows-msvc_parity"
|
||||||
#test-darwin:
|
test-darwin:
|
||||||
# stage: build
|
stage: test
|
||||||
# before_script:
|
only:
|
||||||
# - git submodule update --init --recursive
|
- beta
|
||||||
# script:
|
- tags
|
||||||
# - export RUST_BACKTRACE=1
|
- stable
|
||||||
# - ./test.sh $CARGOFLAGS --no-release
|
|
||||||
# tags:
|
|
||||||
# - osx
|
|
||||||
#test-windows:
|
|
||||||
# stage: build
|
|
||||||
# before_script:
|
|
||||||
# - git submodule update --init --recursive
|
|
||||||
# script:
|
|
||||||
# - set RUST_BACKTRACE=1
|
|
||||||
# - cargo test --features json-tests -p rlp -p ethash -p ethcore -p ethcore-bigint -p ethcore-dapps -p ethcore-rpc -p ethcore-signer -p ethcore-util -p ethcore-network -p ethcore-io -p ethkey -p ethstore -p ethsync -p ethcore-ipc -p ethcore-ipc-tests -p ethcore-ipc-nano -p parity %CARGOFLAGS% --verbose --release
|
|
||||||
# tags:
|
|
||||||
# - rust-windows
|
|
||||||
# allow_failure: true
|
|
||||||
test-linux:
|
|
||||||
stage: build
|
|
||||||
before_script:
|
before_script:
|
||||||
- git submodule update --init --recursive
|
- git submodule update --init --recursive
|
||||||
script:
|
script:
|
||||||
- export RUST_BACKTRACE=1
|
- export RUST_BACKTRACE=1
|
||||||
- ./test.sh $CARGOFLAGS --no-release
|
- ./test.sh $CARGOFLAGS --no-release
|
||||||
tags:
|
tags:
|
||||||
- rust-test
|
- osx
|
||||||
js-release:
|
test-windows:
|
||||||
stage: build
|
stage: test
|
||||||
image: ethcore/javascript:latest
|
|
||||||
only:
|
only:
|
||||||
- master
|
- beta
|
||||||
|
- tags
|
||||||
|
- stable
|
||||||
before_script:
|
before_script:
|
||||||
- ./js/scripts/install-deps.sh
|
- git submodule update --init --recursive
|
||||||
script:
|
script:
|
||||||
- ./js/scripts/build.sh
|
- set RUST_BACKTRACE=1
|
||||||
- ./js/scripts/release.sh
|
- cargo test --features json-tests -p rlp -p ethash -p ethcore -p ethcore-bigint -p ethcore-dapps -p ethcore-rpc -p ethcore-signer -p ethcore-util -p ethcore-network -p ethcore-io -p ethkey -p ethstore -p ethsync -p ethcore-ipc -p ethcore-ipc-tests -p ethcore-ipc-nano -p parity %CARGOFLAGS% --verbose --release
|
||||||
tags:
|
tags:
|
||||||
- javascript
|
- rust-windows
|
||||||
|
allow_failure: true
|
||||||
|
test-rust-stable:
|
||||||
|
stage: test
|
||||||
|
image: ethcore/rust:stable
|
||||||
|
before_script:
|
||||||
|
- git submodule update --init --recursive
|
||||||
|
- export JS_FILES_MODIFIED=$(git --no-pager diff --name-only $CI_BUILD_REF_NAME $(git merge-base $CI_BUILD_REF_NAME master) | grep \.js | wc -l)
|
||||||
|
- echo $JS_FILES_MODIFIED
|
||||||
|
- if [ -z $JS_FILES_MODIFIED ]; then echo "skip js test"; fi
|
||||||
|
script:
|
||||||
|
- export RUST_BACKTRACE=1
|
||||||
|
- echo $JS_FILES_MODIFIED
|
||||||
|
- if [ -z $JS_FILES_MODIFIED ]; then echo "skip js test"; else ./test.sh $CARGOFLAGS --no-release; fi
|
||||||
|
tags:
|
||||||
|
- rust
|
||||||
|
- rust-stable
|
||||||
js-tests:
|
js-tests:
|
||||||
stage: build
|
stage: test
|
||||||
image: ethcore/javascript:latest
|
image: ethcore/rust:stable
|
||||||
before_script:
|
before_script:
|
||||||
- ./js/scripts/install-deps.sh
|
- ./js/scripts/install-deps.sh
|
||||||
script:
|
script:
|
||||||
@ -401,3 +411,18 @@ js-tests:
|
|||||||
- ./js/scripts/build.sh
|
- ./js/scripts/build.sh
|
||||||
tags:
|
tags:
|
||||||
- javascript-test
|
- javascript-test
|
||||||
|
js-release:
|
||||||
|
stage: js-build
|
||||||
|
only:
|
||||||
|
- master
|
||||||
|
- beta
|
||||||
|
- stable
|
||||||
|
- tags
|
||||||
|
image: ethcore/rust:stable
|
||||||
|
before_script:
|
||||||
|
- ./js/scripts/install-deps.sh
|
||||||
|
script:
|
||||||
|
- ./js/scripts/build.sh
|
||||||
|
- ./js/scripts/release.sh
|
||||||
|
tags:
|
||||||
|
- javascript
|
||||||
|
12
Cargo.lock
generated
12
Cargo.lock
generated
@ -312,7 +312,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ethcore-bigint"
|
name = "ethcore-bigint"
|
||||||
version = "0.1.1"
|
version = "0.1.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"heapsize 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"heapsize 0.3.6 (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)",
|
||||||
@ -549,7 +549,7 @@ dependencies = [
|
|||||||
"elastic-array 0.6.0 (git+https://github.com/ethcore/elastic-array)",
|
"elastic-array 0.6.0 (git+https://github.com/ethcore/elastic-array)",
|
||||||
"env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"eth-secp256k1 0.5.4 (git+https://github.com/ethcore/rust-secp256k1)",
|
"eth-secp256k1 0.5.4 (git+https://github.com/ethcore/rust-secp256k1)",
|
||||||
"ethcore-bigint 0.1.1",
|
"ethcore-bigint 0.1.2",
|
||||||
"ethcore-bloom-journal 0.1.0",
|
"ethcore-bloom-journal 0.1.0",
|
||||||
"ethcore-devtools 1.4.0",
|
"ethcore-devtools 1.4.0",
|
||||||
"heapsize 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"heapsize 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -580,7 +580,7 @@ name = "ethcrypto"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"eth-secp256k1 0.5.4 (git+https://github.com/ethcore/rust-secp256k1)",
|
"eth-secp256k1 0.5.4 (git+https://github.com/ethcore/rust-secp256k1)",
|
||||||
"ethcore-bigint 0.1.1",
|
"ethcore-bigint 0.1.2",
|
||||||
"ethkey 0.2.0",
|
"ethkey 0.2.0",
|
||||||
"rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"tiny-keccak 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"tiny-keccak 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -603,7 +603,7 @@ version = "0.2.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"docopt 0.6.80 (registry+https://github.com/rust-lang/crates.io-index)",
|
"docopt 0.6.80 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"eth-secp256k1 0.5.4 (git+https://github.com/ethcore/rust-secp256k1)",
|
"eth-secp256k1 0.5.4 (git+https://github.com/ethcore/rust-secp256k1)",
|
||||||
"ethcore-bigint 0.1.1",
|
"ethcore-bigint 0.1.2",
|
||||||
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lazy_static 0.2.1 (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)",
|
||||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -1249,7 +1249,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/ethcore/js-precompiled.git#f8bd7fa67e91daea3ac698ebcc447fae494802cb"
|
source = "git+https://github.com/ethcore/js-precompiled.git#3a77750a2d29e2babb52bc4dfa5c40b2e26b97ce"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
@ -1463,7 +1463,7 @@ name = "rlp"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"elastic-array 0.6.0 (git+https://github.com/ethcore/elastic-array)",
|
"elastic-array 0.6.0 (git+https://github.com/ethcore/elastic-array)",
|
||||||
"ethcore-bigint 0.1.1",
|
"ethcore-bigint 0.1.2",
|
||||||
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
[![Join the chat at https://gitter.im/ethcore/parity.js](https://badges.gitter.im/ethcore/parity.js.svg)](https://gitter.im/ethcore/parity.js?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
[![Join the chat at https://gitter.im/ethcore/parity.js](https://badges.gitter.im/ethcore/parity.js.svg)](https://gitter.im/ethcore/parity.js?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||||
|
|
||||||
[![Build Status][travis-image]][travis-url] [![Coverage Status][coveralls-image]][coveralls-url] [![Join the chat at https://gitter.im/ethcore/parity][gitter-image]][gitter-url] [![GPLv3][license-image]][license-url]
|
[![Build Status][travis-image]][travis-url] [![build status](https://gitlab.ethcore.io/Mirrors/ethcore-parity/badges/master/build.svg)](https://gitlab.ethcore.io/Mirrors/ethcore-parity/commits/master) [![Coverage Status][coveralls-image]][coveralls-url] [![Join the chat at https://gitter.im/ethcore/parity][gitter-image]][gitter-url] [![GPLv3][license-image]][license-url]
|
||||||
|
|
||||||
[Internal Documentation][doc-url]
|
[Internal Documentation][doc-url]
|
||||||
|
|
||||||
@ -57,6 +57,13 @@ We recommend installing Rust through [rustup](https://www.rustup.rs/). If you do
|
|||||||
$ curl https://sh.rustup.rs -sSf | sh
|
$ curl https://sh.rustup.rs -sSf | sh
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Parity also requires `gcc`, `g++` and `make` packages to be installed.
|
||||||
|
- OSX:
|
||||||
|
```bash
|
||||||
|
$ curl https://sh.rustup.rs -sSf | sh
|
||||||
|
```
|
||||||
|
|
||||||
|
`clang` and `make` are required. These come with Xcode command line tools or can be installed with homebrew.
|
||||||
- Windows
|
- Windows
|
||||||
|
|
||||||
Make sure you have Visual Studio 2015 with C++ support installed. Next, download and run the rustup installer from
|
Make sure you have Visual Studio 2015 with C++ support installed. Next, download and run the rustup installer from
|
||||||
|
@ -11,7 +11,11 @@
|
|||||||
"blockReward": "0x4563918244F40000",
|
"blockReward": "0x4563918244F40000",
|
||||||
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
|
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
|
||||||
"homesteadTransition": "0x118c30",
|
"homesteadTransition": "0x118c30",
|
||||||
"eip150Transition": "0x2625a0"
|
"eip150Transition": "0x2625a0",
|
||||||
|
"eip155Transition": "0x7fffffffffffffff",
|
||||||
|
"eip160Transition": "0x7fffffffffffffff",
|
||||||
|
"eip161abcTransition": "0x7fffffffffffffff",
|
||||||
|
"eip161dTransition": "0x7fffffffffffffff"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -10,7 +10,11 @@
|
|||||||
"blockReward": "0x4563918244F40000",
|
"blockReward": "0x4563918244F40000",
|
||||||
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
|
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
|
||||||
"homesteadTransition": "0x0",
|
"homesteadTransition": "0x0",
|
||||||
"eip150Transition": "0x0"
|
"eip150Transition": "0x0",
|
||||||
|
"eip155Transition": "0x7fffffffffffffff",
|
||||||
|
"eip160Transition": "0x7fffffffffffffff",
|
||||||
|
"eip161abcTransition": "0x7fffffffffffffff",
|
||||||
|
"eip161dTransition": "0x7fffffffffffffff"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
47
ethcore/res/ethereum/eip161_test.json
Normal file
47
ethcore/res/ethereum/eip161_test.json
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
{
|
||||||
|
"name": "Homestead (Test)",
|
||||||
|
"engine": {
|
||||||
|
"Ethash": {
|
||||||
|
"params": {
|
||||||
|
"gasLimitBoundDivisor": "0x0400",
|
||||||
|
"minimumDifficulty": "0x020000",
|
||||||
|
"difficultyBoundDivisor": "0x0800",
|
||||||
|
"durationLimit": "0x0d",
|
||||||
|
"blockReward": "0x4563918244F40000",
|
||||||
|
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
|
||||||
|
"homesteadTransition": "0x0",
|
||||||
|
"eip150Transition": "0x0",
|
||||||
|
"eip155Transition": "0x7fffffffffffffff",
|
||||||
|
"eip160Transition": "0x0",
|
||||||
|
"eip161abcTransition": "0x0",
|
||||||
|
"eip161dTransition": "0x0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"params": {
|
||||||
|
"accountStartNonce": "0x00",
|
||||||
|
"maximumExtraDataSize": "0x20",
|
||||||
|
"minGasLimit": "0x1388",
|
||||||
|
"networkID" : "0x1"
|
||||||
|
},
|
||||||
|
"genesis": {
|
||||||
|
"seal": {
|
||||||
|
"ethereum": {
|
||||||
|
"nonce": "0x0000000000000042",
|
||||||
|
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"difficulty": "0x400000000",
|
||||||
|
"author": "0x0000000000000000000000000000000000000000",
|
||||||
|
"timestamp": "0x00",
|
||||||
|
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"extraData": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa",
|
||||||
|
"gasLimit": "0x1388"
|
||||||
|
},
|
||||||
|
"accounts": {
|
||||||
|
"0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } },
|
||||||
|
"0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } },
|
||||||
|
"0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } },
|
||||||
|
"0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }
|
||||||
|
}
|
||||||
|
}
|
@ -15,7 +15,11 @@
|
|||||||
"difficultyHardforkTransition": "0x59d9",
|
"difficultyHardforkTransition": "0x59d9",
|
||||||
"difficultyHardforkBoundDivisor": "0x0200",
|
"difficultyHardforkBoundDivisor": "0x0200",
|
||||||
"bombDefuseTransition": "0x30d40",
|
"bombDefuseTransition": "0x30d40",
|
||||||
"eip150Transition": "0x7fffffffffffffff"
|
"eip150Transition": "0x7fffffffffffffff",
|
||||||
|
"eip155Transition": "0x7fffffffffffffff",
|
||||||
|
"eip160Transition": "0x7fffffffffffffff",
|
||||||
|
"eip161abcTransition": "0x7fffffffffffffff",
|
||||||
|
"eip161dTransition": "0x7fffffffffffffff"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -130,7 +130,11 @@
|
|||||||
"0xbb9bc244d798123fde783fcc1c72d3bb8c189413",
|
"0xbb9bc244d798123fde783fcc1c72d3bb8c189413",
|
||||||
"0x807640a13483f8ac783c557fcdf27be11ea4ac7a"
|
"0x807640a13483f8ac783c557fcdf27be11ea4ac7a"
|
||||||
],
|
],
|
||||||
"eip150Transition": "0x259518"
|
"eip150Transition": "0x259518",
|
||||||
|
"eip155Transition": 2642462,
|
||||||
|
"eip160Transition": 2642462,
|
||||||
|
"eip161abcTransition": 2642462,
|
||||||
|
"eip161dTransition": 2642462
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -130,7 +130,11 @@
|
|||||||
"0xbb9bc244d798123fde783fcc1c72d3bb8c189413",
|
"0xbb9bc244d798123fde783fcc1c72d3bb8c189413",
|
||||||
"0x807640a13483f8ac783c557fcdf27be11ea4ac7a"
|
"0x807640a13483f8ac783c557fcdf27be11ea4ac7a"
|
||||||
],
|
],
|
||||||
"eip150Transition": "0x7fffffffffffffff"
|
"eip150Transition": "0x7fffffffffffffff",
|
||||||
|
"eip155Transition": "0x7fffffffffffffff",
|
||||||
|
"eip160Transition": "0x7fffffffffffffff",
|
||||||
|
"eip161abcTransition": "0x7fffffffffffffff",
|
||||||
|
"eip161dTransition": "0x7fffffffffffffff"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -10,7 +10,11 @@
|
|||||||
"blockReward": "0x4563918244F40000",
|
"blockReward": "0x4563918244F40000",
|
||||||
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
|
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
|
||||||
"homesteadTransition": "0x7fffffffffffffff",
|
"homesteadTransition": "0x7fffffffffffffff",
|
||||||
"eip150Transition": "0x7fffffffffffffff"
|
"eip150Transition": "0x7fffffffffffffff",
|
||||||
|
"eip155Transition": "0x7fffffffffffffff",
|
||||||
|
"eip160Transition": "0x7fffffffffffffff",
|
||||||
|
"eip161abcTransition": "0x7fffffffffffffff",
|
||||||
|
"eip161dTransition": "0x7fffffffffffffff"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -10,7 +10,11 @@
|
|||||||
"blockReward": "0x4563918244F40000",
|
"blockReward": "0x4563918244F40000",
|
||||||
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
|
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
|
||||||
"homesteadTransition": "0x0",
|
"homesteadTransition": "0x0",
|
||||||
"eip150Transition": "0x7fffffffffffffff"
|
"eip150Transition": "0x7fffffffffffffff",
|
||||||
|
"eip155Transition": "0x7fffffffffffffff",
|
||||||
|
"eip160Transition": "0x7fffffffffffffff",
|
||||||
|
"eip161abcTransition": "0x7fffffffffffffff",
|
||||||
|
"eip161dTransition": "0x7fffffffffffffff"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -10,7 +10,11 @@
|
|||||||
"blockReward": "0x4563918244F40000",
|
"blockReward": "0x4563918244F40000",
|
||||||
"registrar": "0x52dff57a8a1532e6afb3dc07e2af58bb9eb05b3d",
|
"registrar": "0x52dff57a8a1532e6afb3dc07e2af58bb9eb05b3d",
|
||||||
"homesteadTransition": "0x789b0",
|
"homesteadTransition": "0x789b0",
|
||||||
"eip150Transition": "0x1b34d8"
|
"eip150Transition": "0x1b34d8",
|
||||||
|
"eip155Transition": "0x7fffffffffffffff",
|
||||||
|
"eip160Transition": "0x7fffffffffffffff",
|
||||||
|
"eip161abcTransition": "0x7fffffffffffffff",
|
||||||
|
"eip161dTransition": "0x7fffffffffffffff"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -10,7 +10,11 @@
|
|||||||
"blockReward": "0x14D1120D7B160000",
|
"blockReward": "0x14D1120D7B160000",
|
||||||
"registrar": "5e70c0bbcd5636e0f9f9316e9f8633feb64d4050",
|
"registrar": "5e70c0bbcd5636e0f9f9316e9f8633feb64d4050",
|
||||||
"homesteadTransition": "0x7fffffffffffffff",
|
"homesteadTransition": "0x7fffffffffffffff",
|
||||||
"eip150Transition": "0x7fffffffffffffff"
|
"eip150Transition": "0x7fffffffffffffff",
|
||||||
|
"eip155Transition": "0x7fffffffffffffff",
|
||||||
|
"eip160Transition": "0x7fffffffffffffff",
|
||||||
|
"eip161abcTransition": "0x7fffffffffffffff",
|
||||||
|
"eip161dTransition": "0x7fffffffffffffff"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 97066e40ccd061f727deb5cd860e4d9135aa2551
|
Subproject commit 853333e7da312775fb8f32f2c2771b8578cd0d79
|
@ -130,7 +130,11 @@
|
|||||||
"0xbb9bc244d798123fde783fcc1c72d3bb8c189413",
|
"0xbb9bc244d798123fde783fcc1c72d3bb8c189413",
|
||||||
"0x807640a13483f8ac783c557fcdf27be11ea4ac7a"
|
"0x807640a13483f8ac783c557fcdf27be11ea4ac7a"
|
||||||
],
|
],
|
||||||
"eip150Transition": "0xa"
|
"eip150Transition": "0xa",
|
||||||
|
"eip155Transition": "0x7fffffffffffffff",
|
||||||
|
"eip160Transition": "0x7fffffffffffffff",
|
||||||
|
"eip161abcTransition": "0x7fffffffffffffff",
|
||||||
|
"eip161dTransition": "0x7fffffffffffffff"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1468,7 +1468,7 @@ mod tests {
|
|||||||
action: Action::Create,
|
action: Action::Create,
|
||||||
value: 100.into(),
|
value: 100.into(),
|
||||||
data: "601080600c6000396000f3006000355415600957005b60203560003555".from_hex().unwrap(),
|
data: "601080600c6000396000f3006000355415600957005b60203560003555".from_hex().unwrap(),
|
||||||
}.sign(&"".sha3());
|
}.sign(&"".sha3(), None);
|
||||||
|
|
||||||
|
|
||||||
let b1a = canon_chain
|
let b1a = canon_chain
|
||||||
@ -1532,7 +1532,7 @@ mod tests {
|
|||||||
action: Action::Create,
|
action: Action::Create,
|
||||||
value: 100.into(),
|
value: 100.into(),
|
||||||
data: "601080600c6000396000f3006000355415600957005b60203560003555".from_hex().unwrap(),
|
data: "601080600c6000396000f3006000355415600957005b60203560003555".from_hex().unwrap(),
|
||||||
}.sign(&"".sha3());
|
}.sign(&"".sha3(), None);
|
||||||
|
|
||||||
let t2 = Transaction {
|
let t2 = Transaction {
|
||||||
nonce: 1.into(),
|
nonce: 1.into(),
|
||||||
@ -1541,7 +1541,7 @@ mod tests {
|
|||||||
action: Action::Create,
|
action: Action::Create,
|
||||||
value: 100.into(),
|
value: 100.into(),
|
||||||
data: "601080600c6000396000f3006000355415600957005b60203560003555".from_hex().unwrap(),
|
data: "601080600c6000396000f3006000355415600957005b60203560003555".from_hex().unwrap(),
|
||||||
}.sign(&"".sha3());
|
}.sign(&"".sha3(), None);
|
||||||
|
|
||||||
let t3 = Transaction {
|
let t3 = Transaction {
|
||||||
nonce: 2.into(),
|
nonce: 2.into(),
|
||||||
@ -1550,7 +1550,7 @@ mod tests {
|
|||||||
action: Action::Create,
|
action: Action::Create,
|
||||||
value: 100.into(),
|
value: 100.into(),
|
||||||
data: "601080600c6000396000f3006000355415600957005b60203560003555".from_hex().unwrap(),
|
data: "601080600c6000396000f3006000355415600957005b60203560003555".from_hex().unwrap(),
|
||||||
}.sign(&"".sha3());
|
}.sign(&"".sha3(), None);
|
||||||
|
|
||||||
let b1a = canon_chain
|
let b1a = canon_chain
|
||||||
.with_transaction(t1.clone())
|
.with_transaction(t1.clone())
|
||||||
@ -1856,7 +1856,7 @@ mod tests {
|
|||||||
action: Action::Create,
|
action: Action::Create,
|
||||||
value: 101.into(),
|
value: 101.into(),
|
||||||
data: "601080600c6000396000f3006000355415600957005b60203560003555".from_hex().unwrap(),
|
data: "601080600c6000396000f3006000355415600957005b60203560003555".from_hex().unwrap(),
|
||||||
}.sign(&"".sha3());
|
}.sign(&"".sha3(), None);
|
||||||
let t2 = Transaction {
|
let t2 = Transaction {
|
||||||
nonce: 0.into(),
|
nonce: 0.into(),
|
||||||
gas_price: 0.into(),
|
gas_price: 0.into(),
|
||||||
@ -1864,7 +1864,7 @@ mod tests {
|
|||||||
action: Action::Create,
|
action: Action::Create,
|
||||||
value: 102.into(),
|
value: 102.into(),
|
||||||
data: "601080600c6000396000f3006000355415600957005b60203560003555".from_hex().unwrap(),
|
data: "601080600c6000396000f3006000355415600957005b60203560003555".from_hex().unwrap(),
|
||||||
}.sign(&"".sha3());
|
}.sign(&"".sha3(), None);
|
||||||
let t3 = Transaction {
|
let t3 = Transaction {
|
||||||
nonce: 0.into(),
|
nonce: 0.into(),
|
||||||
gas_price: 0.into(),
|
gas_price: 0.into(),
|
||||||
@ -1872,7 +1872,7 @@ mod tests {
|
|||||||
action: Action::Create,
|
action: Action::Create,
|
||||||
value: 103.into(),
|
value: 103.into(),
|
||||||
data: "601080600c6000396000f3006000355415600957005b60203560003555".from_hex().unwrap(),
|
data: "601080600c6000396000f3006000355415600957005b60203560003555".from_hex().unwrap(),
|
||||||
}.sign(&"".sha3());
|
}.sign(&"".sha3(), None);
|
||||||
let tx_hash1 = t1.hash();
|
let tx_hash1 = t1.hash();
|
||||||
let tx_hash2 = t2.hash();
|
let tx_hash2 = t2.hash();
|
||||||
let tx_hash3 = t3.hash();
|
let tx_hash3 = t3.hash();
|
||||||
|
@ -33,7 +33,7 @@ use io::*;
|
|||||||
use views::{HeaderView, BodyView, BlockView};
|
use views::{HeaderView, BodyView, BlockView};
|
||||||
use error::{ImportError, ExecutionError, CallError, BlockError, ImportResult, Error as EthcoreError};
|
use error::{ImportError, ExecutionError, CallError, BlockError, ImportResult, Error as EthcoreError};
|
||||||
use header::BlockNumber;
|
use header::BlockNumber;
|
||||||
use state::State;
|
use state::{State, CleanupMode};
|
||||||
use spec::Spec;
|
use spec::Spec;
|
||||||
use basic_types::Seal;
|
use basic_types::Seal;
|
||||||
use engines::Engine;
|
use engines::Engine;
|
||||||
@ -268,6 +268,22 @@ impl Client {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The env info as of the best block.
|
||||||
|
fn latest_env_info(&self) -> EnvInfo {
|
||||||
|
let header_data = self.best_block_header();
|
||||||
|
let view = HeaderView::new(&header_data);
|
||||||
|
|
||||||
|
EnvInfo {
|
||||||
|
number: view.number(),
|
||||||
|
author: view.author(),
|
||||||
|
timestamp: view.timestamp(),
|
||||||
|
difficulty: view.difficulty(),
|
||||||
|
last_hashes: self.build_last_hashes(view.hash()),
|
||||||
|
gas_used: U256::default(),
|
||||||
|
gas_limit: view.gas_limit(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn build_last_hashes(&self, parent_hash: H256) -> Arc<LastHashes> {
|
fn build_last_hashes(&self, parent_hash: H256) -> Arc<LastHashes> {
|
||||||
{
|
{
|
||||||
let hashes = self.last_hashes.read();
|
let hashes = self.last_hashes.read();
|
||||||
@ -796,7 +812,7 @@ impl BlockChainClient for Client {
|
|||||||
let needed_balance = t.value + t.gas * t.gas_price;
|
let needed_balance = t.value + t.gas * t.gas_price;
|
||||||
if balance < needed_balance {
|
if balance < needed_balance {
|
||||||
// give the sender a sufficient balance
|
// give the sender a sufficient balance
|
||||||
state.add_balance(&sender, &(needed_balance - balance));
|
state.add_balance(&sender, &(needed_balance - balance), CleanupMode::NoEmpty);
|
||||||
}
|
}
|
||||||
let options = TransactOptions { tracing: analytics.transaction_tracing, vm_tracing: analytics.vm_tracing, check_nonce: false };
|
let options = TransactOptions { tracing: analytics.transaction_tracing, vm_tracing: analytics.vm_tracing, check_nonce: false };
|
||||||
let mut ret = try!(Executive::new(&mut state, &env_info, &*self.engine, &self.factories.vm).transact(t, options));
|
let mut ret = try!(Executive::new(&mut state, &env_info, &*self.engine, &self.factories.vm).transact(t, options));
|
||||||
@ -1014,7 +1030,9 @@ impl BlockChainClient for Client {
|
|||||||
transaction_hash: transaction_hash.clone(),
|
transaction_hash: transaction_hash.clone(),
|
||||||
transaction_index: transaction_index,
|
transaction_index: transaction_index,
|
||||||
log_index: i
|
log_index: i
|
||||||
}).collect()
|
}).collect(),
|
||||||
|
log_bloom: receipt.log_bloom,
|
||||||
|
state_root: receipt.state_root,
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
_ => None
|
_ => None
|
||||||
@ -1175,24 +1193,16 @@ impl BlockChainClient for Client {
|
|||||||
fn pending_transactions(&self) -> Vec<SignedTransaction> {
|
fn pending_transactions(&self) -> Vec<SignedTransaction> {
|
||||||
self.miner.pending_transactions(self.chain.read().best_block_number())
|
self.miner.pending_transactions(self.chain.read().best_block_number())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn signing_network_id(&self) -> Option<u8> {
|
||||||
|
self.engine.signing_network_id(&self.latest_env_info())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MiningBlockChainClient for Client {
|
impl MiningBlockChainClient for Client {
|
||||||
|
|
||||||
fn latest_schedule(&self) -> Schedule {
|
fn latest_schedule(&self) -> Schedule {
|
||||||
let header_data = self.best_block_header();
|
self.engine.schedule(&self.latest_env_info())
|
||||||
let view = HeaderView::new(&header_data);
|
|
||||||
|
|
||||||
let env_info = EnvInfo {
|
|
||||||
number: view.number(),
|
|
||||||
author: view.author(),
|
|
||||||
timestamp: view.timestamp(),
|
|
||||||
difficulty: view.difficulty(),
|
|
||||||
last_hashes: self.build_last_hashes(view.hash()),
|
|
||||||
gas_used: U256::default(),
|
|
||||||
gas_limit: view.gas_limit(),
|
|
||||||
};
|
|
||||||
self.engine.schedule(&env_info)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prepare_open_block(&self, author: Address, gas_range_target: (U256, U256), extra_data: Bytes) -> OpenBlock {
|
fn prepare_open_block(&self, author: Address, gas_range_target: (U256, U256), extra_data: Bytes) -> OpenBlock {
|
||||||
|
@ -237,7 +237,7 @@ impl TestBlockChainClient {
|
|||||||
gas_price: U256::one(),
|
gas_price: U256::one(),
|
||||||
nonce: U256::zero()
|
nonce: U256::zero()
|
||||||
};
|
};
|
||||||
let signed_tx = tx.sign(keypair.secret());
|
let signed_tx = tx.sign(keypair.secret(), None);
|
||||||
txs.append(&signed_tx);
|
txs.append(&signed_tx);
|
||||||
txs.out()
|
txs.out()
|
||||||
},
|
},
|
||||||
@ -303,7 +303,7 @@ impl TestBlockChainClient {
|
|||||||
gas_price: U256::one(),
|
gas_price: U256::one(),
|
||||||
nonce: U256::zero()
|
nonce: U256::zero()
|
||||||
};
|
};
|
||||||
let signed_tx = tx.sign(keypair.secret());
|
let signed_tx = tx.sign(keypair.secret(), None);
|
||||||
self.set_balance(signed_tx.sender().unwrap(), 10_000_000.into());
|
self.set_balance(signed_tx.sender().unwrap(), 10_000_000.into());
|
||||||
let res = self.miner.import_external_transactions(self, vec![signed_tx]);
|
let res = self.miner.import_external_transactions(self, vec![signed_tx]);
|
||||||
let res = res.into_iter().next().unwrap().expect("Successful import");
|
let res = res.into_iter().next().unwrap().expect("Successful import");
|
||||||
@ -324,7 +324,7 @@ pub fn get_temp_state_db() -> GuardedTempResult<StateDB> {
|
|||||||
|
|
||||||
impl MiningBlockChainClient for TestBlockChainClient {
|
impl MiningBlockChainClient for TestBlockChainClient {
|
||||||
fn latest_schedule(&self) -> Schedule {
|
fn latest_schedule(&self) -> Schedule {
|
||||||
Schedule::new_homestead_gas_fix()
|
Schedule::new_post_eip150(true, true, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prepare_open_block(&self, author: Address, gas_range_target: (U256, U256), extra_data: Bytes) -> OpenBlock {
|
fn prepare_open_block(&self, author: Address, gas_range_target: (U256, U256), extra_data: Bytes) -> OpenBlock {
|
||||||
@ -643,6 +643,8 @@ impl BlockChainClient for TestBlockChainClient {
|
|||||||
self.miner.pending_transactions(self.chain_info().best_block_number)
|
self.miner.pending_transactions(self.chain_info().best_block_number)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn signing_network_id(&self) -> Option<u8> { None }
|
||||||
|
|
||||||
fn mode(&self) -> Mode { Mode::Active }
|
fn mode(&self) -> Mode { Mode::Active }
|
||||||
|
|
||||||
fn set_mode(&self, _: Mode) { unimplemented!(); }
|
fn set_mode(&self, _: Mode) { unimplemented!(); }
|
||||||
|
@ -227,8 +227,13 @@ pub trait BlockChainClient : Sync + Send {
|
|||||||
Histogram::new(corpus, bucket_number)
|
Histogram::new(corpus, bucket_number)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the preferred network ID to sign on
|
||||||
|
fn signing_network_id(&self) -> Option<u8>;
|
||||||
|
|
||||||
|
/// Get the mode.
|
||||||
fn mode(&self) -> Mode;
|
fn mode(&self) -> Mode;
|
||||||
|
|
||||||
|
/// Set the mode.
|
||||||
fn set_mode(&self, mode: Mode);
|
fn set_mode(&self, mode: Mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,6 +112,9 @@ pub trait Engine : Sync + Send {
|
|||||||
/// Verify a particular transaction is valid.
|
/// Verify a particular transaction is valid.
|
||||||
fn verify_transaction(&self, _t: &SignedTransaction, _header: &Header) -> Result<(), Error> { Ok(()) }
|
fn verify_transaction(&self, _t: &SignedTransaction, _header: &Header) -> Result<(), Error> { Ok(()) }
|
||||||
|
|
||||||
|
/// The network ID that transactions should be signed with.
|
||||||
|
fn signing_network_id(&self, _env_info: &EnvInfo) -> Option<u8> { None }
|
||||||
|
|
||||||
/// Verify the seal of a block. This is an auxilliary method that actually just calls other `verify_` methods
|
/// Verify the seal of a block. This is an auxilliary method that actually just calls other `verify_` methods
|
||||||
/// to get the job done. By default it must pass `verify_basic` and `verify_block_unordered`. If more or fewer
|
/// to get the job done. By default it must pass `verify_basic` and `verify_block_unordered`. If more or fewer
|
||||||
/// methods are needed for an Engine, this may be overridden.
|
/// methods are needed for an Engine, this may be overridden.
|
||||||
|
@ -76,6 +76,8 @@ pub enum TransactionError {
|
|||||||
RecipientBanned,
|
RecipientBanned,
|
||||||
/// Contract creation code is banned.
|
/// Contract creation code is banned.
|
||||||
CodeBanned,
|
CodeBanned,
|
||||||
|
/// Invalid network ID given.
|
||||||
|
InvalidNetworkId,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for TransactionError {
|
impl fmt::Display for TransactionError {
|
||||||
@ -99,6 +101,7 @@ impl fmt::Display for TransactionError {
|
|||||||
SenderBanned => "Sender is temporarily banned.".into(),
|
SenderBanned => "Sender is temporarily banned.".into(),
|
||||||
RecipientBanned => "Recipient is temporarily banned.".into(),
|
RecipientBanned => "Recipient is temporarily banned.".into(),
|
||||||
CodeBanned => "Contract code is temporarily banned.".into(),
|
CodeBanned => "Contract code is temporarily banned.".into(),
|
||||||
|
InvalidNetworkId => "Transaction of this network ID is not allowed on this chain.".into(),
|
||||||
};
|
};
|
||||||
|
|
||||||
f.write_fmt(format_args!("Transaction error ({})", msg))
|
f.write_fmt(format_args!("Transaction error ({})", msg))
|
||||||
|
@ -19,8 +19,9 @@ use util::*;
|
|||||||
use block::*;
|
use block::*;
|
||||||
use builtin::Builtin;
|
use builtin::Builtin;
|
||||||
use env_info::EnvInfo;
|
use env_info::EnvInfo;
|
||||||
use error::{BlockError, Error};
|
use error::{BlockError, TransactionError, Error};
|
||||||
use header::Header;
|
use header::Header;
|
||||||
|
use state::CleanupMode;
|
||||||
use spec::CommonParams;
|
use spec::CommonParams;
|
||||||
use transaction::SignedTransaction;
|
use transaction::SignedTransaction;
|
||||||
use engines::Engine;
|
use engines::Engine;
|
||||||
@ -59,8 +60,16 @@ pub struct EthashParams {
|
|||||||
pub difficulty_hardfork_bound_divisor: U256,
|
pub difficulty_hardfork_bound_divisor: U256,
|
||||||
/// Block on which there is no additional difficulty from the exponential bomb.
|
/// Block on which there is no additional difficulty from the exponential bomb.
|
||||||
pub bomb_defuse_transition: u64,
|
pub bomb_defuse_transition: u64,
|
||||||
/// Bad gas transition block number.
|
/// 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.
|
||||||
|
pub eip160_transition: u64,
|
||||||
|
/// Number of first block where EIP-161.abc begin.
|
||||||
|
pub eip161abc_transition: u64,
|
||||||
|
/// Number of first block where EIP-161.d begins.
|
||||||
|
pub eip161d_transition: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<ethjson::spec::EthashParams> for EthashParams {
|
impl From<ethjson::spec::EthashParams> for EthashParams {
|
||||||
@ -81,6 +90,10 @@ impl From<ethjson::spec::EthashParams> for EthashParams {
|
|||||||
difficulty_hardfork_bound_divisor: p.difficulty_hardfork_bound_divisor.map_or(p.difficulty_bound_divisor.into(), Into::into),
|
difficulty_hardfork_bound_divisor: p.difficulty_hardfork_bound_divisor.map_or(p.difficulty_bound_divisor.into(), Into::into),
|
||||||
bomb_defuse_transition: p.bomb_defuse_transition.map_or(0x7fffffffffffffff, Into::into),
|
bomb_defuse_transition: p.bomb_defuse_transition.map_or(0x7fffffffffffffff, 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),
|
||||||
|
eip161abc_transition: p.eip161abc_transition.map_or(0, Into::into),
|
||||||
|
eip161d_transition: p.eip161d_transition.map_or(0x7fffffffffffffff, Into::into),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -132,7 +145,19 @@ impl Engine for Ethash {
|
|||||||
} else if env_info.number < self.ethash_params.eip150_transition {
|
} else if env_info.number < self.ethash_params.eip150_transition {
|
||||||
Schedule::new_homestead()
|
Schedule::new_homestead()
|
||||||
} else {
|
} else {
|
||||||
Schedule::new_homestead_gas_fix()
|
Schedule::new_post_eip150(
|
||||||
|
env_info.number >= self.ethash_params.eip160_transition,
|
||||||
|
env_info.number >= self.ethash_params.eip161abc_transition,
|
||||||
|
env_info.number >= self.ethash_params.eip161d_transition
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn signing_network_id(&self, env_info: &EnvInfo) -> Option<u8> {
|
||||||
|
if env_info.number >= self.ethash_params.eip155_transition && self.params().network_id < 127 {
|
||||||
|
Some(self.params().network_id as u8)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,7 +194,7 @@ impl Engine for Ethash {
|
|||||||
let mut state = block.fields_mut().state;
|
let mut state = block.fields_mut().state;
|
||||||
for child in &self.ethash_params.dao_hardfork_accounts {
|
for child in &self.ethash_params.dao_hardfork_accounts {
|
||||||
let b = state.balance(child);
|
let b = state.balance(child);
|
||||||
state.transfer_balance(child, &self.ethash_params.dao_hardfork_beneficiary, &b);
|
state.transfer_balance(child, &self.ethash_params.dao_hardfork_beneficiary, &b, CleanupMode::NoEmpty);
|
||||||
}
|
}
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
@ -182,12 +207,12 @@ impl Engine for Ethash {
|
|||||||
let fields = block.fields_mut();
|
let fields = block.fields_mut();
|
||||||
|
|
||||||
// Bestow block reward
|
// Bestow block reward
|
||||||
fields.state.add_balance(fields.header.author(), &(reward + reward / U256::from(32) * U256::from(fields.uncles.len())));
|
fields.state.add_balance(fields.header.author(), &(reward + reward / U256::from(32) * U256::from(fields.uncles.len())), CleanupMode::NoEmpty);
|
||||||
|
|
||||||
// Bestow uncle rewards
|
// Bestow uncle rewards
|
||||||
let current_number = fields.header.number();
|
let current_number = fields.header.number();
|
||||||
for u in fields.uncles.iter() {
|
for u in fields.uncles.iter() {
|
||||||
fields.state.add_balance(u.author(), &(reward * U256::from(8 + u.number() - current_number) / U256::from(8)));
|
fields.state.add_balance(u.author(), &(reward * U256::from(8 + u.number() - current_number) / U256::from(8)), CleanupMode::NoEmpty);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Commit state so that we can actually figure out the state root.
|
// Commit state so that we can actually figure out the state root.
|
||||||
@ -277,6 +302,13 @@ impl Engine for Ethash {
|
|||||||
if header.number() >= self.ethash_params.homestead_transition {
|
if header.number() >= self.ethash_params.homestead_transition {
|
||||||
try!(t.check_low_s());
|
try!(t.check_low_s());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(n) = t.network_id() {
|
||||||
|
if header.number() < self.ethash_params.eip155_transition || n as usize != self.params().network_id {
|
||||||
|
return Err(TransactionError::InvalidNetworkId.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,6 +54,9 @@ pub fn new_homestead_test() -> Spec { load(include_bytes!("../../res/ethereum/ho
|
|||||||
/// Create a new Homestead-EIP150 chain spec as though it never changed from Homestead/Frontier.
|
/// Create a new Homestead-EIP150 chain spec as though it never changed from Homestead/Frontier.
|
||||||
pub fn new_eip150_test() -> Spec { load(include_bytes!("../../res/ethereum/eip150_test.json")) }
|
pub fn new_eip150_test() -> Spec { load(include_bytes!("../../res/ethereum/eip150_test.json")) }
|
||||||
|
|
||||||
|
/// Create a new Homestead-EIP150 chain spec as though it never changed from Homestead/Frontier.
|
||||||
|
pub fn new_eip161_test() -> Spec { load(include_bytes!("../../res/ethereum/eip161_test.json")) }
|
||||||
|
|
||||||
/// Create a new Frontier/Homestead/DAO chain spec with transition points at #5 and #8.
|
/// Create a new Frontier/Homestead/DAO chain spec with transition points at #5 and #8.
|
||||||
pub fn new_transition_test() -> Spec { load(include_bytes!("../../res/ethereum/transition_test.json")) }
|
pub fn new_transition_test() -> Spec { load(include_bytes!("../../res/ethereum/transition_test.json")) }
|
||||||
|
|
||||||
|
@ -52,6 +52,12 @@ pub trait Ext {
|
|||||||
/// Determine whether an account exists.
|
/// Determine whether an account exists.
|
||||||
fn exists(&self, address: &Address) -> bool;
|
fn exists(&self, address: &Address) -> bool;
|
||||||
|
|
||||||
|
/// Determine whether an account exists and is not null (zero balance/nonce, no code).
|
||||||
|
fn exists_and_not_null(&self, address: &Address) -> bool;
|
||||||
|
|
||||||
|
/// Balance of the origin account.
|
||||||
|
fn origin_balance(&self) -> U256;
|
||||||
|
|
||||||
/// Returns address balance.
|
/// Returns address balance.
|
||||||
fn balance(&self, address: &Address) -> U256;
|
fn balance(&self, address: &Address) -> U256;
|
||||||
|
|
||||||
|
@ -146,8 +146,13 @@ impl<Gas: CostType> Gasometer<Gas> {
|
|||||||
instructions::SUICIDE => {
|
instructions::SUICIDE => {
|
||||||
let mut gas = Gas::from(schedule.suicide_gas);
|
let mut gas = Gas::from(schedule.suicide_gas);
|
||||||
|
|
||||||
|
let is_value_transfer = !ext.origin_balance().is_zero();
|
||||||
let address = u256_to_address(stack.peek(0));
|
let address = u256_to_address(stack.peek(0));
|
||||||
if !ext.exists(&address) {
|
if (
|
||||||
|
!schedule.no_empty && !ext.exists(&address)
|
||||||
|
) || (
|
||||||
|
schedule.no_empty && is_value_transfer && !ext.exists_and_not_null(&address)
|
||||||
|
) {
|
||||||
gas = overflowing!(gas.overflow_add(schedule.suicide_to_new_account_cost.into()));
|
gas = overflowing!(gas.overflow_add(schedule.suicide_to_new_account_cost.into()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,12 +195,19 @@ impl<Gas: CostType> Gasometer<Gas> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let address = u256_to_address(stack.peek(1));
|
let address = u256_to_address(stack.peek(1));
|
||||||
|
let is_value_transfer = !stack.peek(2).is_zero();
|
||||||
|
|
||||||
if instruction == instructions::CALL && !ext.exists(&address) {
|
if instruction == instructions::CALL {
|
||||||
|
if (
|
||||||
|
!schedule.no_empty && !ext.exists(&address)
|
||||||
|
) || (
|
||||||
|
schedule.no_empty && is_value_transfer && !ext.exists_and_not_null(&address)
|
||||||
|
) {
|
||||||
gas = overflowing!(gas.overflow_add(schedule.call_new_account_gas.into()));
|
gas = overflowing!(gas.overflow_add(schedule.call_new_account_gas.into()));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if !stack.peek(2).is_zero() {
|
if is_value_transfer {
|
||||||
gas = overflowing!(gas.overflow_add(schedule.call_value_transfer_gas.into()));
|
gas = overflowing!(gas.overflow_add(schedule.call_value_transfer_gas.into()));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -93,6 +93,10 @@ pub struct Schedule {
|
|||||||
/// If Some(x): let limit = GAS * (x - 1) / x; let CALL's gas = min(requested, limit). let CREATE's gas = limit.
|
/// If Some(x): let limit = GAS * (x - 1) / x; let CALL's gas = min(requested, limit). let CREATE's gas = limit.
|
||||||
/// If None: let CALL's gas = (requested > GAS ? [OOG] : GAS). let CREATE's gas = GAS
|
/// If None: let CALL's gas = (requested > GAS ? [OOG] : GAS). let CREATE's gas = GAS
|
||||||
pub sub_gas_cap_divisor: Option<usize>,
|
pub sub_gas_cap_divisor: Option<usize>,
|
||||||
|
/// Don't ever make empty accounts; contracts start with nonce=1. Also, don't charge 25k when sending/suicide zero-value.
|
||||||
|
pub no_empty: bool,
|
||||||
|
/// Kill empty accounts if touched.
|
||||||
|
pub kill_empty: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Schedule {
|
impl Schedule {
|
||||||
@ -106,8 +110,8 @@ impl Schedule {
|
|||||||
Self::new(true, true, 53000)
|
Self::new(true, true, 53000)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Schedule for the Homestead-era of the Ethereum main net.
|
/// Schedule for the post-EIP-150-era of the Ethereum main net.
|
||||||
pub fn new_homestead_gas_fix() -> Schedule {
|
pub fn new_post_eip150(fix_exp: bool, no_empty: bool, kill_empty: bool) -> Schedule {
|
||||||
Schedule {
|
Schedule {
|
||||||
exceptional_failed_code_deposit: true,
|
exceptional_failed_code_deposit: true,
|
||||||
have_delegate_call: true,
|
have_delegate_call: true,
|
||||||
@ -115,7 +119,7 @@ impl Schedule {
|
|||||||
max_depth: 1024,
|
max_depth: 1024,
|
||||||
tier_step_gas: [0, 2, 3, 5, 8, 10, 20, 0],
|
tier_step_gas: [0, 2, 3, 5, 8, 10, 20, 0],
|
||||||
exp_gas: 10,
|
exp_gas: 10,
|
||||||
exp_byte_gas: 10,
|
exp_byte_gas: if fix_exp {50} else {10},
|
||||||
sha3_gas: 30,
|
sha3_gas: 30,
|
||||||
sha3_word_gas: 6,
|
sha3_word_gas: 6,
|
||||||
sload_gas: 200,
|
sload_gas: 200,
|
||||||
@ -146,6 +150,8 @@ impl Schedule {
|
|||||||
suicide_gas: 5000,
|
suicide_gas: 5000,
|
||||||
suicide_to_new_account_cost: 25000,
|
suicide_to_new_account_cost: 25000,
|
||||||
sub_gas_cap_divisor: Some(64),
|
sub_gas_cap_divisor: Some(64),
|
||||||
|
no_empty: no_empty,
|
||||||
|
kill_empty: kill_empty,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,6 +194,8 @@ impl Schedule {
|
|||||||
suicide_gas: 0,
|
suicide_gas: 0,
|
||||||
suicide_to_new_account_cost: 0,
|
suicide_to_new_account_cost: 0,
|
||||||
sub_gas_cap_divisor: None,
|
sub_gas_cap_divisor: None,
|
||||||
|
no_empty: false,
|
||||||
|
kill_empty: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -94,6 +94,14 @@ impl Ext for FakeExt {
|
|||||||
self.balances.contains_key(address)
|
self.balances.contains_key(address)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn exists_and_not_null(&self, address: &Address) -> bool {
|
||||||
|
self.balances.get(address).map_or(false, |b| !b.is_zero())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn origin_balance(&self) -> U256 {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
fn balance(&self, address: &Address) -> U256 {
|
fn balance(&self, address: &Address) -> U256 {
|
||||||
*self.balances.get(address).unwrap()
|
*self.balances.get(address).unwrap()
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
//! Transaction Execution environment.
|
//! Transaction Execution environment.
|
||||||
use util::*;
|
use util::*;
|
||||||
use action_params::{ActionParams, ActionValue};
|
use action_params::{ActionParams, ActionValue};
|
||||||
use state::{State, Substate};
|
use state::{State, Substate, CleanupMode};
|
||||||
use engines::Engine;
|
use engines::Engine;
|
||||||
use types::executed::CallType;
|
use types::executed::CallType;
|
||||||
use env_info::EnvInfo;
|
use env_info::EnvInfo;
|
||||||
@ -256,9 +256,11 @@ impl<'a> Executive<'a> {
|
|||||||
// backup used in case of running out of gas
|
// backup used in case of running out of gas
|
||||||
self.state.checkpoint();
|
self.state.checkpoint();
|
||||||
|
|
||||||
|
let schedule = self.engine.schedule(self.info);
|
||||||
|
|
||||||
// at first, transfer value to destination
|
// at first, transfer value to destination
|
||||||
if let ActionValue::Transfer(val) = params.value {
|
if let ActionValue::Transfer(val) = params.value {
|
||||||
self.state.transfer_balance(¶ms.sender, ¶ms.address, &val);
|
self.state.transfer_balance(¶ms.sender, ¶ms.address, &val, substate.to_cleanup_mode(&schedule));
|
||||||
}
|
}
|
||||||
trace!("Executive::call(params={:?}) self.env_info={:?}", params, self.info);
|
trace!("Executive::call(params={:?}) self.env_info={:?}", params, self.info);
|
||||||
|
|
||||||
@ -364,12 +366,14 @@ impl<'a> Executive<'a> {
|
|||||||
let mut unconfirmed_substate = Substate::new();
|
let mut unconfirmed_substate = Substate::new();
|
||||||
|
|
||||||
// create contract and transfer value to it if necessary
|
// create contract and transfer value to it if necessary
|
||||||
|
let schedule = self.engine.schedule(self.info);
|
||||||
|
let nonce_offset = if schedule.no_empty {1} else {0}.into();
|
||||||
let prev_bal = self.state.balance(¶ms.address);
|
let prev_bal = self.state.balance(¶ms.address);
|
||||||
if let ActionValue::Transfer(val) = params.value {
|
if let ActionValue::Transfer(val) = params.value {
|
||||||
self.state.sub_balance(¶ms.sender, &val);
|
self.state.sub_balance(¶ms.sender, &val);
|
||||||
self.state.new_contract(¶ms.address, val + prev_bal);
|
self.state.new_contract(¶ms.address, val + prev_bal, nonce_offset);
|
||||||
} else {
|
} else {
|
||||||
self.state.new_contract(¶ms.address, prev_bal);
|
self.state.new_contract(¶ms.address, prev_bal, nonce_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
let trace_info = tracer.prepare_trace_create(¶ms);
|
let trace_info = tracer.prepare_trace_create(¶ms);
|
||||||
@ -405,7 +409,7 @@ impl<'a> Executive<'a> {
|
|||||||
fn finalize(
|
fn finalize(
|
||||||
&mut self,
|
&mut self,
|
||||||
t: &SignedTransaction,
|
t: &SignedTransaction,
|
||||||
substate: Substate,
|
mut substate: Substate,
|
||||||
result: evm::Result<U256>,
|
result: evm::Result<U256>,
|
||||||
output: Bytes,
|
output: Bytes,
|
||||||
trace: Vec<FlatTrace>,
|
trace: Vec<FlatTrace>,
|
||||||
@ -440,15 +444,23 @@ impl<'a> Executive<'a> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
trace!("exec::finalize: Refunding refund_value={}, sender={}\n", refund_value, sender);
|
trace!("exec::finalize: Refunding refund_value={}, sender={}\n", refund_value, sender);
|
||||||
self.state.add_balance(&sender, &refund_value);
|
// Below: NoEmpty is safe since the sender must already be non-null to have sent this transaction
|
||||||
|
self.state.add_balance(&sender, &refund_value, CleanupMode::NoEmpty);
|
||||||
trace!("exec::finalize: Compensating author: fees_value={}, author={}\n", fees_value, &self.info.author);
|
trace!("exec::finalize: Compensating author: fees_value={}, author={}\n", fees_value, &self.info.author);
|
||||||
self.state.add_balance(&self.info.author, &fees_value);
|
self.state.add_balance(&self.info.author, &fees_value, substate.to_cleanup_mode(&schedule));
|
||||||
|
|
||||||
// perform suicides
|
// perform suicides
|
||||||
for address in &substate.suicides {
|
for address in &substate.suicides {
|
||||||
self.state.kill_account(address);
|
self.state.kill_account(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// perform garbage-collection
|
||||||
|
for address in &substate.garbage {
|
||||||
|
if self.state.exists(address) && !self.state.exists_and_not_null(address) {
|
||||||
|
self.state.kill_account(address);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
Err(evm::Error::Internal) => Err(ExecutionError::Internal),
|
Err(evm::Error::Internal) => Err(ExecutionError::Internal),
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
@ -509,7 +521,7 @@ mod tests {
|
|||||||
use env_info::EnvInfo;
|
use env_info::EnvInfo;
|
||||||
use evm::{Factory, VMType};
|
use evm::{Factory, VMType};
|
||||||
use error::ExecutionError;
|
use error::ExecutionError;
|
||||||
use state::Substate;
|
use state::{Substate, CleanupMode};
|
||||||
use tests::helpers::*;
|
use tests::helpers::*;
|
||||||
use trace::trace;
|
use trace::trace;
|
||||||
use trace::{FlatTrace, Tracer, NoopTracer, ExecutiveTracer};
|
use trace::{FlatTrace, Tracer, NoopTracer, ExecutiveTracer};
|
||||||
@ -538,7 +550,7 @@ mod tests {
|
|||||||
params.value = ActionValue::Transfer(U256::from(0x7));
|
params.value = ActionValue::Transfer(U256::from(0x7));
|
||||||
let mut state_result = get_temp_state();
|
let mut state_result = get_temp_state();
|
||||||
let mut state = state_result.reference_mut();
|
let mut state = state_result.reference_mut();
|
||||||
state.add_balance(&sender, &U256::from(0x100u64));
|
state.add_balance(&sender, &U256::from(0x100u64), CleanupMode::NoEmpty);
|
||||||
let info = EnvInfo::default();
|
let info = EnvInfo::default();
|
||||||
let engine = TestEngine::new(0);
|
let engine = TestEngine::new(0);
|
||||||
let mut substate = Substate::new();
|
let mut substate = Substate::new();
|
||||||
@ -597,7 +609,7 @@ mod tests {
|
|||||||
params.value = ActionValue::Transfer(U256::from(100));
|
params.value = ActionValue::Transfer(U256::from(100));
|
||||||
let mut state_result = get_temp_state();
|
let mut state_result = get_temp_state();
|
||||||
let mut state = state_result.reference_mut();
|
let mut state = state_result.reference_mut();
|
||||||
state.add_balance(&sender, &U256::from(100));
|
state.add_balance(&sender, &U256::from(100), CleanupMode::NoEmpty);
|
||||||
let info = EnvInfo::default();
|
let info = EnvInfo::default();
|
||||||
let engine = TestEngine::new(0);
|
let engine = TestEngine::new(0);
|
||||||
let mut substate = Substate::new();
|
let mut substate = Substate::new();
|
||||||
@ -656,7 +668,7 @@ mod tests {
|
|||||||
params.call_type = CallType::Call;
|
params.call_type = CallType::Call;
|
||||||
let mut state_result = get_temp_state();
|
let mut state_result = get_temp_state();
|
||||||
let mut state = state_result.reference_mut();
|
let mut state = state_result.reference_mut();
|
||||||
state.add_balance(&sender, &U256::from(100));
|
state.add_balance(&sender, &U256::from(100), CleanupMode::NoEmpty);
|
||||||
let info = EnvInfo::default();
|
let info = EnvInfo::default();
|
||||||
let engine = TestEngine::new(5);
|
let engine = TestEngine::new(5);
|
||||||
let mut substate = Substate::new();
|
let mut substate = Substate::new();
|
||||||
@ -767,7 +779,7 @@ mod tests {
|
|||||||
params.value = ActionValue::Transfer(100.into());
|
params.value = ActionValue::Transfer(100.into());
|
||||||
let mut state_result = get_temp_state();
|
let mut state_result = get_temp_state();
|
||||||
let mut state = state_result.reference_mut();
|
let mut state = state_result.reference_mut();
|
||||||
state.add_balance(&sender, &U256::from(100));
|
state.add_balance(&sender, &U256::from(100), CleanupMode::NoEmpty);
|
||||||
let info = EnvInfo::default();
|
let info = EnvInfo::default();
|
||||||
let engine = TestEngine::new(5);
|
let engine = TestEngine::new(5);
|
||||||
let mut substate = Substate::new();
|
let mut substate = Substate::new();
|
||||||
@ -855,7 +867,7 @@ mod tests {
|
|||||||
params.value = ActionValue::Transfer(U256::from(100));
|
params.value = ActionValue::Transfer(U256::from(100));
|
||||||
let mut state_result = get_temp_state();
|
let mut state_result = get_temp_state();
|
||||||
let mut state = state_result.reference_mut();
|
let mut state = state_result.reference_mut();
|
||||||
state.add_balance(&sender, &U256::from(100));
|
state.add_balance(&sender, &U256::from(100), CleanupMode::NoEmpty);
|
||||||
let info = EnvInfo::default();
|
let info = EnvInfo::default();
|
||||||
let engine = TestEngine::new(0);
|
let engine = TestEngine::new(0);
|
||||||
let mut substate = Substate::new();
|
let mut substate = Substate::new();
|
||||||
@ -907,7 +919,7 @@ mod tests {
|
|||||||
params.value = ActionValue::Transfer(U256::from(100));
|
params.value = ActionValue::Transfer(U256::from(100));
|
||||||
let mut state_result = get_temp_state();
|
let mut state_result = get_temp_state();
|
||||||
let mut state = state_result.reference_mut();
|
let mut state = state_result.reference_mut();
|
||||||
state.add_balance(&sender, &U256::from(100));
|
state.add_balance(&sender, &U256::from(100), CleanupMode::NoEmpty);
|
||||||
let info = EnvInfo::default();
|
let info = EnvInfo::default();
|
||||||
let engine = TestEngine::new(1024);
|
let engine = TestEngine::new(1024);
|
||||||
let mut substate = Substate::new();
|
let mut substate = Substate::new();
|
||||||
@ -967,7 +979,7 @@ mod tests {
|
|||||||
let mut state = state_result.reference_mut();
|
let mut state = state_result.reference_mut();
|
||||||
state.init_code(&address_a, code_a.clone());
|
state.init_code(&address_a, code_a.clone());
|
||||||
state.init_code(&address_b, code_b.clone());
|
state.init_code(&address_b, code_b.clone());
|
||||||
state.add_balance(&sender, &U256::from(100_000));
|
state.add_balance(&sender, &U256::from(100_000), CleanupMode::NoEmpty);
|
||||||
|
|
||||||
let info = EnvInfo::default();
|
let info = EnvInfo::default();
|
||||||
let engine = TestEngine::new(0);
|
let engine = TestEngine::new(0);
|
||||||
@ -1040,13 +1052,13 @@ mod tests {
|
|||||||
gas: U256::from(100_000),
|
gas: U256::from(100_000),
|
||||||
gas_price: U256::zero(),
|
gas_price: U256::zero(),
|
||||||
nonce: U256::zero()
|
nonce: U256::zero()
|
||||||
}.sign(keypair.secret());
|
}.sign(keypair.secret(), None);
|
||||||
let sender = t.sender().unwrap();
|
let sender = t.sender().unwrap();
|
||||||
let contract = contract_address(&sender, &U256::zero());
|
let contract = contract_address(&sender, &U256::zero());
|
||||||
|
|
||||||
let mut state_result = get_temp_state();
|
let mut state_result = get_temp_state();
|
||||||
let mut state = state_result.reference_mut();
|
let mut state = state_result.reference_mut();
|
||||||
state.add_balance(&sender, &U256::from(18));
|
state.add_balance(&sender, &U256::from(18), CleanupMode::NoEmpty);
|
||||||
let mut info = EnvInfo::default();
|
let mut info = EnvInfo::default();
|
||||||
info.gas_limit = U256::from(100_000);
|
info.gas_limit = U256::from(100_000);
|
||||||
let engine = TestEngine::new(0);
|
let engine = TestEngine::new(0);
|
||||||
@ -1107,12 +1119,12 @@ mod tests {
|
|||||||
gas: U256::from(100_000),
|
gas: U256::from(100_000),
|
||||||
gas_price: U256::zero(),
|
gas_price: U256::zero(),
|
||||||
nonce: U256::one()
|
nonce: U256::one()
|
||||||
}.sign(keypair.secret());
|
}.sign(keypair.secret(), None);
|
||||||
let sender = t.sender().unwrap();
|
let sender = t.sender().unwrap();
|
||||||
|
|
||||||
let mut state_result = get_temp_state();
|
let mut state_result = get_temp_state();
|
||||||
let mut state = state_result.reference_mut();
|
let mut state = state_result.reference_mut();
|
||||||
state.add_balance(&sender, &U256::from(17));
|
state.add_balance(&sender, &U256::from(17), CleanupMode::NoEmpty);
|
||||||
let mut info = EnvInfo::default();
|
let mut info = EnvInfo::default();
|
||||||
info.gas_limit = U256::from(100_000);
|
info.gas_limit = U256::from(100_000);
|
||||||
let engine = TestEngine::new(0);
|
let engine = TestEngine::new(0);
|
||||||
@ -1140,12 +1152,12 @@ mod tests {
|
|||||||
gas: U256::from(80_001),
|
gas: U256::from(80_001),
|
||||||
gas_price: U256::zero(),
|
gas_price: U256::zero(),
|
||||||
nonce: U256::zero()
|
nonce: U256::zero()
|
||||||
}.sign(keypair.secret());
|
}.sign(keypair.secret(), None);
|
||||||
let sender = t.sender().unwrap();
|
let sender = t.sender().unwrap();
|
||||||
|
|
||||||
let mut state_result = get_temp_state();
|
let mut state_result = get_temp_state();
|
||||||
let mut state = state_result.reference_mut();
|
let mut state = state_result.reference_mut();
|
||||||
state.add_balance(&sender, &U256::from(17));
|
state.add_balance(&sender, &U256::from(17), CleanupMode::NoEmpty);
|
||||||
let mut info = EnvInfo::default();
|
let mut info = EnvInfo::default();
|
||||||
info.gas_used = U256::from(20_000);
|
info.gas_used = U256::from(20_000);
|
||||||
info.gas_limit = U256::from(100_000);
|
info.gas_limit = U256::from(100_000);
|
||||||
@ -1175,12 +1187,12 @@ mod tests {
|
|||||||
gas: U256::from(100_000),
|
gas: U256::from(100_000),
|
||||||
gas_price: U256::one(),
|
gas_price: U256::one(),
|
||||||
nonce: U256::zero()
|
nonce: U256::zero()
|
||||||
}.sign(keypair.secret());
|
}.sign(keypair.secret(), None);
|
||||||
let sender = t.sender().unwrap();
|
let sender = t.sender().unwrap();
|
||||||
|
|
||||||
let mut state_result = get_temp_state();
|
let mut state_result = get_temp_state();
|
||||||
let mut state = state_result.reference_mut();
|
let mut state = state_result.reference_mut();
|
||||||
state.add_balance(&sender, &U256::from(100_017));
|
state.add_balance(&sender, &U256::from(100_017), CleanupMode::NoEmpty);
|
||||||
let mut info = EnvInfo::default();
|
let mut info = EnvInfo::default();
|
||||||
info.gas_limit = U256::from(100_000);
|
info.gas_limit = U256::from(100_000);
|
||||||
let engine = TestEngine::new(0);
|
let engine = TestEngine::new(0);
|
||||||
@ -1215,7 +1227,7 @@ mod tests {
|
|||||||
params.value = ActionValue::Transfer(U256::from_str("0de0b6b3a7640000").unwrap());
|
params.value = ActionValue::Transfer(U256::from_str("0de0b6b3a7640000").unwrap());
|
||||||
let mut state_result = get_temp_state();
|
let mut state_result = get_temp_state();
|
||||||
let mut state = state_result.reference_mut();
|
let mut state = state_result.reference_mut();
|
||||||
state.add_balance(&sender, &U256::from_str("152d02c7e14af6800000").unwrap());
|
state.add_balance(&sender, &U256::from_str("152d02c7e14af6800000").unwrap(), CleanupMode::NoEmpty);
|
||||||
let info = EnvInfo::default();
|
let info = EnvInfo::default();
|
||||||
let engine = TestEngine::new(0);
|
let engine = TestEngine::new(0);
|
||||||
let mut substate = Substate::new();
|
let mut substate = Substate::new();
|
||||||
|
@ -114,6 +114,12 @@ impl<'a, T, V> Ext for Externalities<'a, T, V> where T: 'a + Tracer, V: 'a + VMT
|
|||||||
self.state.exists(address)
|
self.state.exists(address)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn exists_and_not_null(&self, address: &Address) -> bool {
|
||||||
|
self.state.exists_and_not_null(address)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn origin_balance(&self) -> U256 { self.balance(&self.origin_info.address) }
|
||||||
|
|
||||||
fn balance(&self, address: &Address) -> U256 {
|
fn balance(&self, address: &Address) -> U256 {
|
||||||
self.state.balance(address)
|
self.state.balance(address)
|
||||||
}
|
}
|
||||||
@ -269,11 +275,11 @@ impl<'a, T, V> Ext for Externalities<'a, T, V> where T: 'a + Tracer, V: 'a + VMT
|
|||||||
let address = self.origin_info.address.clone();
|
let address = self.origin_info.address.clone();
|
||||||
let balance = self.balance(&address);
|
let balance = self.balance(&address);
|
||||||
if &address == refund_address {
|
if &address == refund_address {
|
||||||
// TODO [todr] To be consisted with CPP client we set balance to 0 in that case.
|
// TODO [todr] To be consistent with CPP client we set balance to 0 in that case.
|
||||||
self.state.sub_balance(&address, &balance);
|
self.state.sub_balance(&address, &balance);
|
||||||
} else {
|
} else {
|
||||||
trace!("Suiciding {} -> {} (xfer: {})", address, refund_address, balance);
|
trace!(target: "ext", "Suiciding {} -> {} (xfer: {})", address, refund_address, balance);
|
||||||
self.state.transfer_balance(&address, refund_address, &balance);
|
self.state.transfer_balance(&address, refund_address, &balance, self.substate.to_cleanup_mode(&self.schedule));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.tracer.trace_suicide(address, balance, refund_address.clone());
|
self.tracer.trace_suicide(address, balance, refund_address.clone());
|
||||||
|
@ -49,6 +49,7 @@ pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec<String> {
|
|||||||
ChainEra::Frontier => ethereum::new_frontier_test(),
|
ChainEra::Frontier => ethereum::new_frontier_test(),
|
||||||
ChainEra::Homestead => ethereum::new_homestead_test(),
|
ChainEra::Homestead => ethereum::new_homestead_test(),
|
||||||
ChainEra::Eip150 => ethereum::new_eip150_test(),
|
ChainEra::Eip150 => ethereum::new_eip150_test(),
|
||||||
|
ChainEra::Eip161 => ethereum::new_eip161_test(),
|
||||||
ChainEra::TransitionTest => ethereum::new_transition_test(),
|
ChainEra::TransitionTest => ethereum::new_transition_test(),
|
||||||
};
|
};
|
||||||
spec.set_genesis_state(state);
|
spec.set_genesis_state(state);
|
||||||
|
51
ethcore/src/json_tests/eip161_state.rs
Normal file
51
ethcore/src/json_tests/eip161_state.rs
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
// Copyright 2015, 2016 Ethcore (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 super::test_common::*;
|
||||||
|
use tests::helpers::*;
|
||||||
|
use super::state::json_chain_test;
|
||||||
|
|
||||||
|
fn do_json_test(json_data: &[u8]) -> Vec<String> {
|
||||||
|
json_chain_test(json_data, ChainEra::Eip161)
|
||||||
|
}
|
||||||
|
|
||||||
|
declare_test!{StateTests_EIP158_stEIP158SpecificTest, "StateTests/EIP158/stEIP158SpecificTest"}
|
||||||
|
declare_test!{StateTests_EIP158_stNonZeroCallsTest, "StateTests/EIP158/stNonZeroCallsTest"}
|
||||||
|
declare_test!{StateTests_EIP158_stZeroCallsTest, "StateTests/EIP158/stZeroCallsTest"}
|
||||||
|
|
||||||
|
declare_test!{StateTests_EIP158_EIP150_stMemExpandingEIPCalls, "StateTests/EIP158/EIP150/stMemExpandingEIPCalls"}
|
||||||
|
declare_test!{StateTests_EIP158_EIP150_stEIPSpecificTest, "StateTests/EIP158/EIP150/stEIPSpecificTest"}
|
||||||
|
declare_test!{StateTests_EIP158_EIP150_stEIPsingleCodeGasPrices, "StateTests/EIP158/EIP150/stEIPsingleCodeGasPrices"}
|
||||||
|
declare_test!{StateTests_EIP158_EIP150_stChangedTests, "StateTests/EIP158/EIP150/stChangedTests"}
|
||||||
|
|
||||||
|
declare_test!{StateTests_EIP158_Homestead_stBoundsTest, "StateTests/EIP158/Homestead/stBoundsTest"}
|
||||||
|
declare_test!{StateTests_EIP158_Homestead_stCallCodes, "StateTests/EIP158/Homestead/stCallCodes"}
|
||||||
|
declare_test!{StateTests_EIP158_Homestead_stCallCreateCallCodeTest, "StateTests/EIP158/Homestead/stCallCreateCallCodeTest"}
|
||||||
|
declare_test!{StateTests_EIP158_Homestead_stCallDelegateCodes, "StateTests/EIP158/Homestead/stCallDelegateCodes"}
|
||||||
|
declare_test!{StateTests_EIP158_Homestead_stCallDelegateCodesCallCode, "StateTests/EIP158/Homestead/stCallDelegateCodesCallCode"}
|
||||||
|
declare_test!{StateTests_EIP158_Homestead_stDelegatecallTest, "StateTests/EIP158/Homestead/stDelegatecallTest"}
|
||||||
|
declare_test!{StateTests_EIP158_Homestead_stHomeSteadSpecific, "StateTests/EIP158/Homestead/stHomeSteadSpecific"}
|
||||||
|
declare_test!{StateTests_EIP158_Homestead_stInitCodeTest, "StateTests/EIP158/Homestead/stInitCodeTest"}
|
||||||
|
declare_test!{StateTests_EIP158_Homestead_stLogTests, "StateTests/EIP158/Homestead/stLogTests"}
|
||||||
|
declare_test!{heavy => StateTests_EIP158_Homestead_stMemoryTest, "StateTests/EIP158/Homestead/stMemoryTest"}
|
||||||
|
declare_test!{StateTests_EIP158_Homestead_stPreCompiledContracts, "StateTests/EIP158/Homestead/stPreCompiledContracts"}
|
||||||
|
declare_test!{heavy => StateTests_EIP158_Homestead_stQuadraticComplexityTest, "StateTests/EIP158/Homestead/stQuadraticComplexityTest"}
|
||||||
|
declare_test!{StateTests_EIP158_Homestead_stRecursiveCreate, "StateTests/EIP158/Homestead/stRecursiveCreate"}
|
||||||
|
declare_test!{StateTests_EIP158_Homestead_stRefundTest, "StateTests/EIP158/Homestead/stRefundTest"}
|
||||||
|
declare_test!{StateTests_EIP158_Homestead_stSpecialTest, "StateTests/EIP158/Homestead/stSpecialTest"}
|
||||||
|
declare_test!{StateTests_EIP158_Homestead_stSystemOperationsTest, "StateTests/EIP158/Homestead/stSystemOperationsTest"}
|
||||||
|
declare_test!{StateTests_EIP158_Homestead_stTransactionTest, "StateTests/EIP158/Homestead/stTransactionTest"}
|
||||||
|
declare_test!{StateTests_EIP158_Homestead_stWalletTest, "StateTests/EIP158/Homestead/stWalletTest"}
|
@ -92,10 +92,18 @@ impl<'a, T, V> Ext for TestExt<'a, T, V> where T: Tracer, V: VMTracer {
|
|||||||
self.ext.exists(address)
|
self.ext.exists(address)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn exists_and_not_null(&self, address: &Address) -> bool {
|
||||||
|
self.ext.exists_and_not_null(address)
|
||||||
|
}
|
||||||
|
|
||||||
fn balance(&self, address: &Address) -> U256 {
|
fn balance(&self, address: &Address) -> U256 {
|
||||||
self.ext.balance(address)
|
self.ext.balance(address)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn origin_balance(&self) -> U256 {
|
||||||
|
self.ext.origin_balance()
|
||||||
|
}
|
||||||
|
|
||||||
fn blockhash(&self, number: &U256) -> H256 {
|
fn blockhash(&self, number: &U256) -> H256 {
|
||||||
self.ext.blockhash(number)
|
self.ext.blockhash(number)
|
||||||
}
|
}
|
||||||
|
@ -24,4 +24,5 @@ mod chain;
|
|||||||
mod homestead_state;
|
mod homestead_state;
|
||||||
mod homestead_chain;
|
mod homestead_chain;
|
||||||
mod eip150_state;
|
mod eip150_state;
|
||||||
|
mod eip161_state;
|
||||||
mod trie;
|
mod trie;
|
||||||
|
@ -29,6 +29,7 @@ pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec<String> {
|
|||||||
ChainEra::Frontier => ethereum::new_mainnet_like().engine,
|
ChainEra::Frontier => ethereum::new_mainnet_like().engine,
|
||||||
ChainEra::Homestead => ethereum::new_homestead_test().engine,
|
ChainEra::Homestead => ethereum::new_homestead_test().engine,
|
||||||
ChainEra::Eip150 => ethereum::new_eip150_test().engine,
|
ChainEra::Eip150 => ethereum::new_eip150_test().engine,
|
||||||
|
ChainEra::Eip161 => ethereum::new_eip161_test().engine,
|
||||||
ChainEra::TransitionTest => ethereum::new_transition_test().engine,
|
ChainEra::TransitionTest => ethereum::new_transition_test().engine,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -35,17 +35,24 @@ fn do_json_test(json_data: &[u8]) -> Vec<String> {
|
|||||||
Some(x) if x < 1_150_000 => &old_schedule,
|
Some(x) if x < 1_150_000 => &old_schedule,
|
||||||
Some(_) => &new_schedule
|
Some(_) => &new_schedule
|
||||||
};
|
};
|
||||||
|
let allow_network_id_of_one = number.map_or(false, |n| n > 2600000);
|
||||||
|
|
||||||
let rlp: Vec<u8> = test.rlp.into();
|
let rlp: Vec<u8> = test.rlp.into();
|
||||||
let res = UntrustedRlp::new(&rlp)
|
let res = UntrustedRlp::new(&rlp)
|
||||||
.as_val()
|
.as_val()
|
||||||
.map_err(From::from)
|
.map_err(From::from)
|
||||||
.and_then(|t: SignedTransaction| t.validate(schedule, schedule.have_delegate_call));
|
.and_then(|t: SignedTransaction| t.validate(schedule, schedule.have_delegate_call, allow_network_id_of_one));
|
||||||
|
|
||||||
fail_unless(test.transaction.is_none() == res.is_err());
|
fail_unless(test.transaction.is_none() == res.is_err());
|
||||||
if let (Some(tx), Some(sender)) = (test.transaction, test.sender) {
|
if let (Some(tx), Some(sender)) = (test.transaction, test.sender) {
|
||||||
let t = res.unwrap();
|
let t = res.unwrap();
|
||||||
fail_unless(t.sender().unwrap() == sender.into());
|
fail_unless(t.sender().unwrap() == sender.into());
|
||||||
|
let is_acceptable_network_id = match t.network_id() {
|
||||||
|
None => true,
|
||||||
|
Some(1) if allow_network_id_of_one => true,
|
||||||
|
_ => false,
|
||||||
|
};
|
||||||
|
fail_unless(is_acceptable_network_id);
|
||||||
let data: Vec<u8> = tx.data.into();
|
let data: Vec<u8> = tx.data.into();
|
||||||
fail_unless(t.data == data);
|
fail_unless(t.data == data);
|
||||||
fail_unless(t.gas_price == tx.gas_price.into());
|
fail_unless(t.gas_price == tx.gas_price.into());
|
||||||
|
@ -245,7 +245,7 @@ mod tests {
|
|||||||
gas: U256::from(100_000),
|
gas: U256::from(100_000),
|
||||||
gas_price: U256::from(10),
|
gas_price: U256::from(10),
|
||||||
nonce: U256::from(0),
|
nonce: U256::from(0),
|
||||||
}.sign(keypair.secret())
|
}.sign(keypair.secret(), None)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unwrap_err(res: Result<TransactionImportResult, Error>) -> TransactionError {
|
fn unwrap_err(res: Result<TransactionImportResult, Error>) -> TransactionError {
|
||||||
|
@ -21,7 +21,7 @@ use util::*;
|
|||||||
use util::using_queue::{UsingQueue, GetAction};
|
use util::using_queue::{UsingQueue, GetAction};
|
||||||
use account_provider::AccountProvider;
|
use account_provider::AccountProvider;
|
||||||
use views::{BlockView, HeaderView};
|
use views::{BlockView, HeaderView};
|
||||||
use state::State;
|
use state::{State, CleanupMode};
|
||||||
use client::{MiningBlockChainClient, Executive, Executed, EnvInfo, TransactOptions, BlockID, CallAnalytics};
|
use client::{MiningBlockChainClient, Executive, Executed, EnvInfo, TransactOptions, BlockID, CallAnalytics};
|
||||||
use executive::contract_address;
|
use executive::contract_address;
|
||||||
use block::{ClosedBlock, SealedBlock, IsBlock, Block};
|
use block::{ClosedBlock, SealedBlock, IsBlock, Block};
|
||||||
@ -657,7 +657,7 @@ impl MinerService for Miner {
|
|||||||
let needed_balance = t.value + t.gas * t.gas_price;
|
let needed_balance = t.value + t.gas * t.gas_price;
|
||||||
if balance < needed_balance {
|
if balance < needed_balance {
|
||||||
// give the sender a sufficient balance
|
// give the sender a sufficient balance
|
||||||
state.add_balance(&sender, &(needed_balance - balance));
|
state.add_balance(&sender, &(needed_balance - balance), CleanupMode::NoEmpty);
|
||||||
}
|
}
|
||||||
let options = TransactOptions { tracing: analytics.transaction_tracing, vm_tracing: analytics.vm_tracing, check_nonce: false };
|
let options = TransactOptions { tracing: analytics.transaction_tracing, vm_tracing: analytics.vm_tracing, check_nonce: false };
|
||||||
let mut ret = try!(Executive::new(&mut state, &env_info, &*self.engine, chain.vm_factory()).transact(t, options));
|
let mut ret = try!(Executive::new(&mut state, &env_info, &*self.engine, chain.vm_factory()).transact(t, options));
|
||||||
@ -942,6 +942,8 @@ impl MinerService for Miner {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
logs: receipt.logs.clone(),
|
logs: receipt.logs.clone(),
|
||||||
|
log_bloom: receipt.log_bloom,
|
||||||
|
state_root: receipt.state_root,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -1180,7 +1182,7 @@ mod tests {
|
|||||||
gas: U256::from(100_000),
|
gas: U256::from(100_000),
|
||||||
gas_price: U256::zero(),
|
gas_price: U256::zero(),
|
||||||
nonce: U256::zero(),
|
nonce: U256::zero(),
|
||||||
}.sign(keypair.secret())
|
}.sign(keypair.secret(), None)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -42,8 +42,8 @@
|
|||||||
//! let t2 = Transaction { action: Action::Create, value: U256::from(100), data: "3331600055".from_hex().unwrap(),
|
//! let t2 = Transaction { action: Action::Create, value: U256::from(100), data: "3331600055".from_hex().unwrap(),
|
||||||
//! gas: U256::from(100_000), gas_price: U256::one(), nonce: U256::from(11) };
|
//! gas: U256::from(100_000), gas_price: U256::one(), nonce: U256::from(11) };
|
||||||
//!
|
//!
|
||||||
//! let st1 = t1.sign(&key.secret());
|
//! let st1 = t1.sign(&key.secret(), None);
|
||||||
//! let st2 = t2.sign(&key.secret());
|
//! let st2 = t2.sign(&key.secret(), None);
|
||||||
//! let default_account_details = |_a: &Address| AccountDetails {
|
//! let default_account_details = |_a: &Address| AccountDetails {
|
||||||
//! nonce: U256::from(10),
|
//! nonce: U256::from(10),
|
||||||
//! balance: U256::from(1_000_000),
|
//! balance: U256::from(1_000_000),
|
||||||
@ -1104,12 +1104,12 @@ mod test {
|
|||||||
|
|
||||||
fn new_tx(nonce: U256, gas_price: U256) -> SignedTransaction {
|
fn new_tx(nonce: U256, gas_price: U256) -> SignedTransaction {
|
||||||
let keypair = Random.generate().unwrap();
|
let keypair = Random.generate().unwrap();
|
||||||
new_unsigned_tx(nonce, default_gas_val(), gas_price).sign(keypair.secret())
|
new_unsigned_tx(nonce, default_gas_val(), gas_price).sign(keypair.secret(), None)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_tx_with_gas(gas: U256, gas_price: U256) -> SignedTransaction {
|
fn new_tx_with_gas(gas: U256, gas_price: U256) -> SignedTransaction {
|
||||||
let keypair = Random.generate().unwrap();
|
let keypair = Random.generate().unwrap();
|
||||||
new_unsigned_tx(default_nonce(), gas, gas_price).sign(keypair.secret())
|
new_unsigned_tx(default_nonce(), gas, gas_price).sign(keypair.secret(), None)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_tx_default() -> SignedTransaction {
|
fn new_tx_default() -> SignedTransaction {
|
||||||
@ -1133,7 +1133,7 @@ mod test {
|
|||||||
|
|
||||||
let keypair = Random.generate().unwrap();
|
let keypair = Random.generate().unwrap();
|
||||||
let secret = &keypair.secret();
|
let secret = &keypair.secret();
|
||||||
(tx1.sign(secret), tx2.sign(secret))
|
(tx1.sign(secret, None), tx2.sign(secret, None))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns two consecutive transactions, both with increased gas price
|
/// Returns two consecutive transactions, both with increased gas price
|
||||||
@ -1144,7 +1144,7 @@ mod test {
|
|||||||
|
|
||||||
let keypair = Random.generate().unwrap();
|
let keypair = Random.generate().unwrap();
|
||||||
let secret = &keypair.secret();
|
let secret = &keypair.secret();
|
||||||
(tx1.sign(secret), tx2.sign(secret))
|
(tx1.sign(secret, None), tx2.sign(secret, None))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_tx_pair_default(nonce_increment: U256, gas_price_increment: U256) -> (SignedTransaction, SignedTransaction) {
|
fn new_tx_pair_default(nonce_increment: U256, gas_price_increment: U256) -> (SignedTransaction, SignedTransaction) {
|
||||||
@ -1798,9 +1798,9 @@ mod test {
|
|||||||
let mut txq = TransactionQueue::default();
|
let mut txq = TransactionQueue::default();
|
||||||
let kp = Random.generate().unwrap();
|
let kp = Random.generate().unwrap();
|
||||||
let secret = kp.secret();
|
let secret = kp.secret();
|
||||||
let tx = new_unsigned_tx(123.into(), default_gas_val(), 1.into()).sign(secret);
|
let tx = new_unsigned_tx(123.into(), default_gas_val(), 1.into()).sign(secret, None);
|
||||||
let tx1 = new_unsigned_tx(124.into(), default_gas_val(), 1.into()).sign(secret);
|
let tx1 = new_unsigned_tx(124.into(), default_gas_val(), 1.into()).sign(secret, None);
|
||||||
let tx2 = new_unsigned_tx(125.into(), default_gas_val(), 1.into()).sign(secret);
|
let tx2 = new_unsigned_tx(125.into(), default_gas_val(), 1.into()).sign(secret, None);
|
||||||
|
|
||||||
txq.add(tx, TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap();
|
txq.add(tx, TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap();
|
||||||
assert_eq!(txq.status().pending, 1);
|
assert_eq!(txq.status().pending, 1);
|
||||||
@ -2038,11 +2038,11 @@ mod test {
|
|||||||
// given
|
// given
|
||||||
let mut txq = TransactionQueue::default();
|
let mut txq = TransactionQueue::default();
|
||||||
let keypair = Random.generate().unwrap();
|
let keypair = Random.generate().unwrap();
|
||||||
let tx = new_unsigned_tx(123.into(), default_gas_val(), 1.into()).sign(keypair.secret());
|
let tx = new_unsigned_tx(123.into(), default_gas_val(), 1.into()).sign(keypair.secret(), None);
|
||||||
let tx2 = {
|
let tx2 = {
|
||||||
let mut tx2 = (*tx).clone();
|
let mut tx2 = (*tx).clone();
|
||||||
tx2.gas_price = U256::from(200);
|
tx2.gas_price = U256::from(200);
|
||||||
tx2.sign(keypair.secret())
|
tx2.sign(keypair.secret(), None)
|
||||||
};
|
};
|
||||||
|
|
||||||
// when
|
// when
|
||||||
@ -2061,16 +2061,16 @@ mod test {
|
|||||||
// given
|
// given
|
||||||
let mut txq = TransactionQueue::default();
|
let mut txq = TransactionQueue::default();
|
||||||
let keypair = Random.generate().unwrap();
|
let keypair = Random.generate().unwrap();
|
||||||
let tx0 = new_unsigned_tx(123.into(), default_gas_val(), 1.into()).sign(keypair.secret());
|
let tx0 = new_unsigned_tx(123.into(), default_gas_val(), 1.into()).sign(keypair.secret(), None);
|
||||||
let tx1 = {
|
let tx1 = {
|
||||||
let mut tx1 = (*tx0).clone();
|
let mut tx1 = (*tx0).clone();
|
||||||
tx1.nonce = U256::from(124);
|
tx1.nonce = U256::from(124);
|
||||||
tx1.sign(keypair.secret())
|
tx1.sign(keypair.secret(), None)
|
||||||
};
|
};
|
||||||
let tx2 = {
|
let tx2 = {
|
||||||
let mut tx2 = (*tx1).clone();
|
let mut tx2 = (*tx1).clone();
|
||||||
tx2.gas_price = U256::from(200);
|
tx2.gas_price = U256::from(200);
|
||||||
tx2.sign(keypair.secret())
|
tx2.sign(keypair.secret(), None)
|
||||||
};
|
};
|
||||||
|
|
||||||
// when
|
// when
|
||||||
@ -2223,7 +2223,7 @@ mod test {
|
|||||||
let tx3 = new_unsigned_tx(nonce + 2.into(), gas, 1.into());
|
let tx3 = new_unsigned_tx(nonce + 2.into(), gas, 1.into());
|
||||||
|
|
||||||
|
|
||||||
(tx.sign(secret), tx2.sign(secret), tx2_2.sign(secret), tx3.sign(secret))
|
(tx.sign(secret, None), tx2.sign(secret, None), tx2_2.sign(secret, None), tx3.sign(secret, None))
|
||||||
};
|
};
|
||||||
let sender = tx1.sender().unwrap();
|
let sender = tx1.sender().unwrap();
|
||||||
txq.add(tx1, TransactionOrigin::Local, &default_account_details, &gas_estimator).unwrap();
|
txq.add(tx1, TransactionOrigin::Local, &default_account_details, &gas_estimator).unwrap();
|
||||||
|
@ -38,7 +38,7 @@ pub struct CommonParams {
|
|||||||
/// Maximum size of extra data.
|
/// Maximum size of extra data.
|
||||||
pub maximum_extra_data_size: usize,
|
pub maximum_extra_data_size: usize,
|
||||||
/// Network id.
|
/// Network id.
|
||||||
pub network_id: U256,
|
pub network_id: usize,
|
||||||
/// Main subprotocol name.
|
/// Main subprotocol name.
|
||||||
pub subprotocol_name: String,
|
pub subprotocol_name: String,
|
||||||
/// Minimum gas limit.
|
/// Minimum gas limit.
|
||||||
@ -161,7 +161,7 @@ impl Spec {
|
|||||||
pub fn nodes(&self) -> &[String] { &self.nodes }
|
pub fn nodes(&self) -> &[String] { &self.nodes }
|
||||||
|
|
||||||
/// Get the configured Network ID.
|
/// Get the configured Network ID.
|
||||||
pub fn network_id(&self) -> U256 { self.params.network_id }
|
pub fn network_id(&self) -> usize { self.params.network_id }
|
||||||
|
|
||||||
/// Get the configured Network ID.
|
/// Get the configured Network ID.
|
||||||
pub fn subprotocol_name(&self) -> String { self.params.subprotocol_name.clone() }
|
pub fn subprotocol_name(&self) -> String { self.params.subprotocol_name.clone() }
|
||||||
@ -251,7 +251,7 @@ impl Spec {
|
|||||||
}
|
}
|
||||||
trace!(target: "spec", "ensure_db_good: Populated sec trie; root is {}", root);
|
trace!(target: "spec", "ensure_db_good: Populated sec trie; root is {}", root);
|
||||||
for (address, account) in self.genesis_state.get().iter() {
|
for (address, account) in self.genesis_state.get().iter() {
|
||||||
db.note_account_bloom(address);
|
db.note_non_null_account(address);
|
||||||
account.insert_additional(&mut AccountDBMut::new(db.as_hashdb_mut(), address));
|
account.insert_additional(&mut AccountDBMut::new(db.as_hashdb_mut(), address));
|
||||||
}
|
}
|
||||||
assert!(db.as_hashdb().contains(&self.state_root()));
|
assert!(db.as_hashdb().contains(&self.state_root()));
|
||||||
|
@ -300,11 +300,17 @@ impl Account {
|
|||||||
pub fn storage_is_clean(&self) -> bool { self.storage_changes.is_empty() }
|
pub fn storage_is_clean(&self) -> bool { self.storage_changes.is_empty() }
|
||||||
|
|
||||||
/// Check if account has zero nonce, balance, no code and no storage.
|
/// Check if account has zero nonce, balance, no code and no storage.
|
||||||
|
///
|
||||||
|
/// NOTE: Will panic if `!self.storage_is_clean()`
|
||||||
pub fn is_empty(&self) -> bool {
|
pub fn is_empty(&self) -> bool {
|
||||||
self.storage_changes.is_empty() &&
|
assert!(self.storage_is_clean(), "Account::is_empty() may only legally be called when storage is clean.");
|
||||||
|
self.is_null() && self.storage_root == SHA3_NULL_RLP
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check if account has zero nonce, balance, no code.
|
||||||
|
pub fn is_null(&self) -> bool {
|
||||||
self.balance.is_zero() &&
|
self.balance.is_zero() &&
|
||||||
self.nonce.is_zero() &&
|
self.nonce.is_zero() &&
|
||||||
self.storage_root == SHA3_NULL_RLP &&
|
|
||||||
self.code_hash == SHA3_EMPTY
|
self.code_hash == SHA3_EMPTY
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,6 +199,13 @@ enum RequireCache {
|
|||||||
Code,
|
Code,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq)]
|
||||||
|
pub enum CleanupMode<'a> {
|
||||||
|
ForceCreate,
|
||||||
|
NoEmpty,
|
||||||
|
KillEmpty(&'a mut HashSet<Address>),
|
||||||
|
}
|
||||||
|
|
||||||
const SEC_TRIE_DB_UNWRAP_STR: &'static str = "A state can only be created with valid root. Creating a SecTrieDB with a valid root will not fail. \
|
const SEC_TRIE_DB_UNWRAP_STR: &'static str = "A state can only be created with valid root. Creating a SecTrieDB with a valid root will not fail. \
|
||||||
Therefore creating a SecTrieDB with this state's root will not fail.";
|
Therefore creating a SecTrieDB with this state's root will not fail.";
|
||||||
|
|
||||||
@ -329,8 +336,8 @@ impl State {
|
|||||||
|
|
||||||
/// Create a new contract at address `contract`. If there is already an account at the address
|
/// Create a new contract at address `contract`. If there is already an account at the address
|
||||||
/// it will have its code reset, ready for `init_code()`.
|
/// it will have its code reset, ready for `init_code()`.
|
||||||
pub fn new_contract(&mut self, contract: &Address, balance: U256) {
|
pub fn new_contract(&mut self, contract: &Address, balance: U256, nonce_offset: U256) {
|
||||||
self.insert_cache(contract, AccountEntry::new_dirty(Some(Account::new_contract(balance, self.account_start_nonce))));
|
self.insert_cache(contract, AccountEntry::new_dirty(Some(Account::new_contract(balance, self.account_start_nonce + nonce_offset))));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Remove an existing account.
|
/// Remove an existing account.
|
||||||
@ -341,10 +348,15 @@ impl State {
|
|||||||
/// Determine whether an account exists.
|
/// Determine whether an account exists.
|
||||||
pub fn exists(&self, a: &Address) -> bool {
|
pub fn exists(&self, a: &Address) -> bool {
|
||||||
// Bloom filter does not contain empty accounts, so it is important here to
|
// Bloom filter does not contain empty accounts, so it is important here to
|
||||||
// check if account exists in the database directly before EIP-158 is in effect.
|
// check if account exists in the database directly before EIP-161 is in effect.
|
||||||
self.ensure_cached(a, RequireCache::None, false, |a| a.is_some())
|
self.ensure_cached(a, RequireCache::None, false, |a| a.is_some())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Determine whether an account exists and if not empty.
|
||||||
|
pub fn exists_and_not_null(&self, a: &Address) -> bool {
|
||||||
|
self.ensure_cached(a, RequireCache::None, false, |a| a.map_or(false, |a| !a.is_null()))
|
||||||
|
}
|
||||||
|
|
||||||
/// Get the balance of account `a`.
|
/// Get the balance of account `a`.
|
||||||
pub fn balance(&self, a: &Address) -> U256 {
|
pub fn balance(&self, a: &Address) -> U256 {
|
||||||
self.ensure_cached(a, RequireCache::None, true,
|
self.ensure_cached(a, RequireCache::None, true,
|
||||||
@ -399,7 +411,7 @@ impl State {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check bloom before any requests to trie
|
// check bloom before any requests to trie
|
||||||
if !self.db.check_account_bloom(address) { return H256::zero() }
|
if !self.db.check_non_null_bloom(address) { return H256::zero() }
|
||||||
|
|
||||||
// account is not found in the global cache, get from the DB and insert into local
|
// account is not found in the global cache, get from the DB and insert into local
|
||||||
let db = self.factories.trie.readonly(self.db.as_hashdb(), &self.root).expect(SEC_TRIE_DB_UNWRAP_STR);
|
let db = self.factories.trie.readonly(self.db.as_hashdb(), &self.root).expect(SEC_TRIE_DB_UNWRAP_STR);
|
||||||
@ -433,10 +445,18 @@ impl State {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Add `incr` to the balance of account `a`.
|
/// Add `incr` to the balance of account `a`.
|
||||||
pub fn add_balance(&mut self, a: &Address, incr: &U256) {
|
pub fn add_balance(&mut self, a: &Address, incr: &U256, cleanup_mode: CleanupMode) {
|
||||||
trace!(target: "state", "add_balance({}, {}): {}", a, incr, self.balance(a));
|
trace!(target: "state", "add_balance({}, {}): {}", a, incr, self.balance(a));
|
||||||
if !incr.is_zero() || !self.exists(a) {
|
let is_value_transfer = !incr.is_zero();
|
||||||
|
if is_value_transfer || (cleanup_mode == CleanupMode::ForceCreate && !self.exists(a)) {
|
||||||
self.require(a, false).add_balance(incr);
|
self.require(a, false).add_balance(incr);
|
||||||
|
} else {
|
||||||
|
match cleanup_mode {
|
||||||
|
CleanupMode::KillEmpty(set) => if !is_value_transfer && self.exists(a) && !self.exists_and_not_null(a) {
|
||||||
|
set.insert(a.clone());
|
||||||
|
},
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -449,9 +469,9 @@ impl State {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Subtracts `by` from the balance of `from` and adds it to that of `to`.
|
/// Subtracts `by` from the balance of `from` and adds it to that of `to`.
|
||||||
pub fn transfer_balance(&mut self, from: &Address, to: &Address, by: &U256) {
|
pub fn transfer_balance(&mut self, from: &Address, to: &Address, by: &U256, cleanup_mode: CleanupMode) {
|
||||||
self.sub_balance(from, by);
|
self.sub_balance(from, by);
|
||||||
self.add_balance(to, by);
|
self.add_balance(to, by, cleanup_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Increment the nonce of account `a` by 1.
|
/// Increment the nonce of account `a` by 1.
|
||||||
@ -507,14 +527,16 @@ impl State {
|
|||||||
// first, commit the sub trees.
|
// first, commit the sub trees.
|
||||||
for (address, ref mut a) in accounts.iter_mut().filter(|&(_, ref a)| a.is_dirty()) {
|
for (address, ref mut a) in accounts.iter_mut().filter(|&(_, ref a)| a.is_dirty()) {
|
||||||
if let Some(ref mut account) = a.account {
|
if let Some(ref mut account) = a.account {
|
||||||
if !account.is_empty() {
|
|
||||||
db.note_account_bloom(address);
|
|
||||||
}
|
|
||||||
let addr_hash = account.address_hash(address);
|
let addr_hash = account.address_hash(address);
|
||||||
|
{
|
||||||
let mut account_db = factories.accountdb.create(db.as_hashdb_mut(), addr_hash);
|
let mut account_db = factories.accountdb.create(db.as_hashdb_mut(), addr_hash);
|
||||||
account.commit_storage(&factories.trie, account_db.as_hashdb_mut());
|
account.commit_storage(&factories.trie, account_db.as_hashdb_mut());
|
||||||
account.commit_code(account_db.as_hashdb_mut());
|
account.commit_code(account_db.as_hashdb_mut());
|
||||||
}
|
}
|
||||||
|
if !account.is_empty() {
|
||||||
|
db.note_non_null_account(address);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -653,7 +675,7 @@ impl State {
|
|||||||
Some(r) => r,
|
Some(r) => r,
|
||||||
None => {
|
None => {
|
||||||
// first check bloom if it is not in database for sure
|
// first check bloom if it is not in database for sure
|
||||||
if check_bloom && !self.db.check_account_bloom(a) { return f(None); }
|
if check_bloom && !self.db.check_non_null_bloom(a) { return f(None); }
|
||||||
|
|
||||||
// not found in the global cache, get from the DB and insert into local
|
// not found in the global cache, get from the DB and insert into local
|
||||||
let db = self.factories.trie.readonly(self.db.as_hashdb(), &self.root).expect(SEC_TRIE_DB_UNWRAP_STR);
|
let db = self.factories.trie.readonly(self.db.as_hashdb(), &self.root).expect(SEC_TRIE_DB_UNWRAP_STR);
|
||||||
@ -687,7 +709,7 @@ impl State {
|
|||||||
match self.db.get_cached_account(a) {
|
match self.db.get_cached_account(a) {
|
||||||
Some(acc) => self.insert_cache(a, AccountEntry::new_clean_cached(acc)),
|
Some(acc) => self.insert_cache(a, AccountEntry::new_clean_cached(acc)),
|
||||||
None => {
|
None => {
|
||||||
let maybe_acc = if self.db.check_account_bloom(a) {
|
let maybe_acc = if self.db.check_non_null_bloom(a) {
|
||||||
let db = self.factories.trie.readonly(self.db.as_hashdb(), &self.root).expect(SEC_TRIE_DB_UNWRAP_STR);
|
let db = self.factories.trie.readonly(self.db.as_hashdb(), &self.root).expect(SEC_TRIE_DB_UNWRAP_STR);
|
||||||
match db.get(a) {
|
match db.get(a) {
|
||||||
Ok(Some(acc)) => AccountEntry::new_clean(Some(Account::from_rlp(&acc))),
|
Ok(Some(acc)) => AccountEntry::new_clean(Some(Account::from_rlp(&acc))),
|
||||||
@ -793,9 +815,9 @@ fn should_apply_create_transaction() {
|
|||||||
action: Action::Create,
|
action: Action::Create,
|
||||||
value: 100.into(),
|
value: 100.into(),
|
||||||
data: FromHex::from_hex("601080600c6000396000f3006000355415600957005b60203560003555").unwrap(),
|
data: FromHex::from_hex("601080600c6000396000f3006000355415600957005b60203560003555").unwrap(),
|
||||||
}.sign(&"".sha3());
|
}.sign(&"".sha3(), None);
|
||||||
|
|
||||||
state.add_balance(t.sender().as_ref().unwrap(), &(100.into()));
|
state.add_balance(t.sender().as_ref().unwrap(), &(100.into()), CleanupMode::NoEmpty);
|
||||||
let result = state.apply(&info, &engine, &t, true).unwrap();
|
let result = state.apply(&info, &engine, &t, true).unwrap();
|
||||||
let expected_trace = vec![FlatTrace {
|
let expected_trace = vec![FlatTrace {
|
||||||
trace_address: Default::default(),
|
trace_address: Default::default(),
|
||||||
@ -853,9 +875,9 @@ fn should_trace_failed_create_transaction() {
|
|||||||
action: Action::Create,
|
action: Action::Create,
|
||||||
value: 100.into(),
|
value: 100.into(),
|
||||||
data: FromHex::from_hex("5b600056").unwrap(),
|
data: FromHex::from_hex("5b600056").unwrap(),
|
||||||
}.sign(&"".sha3());
|
}.sign(&"".sha3(), None);
|
||||||
|
|
||||||
state.add_balance(t.sender().as_ref().unwrap(), &(100.into()));
|
state.add_balance(t.sender().as_ref().unwrap(), &(100.into()), CleanupMode::NoEmpty);
|
||||||
let result = state.apply(&info, &engine, &t, true).unwrap();
|
let result = state.apply(&info, &engine, &t, true).unwrap();
|
||||||
let expected_trace = vec![FlatTrace {
|
let expected_trace = vec![FlatTrace {
|
||||||
trace_address: Default::default(),
|
trace_address: Default::default(),
|
||||||
@ -890,10 +912,10 @@ fn should_trace_call_transaction() {
|
|||||||
action: Action::Call(0xa.into()),
|
action: Action::Call(0xa.into()),
|
||||||
value: 100.into(),
|
value: 100.into(),
|
||||||
data: vec![],
|
data: vec![],
|
||||||
}.sign(&"".sha3());
|
}.sign(&"".sha3(), None);
|
||||||
|
|
||||||
state.init_code(&0xa.into(), FromHex::from_hex("6000").unwrap());
|
state.init_code(&0xa.into(), FromHex::from_hex("6000").unwrap());
|
||||||
state.add_balance(t.sender().as_ref().unwrap(), &(100.into()));
|
state.add_balance(t.sender().as_ref().unwrap(), &(100.into()), CleanupMode::NoEmpty);
|
||||||
let result = state.apply(&info, &engine, &t, true).unwrap();
|
let result = state.apply(&info, &engine, &t, true).unwrap();
|
||||||
let expected_trace = vec![FlatTrace {
|
let expected_trace = vec![FlatTrace {
|
||||||
trace_address: Default::default(),
|
trace_address: Default::default(),
|
||||||
@ -933,9 +955,9 @@ fn should_trace_basic_call_transaction() {
|
|||||||
action: Action::Call(0xa.into()),
|
action: Action::Call(0xa.into()),
|
||||||
value: 100.into(),
|
value: 100.into(),
|
||||||
data: vec![],
|
data: vec![],
|
||||||
}.sign(&"".sha3());
|
}.sign(&"".sha3(), None);
|
||||||
|
|
||||||
state.add_balance(t.sender().as_ref().unwrap(), &(100.into()));
|
state.add_balance(t.sender().as_ref().unwrap(), &(100.into()), CleanupMode::NoEmpty);
|
||||||
let result = state.apply(&info, &engine, &t, true).unwrap();
|
let result = state.apply(&info, &engine, &t, true).unwrap();
|
||||||
let expected_trace = vec![FlatTrace {
|
let expected_trace = vec![FlatTrace {
|
||||||
trace_address: Default::default(),
|
trace_address: Default::default(),
|
||||||
@ -975,7 +997,7 @@ fn should_trace_call_transaction_to_builtin() {
|
|||||||
action: Action::Call(0x1.into()),
|
action: Action::Call(0x1.into()),
|
||||||
value: 0.into(),
|
value: 0.into(),
|
||||||
data: vec![],
|
data: vec![],
|
||||||
}.sign(&"".sha3());
|
}.sign(&"".sha3(), None);
|
||||||
|
|
||||||
let result = state.apply(&info, engine, &t, true).unwrap();
|
let result = state.apply(&info, engine, &t, true).unwrap();
|
||||||
|
|
||||||
@ -1017,7 +1039,7 @@ fn should_not_trace_subcall_transaction_to_builtin() {
|
|||||||
action: Action::Call(0xa.into()),
|
action: Action::Call(0xa.into()),
|
||||||
value: 0.into(),
|
value: 0.into(),
|
||||||
data: vec![],
|
data: vec![],
|
||||||
}.sign(&"".sha3());
|
}.sign(&"".sha3(), None);
|
||||||
|
|
||||||
state.init_code(&0xa.into(), FromHex::from_hex("600060006000600060006001610be0f1").unwrap());
|
state.init_code(&0xa.into(), FromHex::from_hex("600060006000600060006001610be0f1").unwrap());
|
||||||
let result = state.apply(&info, engine, &t, true).unwrap();
|
let result = state.apply(&info, engine, &t, true).unwrap();
|
||||||
@ -1060,7 +1082,7 @@ fn should_not_trace_callcode() {
|
|||||||
action: Action::Call(0xa.into()),
|
action: Action::Call(0xa.into()),
|
||||||
value: 0.into(),
|
value: 0.into(),
|
||||||
data: vec![],
|
data: vec![],
|
||||||
}.sign(&"".sha3());
|
}.sign(&"".sha3(), None);
|
||||||
|
|
||||||
state.init_code(&0xa.into(), FromHex::from_hex("60006000600060006000600b611000f2").unwrap());
|
state.init_code(&0xa.into(), FromHex::from_hex("60006000600060006000600b611000f2").unwrap());
|
||||||
state.init_code(&0xb.into(), FromHex::from_hex("6000").unwrap());
|
state.init_code(&0xb.into(), FromHex::from_hex("6000").unwrap());
|
||||||
@ -1122,7 +1144,7 @@ fn should_not_trace_delegatecall() {
|
|||||||
action: Action::Call(0xa.into()),
|
action: Action::Call(0xa.into()),
|
||||||
value: 0.into(),
|
value: 0.into(),
|
||||||
data: vec![],
|
data: vec![],
|
||||||
}.sign(&"".sha3());
|
}.sign(&"".sha3(), None);
|
||||||
|
|
||||||
state.init_code(&0xa.into(), FromHex::from_hex("6000600060006000600b618000f4").unwrap());
|
state.init_code(&0xa.into(), FromHex::from_hex("6000600060006000600b618000f4").unwrap());
|
||||||
state.init_code(&0xb.into(), FromHex::from_hex("6000").unwrap());
|
state.init_code(&0xb.into(), FromHex::from_hex("6000").unwrap());
|
||||||
@ -1181,10 +1203,10 @@ fn should_trace_failed_call_transaction() {
|
|||||||
action: Action::Call(0xa.into()),
|
action: Action::Call(0xa.into()),
|
||||||
value: 100.into(),
|
value: 100.into(),
|
||||||
data: vec![],
|
data: vec![],
|
||||||
}.sign(&"".sha3());
|
}.sign(&"".sha3(), None);
|
||||||
|
|
||||||
state.init_code(&0xa.into(), FromHex::from_hex("5b600056").unwrap());
|
state.init_code(&0xa.into(), FromHex::from_hex("5b600056").unwrap());
|
||||||
state.add_balance(t.sender().as_ref().unwrap(), &(100.into()));
|
state.add_balance(t.sender().as_ref().unwrap(), &(100.into()), CleanupMode::NoEmpty);
|
||||||
let result = state.apply(&info, &engine, &t, true).unwrap();
|
let result = state.apply(&info, &engine, &t, true).unwrap();
|
||||||
let expected_trace = vec![FlatTrace {
|
let expected_trace = vec![FlatTrace {
|
||||||
trace_address: Default::default(),
|
trace_address: Default::default(),
|
||||||
@ -1221,11 +1243,11 @@ fn should_trace_call_with_subcall_transaction() {
|
|||||||
action: Action::Call(0xa.into()),
|
action: Action::Call(0xa.into()),
|
||||||
value: 100.into(),
|
value: 100.into(),
|
||||||
data: vec![],
|
data: vec![],
|
||||||
}.sign(&"".sha3());
|
}.sign(&"".sha3(), None);
|
||||||
|
|
||||||
state.init_code(&0xa.into(), FromHex::from_hex("60006000600060006000600b602b5a03f1").unwrap());
|
state.init_code(&0xa.into(), FromHex::from_hex("60006000600060006000600b602b5a03f1").unwrap());
|
||||||
state.init_code(&0xb.into(), FromHex::from_hex("6000").unwrap());
|
state.init_code(&0xb.into(), FromHex::from_hex("6000").unwrap());
|
||||||
state.add_balance(t.sender().as_ref().unwrap(), &(100.into()));
|
state.add_balance(t.sender().as_ref().unwrap(), &(100.into()), CleanupMode::NoEmpty);
|
||||||
let result = state.apply(&info, &engine, &t, true).unwrap();
|
let result = state.apply(&info, &engine, &t, true).unwrap();
|
||||||
|
|
||||||
let expected_trace = vec![FlatTrace {
|
let expected_trace = vec![FlatTrace {
|
||||||
@ -1281,10 +1303,10 @@ fn should_trace_call_with_basic_subcall_transaction() {
|
|||||||
action: Action::Call(0xa.into()),
|
action: Action::Call(0xa.into()),
|
||||||
value: 100.into(),
|
value: 100.into(),
|
||||||
data: vec![],
|
data: vec![],
|
||||||
}.sign(&"".sha3());
|
}.sign(&"".sha3(), None);
|
||||||
|
|
||||||
state.init_code(&0xa.into(), FromHex::from_hex("60006000600060006045600b6000f1").unwrap());
|
state.init_code(&0xa.into(), FromHex::from_hex("60006000600060006045600b6000f1").unwrap());
|
||||||
state.add_balance(t.sender().as_ref().unwrap(), &(100.into()));
|
state.add_balance(t.sender().as_ref().unwrap(), &(100.into()), CleanupMode::NoEmpty);
|
||||||
let result = state.apply(&info, &engine, &t, true).unwrap();
|
let result = state.apply(&info, &engine, &t, true).unwrap();
|
||||||
let expected_trace = vec![FlatTrace {
|
let expected_trace = vec![FlatTrace {
|
||||||
trace_address: Default::default(),
|
trace_address: Default::default(),
|
||||||
@ -1336,10 +1358,10 @@ fn should_not_trace_call_with_invalid_basic_subcall_transaction() {
|
|||||||
action: Action::Call(0xa.into()),
|
action: Action::Call(0xa.into()),
|
||||||
value: 100.into(),
|
value: 100.into(),
|
||||||
data: vec![],
|
data: vec![],
|
||||||
}.sign(&"".sha3());
|
}.sign(&"".sha3(), None);
|
||||||
|
|
||||||
state.init_code(&0xa.into(), FromHex::from_hex("600060006000600060ff600b6000f1").unwrap()); // not enough funds.
|
state.init_code(&0xa.into(), FromHex::from_hex("600060006000600060ff600b6000f1").unwrap()); // not enough funds.
|
||||||
state.add_balance(t.sender().as_ref().unwrap(), &(100.into()));
|
state.add_balance(t.sender().as_ref().unwrap(), &(100.into()), CleanupMode::NoEmpty);
|
||||||
let result = state.apply(&info, &engine, &t, true).unwrap();
|
let result = state.apply(&info, &engine, &t, true).unwrap();
|
||||||
let expected_trace = vec![FlatTrace {
|
let expected_trace = vec![FlatTrace {
|
||||||
trace_address: Default::default(),
|
trace_address: Default::default(),
|
||||||
@ -1379,11 +1401,11 @@ fn should_trace_failed_subcall_transaction() {
|
|||||||
action: Action::Call(0xa.into()),
|
action: Action::Call(0xa.into()),
|
||||||
value: 100.into(),
|
value: 100.into(),
|
||||||
data: vec![],//600480600b6000396000f35b600056
|
data: vec![],//600480600b6000396000f35b600056
|
||||||
}.sign(&"".sha3());
|
}.sign(&"".sha3(), None);
|
||||||
|
|
||||||
state.init_code(&0xa.into(), FromHex::from_hex("60006000600060006000600b602b5a03f1").unwrap());
|
state.init_code(&0xa.into(), FromHex::from_hex("60006000600060006000600b602b5a03f1").unwrap());
|
||||||
state.init_code(&0xb.into(), FromHex::from_hex("5b600056").unwrap());
|
state.init_code(&0xb.into(), FromHex::from_hex("5b600056").unwrap());
|
||||||
state.add_balance(t.sender().as_ref().unwrap(), &(100.into()));
|
state.add_balance(t.sender().as_ref().unwrap(), &(100.into()), CleanupMode::NoEmpty);
|
||||||
let result = state.apply(&info, &engine, &t, true).unwrap();
|
let result = state.apply(&info, &engine, &t, true).unwrap();
|
||||||
let expected_trace = vec![FlatTrace {
|
let expected_trace = vec![FlatTrace {
|
||||||
trace_address: Default::default(),
|
trace_address: Default::default(),
|
||||||
@ -1435,12 +1457,12 @@ fn should_trace_call_with_subcall_with_subcall_transaction() {
|
|||||||
action: Action::Call(0xa.into()),
|
action: Action::Call(0xa.into()),
|
||||||
value: 100.into(),
|
value: 100.into(),
|
||||||
data: vec![],
|
data: vec![],
|
||||||
}.sign(&"".sha3());
|
}.sign(&"".sha3(), None);
|
||||||
|
|
||||||
state.init_code(&0xa.into(), FromHex::from_hex("60006000600060006000600b602b5a03f1").unwrap());
|
state.init_code(&0xa.into(), FromHex::from_hex("60006000600060006000600b602b5a03f1").unwrap());
|
||||||
state.init_code(&0xb.into(), FromHex::from_hex("60006000600060006000600c602b5a03f1").unwrap());
|
state.init_code(&0xb.into(), FromHex::from_hex("60006000600060006000600c602b5a03f1").unwrap());
|
||||||
state.init_code(&0xc.into(), FromHex::from_hex("6000").unwrap());
|
state.init_code(&0xc.into(), FromHex::from_hex("6000").unwrap());
|
||||||
state.add_balance(t.sender().as_ref().unwrap(), &(100.into()));
|
state.add_balance(t.sender().as_ref().unwrap(), &(100.into()), CleanupMode::NoEmpty);
|
||||||
let result = state.apply(&info, &engine, &t, true).unwrap();
|
let result = state.apply(&info, &engine, &t, true).unwrap();
|
||||||
let expected_trace = vec![FlatTrace {
|
let expected_trace = vec![FlatTrace {
|
||||||
trace_address: Default::default(),
|
trace_address: Default::default(),
|
||||||
@ -1510,12 +1532,12 @@ fn should_trace_failed_subcall_with_subcall_transaction() {
|
|||||||
action: Action::Call(0xa.into()),
|
action: Action::Call(0xa.into()),
|
||||||
value: 100.into(),
|
value: 100.into(),
|
||||||
data: vec![],//600480600b6000396000f35b600056
|
data: vec![],//600480600b6000396000f35b600056
|
||||||
}.sign(&"".sha3());
|
}.sign(&"".sha3(), None);
|
||||||
|
|
||||||
state.init_code(&0xa.into(), FromHex::from_hex("60006000600060006000600b602b5a03f1").unwrap());
|
state.init_code(&0xa.into(), FromHex::from_hex("60006000600060006000600b602b5a03f1").unwrap());
|
||||||
state.init_code(&0xb.into(), FromHex::from_hex("60006000600060006000600c602b5a03f1505b601256").unwrap());
|
state.init_code(&0xb.into(), FromHex::from_hex("60006000600060006000600c602b5a03f1505b601256").unwrap());
|
||||||
state.init_code(&0xc.into(), FromHex::from_hex("6000").unwrap());
|
state.init_code(&0xc.into(), FromHex::from_hex("6000").unwrap());
|
||||||
state.add_balance(t.sender().as_ref().unwrap(), &(100.into()));
|
state.add_balance(t.sender().as_ref().unwrap(), &(100.into()), CleanupMode::NoEmpty);
|
||||||
let result = state.apply(&info, &engine, &t, true).unwrap();
|
let result = state.apply(&info, &engine, &t, true).unwrap();
|
||||||
|
|
||||||
let expected_trace = vec![FlatTrace {
|
let expected_trace = vec![FlatTrace {
|
||||||
@ -1583,11 +1605,11 @@ fn should_trace_suicide() {
|
|||||||
action: Action::Call(0xa.into()),
|
action: Action::Call(0xa.into()),
|
||||||
value: 100.into(),
|
value: 100.into(),
|
||||||
data: vec![],
|
data: vec![],
|
||||||
}.sign(&"".sha3());
|
}.sign(&"".sha3(), None);
|
||||||
|
|
||||||
state.init_code(&0xa.into(), FromHex::from_hex("73000000000000000000000000000000000000000bff").unwrap());
|
state.init_code(&0xa.into(), FromHex::from_hex("73000000000000000000000000000000000000000bff").unwrap());
|
||||||
state.add_balance(&0xa.into(), &50.into());
|
state.add_balance(&0xa.into(), &50.into(), CleanupMode::NoEmpty);
|
||||||
state.add_balance(t.sender().as_ref().unwrap(), &100.into());
|
state.add_balance(t.sender().as_ref().unwrap(), &100.into(), CleanupMode::NoEmpty);
|
||||||
let result = state.apply(&info, &engine, &t, true).unwrap();
|
let result = state.apply(&info, &engine, &t, true).unwrap();
|
||||||
let expected_trace = vec![FlatTrace {
|
let expected_trace = vec![FlatTrace {
|
||||||
trace_address: Default::default(),
|
trace_address: Default::default(),
|
||||||
@ -1658,7 +1680,7 @@ fn get_from_database() {
|
|||||||
let (root, db) = {
|
let (root, db) = {
|
||||||
let mut state = get_temp_state_in(temp.as_path());
|
let mut state = get_temp_state_in(temp.as_path());
|
||||||
state.inc_nonce(&a);
|
state.inc_nonce(&a);
|
||||||
state.add_balance(&a, &U256::from(69u64));
|
state.add_balance(&a, &U256::from(69u64), CleanupMode::NoEmpty);
|
||||||
state.commit().unwrap();
|
state.commit().unwrap();
|
||||||
assert_eq!(state.balance(&a), U256::from(69u64));
|
assert_eq!(state.balance(&a), U256::from(69u64));
|
||||||
state.drop()
|
state.drop()
|
||||||
@ -1675,27 +1697,47 @@ fn remove() {
|
|||||||
let mut state_result = get_temp_state();
|
let mut state_result = get_temp_state();
|
||||||
let mut state = state_result.reference_mut();
|
let mut state = state_result.reference_mut();
|
||||||
assert_eq!(state.exists(&a), false);
|
assert_eq!(state.exists(&a), false);
|
||||||
|
assert_eq!(state.exists_and_not_null(&a), false);
|
||||||
state.inc_nonce(&a);
|
state.inc_nonce(&a);
|
||||||
assert_eq!(state.exists(&a), true);
|
assert_eq!(state.exists(&a), true);
|
||||||
|
assert_eq!(state.exists_and_not_null(&a), true);
|
||||||
assert_eq!(state.nonce(&a), U256::from(1u64));
|
assert_eq!(state.nonce(&a), U256::from(1u64));
|
||||||
state.kill_account(&a);
|
state.kill_account(&a);
|
||||||
assert_eq!(state.exists(&a), false);
|
assert_eq!(state.exists(&a), false);
|
||||||
|
assert_eq!(state.exists_and_not_null(&a), false);
|
||||||
assert_eq!(state.nonce(&a), U256::from(0u64));
|
assert_eq!(state.nonce(&a), U256::from(0u64));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn empty_account_exists() {
|
fn empty_account_is_not_created() {
|
||||||
let a = Address::zero();
|
let a = Address::zero();
|
||||||
let path = RandomTempPath::new();
|
let path = RandomTempPath::new();
|
||||||
let db = get_temp_state_db_in(path.as_path());
|
let db = get_temp_state_db_in(path.as_path());
|
||||||
let (root, db) = {
|
let (root, db) = {
|
||||||
let mut state = State::new(db, U256::from(0), Default::default());
|
let mut state = State::new(db, U256::from(0), Default::default());
|
||||||
state.add_balance(&a, &U256::default()); // create an empty account
|
state.add_balance(&a, &U256::default(), CleanupMode::NoEmpty); // create an empty account
|
||||||
|
state.commit().unwrap();
|
||||||
|
state.drop()
|
||||||
|
};
|
||||||
|
let state = State::from_existing(db, root, U256::from(0u8), Default::default()).unwrap();
|
||||||
|
assert!(!state.exists(&a));
|
||||||
|
assert!(!state.exists_and_not_null(&a));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn empty_account_exists_when_creation_forced() {
|
||||||
|
let a = Address::zero();
|
||||||
|
let path = RandomTempPath::new();
|
||||||
|
let db = get_temp_state_db_in(path.as_path());
|
||||||
|
let (root, db) = {
|
||||||
|
let mut state = State::new(db, U256::from(0), Default::default());
|
||||||
|
state.add_balance(&a, &U256::default(), CleanupMode::ForceCreate); // create an empty account
|
||||||
state.commit().unwrap();
|
state.commit().unwrap();
|
||||||
state.drop()
|
state.drop()
|
||||||
};
|
};
|
||||||
let state = State::from_existing(db, root, U256::from(0u8), Default::default()).unwrap();
|
let state = State::from_existing(db, root, U256::from(0u8), Default::default()).unwrap();
|
||||||
assert!(state.exists(&a));
|
assert!(state.exists(&a));
|
||||||
|
assert!(!state.exists_and_not_null(&a));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -1733,7 +1775,7 @@ fn alter_balance() {
|
|||||||
let mut state = state_result.reference_mut();
|
let mut state = state_result.reference_mut();
|
||||||
let a = Address::zero();
|
let a = Address::zero();
|
||||||
let b = 1u64.into();
|
let b = 1u64.into();
|
||||||
state.add_balance(&a, &U256::from(69u64));
|
state.add_balance(&a, &U256::from(69u64), CleanupMode::NoEmpty);
|
||||||
assert_eq!(state.balance(&a), U256::from(69u64));
|
assert_eq!(state.balance(&a), U256::from(69u64));
|
||||||
state.commit().unwrap();
|
state.commit().unwrap();
|
||||||
assert_eq!(state.balance(&a), U256::from(69u64));
|
assert_eq!(state.balance(&a), U256::from(69u64));
|
||||||
@ -1741,7 +1783,7 @@ fn alter_balance() {
|
|||||||
assert_eq!(state.balance(&a), U256::from(27u64));
|
assert_eq!(state.balance(&a), U256::from(27u64));
|
||||||
state.commit().unwrap();
|
state.commit().unwrap();
|
||||||
assert_eq!(state.balance(&a), U256::from(27u64));
|
assert_eq!(state.balance(&a), U256::from(27u64));
|
||||||
state.transfer_balance(&a, &b, &U256::from(18u64));
|
state.transfer_balance(&a, &b, &U256::from(18u64), CleanupMode::NoEmpty);
|
||||||
assert_eq!(state.balance(&a), U256::from(9u64));
|
assert_eq!(state.balance(&a), U256::from(9u64));
|
||||||
assert_eq!(state.balance(&b), U256::from(18u64));
|
assert_eq!(state.balance(&b), U256::from(18u64));
|
||||||
state.commit().unwrap();
|
state.commit().unwrap();
|
||||||
@ -1794,12 +1836,12 @@ fn checkpoint_basic() {
|
|||||||
let mut state = state_result.reference_mut();
|
let mut state = state_result.reference_mut();
|
||||||
let a = Address::zero();
|
let a = Address::zero();
|
||||||
state.checkpoint();
|
state.checkpoint();
|
||||||
state.add_balance(&a, &U256::from(69u64));
|
state.add_balance(&a, &U256::from(69u64), CleanupMode::NoEmpty);
|
||||||
assert_eq!(state.balance(&a), U256::from(69u64));
|
assert_eq!(state.balance(&a), U256::from(69u64));
|
||||||
state.discard_checkpoint();
|
state.discard_checkpoint();
|
||||||
assert_eq!(state.balance(&a), U256::from(69u64));
|
assert_eq!(state.balance(&a), U256::from(69u64));
|
||||||
state.checkpoint();
|
state.checkpoint();
|
||||||
state.add_balance(&a, &U256::from(1u64));
|
state.add_balance(&a, &U256::from(1u64), CleanupMode::NoEmpty);
|
||||||
assert_eq!(state.balance(&a), U256::from(70u64));
|
assert_eq!(state.balance(&a), U256::from(70u64));
|
||||||
state.revert_to_checkpoint();
|
state.revert_to_checkpoint();
|
||||||
assert_eq!(state.balance(&a), U256::from(69u64));
|
assert_eq!(state.balance(&a), U256::from(69u64));
|
||||||
@ -1812,7 +1854,7 @@ fn checkpoint_nested() {
|
|||||||
let a = Address::zero();
|
let a = Address::zero();
|
||||||
state.checkpoint();
|
state.checkpoint();
|
||||||
state.checkpoint();
|
state.checkpoint();
|
||||||
state.add_balance(&a, &U256::from(69u64));
|
state.add_balance(&a, &U256::from(69u64), CleanupMode::NoEmpty);
|
||||||
assert_eq!(state.balance(&a), U256::from(69u64));
|
assert_eq!(state.balance(&a), U256::from(69u64));
|
||||||
state.discard_checkpoint();
|
state.discard_checkpoint();
|
||||||
assert_eq!(state.balance(&a), U256::from(69u64));
|
assert_eq!(state.balance(&a), U256::from(69u64));
|
||||||
@ -1835,7 +1877,7 @@ fn should_not_panic_on_state_diff_with_storage() {
|
|||||||
|
|
||||||
let a: Address = 0xa.into();
|
let a: Address = 0xa.into();
|
||||||
state.init_code(&a, b"abcdefg".to_vec());
|
state.init_code(&a, b"abcdefg".to_vec());
|
||||||
state.add_balance(&a, &256.into());
|
state.add_balance(&a, &256.into(), CleanupMode::NoEmpty);
|
||||||
state.set_storage(&a, 0xb.into(), 0xc.into());
|
state.set_storage(&a, 0xb.into(), 0xc.into());
|
||||||
|
|
||||||
let mut new_state = state.clone();
|
let mut new_state = state.clone();
|
||||||
|
@ -18,6 +18,8 @@
|
|||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use util::{Address, U256};
|
use util::{Address, U256};
|
||||||
use log_entry::LogEntry;
|
use log_entry::LogEntry;
|
||||||
|
use evm::Schedule;
|
||||||
|
use super::CleanupMode;
|
||||||
|
|
||||||
/// State changes which should be applied in finalize,
|
/// State changes which should be applied in finalize,
|
||||||
/// after transaction is fully executed.
|
/// after transaction is fully executed.
|
||||||
@ -26,6 +28,9 @@ pub struct Substate {
|
|||||||
/// Any accounts that have suicided.
|
/// Any accounts that have suicided.
|
||||||
pub suicides: HashSet<Address>,
|
pub suicides: HashSet<Address>,
|
||||||
|
|
||||||
|
/// Any accounts that are tagged for garbage collection.
|
||||||
|
pub garbage: HashSet<Address>,
|
||||||
|
|
||||||
/// Any logs.
|
/// Any logs.
|
||||||
pub logs: Vec<LogEntry>,
|
pub logs: Vec<LogEntry>,
|
||||||
|
|
||||||
@ -45,10 +50,20 @@ impl Substate {
|
|||||||
/// Merge secondary substate `s` into self, accruing each element correspondingly.
|
/// Merge secondary substate `s` into self, accruing each element correspondingly.
|
||||||
pub fn accrue(&mut self, s: Substate) {
|
pub fn accrue(&mut self, s: Substate) {
|
||||||
self.suicides.extend(s.suicides.into_iter());
|
self.suicides.extend(s.suicides.into_iter());
|
||||||
|
self.garbage.extend(s.garbage.into_iter());
|
||||||
self.logs.extend(s.logs.into_iter());
|
self.logs.extend(s.logs.into_iter());
|
||||||
self.sstore_clears_count = self.sstore_clears_count + s.sstore_clears_count;
|
self.sstore_clears_count = self.sstore_clears_count + s.sstore_clears_count;
|
||||||
self.contracts_created.extend(s.contracts_created.into_iter());
|
self.contracts_created.extend(s.contracts_created.into_iter());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the cleanup mode object from this.
|
||||||
|
pub fn to_cleanup_mode(&mut self, schedule: &Schedule) -> CleanupMode {
|
||||||
|
match (schedule.no_empty, schedule.kill_empty) {
|
||||||
|
(false, _) => CleanupMode::ForceCreate,
|
||||||
|
(true, false) => CleanupMode::NoEmpty,
|
||||||
|
(true, true) => CleanupMode::KillEmpty(&mut self.garbage),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -165,13 +165,13 @@ impl StateDB {
|
|||||||
bloom
|
bloom
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_account_bloom(&self, address: &Address) -> bool {
|
pub fn check_non_null_bloom(&self, address: &Address) -> bool {
|
||||||
trace!(target: "account_bloom", "Check account bloom: {:?}", address);
|
trace!(target: "account_bloom", "Check account bloom: {:?}", address);
|
||||||
let bloom = self.account_bloom.lock();
|
let bloom = self.account_bloom.lock();
|
||||||
bloom.check(&*address.sha3())
|
bloom.check(&*address.sha3())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn note_account_bloom(&self, address: &Address) {
|
pub fn note_non_null_account(&self, address: &Address) {
|
||||||
trace!(target: "account_bloom", "Note account bloom: {:?}", address);
|
trace!(target: "account_bloom", "Note account bloom: {:?}", address);
|
||||||
let mut bloom = self.account_bloom.lock();
|
let mut bloom = self.account_bloom.lock();
|
||||||
bloom.set(&*address.sha3());
|
bloom.set(&*address.sha3());
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
use io::IoChannel;
|
use io::IoChannel;
|
||||||
use client::{BlockChainClient, MiningBlockChainClient, Client, ClientConfig, BlockID};
|
use client::{BlockChainClient, MiningBlockChainClient, Client, ClientConfig, BlockID};
|
||||||
|
use state::CleanupMode;
|
||||||
use ethereum;
|
use ethereum;
|
||||||
use block::IsBlock;
|
use block::IsBlock;
|
||||||
use tests::helpers::*;
|
use tests::helpers::*;
|
||||||
@ -217,7 +218,7 @@ fn can_generate_gas_price_histogram() {
|
|||||||
let client = client_result.reference();
|
let client = client_result.reference();
|
||||||
|
|
||||||
let hist = client.gas_price_histogram(20, 5).unwrap();
|
let hist = client.gas_price_histogram(20, 5).unwrap();
|
||||||
let correct_hist = Histogram { bucket_bounds: vec_into![643,2293,3943,5593,7243,8893], counts: vec![4,2,4,6,3] };
|
let correct_hist = Histogram { bucket_bounds: vec_into![643, 2294, 3945, 5596, 7247, 8898], counts: vec![4,2,4,6,4] };
|
||||||
assert_eq!(hist, correct_hist);
|
assert_eq!(hist, correct_hist);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -272,7 +273,7 @@ fn change_history_size() {
|
|||||||
let client = Client::new(ClientConfig::default(), &test_spec, dir.as_path(), Arc::new(Miner::with_spec(&test_spec)), IoChannel::disconnected(), &db_config).unwrap();
|
let client = Client::new(ClientConfig::default(), &test_spec, dir.as_path(), Arc::new(Miner::with_spec(&test_spec)), IoChannel::disconnected(), &db_config).unwrap();
|
||||||
for _ in 0..20 {
|
for _ in 0..20 {
|
||||||
let mut b = client.prepare_open_block(Address::default(), (3141562.into(), 31415620.into()), vec![]);
|
let mut b = client.prepare_open_block(Address::default(), (3141562.into(), 31415620.into()), vec![]);
|
||||||
b.block_mut().fields_mut().state.add_balance(&address, &5.into());
|
b.block_mut().fields_mut().state.add_balance(&address, &5.into(), CleanupMode::NoEmpty);
|
||||||
b.block_mut().fields_mut().state.commit().unwrap();
|
b.block_mut().fields_mut().state.commit().unwrap();
|
||||||
let b = b.close_and_lock().seal(&*test_spec.engine, vec![]).unwrap();
|
let b = b.close_and_lock().seal(&*test_spec.engine, vec![]).unwrap();
|
||||||
client.import_sealed_block(b).unwrap(); // account change is in the journal overlay
|
client.import_sealed_block(b).unwrap(); // account change is in the journal overlay
|
||||||
|
@ -39,6 +39,7 @@ pub enum ChainEra {
|
|||||||
Frontier,
|
Frontier,
|
||||||
Homestead,
|
Homestead,
|
||||||
Eip150,
|
Eip150,
|
||||||
|
Eip161,
|
||||||
TransitionTest,
|
TransitionTest,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -193,7 +194,7 @@ pub fn generate_dummy_client_with_spec_and_data<F>(get_test_spec: F, block_numbe
|
|||||||
action: Action::Create,
|
action: Action::Create,
|
||||||
data: vec![],
|
data: vec![],
|
||||||
value: U256::zero(),
|
value: U256::zero(),
|
||||||
}.sign(kp.secret()), None).unwrap();
|
}.sign(kp.secret(), None), None).unwrap();
|
||||||
n += 1;
|
n += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,6 +93,10 @@ pub struct RichReceipt {
|
|||||||
pub contract_address: Option<Address>,
|
pub contract_address: Option<Address>,
|
||||||
/// Logs
|
/// Logs
|
||||||
pub logs: Vec<LogEntry>,
|
pub logs: Vec<LogEntry>,
|
||||||
|
/// Logs bloom
|
||||||
|
pub log_bloom: LogBloom,
|
||||||
|
/// State root
|
||||||
|
pub state_root: H256,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Receipt with additional info.
|
/// Receipt with additional info.
|
||||||
@ -114,6 +118,10 @@ pub struct LocalizedReceipt {
|
|||||||
pub contract_address: Option<Address>,
|
pub contract_address: Option<Address>,
|
||||||
/// Logs
|
/// Logs
|
||||||
pub logs: Vec<LocalizedLogEntry>,
|
pub logs: Vec<LocalizedLogEntry>,
|
||||||
|
/// Logs bloom
|
||||||
|
pub log_bloom: LogBloom,
|
||||||
|
/// State root
|
||||||
|
pub state_root: H256,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -72,8 +72,8 @@ pub struct Transaction {
|
|||||||
|
|
||||||
impl Transaction {
|
impl Transaction {
|
||||||
/// Append object with a without signature into RLP stream
|
/// Append object with a without signature into RLP stream
|
||||||
pub fn rlp_append_unsigned_transaction(&self, s: &mut RlpStream) {
|
pub fn rlp_append_unsigned_transaction(&self, s: &mut RlpStream, network_id: Option<u8>) {
|
||||||
s.begin_list(6);
|
s.begin_list(if let None = network_id { 6 } else { 9 });
|
||||||
s.append(&self.nonce);
|
s.append(&self.nonce);
|
||||||
s.append(&self.gas_price);
|
s.append(&self.gas_price);
|
||||||
s.append(&self.gas);
|
s.append(&self.gas);
|
||||||
@ -83,6 +83,11 @@ impl Transaction {
|
|||||||
};
|
};
|
||||||
s.append(&self.value);
|
s.append(&self.value);
|
||||||
s.append(&self.data);
|
s.append(&self.data);
|
||||||
|
if let Some(n) = network_id {
|
||||||
|
s.append(&n);
|
||||||
|
s.append(&0u8);
|
||||||
|
s.append(&0u8);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,7 +110,7 @@ impl From<ethjson::state::Transaction> for SignedTransaction {
|
|||||||
},
|
},
|
||||||
value: t.value.into(),
|
value: t.value.into(),
|
||||||
data: t.data.into(),
|
data: t.data.into(),
|
||||||
}.sign(&t.secret.into())
|
}.sign(&t.secret.into(), None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,26 +140,26 @@ impl From<ethjson::transaction::Transaction> for SignedTransaction {
|
|||||||
|
|
||||||
impl Transaction {
|
impl Transaction {
|
||||||
/// The message hash of the transaction.
|
/// The message hash of the transaction.
|
||||||
pub fn hash(&self) -> H256 {
|
pub fn hash(&self, network_id: Option<u8>) -> H256 {
|
||||||
let mut stream = RlpStream::new();
|
let mut stream = RlpStream::new();
|
||||||
self.rlp_append_unsigned_transaction(&mut stream);
|
self.rlp_append_unsigned_transaction(&mut stream, network_id);
|
||||||
stream.out().sha3()
|
stream.out().sha3()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Signs the transaction as coming from `sender`.
|
/// Signs the transaction as coming from `sender`.
|
||||||
pub fn sign(self, secret: &Secret) -> SignedTransaction {
|
pub fn sign(self, secret: &Secret, network_id: Option<u8>) -> SignedTransaction {
|
||||||
let sig = ::ethkey::sign(secret, &self.hash())
|
let sig = ::ethkey::sign(secret, &self.hash(network_id))
|
||||||
.expect("data is valid and context has signing capabilities; qed");
|
.expect("data is valid and context has signing capabilities; qed");
|
||||||
self.with_signature(sig)
|
self.with_signature(sig, network_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Signs the transaction with signature.
|
/// Signs the transaction with signature.
|
||||||
pub fn with_signature(self, sig: Signature) -> SignedTransaction {
|
pub fn with_signature(self, sig: Signature, network_id: Option<u8>) -> SignedTransaction {
|
||||||
SignedTransaction {
|
SignedTransaction {
|
||||||
unsigned: self,
|
unsigned: self,
|
||||||
r: sig.r().into(),
|
r: sig.r().into(),
|
||||||
s: sig.s().into(),
|
s: sig.s().into(),
|
||||||
v: sig.v() + 27,
|
v: sig.v() + if let Some(n) = network_id { 1 + n * 2 } else { 27 },
|
||||||
hash: Cell::new(None),
|
hash: Cell::new(None),
|
||||||
sender: Cell::new(None),
|
sender: Cell::new(None),
|
||||||
}
|
}
|
||||||
@ -204,7 +209,8 @@ impl Transaction {
|
|||||||
pub struct SignedTransaction {
|
pub struct SignedTransaction {
|
||||||
/// Plain Transaction.
|
/// Plain Transaction.
|
||||||
unsigned: Transaction,
|
unsigned: Transaction,
|
||||||
/// The V field of the signature, either 27 or 28; helps describe the point on the curve.
|
/// The V field of the signature; the LS bit described which half of the curve our point falls
|
||||||
|
/// in. The MS bits describe which network this transaction is for. If 27/28, its for all networks.
|
||||||
v: u8,
|
v: u8,
|
||||||
/// The R field of the signature; helps describe the point on the curve.
|
/// The R field of the signature; helps describe the point on the curve.
|
||||||
r: U256,
|
r: U256,
|
||||||
@ -266,7 +272,7 @@ impl HeapSizeOf for SignedTransaction {
|
|||||||
|
|
||||||
impl SignedTransaction {
|
impl SignedTransaction {
|
||||||
/// Append object with a signature into RLP stream
|
/// Append object with a signature into RLP stream
|
||||||
pub fn rlp_append_sealed_transaction(&self, s: &mut RlpStream) {
|
fn rlp_append_sealed_transaction(&self, s: &mut RlpStream) {
|
||||||
s.begin_list(9);
|
s.begin_list(9);
|
||||||
s.append(&self.nonce);
|
s.append(&self.nonce);
|
||||||
s.append(&self.gas_price);
|
s.append(&self.gas_price);
|
||||||
@ -295,8 +301,16 @@ impl SignedTransaction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 0 is `v` is 27, 1 if 28, and 4 otherwise.
|
/// 0 if `v` would have been 27 under "Electrum" notation, 1 if 28 or 4 if invalid.
|
||||||
pub fn standard_v(&self) -> u8 { match self.v { 27 => 0, 28 => 1, _ => 4 } }
|
pub fn standard_v(&self) -> u8 { match self.v { 0 => 4, v => (v - 1) & 1, } }
|
||||||
|
|
||||||
|
/// The network ID, or `None` if this is a global transaction.
|
||||||
|
pub fn network_id(&self) -> Option<u8> {
|
||||||
|
match self.v {
|
||||||
|
0 | 27 | 28 => None,
|
||||||
|
v => Some((v - 1) / 2),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Construct a signature object from the sig.
|
/// Construct a signature object from the sig.
|
||||||
pub fn signature(&self) -> Signature {
|
pub fn signature(&self) -> Signature {
|
||||||
@ -327,20 +341,25 @@ impl SignedTransaction {
|
|||||||
|
|
||||||
/// Returns the public key of the sender.
|
/// Returns the public key of the sender.
|
||||||
pub fn public_key(&self) -> Result<Public, Error> {
|
pub fn public_key(&self) -> Result<Public, Error> {
|
||||||
Ok(try!(recover(&self.signature(), &self.unsigned.hash())))
|
Ok(try!(recover(&self.signature(), &self.unsigned.hash(self.network_id()))))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Do basic validation, checking for valid signature and minimum gas,
|
/// Do basic validation, checking for valid signature and minimum gas,
|
||||||
// TODO: consider use in block validation.
|
// TODO: consider use in block validation.
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[cfg(feature = "json-tests")]
|
#[cfg(feature = "json-tests")]
|
||||||
pub fn validate(self, schedule: &Schedule, require_low: bool) -> Result<SignedTransaction, Error> {
|
pub fn validate(self, schedule: &Schedule, require_low: bool, allow_network_id_of_one: bool) -> Result<SignedTransaction, Error> {
|
||||||
if require_low && !self.signature().is_low_s() {
|
if require_low && !self.signature().is_low_s() {
|
||||||
return Err(EthkeyError::InvalidSignature.into())
|
return Err(EthkeyError::InvalidSignature.into())
|
||||||
}
|
}
|
||||||
|
match self.network_id() {
|
||||||
|
None => {},
|
||||||
|
Some(1) if allow_network_id_of_one => {},
|
||||||
|
_ => return Err(TransactionError::InvalidNetworkId.into()),
|
||||||
|
}
|
||||||
try!(self.sender());
|
try!(self.sender());
|
||||||
if self.gas < U256::from(self.gas_required(&schedule)) {
|
if self.gas < U256::from(self.gas_required(&schedule)) {
|
||||||
Err(From::from(TransactionError::InvalidGasLimit(::util::OutOfBounds{min: Some(U256::from(self.gas_required(&schedule))), max: None, found: self.gas})))
|
Err(TransactionError::InvalidGasLimit(::util::OutOfBounds{min: Some(U256::from(self.gas_required(&schedule))), max: None, found: self.gas}).into())
|
||||||
} else {
|
} else {
|
||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
@ -380,6 +399,7 @@ fn sender_test() {
|
|||||||
} else { panic!(); }
|
} else { panic!(); }
|
||||||
assert_eq!(t.value, U256::from(0x0au64));
|
assert_eq!(t.value, U256::from(0x0au64));
|
||||||
assert_eq!(t.sender().unwrap(), "0f65fe9276bc9a24ae7083ae28e2660ef72df99e".into());
|
assert_eq!(t.sender().unwrap(), "0f65fe9276bc9a24ae7083ae28e2660ef72df99e".into());
|
||||||
|
assert_eq!(t.network_id(), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -394,8 +414,9 @@ fn signing() {
|
|||||||
gas: U256::from(50_000),
|
gas: U256::from(50_000),
|
||||||
value: U256::from(1),
|
value: U256::from(1),
|
||||||
data: b"Hello!".to_vec()
|
data: b"Hello!".to_vec()
|
||||||
}.sign(&key.secret());
|
}.sign(&key.secret(), None);
|
||||||
assert_eq!(Address::from(key.public().sha3()), t.sender().unwrap());
|
assert_eq!(Address::from(key.public().sha3()), t.sender().unwrap());
|
||||||
|
assert_eq!(t.network_id(), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -409,7 +430,47 @@ fn fake_signing() {
|
|||||||
data: b"Hello!".to_vec()
|
data: b"Hello!".to_vec()
|
||||||
}.fake_sign(Address::from(0x69));
|
}.fake_sign(Address::from(0x69));
|
||||||
assert_eq!(Address::from(0x69), t.sender().unwrap());
|
assert_eq!(Address::from(0x69), t.sender().unwrap());
|
||||||
|
assert_eq!(t.network_id(), None);
|
||||||
|
|
||||||
let t = t.clone();
|
let t = t.clone();
|
||||||
assert_eq!(Address::from(0x69), t.sender().unwrap());
|
assert_eq!(Address::from(0x69), t.sender().unwrap());
|
||||||
|
assert_eq!(t.network_id(), None);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn should_recover_from_network_specific_signing() {
|
||||||
|
use ethkey::{Random, Generator};
|
||||||
|
let key = Random.generate().unwrap();
|
||||||
|
let t = Transaction {
|
||||||
|
action: Action::Create,
|
||||||
|
nonce: U256::from(42),
|
||||||
|
gas_price: U256::from(3000),
|
||||||
|
gas: U256::from(50_000),
|
||||||
|
value: U256::from(1),
|
||||||
|
data: b"Hello!".to_vec()
|
||||||
|
}.sign(&key.secret(), Some(69));
|
||||||
|
assert_eq!(Address::from(key.public().sha3()), t.sender().unwrap());
|
||||||
|
assert_eq!(t.network_id(), Some(69));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn should_agree_with_vitalik() {
|
||||||
|
use rustc_serialize::hex::FromHex;
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
let test_vector = |tx_data: &str, address: &'static str| {
|
||||||
|
let signed: SignedTransaction = decode(&FromHex::from_hex(tx_data).unwrap());
|
||||||
|
assert_eq!(signed.sender().unwrap(), address.into());
|
||||||
|
};
|
||||||
|
|
||||||
|
test_vector("f864808504a817c800825208943535353535353535353535353535353535353535808025a0044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116da0044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116d", "0xda39a520355857fdb37ecb527fe814230fa9962c");
|
||||||
|
test_vector("f864018504a817c80182a410943535353535353535353535353535353535353535018025a0c89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc8a0c89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6", "0xd240215f30eafee2aaa5184d8f051ebb41c90b19");
|
||||||
|
test_vector("f864028504a817c80282f618943535353535353535353535353535353535353535088025a0ad7c5bef027816a800da1736444fb58a807ef4c9603b7848673f7e3a68eb14a8a0ad7c5bef027816a800da1736444fb58a807ef4c9603b7848673f7e3a68eb14a5", "0x2f2822c55d894df1ba32961c43325dcb3d614ee8");
|
||||||
|
test_vector("f865038504a817c803830148209435353535353535353535353535353535353535351b8025a02a80e1ef1d7842f27f2e6be0972bb708b9a135c38860dbe73c27c3486c34f4e0a02a80e1ef1d7842f27f2e6be0972bb708b9a135c38860dbe73c27c3486c34f4de", "0xc21df0434ceab6e18a1300d18206e54e807b4456");
|
||||||
|
test_vector("f865048504a817c80483019a28943535353535353535353535353535353535353535408025a013600b294191fc92924bb3ce4b969c1e7e2bab8f4c93c3fc6d0a51733df3c063a013600b294191fc92924bb3ce4b969c1e7e2bab8f4c93c3fc6d0a51733df3c060", "0xf975cee81edae2ab5883f4e2fb2a7f2fd56f4131");
|
||||||
|
test_vector("f865058504a817c8058301ec309435353535353535353535353535353535353535357d8025a0ceebf77a833b30520287ddd9478ff51abbdffa30aa90a8d655dba0e8a79ce0c1a0ceebf77a833b30520287ddd9478ff51abbdffa30aa90a8d655dba0e8a79ce0c1", "0xd477474c9f48dcbfde5d97f30646242ab7a17e06");
|
||||||
|
test_vector("f866068504a817c80683023e3894353535353535353535353535353535353535353581d88025a0e455bf8ea6e7463a1046a0b52804526e119b4bf5136279614e0b1e8e296a4e2da0e455bf8ea6e7463a1046a0b52804526e119b4bf5136279614e0b1e8e296a4e2d", "0xb49948deb719ca21e38d29e3360f534b39db0e76");
|
||||||
|
test_vector("f867078504a817c807830290409435353535353535353535353535353535353535358201578025a052f1a9b320cab38e5da8a8f97989383aab0a49165fc91c737310e4f7e9821021a052f1a9b320cab38e5da8a8f97989383aab0a49165fc91c737310e4f7e9821021", "0xbddfc81a8ce87b2360837049a6eda68ab2f58999");
|
||||||
|
test_vector("f867088504a817c8088302e2489435353535353535353535353535353535353535358202008025a0e4b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c11a0e4b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10", "0x8f2edcf67f329a146dd4cb1e6b3a072daff85b38");
|
||||||
|
test_vector("f867098504a817c809830334509435353535353535353535353535353535353535358202d98025a0d2f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afba0d2f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afb", "0x4ec38d4782fd4a6ff85c1cde77ccf1ae3c54472c");
|
||||||
}
|
}
|
@ -395,7 +395,7 @@ mod tests {
|
|||||||
gas: U256::from(30_000),
|
gas: U256::from(30_000),
|
||||||
gas_price: U256::from(40_000),
|
gas_price: U256::from(40_000),
|
||||||
nonce: U256::one()
|
nonce: U256::one()
|
||||||
}.sign(keypair.secret());
|
}.sign(keypair.secret(), None);
|
||||||
|
|
||||||
let tr2 = Transaction {
|
let tr2 = Transaction {
|
||||||
action: Action::Create,
|
action: Action::Create,
|
||||||
@ -404,7 +404,7 @@ mod tests {
|
|||||||
gas: U256::from(30_000),
|
gas: U256::from(30_000),
|
||||||
gas_price: U256::from(40_000),
|
gas_price: U256::from(40_000),
|
||||||
nonce: U256::from(2)
|
nonce: U256::from(2)
|
||||||
}.sign(keypair.secret());
|
}.sign(keypair.secret(), None);
|
||||||
|
|
||||||
let good_transactions = [ tr1.clone(), tr2.clone() ];
|
let good_transactions = [ tr1.clone(), tr2.clone() ];
|
||||||
|
|
||||||
|
@ -51,6 +51,14 @@ impl Ext for FakeExt {
|
|||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn exists_and_not_null(&self, address: &Address) -> bool {
|
||||||
|
unimplemented!();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn origin_balance(&self) -> U256 {
|
||||||
|
unimplemented!();
|
||||||
|
}
|
||||||
|
|
||||||
fn balance(&self, _address: &Address) -> U256 {
|
fn balance(&self, _address: &Address) -> U256 {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
// test only
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Run `PARITY_URL="127.0.0.1:8180" NODE_ENV="production" npm run build`
|
* Run `PARITY_URL="127.0.0.1:8180" NODE_ENV="production" npm run build`
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "parity.js",
|
"name": "parity.js",
|
||||||
"version": "0.1.47",
|
"version": "0.1.61",
|
||||||
"main": "release/index.js",
|
"main": "release/index.js",
|
||||||
"jsnext:main": "src/index.js",
|
"jsnext:main": "src/index.js",
|
||||||
"author": "Parity Team <admin@parity.io>",
|
"author": "Parity Team <admin@parity.io>",
|
||||||
|
@ -50,20 +50,11 @@ setup_git_user
|
|||||||
git remote set-url origin $GIT_PARITY
|
git remote set-url origin $GIT_PARITY
|
||||||
git reset --hard origin/$BRANCH 2>$GITLOG
|
git reset --hard origin/$BRANCH 2>$GITLOG
|
||||||
|
|
||||||
echo "*** Bumping package.json patch version"
|
if [ "$BRANCH" == "master" ]; then
|
||||||
cd js
|
cd js
|
||||||
|
echo "*** Bumping package.json patch version"
|
||||||
npm --no-git-tag-version version
|
npm --no-git-tag-version version
|
||||||
npm version patch
|
npm version patch
|
||||||
cd ..
|
|
||||||
|
|
||||||
echo "*** Updating cargo parity-ui-precompiled#$PRECOMPILED_HASH"
|
|
||||||
cargo update -p parity-ui-precompiled
|
|
||||||
# --precise "$PRECOMPILED_HASH"
|
|
||||||
|
|
||||||
echo "*** Committing updated files"
|
|
||||||
git add Cargo.lock js/package.json
|
|
||||||
git commit -m "[ci skip] js-precompiled $UTCDATE"
|
|
||||||
git push origin HEAD:refs/heads/$BRANCH 2>$GITLOG
|
|
||||||
|
|
||||||
echo "*** Building packages for npmjs"
|
echo "*** Building packages for npmjs"
|
||||||
cd js
|
cd js
|
||||||
@ -75,6 +66,16 @@ echo "*** Publishing $PACKAGE to npmjs"
|
|||||||
cd .npmjs
|
cd .npmjs
|
||||||
npm publish --access public
|
npm publish --access public
|
||||||
cd ..
|
cd ..
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "*** Updating cargo parity-ui-precompiled#$PRECOMPILED_HASH"
|
||||||
|
cargo update -p parity-ui-precompiled
|
||||||
|
# --precise "$PRECOMPILED_HASH"
|
||||||
|
|
||||||
|
echo "*** Committing updated files"
|
||||||
|
git add .
|
||||||
|
git commit -m "[ci skip] js-precompiled $UTCDATE"
|
||||||
|
git push origin HEAD:refs/heads/$BRANCH 2>$GITLOG
|
||||||
|
|
||||||
# back to root
|
# back to root
|
||||||
echo "*** Release completed"
|
echo "*** Release completed"
|
||||||
|
@ -87,7 +87,8 @@ export default class Status {
|
|||||||
setTimeout(this._pollStatus, timeout);
|
setTimeout(this._pollStatus, timeout);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (isConnected !== this._store.getState().nodeStatus.isConnected) {
|
const wasConnected = this._store.getState().nodeStatus.isConnected;
|
||||||
|
if (isConnected !== wasConnected) {
|
||||||
this._fetchEnode();
|
this._fetchEnode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
75
js/src/ui/CopyToClipboard/copyToClipboard.js
Normal file
75
js/src/ui/CopyToClipboard/copyToClipboard.js
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
// Copyright 2015, 2016 Ethcore (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/>.
|
||||||
|
|
||||||
|
import React, { Component, PropTypes } from 'react';
|
||||||
|
import { IconButton } from 'material-ui';
|
||||||
|
import Clipboard from 'react-copy-to-clipboard';
|
||||||
|
import CopyIcon from 'material-ui/svg-icons/content/content-copy';
|
||||||
|
import Theme from '../Theme';
|
||||||
|
const { textColor, disabledTextColor } = Theme.flatButton;
|
||||||
|
|
||||||
|
export default class CopyToClipboard extends Component {
|
||||||
|
static propTypes = {
|
||||||
|
data: PropTypes.string.isRequired,
|
||||||
|
label: PropTypes.string,
|
||||||
|
onCopy: PropTypes.func,
|
||||||
|
size: PropTypes.number, // in px
|
||||||
|
cooldown: PropTypes.number // in ms
|
||||||
|
};
|
||||||
|
|
||||||
|
static defaultProps = {
|
||||||
|
className: '',
|
||||||
|
label: 'copy to clipboard',
|
||||||
|
onCopy: () => {},
|
||||||
|
size: 16,
|
||||||
|
cooldown: 1000
|
||||||
|
};
|
||||||
|
|
||||||
|
state = {
|
||||||
|
copied: false
|
||||||
|
};
|
||||||
|
|
||||||
|
render () {
|
||||||
|
const { data, label, size } = this.props;
|
||||||
|
const { copied } = this.state;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Clipboard onCopy={ this.onCopy } text={ data }>
|
||||||
|
<IconButton
|
||||||
|
tooltip={ copied ? 'done!' : label }
|
||||||
|
disableTouchRipple
|
||||||
|
tooltipPosition={ 'top-right' }
|
||||||
|
tooltipStyles={ { marginTop: `-${size / 4}px` } }
|
||||||
|
style={ { width: size, height: size, padding: '0' } }
|
||||||
|
iconStyle={ { width: size, height: size } }
|
||||||
|
>
|
||||||
|
<CopyIcon color={ copied ? disabledTextColor : textColor } />
|
||||||
|
</IconButton>
|
||||||
|
</Clipboard>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
onCopy = () => {
|
||||||
|
const { cooldown, onCopy } = this.props;
|
||||||
|
|
||||||
|
this.setState({ copied: true });
|
||||||
|
setTimeout(() => {
|
||||||
|
this.setState({ copied: false });
|
||||||
|
}, cooldown);
|
||||||
|
|
||||||
|
onCopy();
|
||||||
|
}
|
||||||
|
}
|
17
js/src/ui/CopyToClipboard/index.js
Normal file
17
js/src/ui/CopyToClipboard/index.js
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// Copyright 2015, 2016 Ethcore (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/>.
|
||||||
|
|
||||||
|
export default from './copyToClipboard';
|
@ -19,12 +19,11 @@ import React, { Component, PropTypes } from 'react';
|
|||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { bindActionCreators } from 'redux';
|
import { bindActionCreators } from 'redux';
|
||||||
|
|
||||||
|
import Contracts from '../../contracts';
|
||||||
import IdentityIcon from '../IdentityIcon';
|
import IdentityIcon from '../IdentityIcon';
|
||||||
import IdentityName from '../IdentityName';
|
import IdentityName from '../IdentityName';
|
||||||
import { Input, InputAddress } from '../Form';
|
import { Input, InputAddress } from '../Form';
|
||||||
|
|
||||||
import { fetchBytecode, fetchMethod } from '../../redux/providers/blockchainActions';
|
|
||||||
|
|
||||||
import styles from './methodDecoding.css';
|
import styles from './methodDecoding.css';
|
||||||
|
|
||||||
const CONTRACT_CREATE = '0x60606040';
|
const CONTRACT_CREATE = '0x60606040';
|
||||||
@ -41,12 +40,7 @@ class MethodDecoding extends Component {
|
|||||||
address: PropTypes.string.isRequired,
|
address: PropTypes.string.isRequired,
|
||||||
tokens: PropTypes.object,
|
tokens: PropTypes.object,
|
||||||
transaction: PropTypes.object,
|
transaction: PropTypes.object,
|
||||||
historic: PropTypes.bool,
|
historic: PropTypes.bool
|
||||||
|
|
||||||
fetchBytecode: PropTypes.func,
|
|
||||||
fetchMethod: PropTypes.func,
|
|
||||||
bytecodes: PropTypes.object,
|
|
||||||
methods: PropTypes.object
|
|
||||||
}
|
}
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
@ -63,58 +57,7 @@ class MethodDecoding extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentWillMount () {
|
componentWillMount () {
|
||||||
const { transaction } = this.props;
|
this.lookup();
|
||||||
this.lookup(transaction);
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount () {
|
|
||||||
this.setMethod(this.props);
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillReceiveProps (newProps) {
|
|
||||||
const { transaction } = this.props;
|
|
||||||
this.setMethod(newProps);
|
|
||||||
|
|
||||||
if (newProps.transaction.hash !== transaction.hash) {
|
|
||||||
this.lookup(transaction);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setMethod (props) {
|
|
||||||
const { bytecodes, methods } = props;
|
|
||||||
const { contractAddress, methodSignature, methodParams } = this.state;
|
|
||||||
|
|
||||||
if (contractAddress && bytecodes[contractAddress]) {
|
|
||||||
const bytecode = bytecodes[contractAddress];
|
|
||||||
|
|
||||||
if (bytecode && bytecode !== '0x') {
|
|
||||||
this.setState({ isContract: true });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (methodSignature && methods[methodSignature]) {
|
|
||||||
const method = methods[methodSignature];
|
|
||||||
const { api } = this.context;
|
|
||||||
|
|
||||||
let methodInputs = null;
|
|
||||||
let methodName = null;
|
|
||||||
|
|
||||||
if (method && method.length) {
|
|
||||||
const abi = api.util.methodToAbi(method);
|
|
||||||
|
|
||||||
methodName = abi.name;
|
|
||||||
methodInputs = api.util
|
|
||||||
.decodeMethodInput(abi, methodParams)
|
|
||||||
.map((value, index) => {
|
|
||||||
const type = abi.inputs[index].type;
|
|
||||||
|
|
||||||
return { type, value };
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setState({ method, methodName, methodInputs });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
@ -321,7 +264,9 @@ class MethodDecoding extends Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
lookup (transaction) {
|
lookup () {
|
||||||
|
const { transaction } = this.props;
|
||||||
|
|
||||||
if (!transaction) {
|
if (!transaction) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -347,26 +292,51 @@ class MethodDecoding extends Component {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { fetchBytecode, fetchMethod } = this.props;
|
Promise
|
||||||
|
.all([
|
||||||
|
api.eth.getCode(contractAddress),
|
||||||
|
Contracts.get().signatureReg.lookup(signature)
|
||||||
|
])
|
||||||
|
.then(([bytecode, method]) => {
|
||||||
|
let methodInputs = null;
|
||||||
|
let methodName = null;
|
||||||
|
|
||||||
fetchBytecode(contractAddress);
|
if (method && method.length) {
|
||||||
fetchMethod(signature);
|
const { methodParams } = this.state;
|
||||||
|
const abi = api.util.methodToAbi(method);
|
||||||
|
|
||||||
|
methodName = abi.name;
|
||||||
|
methodInputs = api.util
|
||||||
|
.decodeMethodInput(abi, methodParams)
|
||||||
|
.map((value, index) => {
|
||||||
|
const type = abi.inputs[index].type;
|
||||||
|
|
||||||
|
return { type, value };
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
method,
|
||||||
|
methodName,
|
||||||
|
methodInputs,
|
||||||
|
bytecode,
|
||||||
|
isContract: bytecode && bytecode !== '0x'
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.warn('lookup', error);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapStateToProps (state) {
|
function mapStateToProps (state) {
|
||||||
const { tokens } = state.balances;
|
const { tokens } = state.balances;
|
||||||
const { bytecodes, methods } = state.blockchain;
|
|
||||||
|
|
||||||
return {
|
return { tokens };
|
||||||
tokens, bytecodes, methods
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapDispatchToProps (dispatch) {
|
function mapDispatchToProps (dispatch) {
|
||||||
return bindActionCreators({
|
return bindActionCreators({}, dispatch);
|
||||||
fetchBytecode, fetchMethod
|
|
||||||
}, dispatch);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
|
@ -25,6 +25,7 @@ import Button from './Button';
|
|||||||
import ConfirmDialog from './ConfirmDialog';
|
import ConfirmDialog from './ConfirmDialog';
|
||||||
import Container, { Title as ContainerTitle } from './Container';
|
import Container, { Title as ContainerTitle } from './Container';
|
||||||
import ContextProvider from './ContextProvider';
|
import ContextProvider from './ContextProvider';
|
||||||
|
import CopyToClipboard from './CopyToClipboard';
|
||||||
import Errors from './Errors';
|
import Errors from './Errors';
|
||||||
import Form, { AddressSelect, FormWrap, Input, InputAddress, InputAddressSelect, InputChip, InputInline, Select } from './Form';
|
import Form, { AddressSelect, FormWrap, Input, InputAddress, InputAddressSelect, InputChip, InputInline, Select } from './Form';
|
||||||
import IdentityIcon from './IdentityIcon';
|
import IdentityIcon from './IdentityIcon';
|
||||||
@ -53,6 +54,7 @@ export {
|
|||||||
Container,
|
Container,
|
||||||
ContainerTitle,
|
ContainerTitle,
|
||||||
ContextProvider,
|
ContextProvider,
|
||||||
|
CopyToClipboard,
|
||||||
Errors,
|
Errors,
|
||||||
Form,
|
Form,
|
||||||
FormWrap,
|
FormWrap,
|
||||||
|
@ -17,46 +17,37 @@
|
|||||||
import BigNumber from 'bignumber.js';
|
import BigNumber from 'bignumber.js';
|
||||||
import React, { Component, PropTypes } from 'react';
|
import React, { Component, PropTypes } from 'react';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import { bindActionCreators } from 'redux';
|
|
||||||
|
|
||||||
import { fetchBlock, fetchTransaction } from '../../../../redux/providers/blockchainActions';
|
|
||||||
|
|
||||||
import { IdentityIcon, IdentityName, MethodDecoding } from '../../../../ui';
|
import { IdentityIcon, IdentityName, MethodDecoding } from '../../../../ui';
|
||||||
import { txLink, addressLink } from '../../../../3rdparty/etherscan/links';
|
import { txLink, addressLink } from '../../../../3rdparty/etherscan/links';
|
||||||
|
|
||||||
import styles from '../transactions.css';
|
import styles from '../transactions.css';
|
||||||
|
|
||||||
class Transaction extends Component {
|
export default class Transaction extends Component {
|
||||||
static contextTypes = {
|
static contextTypes = {
|
||||||
api: PropTypes.object.isRequired
|
api: PropTypes.object.isRequired
|
||||||
}
|
}
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
transaction: PropTypes.object.isRequired,
|
|
||||||
address: PropTypes.string.isRequired,
|
address: PropTypes.string.isRequired,
|
||||||
isTest: PropTypes.bool.isRequired,
|
isTest: PropTypes.bool.isRequired,
|
||||||
|
transaction: PropTypes.object.isRequired
|
||||||
fetchBlock: PropTypes.func.isRequired,
|
|
||||||
fetchTransaction: PropTypes.func.isRequired,
|
|
||||||
|
|
||||||
block: PropTypes.object,
|
|
||||||
transactionInfo: PropTypes.object
|
|
||||||
}
|
}
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
isContract: false,
|
isContract: false,
|
||||||
isReceived: false
|
isReceived: false,
|
||||||
|
transaction: null,
|
||||||
|
block: null
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount () {
|
componentDidMount () {
|
||||||
const { address, transaction } = this.props;
|
this.lookup();
|
||||||
|
|
||||||
this.lookup(address, transaction);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { block, transaction } = this.props;
|
const { block } = this.state;
|
||||||
|
const { transaction } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<tr>
|
<tr>
|
||||||
@ -75,9 +66,10 @@ class Transaction extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderMethod () {
|
renderMethod () {
|
||||||
const { address, transactionInfo } = this.props;
|
const { address } = this.props;
|
||||||
|
const { transaction } = this.state;
|
||||||
|
|
||||||
if (!transactionInfo) {
|
if (!transaction) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,12 +77,13 @@ class Transaction extends Component {
|
|||||||
<MethodDecoding
|
<MethodDecoding
|
||||||
historic
|
historic
|
||||||
address={ address }
|
address={ address }
|
||||||
transaction={ transactionInfo } />
|
transaction={ transaction } />
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderTransaction () {
|
renderTransaction () {
|
||||||
const { transaction, isTest } = this.props;
|
const { isTest } = this.props;
|
||||||
|
const { transaction } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<td className={ styles.transaction }>
|
<td className={ styles.transaction }>
|
||||||
@ -138,13 +131,13 @@ class Transaction extends Component {
|
|||||||
|
|
||||||
renderEtherValue () {
|
renderEtherValue () {
|
||||||
const { api } = this.context;
|
const { api } = this.context;
|
||||||
const { transactionInfo } = this.props;
|
const { transaction } = this.state;
|
||||||
|
|
||||||
if (!transactionInfo) {
|
if (!transaction) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const value = api.util.fromWei(transactionInfo.value);
|
const value = api.util.fromWei(transaction.value);
|
||||||
|
|
||||||
if (value.eq(0)) {
|
if (value.eq(0)) {
|
||||||
return <div className={ styles.value }>{ ' ' }</div>;
|
return <div className={ styles.value }>{ ' ' }</div>;
|
||||||
@ -177,34 +170,22 @@ class Transaction extends Component {
|
|||||||
return moment(block.timestamp).fromNow();
|
return moment(block.timestamp).fromNow();
|
||||||
}
|
}
|
||||||
|
|
||||||
lookup (address, transaction) {
|
lookup () {
|
||||||
const { transactionInfo } = this.props;
|
const { api } = this.context;
|
||||||
|
const { transaction, address } = this.props;
|
||||||
if (transactionInfo) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setState({ isReceived: address === transaction.to });
|
this.setState({ isReceived: address === transaction.to });
|
||||||
|
|
||||||
const { fetchBlock, fetchTransaction } = this.props;
|
Promise
|
||||||
const { blockNumber, hash } = transaction;
|
.all([
|
||||||
|
api.eth.getBlockByNumber(transaction.blockNumber),
|
||||||
fetchBlock(blockNumber);
|
api.eth.getTransactionByHash(transaction.hash)
|
||||||
fetchTransaction(hash);
|
])
|
||||||
|
.then(([block, transaction]) => {
|
||||||
|
this.setState({ block, transaction });
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.warn('lookup', error);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapStateToProps () {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
function mapDispatchToProps (dispatch) {
|
|
||||||
return bindActionCreators({
|
|
||||||
fetchBlock, fetchTransaction
|
|
||||||
}, dispatch);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default connect(
|
|
||||||
mapStateToProps,
|
|
||||||
mapDispatchToProps
|
|
||||||
)(Transaction);
|
|
||||||
|
@ -38,9 +38,7 @@ class Transactions extends Component {
|
|||||||
contracts: PropTypes.object,
|
contracts: PropTypes.object,
|
||||||
tokens: PropTypes.object,
|
tokens: PropTypes.object,
|
||||||
isTest: PropTypes.bool,
|
isTest: PropTypes.bool,
|
||||||
traceMode: PropTypes.bool,
|
traceMode: PropTypes.bool
|
||||||
blocks: PropTypes.object,
|
|
||||||
transactionsInfo: PropTypes.object
|
|
||||||
}
|
}
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
@ -121,7 +119,7 @@ class Transactions extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderRows () {
|
renderRows () {
|
||||||
const { address, accounts, contacts, contracts, tokens, isTest, blocks, transactionsInfo } = this.props;
|
const { address, accounts, contacts, contracts, tokens, isTest } = this.props;
|
||||||
const { transactions } = this.state;
|
const { transactions } = this.state;
|
||||||
|
|
||||||
return (transactions || [])
|
return (transactions || [])
|
||||||
@ -130,16 +128,9 @@ class Transactions extends Component {
|
|||||||
})
|
})
|
||||||
.slice(0, 25)
|
.slice(0, 25)
|
||||||
.map((transaction, index) => {
|
.map((transaction, index) => {
|
||||||
const { blockNumber, hash } = transaction;
|
|
||||||
|
|
||||||
const block = blocks[blockNumber.toString()];
|
|
||||||
const transactionInfo = transactionsInfo[hash];
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Transaction
|
<Transaction
|
||||||
key={ index }
|
key={ index }
|
||||||
block={ block }
|
|
||||||
transactionInfo={ transactionInfo }
|
|
||||||
transaction={ transaction }
|
transaction={ transaction }
|
||||||
address={ address }
|
address={ address }
|
||||||
accounts={ accounts }
|
accounts={ accounts }
|
||||||
@ -165,9 +156,9 @@ class Transactions extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fetchTransactions = (isTest, address, traceMode) => {
|
fetchTransactions = (isTest, address, traceMode) => {
|
||||||
if (traceMode) {
|
// if (traceMode) {
|
||||||
return this.fetchTraceTransactions(address);
|
// return this.fetchTraceTransactions(address);
|
||||||
}
|
// }
|
||||||
|
|
||||||
return this.fetchEtherscanTransactions(isTest, address);
|
return this.fetchEtherscanTransactions(isTest, address);
|
||||||
}
|
}
|
||||||
@ -211,7 +202,6 @@ function mapStateToProps (state) {
|
|||||||
const { isTest, traceMode } = state.nodeStatus;
|
const { isTest, traceMode } = state.nodeStatus;
|
||||||
const { accounts, contacts, contracts } = state.personal;
|
const { accounts, contacts, contracts } = state.personal;
|
||||||
const { tokens } = state.balances;
|
const { tokens } = state.balances;
|
||||||
const { blocks, transactions } = state.blockchain;
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
isTest,
|
isTest,
|
||||||
@ -219,9 +209,7 @@ function mapStateToProps (state) {
|
|||||||
accounts,
|
accounts,
|
||||||
contacts,
|
contacts,
|
||||||
contracts,
|
contracts,
|
||||||
tokens,
|
tokens
|
||||||
blocks,
|
|
||||||
transactionsInfo: transactions
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,12 +15,10 @@
|
|||||||
/* along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
/* along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
.status {
|
.status {
|
||||||
padding: 1.5em;
|
padding: 0.5em;
|
||||||
text-align: right;
|
font-size: x-small;
|
||||||
color: #ddd;
|
color: #ccc;
|
||||||
display: flex;
|
background-color: rgba(0, 0, 0, 0.2)
|
||||||
flex-direction: column;
|
|
||||||
align-items: flex-end;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
@ -28,9 +26,14 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.enode {
|
.enode {
|
||||||
width: 45em;
|
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
margin: 0.5em 0 0.25em;
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.enode > * {
|
||||||
|
display: inline-block;
|
||||||
|
margin: 0.25em 0.5em;
|
||||||
|
vertical-align: top;
|
||||||
}
|
}
|
||||||
|
|
||||||
.block {
|
.block {
|
||||||
@ -39,9 +42,7 @@
|
|||||||
.netinfo {
|
.netinfo {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
flex-direction: row;
|
color: #ddd;
|
||||||
justify-content: flex-end;
|
|
||||||
margin-top: 0.25em;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.netinfo > * {
|
.netinfo > * {
|
||||||
@ -69,6 +70,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.version {
|
.version {
|
||||||
|
padding: 0.25em 0.5em;
|
||||||
|
float: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
.syncing {
|
.syncing {
|
||||||
|
@ -19,6 +19,7 @@ import { connect } from 'react-redux';
|
|||||||
import { bindActionCreators } from 'redux';
|
import { bindActionCreators } from 'redux';
|
||||||
|
|
||||||
import { BlockStatus } from '../../../ui';
|
import { BlockStatus } from '../../../ui';
|
||||||
|
import CopyToClipboard from '../../../ui/CopyToClipboard';
|
||||||
|
|
||||||
import styles from './status.css';
|
import styles from './status.css';
|
||||||
|
|
||||||
@ -47,15 +48,13 @@ class Status extends Component {
|
|||||||
</div>
|
</div>
|
||||||
{ this.renderEnode() }
|
{ this.renderEnode() }
|
||||||
<div className={ styles.netinfo }>
|
<div className={ styles.netinfo }>
|
||||||
<div>
|
|
||||||
<BlockStatus />
|
<BlockStatus />
|
||||||
<div className={ styles.peers }>
|
|
||||||
{ netPeers.active.toFormat() }/{ netPeers.connected.toFormat() }/{ netPeers.max.toFormat() } peers
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className={ netStyle }>
|
<div className={ netStyle }>
|
||||||
{ isTest ? 'test' : netChain }
|
{ isTest ? 'test' : netChain }
|
||||||
</div>
|
</div>
|
||||||
|
<div className={ styles.peers }>
|
||||||
|
{ netPeers.active.toFormat() }/{ netPeers.connected.toFormat() }/{ netPeers.max.toFormat() } peers
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -68,9 +67,14 @@ class Status extends Component {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const [protocol, rest] = enode.split('://');
|
||||||
|
const [id, host] = rest.split('@');
|
||||||
|
const abbreviated = `${protocol}://${id.slice(0, 3)}…${id.slice(-3)}@${host}`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={ styles.enode }>
|
<div className={ styles.enode }>
|
||||||
{ enode }
|
<CopyToClipboard data={ enode } />
|
||||||
|
<div>{ abbreviated }</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -149,15 +149,15 @@ class TabBar extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderStatusLabel = (label) => {
|
renderStatusLabel = (label) => {
|
||||||
const { isTest, netChain } = this.props;
|
// const { isTest, netChain } = this.props;
|
||||||
const bubble = (
|
// const bubble = (
|
||||||
<Badge
|
// <Badge
|
||||||
color={ isTest ? 'red' : 'default' }
|
// color={ isTest ? 'red' : 'default' }
|
||||||
className={ styles.labelBubble }
|
// className={ styles.labelBubble }
|
||||||
value={ isTest ? 'TEST' : netChain } />
|
// value={ isTest ? 'TEST' : netChain } />
|
||||||
);
|
// );
|
||||||
|
|
||||||
return this.renderLabel(label, bubble);
|
return this.renderLabel(label, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
onActivate = (activeRoute) => {
|
onActivate = (activeRoute) => {
|
||||||
|
@ -17,27 +17,24 @@
|
|||||||
import BigNumber from 'bignumber.js';
|
import BigNumber from 'bignumber.js';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import React, { Component, PropTypes } from 'react';
|
import React, { Component, PropTypes } from 'react';
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import { bindActionCreators } from 'redux';
|
|
||||||
|
|
||||||
import { fetchBlock, fetchTransaction } from '../../../../redux/providers/blockchainActions';
|
|
||||||
import { IdentityIcon, IdentityName, Input, InputAddress } from '../../../../ui';
|
import { IdentityIcon, IdentityName, Input, InputAddress } from '../../../../ui';
|
||||||
import { txLink } from '../../../../3rdparty/etherscan/links';
|
import { txLink } from '../../../../3rdparty/etherscan/links';
|
||||||
|
|
||||||
import styles from '../../contract.css';
|
import styles from '../../contract.css';
|
||||||
|
|
||||||
class Event extends Component {
|
export default class Event extends Component {
|
||||||
static contextTypes = {
|
static contextTypes = {
|
||||||
api: PropTypes.object.isRequired
|
api: PropTypes.object.isRequired
|
||||||
}
|
}
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
event: PropTypes.object.isRequired,
|
event: PropTypes.object.isRequired,
|
||||||
blocks: PropTypes.object,
|
isTest: PropTypes.bool
|
||||||
transactions: PropTypes.object,
|
}
|
||||||
isTest: PropTypes.bool,
|
|
||||||
fetchBlock: PropTypes.func.isRequired,
|
state = {
|
||||||
fetchTransaction: PropTypes.func.isRequired
|
transaction: {}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount () {
|
componentDidMount () {
|
||||||
@ -45,10 +42,9 @@ class Event extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { event, blocks, transactions, isTest } = this.props;
|
const { event, isTest } = this.props;
|
||||||
|
const { block, transaction } = this.state;
|
||||||
|
|
||||||
const block = blocks[event.blockNumber.toString()];
|
|
||||||
const transaction = transactions[event.transactionHash] || {};
|
|
||||||
const classes = `${styles.event} ${styles[event.state]}`;
|
const classes = `${styles.event} ${styles[event.state]}`;
|
||||||
const url = txLink(event.transactionHash, isTest);
|
const url = txLink(event.transactionHash, isTest);
|
||||||
const keys = Object.keys(event.params).join(', ');
|
const keys = Object.keys(event.params).join(', ');
|
||||||
@ -156,31 +152,19 @@ class Event extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
retrieveTransaction () {
|
retrieveTransaction () {
|
||||||
const { event, fetchBlock, fetchTransaction } = this.props;
|
const { api } = this.context;
|
||||||
|
const { event } = this.props;
|
||||||
|
|
||||||
fetchBlock(event.blockNumber);
|
Promise
|
||||||
fetchTransaction(event.transactionHash);
|
.all([
|
||||||
|
api.eth.getBlockByNumber(event.blockNumber),
|
||||||
|
api.eth.getTransactionByHash(event.transactionHash)
|
||||||
|
])
|
||||||
|
.then(([block, transaction]) => {
|
||||||
|
this.setState({ block, transaction });
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.warn('retrieveTransaction', error);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapStateToProps (state) {
|
|
||||||
const { isTest } = state.nodeStatus;
|
|
||||||
const { blocks, transactions } = state.blockchain;
|
|
||||||
|
|
||||||
return {
|
|
||||||
isTest,
|
|
||||||
blocks,
|
|
||||||
transactions
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function mapDispatchToProps (dispatch) {
|
|
||||||
return bindActionCreators({
|
|
||||||
fetchBlock, fetchTransaction
|
|
||||||
}, dispatch);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default connect(
|
|
||||||
mapStateToProps,
|
|
||||||
mapDispatchToProps
|
|
||||||
)(Event);
|
|
||||||
|
@ -27,21 +27,31 @@ export default class Events extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
events: PropTypes.array
|
events: PropTypes.array,
|
||||||
|
isTest: PropTypes.bool.isRequired
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { events } = this.props;
|
const { events, isTest } = this.props;
|
||||||
|
|
||||||
if (!events || !events.length) {
|
if (!events || !events.length) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const list = events.map((event) => {
|
||||||
|
return (
|
||||||
|
<Event
|
||||||
|
key={ event.key }
|
||||||
|
event={ event }
|
||||||
|
isTest={ isTest } />
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<ContainerTitle title='events' />
|
<ContainerTitle title='events' />
|
||||||
<table className={ styles.events }>
|
<table className={ styles.events }>
|
||||||
<tbody>{ events.map((event) => <Event event={ event } key={ event.key } />) }</tbody>
|
<tbody>{ list }</tbody>
|
||||||
</table>
|
</table>
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
|
@ -116,6 +116,7 @@ class Contract extends Component {
|
|||||||
contract={ contract }
|
contract={ contract }
|
||||||
values={ queryValues } />
|
values={ queryValues } />
|
||||||
<Events
|
<Events
|
||||||
|
isTest={ isTest }
|
||||||
events={ allEvents } />
|
events={ allEvents } />
|
||||||
</Page>
|
</Page>
|
||||||
</div>
|
</div>
|
||||||
|
@ -70,6 +70,21 @@ pub struct EthashParams {
|
|||||||
/// See main EthashParams docs.
|
/// See main EthashParams docs.
|
||||||
#[serde(rename="eip150Transition")]
|
#[serde(rename="eip150Transition")]
|
||||||
pub eip150_transition: Option<Uint>,
|
pub eip150_transition: Option<Uint>,
|
||||||
|
|
||||||
|
/// See main EthashParams docs.
|
||||||
|
#[serde(rename="eip155Transition")]
|
||||||
|
pub eip155_transition: Option<Uint>,
|
||||||
|
|
||||||
|
/// See main EthashParams docs.
|
||||||
|
#[serde(rename="eip160Transition")]
|
||||||
|
pub eip160_transition: Option<Uint>,
|
||||||
|
|
||||||
|
/// See main EthashParams docs.
|
||||||
|
#[serde(rename="eip161abcTransition")]
|
||||||
|
pub eip161abc_transition: Option<Uint>,
|
||||||
|
/// See main EthashParams docs.
|
||||||
|
#[serde(rename="eip161dTransition")]
|
||||||
|
pub eip161d_transition: Option<Uint>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Ethash engine deserialization.
|
/// Ethash engine deserialization.
|
||||||
@ -122,7 +137,11 @@ mod tests {
|
|||||||
"difficultyHardforkTransition": "0x59d9",
|
"difficultyHardforkTransition": "0x59d9",
|
||||||
"difficultyHardforkBoundDivisor": "0x0200",
|
"difficultyHardforkBoundDivisor": "0x0200",
|
||||||
"bombDefuseTransition": "0x42",
|
"bombDefuseTransition": "0x42",
|
||||||
"eip150Transition": "0x42"
|
"eip150Transition": "0x42",
|
||||||
|
"eip155Transition": "0x42",
|
||||||
|
"eip160Transition": "0x42",
|
||||||
|
"eip161abcTransition": "0x42",
|
||||||
|
"eip161dTransition": "0x42"
|
||||||
}
|
}
|
||||||
}"#;
|
}"#;
|
||||||
|
|
||||||
|
@ -28,15 +28,17 @@ pub struct Params {
|
|||||||
/// Maximum size of extra data.
|
/// Maximum size of extra data.
|
||||||
#[serde(rename="maximumExtraDataSize")]
|
#[serde(rename="maximumExtraDataSize")]
|
||||||
pub maximum_extra_data_size: Uint,
|
pub maximum_extra_data_size: Uint,
|
||||||
|
/// Minimum gas limit.
|
||||||
|
#[serde(rename="minGasLimit")]
|
||||||
|
pub min_gas_limit: Uint,
|
||||||
|
|
||||||
/// Network id.
|
/// Network id.
|
||||||
#[serde(rename="networkID")]
|
#[serde(rename="networkID")]
|
||||||
pub network_id: Uint,
|
pub network_id: Uint,
|
||||||
/// Name of the main ("eth") subprotocol.
|
/// Name of the main ("eth") subprotocol.
|
||||||
#[serde(rename="subprotocolName")]
|
#[serde(rename="subprotocolName")]
|
||||||
pub subprotocol_name: Option<String>,
|
pub subprotocol_name: Option<String>,
|
||||||
/// Minimum gas limit.
|
|
||||||
#[serde(rename="minGasLimit")]
|
|
||||||
pub min_gas_limit: Uint,
|
|
||||||
/// Option fork block number to check.
|
/// Option fork block number to check.
|
||||||
#[serde(rename="forkBlock")]
|
#[serde(rename="forkBlock")]
|
||||||
pub fork_block: Option<Uint>,
|
pub fork_block: Option<Uint>,
|
||||||
|
@ -98,7 +98,8 @@ section "install"
|
|||||||
|
|
||||||
# Start Menu
|
# Start Menu
|
||||||
createDirectory "$SMPROGRAMS\${COMPANYNAME}"
|
createDirectory "$SMPROGRAMS\${COMPANYNAME}"
|
||||||
createShortCut "$SMPROGRAMS\${COMPANYNAME}\${APPNAME}.lnk" "$INSTDIR\parity.exe" "ui" "$INSTDIR\logo.ico"
|
createShortCut "$SMPROGRAMS\${COMPANYNAME}\${APPNAME} Ethereum.lnk" "$INSTDIR\ptray.exe" "ui" "$INSTDIR\logo.ico"
|
||||||
|
createShortCut "$DESKTOP\${APPNAME} Ethereum.lnk" "$INSTDIR\ptray.exe" "ui" "$INSTDIR\logo.ico"
|
||||||
|
|
||||||
# Firewall remove rules if exists
|
# Firewall remove rules if exists
|
||||||
SimpleFC::AdvRemoveRule "Parity incoming peers (TCP:30303)"
|
SimpleFC::AdvRemoveRule "Parity incoming peers (TCP:30303)"
|
||||||
|
@ -25,7 +25,7 @@ port = 30303
|
|||||||
min_peers = 25
|
min_peers = 25
|
||||||
max_peers = 50
|
max_peers = 50
|
||||||
nat = "any"
|
nat = "any"
|
||||||
id = "0x1"
|
id = 1
|
||||||
bootnodes = []
|
bootnodes = []
|
||||||
discovery = true
|
discovery = true
|
||||||
warp = true
|
warp = true
|
||||||
@ -47,7 +47,7 @@ hosts = ["none"]
|
|||||||
[ipc]
|
[ipc]
|
||||||
disable = false
|
disable = false
|
||||||
path = "$HOME/.parity/jsonrpc.ipc"
|
path = "$HOME/.parity/jsonrpc.ipc"
|
||||||
apis = ["web3", "eth", "net", "ethcore", "traces", "rpc", "personal_safe"]
|
apis = ["web3", "eth", "net", "ethcore", "traces", "rpc", "personal", "personal_safe"]
|
||||||
|
|
||||||
[dapps]
|
[dapps]
|
||||||
disable = false
|
disable = false
|
||||||
|
@ -46,7 +46,7 @@ usage! {
|
|||||||
flag_testnet: bool,
|
flag_testnet: bool,
|
||||||
flag_import_geth_keys: bool,
|
flag_import_geth_keys: bool,
|
||||||
flag_datadir: Option<String>,
|
flag_datadir: Option<String>,
|
||||||
flag_networkid: Option<String>,
|
flag_networkid: Option<usize>,
|
||||||
flag_peers: Option<u16>,
|
flag_peers: Option<u16>,
|
||||||
flag_nodekey: Option<String>,
|
flag_nodekey: Option<String>,
|
||||||
flag_nodiscover: bool,
|
flag_nodiscover: bool,
|
||||||
@ -122,7 +122,7 @@ usage! {
|
|||||||
or |c: &Config| otry!(c.network).nat.clone(),
|
or |c: &Config| otry!(c.network).nat.clone(),
|
||||||
flag_allow_ips: String = "all",
|
flag_allow_ips: String = "all",
|
||||||
or |c: &Config| otry!(c.network).allow_ips.clone(),
|
or |c: &Config| otry!(c.network).allow_ips.clone(),
|
||||||
flag_network_id: Option<String> = None,
|
flag_network_id: Option<usize> = None,
|
||||||
or |c: &Config| otry!(c.network).id.clone().map(Some),
|
or |c: &Config| otry!(c.network).id.clone().map(Some),
|
||||||
flag_bootnodes: Option<String> = None,
|
flag_bootnodes: Option<String> = None,
|
||||||
or |c: &Config| otry!(c.network).bootnodes.clone().map(|vec| Some(vec.join(","))),
|
or |c: &Config| otry!(c.network).bootnodes.clone().map(|vec| Some(vec.join(","))),
|
||||||
@ -155,7 +155,7 @@ usage! {
|
|||||||
or |c: &Config| otry!(c.ipc).disable.clone(),
|
or |c: &Config| otry!(c.ipc).disable.clone(),
|
||||||
flag_ipc_path: String = "$HOME/.parity/jsonrpc.ipc",
|
flag_ipc_path: String = "$HOME/.parity/jsonrpc.ipc",
|
||||||
or |c: &Config| otry!(c.ipc).path.clone(),
|
or |c: &Config| otry!(c.ipc).path.clone(),
|
||||||
flag_ipc_apis: String = "web3,eth,net,ethcore,traces,rpc,personal_safe",
|
flag_ipc_apis: String = "web3,eth,net,ethcore,traces,rpc,personal,personal_safe",
|
||||||
or |c: &Config| otry!(c.ipc).apis.clone().map(|vec| vec.join(",")),
|
or |c: &Config| otry!(c.ipc).apis.clone().map(|vec| vec.join(",")),
|
||||||
|
|
||||||
// DAPPS
|
// DAPPS
|
||||||
@ -323,7 +323,7 @@ struct Network {
|
|||||||
max_pending_peers: Option<u16>,
|
max_pending_peers: Option<u16>,
|
||||||
nat: Option<String>,
|
nat: Option<String>,
|
||||||
allow_ips: Option<String>,
|
allow_ips: Option<String>,
|
||||||
id: Option<String>,
|
id: Option<usize>,
|
||||||
bootnodes: Option<Vec<String>>,
|
bootnodes: Option<Vec<String>>,
|
||||||
discovery: Option<bool>,
|
discovery: Option<bool>,
|
||||||
node_key: Option<String>,
|
node_key: Option<String>,
|
||||||
@ -530,7 +530,7 @@ mod tests {
|
|||||||
flag_snapshot_peers: 0u16,
|
flag_snapshot_peers: 0u16,
|
||||||
flag_allow_ips: "all".into(),
|
flag_allow_ips: "all".into(),
|
||||||
flag_nat: "any".into(),
|
flag_nat: "any".into(),
|
||||||
flag_network_id: Some("0x1".into()),
|
flag_network_id: Some(1),
|
||||||
flag_bootnodes: Some("".into()),
|
flag_bootnodes: Some("".into()),
|
||||||
flag_no_discovery: false,
|
flag_no_discovery: false,
|
||||||
flag_node_key: None,
|
flag_node_key: None,
|
||||||
@ -549,7 +549,7 @@ mod tests {
|
|||||||
// IPC
|
// IPC
|
||||||
flag_no_ipc: false,
|
flag_no_ipc: false,
|
||||||
flag_ipc_path: "$HOME/.parity/jsonrpc.ipc".into(),
|
flag_ipc_path: "$HOME/.parity/jsonrpc.ipc".into(),
|
||||||
flag_ipc_apis: "web3,eth,net,ethcore,traces,rpc,personal_safe".into(),
|
flag_ipc_apis: "web3,eth,net,ethcore,traces,rpc,personal,personal_safe".into(),
|
||||||
|
|
||||||
// DAPPS
|
// DAPPS
|
||||||
flag_no_dapps: false,
|
flag_no_dapps: false,
|
||||||
|
@ -5,5 +5,6 @@ License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
|
|||||||
This is free software: you are free to change and redistribute it.
|
This is free software: you are free to change and redistribute it.
|
||||||
There is NO WARRANTY, to the extent permitted by law.
|
There is NO WARRANTY, to the extent permitted by law.
|
||||||
|
|
||||||
By Wood/Paronyan/Kotewicz/Drwięga/Volf.
|
By Wood/Paronyan/Kotewicz/Drwięga/Volf
|
||||||
|
Habermeier/Czaban/Greeff/Gotchac/Redmann
|
||||||
|
|
||||||
|
@ -86,7 +86,7 @@ impl Configuration {
|
|||||||
let http_conf = try!(self.http_config());
|
let http_conf = try!(self.http_config());
|
||||||
let ipc_conf = try!(self.ipc_config());
|
let ipc_conf = try!(self.ipc_config());
|
||||||
let net_conf = try!(self.net_config());
|
let net_conf = try!(self.net_config());
|
||||||
let network_id = try!(self.network_id());
|
let network_id = self.network_id();
|
||||||
let cache_config = self.cache_config();
|
let cache_config = self.cache_config();
|
||||||
let spec = try!(self.chain().parse());
|
let spec = try!(self.chain().parse());
|
||||||
let tracing = try!(self.args.flag_tracing.parse());
|
let tracing = try!(self.args.flag_tracing.parse());
|
||||||
@ -517,12 +517,8 @@ impl Configuration {
|
|||||||
Ok(ret)
|
Ok(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn network_id(&self) -> Result<Option<U256>, String> {
|
fn network_id(&self) -> Option<usize> {
|
||||||
let net_id = self.args.flag_network_id.as_ref().or(self.args.flag_networkid.as_ref());
|
self.args.flag_network_id.or(self.args.flag_networkid)
|
||||||
match net_id {
|
|
||||||
Some(id) => Ok(Some(try!(to_u256(id)))),
|
|
||||||
None => Ok(None),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rpc_apis(&self) -> String {
|
fn rpc_apis(&self) -> String {
|
||||||
|
@ -63,7 +63,7 @@ impl Default for IpcConfiguration {
|
|||||||
IpcConfiguration {
|
IpcConfiguration {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
socket_addr: parity_ipc_path("$HOME/.parity/jsonrpc.ipc"),
|
socket_addr: parity_ipc_path("$HOME/.parity/jsonrpc.ipc"),
|
||||||
apis: ApiSet::UnsafeContext,
|
apis: ApiSet::IpcContext,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,6 +69,7 @@ impl FromStr for Api {
|
|||||||
pub enum ApiSet {
|
pub enum ApiSet {
|
||||||
SafeContext,
|
SafeContext,
|
||||||
UnsafeContext,
|
UnsafeContext,
|
||||||
|
IpcContext,
|
||||||
List(HashSet<Api>),
|
List(HashSet<Api>),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,6 +140,10 @@ impl ApiSet {
|
|||||||
vec![Api::Web3, Api::Net, Api::Eth, Api::Ethcore, Api::Traces, Api::Rpc, Api::PersonalSafe]
|
vec![Api::Web3, Api::Net, Api::Eth, Api::Ethcore, Api::Traces, Api::Rpc, Api::PersonalSafe]
|
||||||
.into_iter().collect()
|
.into_iter().collect()
|
||||||
},
|
},
|
||||||
|
ApiSet::IpcContext => {
|
||||||
|
vec![Api::Web3, Api::Net, Api::Eth, Api::Ethcore, Api::Traces, Api::Rpc, Api::PersonalAccounts, Api::PersonalSafe]
|
||||||
|
.into_iter().collect()
|
||||||
|
},
|
||||||
ApiSet::SafeContext => {
|
ApiSet::SafeContext => {
|
||||||
vec![Api::Web3, Api::Net, Api::Eth, Api::PersonalAccounts, Api::PersonalSafe, Api::Signer, Api::Ethcore, Api::EthcoreSet, Api::Traces, Api::Rpc]
|
vec![Api::Web3, Api::Net, Api::Eth, Api::PersonalAccounts, Api::PersonalSafe, Api::Signer, Api::Ethcore, Api::EthcoreSet, Api::Traces, Api::Rpc]
|
||||||
.into_iter().collect()
|
.into_iter().collect()
|
||||||
|
@ -20,7 +20,7 @@ use ctrlc::CtrlC;
|
|||||||
use fdlimit::raise_fd_limit;
|
use fdlimit::raise_fd_limit;
|
||||||
use ethcore_rpc::{NetworkSettings, is_major_importing};
|
use ethcore_rpc::{NetworkSettings, is_major_importing};
|
||||||
use ethsync::NetworkConfiguration;
|
use ethsync::NetworkConfiguration;
|
||||||
use util::{Colour, version, U256, RotatingLogger};
|
use util::{Colour, version, RotatingLogger};
|
||||||
use io::{MayPanic, ForwardPanic, PanicHandler};
|
use io::{MayPanic, ForwardPanic, PanicHandler};
|
||||||
use ethcore_logger::{Config as LogConfig};
|
use ethcore_logger::{Config as LogConfig};
|
||||||
use ethcore::client::{Mode, DatabaseCompactionProfile, VMType, ChainNotify, BlockChainClient};
|
use ethcore::client::{Mode, DatabaseCompactionProfile, VMType, ChainNotify, BlockChainClient};
|
||||||
@ -70,7 +70,7 @@ pub struct RunCmd {
|
|||||||
pub http_conf: HttpConfiguration,
|
pub http_conf: HttpConfiguration,
|
||||||
pub ipc_conf: IpcConfiguration,
|
pub ipc_conf: IpcConfiguration,
|
||||||
pub net_conf: NetworkConfiguration,
|
pub net_conf: NetworkConfiguration,
|
||||||
pub network_id: Option<U256>,
|
pub network_id: Option<usize>,
|
||||||
pub warp_sync: bool,
|
pub warp_sync: bool,
|
||||||
pub acc_conf: AccountsConfig,
|
pub acc_conf: AccountsConfig,
|
||||||
pub gas_pricer: GasPricerConfig,
|
pub gas_pricer: GasPricerConfig,
|
||||||
|
@ -63,15 +63,16 @@ pub fn decrypt(accounts: &AccountProvider, address: Address, password: Option<St
|
|||||||
pub fn sign_and_dispatch<C, M>(client: &C, miner: &M, accounts: &AccountProvider, request: TransactionRequest, password: Option<String>) -> Result<RpcH256, Error>
|
pub fn sign_and_dispatch<C, M>(client: &C, miner: &M, accounts: &AccountProvider, request: TransactionRequest, password: Option<String>) -> Result<RpcH256, Error>
|
||||||
where C: MiningBlockChainClient, M: MinerService {
|
where C: MiningBlockChainClient, M: MinerService {
|
||||||
|
|
||||||
|
let network_id = client.signing_network_id();
|
||||||
let address = request.from;
|
let address = request.from;
|
||||||
let signed_transaction = {
|
let signed_transaction = {
|
||||||
let t = prepare_transaction(client, miner, request);
|
let t = prepare_transaction(client, miner, request);
|
||||||
let hash = t.hash();
|
let hash = t.hash(network_id);
|
||||||
let signature = try!(signature(accounts, address, password, hash));
|
let signature = try!(signature(accounts, address, password, hash));
|
||||||
t.with_signature(signature)
|
t.with_signature(signature, network_id)
|
||||||
};
|
};
|
||||||
|
|
||||||
trace!(target: "miner", "send_transaction: dispatching tx: {}", ::rlp::encode(&signed_transaction).to_vec().pretty());
|
trace!(target: "miner", "send_transaction: dispatching tx: {} for network ID {:?}", ::rlp::encode(&signed_transaction).to_vec().pretty(), network_id);
|
||||||
dispatch_transaction(&*client, &*miner, signed_transaction)
|
dispatch_transaction(&*client, &*miner, signed_transaction)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -255,6 +255,7 @@ pub fn from_transaction_error(error: EthcoreError) -> Error {
|
|||||||
SenderBanned => "Sender is banned in local queue.".into(),
|
SenderBanned => "Sender is banned in local queue.".into(),
|
||||||
RecipientBanned => "Recipient is banned in local queue.".into(),
|
RecipientBanned => "Recipient is banned in local queue.".into(),
|
||||||
CodeBanned => "Code is banned in local queue.".into(),
|
CodeBanned => "Code is banned in local queue.".into(),
|
||||||
|
e => format!("{}", e).into(),
|
||||||
};
|
};
|
||||||
Error {
|
Error {
|
||||||
code: ErrorCode::ServerError(codes::TRANSACTION_ERROR),
|
code: ErrorCode::ServerError(codes::TRANSACTION_ERROR),
|
||||||
|
@ -45,7 +45,7 @@ fn account_provider() -> Arc<AccountProvider> {
|
|||||||
|
|
||||||
fn sync_provider() -> Arc<TestSyncProvider> {
|
fn sync_provider() -> Arc<TestSyncProvider> {
|
||||||
Arc::new(TestSyncProvider::new(Config {
|
Arc::new(TestSyncProvider::new(Config {
|
||||||
network_id: U256::from(3),
|
network_id: 3,
|
||||||
num_peers: 120,
|
num_peers: 120,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
@ -209,6 +209,8 @@ impl MinerService for TestMinerService {
|
|||||||
gas_used: r.gas_used.clone(),
|
gas_used: r.gas_used.clone(),
|
||||||
contract_address: None,
|
contract_address: None,
|
||||||
logs: r.logs.clone(),
|
logs: r.logs.clone(),
|
||||||
|
log_bloom: r.log_bloom,
|
||||||
|
state_root: r.state_root,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -16,13 +16,13 @@
|
|||||||
|
|
||||||
//! Test implementation of SyncProvider.
|
//! Test implementation of SyncProvider.
|
||||||
|
|
||||||
use util::{RwLock, U256};
|
use util::{RwLock};
|
||||||
use ethsync::{SyncProvider, SyncStatus, SyncState, PeerInfo};
|
use ethsync::{SyncProvider, SyncStatus, SyncState, PeerInfo};
|
||||||
|
|
||||||
/// TestSyncProvider config.
|
/// TestSyncProvider config.
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
/// Protocol version.
|
/// Protocol version.
|
||||||
pub network_id: U256,
|
pub network_id: usize,
|
||||||
/// Number of peers.
|
/// Number of peers.
|
||||||
pub num_peers: usize,
|
pub num_peers: usize,
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@ fn accounts_provider() -> Arc<AccountProvider> {
|
|||||||
|
|
||||||
fn sync_provider() -> Arc<TestSyncProvider> {
|
fn sync_provider() -> Arc<TestSyncProvider> {
|
||||||
Arc::new(TestSyncProvider::new(Config {
|
Arc::new(TestSyncProvider::new(Config {
|
||||||
network_id: U256::from(3),
|
network_id: 3,
|
||||||
num_peers: 120,
|
num_peers: 120,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
@ -485,7 +485,7 @@ fn rpc_eth_pending_transaction_by_hash() {
|
|||||||
tester.miner.pending_transactions.lock().insert(H256::zero(), tx);
|
tester.miner.pending_transactions.lock().insert(H256::zero(), tx);
|
||||||
}
|
}
|
||||||
|
|
||||||
let response = r#"{"jsonrpc":"2.0","result":{"blockHash":null,"blockNumber":null,"creates":null,"from":"0x0f65fe9276bc9a24ae7083ae28e2660ef72df99e","gas":"0x5208","gasPrice":"0x1","hash":"0x41df922fd0d4766fcc02e161f8295ec28522f329ae487f14d811e4b64c8d6e31","input":"0x","nonce":"0x0","publicKey":"0x7ae46da747962c2ee46825839c1ef9298e3bd2e70ca2938495c3693a485ec3eaa8f196327881090ff64cf4fbb0a48485d4f83098e189ed3b7a87d5941b59f789","raw":"0xf85f800182520894095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a0efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804","to":"0x095e7baea6a6c7c4c2dfeb977efac326af552d87","transactionIndex":null,"value":"0xa"},"id":1}"#;
|
let response = r#"{"jsonrpc":"2.0","result":{"blockHash":null,"blockNumber":null,"creates":null,"from":"0x0f65fe9276bc9a24ae7083ae28e2660ef72df99e","gas":"0x5208","gasPrice":"0x1","hash":"0x41df922fd0d4766fcc02e161f8295ec28522f329ae487f14d811e4b64c8d6e31","input":"0x","nonce":"0x0","publicKey":"0x7ae46da747962c2ee46825839c1ef9298e3bd2e70ca2938495c3693a485ec3eaa8f196327881090ff64cf4fbb0a48485d4f83098e189ed3b7a87d5941b59f789","r":"0x48b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353","raw":"0xf85f800182520894095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a0efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804","s":"0xefffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804","to":"0x095e7baea6a6c7c4c2dfeb977efac326af552d87","transactionIndex":null,"v":0,"value":"0xa"},"id":1}"#;
|
||||||
let request = r#"{
|
let request = r#"{
|
||||||
"jsonrpc": "2.0",
|
"jsonrpc": "2.0",
|
||||||
"method": "eth_getTransactionByHash",
|
"method": "eth_getTransactionByHash",
|
||||||
@ -737,8 +737,8 @@ fn rpc_eth_send_transaction() {
|
|||||||
value: U256::from(0x9184e72au64),
|
value: U256::from(0x9184e72au64),
|
||||||
data: vec![]
|
data: vec![]
|
||||||
};
|
};
|
||||||
let signature = tester.accounts_provider.sign(address, None, t.hash()).unwrap();
|
let signature = tester.accounts_provider.sign(address, None, t.hash(None)).unwrap();
|
||||||
let t = t.with_signature(signature);
|
let t = t.with_signature(signature, None);
|
||||||
|
|
||||||
let response = r#"{"jsonrpc":"2.0","result":""#.to_owned() + format!("0x{:?}", t.hash()).as_ref() + r#"","id":1}"#;
|
let response = r#"{"jsonrpc":"2.0","result":""#.to_owned() + format!("0x{:?}", t.hash()).as_ref() + r#"","id":1}"#;
|
||||||
|
|
||||||
@ -754,8 +754,8 @@ fn rpc_eth_send_transaction() {
|
|||||||
value: U256::from(0x9184e72au64),
|
value: U256::from(0x9184e72au64),
|
||||||
data: vec![]
|
data: vec![]
|
||||||
};
|
};
|
||||||
let signature = tester.accounts_provider.sign(address, None, t.hash()).unwrap();
|
let signature = tester.accounts_provider.sign(address, None, t.hash(None)).unwrap();
|
||||||
let t = t.with_signature(signature);
|
let t = t.with_signature(signature, None);
|
||||||
|
|
||||||
let response = r#"{"jsonrpc":"2.0","result":""#.to_owned() + format!("0x{:?}", t.hash()).as_ref() + r#"","id":1}"#;
|
let response = r#"{"jsonrpc":"2.0","result":""#.to_owned() + format!("0x{:?}", t.hash()).as_ref() + r#"","id":1}"#;
|
||||||
|
|
||||||
@ -819,8 +819,8 @@ fn rpc_eth_send_raw_transaction() {
|
|||||||
value: U256::from(0x9184e72au64),
|
value: U256::from(0x9184e72au64),
|
||||||
data: vec![]
|
data: vec![]
|
||||||
};
|
};
|
||||||
let signature = tester.accounts_provider.sign(address, None, t.hash()).unwrap();
|
let signature = tester.accounts_provider.sign(address, None, t.hash(None)).unwrap();
|
||||||
let t = t.with_signature(signature);
|
let t = t.with_signature(signature, None);
|
||||||
|
|
||||||
let rlp = ::rlp::encode(&t).to_vec().to_hex();
|
let rlp = ::rlp::encode(&t).to_vec().to_hex();
|
||||||
|
|
||||||
@ -862,7 +862,9 @@ fn rpc_eth_transaction_receipt() {
|
|||||||
transaction_hash: H256::new(),
|
transaction_hash: H256::new(),
|
||||||
transaction_index: 0,
|
transaction_index: 0,
|
||||||
log_index: 1,
|
log_index: 1,
|
||||||
}]
|
}],
|
||||||
|
log_bloom: 0.into(),
|
||||||
|
state_root: 0.into(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let hash = H256::from_str("b903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238").unwrap();
|
let hash = H256::from_str("b903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238").unwrap();
|
||||||
@ -875,7 +877,7 @@ fn rpc_eth_transaction_receipt() {
|
|||||||
"params": ["0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238"],
|
"params": ["0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238"],
|
||||||
"id": 1
|
"id": 1
|
||||||
}"#;
|
}"#;
|
||||||
let response = r#"{"jsonrpc":"2.0","result":{"blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x4510c","contractAddress":null,"cumulativeGasUsed":"0x20","gasUsed":"0x10","logs":[{"address":"0x33990122638b9132ca29c723bdf037f1a891a70c","blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x4510c","data":"0x","logIndex":"0x1","topics":["0xa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc","0x4861736852656700000000000000000000000000000000000000000000000000"],"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","type":"mined"}],"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0"},"id":1}"#;
|
let response = r#"{"jsonrpc":"2.0","result":{"blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x4510c","contractAddress":null,"cumulativeGasUsed":"0x20","gasUsed":"0x10","logs":[{"address":"0x33990122638b9132ca29c723bdf037f1a891a70c","blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x4510c","data":"0x","logIndex":"0x1","topics":["0xa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc","0x4861736852656700000000000000000000000000000000000000000000000000"],"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","type":"mined"}],"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","root":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0"},"id":1}"#;
|
||||||
|
|
||||||
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
|
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
|
||||||
}
|
}
|
||||||
|
@ -246,8 +246,8 @@ fn should_dispatch_transaction_if_account_is_unlock() {
|
|||||||
value: U256::from(0x9184e72au64),
|
value: U256::from(0x9184e72au64),
|
||||||
data: vec![]
|
data: vec![]
|
||||||
};
|
};
|
||||||
let signature = tester.accounts.sign(acc, None, t.hash()).unwrap();
|
let signature = tester.accounts.sign(acc, None, t.hash(None)).unwrap();
|
||||||
let t = t.with_signature(signature);
|
let t = t.with_signature(signature, None);
|
||||||
|
|
||||||
// when
|
// when
|
||||||
let request = r#"{
|
let request = r#"{
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use util::log::RotatingLogger;
|
use util::log::RotatingLogger;
|
||||||
use util::{U256, Address};
|
use util::{Address};
|
||||||
use ethsync::ManageNetwork;
|
use ethsync::ManageNetwork;
|
||||||
use ethcore::client::{TestBlockChainClient};
|
use ethcore::client::{TestBlockChainClient};
|
||||||
use ethstore::ethkey::{Generator, Random};
|
use ethstore::ethkey::{Generator, Random};
|
||||||
@ -46,7 +46,7 @@ impl Dependencies {
|
|||||||
miner: Arc::new(TestMinerService::default()),
|
miner: Arc::new(TestMinerService::default()),
|
||||||
client: Arc::new(TestBlockChainClient::default()),
|
client: Arc::new(TestBlockChainClient::default()),
|
||||||
sync: Arc::new(TestSyncProvider::new(Config {
|
sync: Arc::new(TestSyncProvider::new(Config {
|
||||||
network_id: U256::from(3),
|
network_id: 3,
|
||||||
num_peers: 120,
|
num_peers: 120,
|
||||||
})),
|
})),
|
||||||
logger: Arc::new(RotatingLogger::new("rpc=trace".to_owned())),
|
logger: Arc::new(RotatingLogger::new("rpc=trace".to_owned())),
|
||||||
|
@ -21,7 +21,7 @@ use v1::tests::helpers::{Config, TestSyncProvider};
|
|||||||
|
|
||||||
fn sync_provider() -> Arc<TestSyncProvider> {
|
fn sync_provider() -> Arc<TestSyncProvider> {
|
||||||
Arc::new(TestSyncProvider::new(Config {
|
Arc::new(TestSyncProvider::new(Config {
|
||||||
network_id: 3.into(),
|
network_id: 3,
|
||||||
num_peers: 120,
|
num_peers: 120,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
@ -201,8 +201,8 @@ fn sign_and_send_transaction() {
|
|||||||
data: vec![]
|
data: vec![]
|
||||||
};
|
};
|
||||||
tester.accounts.unlock_account_temporarily(address, "password123".into()).unwrap();
|
tester.accounts.unlock_account_temporarily(address, "password123".into()).unwrap();
|
||||||
let signature = tester.accounts.sign(address, None, t.hash()).unwrap();
|
let signature = tester.accounts.sign(address, None, t.hash(None)).unwrap();
|
||||||
let t = t.with_signature(signature);
|
let t = t.with_signature(signature, None);
|
||||||
|
|
||||||
let response = r#"{"jsonrpc":"2.0","result":""#.to_owned() + format!("0x{:?}", t.hash()).as_ref() + r#"","id":1}"#;
|
let response = r#"{"jsonrpc":"2.0","result":""#.to_owned() + format!("0x{:?}", t.hash()).as_ref() + r#"","id":1}"#;
|
||||||
|
|
||||||
@ -219,8 +219,8 @@ fn sign_and_send_transaction() {
|
|||||||
data: vec![]
|
data: vec![]
|
||||||
};
|
};
|
||||||
tester.accounts.unlock_account_temporarily(address, "password123".into()).unwrap();
|
tester.accounts.unlock_account_temporarily(address, "password123".into()).unwrap();
|
||||||
let signature = tester.accounts.sign(address, None, t.hash()).unwrap();
|
let signature = tester.accounts.sign(address, None, t.hash(None)).unwrap();
|
||||||
let t = t.with_signature(signature);
|
let t = t.with_signature(signature, None);
|
||||||
|
|
||||||
let response = r#"{"jsonrpc":"2.0","result":""#.to_owned() + format!("0x{:?}", t.hash()).as_ref() + r#"","id":1}"#;
|
let response = r#"{"jsonrpc":"2.0","result":""#.to_owned() + format!("0x{:?}", t.hash()).as_ref() + r#"","id":1}"#;
|
||||||
|
|
||||||
|
@ -186,8 +186,8 @@ fn should_confirm_transaction_and_dispatch() {
|
|||||||
data: vec![]
|
data: vec![]
|
||||||
};
|
};
|
||||||
tester.accounts.unlock_account_temporarily(address, "test".into()).unwrap();
|
tester.accounts.unlock_account_temporarily(address, "test".into()).unwrap();
|
||||||
let signature = tester.accounts.sign(address, None, t.hash()).unwrap();
|
let signature = tester.accounts.sign(address, None, t.hash(None)).unwrap();
|
||||||
let t = t.with_signature(signature);
|
let t = t.with_signature(signature, None);
|
||||||
|
|
||||||
assert_eq!(tester.signer.requests().len(), 1);
|
assert_eq!(tester.signer.requests().len(), 1);
|
||||||
|
|
||||||
|
@ -103,7 +103,7 @@ mod tests {
|
|||||||
fn test_serialize_block_transactions() {
|
fn test_serialize_block_transactions() {
|
||||||
let t = BlockTransactions::Full(vec![Transaction::default()]);
|
let t = BlockTransactions::Full(vec![Transaction::default()]);
|
||||||
let serialized = serde_json::to_string(&t).unwrap();
|
let serialized = serde_json::to_string(&t).unwrap();
|
||||||
assert_eq!(serialized, r#"[{"hash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"from":"0x0000000000000000000000000000000000000000","to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":"0x","creates":null,"raw":"0x","publicKey":null}]"#);
|
assert_eq!(serialized, r#"[{"hash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"from":"0x0000000000000000000000000000000000000000","to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":"0x","creates":null,"raw":"0x","publicKey":null,"v":0,"r":"0x0000000000000000000000000000000000000000000000000000000000000000","s":"0x0000000000000000000000000000000000000000000000000000000000000000"}]"#);
|
||||||
|
|
||||||
let t = BlockTransactions::Hashes(vec![H256::default().into()]);
|
let t = BlockTransactions::Hashes(vec![H256::default().into()]);
|
||||||
let serialized = serde_json::to_string(&t).unwrap();
|
let serialized = serde_json::to_string(&t).unwrap();
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use v1::types::{Log, H160, H256, U256};
|
use v1::types::{Log, H160, H256, H2048, U256};
|
||||||
use ethcore::receipt::{Receipt as EthReceipt, RichReceipt, LocalizedReceipt};
|
use ethcore::receipt::{Receipt as EthReceipt, RichReceipt, LocalizedReceipt};
|
||||||
|
|
||||||
/// Receipt
|
/// Receipt
|
||||||
@ -43,6 +43,12 @@ pub struct Receipt {
|
|||||||
pub contract_address: Option<H160>,
|
pub contract_address: Option<H160>,
|
||||||
/// Logs
|
/// Logs
|
||||||
pub logs: Vec<Log>,
|
pub logs: Vec<Log>,
|
||||||
|
/// State Root
|
||||||
|
#[serde(rename="root")]
|
||||||
|
pub state_root: H256,
|
||||||
|
/// Logs bloom
|
||||||
|
#[serde(rename="logsBloom")]
|
||||||
|
pub logs_bloom: H2048,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<LocalizedReceipt> for Receipt {
|
impl From<LocalizedReceipt> for Receipt {
|
||||||
@ -56,6 +62,8 @@ impl From<LocalizedReceipt> for Receipt {
|
|||||||
gas_used: Some(r.gas_used.into()),
|
gas_used: Some(r.gas_used.into()),
|
||||||
contract_address: r.contract_address.map(Into::into),
|
contract_address: r.contract_address.map(Into::into),
|
||||||
logs: r.logs.into_iter().map(Into::into).collect(),
|
logs: r.logs.into_iter().map(Into::into).collect(),
|
||||||
|
state_root: r.state_root.into(),
|
||||||
|
logs_bloom: r.log_bloom.into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -71,6 +79,8 @@ impl From<RichReceipt> for Receipt {
|
|||||||
gas_used: Some(r.gas_used.into()),
|
gas_used: Some(r.gas_used.into()),
|
||||||
contract_address: r.contract_address.map(Into::into),
|
contract_address: r.contract_address.map(Into::into),
|
||||||
logs: r.logs.into_iter().map(Into::into).collect(),
|
logs: r.logs.into_iter().map(Into::into).collect(),
|
||||||
|
state_root: r.state_root.into(),
|
||||||
|
logs_bloom: r.log_bloom.into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -86,6 +96,8 @@ impl From<EthReceipt> for Receipt {
|
|||||||
gas_used: None,
|
gas_used: None,
|
||||||
contract_address: None,
|
contract_address: None,
|
||||||
logs: r.logs.into_iter().map(Into::into).collect(),
|
logs: r.logs.into_iter().map(Into::into).collect(),
|
||||||
|
state_root: r.state_root.into(),
|
||||||
|
logs_bloom: r.log_bloom.into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -93,35 +105,36 @@ impl From<EthReceipt> for Receipt {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use serde_json;
|
use serde_json;
|
||||||
use std::str::FromStr;
|
use v1::types::{Log, Receipt};
|
||||||
use v1::types::{Log, Receipt, U256, H256, H160};
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn receipt_serialization() {
|
fn receipt_serialization() {
|
||||||
let s = r#"{"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x4510c","cumulativeGasUsed":"0x20","gasUsed":"0x10","contractAddress":null,"logs":[{"address":"0x33990122638b9132ca29c723bdf037f1a891a70c","topics":["0xa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc","0x4861736852656700000000000000000000000000000000000000000000000000"],"data":"0x","blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x4510c","transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","logIndex":"0x1","type":"mined"}]}"#;
|
let s = r#"{"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x4510c","cumulativeGasUsed":"0x20","gasUsed":"0x10","contractAddress":null,"logs":[{"address":"0x33990122638b9132ca29c723bdf037f1a891a70c","topics":["0xa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc","0x4861736852656700000000000000000000000000000000000000000000000000"],"data":"0x","blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x4510c","transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","logIndex":"0x1","type":"mined"}],"root":"0x000000000000000000000000000000000000000000000000000000000000000a","logsBloom":"0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f"}"#;
|
||||||
|
|
||||||
let receipt = Receipt {
|
let receipt = Receipt {
|
||||||
transaction_hash: Some(H256::from(0)),
|
transaction_hash: Some(0.into()),
|
||||||
transaction_index: Some(U256::from(0)),
|
transaction_index: Some(0.into()),
|
||||||
block_hash: Some(H256::from_str("ed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5").unwrap()),
|
block_hash: Some("ed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5".parse().unwrap()),
|
||||||
block_number: Some(U256::from(0x4510c)),
|
block_number: Some(0x4510c.into()),
|
||||||
cumulative_gas_used: U256::from(0x20),
|
cumulative_gas_used: 0x20.into(),
|
||||||
gas_used: Some(U256::from(0x10)),
|
gas_used: Some(0x10.into()),
|
||||||
contract_address: None,
|
contract_address: None,
|
||||||
logs: vec![Log {
|
logs: vec![Log {
|
||||||
address: H160::from_str("33990122638b9132ca29c723bdf037f1a891a70c").unwrap(),
|
address: "33990122638b9132ca29c723bdf037f1a891a70c".parse().unwrap(),
|
||||||
topics: vec![
|
topics: vec![
|
||||||
H256::from_str("a6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc").unwrap(),
|
"a6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc".parse().unwrap(),
|
||||||
H256::from_str("4861736852656700000000000000000000000000000000000000000000000000").unwrap(),
|
"4861736852656700000000000000000000000000000000000000000000000000".parse().unwrap(),
|
||||||
],
|
],
|
||||||
data: vec![].into(),
|
data: vec![].into(),
|
||||||
block_hash: Some(H256::from_str("ed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5").unwrap()),
|
block_hash: Some("ed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5".parse().unwrap()),
|
||||||
block_number: Some(U256::from(0x4510c)),
|
block_number: Some(0x4510c.into()),
|
||||||
transaction_hash: Some(H256::default()),
|
transaction_hash: Some(0.into()),
|
||||||
transaction_index: Some(U256::default()),
|
transaction_index: Some(0.into()),
|
||||||
log_index: Some(U256::from(1)),
|
log_index: Some(1.into()),
|
||||||
log_type: "mined".to_owned(),
|
log_type: "mined".into(),
|
||||||
}]
|
}],
|
||||||
|
logs_bloom: 15.into(),
|
||||||
|
state_root: 10.into(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let serialized = serde_json::to_string(&receipt).unwrap();
|
let serialized = serde_json::to_string(&receipt).unwrap();
|
||||||
|
@ -54,10 +54,17 @@ pub struct Transaction {
|
|||||||
/// Public key of the signer.
|
/// Public key of the signer.
|
||||||
#[serde(rename="publicKey")]
|
#[serde(rename="publicKey")]
|
||||||
pub public_key: Option<H512>,
|
pub public_key: Option<H512>,
|
||||||
|
/// The V field of the signature.
|
||||||
|
pub v: u8,
|
||||||
|
/// The R field of the signature.
|
||||||
|
pub r: H256,
|
||||||
|
/// The S field of the signature.
|
||||||
|
pub s: H256,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<LocalizedTransaction> for Transaction {
|
impl From<LocalizedTransaction> for Transaction {
|
||||||
fn from(t: LocalizedTransaction) -> Transaction {
|
fn from(t: LocalizedTransaction) -> Transaction {
|
||||||
|
let signature = t.signature();
|
||||||
Transaction {
|
Transaction {
|
||||||
hash: t.hash().into(),
|
hash: t.hash().into(),
|
||||||
nonce: t.nonce.into(),
|
nonce: t.nonce.into(),
|
||||||
@ -79,12 +86,16 @@ impl From<LocalizedTransaction> for Transaction {
|
|||||||
},
|
},
|
||||||
raw: ::rlp::encode(&t.signed).to_vec().into(),
|
raw: ::rlp::encode(&t.signed).to_vec().into(),
|
||||||
public_key: t.public_key().ok().map(Into::into),
|
public_key: t.public_key().ok().map(Into::into),
|
||||||
|
v: signature.v(),
|
||||||
|
r: signature.r().into(),
|
||||||
|
s: signature.s().into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<SignedTransaction> for Transaction {
|
impl From<SignedTransaction> for Transaction {
|
||||||
fn from(t: SignedTransaction) -> Transaction {
|
fn from(t: SignedTransaction) -> Transaction {
|
||||||
|
let signature = t.signature();
|
||||||
Transaction {
|
Transaction {
|
||||||
hash: t.hash().into(),
|
hash: t.hash().into(),
|
||||||
nonce: t.nonce.into(),
|
nonce: t.nonce.into(),
|
||||||
@ -106,6 +117,9 @@ impl From<SignedTransaction> for Transaction {
|
|||||||
},
|
},
|
||||||
raw: ::rlp::encode(&t).to_vec().into(),
|
raw: ::rlp::encode(&t).to_vec().into(),
|
||||||
public_key: t.public_key().ok().map(Into::into),
|
public_key: t.public_key().ok().map(Into::into),
|
||||||
|
v: signature.v(),
|
||||||
|
r: signature.r().into(),
|
||||||
|
s: signature.s().into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -119,7 +133,7 @@ mod tests {
|
|||||||
fn test_transaction_serialize() {
|
fn test_transaction_serialize() {
|
||||||
let t = Transaction::default();
|
let t = Transaction::default();
|
||||||
let serialized = serde_json::to_string(&t).unwrap();
|
let serialized = serde_json::to_string(&t).unwrap();
|
||||||
assert_eq!(serialized, r#"{"hash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"from":"0x0000000000000000000000000000000000000000","to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":"0x","creates":null,"raw":"0x","publicKey":null}"#);
|
assert_eq!(serialized, r#"{"hash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"from":"0x0000000000000000000000000000000000000000","to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":"0x","creates":null,"raw":"0x","publicKey":null,"v":0,"r":"0x0000000000000000000000000000000000000000000000000000000000000000","s":"0x0000000000000000000000000000000000000000000000000000000000000000"}"#);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ pub struct SyncConfig {
|
|||||||
/// Max blocks to download ahead
|
/// Max blocks to download ahead
|
||||||
pub max_download_ahead_blocks: usize,
|
pub max_download_ahead_blocks: usize,
|
||||||
/// Network ID
|
/// Network ID
|
||||||
pub network_id: U256,
|
pub network_id: usize,
|
||||||
/// Main "eth" subprotocol name.
|
/// Main "eth" subprotocol name.
|
||||||
pub subprotocol_name: [u8; 3],
|
pub subprotocol_name: [u8; 3],
|
||||||
/// Fork block to check
|
/// Fork block to check
|
||||||
@ -55,7 +55,7 @@ impl Default for SyncConfig {
|
|||||||
fn default() -> SyncConfig {
|
fn default() -> SyncConfig {
|
||||||
SyncConfig {
|
SyncConfig {
|
||||||
max_download_ahead_blocks: 20000,
|
max_download_ahead_blocks: 20000,
|
||||||
network_id: U256::from(1),
|
network_id: 1,
|
||||||
subprotocol_name: *b"eth",
|
subprotocol_name: *b"eth",
|
||||||
fork_block: None,
|
fork_block: None,
|
||||||
warp_sync: false,
|
warp_sync: false,
|
||||||
|
@ -188,7 +188,7 @@ pub struct SyncStatus {
|
|||||||
/// Syncing protocol version. That's the maximum protocol version we connect to.
|
/// Syncing protocol version. That's the maximum protocol version we connect to.
|
||||||
pub protocol_version: u8,
|
pub protocol_version: u8,
|
||||||
/// The underlying p2p network version.
|
/// The underlying p2p network version.
|
||||||
pub network_id: U256,
|
pub network_id: usize,
|
||||||
/// `BlockChain` height for the moment the sync started.
|
/// `BlockChain` height for the moment the sync started.
|
||||||
pub start_block_number: BlockNumber,
|
pub start_block_number: BlockNumber,
|
||||||
/// Last fully downloaded and imported block number (if any).
|
/// Last fully downloaded and imported block number (if any).
|
||||||
@ -269,7 +269,7 @@ struct PeerInfo {
|
|||||||
/// Peer chain genesis hash
|
/// Peer chain genesis hash
|
||||||
genesis: H256,
|
genesis: H256,
|
||||||
/// Peer network id
|
/// Peer network id
|
||||||
network_id: U256,
|
network_id: usize,
|
||||||
/// Peer best block hash
|
/// Peer best block hash
|
||||||
latest_hash: H256,
|
latest_hash: H256,
|
||||||
/// Peer total difficulty if known
|
/// Peer total difficulty if known
|
||||||
@ -328,7 +328,7 @@ pub struct ChainSync {
|
|||||||
/// Last propagated block number
|
/// Last propagated block number
|
||||||
last_sent_block_number: BlockNumber,
|
last_sent_block_number: BlockNumber,
|
||||||
/// Network ID
|
/// Network ID
|
||||||
network_id: U256,
|
network_id: usize,
|
||||||
/// Optional fork block to check
|
/// Optional fork block to check
|
||||||
fork_block: Option<(BlockNumber, H256)>,
|
fork_block: Option<(BlockNumber, H256)>,
|
||||||
/// Snapshot downloader.
|
/// Snapshot downloader.
|
||||||
@ -2145,7 +2145,7 @@ mod tests {
|
|||||||
PeerInfo {
|
PeerInfo {
|
||||||
protocol_version: 0,
|
protocol_version: 0,
|
||||||
genesis: H256::zero(),
|
genesis: H256::zero(),
|
||||||
network_id: U256::zero(),
|
network_id: 0,
|
||||||
latest_hash: peer_latest_hash,
|
latest_hash: peer_latest_hash,
|
||||||
difficulty: None,
|
difficulty: None,
|
||||||
asking: PeerAsking::Nothing,
|
asking: PeerAsking::Nothing,
|
||||||
|
@ -4,7 +4,7 @@ homepage = "http://ethcore.io"
|
|||||||
repository = "https://github.com/ethcore/parity"
|
repository = "https://github.com/ethcore/parity"
|
||||||
license = "GPL-3.0"
|
license = "GPL-3.0"
|
||||||
name = "ethcore-bigint"
|
name = "ethcore-bigint"
|
||||||
version = "0.1.1"
|
version = "0.1.2"
|
||||||
authors = ["Ethcore <admin@ethcore.io>"]
|
authors = ["Ethcore <admin@ethcore.io>"]
|
||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
|
|
||||||
|
@ -386,6 +386,12 @@ macro_rules! impl_hash {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a [u8]> for $from {
|
||||||
|
fn from(s: &'a [u8]) -> $from {
|
||||||
|
$from::from_slice(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ pub fn version() -> String {
|
|||||||
let date_dash = if commit_date.is_empty() { "" } else { "-" };
|
let date_dash = if commit_date.is_empty() { "" } else { "-" };
|
||||||
let env = Target::env();
|
let env = Target::env();
|
||||||
let env_dash = if env.is_empty() { "" } else { "-" };
|
let env_dash = if env.is_empty() { "" } else { "-" };
|
||||||
format!("Parity/v{}-unstable{}{}{}{}/{}-{}{}{}/rustc{}", env!("CARGO_PKG_VERSION"), sha3_dash, sha3, date_dash, commit_date, Target::arch(), Target::os(), env_dash, env, rustc_version())
|
format!("Parity/v{}-beta{}{}{}{}/{}-{}{}{}/rustc{}", env!("CARGO_PKG_VERSION"), sha3_dash, sha3, date_dash, commit_date, Target::arch(), Target::os(), env_dash, env, rustc_version())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the standard version data for this software.
|
/// Get the standard version data for this software.
|
||||||
|
@ -28,13 +28,17 @@ pub struct Histogram {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Histogram {
|
impl Histogram {
|
||||||
/// Histogram if a sorted corpus is at least fills the buckets.
|
/// Histogram of a sorted corpus if it at least spans the buckets. Bounds are left closed.
|
||||||
pub fn new(corpus: &[U256], bucket_number: usize) -> Option<Histogram> {
|
pub fn new(corpus: &[U256], bucket_number: usize) -> Option<Histogram> {
|
||||||
if corpus.len() <= bucket_number { return None; }
|
if corpus.len() < 1 { return None; }
|
||||||
let corpus_end = corpus.last().expect("there are at least bucket_number elements; qed").clone();
|
let corpus_end = corpus.last().expect("there is at least 1 element; qed").clone();
|
||||||
// If there are extremely few transactions, go from zero.
|
let corpus_start = corpus.first().expect("there is at least 1 element; qed").clone();
|
||||||
let corpus_start = corpus.first().expect("there are at least bucket_number elements; qed").clone();
|
// Bucket needs to be at least 1 wide.
|
||||||
let bucket_size = (corpus_end - corpus_start + 1.into()) / bucket_number.into();
|
let bucket_size = {
|
||||||
|
// Round up to get the entire corpus included.
|
||||||
|
let raw_bucket_size = (corpus_end - corpus_start + bucket_number.into()) / bucket_number.into();
|
||||||
|
if raw_bucket_size == 0.into() { 1.into() } else { raw_bucket_size }
|
||||||
|
};
|
||||||
let mut bucket_end = corpus_start + bucket_size;
|
let mut bucket_end = corpus_start + bucket_size;
|
||||||
|
|
||||||
let mut bucket_bounds = vec![corpus_start; bucket_number + 1];
|
let mut bucket_bounds = vec![corpus_start; bucket_number + 1];
|
||||||
@ -42,10 +46,12 @@ impl Histogram {
|
|||||||
let mut corpus_i = 0;
|
let mut corpus_i = 0;
|
||||||
// Go through the corpus adding to buckets.
|
// Go through the corpus adding to buckets.
|
||||||
for bucket in 0..bucket_number {
|
for bucket in 0..bucket_number {
|
||||||
while corpus[corpus_i] < bucket_end {
|
while corpus.get(corpus_i).map_or(false, |v| v < &bucket_end) {
|
||||||
|
// Initialized to size bucket_number above; iterates up to bucket_number; qed
|
||||||
counts[bucket] += 1;
|
counts[bucket] += 1;
|
||||||
corpus_i += 1;
|
corpus_i += 1;
|
||||||
}
|
}
|
||||||
|
// Initialized to size bucket_number + 1 above; iterates up to bucket_number; subscript is in range; qed
|
||||||
bucket_bounds[bucket + 1] = bucket_end;
|
bucket_bounds[bucket + 1] = bucket_end;
|
||||||
bucket_end = bucket_end + bucket_size;
|
bucket_end = bucket_end + bucket_size;
|
||||||
}
|
}
|
||||||
@ -62,14 +68,36 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn check_histogram() {
|
fn check_histogram() {
|
||||||
let hist = Histogram::new(&vec_into![643,689,1408,2000,2296,2512,4250,4320,4842,4958,5804,6065,6098,6354,7002,7145,7845,8589,8593,8895], 5).unwrap();
|
let hist = Histogram::new(&vec_into![643,689,1408,2000,2296,2512,4250,4320,4842,4958,5804,6065,6098,6354,7002,7145,7845,8589,8593,8895], 5).unwrap();
|
||||||
let correct_bounds: Vec<U256> = vec_into![643,2293,3943,5593,7243,8893];
|
let correct_bounds: Vec<U256> = vec_into![643, 2294, 3945, 5596, 7247, 8898];
|
||||||
assert_eq!(Histogram { bucket_bounds: correct_bounds, counts: vec![4,2,4,6,3] }, hist);
|
assert_eq!(Histogram { bucket_bounds: correct_bounds, counts: vec![4,2,4,6,4] }, hist);
|
||||||
|
|
||||||
assert!(Histogram::new(&vec_into![1, 2], 5).is_none());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_not_panic_when_asking_for_bucket_too_big() {
|
fn smaller_data_range_than_bucket_range() {
|
||||||
assert!(Histogram::new(&vec_into![1, 2], 2).is_none());
|
assert_eq!(
|
||||||
|
Histogram::new(&vec_into![1, 2, 2], 3),
|
||||||
|
Some(Histogram { bucket_bounds: vec_into![1, 2, 3, 4], counts: vec![1, 2, 0] })
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn data_range_is_not_multiple_of_bucket_range() {
|
||||||
|
assert_eq!(
|
||||||
|
Histogram::new(&vec_into![1, 2, 5], 2),
|
||||||
|
Some(Histogram { bucket_bounds: vec_into![1, 4, 7], counts: vec![2, 1] })
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn data_range_is_multiple_of_bucket_range() {
|
||||||
|
assert_eq!(
|
||||||
|
Histogram::new(&vec_into![1, 2, 6], 2),
|
||||||
|
Some(Histogram { bucket_bounds: vec_into![1, 4, 7], counts: vec![2, 1] })
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn none_when_too_few_data() {
|
||||||
|
assert!(Histogram::new(&vec_into![], 1).is_none());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,8 +69,12 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
|
|||||||
UNREFERENCED_PARAMETER(lpCmdLine);
|
UNREFERENCED_PARAMETER(lpCmdLine);
|
||||||
|
|
||||||
CreateMutex(0, FALSE, _T("Local\\ParityTray"));
|
CreateMutex(0, FALSE, _T("Local\\ParityTray"));
|
||||||
if (GetLastError() == ERROR_ALREADY_EXISTS)
|
if (GetLastError() == ERROR_ALREADY_EXISTS) {
|
||||||
return -1;
|
// open the UI
|
||||||
|
OpenUI();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
|
LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
|
||||||
LoadStringW(hInstance, IDC_PTRAY, szWindowClass, MAX_LOADSTRING);
|
LoadStringW(hInstance, IDC_PTRAY, szWindowClass, MAX_LOADSTRING);
|
||||||
|
Loading…
Reference in New Issue
Block a user