Merge branch 'master' into new-ui

This commit is contained in:
Tomasz Drwięga 2016-07-17 17:41:58 +02:00
commit a2735308b9
46 changed files with 27555 additions and 303 deletions

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)",
@ -585,6 +586,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"
@ -1067,7 +1078,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#6472a9dce16c267a3acec2ee6fd01d1bf8de4913" source = "git+https://github.com/ethcore/rust-rocksdb#dd597245bfcb621c6ffc45478e1fda0b05d2f409"
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)",
@ -1076,7 +1087,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#6472a9dce16c267a3acec2ee6fd01d1bf8de4913" source = "git+https://github.com/ethcore/rust-rocksdb#dd597245bfcb621c6ffc45478e1fda0b05d2f409"
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

@ -18,10 +18,10 @@ branches:
install: install:
- git submodule update --init --recursive - git submodule update --init --recursive
- ps: Install-Product node 6 - ps: Install-Product node 6
- ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-1.9.0-x86_64-pc-windows-msvc.exe" - ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-1.10.0-x86_64-pc-windows-msvc.exe"
- ps: Start-FileDownload "https://github.com/ethcore/win-build/raw/master/SimpleFC.dll" -FileName nsis\SimpleFC.dll - ps: Start-FileDownload "https://github.com/ethcore/win-build/raw/master/SimpleFC.dll" -FileName nsis\SimpleFC.dll
- ps: Start-FileDownload "https://github.com/ethcore/win-build/raw/master/vc_redist.x64.exe" -FileName nsis\vc_redist.x64.exe - ps: Start-FileDownload "https://github.com/ethcore/win-build/raw/master/vc_redist.x64.exe" -FileName nsis\vc_redist.x64.exe
- rust-1.9.0-x86_64-pc-windows-msvc.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust" - rust-1.10.0-x86_64-pc-windows-msvc.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust"
- SET PATH=%PATH%;C:\Program Files (x86)\Rust\bin;C:\Program Files (x86)\NSIS;C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Bin - SET PATH=%PATH%;C:\Program Files (x86)\Rust\bin;C:\Program Files (x86)\NSIS;C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Bin
- rustc -V - rustc -V
- cargo -V - cargo -V

View File

@ -271,11 +271,12 @@ fn hash_compute(light: &Light, full_size: usize, header_hash: &H256, nonce: u64)
let page_size = 4 * MIX_WORDS; let page_size = 4 * MIX_WORDS;
let num_full_pages = (full_size / page_size) as u32; let num_full_pages = (full_size / page_size) as u32;
let cache: &[Node] = &light.cache; // deref once for better performance
for i in 0..(ETHASH_ACCESSES as u32) { for i in 0..(ETHASH_ACCESSES as u32) {
let index = fnv_hash(f_mix.get_unchecked(0).as_words().get_unchecked(0) ^ i, *mix.get_unchecked(0).as_words().get_unchecked((i as usize) % MIX_WORDS)) % num_full_pages; let index = fnv_hash(f_mix.get_unchecked(0).as_words().get_unchecked(0) ^ i, *mix.get_unchecked(0).as_words().get_unchecked((i as usize) % MIX_WORDS)) % num_full_pages;
for n in 0..MIX_NODES { for n in 0..MIX_NODES {
let tmp_node = calculate_dag_item(index * MIX_NODES as u32 + n as u32, light); let tmp_node = calculate_dag_item(index * MIX_NODES as u32 + n as u32, cache);
for w in 0..NODE_WORDS { for w in 0..NODE_WORDS {
*mix.get_unchecked_mut(n).as_words_mut().get_unchecked_mut(w) = fnv_hash(*mix.get_unchecked(n).as_words().get_unchecked(w), *tmp_node.as_words().get_unchecked(w)); *mix.get_unchecked_mut(n).as_words_mut().get_unchecked_mut(w) = fnv_hash(*mix.get_unchecked(n).as_words().get_unchecked(w), *tmp_node.as_words().get_unchecked(w));
} }
@ -306,18 +307,17 @@ fn hash_compute(light: &Light, full_size: usize, header_hash: &H256, nonce: u64)
} }
} }
fn calculate_dag_item(node_index: u32, light: &Light) -> Node { fn calculate_dag_item(node_index: u32, cache: &[Node]) -> Node {
unsafe { unsafe {
let num_parent_nodes = light.cache.len(); let num_parent_nodes = cache.len();
let cache_nodes = &light.cache; let init = cache.get_unchecked(node_index as usize % num_parent_nodes);
let init = cache_nodes.get_unchecked(node_index as usize % num_parent_nodes);
let mut ret = init.clone(); let mut ret = init.clone();
*ret.as_words_mut().get_unchecked_mut(0) ^= node_index; *ret.as_words_mut().get_unchecked_mut(0) ^= node_index;
sha3::sha3_512(ret.bytes.as_mut_ptr(), ret.bytes.len(), ret.bytes.as_ptr(), ret.bytes.len()); sha3::sha3_512(ret.bytes.as_mut_ptr(), ret.bytes.len(), ret.bytes.as_ptr(), ret.bytes.len());
for i in 0..ETHASH_DATASET_PARENTS { for i in 0..ETHASH_DATASET_PARENTS {
let parent_index = fnv_hash(node_index ^ i, *ret.as_words().get_unchecked(i as usize % NODE_WORDS)) % num_parent_nodes as u32; let parent_index = fnv_hash(node_index ^ i, *ret.as_words().get_unchecked(i as usize % NODE_WORDS)) % num_parent_nodes as u32;
let parent = cache_nodes.get_unchecked(parent_index as usize); let parent = cache.get_unchecked(parent_index as usize);
for w in 0..NODE_WORDS { for w in 0..NODE_WORDS {
*ret.as_words_mut().get_unchecked_mut(w) = fnv_hash(*ret.as_words().get_unchecked(w), *parent.as_words().get_unchecked(w)); *ret.as_words_mut().get_unchecked_mut(w) = fnv_hash(*ret.as_words().get_unchecked(w), *parent.as_words().get_unchecked(w));
} }

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"
} }
} }
}, },

