Merge branch 'master' into sync-svc

This commit is contained in:
NikVolf 2016-07-16 15:57:30 +02:00
commit be25e930e5
51 changed files with 28433 additions and 1011 deletions

View File

@ -1,6 +1,7 @@
sudo: required sudo: required
dist: trusty dist: trusty
language: rust language: rust
branches: branches:
only: only:
- master - master
@ -51,14 +52,15 @@ addons:
install: install:
- rm -rf ~/.nvm && git clone https://github.com/creationix/nvm.git ~/.nvm && (cd ~/.nvm && git checkout `git describe --abbrev=0 --tags`) && source ~/.nvm/nvm.sh && nvm install $TRAVIS_NODE_VERSION - rm -rf ~/.nvm && git clone https://github.com/creationix/nvm.git ~/.nvm && (cd ~/.nvm && git checkout `git describe --abbrev=0 --tags`) && source ~/.nvm/nvm.sh && nvm install $TRAVIS_NODE_VERSION
- (true && [ "$RUN_COVERAGE" = "false" ]) || - ([ "$RUN_COVERAGE" = "false" ]) || (test -x $KCOV_CMD) || (
(wget https://github.com/SimonKagstrom/kcov/archive/master.tar.gz && wget https://github.com/SimonKagstrom/kcov/archive/master.tar.gz &&
tar xzf master.tar.gz && tar xzf master.tar.gz &&
mkdir -p kcov-master/build && mkdir -p kcov-master/build &&
cd kcov-master/build && cd kcov-master/build &&
cmake .. && cmake .. &&
make && make install DESTDIR=../tmp && make && make install DESTDIR=../tmp &&
cd) cd
)
script: script:
- if [ "$RUN_TESTS" = "true" ]; then ./test.sh; fi - if [ "$RUN_TESTS" = "true" ]; then ./test.sh; fi

15
Cargo.lock generated
View File

