diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index bbfb7927e0b..b0a665a3980 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -226,6 +226,8 @@ build-windows-msvc-x86_64: package-linux-snap-amd64: &package_snap stage: package only: *releaseable_branches + except: + - master image: parity/snapcraft:gitlab-ci cache: {} before_script: *determine_version diff --git a/Cargo.lock b/Cargo.lock index 3c7c5c79daf..877d800cc38 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -643,7 +643,7 @@ dependencies = [ "rlp_derive 0.1.0", "serde 1.0.78 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.78 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "stats 0.1.0", "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "triehash-ethereum 0.2.0", @@ -690,7 +690,7 @@ dependencies = [ "rlp 0.3.0-beta.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "trace-time 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "transaction-pool 1.13.2 (registry+https://github.com/rust-lang/crates.io-index)", + "transaction-pool 1.13.3 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -780,7 +780,7 @@ dependencies = [ "serde_derive 1.0.78 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "transaction-pool 1.13.2 (registry+https://github.com/rust-lang/crates.io-index)", + "transaction-pool 1.13.3 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -877,7 +877,6 @@ dependencies = [ "fastmap 0.1.0", "hashdb 0.3.0-beta.0 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ipnetwork 0.12.8 (registry+https://github.com/rust-lang/crates.io-index)", "keccak-hash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "keccak-hasher 0.1.1", "kvdb 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -889,8 +888,6 @@ dependencies = [ "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "rlp 0.3.0-beta.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "trace-time 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "triehash-ethereum 0.2.0", ] @@ -997,7 +994,7 @@ dependencies = [ "serde 1.0.78 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.78 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2251,7 +2248,7 @@ dependencies = [ "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "transaction-pool 1.13.2 (registry+https://github.com/rust-lang/crates.io-index)", + "transaction-pool 1.13.3 (registry+https://github.com/rust-lang/crates.io-index)", "transient-hashmap 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "vm 0.1.0", ] @@ -2378,7 +2375,7 @@ dependencies = [ "serde_derive 1.0.78 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3030,14 +3027,6 @@ name = "smallvec" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "smallvec" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "smallvec" version = "0.6.5" @@ -3492,12 +3481,12 @@ dependencies = [ [[package]] name = "transaction-pool" -version = "1.13.2" +version = "1.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "trace-time 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -4088,7 +4077,6 @@ dependencies = [ "checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23" "checksum slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5f9776d6b986f77b35c6cf846c11ad986ff128fe0b2b63a3628e3755e8d3102d" "checksum smallvec 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4c8cbcd6df1e117c2210e13ab5109635ad68a929fcbb8964dc965b76cb5ee013" -"checksum smallvec 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f90c5e5fe535e48807ab94fc611d323935f39d4660c52b26b96446a7b33aef10" "checksum smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "153ffa32fd170e9944f7e0838edf824a754ec4c1fc64746fcc9fe1f8fa602e5d" "checksum socket2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c4d11a52082057d87cb5caa31ad812f4504b97ab44732cd8359df2e9ff9f48e7" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" @@ -4132,7 +4120,7 @@ dependencies = [ "checksum tokio-uds 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "424c1ed15a0132251813ccea50640b224c809d6ceafb88154c1a8775873a0e89" "checksum toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a0263c6c02c4db6c8f7681f9fd35e90de799ebd4cfdeab77a38f4ff6b3d8c0d9" "checksum trace-time 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe82f2f0bf1991e163e757baf044282823155dd326e70f44ce2186c3c320cc9" -"checksum transaction-pool 1.13.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fdb8870eea404a57e2f62056ac45067a53a6207fd31866122356481d3c2e1a30" +"checksum transaction-pool 1.13.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e5866e5126b14358f1d7af4bf51a0be677a363799b90e655edcec8254edef1d2" "checksum transient-hashmap 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aeb4b191d033a35edfce392a38cdcf9790b6cebcb30fa690c312c29da4dc433e" "checksum trezor-sys 1.0.0 (git+https://github.com/paritytech/trezor-sys)" = "" "checksum trie-standardmap 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0e26f52976a57a0859616d6fcec87092ac35d08eabbd78dc3dabee93b480ea5f" diff --git a/Cargo.toml b/Cargo.toml index 180c98d9c2a..b321c803966 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -89,6 +89,7 @@ daemonize = { git = "https://github.com/paritytech/daemonize" } [features] miner-debug = ["ethcore/miner-debug"] json-tests = ["ethcore/json-tests"] +ci-skip-issue = ["ethcore/ci-skip-issue"] test-heavy = ["ethcore/test-heavy"] evm-debug = ["ethcore/evm-debug"] evm-debug-tests = ["ethcore/evm-debug-tests"] diff --git a/ethcore/Cargo.toml b/ethcore/Cargo.toml index 2f0637c4ec9..2bf5795e08a 100644 --- a/ethcore/Cargo.toml +++ b/ethcore/Cargo.toml @@ -102,6 +102,8 @@ evm-debug-tests = ["evm-debug", "evm/evm-debug-tests"] slow-blocks = [] # Run JSON consensus tests. json-tests = ["ethcore-transaction/json-tests", "test-helpers", "tempdir"] +# Skip JSON consensus tests with pending issues. +ci-skip-issue = [] # Run memory/cpu heavy tests. test-heavy = [] # Compile benches diff --git a/ethcore/light/Cargo.toml b/ethcore/light/Cargo.toml index ddbd08cdd31..8b9071b0079 100644 --- a/ethcore/light/Cargo.toml +++ b/ethcore/light/Cargo.toml @@ -23,7 +23,7 @@ vm = { path = "../vm" } fastmap = { path = "../../util/fastmap" } rlp = { version = "0.3.0-beta", features = ["ethereum"] } rlp_derive = { path = "../../util/rlp_derive" } -smallvec = "0.4" +smallvec = "0.6" futures = "0.1" rand = "0.4" itertools = "0.5" diff --git a/ethcore/light/src/provider.rs b/ethcore/light/src/provider.rs index 2ac3ebd9178..72344620653 100644 --- a/ethcore/light/src/provider.rs +++ b/ethcore/light/src/provider.rs @@ -176,7 +176,7 @@ impl Provider for T { } fn block_receipts(&self, req: request::CompleteReceiptsRequest) -> Option { - BlockChainClient::block_receipts(self, &req.hash) + BlockChainClient::encoded_block_receipts(self, &req.hash) .map(|x| ::request::ReceiptsResponse { receipts: ::rlp::decode_list(&x) }) } diff --git a/ethcore/res/ethereum/constantinople_test.json b/ethcore/res/ethereum/constantinople_test.json index 6169b743eff..888eda466f9 100644 --- a/ethcore/res/ethereum/constantinople_test.json +++ b/ethcore/res/ethereum/constantinople_test.json @@ -6,7 +6,10 @@ "minimumDifficulty": "0x020000", "difficultyBoundDivisor": "0x0800", "durationLimit": "0x0d", - "blockReward": "0x1BC16D674EC80000", + "blockReward": { + "0": "0x29A2241AF62C0000", + "5": "0x1BC16D674EC80000" + }, "homesteadTransition": "0x0", "eip100bTransition": "0x0", "difficultyBombDelays": { @@ -58,9 +61,9 @@ "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 } } } }, - "0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": "0x00", "pricing": { "modexp": { "divisor": 100 } } } }, + "0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": "0x00", "pricing": { "modexp": { "divisor": 20 } } } }, "0000000000000000000000000000000000000006": { "builtin": { "name": "alt_bn128_add", "activate_at": "0x00", "pricing": { "linear": { "base": 500, "word": 0 } } } }, - "0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": "0x00", "pricing": { "linear": { "base": 2000, "word": 0 } } } }, + "0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": "0x00", "pricing": { "linear": { "base": 40000, "word": 0 } } } }, "0000000000000000000000000000000000000008": { "builtin": { "name": "alt_bn128_pairing", "activate_at": "0x00", "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } } } } diff --git a/ethcore/res/ethereum/poasokol.json b/ethcore/res/ethereum/poasokol.json index 443ebbed0e4..c6d51a9c8a6 100644 --- a/ethcore/res/ethereum/poasokol.json +++ b/ethcore/res/ethereum/poasokol.json @@ -18,9 +18,14 @@ }, "509355": { "safeContract": "0x03048F666359CFD3C74a1A5b9a97848BF71d5038" + }, + "4622420": { + "safeContract": "0x4c6a159659CCcb033F4b2e2Be0C16ACC62b89DDB" } } - } + }, + "blockRewardContractAddress": "0x3145197AD50D7083D0222DE4fCCf67d9BD05C30D", + "blockRewardContractTransition": 4639000 } } }, diff --git a/ethcore/res/ethereum/tests-issues/currents.json b/ethcore/res/ethereum/tests-issues/currents.json new file mode 100644 index 00000000000..371211cab82 --- /dev/null +++ b/ethcore/res/ethereum/tests-issues/currents.json @@ -0,0 +1,370 @@ +{ "block": + [ + { + "reference": "9590", + "failing": "stCreateTest", + "subtests": [ + "CreateOOGafterInitCodeReturndata2_d0g1v0_Constantinople" + ] + }, + { + "reference": "9590", + "failing": "stCreate2", + "subtests": [ + "RevertDepthCreateAddressCollision_d0g1v0_Constantinople", + "RevertDepthCreateAddressCollision_d1g1v1_Constantinople", + "CREATE2_Suicide_d5g0v0_Constantinople", + "CREATE2_Suicide_d7g0v0_Constantinople", + "create2collisionSelfdestructedOOG_d2g0v0_Byzantium", + "create2collisionSelfdestructedOOG_d2g0v0_Constantinople", + "create2collisionNonce_d1g0v0_Byzantium", + "create2collisionNonce_d1g0v0_Constantinople", + "CreateMessageRevertedOOGInInit_d0g1v0_Constantinople", + "create2callPrecompiles_d3g0v0_Constantinople", + "create2collisionCode_d1g0v0_Byzantium", + "create2collisionCode_d1g0v0_Constantinople", + "create2collisionStorage_d0g0v0_Byzantium", + "create2collisionStorage_d0g0v0_Constantinople", + "create2callPrecompiles_d4g0v0_Constantinople", + "create2collisionSelfdestructedRevert_d0g0v0_Byzantium", + "create2collisionSelfdestructedRevert_d0g0v0_Constantinople", + "CreateMessageReverted_d0g1v0_Constantinople", + "RevertOpcodeCreate_d0g1v0_Constantinople", + "CREATE2_Suicide_d11g0v0_Constantinople", + "create2checkFieldsInInitcode_d5g0v0_Constantinople", + "create2collisionSelfdestructedOOG_d1g0v0_Byzantium", + "create2collisionSelfdestructedOOG_d1g0v0_Constantinople", + "returndatacopy_following_create_d1g0v0_Constantinople", + "RevertDepthCreate2OOG_d1g1v1_Constantinople", + "create2collisionSelfdestructed_d2g0v0_Byzantium", + "create2collisionSelfdestructed_d2g0v0_Constantinople", + "create2callPrecompiles_d2g0v0_Constantinople", + "create2InitCodes_d2g0v0_Constantinople", + "create2collisionNonce_d2g0v0_Byzantium", + "create2collisionNonce_d2g0v0_Constantinople", + "create2collisionCode_d0g0v0_Byzantium", + "create2collisionCode_d0g0v0_Constantinople", + "CREATE2_Bounds_d0g0v0_Constantinople", + "RevertDepthCreate2OOG_d0g0v0_Constantinople", + "CREATE2_Suicide_d1g0v0_Constantinople", + "CREATE2_Bounds3_d0g1v0_Constantinople", + "create2collisionStorage_d2g0v0_Byzantium", + "create2collisionStorage_d2g0v0_Constantinople", + "RevertDepthCreateAddressCollision_d0g0v1_Constantinople", + "create2callPrecompiles_d5g0v0_Constantinople", + "create2collisionCode2_d0g0v0_Byzantium", + "create2collisionCode2_d0g0v0_Constantinople", + "create2noCash_d0g0v0_Byzantium", + "create2noCash_d0g0v0_Constantinople", + "create2checkFieldsInInitcode_d7g0v0_Constantinople", + "create2SmartInitCode_d1g0v0_Constantinople", + "create2InitCodes_d6g0v0_Constantinople", + "create2noCash_d1g0v0_Byzantium", + "create2noCash_d1g0v0_Constantinople", + "CREATE2_ContractSuicideDuringInit_ThenStoreThenReturn_d0g0v0_Constantinople", + "RevertOpcodeInCreateReturns_d0g0v0_Constantinople", + "create2collisionStorage_d1g0v0_Byzantium", + "create2collisionStorage_d1g0v0_Constantinople", + "create2checkFieldsInInitcode_d3g0v0_Constantinople", + "create2collisionBalance_d0g0v0_Byzantium", + "create2collisionBalance_d0g0v0_Constantinople", + "create2collisionSelfdestructed2_d0g0v0_Constantinople", + "create2InitCodes_d3g0v0_Constantinople", + "create2collisionCode2_d1g0v0_Byzantium", + "create2collisionCode2_d1g0v0_Constantinople", + "create2checkFieldsInInitcode_d1g0v0_Constantinople", + "create2collisionBalance_d1g0v0_Byzantium", + "create2collisionBalance_d1g0v0_Constantinople", + "CREATE2_Bounds3_d0g2v0_Constantinople", + "create2callPrecompiles_d6g0v0_Constantinople", + "Create2Recursive_d0g0v0_Constantinople", + "create2collisionSelfdestructedOOG_d0g0v0_Byzantium", + "create2collisionSelfdestructedOOG_d0g0v0_Constantinople", + "CREATE2_Suicide_d3g0v0_Constantinople", + "returndatacopy_following_create_d0g0v0_Constantinople", + "create2InitCodes_d8g0v0_Constantinople", + "RevertDepthCreate2OOG_d0g0v1_Constantinople", + "create2checkFieldsInInitcode_d2g0v0_Constantinople", + "RevertDepthCreate2OOG_d1g0v1_Constantinople", + "Create2OnDepth1024_d0g0v0_Constantinople", + "create2collisionSelfdestructed2_d1g0v0_Constantinople", + "create2collisionSelfdestructedRevert_d2g0v0_Byzantium", + "create2collisionSelfdestructedRevert_d2g0v0_Constantinople", + "create2callPrecompiles_d0g0v0_Constantinople", + "RevertDepthCreateAddressCollision_d0g1v1_Constantinople", + "create2collisionSelfdestructed_d1g0v0_Byzantium", + "create2collisionSelfdestructed_d1g0v0_Constantinople", + "call_outsize_then_create2_successful_then_returndatasize_d0g0v0_Byzantium", + "call_outsize_then_create2_successful_then_returndatasize_d0g0v0_Constantinople", + "Create2OOGafterInitCodeRevert_d0g0v0_Constantinople", + "Create2OOGafterInitCodeReturndata3_d0g0v0_Constantinople", + "Create2OOGafterInitCodeReturndataSize_d0g0v0_Constantinople", + "create2InitCodes_d7g0v0_Constantinople", + "CREATE2_Suicide_d10g0v0_Constantinople", + "RevertDepthCreate2OOG_d0g1v0_Constantinople", + "create2InitCodes_d5g0v0_Constantinople", + "create2collisionSelfdestructedRevert_d1g0v0_Byzantium", + "create2collisionSelfdestructedRevert_d1g0v0_Constantinople", + "RevertDepthCreate2OOG_d1g1v0_Constantinople", + "create2collisionSelfdestructed_d0g0v0_Byzantium", + "create2collisionSelfdestructed_d0g0v0_Constantinople", + "create2noCash_d2g0v0_Byzantium", + "create2noCash_d2g0v0_Constantinople", + "CREATE2_Bounds3_d0g0v0_Constantinople", + "create2collisionNonce_d0g0v0_Byzantium", + "create2collisionNonce_d0g0v0_Constantinople", + "CREATE2_Suicide_d2g0v0_Constantinople", + "Create2OOGafterInitCode_d0g0v0_Constantinople", + "call_then_create2_successful_then_returndatasize_d0g0v0_Byzantium", + "call_then_create2_successful_then_returndatasize_d0g0v0_Constantinople", + "create2collisionBalance_d2g0v0_Byzantium", + "create2collisionBalance_d2g0v0_Constantinople", + "create2checkFieldsInInitcode_d6g0v0_Constantinople", + "RevertDepthCreate2OOG_d0g1v1_Constantinople", + "returndatacopy_afterFailing_create_d0g0v0_Constantinople", + "returndatacopy_following_revert_in_create_d0g0v0_Constantinople", + "CREATE2_Suicide_d9g0v0_Constantinople", + "create2callPrecompiles_d7g0v0_Constantinople", + "RevertDepthCreateAddressCollision_d1g0v1_Constantinople", + "create2InitCodes_d1g0v0_Constantinople", + "CREATE2_Bounds_d0g1v0_Constantinople", + "Create2OOGafterInitCodeReturndata_d0g0v0_Constantinople", + "create2checkFieldsInInitcode_d4g0v0_Constantinople", + "CreateMessageRevertedOOGInInit_d0g0v0_Constantinople", + "RevertDepthCreateAddressCollision_d1g1v0_Constantinople", + "returndatacopy_following_successful_create_d0g0v0_Constantinople", + "create2checkFieldsInInitcode_d0g0v0_Constantinople", + "CreateMessageReverted_d0g0v0_Constantinople", + "create2SmartInitCode_d0g0v0_Constantinople", + "CREATE2_Bounds2_d0g0v0_Constantinople", + "returndatasize_following_successful_create_d0g0v0_Constantinople", + "CREATE2_Bounds2_d0g1v0_Constantinople", + "returndatacopy_0_0_following_successful_create_d0g0v0_Constantinople", + "RevertDepthCreateAddressCollision_d0g0v0_Constantinople", + "CREATE2_Suicide_d0g0v0_Constantinople", + "create2InitCodes_d0g0v0_Constantinople", + "Create2OnDepth1023_d0g0v0_Constantinople", + "create2InitCodes_d4g0v0_Constantinople", + "Create2OOGafterInitCodeReturndata2_d0g0v0_Constantinople", + "create2collisionBalance_d3g0v0_Byzantium", + "create2collisionBalance_d3g0v0_Constantinople", + "CREATE2_Suicide_d4g0v0_Constantinople", + "Create2OOGafterInitCode_d0g1v0_Constantinople", + "RevertDepthCreateAddressCollision_d1g0v0_Constantinople", + "Create2OOGafterInitCodeRevert2_d0g0v0_Constantinople", + "Create2OOGafterInitCodeReturndata_d0g1v0_Constantinople", + "Create2Recursive_d0g1v0_Constantinople", + "create2collisionCode_d2g0v0_Byzantium", + "create2collisionCode_d2g0v0_Constantinople", + "CREATE2_Suicide_d6g0v0_Constantinople", + "CREATE2_Suicide_d8g0v0_Constantinople", + "RevertOpcodeCreate_d0g0v0_Constantinople", + "Create2OOGafterInitCodeReturndata2_d0g1v0_Constantinople", + "create2callPrecompiles_d1g0v0_Constantinople", + "RevertInCreateInInit_d0g0v0_Constantinople", + "RevertDepthCreate2OOG_d1g0v0_Constantinople" + ] + }, + { + "reference": "9590", + "failing": "bcStateTest", + "subtests": [ + "suicideStorageCheck_Byzantium", + "suicideStorageCheck_Constantinople", + "suicideStorageCheckVCreate2_Byzantium", + "suicideStorageCheckVCreate2_Constantinople", + "create2collisionwithSelfdestructSameBlock_Constantinople", + "blockhashNonConstArg_Constantinople", + "suicideThenCheckBalance_Constantinople", + "suicideThenCheckBalance_Homestead", + "suicideStorageCheckVCreate_Byzantium", + "suicideStorageCheckVCreate_Constantinople" + ] + }, + { + "reference": "9590", + "failing": "stEIP158Specific", + "subtests": [ + "callToEmptyThenCallError_d0g0v0_Byzantium", + "callToEmptyThenCallError_d0g0v0_Constantinople", + "callToEmptyThenCallError_d0g0v0_EIP158" + ] + }, + { + "reference": "9590", + "failing": "stPreCompiledContracts", + "subtests": [ + "identity_to_smaller_d0g0v0_Constantinople", + "identity_to_bigger_d0g0v0_Constantinople" + ] + }, + { + "reference": "9590", + "failing": "stReturnDataTest", + "subtests": [ + "modexp_modsize0_returndatasize_d0g1v0_Constantinople", + "modexp_modsize0_returndatasize_d0g2v0_Constantinople", + "modexp_modsize0_returndatasize_d0g3v0_Constantinople" + ] + }, + { + "reference": "9590", + "failing": "stSpecialTest", + "subtests": [ + "push32withoutByte_d0g0v0_Constantinople" + ] + } + + ], + "state": + [ + { + "reference": "9590", + "failing": "stCreateTest", + "subtests": { + "CreateOOGafterInitCodeReturndata2": { + "subnumbers": ["2"], + "chain": "Constantinople (test)" + } + } + }, + { + "reference": "9590", + "failing": "stCreate2Test", + "subtests": { + "RevertInCreateInInit": { + "subnumbers": ["1"], + "chain": "Constantinople (test)" + } + } + }, + { + "reference": "9590", + "failing": "stEIP150Specific", + "subtests": { + "NewGasPriceForCodes": { + "subnumbers": ["1"], + "chain": "Constantinople (test)" + } + } + }, + { + "reference": "9590", + "failing": "stInitCodeTest", + "subtests": { + "OutOfGasContractCreation": { + "subnumbers": ["4"], + "chain": "Constantinople (test)" + } + } + }, + { + "reference": "9590", + "failing": "stPreCompiledContracts", + "subtests": { + "modexp": { + "subnumbers": ["*"], + "chain": "Constantinople (test)" + } + } + }, + { + "reference": "9590", + "failing": "stRevertTest", + "subtests": { + "LoopCallsDepthThenRevert3": { + "subnumbers": ["1"], + "chain": "Constantinople (test)" + }, + "RevertOpcodeCreate": { + "subnumbers": ["1"], + "chain": "Constantinople (test)" + }, + "RevertSubCallStorageOOG2": { + "subnumbers": ["1","3"], + "chain": "Constantinople (test)" + }, + "RevertDepthCreateOOG": { + "subnumbers": ["3","4"], + "chain": "Constantinople (test)" + }, + "RevertOpcodeMultipleSubCalls": { + "subnumbers": ["*"], + "chain": "Constantinople (test)" + }, + "RevertOpcodeDirectCall": { + "subnumbers": ["1","2"], + "chain": "Constantinople (test)" + }, + "LoopCallsDepthThenRevert2": { + "subnumbers": ["1"], + "chain": "Constantinople (test)" + }, + "RevertDepth2": { + "subnumbers": ["1"], + "chain": "Constantinople (test)" + }, + "RevertRemoteSubCallStorageOOG2": { + "subnumbers": ["1","2"], + "chain": "Constantinople (test)" + }, + "RevertDepthCreateAddressCollision": { + "subnumbers": ["3","4"], + "chain": "Constantinople (test)" + } + } + }, + { + "reference": "9590", + "failing": "stStaticCall", + "subtests": { + "static_RevertDepth2": { + "subnumbers": ["1","3"], + "chain": "Constantinople (test)" + }, + "static_CheckOpcodes4": { + "subnumbers": ["3"], + "chain": "Constantinople (test)" + }, + "static_CheckOpcodes3": { + "subnumbers": ["5","6","7","8"], + "chain": "Constantinople (test)" + }, + "static_callBasic": { + "subnumbers": ["1","2"], + "chain": "Constantinople (test)" + }, + "static_CheckOpcodes2": { + "subnumbers": ["5","6","7","8"], + "chain": "Constantinople (test)" + }, + "static_callCreate": { + "subnumbers": ["2"], + "chain": "Constantinople (test)" + } + } + }, + { + "reference": "https://github.com/ethereum/tests/issues/512", + "failing": "stZeroKnowledge", + "subtests": { + "pointAddTrunc": { + "subnumbers": ["*"], + "chain": "Constantinople (test)" + }, + "pointAdd": { + "subnumbers": ["*"], + "chain": "Constantinople (test)" + }, + "pointMulAdd": { + "subnumbers": ["*"], + "chain": "Constantinople (test)" + }, + "pointMulAdd2": { + "subnumbers": ["*"], + "chain": "Constantinople (test)" + } + } + } + ] +} diff --git a/ethcore/src/blockchain/blockchain.rs b/ethcore/src/blockchain/blockchain.rs index d9448286f1f..5785aa10343 100644 --- a/ethcore/src/blockchain/blockchain.rs +++ b/ethcore/src/blockchain/blockchain.rs @@ -160,11 +160,6 @@ pub trait BlockProvider { .and_then(|n| body.view().localized_transaction_at(&address.block_hash, n, address.index))) } - /// Get transaction receipt. - fn transaction_receipt(&self, address: &TransactionAddress) -> Option { - self.block_receipts(&address.block_hash).and_then(|br| br.receipts.into_iter().nth(address.index)) - } - /// Get a list of transactions for a given block. /// Returns None if block does not exist. fn transactions(&self, hash: &H256) -> Option> { diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 01fe1b1b957..cc7d2af2111 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -294,7 +294,6 @@ impl Importer { continue; } - let raw = block.bytes.clone(); match self.check_and_lock_block(block, client) { Ok(closed_block) => { if self.engine.is_proposal(&header) { @@ -312,8 +311,8 @@ impl Importer { } }, Err(err) => { - self.bad_blocks.report(raw, format!("{:?}", err)); - invalid_blocks.insert(header.hash()); + self.bad_blocks.report(bytes, format!("{:?}", err)); + invalid_blocks.insert(hash); }, } } @@ -354,7 +353,7 @@ impl Importer { imported } - fn check_and_lock_block(&self, block: PreverifiedBlock, client: &Client) -> Result { + fn check_and_lock_block(&self, block: PreverifiedBlock, client: &Client) -> EthcoreResult { let engine = &*self.engine; let header = block.header.clone(); @@ -362,7 +361,7 @@ impl Importer { let best_block_number = client.chain.read().best_block_number(); if client.pruning_info().earliest_state > header.number() { warn!(target: "client", "Block import failed for #{} ({})\nBlock is ancient (current best block: #{}).", header.number(), header.hash(), best_block_number); - return Err(()); + bail!("Block is ancient"); } // Check if parent is in chain @@ -370,7 +369,7 @@ impl Importer { Some(h) => h, None => { warn!(target: "client", "Block import failed for #{} ({}): Parent not found ({}) ", header.number(), header.hash(), header.parent_hash()); - return Err(()); + bail!("Parent not found"); } }; @@ -389,13 +388,13 @@ impl Importer { if let Err(e) = verify_family_result { warn!(target: "client", "Stage 3 block verification failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e); - return Err(()); + bail!(e); }; let verify_external_result = self.verifier.verify_block_external(&header, engine); if let Err(e) = verify_external_result { warn!(target: "client", "Stage 4 block verification failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e); - return Err(()); + bail!(e); }; // Enact Verified Block @@ -415,9 +414,13 @@ impl Importer { &mut chain.ancestry_with_metadata_iter(*header.parent_hash()), ); - let mut locked_block = enact_result.map_err(|e| { - warn!(target: "client", "Block import failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e); - })?; + let mut locked_block = match enact_result { + Ok(b) => b, + Err(e) => { + warn!(target: "client", "Block import failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e); + bail!(e); + } + }; // Strip receipts for blocks before validate_receipts_transition, // if the expected receipts root header does not match. @@ -431,7 +434,7 @@ impl Importer { // Final Verification if let Err(e) = self.verifier.verify_block_final(&header, locked_block.block().header()) { warn!(target: "client", "Stage 5 block verification failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e); - return Err(()); + bail!(e); } Ok(locked_block) @@ -441,7 +444,7 @@ impl Importer { /// /// The block is guaranteed to be the next best blocks in the /// first block sequence. Does no sealing or transaction validation. - fn import_old_block(&self, unverified: Unverified, receipts_bytes: &[u8], db: &KeyValueDB, chain: &BlockChain) -> Result<(), ::error::Error> { + fn import_old_block(&self, unverified: Unverified, receipts_bytes: &[u8], db: &KeyValueDB, chain: &BlockChain) -> EthcoreResult<()> { let receipts = ::rlp::decode_list(receipts_bytes); let _import_lock = self.import_lock.lock(); @@ -1489,7 +1492,7 @@ impl Call for Client { let sender = t.sender(); let options = || TransactOptions::with_tracing().dont_check_nonce(); - let cond = |gas| { + let exec = |gas| { let mut tx = t.as_unsigned().clone(); tx.gas = gas; let tx = tx.fake_sign(sender); @@ -1497,22 +1500,28 @@ impl Call for Client { let mut clone = state.clone(); let machine = self.engine.machine(); let schedule = machine.schedule(env_info.number); - Ok(Executive::new(&mut clone, &env_info, &machine, &schedule) + Executive::new(&mut clone, &env_info, &machine, &schedule) .transact_virtual(&tx, options()) + .ok() .map(|r| r.exception.is_none()) - .unwrap_or(false)) }; - if !cond(upper)? { + let cond = |gas| exec(gas).unwrap_or(false); + + if !cond(upper) { upper = max_upper; - if !cond(upper)? { - trace!(target: "estimate_gas", "estimate_gas failed with {}", upper); - let err = ExecutionError::Internal(format!("Requires higher than upper limit of {}", upper)); - return Err(err.into()) + match exec(upper) { + Some(false) => return Err(CallError::Exceptional), + None => { + trace!(target: "estimate_gas", "estimate_gas failed with {}", upper); + let err = ExecutionError::Internal(format!("Requires higher than upper limit of {}", upper)); + return Err(err.into()) + }, + _ => {}, } } let lower = t.gas_required(&self.engine.schedule(env_info.number)).into(); - if cond(lower)? { + if cond(lower) { trace!(target: "estimate_gas", "estimate_gas succeeded with {}", lower); return Ok(lower) } @@ -1521,12 +1530,12 @@ impl Call for Client { /// Returns the lowest value between `lower` and `upper` for which `cond` returns true. /// We assert: `cond(lower) = false`, `cond(upper) = true` fn binary_chop(mut lower: U256, mut upper: U256, mut cond: F) -> Result - where F: FnMut(U256) -> Result + where F: FnMut(U256) -> bool { while upper - lower > 1.into() { let mid = (lower + upper) / 2; trace!(target: "estimate_gas", "{} .. {} .. {}", lower, mid, upper); - let c = cond(mid)?; + let c = cond(mid); match c { true => upper = mid, false => lower = mid, @@ -1783,26 +1792,49 @@ impl BlockChainClient for Client { } fn transaction_receipt(&self, id: TransactionId) -> Option { + // NOTE Don't use block_receipts here for performance reasons + let address = self.transaction_address(id)?; + let hash = address.block_hash; let chain = self.chain.read(); - self.transaction_address(id) - .and_then(|address| chain.block_number(&address.block_hash).and_then(|block_number| { - let transaction = chain.block_body(&address.block_hash) - .and_then(|body| body.view().localized_transaction_at(&address.block_hash, block_number, address.index)); - - let previous_receipts = (0..address.index + 1) - .map(|index| { - let mut address = address.clone(); - address.index = index; - chain.transaction_receipt(&address) - }) - .collect(); - match (transaction, previous_receipts) { - (Some(transaction), Some(previous_receipts)) => { - Some(transaction_receipt(self.engine().machine(), transaction, previous_receipts)) - }, - _ => None, - } - })) + let number = chain.block_number(&hash)?; + let body = chain.block_body(&hash)?; + let mut receipts = chain.block_receipts(&hash)?.receipts; + receipts.truncate(address.index + 1); + + let transaction = body.view().localized_transaction_at(&hash, number, address.index)?; + let receipt = receipts.pop()?; + let gas_used = receipts.last().map_or_else(|| 0.into(), |r| r.gas_used); + let no_of_logs = receipts.into_iter().map(|receipt| receipt.logs.len()).sum::(); + + let receipt = transaction_receipt(self.engine().machine(), transaction, receipt, gas_used, no_of_logs); + Some(receipt) + } + + fn block_receipts(&self, id: BlockId) -> Option> { + let hash = self.block_hash(id)?; + + let chain = self.chain.read(); + let receipts = chain.block_receipts(&hash)?; + let number = chain.block_number(&hash)?; + let body = chain.block_body(&hash)?; + let engine = self.engine.clone(); + + let mut gas_used = 0.into(); + let mut no_of_logs = 0; + + Some(body + .view() + .localized_transactions(&hash, number) + .into_iter() + .zip(receipts.receipts) + .map(move |(transaction, receipt)| { + let result = transaction_receipt(engine.machine(), transaction, receipt, gas_used, no_of_logs); + gas_used = result.cumulative_gas_used; + no_of_logs += result.logs.len(); + result + }) + .collect() + ) } fn tree_route(&self, from: &H256, to: &H256) -> Option { @@ -1821,7 +1853,7 @@ impl BlockChainClient for Client { self.state_db.read().journal_db().state(hash) } - fn block_receipts(&self, hash: &H256) -> Option { + fn encoded_block_receipts(&self, hash: &H256) -> Option { self.chain.read().block_receipts(hash).map(|receipts| ::rlp::encode(&receipts)) } @@ -2376,16 +2408,14 @@ impl Drop for Client { /// Returns `LocalizedReceipt` given `LocalizedTransaction` /// and a vector of receipts from given block up to transaction index. -fn transaction_receipt(machine: &::machine::EthereumMachine, mut tx: LocalizedTransaction, mut receipts: Vec) -> LocalizedReceipt { - assert_eq!(receipts.len(), tx.transaction_index + 1, "All previous receipts are provided."); - +fn transaction_receipt( + machine: &::machine::EthereumMachine, + mut tx: LocalizedTransaction, + receipt: Receipt, + prior_gas_used: U256, + prior_no_of_logs: usize, +) -> LocalizedReceipt { let sender = tx.sender(); - let receipt = receipts.pop().expect("Current receipt is provided; qed"); - let prior_gas_used = match tx.transaction_index { - 0 => 0.into(), - i => receipts.get(i - 1).expect("All previous receipts are provided; qed").gas_used, - }; - let no_of_logs = receipts.into_iter().map(|receipt| receipt.logs.len()).sum::(); let transaction_hash = tx.hash(); let block_hash = tx.block_hash; let block_number = tx.block_number; @@ -2414,7 +2444,7 @@ fn transaction_receipt(machine: &::machine::EthereumMachine, mut tx: LocalizedTr transaction_hash: transaction_hash, transaction_index: transaction_index, transaction_log_index: i, - log_index: no_of_logs + i, + log_index: prior_no_of_logs + i, }).collect(), log_bloom: receipt.log_bloom, outcome: receipt.outcome, @@ -2462,6 +2492,33 @@ mod tests { assert!(client.tree_route(&genesis, &new_hash).is_none()); } + #[test] + fn should_return_block_receipts() { + use client::{BlockChainClient, BlockId, TransactionId}; + use test_helpers::{generate_dummy_client_with_data}; + + let client = generate_dummy_client_with_data(2, 2, &[1.into(), 1.into()]); + let receipts = client.block_receipts(BlockId::Latest).unwrap(); + + assert_eq!(receipts.len(), 2); + assert_eq!(receipts[0].transaction_index, 0); + assert_eq!(receipts[0].block_number, 2); + assert_eq!(receipts[0].cumulative_gas_used, 53_000.into()); + assert_eq!(receipts[0].gas_used, 53_000.into()); + + assert_eq!(receipts[1].transaction_index, 1); + assert_eq!(receipts[1].block_number, 2); + assert_eq!(receipts[1].cumulative_gas_used, 106_000.into()); + assert_eq!(receipts[1].gas_used, 53_000.into()); + + + let receipt = client.transaction_receipt(TransactionId::Hash(receipts[0].transaction_hash)); + assert_eq!(receipt, Some(receipts[0].clone())); + + let receipt = client.transaction_receipt(TransactionId::Hash(receipts[1].transaction_hash)); + assert_eq!(receipt, Some(receipts[1].clone())); + } + #[test] fn should_return_correct_log_index() { use hash::keccak; @@ -2505,20 +2562,15 @@ mod tests { topics: vec![], data: vec![], }]; - let receipts = vec![Receipt { - outcome: TransactionOutcome::StateRoot(state_root), - gas_used: 5.into(), - log_bloom: Default::default(), - logs: vec![logs[0].clone()], - }, Receipt { + let receipt = Receipt { outcome: TransactionOutcome::StateRoot(state_root), gas_used: gas_used, log_bloom: Default::default(), logs: logs.clone(), - }]; + }; // when - let receipt = transaction_receipt(&machine, transaction, receipts); + let receipt = transaction_receipt(&machine, transaction, receipt, 5.into(), 1); // then assert_eq!(receipt, LocalizedReceipt { diff --git a/ethcore/src/client/evm_test_client.rs b/ethcore/src/client/evm_test_client.rs index 1d827dea626..20a04613ab4 100644 --- a/ethcore/src/client/evm_test_client.rs +++ b/ethcore/src/client/evm_test_client.rs @@ -86,9 +86,9 @@ impl<'a> EvmTestClient<'a> { ForkSpec::EIP150 => Some(ethereum::new_eip150_test()), ForkSpec::EIP158 => Some(ethereum::new_eip161_test()), ForkSpec::Byzantium => Some(ethereum::new_byzantium_test()), + ForkSpec::Constantinople => Some(ethereum::new_constantinople_test()), ForkSpec::EIP158ToByzantiumAt5 => Some(ethereum::new_transition_test()), ForkSpec::FrontierToHomesteadAt5 | ForkSpec::HomesteadToDaoAt5 | ForkSpec::HomesteadToEIP150At5 => None, - _ => None, } } @@ -182,6 +182,19 @@ impl<'a> EvmTestClient<'a> { gas_used: 0.into(), gas_limit: *genesis.gas_limit(), }; + self.call_envinfo(params, tracer, vm_tracer, info) + } + + /// Execute the VM given envinfo, ActionParams and tracer. + /// Returns amount of gas left and the output. + pub fn call_envinfo( + &mut self, + params: ActionParams, + tracer: &mut T, + vm_tracer: &mut V, + info: client::EnvInfo, + ) -> Result + { let mut substate = state::Substate::new(); let machine = self.spec.engine.machine(); let schedule = machine.schedule(info.number); diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index 9198cadecf4..c1f755444bf 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -687,6 +687,10 @@ impl BlockChainClient for TestBlockChainClient { self.receipts.read().get(&id).cloned() } + fn block_receipts(&self, _id: BlockId) -> Option> { + Some(self.receipts.read().values().cloned().collect()) + } + fn logs(&self, filter: Filter) -> Result, BlockId> { match self.error_on_logs.read().as_ref() { Some(id) => return Err(id.clone()), @@ -786,7 +790,7 @@ impl BlockChainClient for TestBlockChainClient { None } - fn block_receipts(&self, hash: &H256) -> Option { + fn encoded_block_receipts(&self, hash: &H256) -> Option { // starts with 'f' ? if *hash > H256::from("f000000000000000000000000000000000000000000000000000000000000000") { let receipt = BlockReceipts::new(vec![Receipt::new( diff --git a/ethcore/src/client/traits.rs b/ethcore/src/client/traits.rs index 85dedb09bd5..ebe70dcd82c 100644 --- a/ethcore/src/client/traits.rs +++ b/ethcore/src/client/traits.rs @@ -281,6 +281,9 @@ pub trait BlockChainClient : Sync + Send + AccountData + BlockChain + CallContra /// Get transaction receipt with given hash. fn transaction_receipt(&self, id: TransactionId) -> Option; + /// Get localized receipts for all transaction in given block. + fn block_receipts(&self, id: BlockId) -> Option>; + /// Get a tree route between `from` and `to`. /// See `BlockChain::tree_route`. fn tree_route(&self, from: &H256, to: &H256) -> Option; @@ -292,7 +295,7 @@ pub trait BlockChainClient : Sync + Send + AccountData + BlockChain + CallContra fn state_data(&self, hash: &H256) -> Option; /// Get raw block receipts data by block header hash. - fn block_receipts(&self, hash: &H256) -> Option; + fn encoded_block_receipts(&self, hash: &H256) -> Option; /// Get block queue information. fn queue_info(&self) -> BlockQueueInfo; diff --git a/ethcore/src/engines/mod.rs b/ethcore/src/engines/mod.rs index 424a9e94c91..11507c206e2 100644 --- a/ethcore/src/engines/mod.rs +++ b/ethcore/src/engines/mod.rs @@ -44,7 +44,7 @@ use self::epoch::PendingTransition; use account_provider::AccountProvider; use builtin::Builtin; -use vm::{EnvInfo, Schedule, CreateContractAddress}; +use vm::{EnvInfo, Schedule, CreateContractAddress, CallType, ActionValue}; use error::Error; use header::{Header, BlockNumber}; use snapshot::SnapshotComponents; @@ -163,8 +163,10 @@ pub fn default_system_or_code_call<'a>(machine: &'a ::machine::EthereumMachine, None, Some(code), Some(code_hash), + Some(ActionValue::Apparent(U256::zero())), U256::max_value(), Some(data), + Some(CallType::StaticCall), ) }, }; diff --git a/ethcore/src/json_tests/chain.rs b/ethcore/src/json_tests/chain.rs index 83a940fcb64..120bcce8393 100644 --- a/ethcore/src/json_tests/chain.rs +++ b/ethcore/src/json_tests/chain.rs @@ -23,6 +23,7 @@ use miner::Miner; use io::IoChannel; use test_helpers; use verification::queue::kind::blocks::Unverified; +use super::SKIP_TEST_STATE; use super::HookType; @@ -36,12 +37,20 @@ pub fn run_test_file(p: &Path, h: &mut H) { ::json_tests::test_common::run_test_file(p, json_chain_test, h) } +fn skip_test(name: &String) -> bool { + SKIP_TEST_STATE.block.iter().any(|block_test|block_test.subtests.contains(name)) +} + pub fn json_chain_test(json_data: &[u8], start_stop_hook: &mut H) -> Vec { ::ethcore_logger::init_log(); let tests = ethjson::blockchain::Test::load(json_data).unwrap(); let mut failed = Vec::new(); for (name, blockchain) in tests.into_iter() { + if skip_test(&name) { + println!(" - {} | {:?} Ignoring tests because in skip list", name, blockchain.network); + continue; + } start_stop_hook(&name, HookType::OnStart); let mut fail = false; @@ -122,19 +131,24 @@ mod block_tests { declare_test!{BlockchainTests_bcInvalidHeaderTest, "BlockchainTests/bcInvalidHeaderTest"} declare_test!{BlockchainTests_bcMultiChainTest, "BlockchainTests/bcMultiChainTest"} declare_test!{BlockchainTests_bcRandomBlockhashTest, "BlockchainTests/bcRandomBlockhashTest"} + declare_test!{BlockchainTests_bcStateTest, "BlockchainTests/bcStateTests"} declare_test!{BlockchainTests_bcTotalDifficultyTest, "BlockchainTests/bcTotalDifficultyTest"} declare_test!{BlockchainTests_bcUncleHeaderValidity, "BlockchainTests/bcUncleHeaderValidity"} declare_test!{BlockchainTests_bcUncleTest, "BlockchainTests/bcUncleTest"} declare_test!{BlockchainTests_bcValidBlockTest, "BlockchainTests/bcValidBlockTest"} declare_test!{BlockchainTests_bcWalletTest, "BlockchainTests/bcWalletTest"} + declare_test!{BlockchainTests_GeneralStateTest_stArgsZeroOneBalance, "BlockchainTests/GeneralStateTests/stArgsZeroOneBalance/"} declare_test!{BlockchainTests_GeneralStateTest_stAttackTest, "BlockchainTests/GeneralStateTests/stAttackTest/"} declare_test!{BlockchainTests_GeneralStateTest_stBadOpcodeTest, "BlockchainTests/GeneralStateTests/stBadOpcode/"} + declare_test!{BlockchainTests_GeneralStateTest_stBugsTest, "BlockchainTests/GeneralStateTests/stBugs/"} declare_test!{BlockchainTests_GeneralStateTest_stCallCodes, "BlockchainTests/GeneralStateTests/stCallCodes/"} + declare_test!{BlockchainTests_GeneralStateTest_stCallCreateCallCodeTest, "BlockchainTests/GeneralStateTests/stCallCreateCallCodeTest/"} declare_test!{BlockchainTests_GeneralStateTest_stCallDelegateCodesCallCodeHomestead, "BlockchainTests/GeneralStateTests/stCallDelegateCodesCallCodeHomestead/"} declare_test!{BlockchainTests_GeneralStateTest_stCallDelegateCodesHomestead, "BlockchainTests/GeneralStateTests/stCallDelegateCodesHomestead/"} declare_test!{BlockchainTests_GeneralStateTest_stChangedEIP150, "BlockchainTests/GeneralStateTests/stChangedEIP150/"} declare_test!{BlockchainTests_GeneralStateTest_stCodeSizeLimit, "BlockchainTests/GeneralStateTests/stCodeSizeLimit/"} + declare_test!{BlockchainTests_GeneralStateTest_stCreate2, "BlockchainTests/GeneralStateTests/stCreate2/"} declare_test!{BlockchainTests_GeneralStateTest_stCreateTest, "BlockchainTests/GeneralStateTests/stCreateTest/"} declare_test!{BlockchainTests_GeneralStateTest_stDelegatecallTestHomestead, "BlockchainTests/GeneralStateTests/stDelegatecallTestHomestead/"} declare_test!{BlockchainTests_GeneralStateTest_stEIP150singleCodeGasPrices, "BlockchainTests/GeneralStateTests/stEIP150singleCodeGasPrices/"} @@ -149,12 +163,15 @@ mod block_tests { declare_test!{BlockchainTests_GeneralStateTest_stMemoryTest, "BlockchainTests/GeneralStateTests/stMemoryTest/"} declare_test!{BlockchainTests_GeneralStateTest_stNonZeroCallsTest, "BlockchainTests/GeneralStateTests/stNonZeroCallsTest/"} declare_test!{BlockchainTests_GeneralStateTest_stPreCompiledContracts, "BlockchainTests/GeneralStateTests/stPreCompiledContracts/"} + declare_test!{BlockchainTests_GeneralStateTest_stPreCompiledContracts2, "BlockchainTests/GeneralStateTests/stPreCompiledContracts2/"} declare_test!{heavy => BlockchainTests_GeneralStateTest_stQuadraticComplexityTest, "BlockchainTests/GeneralStateTests/stQuadraticComplexityTest/"} declare_test!{BlockchainTests_GeneralStateTest_stRandom, "BlockchainTests/GeneralStateTests/stRandom/"} + declare_test!{BlockchainTests_GeneralStateTest_stRandom2, "BlockchainTests/GeneralStateTests/stRandom2/"} declare_test!{BlockchainTests_GeneralStateTest_stRecursiveCreate, "BlockchainTests/GeneralStateTests/stRecursiveCreate/"} declare_test!{BlockchainTests_GeneralStateTest_stRefundTest, "BlockchainTests/GeneralStateTests/stRefundTest/"} declare_test!{BlockchainTests_GeneralStateTest_stReturnDataTest, "BlockchainTests/GeneralStateTests/stReturnDataTest/"} declare_test!{BlockchainTests_GeneralStateTest_stRevertTest, "BlockchainTests/GeneralStateTests/stRevertTest/"} + declare_test!{BlockchainTests_GeneralStateTest_stShift, "BlockchainTests/GeneralStateTests/stShift/"} declare_test!{BlockchainTests_GeneralStateTest_stSolidityTest, "BlockchainTests/GeneralStateTests/stSolidityTest/"} declare_test!{BlockchainTests_GeneralStateTest_stSpecialTest, "BlockchainTests/GeneralStateTests/stSpecialTest/"} declare_test!{BlockchainTests_GeneralStateTest_stStackTests, "BlockchainTests/GeneralStateTests/stStackTests/"} @@ -166,6 +183,7 @@ mod block_tests { declare_test!{BlockchainTests_GeneralStateTest_stZeroCallsRevert, "BlockchainTests/GeneralStateTests/stZeroCallsRevert/"} declare_test!{BlockchainTests_GeneralStateTest_stZeroCallsTest, "BlockchainTests/GeneralStateTests/stZeroCallsTest/"} declare_test!{BlockchainTests_GeneralStateTest_stZeroKnowledge, "BlockchainTests/GeneralStateTests/stZeroKnowledge/"} + declare_test!{BlockchainTests_GeneralStateTest_stZeroKnowledge2, "BlockchainTests/GeneralStateTests/stZeroKnowledge2/"} declare_test!{BlockchainTests_TransitionTests_bcEIP158ToByzantium, "BlockchainTests/TransitionTests/bcEIP158ToByzantium/"} declare_test!{BlockchainTests_TransitionTests_bcFrontierToHomestead, "BlockchainTests/TransitionTests/bcFrontierToHomestead/"} diff --git a/ethcore/src/json_tests/mod.rs b/ethcore/src/json_tests/mod.rs index fa1c822ce2a..35d5034806a 100644 --- a/ethcore/src/json_tests/mod.rs +++ b/ethcore/src/json_tests/mod.rs @@ -24,10 +24,12 @@ mod executive; mod state; mod chain; mod trie; +mod skip; #[cfg(test)] mod difficulty; + pub use self::test_common::HookType; pub use self::transaction::run_test_path as run_transaction_test_path; @@ -42,3 +44,4 @@ pub use self::trie::run_generic_test_path as run_generic_trie_test_path; pub use self::trie::run_generic_test_file as run_generic_trie_test_file; pub use self::trie::run_secure_test_path as run_secure_trie_test_path; pub use self::trie::run_secure_test_file as run_secure_trie_test_file; +use self::skip::SKIP_TEST_STATE; diff --git a/ethcore/src/json_tests/skip.rs b/ethcore/src/json_tests/skip.rs new file mode 100644 index 00000000000..784e2975d73 --- /dev/null +++ b/ethcore/src/json_tests/skip.rs @@ -0,0 +1,37 @@ +// Copyright 2015-2018 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! State tests to skip. + +use ethjson; + +#[cfg(all(not(test), feature = "ci-skip-tests"))] +compile_error!("ci-skip-tests can only be enabled for testing builds."); + +#[cfg(feature="ci-skip-issue")] +lazy_static!{ + pub static ref SKIP_TEST_STATE: ethjson::test::SkipStates = { + let skip_data = include_bytes!("../../res/ethereum/tests-issues/currents.json"); + ethjson::test::SkipStates::load(&skip_data[..]).expect("No invalid json allowed") + }; +} + +#[cfg(not(feature="ci-skip-issue"))] +lazy_static!{ + pub static ref SKIP_TEST_STATE: ethjson::test::SkipStates = { + ethjson::test::SkipStates::empty() + }; +} diff --git a/ethcore/src/json_tests/state.rs b/ethcore/src/json_tests/state.rs index 5837f191c7d..04ca947bf19 100644 --- a/ethcore/src/json_tests/state.rs +++ b/ethcore/src/json_tests/state.rs @@ -22,7 +22,7 @@ use client::{EvmTestClient, EvmTestError, TransactResult}; use ethjson; use transaction::SignedTransaction; use vm::EnvInfo; - +use super::SKIP_TEST_STATE; use super::HookType; /// Run state jsontests on a given folder. @@ -35,6 +35,18 @@ pub fn run_test_file(p: &Path, h: &mut H) { ::json_tests::test_common::run_test_file(p, json_chain_test, h) } +fn skip_test(subname: &str, chain: &String, number: usize) -> bool { + SKIP_TEST_STATE.state.iter().any(|state_test|{ + if let Some(subtest) = state_test.subtests.get(subname) { + chain == &subtest.chain && + (subtest.subnumbers[0] == "*" + || subtest.subnumbers.contains(&number.to_string())) + } else { + false + } + }) +} + pub fn json_chain_test(json_data: &[u8], start_stop_hook: &mut H) -> Vec { ::ethcore_logger::init_log(); let tests = ethjson::state::test::Test::load(json_data).unwrap(); @@ -60,6 +72,10 @@ pub fn json_chain_test(json_data: &[u8], start_stop_ho for (i, state) in states.into_iter().enumerate() { let info = format!(" - {} | {:?} ({}/{}) ...", name, spec_name, i + 1, total); + if skip_test(&name, &spec.name, i + 1) { + println!("{} in skip list : SKIPPED", info); + continue; + } let post_root: H256 = state.hash.into(); let transaction: SignedTransaction = multitransaction.select(&state.indexes).into(); @@ -125,11 +141,13 @@ mod state_tests { declare_test!{GeneralStateTest_stChangedEIP150, "GeneralStateTests/stChangedEIP150/"} declare_test!{GeneralStateTest_stCodeCopyTest, "GeneralStateTests/stCodeCopyTest/"} declare_test!{GeneralStateTest_stCodeSizeLimit, "GeneralStateTests/stCodeSizeLimit/"} + declare_test!{GeneralStateTest_stCreate2Test, "GeneralStateTests/stCreate2/"} declare_test!{GeneralStateTest_stCreateTest, "GeneralStateTests/stCreateTest/"} declare_test!{GeneralStateTest_stDelegatecallTestHomestead, "GeneralStateTests/stDelegatecallTestHomestead/"} declare_test!{GeneralStateTest_stEIP150singleCodeGasPrices, "GeneralStateTests/stEIP150singleCodeGasPrices/"} declare_test!{GeneralStateTest_stEIP150Specific, "GeneralStateTests/stEIP150Specific/"} declare_test!{GeneralStateTest_stEIP158Specific, "GeneralStateTests/stEIP158Specific/"} + declare_test!{GeneralStateTest_stEWASMTests, "GeneralStateTests/stEWASMTests/"} declare_test!{GeneralStateTest_stExample, "GeneralStateTests/stExample/"} declare_test!{GeneralStateTest_stHomesteadSpecific, "GeneralStateTests/stHomesteadSpecific/"} declare_test!{GeneralStateTest_stInitCodeTest, "GeneralStateTests/stInitCodeTest/"} diff --git a/ethcore/src/json_tests/test_common.rs b/ethcore/src/json_tests/test_common.rs index ce5c68a73a0..ce16395d228 100644 --- a/ethcore/src/json_tests/test_common.rs +++ b/ethcore/src/json_tests/test_common.rs @@ -34,6 +34,18 @@ pub fn run_test_path( p: &Path, skip: &[&'static str], runner: fn(json_data: &[u8], start_stop_hook: &mut H) -> Vec, start_stop_hook: &mut H +) { + let mut errors = Vec::new(); + run_test_path_inner(p, skip, runner, start_stop_hook, &mut errors); + let empty: [String; 0] = []; + assert_eq!(errors, empty); +} + +fn run_test_path_inner( + p: &Path, skip: &[&'static str], + runner: fn(json_data: &[u8], start_stop_hook: &mut H) -> Vec, + start_stop_hook: &mut H, + errors: &mut Vec ) { let path = Path::new(p); let s: HashSet = skip.iter().map(|s| { @@ -50,17 +62,32 @@ pub fn run_test_path( } else { Some(e.path()) }}) { - run_test_path(&p, skip, runner, start_stop_hook) + run_test_path_inner(&p, skip, runner, start_stop_hook, errors); } } else if extension == Some("swp") || extension == None { // Ignore junk } else { let mut path = p.to_path_buf(); path.set_extension("json"); - run_test_file(&path, runner, start_stop_hook) + run_test_file_append(&path, runner, start_stop_hook, errors) } } +fn run_test_file_append( + path: &Path, + runner: fn(json_data: &[u8], start_stop_hook: &mut H) -> Vec, + start_stop_hook: &mut H, + errors: &mut Vec +) { + let mut data = Vec::new(); + let mut file = match File::open(&path) { + Ok(file) => file, + Err(_) => panic!("Error opening test file at: {:?}", path), + }; + file.read_to_end(&mut data).expect("Error reading test file"); + errors.append(&mut runner(&data, start_stop_hook)); +} + pub fn run_test_file( path: &Path, runner: fn(json_data: &[u8], start_stop_hook: &mut H) -> Vec, diff --git a/ethcore/src/lib.rs b/ethcore/src/lib.rs index 7a746b74b44..fefa9b5e051 100644 --- a/ethcore/src/lib.rs +++ b/ethcore/src/lib.rs @@ -159,6 +159,7 @@ pub mod header; pub mod machine; pub mod miner; pub mod pod_state; +pub mod pod_account; pub mod snapshot; pub mod spec; pub mod state; @@ -167,7 +168,6 @@ pub mod trace; pub mod verification; mod cache_manager; -mod pod_account; mod account_db; mod externalities; mod blockchain; diff --git a/ethcore/src/machine.rs b/ethcore/src/machine.rs index 8162408e92f..c74cc6bf4d1 100644 --- a/ethcore/src/machine.rs +++ b/ethcore/src/machine.rs @@ -135,8 +135,10 @@ impl EthereumMachine { Some(contract_address), code, code_hash, + None, gas, - data + data, + None, ) } @@ -149,8 +151,10 @@ impl EthereumMachine { contract_address: Option
, code: Option>>, code_hash: Option, + value: Option, gas: U256, - data: Option> + data: Option>, + call_type: Option, ) -> Result, Error> { let env_info = { let mut env_info = block.env_info(); @@ -167,11 +171,11 @@ impl EthereumMachine { origin: SYSTEM_ADDRESS, gas, gas_price: 0.into(), - value: ActionValue::Transfer(0.into()), + value: value.unwrap_or(ActionValue::Transfer(0.into())), code, code_hash, data, - call_type: CallType::Call, + call_type: call_type.unwrap_or(CallType::Call), params_type: ParamsType::Separate, }; let schedule = self.schedule(env_info.number); diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs index 1a0d34b10b7..987d895ab04 100644 --- a/ethcore/src/miner/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -50,7 +50,7 @@ use executive::contract_address; use header::{Header, BlockNumber}; use miner; use miner::pool_client::{PoolClient, CachedNonceClient, NonceCache}; -use receipt::{Receipt, RichReceipt}; +use receipt::RichReceipt; use spec::Spec; use state::State; use ethkey::Password; @@ -1039,19 +1039,17 @@ impl miner::MinerService for Miner { self.transaction_queue.status() } - fn pending_receipt(&self, best_block: BlockNumber, hash: &H256) -> Option { + fn pending_receipts(&self, best_block: BlockNumber) -> Option> { self.map_existing_pending_block(|pending| { - let txs = pending.transactions(); - txs.iter() - .map(|t| t.hash()) - .position(|t| t == *hash) - .map(|index| { - let receipts = pending.receipts(); + let receipts = pending.receipts(); + pending.transactions() + .into_iter() + .enumerate() + .map(|(index, tx)| { let prev_gas = if index == 0 { Default::default() } else { receipts[index - 1].gas_used }; - let tx = &txs[index]; let receipt = &receipts[index]; RichReceipt { - transaction_hash: hash.clone(), + transaction_hash: tx.hash(), transaction_index: index, cumulative_gas_used: receipt.gas_used, gas_used: receipt.gas_used - prev_gas, @@ -1067,15 +1065,7 @@ impl miner::MinerService for Miner { outcome: receipt.outcome.clone(), } }) - }, best_block).and_then(|x| x) - } - - fn pending_receipts(&self, best_block: BlockNumber) -> Option> { - self.map_existing_pending_block(|pending| { - let hashes = pending.transactions().iter().map(|t| t.hash()); - let receipts = pending.receipts().iter().cloned(); - - hashes.zip(receipts).collect() + .collect() }, best_block) } diff --git a/ethcore/src/miner/mod.rs b/ethcore/src/miner/mod.rs index cc56bf01f94..4ba1b036115 100644 --- a/ethcore/src/miner/mod.rs +++ b/ethcore/src/miner/mod.rs @@ -44,7 +44,7 @@ use client::{ }; use error::Error; use header::{BlockNumber, Header}; -use receipt::{RichReceipt, Receipt}; +use receipt::RichReceipt; use transaction::{self, UnverifiedTransaction, SignedTransaction, PendingTransaction}; use state::StateInfo; use ethkey::Password; @@ -95,10 +95,13 @@ pub trait MinerService : Send + Sync { // Pending block /// Get a list of all pending receipts from pending block. - fn pending_receipts(&self, best_block: BlockNumber) -> Option>; + fn pending_receipts(&self, best_block: BlockNumber) -> Option>; /// Get a particular receipt from pending block. - fn pending_receipt(&self, best_block: BlockNumber, hash: &H256) -> Option; + fn pending_receipt(&self, best_block: BlockNumber, hash: &H256) -> Option { + let receipts = self.pending_receipts(best_block)?; + receipts.into_iter().find(|r| &r.transaction_hash == hash) + } /// Get `Some` `clone()` of the current pending block's state or `None` if we're not sealing. fn pending_state(&self, latest_block_number: BlockNumber) -> Option; diff --git a/ethcore/src/pod_account.rs b/ethcore/src/pod_account.rs index 33e84474eb6..db5d0660c24 100644 --- a/ethcore/src/pod_account.rs +++ b/ethcore/src/pod_account.rs @@ -14,6 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . +//! Account system expressed in Plain Old Data. + use std::fmt; use std::collections::BTreeMap; use itertools::Itertools; diff --git a/ethcore/src/verification/queue/mod.rs b/ethcore/src/verification/queue/mod.rs index 8c65d2ea795..2d5f50c5d03 100644 --- a/ethcore/src/verification/queue/mod.rs +++ b/ethcore/src/verification/queue/mod.rs @@ -39,9 +39,6 @@ pub mod kind; const MIN_MEM_LIMIT: usize = 16384; const MIN_QUEUE_LIMIT: usize = 512; -// maximum possible number of verification threads. -const MAX_VERIFIERS: usize = 8; - /// Type alias for block queue convenience. pub type BlockQueue = VerificationQueue; @@ -85,7 +82,7 @@ impl Default for VerifierSettings { fn default() -> Self { VerifierSettings { scale_verifiers: false, - num_verifiers: MAX_VERIFIERS, + num_verifiers: ::num_cpus::get(), } } } @@ -231,16 +228,24 @@ impl VerificationQueue { let empty = Arc::new(Condvar::new()); let scale_verifiers = config.verifier_settings.scale_verifiers; - let num_cpus = ::num_cpus::get(); - let max_verifiers = cmp::min(num_cpus, MAX_VERIFIERS); + let max_verifiers = ::num_cpus::get(); let default_amount = cmp::max(1, cmp::min(max_verifiers, config.verifier_settings.num_verifiers)); + + // if `auto-scaling` is enabled spawn up extra threads as they might be needed + // otherwise just spawn the number of threads specified by the config + let number_of_threads = if scale_verifiers { + max_verifiers + } else { + cmp::min(default_amount, max_verifiers) + }; + let state = Arc::new((Mutex::new(State::Work(default_amount)), Condvar::new())); - let mut verifier_handles = Vec::with_capacity(max_verifiers); + let mut verifier_handles = Vec::with_capacity(number_of_threads); - debug!(target: "verification", "Allocating {} verifiers, {} initially active", max_verifiers, default_amount); + debug!(target: "verification", "Allocating {} verifiers, {} initially active", number_of_threads, default_amount); debug!(target: "verification", "Verifier auto-scaling {}", if scale_verifiers { "enabled" } else { "disabled" }); - for i in 0..max_verifiers { + for i in 0..number_of_threads { debug!(target: "verification", "Adding verification thread #{}", i); let verification = verification.clone(); @@ -465,19 +470,19 @@ impl VerificationQueue { /// Add a block to the queue. pub fn import(&self, input: K::Input) -> EthcoreResult { - let h = input.hash(); + let hash = input.hash(); { - if self.processing.read().contains_key(&h) { + if self.processing.read().contains_key(&hash) { bail!(ErrorKind::Import(ImportErrorKind::AlreadyQueued)); } let mut bad = self.verification.bad.lock(); - if bad.contains(&h) { + if bad.contains(&hash) { bail!(ErrorKind::Import(ImportErrorKind::KnownBad)); } if bad.contains(&input.parent_hash()) { - bad.insert(h.clone()); + bad.insert(hash); bail!(ErrorKind::Import(ImportErrorKind::KnownBad)); } } @@ -486,21 +491,21 @@ impl VerificationQueue { Ok(item) => { self.verification.sizes.unverified.fetch_add(item.heap_size_of_children(), AtomicOrdering::SeqCst); - self.processing.write().insert(h.clone(), item.difficulty()); + self.processing.write().insert(hash, item.difficulty()); { let mut td = self.total_difficulty.write(); *td = *td + item.difficulty(); } self.verification.unverified.lock().push_back(item); self.more_to_verify.notify_all(); - Ok(h) + Ok(hash) }, Err(err) => { match err { // Don't mark future blocks as bad. Error(ErrorKind::Block(BlockError::TemporarilyInvalid(_)), _) => {}, _ => { - self.verification.bad.lock().insert(h.clone()); + self.verification.bad.lock().insert(hash); } } Err(err) @@ -743,6 +748,13 @@ mod tests { BlockQueue::new(config, engine, IoChannel::disconnected(), true) } + fn get_test_config(num_verifiers: usize, is_auto_scale: bool) -> Config { + let mut config = Config::default(); + config.verifier_settings.num_verifiers = num_verifiers; + config.verifier_settings.scale_verifiers = is_auto_scale; + config + } + fn new_unverified(bytes: Bytes) -> Unverified { Unverified::from_rlp(bytes).expect("Should be valid rlp") } @@ -843,12 +855,11 @@ mod tests { #[test] fn scaling_limits() { - use super::MAX_VERIFIERS; - + let max_verifiers = ::num_cpus::get(); let queue = get_test_queue(true); - queue.scale_verifiers(MAX_VERIFIERS + 1); + queue.scale_verifiers(max_verifiers + 1); - assert!(queue.num_verifiers() < MAX_VERIFIERS + 1); + assert!(queue.num_verifiers() < max_verifiers + 1); queue.scale_verifiers(0); @@ -877,4 +888,50 @@ mod tests { queue.collect_garbage(); assert_eq!(queue.num_verifiers(), 1); } + + #[test] + fn worker_threads_honor_specified_number_without_scaling() { + let spec = Spec::new_test(); + let engine = spec.engine; + let config = get_test_config(1, false); + let queue = BlockQueue::new(config, engine, IoChannel::disconnected(), true); + + assert_eq!(queue.num_verifiers(), 1); + } + + #[test] + fn worker_threads_specified_to_zero_should_set_to_one() { + let spec = Spec::new_test(); + let engine = spec.engine; + let config = get_test_config(0, false); + let queue = BlockQueue::new(config, engine, IoChannel::disconnected(), true); + + assert_eq!(queue.num_verifiers(), 1); + } + + #[test] + fn worker_threads_should_only_accept_max_number_cpus() { + let spec = Spec::new_test(); + let engine = spec.engine; + let config = get_test_config(10_000, false); + let queue = BlockQueue::new(config, engine, IoChannel::disconnected(), true); + let num_cpus = ::num_cpus::get(); + + assert_eq!(queue.num_verifiers(), num_cpus); + } + + #[test] + fn worker_threads_scaling_with_specifed_num_of_workers() { + let num_cpus = ::num_cpus::get(); + // only run the test with at least 2 CPUs + if num_cpus > 1 { + let spec = Spec::new_test(); + let engine = spec.engine; + let config = get_test_config(num_cpus - 1, true); + let queue = BlockQueue::new(config, engine, IoChannel::disconnected(), true); + queue.scale_verifiers(num_cpus); + + assert_eq!(queue.num_verifiers(), num_cpus); + } + } } diff --git a/ethcore/src/views/body.rs b/ethcore/src/views/body.rs index 6560140cad1..f1a30949b32 100644 --- a/ethcore/src/views/body.rs +++ b/ethcore/src/views/body.rs @@ -38,9 +38,9 @@ impl<'a> BodyView<'a> { /// ``` /// #[macro_use] /// extern crate ethcore; - /// + /// /// use ethcore::views::{BodyView}; - /// + /// /// fn main() { /// let bytes : &[u8] = &[]; /// let body_view = view!(BodyView, bytes); diff --git a/ethcore/sync/Cargo.toml b/ethcore/sync/Cargo.toml index 538f6f15287..eb3f567bac9 100644 --- a/ethcore/sync/Cargo.toml +++ b/ethcore/sync/Cargo.toml @@ -20,7 +20,6 @@ ethereum-types = "0.4" hashdb = "0.3.0-beta" fastmap = { path = "../../util/fastmap" } rlp = { version = "0.3.0-beta", features = ["ethereum"] } -rustc-hex = "1.0" keccak-hash = "0.1" keccak-hasher = { path = "../../util/keccak-hasher" } triehash-ethereum = {version = "0.2", path = "../../util/triehash-ethereum" } @@ -30,11 +29,8 @@ log = "0.4" env_logger = "0.5" rand = "0.4" heapsize = "0.4" -semver = "0.9" -smallvec = { version = "0.4", features = ["heapsizeof"] } parking_lot = "0.6" trace-time = "0.1" -ipnetwork = "0.12.6" [dev-dependencies] ethcore-io = { path = "../../util/io", features = ["mio"] } @@ -42,3 +38,4 @@ ethkey = { path = "../../ethkey" } kvdb-memorydb = "0.1" ethcore-private-tx = { path = "../private-tx" } ethcore = { path = "..", features = ["test-helpers"] } +rustc-hex = "1.0" diff --git a/ethcore/sync/src/blocks.rs b/ethcore/sync/src/blocks.rs index 3815084f8f1..4a6805a2bbe 100644 --- a/ethcore/sync/src/blocks.rs +++ b/ethcore/sync/src/blocks.rs @@ -15,7 +15,6 @@ // along with Parity. If not, see . use std::collections::{HashSet, HashMap, hash_map}; -use smallvec::SmallVec; use hash::{keccak, KECCAK_NULL_RLP, KECCAK_EMPTY_LIST_RLP}; use heapsize::HeapSizeOf; use ethereum_types::H256; @@ -29,8 +28,6 @@ use transaction::UnverifiedTransaction; known_heap_size!(0, HeaderId); -type SmallHashVec = SmallVec<[H256; 1]>; - #[derive(PartialEq, Debug, Clone)] pub struct SyncHeader { pub bytes: Bytes, @@ -157,7 +154,7 @@ pub struct BlockCollection { /// Used to map body to header. header_ids: HashMap, /// Used to map receipts root to headers. - receipt_ids: HashMap, + receipt_ids: HashMap>, /// First block in `blocks`. head: Option, /// Set of block header hashes being downloaded @@ -522,7 +519,7 @@ impl BlockCollection { let receipts_stream = RlpStream::new_list(0); (Some(receipts_stream.out()), receipt_root) } else { - self.receipt_ids.entry(receipt_root).or_insert_with(|| SmallHashVec::new()).push(hash); + self.receipt_ids.entry(receipt_root).or_insert_with(Vec::new).push(hash); (None, receipt_root) } } else { diff --git a/ethcore/sync/src/chain/supplier.rs b/ethcore/sync/src/chain/supplier.rs index e2113b0b1c2..201e0d9f35a 100644 --- a/ethcore/sync/src/chain/supplier.rs +++ b/ethcore/sync/src/chain/supplier.rs @@ -226,7 +226,7 @@ impl SyncSupplier { let mut added_receipts = 0usize; let mut data = Bytes::new(); for i in 0..count { - if let Some(mut receipts_bytes) = io.chain().block_receipts(&rlp.val_at::(i)?) { + if let Some(mut receipts_bytes) = io.chain().encoded_block_receipts(&rlp.val_at::(i)?) { data.append(&mut receipts_bytes); added_receipts += receipts_bytes.len(); added_headers += 1; diff --git a/ethcore/sync/src/lib.rs b/ethcore/sync/src/lib.rs index 9fb7da99053..294ba0cd781 100644 --- a/ethcore/sync/src/lib.rs +++ b/ethcore/sync/src/lib.rs @@ -30,18 +30,12 @@ extern crate ethcore_transaction as transaction; extern crate ethcore; extern crate ethereum_types; extern crate env_logger; -extern crate hashdb; extern crate fastmap; extern crate rand; -extern crate semver; extern crate parking_lot; -extern crate smallvec; extern crate rlp; -extern crate ipnetwork; extern crate keccak_hash as hash; -extern crate keccak_hasher; extern crate triehash_ethereum; -extern crate kvdb; extern crate ethcore_light as light; diff --git a/ethstore/Cargo.toml b/ethstore/Cargo.toml index d51a7f9b7f8..7393baf2c72 100644 --- a/ethstore/Cargo.toml +++ b/ethstore/Cargo.toml @@ -19,7 +19,7 @@ parking_lot = "0.6" parity-crypto = "0.1" ethereum-types = "0.4" dir = { path = "../util/dir" } -smallvec = "0.4" +smallvec = "0.6" parity-wordlist = "1.0" tempdir = "0.3" diff --git a/json/src/test/mod.rs b/json/src/test/mod.rs index 8f95a9aec49..e6148e0d08c 100644 --- a/json/src/test/mod.rs +++ b/json/src/test/mod.rs @@ -45,6 +45,7 @@ pub struct DifficultyTestCase { #[serde(rename="currentBlockNumber")] pub current_block_number: Uint, } + /// Blockchain test deserializer. #[derive(Debug, PartialEq, Deserialize)] pub struct DifficultyTest(BTreeMap); @@ -64,3 +65,59 @@ impl DifficultyTest { serde_json::from_reader(reader) } } + +/// Test to skip (only if issue ongoing) +#[derive(Debug, PartialEq, Deserialize)] +pub struct SkipStates { + /// Block tests + pub block: Vec, + /// State tests + pub state: Vec, + +} + +/// Block test to skip. +#[derive(Debug, PartialEq, Deserialize)] +pub struct BlockSkipStates { + /// Issue reference. + pub reference: String, + /// Test failing name. + pub failing: String, + /// Items failing for the test. + pub subtests: Vec, +} + +/// State test to skip. +#[derive(Debug, PartialEq, Deserialize)] +pub struct StateSkipStates { + /// Issue reference. + pub reference: String, + /// Test failing name. + pub failing: String, + /// Items failing for the test. + pub subtests: BTreeMap +} + +/// State subtest to skip. +#[derive(Debug, PartialEq, Deserialize)] +pub struct StateSkipSubStates { + /// State test number of this item. Or '*' for all state. + pub subnumbers: Vec, + /// Chain for this items. + pub chain: String, +} + +impl SkipStates { + /// Loads skip states from json. + pub fn load(reader: R) -> Result where R: Read { + serde_json::from_reader(reader) + } + + /// Empty skip states. + pub fn empty() -> Self { + SkipStates { + block: Vec::new(), + state: Vec::new(), + } + } +} diff --git a/miner/src/pool/tests/mod.rs b/miner/src/pool/tests/mod.rs index 36897a04710..30a3e5130bd 100644 --- a/miner/src/pool/tests/mod.rs +++ b/miner/src/pool/tests/mod.rs @@ -76,6 +76,7 @@ fn should_return_correct_nonces_when_dropped_because_of_limit() { // when let tx1 = Tx::gas_price(2).signed(); let tx2 = Tx::gas_price(2).signed(); + let sender = tx2.sender(); let tx3 = Tx::gas_price(1).signed(); let tx4 = Tx::gas_price(3).signed(); let res = txq.import(TestClient::new(), vec![tx1, tx2].retracted()); @@ -90,7 +91,8 @@ fn should_return_correct_nonces_when_dropped_because_of_limit() { Ok(()) ]); assert_eq!(txq.status().status.transaction_count, 3); - // First inserted transacton got dropped because of limit + // tx2 transacton got dropped because of limit + // tx1 and tx1' are kept, because they have lower insertion_ids so they are preferred. assert_eq!(txq.next_nonce(TestClient::new(), &sender), None); } diff --git a/parity/cli/mod.rs b/parity/cli/mod.rs index 4fb4411dae7..f3c1e2dbf4e 100644 --- a/parity/cli/mod.rs +++ b/parity/cli/mod.rs @@ -338,7 +338,7 @@ usage! { ARG arg_unlock: (Option) = None, or |c: &Config| c.account.as_ref()?.unlock.as_ref().map(|vec| vec.join(",")), "--unlock=[ACCOUNTS]", - "Unlock ACCOUNTS for the duration of the execution. ACCOUNTS is a comma-delimited list of addresses. Implies --no-ui.", + "Unlock ACCOUNTS for the duration of the execution. ACCOUNTS is a comma-delimited list of addresses.", ARG arg_password: (Vec) = Vec::new(), or |c: &Config| c.account.as_ref()?.password.clone(), "--password=[FILE]...", diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index d54d2c7adc2..cb31166b51b 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -29,7 +29,6 @@ use ethcore::account_provider::AccountProvider; use ethcore::client::{BlockChainClient, BlockId, TransactionId, UncleId, StateOrBlock, StateClient, StateInfo, Call, EngineInfo}; use ethcore::filter::Filter as EthcoreFilter; use ethcore::header::{BlockNumber as EthBlockNumber}; -use ethcore::log_entry::LogEntry; use ethcore::miner::{self, MinerService}; use ethcore::snapshot::SnapshotService; use ethcore::encoded; @@ -419,11 +418,11 @@ impl EthClient(miner: &M, best_block: EthBlockNumber, filter: &EthcoreFilter) -> Vec where M: MinerService { let receipts = miner.pending_receipts(best_block).unwrap_or_default(); - let pending_logs = receipts.into_iter() - .flat_map(|(hash, r)| r.logs.into_iter().map(|l| (hash.clone(), l)).collect::>()) - .collect::>(); - - pending_logs.into_iter() + receipts.into_iter() + .flat_map(|r| { + let hash = r.transaction_hash; + r.logs.into_iter().map(move |l| (hash, l)) + }) .filter(|pair| filter.matches(&pair.1)) .map(|pair| { let mut log = Log::from(pair.1); @@ -673,16 +672,17 @@ impl Eth for EthClient< } fn transaction_receipt(&self, hash: RpcH256) -> BoxFuture> { - let best_block = self.client.chain_info().best_block_number; let hash: H256 = hash.into(); - match (self.miner.pending_receipt(best_block, &hash), self.options.allow_pending_receipt_query) { - (Some(receipt), true) => Box::new(future::ok(Some(receipt.into()))), - _ => { - let receipt = self.client.transaction_receipt(TransactionId::Hash(hash)); - Box::new(future::ok(receipt.map(Into::into))) + if self.options.allow_pending_receipt_query { + let best_block = self.client.chain_info().best_block_number; + if let Some(receipt) = self.miner.pending_receipt(best_block, &hash) { + return Box::new(future::ok(Some(receipt.into()))); } } + + let receipt = self.client.transaction_receipt(TransactionId::Hash(hash)); + Box::new(future::ok(receipt.map(Into::into))) } fn uncle_by_block_hash_and_index(&self, hash: RpcH256, index: Index) -> BoxFuture> { diff --git a/rpc/src/v1/impls/light/eth.rs b/rpc/src/v1/impls/light/eth.rs index 77c59e11c0a..d03b2c002fb 100644 --- a/rpc/src/v1/impls/light/eth.rs +++ b/rpc/src/v1/impls/light/eth.rs @@ -46,7 +46,7 @@ use v1::helpers::{SyncPollFilter, PollManager}; use v1::helpers::light_fetch::{self, LightFetch}; use v1::traits::Eth; use v1::types::{ - RichBlock, Block, BlockTransactions, BlockNumber, Bytes, SyncStatus, SyncInfo, + RichBlock, Block, BlockTransactions, BlockNumber, LightBlockNumber, Bytes, SyncStatus, SyncInfo, Transaction, CallRequest, Index, Filter, Log, Receipt, Work, H64 as RpcH64, H256 as RpcH256, H160 as RpcH160, U256 as RpcU256, }; @@ -67,23 +67,6 @@ pub struct EthClient { gas_price_percentile: usize, } -impl EthClient { - fn num_to_id(num: BlockNumber) -> BlockId { - // Note: Here we treat `Pending` as `Latest`. - // Since light clients don't produce pending blocks - // (they don't have state) we can safely fallback to `Latest`. - match num { - BlockNumber::Num(n) => BlockId::Number(n), - BlockNumber::Earliest => BlockId::Earliest, - BlockNumber::Latest => BlockId::Latest, - BlockNumber::Pending => { - warn!("`Pending` is deprecated and may be removed in future versions. Falling back to `Latest`"); - BlockId::Latest - } - } - } -} - impl Clone for EthClient { fn clone(&self) -> Self { // each instance should have its own poll manager. @@ -285,7 +268,7 @@ impl Eth for EthClient { } fn balance(&self, address: RpcH160, num: Trailing) -> BoxFuture { - Box::new(self.fetcher().account(address.into(), Self::num_to_id(num.unwrap_or_default())) + Box::new(self.fetcher().account(address.into(), num.unwrap_or_default().to_block_id()) .map(|acc| acc.map_or(0.into(), |a| a.balance).into())) } @@ -298,11 +281,11 @@ impl Eth for EthClient { } fn block_by_number(&self, num: BlockNumber, include_txs: bool) -> BoxFuture> { - Box::new(self.rich_block(Self::num_to_id(num), include_txs).map(Some)) + Box::new(self.rich_block(num.to_block_id(), include_txs).map(Some)) } fn transaction_count(&self, address: RpcH160, num: Trailing) -> BoxFuture { - Box::new(self.fetcher().account(address.into(), Self::num_to_id(num.unwrap_or_default())) + Box::new(self.fetcher().account(address.into(), num.unwrap_or_default().to_block_id()) .map(|acc| acc.map_or(0.into(), |a| a.nonce).into())) } @@ -325,7 +308,7 @@ impl Eth for EthClient { fn block_transaction_count_by_number(&self, num: BlockNumber) -> BoxFuture> { let (sync, on_demand) = (self.sync.clone(), self.on_demand.clone()); - Box::new(self.fetcher().header(Self::num_to_id(num)).and_then(move |hdr| { + Box::new(self.fetcher().header(num.to_block_id()).and_then(move |hdr| { if hdr.transactions_root() == KECCAK_NULL_RLP { Either::A(future::ok(Some(U256::from(0).into()))) } else { @@ -357,7 +340,7 @@ impl Eth for EthClient { fn block_uncles_count_by_number(&self, num: BlockNumber) -> BoxFuture> { let (sync, on_demand) = (self.sync.clone(), self.on_demand.clone()); - Box::new(self.fetcher().header(Self::num_to_id(num)).and_then(move |hdr| { + Box::new(self.fetcher().header(num.to_block_id()).and_then(move |hdr| { if hdr.uncles_hash() == KECCAK_EMPTY_LIST_RLP { Either::B(future::ok(Some(U256::from(0).into()))) } else { @@ -371,7 +354,7 @@ impl Eth for EthClient { } fn code_at(&self, address: RpcH160, num: Trailing) -> BoxFuture { - Box::new(self.fetcher().code(address.into(), Self::num_to_id(num.unwrap_or_default())).map(Into::into)) + Box::new(self.fetcher().code(address.into(), num.unwrap_or_default().to_block_id()).map(Into::into)) } fn send_raw_transaction(&self, raw: Bytes) -> Result { @@ -438,7 +421,7 @@ impl Eth for EthClient { } fn transaction_by_block_number_and_index(&self, num: BlockNumber, idx: Index) -> BoxFuture> { - Box::new(self.fetcher().block(Self::num_to_id(num)).map(move |block| { + Box::new(self.fetcher().block(num.to_block_id()).map(move |block| { light_fetch::extract_transaction_at_index(block, idx.value()) })) } @@ -482,7 +465,7 @@ impl Eth for EthClient { fn uncle_by_block_number_and_index(&self, num: BlockNumber, idx: Index) -> BoxFuture> { let client = self.client.clone(); - Box::new(self.fetcher().block(Self::num_to_id(num)).map(move |block| { + Box::new(self.fetcher().block(num.to_block_id()).map(move |block| { extract_uncle_at_index(block, idx, client) })) } diff --git a/rpc/src/v1/impls/light/parity.rs b/rpc/src/v1/impls/light/parity.rs index f74886e619f..4ab456e6836 100644 --- a/rpc/src/v1/impls/light/parity.rs +++ b/rpc/src/v1/impls/light/parity.rs @@ -26,7 +26,6 @@ use ethstore::random_phrase; use sync::LightSyncProvider; use ethcore::account_provider::AccountProvider; use ethcore_logger::RotatingLogger; -use ethcore::ids::BlockId; use light::client::LightChainClient; @@ -42,9 +41,9 @@ use v1::types::{ Bytes, U256, U64, H160, H256, H512, CallRequest, Peers, Transaction, RpcSettings, Histogram, TransactionStats, LocalTransactionStatus, - BlockNumber, ConsensusCapability, VersionInfo, + BlockNumber, LightBlockNumber, ConsensusCapability, VersionInfo, OperationsInfo, ChainStatus, - AccountInfo, HwAccountInfo, Header, RichHeader, + AccountInfo, HwAccountInfo, Header, RichHeader, Receipt, }; use Host; @@ -403,18 +402,15 @@ impl Parity for ParityClient { extra_info: extra_info, }) }; - // Note: Here we treat `Pending` as `Latest`. - // Since light clients don't produce pending blocks - // (they don't have state) we can safely fallback to `Latest`. - let id = match number.unwrap_or_default() { - BlockNumber::Num(n) => BlockId::Number(n), - BlockNumber::Earliest => BlockId::Earliest, - BlockNumber::Latest | BlockNumber::Pending => BlockId::Latest, - }; - + let id = number.unwrap_or_default().to_block_id(); Box::new(self.fetcher().header(id).and_then(from_encoded)) } + fn block_receipts(&self, number: Trailing) -> BoxFuture> { + let id = number.unwrap_or_default().to_block_id(); + Box::new(self.fetcher().receipts(id).and_then(|receipts| Ok(receipts.into_iter().map(Into::into).collect()))) + } + fn ipfs_cid(&self, content: Bytes) -> Result { ipfs::cid(content) } diff --git a/rpc/src/v1/impls/parity.rs b/rpc/src/v1/impls/parity.rs index 3e20d582141..bbf75411eae 100644 --- a/rpc/src/v1/impls/parity.rs +++ b/rpc/src/v1/impls/parity.rs @@ -45,7 +45,7 @@ use v1::types::{ TransactionStats, LocalTransactionStatus, BlockNumber, ConsensusCapability, VersionInfo, OperationsInfo, ChainStatus, - AccountInfo, HwAccountInfo, RichHeader, + AccountInfo, HwAccountInfo, RichHeader, Receipt, block_number_to_id }; use Host; @@ -332,7 +332,7 @@ impl Parity for ParityClient where fn ws_url(&self) -> Result { helpers::to_url(&self.ws_address) - .ok_or_else(|| errors::ws_disabled()) + .ok_or_else(errors::ws_disabled) } fn next_nonce(&self, address: H160) -> BoxFuture { @@ -387,7 +387,8 @@ impl Parity for ParityClient where let (header, extra) = if number == BlockNumber::Pending { let info = self.client.chain_info(); - let header = try_bf!(self.miner.pending_block_header(info.best_block_number).ok_or(errors::unknown_block())); + let header = + try_bf!(self.miner.pending_block_header(info.best_block_number).ok_or_else(errors::unknown_block)); (header.encoded(), None) } else { @@ -398,7 +399,7 @@ impl Parity for ParityClient where BlockNumber::Pending => unreachable!(), // Already covered }; - let header = try_bf!(self.client.block_header(id.clone()).ok_or(errors::unknown_block())); + let header = try_bf!(self.client.block_header(id.clone()).ok_or_else(errors::unknown_block)); let info = self.client.block_extra_info(id).expect(EXTRA_INFO_PROOF); (header, Some(info)) @@ -410,6 +411,27 @@ impl Parity for ParityClient where })) } + fn block_receipts(&self, number: Trailing) -> BoxFuture> { + let number = number.unwrap_or_default(); + + let id = match number { + BlockNumber::Pending => { + let info = self.client.chain_info(); + let receipts = try_bf!(self.miner.pending_receipts(info.best_block_number).ok_or_else(errors::unknown_block)); + return Box::new(future::ok(receipts + .into_iter() + .map(Into::into) + .collect() + )) + }, + BlockNumber::Num(num) => BlockId::Number(num), + BlockNumber::Earliest => BlockId::Earliest, + BlockNumber::Latest => BlockId::Latest, + }; + let receipts = try_bf!(self.client.block_receipts(id).ok_or_else(errors::unknown_block)); + Box::new(future::ok(receipts.into_iter().map(Into::into).collect())) + } + fn ipfs_cid(&self, content: Bytes) -> Result { ipfs::cid(content) } @@ -427,8 +449,8 @@ impl Parity for ParityClient where let (mut state, header) = if num == BlockNumber::Pending { let info = self.client.chain_info(); - let state = self.miner.pending_state(info.best_block_number).ok_or(errors::state_pruned())?; - let header = self.miner.pending_block_header(info.best_block_number).ok_or(errors::state_pruned())?; + let state = self.miner.pending_state(info.best_block_number).ok_or_else(errors::state_pruned)?; + let header = self.miner.pending_block_header(info.best_block_number).ok_or_else(errors::state_pruned)?; (state, header) } else { @@ -439,8 +461,8 @@ impl Parity for ParityClient where BlockNumber::Pending => unreachable!(), // Already covered }; - let state = self.client.state_at(id).ok_or(errors::state_pruned())?; - let header = self.client.block_header(id).ok_or(errors::state_pruned())?.decode().map_err(errors::decode)?; + let state = self.client.state_at(id).ok_or_else(errors::state_pruned)?; + let header = self.client.block_header(id).ok_or_else(errors::state_pruned)?.decode().map_err(errors::decode)?; (state, header) }; diff --git a/rpc/src/v1/tests/helpers/miner_service.rs b/rpc/src/v1/tests/helpers/miner_service.rs index e26290e48eb..088b1d45ddb 100644 --- a/rpc/src/v1/tests/helpers/miner_service.rs +++ b/rpc/src/v1/tests/helpers/miner_service.rs @@ -28,7 +28,7 @@ use ethcore::error::Error; use ethcore::header::{BlockNumber, Header}; use ethcore::ids::BlockId; use ethcore::miner::{self, MinerService, AuthoringParams}; -use ethcore::receipt::{Receipt, RichReceipt}; +use ethcore::receipt::RichReceipt; use ethereum_types::{H256, U256, Address}; use miner::pool::local_transactions::Status as LocalTransactionStatus; use miner::pool::{verifier, VerifiedTransaction, QueueStatus}; @@ -46,7 +46,7 @@ pub struct TestMinerService { /// Pre-existed local transactions pub local_transactions: Mutex>, /// Pre-existed pending receipts - pub pending_receipts: Mutex>, + pub pending_receipts: Mutex>, /// Next nonces. pub next_nonces: RwLock>, /// Password held by Engine. @@ -58,11 +58,11 @@ pub struct TestMinerService { impl Default for TestMinerService { fn default() -> TestMinerService { TestMinerService { - imported_transactions: Mutex::new(Vec::new()), - pending_transactions: Mutex::new(HashMap::new()), - local_transactions: Mutex::new(BTreeMap::new()), - pending_receipts: Mutex::new(BTreeMap::new()), - next_nonces: RwLock::new(HashMap::new()), + imported_transactions: Default::default(), + pending_transactions: Default::default(), + local_transactions: Default::default(), + pending_receipts: Default::default(), + next_nonces: Default::default(), password: RwLock::new("".into()), authoring_params: RwLock::new(AuthoringParams { author: Address::zero(), @@ -230,23 +230,7 @@ impl MinerService for TestMinerService { }).collect() } - fn pending_receipt(&self, _best_block: BlockNumber, hash: &H256) -> Option { - // Not much point implementing this since the logic is complex and the only thing it relies on is pending_receipts, which is already tested. - self.pending_receipts(0).unwrap().get(hash).map(|r| - RichReceipt { - transaction_hash: Default::default(), - transaction_index: Default::default(), - cumulative_gas_used: r.gas_used.clone(), - gas_used: r.gas_used.clone(), - contract_address: None, - logs: r.logs.clone(), - log_bloom: r.log_bloom, - outcome: r.outcome.clone(), - } - ) - } - - fn pending_receipts(&self, _best_block: BlockNumber) -> Option> { + fn pending_receipts(&self, _best_block: BlockNumber) -> Option> { Some(self.pending_receipts.lock().clone()) } diff --git a/rpc/src/v1/tests/mocked/parity.rs b/rpc/src/v1/tests/mocked/parity.rs index 68251d30b9b..8ac8e44eb29 100644 --- a/rpc/src/v1/tests/mocked/parity.rs +++ b/rpc/src/v1/tests/mocked/parity.rs @@ -16,7 +16,8 @@ use std::sync::Arc; use ethcore::account_provider::AccountProvider; -use ethcore::client::{TestBlockChainClient, Executed}; +use ethcore::client::{TestBlockChainClient, Executed, TransactionId}; +use ethcore::receipt::{LocalizedReceipt, TransactionOutcome}; use ethcore_logger::RotatingLogger; use ethereum_types::{Address, U256, H256}; use ethstore::ethkey::{Generator, Random}; @@ -531,3 +532,34 @@ fn rpc_parity_call() { assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); } + +#[test] +fn rpc_parity_block_receipts() { + let deps = Dependencies::new(); + deps.client.receipts.write() + .insert(TransactionId::Hash(1.into()), LocalizedReceipt { + transaction_hash: 1.into(), + transaction_index: 0, + block_hash: 3.into(), + block_number: 0, + cumulative_gas_used: 21_000.into(), + gas_used: 21_000.into(), + contract_address: None, + logs: vec![], + log_bloom: 1.into(), + outcome: TransactionOutcome::Unknown, + to: None, + from: 9.into(), + }); + let io = deps.default_client(); + + let request = r#"{ + "jsonrpc": "2.0", + "method": "parity_getBlockReceipts", + "params": [], + "id": 1 + }"#; + let response = r#"{"jsonrpc":"2.0","result":[{"blockHash":"0x0000000000000000000000000000000000000000000000000000000000000003","blockNumber":"0x0","contractAddress":null,"cumulativeGasUsed":"0x5208","from":"0x0000000000000000000000000000000000000009","gasUsed":"0x5208","logs":[],"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001","root":null,"status":null,"to":null,"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000001","transactionIndex":"0x0"}],"id":1}"#; + + assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); +} diff --git a/rpc/src/v1/traits/parity.rs b/rpc/src/v1/traits/parity.rs index 76df05bbc64..c71e6d8dc6a 100644 --- a/rpc/src/v1/traits/parity.rs +++ b/rpc/src/v1/traits/parity.rs @@ -27,7 +27,7 @@ use v1::types::{ TransactionStats, LocalTransactionStatus, BlockNumber, ConsensusCapability, VersionInfo, OperationsInfo, ChainStatus, - AccountInfo, HwAccountInfo, RichHeader, + AccountInfo, HwAccountInfo, RichHeader, Receipt, }; build_rpc_trait! { @@ -211,6 +211,12 @@ build_rpc_trait! { #[rpc(name = "parity_getBlockHeaderByNumber")] fn block_header(&self, Trailing) -> BoxFuture; + /// Get block receipts. + /// Allows you to fetch receipts from the entire block at once. + /// If no parameter is provided defaults to `latest`. + #[rpc(name = "parity_getBlockReceipts")] + fn block_receipts(&self, Trailing) -> BoxFuture>; + /// Get IPFS CIDv0 given protobuf encoded bytes. #[rpc(name = "parity_cidV0")] fn ipfs_cid(&self, Bytes) -> Result; diff --git a/rpc/src/v1/types/block_number.rs b/rpc/src/v1/types/block_number.rs index b92a0d4a3fe..085886998e2 100644 --- a/rpc/src/v1/types/block_number.rs +++ b/rpc/src/v1/types/block_number.rs @@ -54,6 +54,31 @@ impl BlockNumber { } } +/// BlockNumber to BlockId conversion +/// +/// NOTE use only for light clients. +pub trait LightBlockNumber { + /// Convert block number to block id. + fn to_block_id(self) -> BlockId; +} + +impl LightBlockNumber for BlockNumber { + fn to_block_id(self) -> BlockId { + // NOTE Here we treat `Pending` as `Latest`. + // Since light clients don't produce pending blocks + // (they don't have state) we can safely fallback to `Latest`. + match self { + BlockNumber::Num(n) => BlockId::Number(n), + BlockNumber::Earliest => BlockId::Earliest, + BlockNumber::Latest => BlockId::Latest, + BlockNumber::Pending => { + warn!("`Pending` is deprecated and may be removed in future versions. Falling back to `Latest`"); + BlockId::Latest + } + } + } +} + impl Serialize for BlockNumber { fn serialize(&self, serializer: S) -> Result where S: Serializer { match *self { diff --git a/rpc/src/v1/types/mod.rs b/rpc/src/v1/types/mod.rs index fe35dd50a09..eb8c0dc226c 100644 --- a/rpc/src/v1/types/mod.rs +++ b/rpc/src/v1/types/mod.rs @@ -49,7 +49,7 @@ pub mod pubsub; pub use self::account_info::{AccountInfo, ExtAccountInfo, HwAccountInfo}; pub use self::bytes::Bytes; pub use self::block::{RichBlock, Block, BlockTransactions, Header, RichHeader, Rich}; -pub use self::block_number::{BlockNumber, block_number_to_id}; +pub use self::block_number::{BlockNumber, LightBlockNumber, block_number_to_id}; pub use self::call_request::CallRequest; pub use self::confirmations::{ ConfirmationPayload, ConfirmationRequest, ConfirmationResponse, ConfirmationResponseWithToken, diff --git a/secret_store/src/key_server_cluster/cluster.rs b/secret_store/src/key_server_cluster/cluster.rs index b48290a4fc3..1c0986aadff 100644 --- a/secret_store/src/key_server_cluster/cluster.rs +++ b/secret_store/src/key_server_cluster/cluster.rs @@ -1431,7 +1431,11 @@ pub mod tests { } } + // test ignored because of + // + // https://github.com/paritytech/parity-ethereum/issues/9635 #[test] + #[ignore] fn schnorr_signing_session_completes_if_node_does_not_have_a_share() { //::logger::init_log(); let mut core = Core::new().unwrap(); @@ -1480,7 +1484,11 @@ pub mod tests { session1.wait().unwrap_err(); } + // test ignored because of + // + // https://github.com/paritytech/parity-ethereum/issues/9635 #[test] + #[ignore] fn ecdsa_signing_session_completes_if_node_does_not_have_a_share() { //::logger::init_log(); let mut core = Core::new().unwrap(); diff --git a/test.sh b/test.sh index 83d07b78bc9..a3ed39e8d2c 100755 --- a/test.sh +++ b/test.sh @@ -1,7 +1,7 @@ #!/bin/sh # Running Parity Full Test Suite -FEATURES="json-tests" +FEATURES="json-tests,ci-skip-issue" OPTIONS="--release" VALIDATE=1 diff --git a/util/journaldb/src/overlayrecentdb.rs b/util/journaldb/src/overlayrecentdb.rs index f9e4caa98c3..017447bcc4b 100644 --- a/util/journaldb/src/overlayrecentdb.rs +++ b/util/journaldb/src/overlayrecentdb.rs @@ -468,7 +468,6 @@ impl HashDB for OverlayRecentDB { let journal_overlay = self.journal_overlay.read(); let key = to_short_key(key); journal_overlay.backing_overlay.get(&key) - // .or_else(move || journal_overlay.pending_overlay.get(&key)) .or_else(|| journal_overlay.pending_overlay.get(&key).cloned()) }; v.or_else(|| self.payload(key)) diff --git a/whisper/Cargo.toml b/whisper/Cargo.toml index 02d0e6dbb42..fa1c209b62c 100644 --- a/whisper/Cargo.toml +++ b/whisper/Cargo.toml @@ -22,7 +22,7 @@ serde = "1.0" serde_derive = "1.0" serde_json = "1.0" slab = "0.3" -smallvec = "0.4" +smallvec = "0.6" tiny-keccak = "1.4" jsonrpc-core = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-1.11" }