@ -1 +1 @@
Subproject commit 99afe8f5aad7bca5d0f1b1685390a4dea32d73c3 Subproject commit ac5475d676536cb945f98e9ff98384c01abd0599

View File

@ -35,6 +35,8 @@ pub struct Account {
code_hash: Option<H256>, code_hash: Option<H256>,
// Code cache of the account. // Code cache of the account.
code_cache: Bytes, code_cache: Bytes,
// Account is new or has been modified
dirty: bool,
} }
impl Account { impl Account {
@ -47,7 +49,8 @@ impl Account {
storage_root: SHA3_NULL_RLP, storage_root: SHA3_NULL_RLP,
storage_overlay: RefCell::new(storage.into_iter().map(|(k, v)| (k, (Filth::Dirty, v))).collect()), storage_overlay: RefCell::new(storage.into_iter().map(|(k, v)| (k, (Filth::Dirty, v))).collect()),
code_hash: Some(code.sha3()), code_hash: Some(code.sha3()),
code_cache: code code_cache: code,
dirty: true,
} }
} }
@ -59,7 +62,8 @@ impl Account {
storage_root: SHA3_NULL_RLP, storage_root: SHA3_NULL_RLP,
storage_overlay: RefCell::new(pod.storage.into_iter().map(|(k, v)| (k, (Filth::Dirty, v))).collect()), storage_overlay: RefCell::new(pod.storage.into_iter().map(|(k, v)| (k, (Filth::Dirty, v))).collect()),
code_hash: Some(pod.code.sha3()), code_hash: Some(pod.code.sha3()),
code_cache: pod.code code_cache: pod.code,
dirty: true,
} }
} }
@ -72,6 +76,7 @@ impl Account {
storage_overlay: RefCell::new(HashMap::new()), storage_overlay: RefCell::new(HashMap::new()),
code_hash: Some(SHA3_EMPTY), code_hash: Some(SHA3_EMPTY),
code_cache: vec![], code_cache: vec![],
dirty: true,
} }
} }
@ -85,6 +90,7 @@ impl Account {
storage_overlay: RefCell::new(HashMap::new()), storage_overlay: RefCell::new(HashMap::new()),
code_hash: Some(r.val_at(3)), code_hash: Some(r.val_at(3)),
code_cache: vec![], code_cache: vec![],
dirty: false,
} }
} }
@ -98,6 +104,7 @@ impl Account {
storage_overlay: RefCell::new(HashMap::new()), storage_overlay: RefCell::new(HashMap::new()),
code_hash: None, code_hash: None,
code_cache: vec![], code_cache: vec![],
dirty: true,
} }
} }
@ -106,6 +113,7 @@ impl Account {
pub fn init_code(&mut self, code: Bytes) { pub fn init_code(&mut self, code: Bytes) {
assert!(self.code_hash.is_none()); assert!(self.code_hash.is_none());
self.code_cache = code; self.code_cache = code;
self.dirty = true;
} }
/// Reset this account's code to the given code. /// Reset this account's code to the given code.
@ -117,6 +125,7 @@ impl Account {
/// Set (and cache) the contents of the trie's storage at `key` to `value`. /// Set (and cache) the contents of the trie's storage at `key` to `value`.
pub fn set_storage(&mut self, key: H256, value: H256) { pub fn set_storage(&mut self, key: H256, value: H256) {
self.storage_overlay.borrow_mut().insert(key, (Filth::Dirty, value)); self.storage_overlay.borrow_mut().insert(key, (Filth::Dirty, value));
self.dirty = true;
} }
/// Get (and cache) the contents of the trie's storage at `key`. /// Get (and cache) the contents of the trie's storage at `key`.
@ -172,6 +181,10 @@ impl Account {
!self.code_cache.is_empty() || (self.code_cache.is_empty() && self.code_hash == Some(SHA3_EMPTY)) !self.code_cache.is_empty() || (self.code_cache.is_empty() && self.code_hash == Some(SHA3_EMPTY))
} }
/// Is this a new or modified account?
pub fn is_dirty(&self) -> bool {
self.dirty
}
/// Provide a database to get `code_hash`. Should not be called if it is a contract without code. /// Provide a database to get `code_hash`. Should not be called if it is a contract without code.
pub fn cache_code(&mut self, db: &AccountDB) -> bool { pub fn cache_code(&mut self, db: &AccountDB) -> bool {
// TODO: fill out self.code_cache; // TODO: fill out self.code_cache;
@ -201,16 +214,23 @@ impl Account {
pub fn storage_overlay(&self) -> Ref<HashMap<H256, (Filth, H256)>> { self.storage_overlay.borrow() } pub fn storage_overlay(&self) -> Ref<HashMap<H256, (Filth, H256)>> { self.storage_overlay.borrow() }
/// Increment the nonce of the account by one. /// Increment the nonce of the account by one.
pub fn inc_nonce(&mut self) { self.nonce = self.nonce + U256::from(1u8); } pub fn inc_nonce(&mut self) {
self.nonce = self.nonce + U256::from(1u8);
self.dirty = true;
}
/// Increment the nonce of the account by one. /// Increment the nonce of the account by one.
pub fn add_balance(&mut self, x: &U256) { self.balance = self.balance + *x; } pub fn add_balance(&mut self, x: &U256) {
self.balance = self.balance + *x;
self.dirty = true;
}
/// Increment the nonce of the account by one. /// Increment the nonce of the account by one.
/// Panics if balance is less than `x` /// Panics if balance is less than `x`
pub fn sub_balance(&mut self, x: &U256) { pub fn sub_balance(&mut self, x: &U256) {
assert!(self.balance >= *x); assert!(self.balance >= *x);
self.balance = self.balance - *x; self.balance = self.balance - *x;
self.dirty = true;
} }
/// Commit the `storage_overlay` to the backing DB and update `storage_root`. /// Commit the `storage_overlay` to the backing DB and update `storage_root`.

View File

@ -494,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

@ -359,6 +359,12 @@ impl BlockChain {
bc bc
} }
/// Returns true if the given parent block has given child
/// (though not necessarily a part of the canon chain).
fn is_known_child(&self, parent: &H256, hash: &H256) -> bool {
self.extras_db.read_with_cache(&self.block_details, parent).map_or(false, |d| d.children.contains(hash))
}
/// Set the cache configuration. /// Set the cache configuration.
pub fn configure_cache(&self, pref_cache_size: usize, max_cache_size: usize) { pub fn configure_cache(&self, pref_cache_size: usize, max_cache_size: usize) {
self.pref_cache_size.store(pref_cache_size, AtomicOrder::Relaxed); self.pref_cache_size.store(pref_cache_size, AtomicOrder::Relaxed);
@ -463,7 +469,7 @@ impl BlockChain {
let header = block.header_view(); let header = block.header_view();
let hash = header.sha3(); let hash = header.sha3();
if self.is_known(&hash) { if self.is_known_child(&header.parent_hash(), &hash) {
return ImportRoute::none(); return ImportRoute::none();
} }
@ -488,7 +494,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 +501,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 +530,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 +1195,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
@ -145,6 +145,7 @@ pub struct Client {
notify: RwLock<Option<Weak<ChainNotify>>>, notify: RwLock<Option<Weak<ChainNotify>>>,
queue_transactions: AtomicUsize, queue_transactions: AtomicUsize,
previous_enode: Mutex<Option<String>>, previous_enode: Mutex<Option<String>>,
last_hashes: RwLock<VecDeque<H256>>,
} }
const HISTORY: u64 = 1200; const HISTORY: u64 = 1200;
@ -232,6 +233,7 @@ impl Client {
notify: RwLock::new(None), notify: RwLock::new(None),
queue_transactions: AtomicUsize::new(0), queue_transactions: AtomicUsize::new(0),
previous_enode: Mutex::new(None), previous_enode: Mutex::new(None),
last_hashes: RwLock::new(VecDeque::new()),
}; };
Ok(Arc::new(client)) Ok(Arc::new(client))
} }
@ -253,6 +255,14 @@ impl Client {
} }
fn build_last_hashes(&self, parent_hash: H256) -> LastHashes { fn build_last_hashes(&self, parent_hash: H256) -> LastHashes {
{
let hashes = self.last_hashes.read();
if hashes.front().map_or(false, |h| h == &parent_hash) {
let mut res = Vec::from(hashes.clone());
res.resize(256, H256::default());
return res;
}
}
let mut last_hashes = LastHashes::new(); let mut last_hashes = LastHashes::new();
last_hashes.resize(256, H256::new()); last_hashes.resize(256, H256::new());
last_hashes[0] = parent_hash; last_hashes[0] = parent_hash;
@ -264,6 +274,8 @@ impl Client {
None => break, None => break,
} }
} }
let mut cached_hashes = self.last_hashes.write();
*cached_hashes = VecDeque::from(last_hashes.clone());
last_hashes last_hashes
} }
@ -418,6 +430,7 @@ impl Client {
fn commit_block<B>(&self, block: B, hash: &H256, block_data: &[u8]) -> ImportRoute where B: IsBlock + Drain { fn commit_block<B>(&self, block: B, hash: &H256, block_data: &[u8]) -> ImportRoute where B: IsBlock + Drain {
let number = block.header().number(); let number = block.header().number();
let parent = block.header().parent_hash().clone();
// Are we committing an era? // Are we committing an era?
let ancient = if number >= HISTORY { let ancient = if number >= HISTORY {
let n = number - HISTORY; let n = number - HISTORY;
@ -445,9 +458,20 @@ impl Client {
enacted: route.enacted.clone(), enacted: route.enacted.clone(),
retracted: route.retracted.len() retracted: route.retracted.len()
}); });
self.update_last_hashes(&parent, hash);
route route
} }
fn update_last_hashes(&self, parent: &H256, hash: &H256) {
let mut hashes = self.last_hashes.write();
if hashes.front().map_or(false, |h| h == parent) {
if hashes.len() > 255 {
hashes.pop_back();
}
hashes.push_front(hash.clone());
}
}
/// Import transactions from the IO queue /// Import transactions from the IO queue
pub fn import_queued_transactions(&self, transactions: &[Bytes]) -> usize { pub fn import_queued_transactions(&self, transactions: &[Bytes]) -> usize {
let _timer = PerfTimer::new("import_queued_transactions"); let _timer = PerfTimer::new("import_queued_transactions");
@ -608,18 +632,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)]
@ -687,7 +699,7 @@ 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 &BlockID::Pending = &id {
if let Some(block) = self.miner.pending_block() { if let Some(block) = self.miner.pending_block() {
return Some(block.rlp_bytes(Seal::Without)); return Some(block.rlp_bytes(Seal::Without));
} }
} }
@ -708,7 +720,7 @@ impl BlockChainClient for Client {
if let &BlockID::Pending = &id { if let &BlockID::Pending = &id {
if let Some(block) = self.miner.pending_block() { 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")); 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

@ -59,8 +59,6 @@ pub enum TransactionError {
}, },
/// Transaction's gas limit (aka gas) is invalid. /// Transaction's gas limit (aka gas) is invalid.
InvalidGasLimit(OutOfBounds<U256>), InvalidGasLimit(OutOfBounds<U256>),
/// Transaction is invalid for some other reason.
DAORescue,
} }
impl fmt::Display for TransactionError { impl fmt::Display for TransactionError {
@ -79,7 +77,6 @@ impl fmt::Display for TransactionError {
GasLimitExceeded { limit, got } => GasLimitExceeded { limit, got } =>
format!("Gas limit exceeded. Limit={}, Given={}", limit, got), format!("Gas limit exceeded. Limit={}, Given={}", limit, got),
InvalidGasLimit(ref err) => format!("Invalid gas limit. {}", err), InvalidGasLimit(ref err) => format!("Invalid gas limit. {}", err),
DAORescue => "Transaction is invalid due to the DAO rescue.".into(),
}; };
f.write_fmt(format_args!("Transaction error ({})", msg)) f.write_fmt(format_args!("Transaction error ({})", msg))

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

@ -80,8 +80,6 @@ pub struct Schedule {
pub tx_data_non_zero_gas: usize, pub tx_data_non_zero_gas: usize,
/// Gas price for copying memory /// Gas price for copying memory
pub copy_gas: usize, pub copy_gas: usize,
/// DAO Rescue softfork block
pub reject_dao_transactions: bool,
} }
impl Schedule { impl Schedule {
@ -128,7 +126,6 @@ impl Schedule {
tx_data_zero_gas: 4, tx_data_zero_gas: 4,
tx_data_non_zero_gas: 68, tx_data_non_zero_gas: 68,
copy_gas: 3, copy_gas: 3,
reject_dao_transactions: false,
} }
} }
} }

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