@ -21,6 +21,7 @@ dependencies = [
"ethsync 1.3.0", "ethsync 1.3.0",
"fdlimit 0.1.0", "fdlimit 0.1.0",
"hyper 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
"isatty 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"json-ipc-server 0.2.4 (git+https://github.com/ethcore/json-ipc-server.git)", "json-ipc-server 0.2.4 (git+https://github.com/ethcore/json-ipc-server.git)",
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
@ -586,6 +587,16 @@ dependencies = [
"xmltree 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "xmltree 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "isatty"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "itertools" name = "itertools"
version = "0.4.13" version = "0.4.13"
@ -1068,7 +1079,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "rocksdb" name = "rocksdb"
version = "0.4.5" version = "0.4.5"
source = "git+https://github.com/ethcore/rust-rocksdb#9be41e05923616dfa28741c58b22776d479751e6" source = "git+https://github.com/ethcore/rust-rocksdb#6472a9dce16c267a3acec2ee6fd01d1bf8de4913"
dependencies = [ dependencies = [
"libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
"rocksdb-sys 0.3.0 (git+https://github.com/ethcore/rust-rocksdb)", "rocksdb-sys 0.3.0 (git+https://github.com/ethcore/rust-rocksdb)",
@ -1077,7 +1088,7 @@ dependencies = [
[[package]] [[package]]
name = "rocksdb-sys" name = "rocksdb-sys"
version = "0.3.0" version = "0.3.0"
source = "git+https://github.com/ethcore/rust-rocksdb#9be41e05923616dfa28741c58b22776d479751e6" source = "git+https://github.com/ethcore/rust-rocksdb#6472a9dce16c267a3acec2ee6fd01d1bf8de4913"
dependencies = [ dependencies = [
"gcc 0.3.28 (registry+https://github.com/rust-lang/crates.io-index)", "gcc 0.3.28 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",

View File

@ -24,6 +24,7 @@ semver = "0.2"
ansi_term = "0.7" ansi_term = "0.7"
lazy_static = "0.2" lazy_static = "0.2"
regex = "0.1" regex = "0.1"
isatty = "0.1"
ctrlc = { git = "https://github.com/ethcore/rust-ctrlc.git" } ctrlc = { git = "https://github.com/ethcore/rust-ctrlc.git" }
fdlimit = { path = "util/fdlimit" } fdlimit = { path = "util/fdlimit" }
ethcore = { path = "ethcore" } ethcore = { path = "ethcore" }

View File

@ -0,0 +1,162 @@
{
"name": "DAO hard-fork consensus test",
"engine": {
"Ethash": {
"params": {
"gasLimitBoundDivisor": "0x0400",
"minimumDifficulty": "0x020000",
"difficultyBoundDivisor": "0x0800",
"durationLimit": "0x0d",
"blockReward": "0x4563918244F40000",
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
"frontierCompatibilityModeLimit": "0x5",
"daoHardforkTransition": "0x8",
"daoHardforkBeneficiary": "0xbf4ed7b27f1d666546e30d74d50d173d20bca754",
"daoHardforkAccounts": [
"0xd4fe7bc31cedb7bfb8a345f31e668033056b2728",
"0xb3fb0e5aba0e20e5c49d252dfd30e102b171a425",
"0x2c19c7f9ae8b751e37aeb2d93a699722395ae18f",
"0xecd135fa4f61a655311e86238c92adcd779555d2",
"0x1975bd06d486162d5dc297798dfc41edd5d160a7",
"0xa3acf3a1e16b1d7c315e23510fdd7847b48234f6",
"0x319f70bab6845585f412ec7724b744fec6095c85",
"0x06706dd3f2c9abf0a21ddcc6941d9b86f0596936",
"0x5c8536898fbb74fc7445814902fd08422eac56d0",
"0x6966ab0d485353095148a2155858910e0965b6f9",
"0x779543a0491a837ca36ce8c635d6154e3c4911a6",
"0x2a5ed960395e2a49b1c758cef4aa15213cfd874c",
"0x5c6e67ccd5849c0d29219c4f95f1a7a93b3f5dc5",
"0x9c50426be05db97f5d64fc54bf89eff947f0a321",
"0x200450f06520bdd6c527622a273333384d870efb",
"0xbe8539bfe837b67d1282b2b1d61c3f723966f049",
"0x6b0c4d41ba9ab8d8cfb5d379c69a612f2ced8ecb",
"0xf1385fb24aad0cd7432824085e42aff90886fef5",
"0xd1ac8b1ef1b69ff51d1d401a476e7e612414f091",
"0x8163e7fb499e90f8544ea62bbf80d21cd26d9efd",
"0x51e0ddd9998364a2eb38588679f0d2c42653e4a6",
"0x627a0a960c079c21c34f7612d5d230e01b4ad4c7",
"0xf0b1aa0eb660754448a7937c022e30aa692fe0c5",
"0x24c4d950dfd4dd1902bbed3508144a54542bba94",
"0x9f27daea7aca0aa0446220b98d028715e3bc803d",
"0xa5dc5acd6a7968a4554d89d65e59b7fd3bff0f90",
"0xd9aef3a1e38a39c16b31d1ace71bca8ef58d315b",
"0x63ed5a272de2f6d968408b4acb9024f4cc208ebf",
"0x6f6704e5a10332af6672e50b3d9754dc460dfa4d",
"0x77ca7b50b6cd7e2f3fa008e24ab793fd56cb15f6",
"0x492ea3bb0f3315521c31f273e565b868fc090f17",
"0x0ff30d6de14a8224aa97b78aea5388d1c51c1f00",
"0x9ea779f907f0b315b364b0cfc39a0fde5b02a416",
"0xceaeb481747ca6c540a000c1f3641f8cef161fa7",
"0xcc34673c6c40e791051898567a1222daf90be287",
"0x579a80d909f346fbfb1189493f521d7f48d52238",
"0xe308bd1ac5fda103967359b2712dd89deffb7973",
"0x4cb31628079fb14e4bc3cd5e30c2f7489b00960c",
"0xac1ecab32727358dba8962a0f3b261731aad9723",
"0x4fd6ace747f06ece9c49699c7cabc62d02211f75",
"0x440c59b325d2997a134c2c7c60a8c61611212bad",
"0x4486a3d68fac6967006d7a517b889fd3f98c102b",
"0x9c15b54878ba618f494b38f0ae7443db6af648ba",
"0x27b137a85656544b1ccb5a0f2e561a5703c6a68f",
"0x21c7fdb9ed8d291d79ffd82eb2c4356ec0d81241",
"0x23b75c2f6791eef49c69684db4c6c1f93bf49a50",
"0x1ca6abd14d30affe533b24d7a21bff4c2d5e1f3b",
"0xb9637156d330c0d605a791f1c31ba5890582fe1c",
"0x6131c42fa982e56929107413a9d526fd99405560",
"0x1591fc0f688c81fbeb17f5426a162a7024d430c2",
"0x542a9515200d14b68e934e9830d91645a980dd7a",
"0xc4bbd073882dd2add2424cf47d35213405b01324",
"0x782495b7b3355efb2833d56ecb34dc22ad7dfcc4",
"0x58b95c9a9d5d26825e70a82b6adb139d3fd829eb",
"0x3ba4d81db016dc2890c81f3acec2454bff5aada5",
"0xb52042c8ca3f8aa246fa79c3feaa3d959347c0ab",
"0xe4ae1efdfc53b73893af49113d8694a057b9c0d1",
"0x3c02a7bc0391e86d91b7d144e61c2c01a25a79c5",
"0x0737a6b837f97f46ebade41b9bc3e1c509c85c53",
"0x97f43a37f595ab5dd318fb46e7a155eae057317a",
"0x52c5317c848ba20c7504cb2c8052abd1fde29d03",
"0x4863226780fe7c0356454236d3b1c8792785748d",
"0x5d2b2e6fcbe3b11d26b525e085ff818dae332479",
"0x5f9f3392e9f62f63b8eac0beb55541fc8627f42c",
"0x057b56736d32b86616a10f619859c6cd6f59092a",
"0x9aa008f65de0b923a2a4f02012ad034a5e2e2192",
"0x304a554a310c7e546dfe434669c62820b7d83490",
"0x914d1b8b43e92723e64fd0a06f5bdb8dd9b10c79",
"0x4deb0033bb26bc534b197e61d19e0733e5679784",
"0x07f5c1e1bc2c93e0402f23341973a0e043f7bf8a",
"0x35a051a0010aba705c9008d7a7eff6fb88f6ea7b",
"0x4fa802324e929786dbda3b8820dc7834e9134a2a",
"0x9da397b9e80755301a3b32173283a91c0ef6c87e",
"0x8d9edb3054ce5c5774a420ac37ebae0ac02343c6",
"0x0101f3be8ebb4bbd39a2e3b9a3639d4259832fd9",
"0x5dc28b15dffed94048d73806ce4b7a4612a1d48f",
"0xbcf899e6c7d9d5a215ab1e3444c86806fa854c76",
"0x12e626b0eebfe86a56d633b9864e389b45dcb260",
"0xa2f1ccba9395d7fcb155bba8bc92db9bafaeade7",
"0xec8e57756626fdc07c63ad2eafbd28d08e7b0ca5",
"0xd164b088bd9108b60d0ca3751da4bceb207b0782",
"0x6231b6d0d5e77fe001c2a460bd9584fee60d409b",
"0x1cba23d343a983e9b5cfd19496b9a9701ada385f",
"0xa82f360a8d3455c5c41366975bde739c37bfeb8a",
"0x9fcd2deaff372a39cc679d5c5e4de7bafb0b1339",
"0x005f5cee7a43331d5a3d3eec71305925a62f34b6",
"0x0e0da70933f4c7849fc0d203f5d1d43b9ae4532d",
"0xd131637d5275fd1a68a3200f4ad25c71a2a9522e",
"0xbc07118b9ac290e4622f5e77a0853539789effbe",
"0x47e7aa56d6bdf3f36be34619660de61275420af8",
"0xacd87e28b0c9d1254e868b81cba4cc20d9a32225",
"0xadf80daec7ba8dcf15392f1ac611fff65d94f880",
"0x5524c55fb03cf21f549444ccbecb664d0acad706",
"0x40b803a9abce16f50f36a77ba41180eb90023925",
"0xfe24cdd8648121a43a7c86d289be4dd2951ed49f",
"0x17802f43a0137c506ba92291391a8a8f207f487d",
"0x253488078a4edf4d6f42f113d1e62836a942cf1a",
"0x86af3e9626fce1957c82e88cbf04ddf3a2ed7915",
"0xb136707642a4ea12fb4bae820f03d2562ebff487",
"0xdbe9b615a3ae8709af8b93336ce9b477e4ac0940",
"0xf14c14075d6c4ed84b86798af0956deef67365b5",
"0xca544e5c4687d109611d0f8f928b53a25af72448",
"0xaeeb8ff27288bdabc0fa5ebb731b6f409507516c",
"0xcbb9d3703e651b0d496cdefb8b92c25aeb2171f7",
"0x6d87578288b6cb5549d5076a207456a1f6a63dc0",
"0xb2c6f0dfbb716ac562e2d85d6cb2f8d5ee87603e",
"0xaccc230e8a6e5be9160b8cdf2864dd2a001c28b6",
"0x2b3455ec7fedf16e646268bf88846bd7a2319bb2",
"0x4613f3bca5c44ea06337a9e439fbc6d42e501d0a",
"0xd343b217de44030afaa275f54d31a9317c7f441e",
"0x84ef4b2357079cd7a7c69fd7a37cd0609a679106",
"0xda2fef9e4a3230988ff17df2165440f37e8b1708",
"0xf4c64518ea10f995918a454158c6b61407ea345c",
"0x7602b46df5390e432ef1c307d4f2c9ff6d65cc97",
"0xbb9bc244d798123fde783fcc1c72d3bb8c189413",
"0x807640a13483f8ac783c557fcdf27be11ea4ac7a"
]
}
}
},
"params": {
"accountStartNonce": "0x00",
"maximumExtraDataSize": "0x20",
"minGasLimit": "0x1388",
"networkID" : "0x1"
},
"genesis": {
"seal": {
"ethereum": {
"nonce": "0x0000000000000042",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
}
},
"difficulty": "0x400000000",
"author": "0x0000000000000000000000000000000000000000",
"timestamp": "0x00",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"extraData": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa",
"gasLimit": "0x1388"
},
"accounts": {
"0000000000000000000000000000000000000001": { "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } },
"0000000000000000000000000000000000000002": { "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } },
"0000000000000000000000000000000000000003": { "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } },
"0000000000000000000000000000000000000004": { "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }
}
}

File diff suppressed because it is too large Load Diff

View File

@ -9,7 +9,127 @@
"durationLimit": "0x0d", "durationLimit": "0x0d",
"blockReward": "0x4563918244F40000", "blockReward": "0x4563918244F40000",
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b", "registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
"frontierCompatibilityModeLimit": "0x118c30" "frontierCompatibilityModeLimit": "0x118c30",
"daoHardforkTransition": "0x1d4c00",
"daoHardforkBeneficiary": "0xbf4ed7b27f1d666546e30d74d50d173d20bca754",
"daoHardforkAccounts": [
"0xd4fe7bc31cedb7bfb8a345f31e668033056b2728",
"0xb3fb0e5aba0e20e5c49d252dfd30e102b171a425",
"0x2c19c7f9ae8b751e37aeb2d93a699722395ae18f",
"0xecd135fa4f61a655311e86238c92adcd779555d2",
"0x1975bd06d486162d5dc297798dfc41edd5d160a7",
"0xa3acf3a1e16b1d7c315e23510fdd7847b48234f6",
"0x319f70bab6845585f412ec7724b744fec6095c85",
"0x06706dd3f2c9abf0a21ddcc6941d9b86f0596936",
"0x5c8536898fbb74fc7445814902fd08422eac56d0",
"0x6966ab0d485353095148a2155858910e0965b6f9",
"0x779543a0491a837ca36ce8c635d6154e3c4911a6",
"0x2a5ed960395e2a49b1c758cef4aa15213cfd874c",
"0x5c6e67ccd5849c0d29219c4f95f1a7a93b3f5dc5",
"0x9c50426be05db97f5d64fc54bf89eff947f0a321",
"0x200450f06520bdd6c527622a273333384d870efb",
"0xbe8539bfe837b67d1282b2b1d61c3f723966f049",
"0x6b0c4d41ba9ab8d8cfb5d379c69a612f2ced8ecb",
"0xf1385fb24aad0cd7432824085e42aff90886fef5",
"0xd1ac8b1ef1b69ff51d1d401a476e7e612414f091",
"0x8163e7fb499e90f8544ea62bbf80d21cd26d9efd",
"0x51e0ddd9998364a2eb38588679f0d2c42653e4a6",
"0x627a0a960c079c21c34f7612d5d230e01b4ad4c7",
"0xf0b1aa0eb660754448a7937c022e30aa692fe0c5",
"0x24c4d950dfd4dd1902bbed3508144a54542bba94",
"0x9f27daea7aca0aa0446220b98d028715e3bc803d",
"0xa5dc5acd6a7968a4554d89d65e59b7fd3bff0f90",
"0xd9aef3a1e38a39c16b31d1ace71bca8ef58d315b",
"0x63ed5a272de2f6d968408b4acb9024f4cc208ebf",
"0x6f6704e5a10332af6672e50b3d9754dc460dfa4d",
"0x77ca7b50b6cd7e2f3fa008e24ab793fd56cb15f6",
"0x492ea3bb0f3315521c31f273e565b868fc090f17",
"0x0ff30d6de14a8224aa97b78aea5388d1c51c1f00",
"0x9ea779f907f0b315b364b0cfc39a0fde5b02a416",
"0xceaeb481747ca6c540a000c1f3641f8cef161fa7",
"0xcc34673c6c40e791051898567a1222daf90be287",
"0x579a80d909f346fbfb1189493f521d7f48d52238",
"0xe308bd1ac5fda103967359b2712dd89deffb7973",
"0x4cb31628079fb14e4bc3cd5e30c2f7489b00960c",
"0xac1ecab32727358dba8962a0f3b261731aad9723",
"0x4fd6ace747f06ece9c49699c7cabc62d02211f75",
"0x440c59b325d2997a134c2c7c60a8c61611212bad",
"0x4486a3d68fac6967006d7a517b889fd3f98c102b",
"0x9c15b54878ba618f494b38f0ae7443db6af648ba",
"0x27b137a85656544b1ccb5a0f2e561a5703c6a68f",
"0x21c7fdb9ed8d291d79ffd82eb2c4356ec0d81241",
"0x23b75c2f6791eef49c69684db4c6c1f93bf49a50",
"0x1ca6abd14d30affe533b24d7a21bff4c2d5e1f3b",
"0xb9637156d330c0d605a791f1c31ba5890582fe1c",
"0x6131c42fa982e56929107413a9d526fd99405560",
"0x1591fc0f688c81fbeb17f5426a162a7024d430c2",
"0x542a9515200d14b68e934e9830d91645a980dd7a",
"0xc4bbd073882dd2add2424cf47d35213405b01324",
"0x782495b7b3355efb2833d56ecb34dc22ad7dfcc4",
"0x58b95c9a9d5d26825e70a82b6adb139d3fd829eb",
"0x3ba4d81db016dc2890c81f3acec2454bff5aada5",
"0xb52042c8ca3f8aa246fa79c3feaa3d959347c0ab",
"0xe4ae1efdfc53b73893af49113d8694a057b9c0d1",
"0x3c02a7bc0391e86d91b7d144e61c2c01a25a79c5",
"0x0737a6b837f97f46ebade41b9bc3e1c509c85c53",
"0x97f43a37f595ab5dd318fb46e7a155eae057317a",
"0x52c5317c848ba20c7504cb2c8052abd1fde29d03",
"0x4863226780fe7c0356454236d3b1c8792785748d",
"0x5d2b2e6fcbe3b11d26b525e085ff818dae332479",
"0x5f9f3392e9f62f63b8eac0beb55541fc8627f42c",
"0x057b56736d32b86616a10f619859c6cd6f59092a",
"0x9aa008f65de0b923a2a4f02012ad034a5e2e2192",
"0x304a554a310c7e546dfe434669c62820b7d83490",
"0x914d1b8b43e92723e64fd0a06f5bdb8dd9b10c79",
"0x4deb0033bb26bc534b197e61d19e0733e5679784",
"0x07f5c1e1bc2c93e0402f23341973a0e043f7bf8a",
"0x35a051a0010aba705c9008d7a7eff6fb88f6ea7b",
"0x4fa802324e929786dbda3b8820dc7834e9134a2a",
"0x9da397b9e80755301a3b32173283a91c0ef6c87e",
"0x8d9edb3054ce5c5774a420ac37ebae0ac02343c6",
"0x0101f3be8ebb4bbd39a2e3b9a3639d4259832fd9",
"0x5dc28b15dffed94048d73806ce4b7a4612a1d48f",
"0xbcf899e6c7d9d5a215ab1e3444c86806fa854c76",
"0x12e626b0eebfe86a56d633b9864e389b45dcb260",
"0xa2f1ccba9395d7fcb155bba8bc92db9bafaeade7",
"0xec8e57756626fdc07c63ad2eafbd28d08e7b0ca5",
"0xd164b088bd9108b60d0ca3751da4bceb207b0782",
"0x6231b6d0d5e77fe001c2a460bd9584fee60d409b",
"0x1cba23d343a983e9b5cfd19496b9a9701ada385f",
"0xa82f360a8d3455c5c41366975bde739c37bfeb8a",
"0x9fcd2deaff372a39cc679d5c5e4de7bafb0b1339",
"0x005f5cee7a43331d5a3d3eec71305925a62f34b6",
"0x0e0da70933f4c7849fc0d203f5d1d43b9ae4532d",
"0xd131637d5275fd1a68a3200f4ad25c71a2a9522e",
"0xbc07118b9ac290e4622f5e77a0853539789effbe",
"0x47e7aa56d6bdf3f36be34619660de61275420af8",
"0xacd87e28b0c9d1254e868b81cba4cc20d9a32225",
"0xadf80daec7ba8dcf15392f1ac611fff65d94f880",
"0x5524c55fb03cf21f549444ccbecb664d0acad706",
"0x40b803a9abce16f50f36a77ba41180eb90023925",
"0xfe24cdd8648121a43a7c86d289be4dd2951ed49f",
"0x17802f43a0137c506ba92291391a8a8f207f487d",
"0x253488078a4edf4d6f42f113d1e62836a942cf1a",
"0x86af3e9626fce1957c82e88cbf04ddf3a2ed7915",
"0xb136707642a4ea12fb4bae820f03d2562ebff487",
"0xdbe9b615a3ae8709af8b93336ce9b477e4ac0940",
"0xf14c14075d6c4ed84b86798af0956deef67365b5",
"0xca544e5c4687d109611d0f8f928b53a25af72448",
"0xaeeb8ff27288bdabc0fa5ebb731b6f409507516c",
"0xcbb9d3703e651b0d496cdefb8b92c25aeb2171f7",
"0x6d87578288b6cb5549d5076a207456a1f6a63dc0",
"0xb2c6f0dfbb716ac562e2d85d6cb2f8d5ee87603e",
"0xaccc230e8a6e5be9160b8cdf2864dd2a001c28b6",
"0x2b3455ec7fedf16e646268bf88846bd7a2319bb2",
"0x4613f3bca5c44ea06337a9e439fbc6d42e501d0a",
"0xd343b217de44030afaa275f54d31a9317c7f441e",
"0x84ef4b2357079cd7a7c69fd7a37cd0609a679106",
"0xda2fef9e4a3230988ff17df2165440f37e8b1708",
"0xf4c64518ea10f995918a454158c6b61407ea345c",
"0x7602b46df5390e432ef1c307d4f2c9ff6d65cc97",
"0xbb9bc244d798123fde783fcc1c72d3bb8c189413",
"0x807640a13483f8ac783c557fcdf27be11ea4ac7a"
]
} }
} }
}, },

View File

@ -9,7 +9,127 @@
"durationLimit": "0x0d", "durationLimit": "0x0d",
"blockReward": "0x4563918244F40000", "blockReward": "0x4563918244F40000",
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b", "registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
"frontierCompatibilityModeLimit": "0x118c30" "frontierCompatibilityModeLimit": "0x118c30",
"daoHardforkTransition": "0x1d4c00",
"daoHardforkBeneficiary": "0xbf4ed7b27f1d666546e30d74d50d173d20bca754",
"daoHardforkAccounts": [
"0xd4fe7bc31cedb7bfb8a345f31e668033056b2728",
"0xb3fb0e5aba0e20e5c49d252dfd30e102b171a425",
"0x2c19c7f9ae8b751e37aeb2d93a699722395ae18f",
"0xecd135fa4f61a655311e86238c92adcd779555d2",
"0x1975bd06d486162d5dc297798dfc41edd5d160a7",
"0xa3acf3a1e16b1d7c315e23510fdd7847b48234f6",
"0x319f70bab6845585f412ec7724b744fec6095c85",
"0x06706dd3f2c9abf0a21ddcc6941d9b86f0596936",
"0x5c8536898fbb74fc7445814902fd08422eac56d0",
"0x6966ab0d485353095148a2155858910e0965b6f9",
"0x779543a0491a837ca36ce8c635d6154e3c4911a6",
"0x2a5ed960395e2a49b1c758cef4aa15213cfd874c",
"0x5c6e67ccd5849c0d29219c4f95f1a7a93b3f5dc5",
"0x9c50426be05db97f5d64fc54bf89eff947f0a321",
"0x200450f06520bdd6c527622a273333384d870efb",
"0xbe8539bfe837b67d1282b2b1d61c3f723966f049",
"0x6b0c4d41ba9ab8d8cfb5d379c69a612f2ced8ecb",
"0xf1385fb24aad0cd7432824085e42aff90886fef5",
"0xd1ac8b1ef1b69ff51d1d401a476e7e612414f091",
"0x8163e7fb499e90f8544ea62bbf80d21cd26d9efd",
"0x51e0ddd9998364a2eb38588679f0d2c42653e4a6",
"0x627a0a960c079c21c34f7612d5d230e01b4ad4c7",
"0xf0b1aa0eb660754448a7937c022e30aa692fe0c5",
"0x24c4d950dfd4dd1902bbed3508144a54542bba94",
"0x9f27daea7aca0aa0446220b98d028715e3bc803d",
"0xa5dc5acd6a7968a4554d89d65e59b7fd3bff0f90",
"0xd9aef3a1e38a39c16b31d1ace71bca8ef58d315b",
"0x63ed5a272de2f6d968408b4acb9024f4cc208ebf",
"0x6f6704e5a10332af6672e50b3d9754dc460dfa4d",
"0x77ca7b50b6cd7e2f3fa008e24ab793fd56cb15f6",
"0x492ea3bb0f3315521c31f273e565b868fc090f17",
"0x0ff30d6de14a8224aa97b78aea5388d1c51c1f00",
"0x9ea779f907f0b315b364b0cfc39a0fde5b02a416",
"0xceaeb481747ca6c540a000c1f3641f8cef161fa7",
"0xcc34673c6c40e791051898567a1222daf90be287",
"0x579a80d909f346fbfb1189493f521d7f48d52238",
"0xe308bd1ac5fda103967359b2712dd89deffb7973",
"0x4cb31628079fb14e4bc3cd5e30c2f7489b00960c",
"0xac1ecab32727358dba8962a0f3b261731aad9723",
"0x4fd6ace747f06ece9c49699c7cabc62d02211f75",
"0x440c59b325d2997a134c2c7c60a8c61611212bad",
"0x4486a3d68fac6967006d7a517b889fd3f98c102b",
"0x9c15b54878ba618f494b38f0ae7443db6af648ba",
"0x27b137a85656544b1ccb5a0f2e561a5703c6a68f",
"0x21c7fdb9ed8d291d79ffd82eb2c4356ec0d81241",
"0x23b75c2f6791eef49c69684db4c6c1f93bf49a50",
"0x1ca6abd14d30affe533b24d7a21bff4c2d5e1f3b",
"0xb9637156d330c0d605a791f1c31ba5890582fe1c",
"0x6131c42fa982e56929107413a9d526fd99405560",
"0x1591fc0f688c81fbeb17f5426a162a7024d430c2",
"0x542a9515200d14b68e934e9830d91645a980dd7a",
"0xc4bbd073882dd2add2424cf47d35213405b01324",
"0x782495b7b3355efb2833d56ecb34dc22ad7dfcc4",
"0x58b95c9a9d5d26825e70a82b6adb139d3fd829eb",
"0x3ba4d81db016dc2890c81f3acec2454bff5aada5",
"0xb52042c8ca3f8aa246fa79c3feaa3d959347c0ab",
"0xe4ae1efdfc53b73893af49113d8694a057b9c0d1",
"0x3c02a7bc0391e86d91b7d144e61c2c01a25a79c5",
"0x0737a6b837f97f46ebade41b9bc3e1c509c85c53",
"0x97f43a37f595ab5dd318fb46e7a155eae057317a",
"0x52c5317c848ba20c7504cb2c8052abd1fde29d03",
"0x4863226780fe7c0356454236d3b1c8792785748d",
"0x5d2b2e6fcbe3b11d26b525e085ff818dae332479",
"0x5f9f3392e9f62f63b8eac0beb55541fc8627f42c",
"0x057b56736d32b86616a10f619859c6cd6f59092a",
"0x9aa008f65de0b923a2a4f02012ad034a5e2e2192",
"0x304a554a310c7e546dfe434669c62820b7d83490",
"0x914d1b8b43e92723e64fd0a06f5bdb8dd9b10c79",
"0x4deb0033bb26bc534b197e61d19e0733e5679784",
"0x07f5c1e1bc2c93e0402f23341973a0e043f7bf8a",
"0x35a051a0010aba705c9008d7a7eff6fb88f6ea7b",
"0x4fa802324e929786dbda3b8820dc7834e9134a2a",
"0x9da397b9e80755301a3b32173283a91c0ef6c87e",
"0x8d9edb3054ce5c5774a420ac37ebae0ac02343c6",
"0x0101f3be8ebb4bbd39a2e3b9a3639d4259832fd9",
"0x5dc28b15dffed94048d73806ce4b7a4612a1d48f",
"0xbcf899e6c7d9d5a215ab1e3444c86806fa854c76",
"0x12e626b0eebfe86a56d633b9864e389b45dcb260",
"0xa2f1ccba9395d7fcb155bba8bc92db9bafaeade7",
"0xec8e57756626fdc07c63ad2eafbd28d08e7b0ca5",
"0xd164b088bd9108b60d0ca3751da4bceb207b0782",
"0x6231b6d0d5e77fe001c2a460bd9584fee60d409b",
"0x1cba23d343a983e9b5cfd19496b9a9701ada385f",
"0xa82f360a8d3455c5c41366975bde739c37bfeb8a",
"0x9fcd2deaff372a39cc679d5c5e4de7bafb0b1339",
"0x005f5cee7a43331d5a3d3eec71305925a62f34b6",
"0x0e0da70933f4c7849fc0d203f5d1d43b9ae4532d",
"0xd131637d5275fd1a68a3200f4ad25c71a2a9522e",
"0xbc07118b9ac290e4622f5e77a0853539789effbe",
"0x47e7aa56d6bdf3f36be34619660de61275420af8",
"0xacd87e28b0c9d1254e868b81cba4cc20d9a32225",
"0xadf80daec7ba8dcf15392f1ac611fff65d94f880",
"0x5524c55fb03cf21f549444ccbecb664d0acad706",
"0x40b803a9abce16f50f36a77ba41180eb90023925",
"0xfe24cdd8648121a43a7c86d289be4dd2951ed49f",
"0x17802f43a0137c506ba92291391a8a8f207f487d",
"0x253488078a4edf4d6f42f113d1e62836a942cf1a",
"0x86af3e9626fce1957c82e88cbf04ddf3a2ed7915",
"0xb136707642a4ea12fb4bae820f03d2562ebff487",
"0xdbe9b615a3ae8709af8b93336ce9b477e4ac0940",
"0xf14c14075d6c4ed84b86798af0956deef67365b5",
"0xca544e5c4687d109611d0f8f928b53a25af72448",
"0xaeeb8ff27288bdabc0fa5ebb731b6f409507516c",
"0xcbb9d3703e651b0d496cdefb8b92c25aeb2171f7",
"0x6d87578288b6cb5549d5076a207456a1f6a63dc0",
"0xb2c6f0dfbb716ac562e2d85d6cb2f8d5ee87603e",
"0xaccc230e8a6e5be9160b8cdf2864dd2a001c28b6",
"0x2b3455ec7fedf16e646268bf88846bd7a2319bb2",
"0x4613f3bca5c44ea06337a9e439fbc6d42e501d0a",
"0xd343b217de44030afaa275f54d31a9317c7f441e",
"0x84ef4b2357079cd7a7c69fd7a37cd0609a679106",
"0xda2fef9e4a3230988ff17df2165440f37e8b1708",
"0xf4c64518ea10f995918a454158c6b61407ea345c",
"0x7602b46df5390e432ef1c307d4f2c9ff6d65cc97",
"0xbb9bc244d798123fde783fcc1c72d3bb8c189413",
"0x807640a13483f8ac783c557fcdf27be11ea4ac7a"
]
} }
} }
}, },

View File

@ -1,42 +0,0 @@
{
"name": "Frontier (Test)",
"engine": {
"Ethash": {
"params": {
"gasLimitBoundDivisor": "0x0400",
"minimumDifficulty": "0x020000",
"difficultyBoundDivisor": "0x0800",
"durationLimit": "0x0d",
"blockReward": "0x4563918244F40000",
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
"frontierCompatibilityModeLimit": "0x118c30"
}
}
},
"params": {
"accountStartNonce": "0x00",
"maximumExtraDataSize": "0x20",
"minGasLimit": "0x1388",
"networkID" : "0x1"
},
"genesis": {
"seal": {
"ethereum": {
"nonce": "0x0000000000000042",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
}
},
"difficulty": "0x400000000",
"author": "0x0000000000000000000000000000000000000000",
"timestamp": "0x00",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"extraData": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa",
"gasLimit": "0x1388"
},
"accounts": {
"0000000000000000000000000000000000000001": { "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } },
"0000000000000000000000000000000000000002": { "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } },
"0000000000000000000000000000000000000003": { "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } },
"0000000000000000000000000000000000000004": { "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }
}
}

View File

@ -9,7 +9,7 @@
"durationLimit": "0x0d", "durationLimit": "0x0d",
"blockReward": "0x4563918244F40000", "blockReward": "0x4563918244F40000",
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b", "registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
"frontierCompatibilityModeLimit": 0 "frontierCompatibilityModeLimit": "0x0"
} }
} }
}, },

View File

@ -1,42 +0,0 @@
{
"name": "Homestead (Test)",
"engine": {
"Ethash": {
"params": {
"gasLimitBoundDivisor": "0x0400",
"minimumDifficulty": "0x020000",
"difficultyBoundDivisor": "0x0800",
"durationLimit": "0x0d",
"blockReward": "0x4563918244F40000",
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
"frontierCompatibilityModeLimit": 0
}
}
},
"params": {
"accountStartNonce": "0x00",
"maximumExtraDataSize": "0x20",
"minGasLimit": "0x1388",
"networkID" : "0x1"
},
"genesis": {
"seal": {
"ethereum": {
"nonce": "0x0000000000000042",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
}
},
"difficulty": "0x400000000",
"author": "0x0000000000000000000000000000000000000000",
"timestamp": "0x00",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"extraData": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa",
"gasLimit": "0x1388"
},
"accounts": {
"0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } },
"0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } },
"0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } },
"0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }
}
}

View File

@ -8,8 +8,7 @@
"difficultyBoundDivisor": "0x0800", "difficultyBoundDivisor": "0x0800",
"durationLimit": "0x08", "durationLimit": "0x08",
"blockReward": "0x14D1120D7B160000", "blockReward": "0x14D1120D7B160000",
"registrar": "5e70c0bbcd5636e0f9f9316e9f8633feb64d4050", "registrar": "5e70c0bbcd5636e0f9f9316e9f8633feb64d4050"
"frontierCompatibilityModeLimit": "0xffffffffffffffff"
} }
} }
}, },

View File

@ -39,8 +39,18 @@ impl Block {
pub fn is_good(b: &[u8]) -> bool { pub fn is_good(b: &[u8]) -> bool {
UntrustedRlp::new(b).as_val::<Block>().is_ok() UntrustedRlp::new(b).as_val::<Block>().is_ok()
} }
/// Get the RLP-encoding of the block without the seal.
pub fn rlp_bytes(&self, seal: Seal) -> Bytes {
let mut block_rlp = RlpStream::new_list(3);
self.header.stream_rlp(&mut block_rlp, seal);
block_rlp.append(&self.transactions);
block_rlp.append(&self.uncles);
block_rlp.out()
}
} }
impl Decodable for Block { impl Decodable for Block {
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder { fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
if decoder.as_raw().len() != try!(decoder.as_rlp().payload_info()).total() { if decoder.as_raw().len() != try!(decoder.as_rlp().payload_info()).total() {
@ -140,9 +150,12 @@ impl ExecutedBlock {
/// Trait for a object that is a `ExecutedBlock`. /// Trait for a object that is a `ExecutedBlock`.
pub trait IsBlock { pub trait IsBlock {
/// Get the block associated with this object. /// Get the `ExecutedBlock` associated with this object.
fn block(&self) -> &ExecutedBlock; fn block(&self) -> &ExecutedBlock;
/// Get the base `Block` object associated with this.
fn base(&self) -> &Block { &self.block().base }
/// Get the header associated with this object's block. /// Get the header associated with this object's block.
fn header(&self) -> &Header { &self.block().base.header } fn header(&self) -> &Header { &self.block().base.header }
@ -481,10 +494,12 @@ pub fn enact(
} }
} }
let mut b = try!(OpenBlock::new(engine, vm_factory, trie_factory, tracing, db, parent, last_hashes, header.author().clone(), (3141562.into(), 31415620.into()), header.extra_data().clone())); let mut b = try!(OpenBlock::new(engine, vm_factory, trie_factory, tracing, db, parent, last_hashes, Address::new(), (3141562.into(), 31415620.into()), vec![]));
b.set_difficulty(*header.difficulty()); b.set_difficulty(*header.difficulty());
b.set_gas_limit(*header.gas_limit()); b.set_gas_limit(*header.gas_limit());
b.set_timestamp(header.timestamp()); b.set_timestamp(header.timestamp());
b.set_author(header.author().clone());
b.set_extra_data(header.extra_data().clone()).unwrap_or_else(|e| warn!("Couldn't set extradata: {}. Ignoring.", e));
for t in transactions { try!(b.push_transaction(t.clone(), None)); } for t in transactions { try!(b.push_transaction(t.clone(), None)); }
for u in uncles { try!(b.push_uncle(u.clone())); } for u in uncles { try!(b.push_uncle(u.clone())); }
Ok(b.close_and_lock()) Ok(b.close_and_lock())

View File

@ -488,7 +488,6 @@ impl BlockChain {
/// Applies extras update. /// Applies extras update.
fn apply_update(&self, update: ExtrasUpdate) { fn apply_update(&self, update: ExtrasUpdate) {
let batch = DBTransaction::new(); let batch = DBTransaction::new();
batch.put(b"best", &update.info.hash).unwrap();
{ {
for hash in update.block_details.keys().cloned() { for hash in update.block_details.keys().cloned() {
@ -496,29 +495,27 @@ impl BlockChain {
} }
let mut write_details = self.block_details.write(); let mut write_details = self.block_details.write();
batch.extend_with_cache(write_details.deref_mut(), update.block_details, CacheUpdatePolicy::Overwrite); batch.extend_with_cache(&mut *write_details, update.block_details, CacheUpdatePolicy::Overwrite);
} }
{ {
let mut write_receipts = self.block_receipts.write(); let mut write_receipts = self.block_receipts.write();
batch.extend_with_cache(write_receipts.deref_mut(), update.block_receipts, CacheUpdatePolicy::Remove); batch.extend_with_cache(&mut *write_receipts, update.block_receipts, CacheUpdatePolicy::Remove);
} }
{ {
let mut write_blocks_blooms = self.blocks_blooms.write(); let mut write_blocks_blooms = self.blocks_blooms.write();
batch.extend_with_cache(write_blocks_blooms.deref_mut(), update.blocks_blooms, CacheUpdatePolicy::Remove); batch.extend_with_cache(&mut *write_blocks_blooms, update.blocks_blooms, CacheUpdatePolicy::Remove);
} }
// These cached values must be updated last and togeterh // These cached values must be updated last and togeterh
{ {
let mut best_block = self.best_block.write();
let mut write_hashes = self.block_hashes.write();
let mut write_txs = self.transaction_addresses.write();
// update best block // update best block
match update.info.location { match update.info.location {
BlockLocation::Branch => (), BlockLocation::Branch => (),
_ => { _ => {
batch.put(b"best", &update.info.hash).unwrap();
let mut best_block = self.best_block.write();
*best_block = BestBlock { *best_block = BestBlock {
hash: update.info.hash, hash: update.info.hash,
number: update.info.number, number: update.info.number,
@ -527,8 +524,11 @@ impl BlockChain {
} }
} }
batch.extend_with_cache(write_hashes.deref_mut(), update.block_hashes, CacheUpdatePolicy::Remove); let mut write_hashes = self.block_hashes.write();
batch.extend_with_cache(write_txs.deref_mut(), update.transactions_addresses, CacheUpdatePolicy::Remove); let mut write_txs = self.transaction_addresses.write();
batch.extend_with_cache(&mut *write_hashes, update.block_hashes, CacheUpdatePolicy::Remove);
batch.extend_with_cache(&mut *write_txs, update.transactions_addresses, CacheUpdatePolicy::Remove);
// update extras database // update extras database
self.extras_db.write(batch).unwrap(); self.extras_db.write(batch).unwrap();
@ -1189,4 +1189,31 @@ mod tests {
assert_eq!(blocks_b2, vec![2]); assert_eq!(blocks_b2, vec![2]);
assert_eq!(blocks_ba, vec![3]); assert_eq!(blocks_ba, vec![3]);
} }
#[test]
fn test_best_block_update() {
let mut canon_chain = ChainGenerator::default();
let mut finalizer = BlockFinalizer::default();
let genesis = canon_chain.generate(&mut finalizer).unwrap();
let temp = RandomTempPath::new();
{
let bc = BlockChain::new(Config::default(), &genesis, temp.as_path());
let uncle = canon_chain.fork(1).generate(&mut finalizer.fork()).unwrap();
// create a longer fork
for _ in 0..5 {
let canon_block = canon_chain.generate(&mut finalizer).unwrap();
bc.insert_block(&canon_block, vec![]);
}
assert_eq!(bc.best_block_number(), 5);
bc.insert_block(&uncle, vec![]);
}
// re-loading the blockchain should load the correct best block.
let bc = BlockChain::new(Config::default(), &genesis, temp.as_path());
assert_eq!(bc.best_block_number(), 5);
}
} }

View File

@ -35,7 +35,7 @@ use util::rlp::{RlpStream, Rlp, UntrustedRlp};
use util::journaldb; use util::journaldb;
use util::journaldb::JournalDB; use util::journaldb::JournalDB;
use util::kvdb::*; use util::kvdb::*;
use util::{Applyable, Stream, View, PerfTimer, Itertools, Colour}; use util::{Stream, View, PerfTimer, Itertools};
use util::{Mutex, RwLock}; use util::{Mutex, RwLock};
// other // other
@ -44,6 +44,7 @@ use error::{ImportError, ExecutionError, BlockError, ImportResult};
use header::BlockNumber; use header::BlockNumber;
use state::State; use state::State;
use spec::Spec; use spec::Spec;
use basic_types::Seal;
use engine::Engine; use engine::Engine;
use views::HeaderView; use views::HeaderView;
use service::ClientIoMessage; use service::ClientIoMessage;
@ -462,8 +463,10 @@ impl Client {
/// Otherwise, this can fail (but may not) if the DB prunes state. /// Otherwise, this can fail (but may not) if the DB prunes state.
pub fn state_at(&self, id: BlockID) -> Option<State> { pub fn state_at(&self, id: BlockID) -> Option<State> {
// fast path for latest state. // fast path for latest state.
if let BlockID::Latest = id.clone() { match id.clone() {
return Some(self.state()) BlockID::Pending => return self.miner.pending_state().or_else(|| Some(self.state())),
BlockID::Latest => return Some(self.state()),
_ => {},
} }
let block_number = match self.block_number(id.clone()) { let block_number = match self.block_number(id.clone()) {
@ -556,7 +559,7 @@ impl Client {
BlockID::Number(number) => Some(number), BlockID::Number(number) => Some(number),
BlockID::Hash(ref hash) => self.chain.block_number(hash), BlockID::Hash(ref hash) => self.chain.block_number(hash),
BlockID::Earliest => Some(0), BlockID::Earliest => Some(0),
BlockID::Latest => Some(self.chain.best_block_number()) BlockID::Latest | BlockID::Pending => Some(self.chain.best_block_number()),
} }
} }
@ -565,7 +568,7 @@ impl Client {
BlockID::Hash(hash) => Some(hash), BlockID::Hash(hash) => Some(hash),
BlockID::Number(number) => chain.block_hash(number), BlockID::Number(number) => chain.block_hash(number),
BlockID::Earliest => chain.block_hash(0), BlockID::Earliest => chain.block_hash(0),
BlockID::Latest => Some(chain.best_block_hash()) BlockID::Latest | BlockID::Pending => Some(chain.best_block_hash()),
} }
} }
@ -605,18 +608,6 @@ impl Client {
} }
} }
} }
/// Notify us that the network has been started.
pub fn network_started(&self, url: &str) {
let mut previous_enode = self.previous_enode.lock();
if let Some(ref u) = *previous_enode {
if u == url {
return;
}
}
*previous_enode = Some(url.into());
info!(target: "mode", "Public node URL: {}", url.apply(Colour::White.bold()));
}
} }
#[derive(Ipc)] #[derive(Ipc)]
@ -683,6 +674,11 @@ impl BlockChainClient for Client {
} }
fn block(&self, id: BlockID) -> Option<Bytes> { fn block(&self, id: BlockID) -> Option<Bytes> {
if let &BlockID::Pending = &id {
if let Some(block) = self.miner.pending_block() {
return Some(block.rlp_bytes(Seal::Without));
}
}
Self::block_hash(&self.chain, id).and_then(|hash| { Self::block_hash(&self.chain, id).and_then(|hash| {
self.chain.block(&hash) self.chain.block(&hash)
}) })
@ -697,6 +693,11 @@ impl BlockChainClient for Client {
} }
fn block_total_difficulty(&self, id: BlockID) -> Option<U256> { fn block_total_difficulty(&self, id: BlockID) -> Option<U256> {
if let &BlockID::Pending = &id {
if let Some(block) = self.miner.pending_block() {
return Some(*block.header.difficulty() + self.block_total_difficulty(BlockID::Latest).expect("blocks in chain have details; qed"));
}
}
Self::block_hash(&self.chain, id).and_then(|hash| self.chain.block_details(&hash)).map(|d| d.total_difficulty) Self::block_hash(&self.chain, id).and_then(|hash| self.chain.block_details(&hash)).map(|d| d.total_difficulty)
} }

View File

@ -241,7 +241,7 @@ impl TestBlockChainClient {
BlockID::Hash(hash) => Some(hash), BlockID::Hash(hash) => Some(hash),
BlockID::Number(n) => self.numbers.read().get(&(n as usize)).cloned(), BlockID::Number(n) => self.numbers.read().get(&(n as usize)).cloned(),
BlockID::Earliest => self.numbers.read().get(&0).cloned(), BlockID::Earliest => self.numbers.read().get(&0).cloned(),
BlockID::Latest => self.numbers.read().get(&(self.numbers.read().len() - 1)).cloned() BlockID::Latest | BlockID::Pending => self.numbers.read().get(&(self.numbers.read().len() - 1)).cloned()
} }
} }
} }