@ -116,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;
@ -775,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

@ -232,36 +232,10 @@ impl State {
let options = TransactOptions { tracing: tracing, vm_tracing: false, check_nonce: true }; let options = TransactOptions { tracing: tracing, vm_tracing: false, check_nonce: true };
let e = try!(Executive::new(self, env_info, engine, vm_factory).transact(t, options)); let e = try!(Executive::new(self, env_info, engine, vm_factory).transact(t, options));
let broken_dao = H256::from("6a5d24750f78441e56fec050dc52fe8e911976485b7472faac7464a176a67caa");
// dao attack soft fork
if engine.schedule(&env_info).reject_dao_transactions {
let whitelisted = if let Action::Call(to) = t.action {
to == Address::from("Da4a4626d3E16e094De3225A751aAb7128e96526") ||
to == Address::from("2ba9D006C1D72E67A70b5526Fc6b4b0C0fd6D334")
} else { false };
if !whitelisted {
// collect all the addresses which have changed.
let addresses = self.cache.borrow().iter().map(|(addr, _)| addr.clone()).collect::<Vec<_>>();
for a in &addresses {
if self.code(a).map_or(false, |c| c.sha3() == broken_dao) {
// Figure out if the balance has been reduced.
let maybe_original = self.trie_factory
.readonly(self.db.as_hashdb(), &self.root)
.expect(SEC_TRIE_DB_UNWRAP_STR)
.get(&a).map(Account::from_rlp);
if maybe_original.map_or(false, |original| *original.balance() > self.balance(a)) {
return Err(Error::Transaction(TransactionError::DAORescue));
}
}
}
}
}
// TODO uncomment once to_pod() works correctly. // TODO uncomment once to_pod() works correctly.
// trace!("Applied transaction. Diff:\n{}\n", state_diff::diff_pod(&old, &self.to_pod())); // trace!("Applied transaction. Diff:\n{}\n", state_diff::diff_pod(&old, &self.to_pod()));
self.commit(); self.commit();
self.clear();
let receipt = Receipt::new(self.root().clone(), e.cumulative_gas_used, e.logs); let receipt = Receipt::new(self.root().clone(), e.cumulative_gas_used, e.logs);
// trace!("Transaction receipt: {:?}", receipt); // trace!("Transaction receipt: {:?}", receipt);
Ok(ApplyOutcome{receipt: receipt, trace: e.trace}) Ok(ApplyOutcome{receipt: receipt, trace: e.trace})
@ -275,12 +249,12 @@ impl State {
// TODO: is this necessary or can we dispense with the `ref mut a` for just `a`? // TODO: is this necessary or can we dispense with the `ref mut a` for just `a`?
for (address, ref mut a) in accounts.iter_mut() { for (address, ref mut a) in accounts.iter_mut() {
match a { match a {
&mut&mut Some(ref mut account) => { &mut&mut Some(ref mut account) if account.is_dirty() => {
let mut account_db = AccountDBMut::new(db, address); let mut account_db = AccountDBMut::new(db, address);
account.commit_storage(trie_factory, &mut account_db); account.commit_storage(trie_factory, &mut account_db);
account.commit_code(&mut account_db); account.commit_code(&mut account_db);
} }
&mut&mut None => {} _ => {}
} }
} }
@ -288,8 +262,9 @@ impl State {
let mut trie = trie_factory.from_existing(db, root).unwrap(); let mut trie = trie_factory.from_existing(db, root).unwrap();
for (address, ref a) in accounts.iter() { for (address, ref a) in accounts.iter() {
match **a { match **a {
Some(ref account) => trie.insert(address, &account.rlp()), Some(ref account) if account.is_dirty() => trie.insert(address, &account.rlp()),
None => trie.remove(address), None => trie.remove(address),
_ => (),
} }
} }
} }
@ -301,6 +276,11 @@ impl State {
Self::commit_into(&self.trie_factory, self.db.as_hashdb_mut(), &mut self.root, self.cache.borrow_mut().deref_mut()); Self::commit_into(&self.trie_factory, self.db.as_hashdb_mut(), &mut self.root, self.cache.borrow_mut().deref_mut());
} }
/// Clear state cache
pub fn clear(&mut self) {
self.cache.borrow_mut().clear();
}
#[cfg(test)] #[cfg(test)]
#[cfg(feature = "json-tests")] #[cfg(feature = "json-tests")]
/// Populate the state from `accounts`. /// Populate the state from `accounts`.

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