View File

@ -39,6 +39,12 @@ pub struct EthashParams {
pub registrar: Address, pub registrar: Address,
/// Homestead transition block number. /// Homestead transition block number.
pub frontier_compatibility_mode_limit: u64, pub frontier_compatibility_mode_limit: u64,
/// DAO hard-fork transition block (X).
pub dao_hardfork_transition: u64,
/// DAO hard-fork refund contract address (C).
pub dao_hardfork_beneficiary: Address,
/// DAO hard-fork DAO accounts list (L)
pub dao_hardfork_accounts: Vec<Address>,
} }
impl From<ethjson::spec::EthashParams> for EthashParams { impl From<ethjson::spec::EthashParams> for EthashParams {
@ -49,8 +55,11 @@ impl From<ethjson::spec::EthashParams> for EthashParams {
difficulty_bound_divisor: p.difficulty_bound_divisor.into(), difficulty_bound_divisor: p.difficulty_bound_divisor.into(),
duration_limit: p.duration_limit.into(), duration_limit: p.duration_limit.into(),
block_reward: p.block_reward.into(), block_reward: p.block_reward.into(),
registrar: p.registrar.into(), registrar: p.registrar.map(Into::into).unwrap_or(Address::new()),
frontier_compatibility_mode_limit: p.frontier_compatibility_mode_limit.into(), frontier_compatibility_mode_limit: p.frontier_compatibility_mode_limit.map(Into::into).unwrap_or(0),
dao_hardfork_transition: p.dao_hardfork_transition.map(Into::into).unwrap_or(0x7fffffffffffffff),
dao_hardfork_beneficiary: p.dao_hardfork_beneficiary.map(Into::into).unwrap_or(Address::new()),
dao_hardfork_accounts: p.dao_hardfork_accounts.unwrap_or(vec![]).into_iter().map(Into::into).collect(),
} }
} }
} }
@ -119,10 +128,27 @@ impl Engine for Ethash {
(header.gas_used * 6.into() / 5.into()) / bound_divisor)) (header.gas_used * 6.into() / 5.into()) / bound_divisor))
} }
}; };
if header.number >= self.ethash_params.dao_hardfork_transition &&
header.number <= self.ethash_params.dao_hardfork_transition + 9 {
header.extra_data = b"dao-hard-fork"[..].to_owned();
}
header.note_dirty(); header.note_dirty();
// info!("ethash: populate_from_parent #{}: difficulty={} and gas_limit={}", header.number, header.difficulty, header.gas_limit); // info!("ethash: populate_from_parent #{}: difficulty={} and gas_limit={}", header.number, header.difficulty, header.gas_limit);
} }
fn on_new_block(&self, block: &mut ExecutedBlock) {
if block.fields().header.number == self.ethash_params.dao_hardfork_transition {
// TODO: enable trigger function maybe?
// if block.fields().header.gas_limit <= 4_000_000.into() {
let mut state = block.fields_mut().state;
for child in self.ethash_params.dao_hardfork_accounts.iter() {
let b = state.balance(child);
state.transfer_balance(child, &self.ethash_params.dao_hardfork_beneficiary, &b);
}
// }
}
}
/// Apply the block reward on finalisation of the block. /// Apply the block reward on finalisation of the block.
/// This assumes that all uncles are valid uncles (i.e. of at least one generation before the current). /// This assumes that all uncles are valid uncles (i.e. of at least one generation before the current).
fn on_close_block(&self, block: &mut ExecutedBlock) { fn on_close_block(&self, block: &mut ExecutedBlock) {
@ -164,6 +190,17 @@ impl Engine for Ethash {
if difficulty < header.difficulty { if difficulty < header.difficulty {
return Err(From::from(BlockError::InvalidProofOfWork(OutOfBounds { min: Some(header.difficulty), max: None, found: difficulty }))); return Err(From::from(BlockError::InvalidProofOfWork(OutOfBounds { min: Some(header.difficulty), max: None, found: difficulty })));
} }
if header.number >= self.ethash_params.dao_hardfork_transition &&
header.number <= self.ethash_params.dao_hardfork_transition + 9 &&
header.extra_data[..] != b"dao-hard-fork"[..] {
return Err(From::from(BlockError::ExtraDataOutOfBounds(OutOfBounds { min: None, max: None, found: 0 })));
}
if header.gas_limit > 0x7fffffffffffffffu64.into() {
return Err(From::from(BlockError::InvalidGasLimit(OutOfBounds { min: None, max: Some(0x7fffffffffffffffu64.into()), found: header.gas_limit })));
}
Ok(()) Ok(())
} }

View File

@ -37,12 +37,20 @@ pub fn new_frontier() -> Spec {
Spec::load(include_bytes!("../../res/ethereum/frontier.json")) Spec::load(include_bytes!("../../res/ethereum/frontier.json"))
} }
/// Create a new Frontier mainnet chain spec without the DAO hardfork.
pub fn new_frontier_dogmatic() -> Spec {
Spec::load(include_bytes!("../../res/ethereum/frontier-dogmatic.json"))
}
/// Create a new Frontier chain spec as though it never changes to Homestead. /// Create a new Frontier chain spec as though it never changes to Homestead.
pub fn new_frontier_test() -> Spec { Spec::load(include_bytes!("../../res/ethereum/frontier_test.json")) } pub fn new_frontier_test() -> Spec { Spec::load(include_bytes!("../../res/ethereum/frontier_test.json")) }
/// Create a new Homestead chain spec as though it never changed from Frontier. /// Create a new Homestead chain spec as though it never changed from Frontier.
pub fn new_homestead_test() -> Spec { Spec::load(include_bytes!("../../res/ethereum/homestead_test.json")) } pub fn new_homestead_test() -> Spec { Spec::load(include_bytes!("../../res/ethereum/homestead_test.json")) }
/// Create a new Frontier/Homestead/DAO chain spec with transition points at #5 and #8.
pub fn new_daohardfork_test() -> Spec { Spec::load(include_bytes!("../../res/ethereum/daohardfork_test.json")) }
/// Create a new Frontier main net chain spec without genesis accounts. /// Create a new Frontier main net chain spec without genesis accounts.
pub fn new_mainnet_like() -> Spec { Spec::load(include_bytes!("../../res/ethereum/frontier_like_test.json")) } pub fn new_mainnet_like() -> Spec { Spec::load(include_bytes!("../../res/ethereum/frontier_like_test.json")) }

View File

@ -48,6 +48,7 @@ pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec<String> {
let mut spec = match era { let mut spec = match era {
ChainEra::Frontier => ethereum::new_frontier_test(), ChainEra::Frontier => ethereum::new_frontier_test(),
ChainEra::Homestead => ethereum::new_homestead_test(), ChainEra::Homestead => ethereum::new_homestead_test(),
ChainEra::DaoHardfork => ethereum::new_daohardfork_test(),
}; };
spec.set_genesis_state(state); spec.set_genesis_state(state);
spec.overwrite_genesis_params(genesis); spec.overwrite_genesis_params(genesis);
@ -84,26 +85,43 @@ pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec<String> {
failed failed
} }
fn do_json_test(json_data: &[u8]) -> Vec<String> { mod frontier_era_tests {
json_chain_test(json_data, ChainEra::Frontier) use tests::helpers::*;
use super::json_chain_test;
fn do_json_test(json_data: &[u8]) -> Vec<String> {
json_chain_test(json_data, ChainEra::Frontier)
}
declare_test!{BlockchainTests_bcBlockGasLimitTest, "BlockchainTests/bcBlockGasLimitTest"}
declare_test!{BlockchainTests_bcForkBlockTest, "BlockchainTests/bcForkBlockTest"}
declare_test!{BlockchainTests_bcForkStressTest, "BlockchainTests/bcForkStressTest"}
declare_test!{BlockchainTests_bcForkUncle, "BlockchainTests/bcForkUncle"}
declare_test!{BlockchainTests_bcGasPricerTest, "BlockchainTests/bcGasPricerTest"}
declare_test!{BlockchainTests_bcInvalidHeaderTest, "BlockchainTests/bcInvalidHeaderTest"}
// TODO [ToDr] Ignored because of incorrect JSON (https://github.com/ethereum/tests/pull/113)
declare_test!{ignore => BlockchainTests_bcInvalidRLPTest, "BlockchainTests/bcInvalidRLPTest"}
declare_test!{BlockchainTests_bcMultiChainTest, "BlockchainTests/bcMultiChainTest"}
declare_test!{BlockchainTests_bcRPC_API_Test, "BlockchainTests/bcRPC_API_Test"}
declare_test!{BlockchainTests_bcStateTest, "BlockchainTests/bcStateTest"}
declare_test!{BlockchainTests_bcTotalDifficultyTest, "BlockchainTests/bcTotalDifficultyTest"}
declare_test!{BlockchainTests_bcUncleHeaderValiditiy, "BlockchainTests/bcUncleHeaderValiditiy"}
declare_test!{BlockchainTests_bcUncleTest, "BlockchainTests/bcUncleTest"}
declare_test!{BlockchainTests_bcValidBlockTest, "BlockchainTests/bcValidBlockTest"}
declare_test!{BlockchainTests_bcWalletTest, "BlockchainTests/bcWalletTest"}
declare_test!{BlockchainTests_RandomTests_bl10251623GO, "BlockchainTests/RandomTests/bl10251623GO"}
declare_test!{BlockchainTests_RandomTests_bl201507071825GO, "BlockchainTests/RandomTests/bl201507071825GO"}
} }
declare_test!{BlockchainTests_bcBlockGasLimitTest, "BlockchainTests/bcBlockGasLimitTest"} mod daohardfork_tests {
declare_test!{BlockchainTests_bcForkBlockTest, "BlockchainTests/bcForkBlockTest"} use tests::helpers::*;
declare_test!{BlockchainTests_bcForkStressTest, "BlockchainTests/bcForkStressTest"} use super::json_chain_test;
declare_test!{BlockchainTests_bcForkUncle, "BlockchainTests/bcForkUncle"}
declare_test!{BlockchainTests_bcGasPricerTest, "BlockchainTests/bcGasPricerTest"}
declare_test!{BlockchainTests_bcInvalidHeaderTest, "BlockchainTests/bcInvalidHeaderTest"}
// TODO [ToDr] Ignored because of incorrect JSON (https://github.com/ethereum/tests/pull/113)
declare_test!{ignore => BlockchainTests_bcInvalidRLPTest, "BlockchainTests/bcInvalidRLPTest"}
declare_test!{BlockchainTests_bcMultiChainTest, "BlockchainTests/bcMultiChainTest"}
declare_test!{BlockchainTests_bcRPC_API_Test, "BlockchainTests/bcRPC_API_Test"}
declare_test!{BlockchainTests_bcStateTest, "BlockchainTests/bcStateTest"}
declare_test!{BlockchainTests_bcTotalDifficultyTest, "BlockchainTests/bcTotalDifficultyTest"}
declare_test!{BlockchainTests_bcUncleHeaderValiditiy, "BlockchainTests/bcUncleHeaderValiditiy"}
declare_test!{BlockchainTests_bcUncleTest, "BlockchainTests/bcUncleTest"}
declare_test!{BlockchainTests_bcValidBlockTest, "BlockchainTests/bcValidBlockTest"}
declare_test!{BlockchainTests_bcWalletTest, "BlockchainTests/bcWalletTest"}
declare_test!{BlockchainTests_RandomTests_bl10251623GO, "BlockchainTests/RandomTests/bl10251623GO"} fn do_json_test(json_data: &[u8]) -> Vec<String> {
declare_test!{BlockchainTests_RandomTests_bl201507071825GO, "BlockchainTests/RandomTests/bl201507071825GO"} json_chain_test(json_data, ChainEra::DaoHardfork)
}
declare_test!{BlockchainTests_TestNetwork_bcSimpleTransitionTest, "BlockchainTests/TestNetwork/bcSimpleTransitionTest"}
declare_test!{BlockchainTests_TestNetwork_bcTheDaoTest, "BlockchainTests/TestNetwork/bcTheDaoTest"}
}

View File

@ -30,8 +30,9 @@ pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec<String> {
let mut failed = Vec::new(); let mut failed = Vec::new();
let engine = match era { let engine = match era {
ChainEra::Frontier => ethereum::new_mainnet_like().engine, ChainEra::Frontier => ethereum::new_mainnet_like().engine,
ChainEra::Homestead => ethereum::new_homestead_test().engine ChainEra::Homestead => ethereum::new_homestead_test().engine,
}; ChainEra::DaoHardfork => ethereum::new_daohardfork_test().engine,
};
for (name, test) in tests.into_iter() { for (name, test) in tests.into_iter() {
let mut fail = false; let mut fail = false;

View File

@ -22,8 +22,9 @@ use util::*;
use util::using_queue::{UsingQueue, GetAction}; use util::using_queue::{UsingQueue, GetAction};
use account_provider::AccountProvider; use account_provider::AccountProvider;
use views::{BlockView, HeaderView}; use views::{BlockView, HeaderView};
use state::State;
use client::{MiningBlockChainClient, Executive, Executed, EnvInfo, TransactOptions, BlockID, CallAnalytics}; use client::{MiningBlockChainClient, Executive, Executed, EnvInfo, TransactOptions, BlockID, CallAnalytics};
use block::{ClosedBlock, IsBlock}; use block::{ClosedBlock, IsBlock, Block};
use error::*; use error::*;
use transaction::SignedTransaction; use transaction::SignedTransaction;
use receipt::Receipt; use receipt::Receipt;
@ -115,7 +116,7 @@ impl GasPriceCalibrator {
let wei_per_usd: f32 = 1.0e18 / usd_per_eth; let wei_per_usd: f32 = 1.0e18 / usd_per_eth;
let gas_per_tx: f32 = 21000.0; let gas_per_tx: f32 = 21000.0;
let wei_per_gas: f32 = wei_per_usd * usd_per_tx / gas_per_tx; let wei_per_gas: f32 = wei_per_usd * usd_per_tx / gas_per_tx;
info!(target: "miner", "Updated conversion rate to Ξ1 = {} ({} wei/gas)", format!("US${}", usd_per_eth).apply(Colour::White.bold()), format!("{}", wei_per_gas).apply(Colour::Yellow.bold())); info!(target: "miner", "Updated conversion rate to Ξ1 = {} ({} wei/gas)", Colour::White.bold().paint(format!("US${}", usd_per_eth)), Colour::Yellow.bold().paint(format!("{}", wei_per_gas)));
set_price(U256::from_dec_str(&format!("{:.0}", wei_per_gas)).unwrap()); set_price(U256::from_dec_str(&format!("{:.0}", wei_per_gas)).unwrap());
}) { }) {
self.next_calibration = Instant::now() + self.options.recalibration_period; self.next_calibration = Instant::now() + self.options.recalibration_period;
@ -226,6 +227,16 @@ impl Miner {
self.options.force_sealing || !self.options.new_work_notify.is_empty() self.options.force_sealing || !self.options.new_work_notify.is_empty()
} }
/// Get `Some` `clone()` of the current pending block's state or `None` if we're not sealing.
pub fn pending_state(&self) -> Option<State> {
self.sealing_work.lock().peek_last_ref().map(|b| b.block().fields().state.clone())
}
/// Get `Some` `clone()` of the current pending block's state or `None` if we're not sealing.
pub fn pending_block(&self) -> Option<Block> {
self.sealing_work.lock().peek_last_ref().map(|b| b.base().clone())
}
/// Prepares new block for sealing including top transactions from queue. /// Prepares new block for sealing including top transactions from queue.
#[cfg_attr(feature="dev", allow(match_same_arms))] #[cfg_attr(feature="dev", allow(match_same_arms))]
#[cfg_attr(feature="dev", allow(cyclomatic_complexity))] #[cfg_attr(feature="dev", allow(cyclomatic_complexity))]
@ -764,7 +775,7 @@ impl MinerService for Miner {
let n = sealed.header().number(); let n = sealed.header().number();
let h = sealed.header().hash(); let h = sealed.header().hash();
try!(chain.import_sealed_block(sealed)); try!(chain.import_sealed_block(sealed));
info!(target: "miner", "Mined block imported OK. #{}: {}", format!("{}", n).apply(Colour::White.bold()), h.hex().apply(Colour::White.bold())); info!(target: "miner", "Mined block imported OK. #{}: {}", Colour::White.bold().paint(format!("{}", n)), Colour::White.bold().paint(h.hex()));
Ok(()) Ok(())
}) })
} }

View File

@ -54,7 +54,7 @@ impl ClientService {
let io_service = try!(IoService::<ClientIoMessage>::start()); let io_service = try!(IoService::<ClientIoMessage>::start());
panic_handler.forward_from(&io_service); panic_handler.forward_from(&io_service);
info!("Configured for {} using {} engine", spec.name.clone().apply(Colour::White.bold()), spec.engine.name().apply(Colour::Yellow.bold())); info!("Configured for {} using {} engine", Colour::White.bold().paint(spec.name.clone()), Colour::Yellow.bold().paint(spec.engine.name()));
let client = try!(Client::new(config, spec, db_path, miner, io_service.channel())); let client = try!(Client::new(config, spec, db_path, miner, io_service.channel()));
panic_handler.forward_from(client.deref()); panic_handler.forward_from(client.deref());
let client_io = Arc::new(ClientIoHandler { let client_io = Arc::new(ClientIoHandler {

View File

@ -30,6 +30,7 @@ use miner::Miner;
pub enum ChainEra { pub enum ChainEra {
Frontier, Frontier,
Homestead, Homestead,
DaoHardfork,
} }
pub struct TestEngine { pub struct TestEngine {

View File

@ -33,7 +33,9 @@ pub enum BlockID {
/// Earliest block (genesis). /// Earliest block (genesis).
Earliest, Earliest,
/// Latest mined block. /// Latest mined block.
Latest Latest,
/// Pending block.
Pending,
} }
/// Uniquely identifies transaction. /// Uniquely identifies transaction.

View File

@ -53,7 +53,10 @@ mod tests {
"durationLimit": "0x0d", "durationLimit": "0x0d",
"blockReward": "0x4563918244F40000", "blockReward": "0x4563918244F40000",
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b", "registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
"frontierCompatibilityModeLimit" : "0x" "frontierCompatibilityModeLimit" : "0x",
"daoHardforkTransition": "0xffffffffffffffff",
"daoHardforkBeneficiary": "0x0000000000000000000000000000000000000000",
"daoHardforkAccounts": []
} }
} }
}"#; }"#;

View File

@ -19,29 +19,38 @@
use uint::Uint; use uint::Uint;
use hash::Address; use hash::Address;
/// Ethash params deserialization. /// Deserializable doppelganger of EthashParams.
#[derive(Debug, PartialEq, Deserialize)] #[derive(Debug, PartialEq, Deserialize)]
pub struct EthashParams { pub struct EthashParams {
/// Gas limit divisor. /// See main EthashParams docs.
#[serde(rename="gasLimitBoundDivisor")] #[serde(rename="gasLimitBoundDivisor")]
pub gas_limit_bound_divisor: Uint, pub gas_limit_bound_divisor: Uint,
/// Minimum difficulty. /// See main EthashParams docs.
#[serde(rename="minimumDifficulty")] #[serde(rename="minimumDifficulty")]
pub minimum_difficulty: Uint, pub minimum_difficulty: Uint,
/// Difficulty bound divisor. /// See main EthashParams docs.
#[serde(rename="difficultyBoundDivisor")] #[serde(rename="difficultyBoundDivisor")]
pub difficulty_bound_divisor: Uint, pub difficulty_bound_divisor: Uint,
/// Block duration. /// See main EthashParams docs.
#[serde(rename="durationLimit")] #[serde(rename="durationLimit")]
pub duration_limit: Uint, pub duration_limit: Uint,
/// Block reward. /// See main EthashParams docs.
#[serde(rename="blockReward")] #[serde(rename="blockReward")]
pub block_reward: Uint, pub block_reward: Uint,
/// Namereg contract address. /// See main EthashParams docs.
pub registrar: Address, pub registrar: Option<Address>,
/// Homestead transition block number. /// See main EthashParams docs.
#[serde(rename="frontierCompatibilityModeLimit")] #[serde(rename="frontierCompatibilityModeLimit")]
pub frontier_compatibility_mode_limit: Uint, pub frontier_compatibility_mode_limit: Option<Uint>,
/// See main EthashParams docs.
#[serde(rename="daoHardforkTransition")]
pub dao_hardfork_transition: Option<Uint>,
/// See main EthashParams docs.
#[serde(rename="daoHardforkBeneficiary")]
pub dao_hardfork_beneficiary: Option<Address>,
/// See main EthashParams docs.
#[serde(rename="daoHardforkAccounts")]
pub dao_hardfork_accounts: Option<Vec<Address>>,
} }
/// Ethash engine deserialization. /// Ethash engine deserialization.
@ -66,7 +75,46 @@ mod tests {
"durationLimit": "0x0d", "durationLimit": "0x0d",
"blockReward": "0x4563918244F40000", "blockReward": "0x4563918244F40000",
"registrar": "0xc6d9d2cd449a754c494264e1809c50e34d64562b", "registrar": "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
"frontierCompatibilityModeLimit": "0x42" "frontierCompatibilityModeLimit": "0x42",
"daoHardforkTransition": "0x08",
"daoHardforkBeneficiary": "0xabcabcabcabcabcabcabcabcabcabcabcabcabca",
"daoHardforkAccounts": [
"0x304a554a310c7e546dfe434669c62820b7d83490",
"0x914d1b8b43e92723e64fd0a06f5bdb8dd9b10c79",
"0xfe24cdd8648121a43a7c86d289be4dd2951ed49f",
"0x17802f43a0137c506ba92291391a8a8f207f487d",
"0xb136707642a4ea12fb4bae820f03d2562ebff487",
"0xdbe9b615a3ae8709af8b93336ce9b477e4ac0940",
"0xf14c14075d6c4ed84b86798af0956deef67365b5",
"0xca544e5c4687d109611d0f8f928b53a25af72448",
"0xaeeb8ff27288bdabc0fa5ebb731b6f409507516c",
"0xcbb9d3703e651b0d496cdefb8b92c25aeb2171f7",
"0xaccc230e8a6e5be9160b8cdf2864dd2a001c28b6",
"0x2b3455ec7fedf16e646268bf88846bd7a2319bb2",
"0x4613f3bca5c44ea06337a9e439fbc6d42e501d0a",
"0xd343b217de44030afaa275f54d31a9317c7f441e",
"0x84ef4b2357079cd7a7c69fd7a37cd0609a679106",
"0xda2fef9e4a3230988ff17df2165440f37e8b1708",
"0xf4c64518ea10f995918a454158c6b61407ea345c",
"0x7602b46df5390e432ef1c307d4f2c9ff6d65cc97",
"0xbb9bc244d798123fde783fcc1c72d3bb8c189413",
"0x807640a13483f8ac783c557fcdf27be11ea4ac7a"
]
}
}"#;
let _deserialized: Ethash = serde_json::from_str(s).unwrap();
}
#[test]
fn ethash_deserialization_missing_optionals() {
let s = r#"{
"params": {
"gasLimitBoundDivisor": "0x0400",
"minimumDifficulty": "0x020000",
"difficultyBoundDivisor": "0x0800",
"durationLimit": "0x0d",
"blockReward": "0x4563918244F40000"
} }
}"#; }"#;

View File

@ -63,7 +63,10 @@ mod tests {
"durationLimit": "0x0d", "durationLimit": "0x0d",
"blockReward": "0x4563918244F40000", "blockReward": "0x4563918244F40000",
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b", "registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
"frontierCompatibilityModeLimit" : "0x" "frontierCompatibilityModeLimit" : "0x",
"daoHardforkTransition": "0xffffffffffffffff",
"daoHardforkBeneficiary": "0x0000000000000000000000000000000000000000",
"daoHardforkAccounts": []
} }
} }
}, },

View File