@ -1,6 +1,6 @@
#!/usr/bin/env bash #!/usr/bin/env bash
PARITY_DEB_URL=https://github.com/ethcore/parity/releases/download/v1.2.1/parity_linux_1.2.1-0_amd64.deb PARITY_DEB_URL=https://github.com/ethcore/parity/releases/download/v1.2.2/parity_linux_1.2.2-0_amd64.deb
function run_installer() function run_installer()

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;
@ -82,7 +83,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, use ethcore::client::{BlockID, BlockChainClient, ClientConfig, get_db_path, BlockImportError,
ChainNotify, Mode}; ChainNotify, Mode};
@ -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

@ -170,7 +170,6 @@ fn transaction_error(error: EthcoreError) -> Error {
format!("Transaction cost exceeds current gas limit. Limit: {}, got: {}. Try decreasing supplied gas.", limit, got) format!("Transaction cost exceeds current gas limit. Limit: {}, got: {}. Try decreasing supplied gas.", limit, got)
}, },
InvalidGasLimit(_) => "Supplied gas is beyond limit.".into(), InvalidGasLimit(_) => "Supplied gas is beyond limit.".into(),
DAORescue => "Transaction removes funds from a DAO.".into(),
}; };
Error { Error {
code: ErrorCode::ServerError(error_codes::TRANSACTION_ERROR), code: ErrorCode::ServerError(error_codes::TRANSACTION_ERROR),

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

@ -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

@ -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

@ -177,16 +177,13 @@ impl Database {
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 { if let Some(cache_size) = config.cache_size {
block_opts.set_cache(Cache::new(cache_size * 1024 * 256)); block_opts.set_cache(Cache::new(cache_size * 1024 * 1024));
opts.set_write_buffer_size(cache_size * 1024 * 256);
} }
} else if let Some(cache_size) = config.cache_size { } else if let Some(cache_size) = config.cache_size {
let mut block_opts = BlockBasedOptions::new(); let mut block_opts = BlockBasedOptions::new();
// half goes to read cache // half goes to read cache
block_opts.set_cache(Cache::new(cache_size * 1024 * 256)); block_opts.set_cache(Cache::new(cache_size * 1024 * 1024));
opts.set_block_based_table_factory(&block_opts); 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(); let mut write_opts = WriteOptions::new();
@ -207,12 +204,12 @@ impl Database {
/// 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.
pub fn put(&self, key: &[u8], value: &[u8]) -> Result<(), String> { pub fn put(&self, key: &[u8], value: &[u8]) -> Result<(), String> {
self.db.put(key, value) self.db.put_opt(key, value, &self.write_opts)
} }
/// Delete value by key. /// Delete value by key.
pub fn delete(&self, key: &[u8]) -> Result<(), String> { pub fn delete(&self, key: &[u8]) -> Result<(), String> {
self.db.delete(key) self.db.delete_opt(key, &self.write_opts)
} }
/// Commit transaction to database. /// Commit transaction to database.

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(())
} }