@ -47,18 +47,13 @@ Operating Options:
[default: 3600]. [default: 3600].
--chain CHAIN Specify the blockchain type. CHAIN may be either a --chain CHAIN Specify the blockchain type. CHAIN may be either a
JSON chain specification file or olympic, frontier, JSON chain specification file or olympic, frontier,
homestead, mainnet, morden, or testnet homestead, mainnet, morden, homestead-dogmatic, or
[default: homestead]. testnet [default: homestead].
-d --db-path PATH Specify the database & configuration directory path -d --db-path PATH Specify the database & configuration directory path
[default: $HOME/.parity]. [default: $HOME/.parity].
--keys-path PATH Specify the path for JSON key files to be found --keys-path PATH Specify the path for JSON key files to be found
[default: $HOME/.parity/keys]. [default: $HOME/.parity/keys].
--identity NAME Specify your node's name. --identity NAME Specify your node's name.
--fork POLICY Specifies the client's fork policy. POLICY must be
one of:
dogmatic - sticks rigidly to the standard chain.
none - goes with whatever fork is decided but
votes for none. [default: none].
Account Options: Account Options:
--unlock ACCOUNTS Unlock ACCOUNTS for the duration of the execution. --unlock ACCOUNTS Unlock ACCOUNTS for the duration of the execution.
@ -145,7 +140,7 @@ Sealing/Mining Options:
none - never reseal on new transactions; none - never reseal on new transactions;
own - reseal only on a new local transaction; own - reseal only on a new local transaction;
ext - reseal only on a new external transaction; ext - reseal only on a new external transaction;
all - reseal on all new transactions [default: all]. all - reseal on all new transactions [default: own].
--reseal-min-period MS Specify the minimum time between reseals from --reseal-min-period MS Specify the minimum time between reseals from
incoming transactions. MS is time measured in incoming transactions. MS is time measured in
milliseconds [default: 2000]. milliseconds [default: 2000].
@ -292,7 +287,6 @@ pub struct Args {
pub flag_chain: String, pub flag_chain: String,
pub flag_db_path: String, pub flag_db_path: String,
pub flag_identity: String, pub flag_identity: String,
pub flag_fork: String,
pub flag_unlock: Option<String>, pub flag_unlock: Option<String>,
pub flag_password: Vec<String>, pub flag_password: Vec<String>,
pub flag_cache: Option<usize>, pub flag_cache: Option<usize>,

View File

@ -46,12 +46,6 @@ pub struct Directories {
pub signer: String, pub signer: String,
} }
#[derive(Eq, PartialEq, Debug)]
pub enum Policy {
None,
Dogmatic,
}
impl Configuration { impl Configuration {
pub fn parse() -> Self { pub fn parse() -> Self {
Configuration { Configuration {
@ -131,14 +125,6 @@ impl Configuration {
})) }))
} }
pub fn policy(&self) -> Policy {
match self.args.flag_fork.as_str() {
"none" => Policy::None,
"dogmatic" => Policy::Dogmatic,
x => die!("{}: Invalid value given for --policy option. Use --help for more info.", x)
}
}
pub fn gas_floor_target(&self) -> U256 { pub fn gas_floor_target(&self) -> U256 {
let d = &self.args.flag_gas_floor_target; let d = &self.args.flag_gas_floor_target;
U256::from_dec_str(d).unwrap_or_else(|_| { U256::from_dec_str(d).unwrap_or_else(|_| {
@ -195,7 +181,7 @@ impl Configuration {
let wei_per_usd: f32 = 1.0e18 / usd_per_eth; let wei_per_usd: f32 = 1.0e18 / usd_per_eth;
let gas_per_tx: f32 = 21000.0; let gas_per_tx: f32 = 21000.0;
let wei_per_gas: f32 = wei_per_usd * usd_per_tx / gas_per_tx; let wei_per_gas: f32 = wei_per_usd * usd_per_tx / gas_per_tx;
info!("Using a fixed conversion rate of Ξ1 = {} ({} wei/gas)", format!("US${}", usd_per_eth).apply(White.bold()), format!("{}", wei_per_gas).apply(Yellow.bold())); info!("Using a fixed conversion rate of Ξ1 = {} ({} wei/gas)", White.bold().paint(format!("US${}", usd_per_eth)), Yellow.bold().paint(format!("{}", wei_per_gas)));
GasPricer::Fixed(U256::from_dec_str(&format!("{:.0}", wei_per_gas)).unwrap()) GasPricer::Fixed(U256::from_dec_str(&format!("{:.0}", wei_per_gas)).unwrap())
} }
} }
@ -214,6 +200,7 @@ impl Configuration {
pub fn spec(&self) -> Spec { pub fn spec(&self) -> Spec {
match self.chain().as_str() { match self.chain().as_str() {
"frontier" | "homestead" | "mainnet" => ethereum::new_frontier(), "frontier" | "homestead" | "mainnet" => ethereum::new_frontier(),
"homestead-dogmatic" => ethereum::new_frontier_dogmatic(),
"morden" | "testnet" => ethereum::new_morden(), "morden" | "testnet" => ethereum::new_morden(),
"olympic" => ethereum::new_olympic(), "olympic" => ethereum::new_olympic(),
f => Spec::load(contents(f).unwrap_or_else(|_| { f => Spec::load(contents(f).unwrap_or_else(|_| {

View File

@ -20,6 +20,7 @@ use self::ansi_term::Style;
use std::time::{Instant, Duration}; use std::time::{Instant, Duration};
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
use isatty::{stdout_isatty};
use ethsync::{SyncStatus, NetworkConfiguration}; use ethsync::{SyncStatus, NetworkConfiguration};
use util::{Uint, RwLock}; use util::{Uint, RwLock};
use ethcore::client::*; use ethcore::client::*;
@ -91,7 +92,7 @@ impl Informant {
let mut write_report = self.report.write(); let mut write_report = self.report.write();
let report = client.report(); let report = client.report();
let paint = |c: Style, t: String| match self.with_color { let paint = |c: Style, t: String| match self.with_color && stdout_isatty() {
true => format!("{}", c.paint(t)), true => format!("{}", c.paint(t)),
false => t, false => t,
}; };

View File

@ -53,6 +53,7 @@ extern crate ansi_term;
#[macro_use] #[macro_use]
extern crate lazy_static; extern crate lazy_static;
extern crate regex; extern crate regex;
extern crate isatty;
#[cfg(feature = "dapps")] #[cfg(feature = "dapps")]
extern crate ethcore_dapps; extern crate ethcore_dapps;
@ -83,7 +84,7 @@ use std::thread::sleep;
use std::time::Duration; use std::time::Duration;
use rustc_serialize::hex::FromHex; use rustc_serialize::hex::FromHex;
use ctrlc::CtrlC; use ctrlc::CtrlC;
use util::{H256, ToPretty, PayloadInfo, Bytes, Colour, Applyable, version, journaldb}; use util::{H256, ToPretty, PayloadInfo, Bytes, Colour, version, journaldb};
use util::panics::{MayPanic, ForwardPanic, PanicHandler}; use util::panics::{MayPanic, ForwardPanic, PanicHandler};
use ethcore::client::{BlockID, BlockChainClient, ClientConfig, get_db_path, BlockImportError, Mode}; use ethcore::client::{BlockID, BlockChainClient, ClientConfig, get_db_path, BlockImportError, Mode};
use ethcore::error::{ImportError}; use ethcore::error::{ImportError};
@ -101,7 +102,7 @@ use rpc::RpcServer;
use signer::{SignerServer, new_token}; use signer::{SignerServer, new_token};
use dapps::WebappServer; use dapps::WebappServer;
use io_handler::ClientIoHandler; use io_handler::ClientIoHandler;
use configuration::{Policy, Configuration}; use configuration::{Configuration};
fn main() { fn main() {
let conf = Configuration::parse(); let conf = Configuration::parse();
@ -179,7 +180,7 @@ fn execute_upgrades(conf: &Configuration, spec: &Spec, client_config: &ClientCon
let db_path = get_db_path(Path::new(&conf.path()), client_config.pruning, spec.genesis_header().hash()); let db_path = get_db_path(Path::new(&conf.path()), client_config.pruning, spec.genesis_header().hash());
let result = migrate(&db_path, client_config.pruning); let result = migrate(&db_path, client_config.pruning);
if let Err(err) = result { if let Err(err) = result {
die_with_message(&format!("{}", err)); die_with_message(&format!("{} DB path: {}", err, db_path.to_string_lossy()));
} }
} }
@ -192,18 +193,18 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig)
// Raise fdlimit // Raise fdlimit
unsafe { ::fdlimit::raise_fd_limit(); } unsafe { ::fdlimit::raise_fd_limit(); }
info!("Starting {}", format!("{}", version()).apply(Colour::White.bold())); info!("Starting {}", Colour::White.bold().paint(format!("{}", version())));
info!("Using state DB journalling strategy {}", match client_config.pruning { info!("Using state DB journalling strategy {}", Colour::White.bold().paint(match client_config.pruning {
journaldb::Algorithm::Archive => "archive", journaldb::Algorithm::Archive => "archive",
journaldb::Algorithm::EarlyMerge => "light", journaldb::Algorithm::EarlyMerge => "light",
journaldb::Algorithm::OverlayRecent => "fast", journaldb::Algorithm::OverlayRecent => "fast",
journaldb::Algorithm::RefCounted => "basic", journaldb::Algorithm::RefCounted => "basic",
}.apply(Colour::White.bold())); }));
// Display warning about using experimental journaldb types // Display warning about using experimental journaldb types
match client_config.pruning { match client_config.pruning {
journaldb::Algorithm::EarlyMerge | journaldb::Algorithm::RefCounted => { journaldb::Algorithm::EarlyMerge | journaldb::Algorithm::RefCounted => {
warn!("Your chosen strategy is {}! You can re-run with --pruning to change.", "unstable".apply(Colour::Red.bold())); warn!("Your chosen strategy is {}! You can re-run with --pruning to change.", Colour::Red.bold().paint("unstable"));
} }
_ => {} _ => {}
} }
@ -214,11 +215,6 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig)
warn!("NOTE that Signer will not ask you to confirm transactions from unlocked account."); warn!("NOTE that Signer will not ask you to confirm transactions from unlocked account.");
} }
// Check fork settings.
if conf.policy() != Policy::None {
warn!("Value given for --policy, yet no proposed forks exist. Ignoring.");
}
let net_settings = conf.net_settings(&spec); let net_settings = conf.net_settings(&spec);
let sync_config = conf.sync_config(&spec); let sync_config = conf.sync_config(&spec);

View File

@ -37,11 +37,15 @@ const VERSION_FILE_NAME: &'static str = "db_version";
pub enum Error { pub enum Error {
/// Returned when current version cannot be read or guessed. /// Returned when current version cannot be read or guessed.
UnknownDatabaseVersion, UnknownDatabaseVersion,
/// Returned when migration is not possible. /// Migration does not support existing pruning algorithm.
UnsuportedPruningMethod,
/// Existing DB is newer than the known one.
FutureDBVersion,
/// Migration is not possible.
MigrationImpossible, MigrationImpossible,
/// Returned when migration unexpectadly failed. /// Migration unexpectadly failed.
MigrationFailed, MigrationFailed,
/// Returned when migration was completed succesfully, /// Migration was completed succesfully,
/// but there was a problem with io. /// but there was a problem with io.
Io(IoError), Io(IoError),
} }
@ -50,9 +54,11 @@ impl Display for Error {
fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
let out = match *self { let out = match *self {
Error::UnknownDatabaseVersion => "Current database version cannot be read".into(), Error::UnknownDatabaseVersion => "Current database version cannot be read".into(),
Error::MigrationImpossible => format!("Migration to version {} is not possible", CURRENT_VERSION), Error::UnsuportedPruningMethod => "Unsupported pruning method for database migration. Delete DB and resync.".into(),
Error::MigrationFailed => "Migration unexpectedly failed".into(), Error::FutureDBVersion => "Database was created with newer client version. Upgrade your client or delete DB and resync.".into(),
Error::Io(ref err) => format!("Unexpected io error: {}", err), Error::MigrationImpossible => format!("Database migration to version {} is not possible.", CURRENT_VERSION),
Error::MigrationFailed => "Database migration unexpectedly failed".into(),
Error::Io(ref err) => format!("Unexpected io error on DB migration: {}.", err),
}; };
write!(f, "{}", out) write!(f, "{}", out)
@ -159,7 +165,7 @@ fn state_database_migrations(pruning: Algorithm) -> Result<MigrationManager, Err
let res = match pruning { let res = match pruning {
Algorithm::Archive => manager.add_migration(migrations::state::ArchiveV7::default()), Algorithm::Archive => manager.add_migration(migrations::state::ArchiveV7::default()),
Algorithm::OverlayRecent => manager.add_migration(migrations::state::OverlayRecentV7::default()), Algorithm::OverlayRecent => manager.add_migration(migrations::state::OverlayRecentV7::default()),
_ => die!("Unsupported pruning method for migration. Delete DB and resync"), _ => return Err(Error::UnsuportedPruningMethod),
}; };
try!(res.map_err(|_| Error::MigrationImpossible)); try!(res.map_err(|_| Error::MigrationImpossible));
@ -207,12 +213,14 @@ pub fn migrate(path: &Path, pruning: Algorithm) -> Result<(), Error> {
// migrate the databases. // migrate the databases.
// main db directory may already exists, so let's check if we have blocks dir // main db directory may already exists, so let's check if we have blocks dir
if version != CURRENT_VERSION && exists(&blocks_database_path(path)) { if version < CURRENT_VERSION && exists(&blocks_database_path(path)) {
println!("Migrating database from version {} to {}", version, CURRENT_VERSION); println!("Migrating database from version {} to {}", version, CURRENT_VERSION);
try!(migrate_database(version, blocks_database_path(path), try!(blocks_database_migrations()))); try!(migrate_database(version, blocks_database_path(path), try!(blocks_database_migrations())));
try!(migrate_database(version, extras_database_path(path), try!(extras_database_migrations()))); try!(migrate_database(version, extras_database_path(path), try!(extras_database_migrations())));
try!(migrate_database(version, state_database_path(path), try!(state_database_migrations(pruning)))); try!(migrate_database(version, state_database_path(path), try!(state_database_migrations(pruning))));
println!("Migration finished"); println!("Migration finished");
} else if version > CURRENT_VERSION {
return Err(Error::FutureDBVersion);
} }
// update version file. // update version file.

View File

@ -19,11 +19,12 @@ use std::env;
use std::sync::Arc; use std::sync::Arc;
use std::fs::File; use std::fs::File;
use std::io::Write; use std::io::Write;
use isatty::{stderr_isatty};
use time; use time;
use env_logger::LogBuilder; use env_logger::LogBuilder;
use regex::Regex; use regex::Regex;
use util::RotatingLogger; use util::RotatingLogger;
use util::log::{Applyable, Colour}; use util::log::Colour;
/// Sets up the logger /// Sets up the logger
pub fn setup_log(init: &Option<String>, enable_color: bool, log_to_file: &Option<String>) -> Arc<RotatingLogger> { pub fn setup_log(init: &Option<String>, enable_color: bool, log_to_file: &Option<String>) -> Arc<RotatingLogger> {
@ -47,19 +48,26 @@ pub fn setup_log(init: &Option<String>, enable_color: bool, log_to_file: &Option
builder.parse(s); builder.parse(s);
} }
let logs = Arc::new(RotatingLogger::new(levels, enable_color)); let enable_color = enable_color && stderr_isatty();
let logs = Arc::new(RotatingLogger::new(levels));
let logger = logs.clone(); let logger = logs.clone();
let maybe_file = log_to_file.as_ref().map(|f| File::create(f).unwrap_or_else(|_| die!("Cannot write to log file given: {}", f))); let maybe_file = log_to_file.as_ref().map(|f| File::create(f).unwrap_or_else(|_| die!("Cannot write to log file given: {}", f)));
let format = move |record: &LogRecord| { let format = move |record: &LogRecord| {
let timestamp = time::strftime("%Y-%m-%d %H:%M:%S %Z", &time::now()).unwrap(); let timestamp = time::strftime("%Y-%m-%d %H:%M:%S %Z", &time::now()).unwrap();
let format = if max_log_level() <= LogLevelFilter::Info { let with_color = if max_log_level() <= LogLevelFilter::Info {
format!("{}{}", timestamp.apply(Colour::Black.bold()), record.args()) format!("{}{}", Colour::Black.bold().paint(timestamp), record.args())
} else { } else {
format!("{}{}:{}: {}", timestamp.apply(Colour::Black.bold()), record.level(), record.target(), record.args()) format!("{}{}:{}: {}", Colour::Black.bold().paint(timestamp), record.level(), record.target(), record.args())
};
let removed_color = kill_color(with_color.as_ref());
let ret = match enable_color {
true => with_color,
false => removed_color.clone(),
}; };
let removed_color = kill_color(format.as_ref());
if let Some(mut file) = maybe_file.as_ref() { if let Some(mut file) = maybe_file.as_ref() {
// ignore errors - there's nothing we can do // ignore errors - there's nothing we can do
let _ = file.write_all(removed_color.as_bytes()); let _ = file.write_all(removed_color.as_bytes());
@ -67,7 +75,7 @@ pub fn setup_log(init: &Option<String>, enable_color: bool, log_to_file: &Option
} }
logger.append(removed_color); logger.append(removed_color);
format ret
}; };
builder.format(format); builder.format(format);
builder.init().unwrap(); builder.init().unwrap();
@ -84,7 +92,7 @@ fn kill_color(s: &str) -> String {
#[test] #[test]
fn should_remove_colour() { fn should_remove_colour() {
let before = "test"; let before = "test";
let after = kill_color(&before.apply(Colour::Red.bold())); let after = kill_color(&Colour::Red.bold().paint(before));
assert_eq!(after, "test"); assert_eq!(after, "test");
} }

View File

@ -20,7 +20,6 @@ use std::path::PathBuf;
use ansi_term::Colour; use ansi_term::Colour;
use util::panics::{ForwardPanic, PanicHandler}; use util::panics::{ForwardPanic, PanicHandler};
use util::path::restrict_permissions_owner; use util::path::restrict_permissions_owner;
use util::Applyable;
use rpc_apis; use rpc_apis;
use ethcore_signer as signer; use ethcore_signer as signer;
use die::*; use die::*;
@ -60,7 +59,7 @@ pub fn new_token(path: String) -> io::Result<()> {
let mut codes = try!(signer::AuthCodes::from_file(&path)); let mut codes = try!(signer::AuthCodes::from_file(&path));
let code = try!(codes.generate_new()); let code = try!(codes.generate_new());
try!(codes.to_file(&path)); try!(codes.to_file(&path));
println!("This key code will authorise your System Signer UI: {}", code.apply(Colour::White.bold())); info!("This key code will authorise your System Signer UI: {}", Colour::White.bold().paint(code));
Ok(()) Ok(())
} }

View File

@ -18,6 +18,8 @@
extern crate ethash; extern crate ethash;
use std::io::{Write};
use std::process::{Command, Stdio};
use std::thread; use std::thread;
use std::time::{Instant, Duration}; use std::time::{Instant, Duration};
use std::sync::{Arc, Weak}; use std::sync::{Arc, Weak};
@ -28,7 +30,7 @@ use jsonrpc_core::*;
use util::numbers::*; use util::numbers::*;
use util::sha3::*; use util::sha3::*;
use util::rlp::{encode, decode, UntrustedRlp, View}; use util::rlp::{encode, decode, UntrustedRlp, View};
use util::Mutex; use util::{FromHex, Mutex};
use ethcore::account_provider::AccountProvider; use ethcore::account_provider::AccountProvider;
use ethcore::client::{MiningBlockChainClient, BlockID, TransactionID, UncleID}; use ethcore::client::{MiningBlockChainClient, BlockID, TransactionID, UncleID};
use ethcore::header::Header as BlockHeader; use ethcore::header::Header as BlockHeader;
@ -255,6 +257,12 @@ impl<C, S: ?Sized, M, EM> EthClient<C, S, M, EM> where
} }
} }
#[cfg(windows)]
static SOLC: &'static str = "solc.exe";
#[cfg(not(windows))]
static SOLC: &'static str = "solc";
impl<C, S: ?Sized, M, EM> Eth for EthClient<C, S, M, EM> where impl<C, S: ?Sized, M, EM> Eth for EthClient<C, S, M, EM> where
C: MiningBlockChainClient + 'static, C: MiningBlockChainClient + 'static,
S: SyncProvider + 'static, S: SyncProvider + 'static,
@ -508,7 +516,13 @@ impl<C, S: ?Sized, M, EM> Eth for EthClient<C, S, M, EM> where
fn compilers(&self, params: Params) -> Result<Value, Error> { fn compilers(&self, params: Params) -> Result<Value, Error> {
try!(self.active()); try!(self.active());
match params { match params {
Params::None => to_value(&(&[] as &[String])), Params::None => {
let mut compilers = vec![];
if Command::new(SOLC).output().is_ok() {
compilers.push("solidity".to_owned())
}
to_value(&compilers)
}
_ => Err(Error::invalid_params()) _ => Err(Error::invalid_params())
} }
} }
@ -647,8 +661,28 @@ impl<C, S: ?Sized, M, EM> Eth for EthClient<C, S, M, EM> where
rpc_unimplemented!() rpc_unimplemented!()
} }
fn compile_solidity(&self, _: Params) -> Result<Value, Error> { fn compile_solidity(&self, params: Params) -> Result<Value, Error> {
try!(self.active()); try!(self.active());
rpc_unimplemented!() from_params::<(String, )>(params)
.and_then(|(code, )| {
let maybe_child = Command::new(SOLC)
.arg("--bin")
.arg("--optimize")
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.stderr(Stdio::null())
.spawn();
if let Ok(mut child) = maybe_child {
if let Ok(_) = child.stdin.as_mut().expect("we called child.stdin(Stdio::piped()) before spawn; qed").write_all(code.as_bytes()) {
if let Ok(output) = child.wait_with_output() {
let s = String::from_utf8_lossy(&output.stdout);
if let Some(hex) = s.lines().skip_while(|ref l| !l.contains("Binary")).skip(1).next() {
return to_value(&Bytes::new(hex.from_hex().unwrap_or(vec![])));
}
}
}
}
Err(Error::invalid_params())
})
} }
} }

View File

@ -201,7 +201,10 @@ const TRANSACTION_COUNT_SPEC: &'static [u8] = br#"{
"durationLimit": "0x0d", "durationLimit": "0x0d",
"blockReward": "0x4563918244F40000", "blockReward": "0x4563918244F40000",
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b", "registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
"frontierCompatibilityModeLimit": "0xffffffffffffffff" "frontierCompatibilityModeLimit": "0xffffffffffffffff",
"daoHardforkTransition": "0xffffffffffffffff",
"daoHardforkBeneficiary": "0x0000000000000000000000000000000000000000",
"daoHardforkAccounts": []
} }
} }
}, },

View File

@ -707,6 +707,11 @@ fn rpc_eth_compilers() {
assert_eq!(EthTester::default().io.handle_request(request), Some(response.to_owned())); assert_eq!(EthTester::default().io.handle_request(request), Some(response.to_owned()));
} }
// These tests are incorrect: their output is undefined as long as eth_getCompilers is [].
// Will ignore for now, but should probably be replaced by more substantial tests which check
// the output of eth_getCompilers to determine whether to test. CI systems can then be preinstalled
// with solc/serpent/lllc and they'll be proper again.
#[ignore]
#[test] #[test]
fn rpc_eth_compile_lll() { fn rpc_eth_compile_lll() {
let request = r#"{"jsonrpc": "2.0", "method": "eth_compileLLL", "params": [], "id": 1}"#; let request = r#"{"jsonrpc": "2.0", "method": "eth_compileLLL", "params": [], "id": 1}"#;
@ -715,6 +720,7 @@ fn rpc_eth_compile_lll() {
assert_eq!(EthTester::default().io.handle_request(request), Some(response.to_owned())); assert_eq!(EthTester::default().io.handle_request(request), Some(response.to_owned()));
} }
#[ignore]
#[test] #[test]
fn rpc_eth_compile_solidity() { fn rpc_eth_compile_solidity() {
let request = r#"{"jsonrpc": "2.0", "method": "eth_compileSolidity", "params": [], "id": 1}"#; let request = r#"{"jsonrpc": "2.0", "method": "eth_compileSolidity", "params": [], "id": 1}"#;
@ -723,6 +729,7 @@ fn rpc_eth_compile_solidity() {
assert_eq!(EthTester::default().io.handle_request(request), Some(response.to_owned())); assert_eq!(EthTester::default().io.handle_request(request), Some(response.to_owned()));
} }
#[ignore]
#[test] #[test]
fn rpc_eth_compile_serpent() { fn rpc_eth_compile_serpent() {
let request = r#"{"jsonrpc": "2.0", "method": "eth_compileSerpent", "params": [], "id": 1}"#; let request = r#"{"jsonrpc": "2.0", "method": "eth_compileSerpent", "params": [], "id": 1}"#;

View File

@ -32,7 +32,7 @@ fn client_service() -> Arc<TestBlockChainClient> {
} }
fn logger() -> Arc<RotatingLogger> { fn logger() -> Arc<RotatingLogger> {
Arc::new(RotatingLogger::new("rpc=trace".to_owned(), false)) Arc::new(RotatingLogger::new("rpc=trace".to_owned()))
} }
fn settings() -> Arc<NetworkSettings> { fn settings() -> Arc<NetworkSettings> {

View File

@ -28,7 +28,7 @@ pub enum BlockNumber {
/// Earliest block (genesis) /// Earliest block (genesis)
Earliest, Earliest,
/// Pending block (being mined) /// Pending block (being mined)
Pending Pending,
} }
impl Deserialize for BlockNumber { impl Deserialize for BlockNumber {
@ -63,8 +63,8 @@ impl Into<BlockID> for BlockNumber {
match self { match self {
BlockNumber::Num(n) => BlockID::Number(n), BlockNumber::Num(n) => BlockID::Number(n),
BlockNumber::Earliest => BlockID::Earliest, BlockNumber::Earliest => BlockID::Earliest,
// TODO: change this once blockid support pendingst, BlockNumber::Latest => BlockID::Latest,
BlockNumber::Pending | BlockNumber::Latest => BlockID::Latest, BlockNumber::Pending => BlockID::Pending,
} }
} }
} }
@ -87,7 +87,7 @@ mod tests {
assert_eq!(BlockID::Number(100), BlockNumber::Num(100).into()); assert_eq!(BlockID::Number(100), BlockNumber::Num(100).into());
assert_eq!(BlockID::Earliest, BlockNumber::Earliest.into()); assert_eq!(BlockID::Earliest, BlockNumber::Earliest.into());
assert_eq!(BlockID::Latest, BlockNumber::Latest.into()); assert_eq!(BlockID::Latest, BlockNumber::Latest.into());
assert_eq!(BlockID::Latest, BlockNumber::Pending.into()); assert_eq!(BlockID::Pending, BlockNumber::Pending.into());
} }
} }

View File

@ -23,6 +23,5 @@ parity-dapps-signer = { git = "https://github.com/ethcore/parity-ui.git", versio
clippy = { version = "0.0.79", optional = true} clippy = { version = "0.0.79", optional = true}
[features] [features]
default = ["ui"]
dev = ["clippy"] dev = ["clippy"]
ui = ["parity-dapps-signer"] ui = ["parity-dapps-signer"]

View File

@ -295,7 +295,7 @@ impl JournalDB for OverlayRecentDB {
} }
// update the overlay // update the overlay
for k in overlay_deletions { for k in overlay_deletions {
journal_overlay.backing_overlay.remove(&OverlayRecentDB::to_short_key(&k)); journal_overlay.backing_overlay.remove_and_purge(&OverlayRecentDB::to_short_key(&k));
} }
// apply canon deletions // apply canon deletions
for k in canon_deletions { for k in canon_deletions {
@ -303,7 +303,6 @@ impl JournalDB for OverlayRecentDB {
try!(batch.delete(&k)); try!(batch.delete(&k));
} }
} }
journal_overlay.backing_overlay.purge();
} }
journal_overlay.journal.remove(&end_era); journal_overlay.journal.remove(&end_era);
} }

View File

@ -17,8 +17,8 @@
//! Key-Value store abstraction with `RocksDB` backend. //! Key-Value store abstraction with `RocksDB` backend.
use std::default::Default; use std::default::Default;
use rocksdb::{DB, Writable, WriteBatch, IteratorMode, DBVector, DBIterator, use rocksdb::{DB, Writable, WriteBatch, WriteOptions, IteratorMode, DBVector, DBIterator,
IndexType, Options, DBCompactionStyle, BlockBasedOptions, Direction}; IndexType, Options, DBCompactionStyle, BlockBasedOptions, Direction, Cache};
const DB_BACKGROUND_FLUSHES: i32 = 2; const DB_BACKGROUND_FLUSHES: i32 = 2;
const DB_BACKGROUND_COMPACTIONS: i32 = 2; const DB_BACKGROUND_COMPACTIONS: i32 = 2;
@ -144,6 +144,7 @@ impl<'a> Iterator for DatabaseIterator {
/// Key-Value database. /// Key-Value database.
pub struct Database { pub struct Database {
db: DB, db: DB,
write_opts: WriteOptions,
} }
impl Database { impl Database {
@ -169,36 +170,28 @@ impl Database {
opts.set_max_background_flushes(DB_BACKGROUND_FLUSHES); opts.set_max_background_flushes(DB_BACKGROUND_FLUSHES);
opts.set_max_background_compactions(DB_BACKGROUND_COMPACTIONS); opts.set_max_background_compactions(DB_BACKGROUND_COMPACTIONS);
if let Some(cache_size) = config.cache_size {
// half goes to read cache
opts.set_block_cache_size_mb(cache_size as u64 / 2);
// quarter goes to each of the two write buffers
opts.set_write_buffer_size(cache_size * 1024 * 256);
}
/*
opts.set_bytes_per_sync(8388608);
opts.set_disable_data_sync(false);
opts.set_block_cache_size_mb(1024);
opts.set_table_cache_num_shard_bits(6);
opts.set_max_write_buffer_number(32);
opts.set_write_buffer_size(536870912);
opts.set_target_file_size_base(1073741824);
opts.set_min_write_buffer_number_to_merge(4);
opts.set_level_zero_stop_writes_trigger(2000);
opts.set_level_zero_slowdown_writes_trigger(0);
opts.set_compaction_style(DBUniversalCompaction);
opts.set_max_background_compactions(4);
opts.set_max_background_flushes(4);
opts.set_filter_deletes(false);
opts.set_disable_auto_compactions(false);
*/
if let Some(size) = config.prefix_size { if let Some(size) = config.prefix_size {
let mut block_opts = BlockBasedOptions::new(); let mut block_opts = BlockBasedOptions::new();
block_opts.set_index_type(IndexType::HashSearch); block_opts.set_index_type(IndexType::HashSearch);
opts.set_block_based_table_factory(&block_opts); opts.set_block_based_table_factory(&block_opts);
opts.set_prefix_extractor_fixed_size(size); opts.set_prefix_extractor_fixed_size(size);
if let Some(cache_size) = config.cache_size {
block_opts.set_cache(Cache::new(cache_size * 1024 * 256));
opts.set_write_buffer_size(cache_size * 1024 * 256);
}
} else if let Some(cache_size) = config.cache_size {
let mut block_opts = BlockBasedOptions::new();
// half goes to read cache
block_opts.set_cache(Cache::new(cache_size * 1024 * 256));
opts.set_block_based_table_factory(&block_opts);
// quarter goes to each of the two write buffers
opts.set_write_buffer_size(cache_size * 1024 * 256);
} }
let mut write_opts = WriteOptions::new();
write_opts.disable_wal(true);
let db = match DB::open(&opts, path) { let db = match DB::open(&opts, path) {
Ok(db) => db, Ok(db) => db,
Err(ref s) if s.starts_with("Corruption:") => { Err(ref s) if s.starts_with("Corruption:") => {
@ -209,7 +202,7 @@ impl Database {
}, },
Err(s) => { return Err(s); } Err(s) => { return Err(s); }
}; };
Ok(Database { db: db }) Ok(Database { db: db, write_opts: write_opts, })
} }
/// Insert a key-value pair in the transaction. Any existing value value will be overwritten. /// Insert a key-value pair in the transaction. Any existing value value will be overwritten.
@ -224,7 +217,7 @@ impl Database {
/// Commit transaction to database. /// Commit transaction to database.
pub fn write(&self, tr: DBTransaction) -> Result<(), String> { pub fn write(&self, tr: DBTransaction) -> Result<(), String> {
self.db.write(tr.batch) self.db.write_opt(tr.batch, &self.write_opts)
} }
/// Get value by key. /// Get value by key.

View File

@ -17,35 +17,13 @@
//! Common log helper functions //! Common log helper functions
use std::env; use std::env;
use std::borrow::Cow;
use rlog::LogLevelFilter; use rlog::LogLevelFilter;
use env_logger::LogBuilder; use env_logger::LogBuilder;
use std::sync::atomic::{Ordering, AtomicBool};
use arrayvec::ArrayVec; use arrayvec::ArrayVec;
pub use ansi_term::{Colour, Style}; pub use ansi_term::{Colour, Style};
use parking_lot::{RwLock, RwLockReadGuard}; use parking_lot::{RwLock, RwLockReadGuard};
lazy_static! {
static ref USE_COLOR: AtomicBool = AtomicBool::new(false);
}
/// Something which can be apply()ed.
pub trait Applyable: AsRef<str> {
/// Apply the style `c` to ourself, returning us styled in that manner.
fn apply(&self, c: Style) -> Cow<str>;
}
impl<T: AsRef<str>> Applyable for T {
fn apply(&self, c: Style) -> Cow<str> {
let s = self.as_ref();
match USE_COLOR.load(Ordering::Relaxed) {
true => Cow::Owned(format!("{}", c.paint(s))),
false => Cow::Borrowed(s),
}
}
}
lazy_static! { lazy_static! {
static ref LOG_DUMMY: bool = { static ref LOG_DUMMY: bool = {
let mut builder = LogBuilder::new(); let mut builder = LogBuilder::new();
@ -81,8 +59,7 @@ impl RotatingLogger {
/// Creates new `RotatingLogger` with given levels. /// Creates new `RotatingLogger` with given levels.
/// It does not enforce levels - it's just read only. /// It does not enforce levels - it's just read only.
pub fn new(levels: String, enable_color: bool) -> Self { pub fn new(levels: String) -> Self {
USE_COLOR.store(enable_color, Ordering::Relaxed);
RotatingLogger { RotatingLogger {
levels: levels, levels: levels,
logs: RwLock::new(ArrayVec::<[_; LOG_SIZE]>::new()), logs: RwLock::new(ArrayVec::<[_; LOG_SIZE]>::new()),
@ -111,7 +88,7 @@ mod test {
use super::RotatingLogger; use super::RotatingLogger;
fn logger() -> RotatingLogger { fn logger() -> RotatingLogger {
RotatingLogger::new("test".to_owned(), false) RotatingLogger::new("test".to_owned())
} }
#[test] #[test]

View File

@ -24,6 +24,7 @@ use hashdb::*;
use heapsize::*; use heapsize::*;
use std::mem; use std::mem;
use std::collections::HashMap; use std::collections::HashMap;
use std::collections::hash_map::Entry;
use std::default::Default; use std::default::Default;
#[derive(Debug,Clone)] #[derive(Debug,Clone)]
@ -162,6 +163,24 @@ impl MemoryDB {
pub fn mem_used(&self) -> usize { pub fn mem_used(&self) -> usize {
self.data.heap_size_of_children() self.data.heap_size_of_children()
} }
/// Remove an element and delete it from storage if reference count reaches zero.
pub fn remove_and_purge(&mut self, key: &H256) {
if key == &SHA3_NULL_RLP {
return;
}
match self.data.entry(key.clone()) {
Entry::Occupied(mut entry) =>
if entry.get().1 == 1 {
entry.remove();
} else {
entry.get_mut().1 -= 1;
},
Entry::Vacant(entry) => {
entry.insert((Bytes::new(), -1));
}
}
}
} }
static NULL_RLP_STATIC: [u8; 1] = [0x80; 1]; static NULL_RLP_STATIC: [u8; 1] = [0x80; 1];
@ -269,3 +288,28 @@ fn memorydb_denote() {
assert_eq!(m.get(&hash).unwrap(), b"Hello world!"); assert_eq!(m.get(&hash).unwrap(), b"Hello world!");
} }
#[test]
fn memorydb_remove_and_purge() {
let hello_bytes = b"Hello world!";
let hello_key = hello_bytes.sha3();
let mut m = MemoryDB::new();
m.remove(&hello_key);
assert_eq!(m.raw(&hello_key).unwrap().1, -1);
m.purge();
assert_eq!(m.raw(&hello_key).unwrap().1, -1);
m.insert(hello_bytes);
assert_eq!(m.raw(&hello_key).unwrap().1, 0);
m.purge();
assert_eq!(m.raw(&hello_key), None);
let mut m = MemoryDB::new();
m.remove_and_purge(&hello_key);
assert_eq!(m.raw(&hello_key).unwrap().1, -1);
m.insert(hello_bytes);
m.insert(hello_bytes);
assert_eq!(m.raw(&hello_key).unwrap().1, 1);
m.remove_and_purge(&hello_key);
assert_eq!(m.raw(&hello_key), None);
}

View File

@ -21,10 +21,25 @@ use network::error::NetworkError;
use network::host::{Host, NetworkContext, NetworkIoMessage, ProtocolId}; use network::host::{Host, NetworkContext, NetworkIoMessage, ProtocolId};
use network::stats::NetworkStats; use network::stats::NetworkStats;
use io::*; use io::*;
use std::sync::Arc;
use parking_lot::RwLock; use parking_lot::RwLock;
use std::sync::Arc;
use ansi_term::Colour;
struct HostHandler {
public_url: RwLock<Option<String>>
}
impl IoHandler<NetworkIoMessage> for HostHandler {
fn message(&self, _io: &IoContext<NetworkIoMessage>, message: &NetworkIoMessage) {
if let NetworkIoMessage::NetworkStarted(ref public_url) = *message {
let mut url = self.public_url.write();
if url.as_ref().map(|uref| uref != public_url).unwrap_or(true) {
info!(target: "network", "Public node URL: {}", Colour::White.bold().paint(public_url.as_ref()));
}
*url = Some(public_url.to_owned());
}
}
}
/// IO Service with networking /// IO Service with networking
/// `Message` defines a notification data type. /// `Message` defines a notification data type.
@ -34,12 +49,14 @@ pub struct NetworkService {
host: RwLock<Option<Arc<Host>>>, host: RwLock<Option<Arc<Host>>>,
stats: Arc<NetworkStats>, stats: Arc<NetworkStats>,
panic_handler: Arc<PanicHandler>, panic_handler: Arc<PanicHandler>,
host_handler: Arc<HostHandler>,
config: NetworkConfiguration, config: NetworkConfiguration,
} }
impl NetworkService { impl NetworkService {
/// Starts IO event loop /// Starts IO event loop
pub fn new(config: NetworkConfiguration) -> Result<NetworkService, UtilError> { pub fn new(config: NetworkConfiguration) -> Result<NetworkService, UtilError> {
let host_handler = Arc::new(HostHandler { public_url: RwLock::new(None) });
let panic_handler = PanicHandler::new_in_arc(); let panic_handler = PanicHandler::new_in_arc();
let io_service = try!(IoService::<NetworkIoMessage>::start()); let io_service = try!(IoService::<NetworkIoMessage>::start());
panic_handler.forward_from(&io_service); panic_handler.forward_from(&io_service);
@ -53,6 +70,7 @@ impl NetworkService {
panic_handler: panic_handler, panic_handler: panic_handler,
host: RwLock::new(None), host: RwLock::new(None),
config: config, config: config,
host_handler: host_handler,
}) })
} }
@ -106,6 +124,11 @@ impl NetworkService {
try!(self.io_service.register_handler(h.clone())); try!(self.io_service.register_handler(h.clone()));
*host = Some(h); *host = Some(h);
} }
if self.host_handler.public_url.read().is_none() {
try!(self.io_service.register_handler(self.host_handler.clone()));
}
Ok(()) Ok(())
} }

View File

@ -54,10 +54,14 @@ impl<'db> FatDBMut<'db> {
} }
impl<'db> TrieMut for FatDBMut<'db> { impl<'db> TrieMut for FatDBMut<'db> {
fn root(&self) -> &H256 { fn root(&mut self) -> &H256 {
self.raw.root() self.raw.root()
} }
fn is_empty(&self) -> bool {
self.raw.is_empty()
}
fn contains(&self, key: &[u8]) -> bool { fn contains(&self, key: &[u8]) -> bool {
self.raw.contains(&key.sha3()) self.raw.contains(&key.sha3())
} }

View File

@ -38,7 +38,6 @@ pub mod sectriedb;
pub mod sectriedbmut; pub mod sectriedbmut;
mod fatdb; mod fatdb;
mod fatdbmut; mod fatdbmut;
pub use self::trietraits::{Trie, TrieMut}; pub use self::trietraits::{Trie, TrieMut};

View File

@ -25,11 +25,11 @@ pub enum Node<'a> {
/// Null trie node; could be an empty root or an empty branch entry. /// Null trie node; could be an empty root or an empty branch entry.
Empty, Empty,
/// Leaf node; has key slice and value. Value may not be empty. /// Leaf node; has key slice and value. Value may not be empty.
Leaf(NibbleSlice<'a>, &'a[u8]), Leaf(NibbleSlice<'a>, &'a [u8]),
/// Extension node; has key slice and node data. Data may not be null. /// Extension node; has key slice and node data. Data may not be null.
Extension(NibbleSlice<'a>, &'a[u8]), Extension(NibbleSlice<'a>, &'a [u8]),
/// Branch node; has array of 16 child nodes (each possibly null) and an optional immediate node data. /// Branch node; has array of 16 child nodes (each possibly null) and an optional immediate node data.
Branch([&'a[u8]; 16], Option<&'a [u8]>) Branch([&'a [u8]; 16], Option<&'a [u8]>)
} }
impl<'a> Node<'a> { impl<'a> Node<'a> {

View File

@ -51,7 +51,13 @@ impl<'db> SecTrieDBMut<'db> {
} }
impl<'db> TrieMut for SecTrieDBMut<'db> { impl<'db> TrieMut for SecTrieDBMut<'db> {
fn root(&self) -> &H256 { self.raw.root() } fn root(&mut self) -> &H256 {
self.raw.root()
}
fn is_empty(&self) -> bool {
self.raw.is_empty()
}
fn contains(&self, key: &[u8]) -> bool { fn contains(&self, key: &[u8]) -> bool {
self.raw.contains(&key.sha3()) self.raw.contains(&key.sha3())

View File

@ -88,8 +88,7 @@ impl<'db> TrieDB<'db> {
pub fn to_map(hashes: Vec<H256>) -> HashMap<H256, u32> { pub fn to_map(hashes: Vec<H256>) -> HashMap<H256, u32> {
let mut r: HashMap<H256, u32> = HashMap::new(); let mut r: HashMap<H256, u32> = HashMap::new();
for h in hashes.into_iter() { for h in hashes.into_iter() {
let c = *r.get(&h).unwrap_or(&0); *r.entry(h).or_insert(0) += 1;
r.insert(h, c + 1);
} }
r r
} }
@ -184,7 +183,7 @@ impl<'db> TrieDB<'db> {
/// Return optional data for a key given as a `NibbleSlice`. Returns `None` if no data exists. /// Return optional data for a key given as a `NibbleSlice`. Returns `None` if no data exists.
fn do_lookup<'a, 'key>(&'a self, key: &NibbleSlice<'key>) -> Option<&'a [u8]> where 'a: 'key { fn do_lookup<'a, 'key>(&'a self, key: &NibbleSlice<'key>) -> Option<&'a [u8]> where 'a: 'key {
let root_rlp = self.db.get(&self.root).expect("Trie root not found!"); let root_rlp = self.root_data();
self.get_from_node(&root_rlp, key) self.get_from_node(&root_rlp, key)
} }

File diff suppressed because it is too large Load Diff

View File

@ -18,7 +18,7 @@ use hash::H256;
use rlp::SHA3_NULL_RLP; use rlp::SHA3_NULL_RLP;
/// Trie-Item type. /// Trie-Item type.
pub type TrieItem<'a> = (Vec<u8>, &'a[u8]); pub type TrieItem<'a> = (Vec<u8>, &'a [u8]);
/// A key-value datastore implemented as a database-backed modified Merkle tree. /// A key-value datastore implemented as a database-backed modified Merkle tree.
pub trait Trie { pub trait Trie {
@ -41,10 +41,10 @@ pub trait Trie {
/// A key-value datastore implemented as a database-backed modified Merkle tree. /// A key-value datastore implemented as a database-backed modified Merkle tree.
pub trait TrieMut { pub trait TrieMut {
/// Return the root of the trie. /// Return the root of the trie.
fn root(&self) -> &H256; fn root(&mut self) -> &H256;
/// Is the trie empty? /// Is the trie empty?
fn is_empty(&self) -> bool { *self.root() == SHA3_NULL_RLP } fn is_empty(&self) -> bool;
/// Does the trie contain a given key? /// Does the trie contain a given key?
fn contains(&self, key: &[u8]) -> bool; fn contains(&self, key: &[u8]) -> bool;