[beta] More backports for 2.1.2 (#9733)

* produce portable binaries (#9725)

* HF in POA Core (2018-10-22) (#9724)

https://github.com/poanetwork/poa-chain-spec/pull/87

* Use static call and apparent value transfer for block reward contract code (#9603)

* Verify block syncing responses against requests (#9670)

* sync: Validate received BlockHeaders packets against stored request.

* sync: Validate received BlockBodies and BlockReceipts.

* sync: Fix broken tests.

* sync: Unit tests for BlockDownloader::import_headers.

* sync: Unit tests for import_{bodies,receipts}.

* tests: Add missing method doc.

* Fix ancient blocks sync (#9531)

* Log block set in block_sync for easier debugging

* logging macros

* Match no args in sync logging macros

* Add QueueFull error

* Only allow importing headers if the first matches requested

* WIP

* Test for chain head gaps and log

* Calc distance even with 2 heads

* Revert previous commits, preparing simple fix

This reverts commit 5f38aa885b22ebb0e3a1d60120cea69f9f322628.

* Reject headers with no gaps when ChainHead

* Reset block sync download when queue full

* Simplify check for subchain heads

* Add comment to explain subchain heads filter

* Fix is_subchain_heads check and comment

* Prevent premature round completion after restart

This is a problem on mainnet where multiple stale peer requests will
force many rounds to complete quickly, forcing the retraction.

* Reset stale old blocks request after queue full

* Revert "Reject headers with no gaps when ChainHead"

This reverts commit 0eb865539e5dee37ab34f168f5fb643300de5ace.

* Add BlockSet to BlockDownloader logging

Currently it is difficult to debug this because there are two instances,
one for OldBlocks and one for NewBlocks. This adds the BlockSet to all
log messages for easy log filtering.

* Reset OldBlocks download from last enqueued

Previously when the ancient block queue was full it would restart the
download from the last imported block, so the ones still in the queue would be
redownloaded. Keeping the existing downloader instance and just
resetting it will start again from the last enqueued block.:wq

* Ignore expired Body and Receipt requests

* Log when ancient block download being restarted

* Only request old blocks from peers with >= difficulty

https://github.com/paritytech/parity-ethereum/pull/9226 might be too
permissive and causing the behaviour of the retraction soon after the
fork block. With this change the peer difficulty has to be greater than
or euqal to our syncing difficulty, so should still fix
https://github.com/paritytech/parity-ethereum/issues/9225

* Some logging and clear stalled blocks head

* Revert "Some logging and clear stalled blocks head"

This reverts commit 757641d9b817ae8b63fec684759b0815af9c4d0e.

* Reset stalled header if useless more than once

* Store useless headers in HashSet

* Add sync target to logging macro

* Don't disable useless peer and fix log macro

* Clear useless headers on reset and comments

* Use custom error for collecting blocks

Previously we resued BlockImportError, however only the Invalid case and
this made little sense with the QueueFull error.

* Remove blank line

* Test for reset sync after consecutive useless headers

* Don't reset after consecutive headers when chain head

* Delete commented out imports

* Return DownloadAction from collect_blocks instead of error

* Don't reset after round complete, was causing test hangs

* Add comment explaining reset after useless

* Replace HashSet with counter for useless headers

* Refactor sync reset on bad block/queue full

* Add missing target for log message

* Fix compiler errors and test after merge

* ethcore: revert ethereum tests submodule update

* Add hardcoded headers (#9730)

* add foundation hardcoded header #6486017

* add ropsten hardcoded headers #4202497

* add kovan hardcoded headers #9023489

* gitlab ci: releasable_branches: change variables condition to schedule (#9729)
This commit is contained in:
André Silva 2018-10-10 17:55:55 +01:00 committed by Afri Schoedon
parent 52fe28a052
commit d35f4c1f0d
14 changed files with 1246 additions and 241 deletions

View File

@ -24,6 +24,7 @@ cache:
- stable
- beta
- tags
- schedules
.collect_artifacts: &collect_artifacts
artifacts:

6
Cargo.lock generated
View File

@ -2179,12 +2179,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
"local-encoding 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-rocksdb-sys 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-rocksdb-sys 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "parity-rocksdb-sys"
version = "0.5.2"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
@ -4056,7 +4056,7 @@ dependencies = [
"checksum parity-crypto 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c1117f6574377d21309bfa1f7d69ff734120685d92b02c3f362b122585758840"
"checksum parity-path 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5962540f99d3895d9addf535f37ab1397886bc2c68e59efd040ef458e5f8c3f7"
"checksum parity-rocksdb 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cd55d2d6d6000ec99f021cf52c9acc7d2a402e14f95ced4c5de230696fabe00b"
"checksum parity-rocksdb-sys 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9ae07d4bfb2759541957c19f471996b807fc09ef3a5bdce14409b57f038de49f"
"checksum parity-rocksdb-sys 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0e59eda423021494a6cf1be74f6989add403f53157409993f794e17b123cab51"
"checksum parity-snappy 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2c5f9d149b13134b8b354d93a92830efcbee6fe5b73a2e6e540fe70d4dd8a63"
"checksum parity-snappy-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c2086caac40c79289cb70d7e1c64f5888e1c53f5d38399d3e95101493739f423"
"checksum parity-tokio-ipc 0.1.5 (git+https://github.com/nikvolf/parity-tokio-ipc?rev=7c9bbe3bc45d8e72a92b0951acc877da228abd50)" = "<none>"

View File

@ -177,8 +177,8 @@
"stateRoot": "0xd7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544"
},
"hardcodedSync": {
"header": "f9020ba0c7139a7f4b14c2e12dbe34aeb92711b37747bf8698ecdd6f2c3b1f5f3840e288a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479452e44f279f4203dcf680395379e5f9990a69f13ca06e817f8a9b206f93a393da76a3ece2a74b98eaecc4dae0cfa8f409455e88ccb4a0d739197170d2bc6bbb24fac0ce695982090702082fe1541bb7634f018dfe87b3a038503b7299fb1c113a78b4a3a5dfd997ef32e7fbf722fc178dfcb21e1af1f7f5b9010000020000000000000008000000000010000000000000000000000000000200000002000000000008000000000000000000000000000000000000000000000000000000000000000001004008000000000000000000000000000080000000000008000000080000000000008000000000000000000000000000040210004000000010000000400000000001040000000200000000000000440008000000040000000000000000000000000010000000000000000000000000000000800000000000100002000000000000000000002000000000000000000000000000000000000080000000100000000000000000040400000000000000004000000000000000870c90e059b181c6835ee8018379fb9583065150845b833d198a7777772e62772e636f6da0171fc2d066507ea10c8c2d7bedd5ccc3f0dfb4d590a3998a614013326c0b213a88b4fd884826187393",
"totalDifficulty": "6255555800944520547241",
"header": "f90206a0391c42ff4f047145a6b9a14179c3cc404b31d92f30693e28cf2bba41f47f6329a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794b2930b35844a230f00e51431acae96fe543a0347a0fb280d4457e60a0b96577e1dde9e00905102cfd36def5c5b31dcc2284636136ea077f739c324e35c7448b14aa02186973d3c74cc1ab081498cd0c487a604873723a0e462d76b5204d14b13d1f1b39ea048a3b637f91d42c729c367d5bbdbd0a72d70b90100008003410402005000200009400030c40490500208480008414000a40048806408000080802008204400010001800c0020080c0a00400105a9080820400900240000084012030a1504030508000200005c4404a0c3490820000010400811040004708a1006910211444040c28001a800e920d00000940c200119111a10401001008044214002002080c21081801e008a320848a204400042400898004004010028840181106210080254a081112480031000410202440092c880be3894000120050500860880000108000c0080009e0000204007212840808cb80200601024020000210280100c018540b28a1041a62400000108204084000008808040000004870bc009a1914d7f8362f801837a121d8379ee5a845bbd53ca8573696e6731a0abce0f90ce69f740080eeb94d1cb13981fafe3bc6d020a44815acd86cbd3fc0a889501b04c0614e053",
"totalDifficulty": "7128515864594819065361",
"CHTs": [
"0x0eb474b7721727204978e92e27d31cddff56471911e424a4c8271c35f9c982cc",
"0xe10e94515fb5ffb7ffa9bf50db4a959b3f50c2ff75e0b8bd5f5e038749e52a11",
@ -3216,7 +3216,137 @@
"0xf344c0cf6516f0fa6617e48076726aefbdaaf5a31f67ad8199bc3f6e426bf904",
"0x3f3d2d33f36ba9009e9a72f3f5bbcb5df5392a19fc7afc8d37823aaf52b03477",
"0x346a89411f090d559ff90e670bf0a385b1b09f117fc9ffa18b09d3b6d5d8e45c",
"0x5bc5689e2b4572b8ceea472cc7827e22cbfd018920beebf5c5b25f65f5cd5357"
"0x5bc5689e2b4572b8ceea472cc7827e22cbfd018920beebf5c5b25f65f5cd5357",
"0xda418efcaa0076f77e4d2f0c57fc32fa67179a5631d9df52d56497113d0e87af",
"0x5a8050832e835202695129f6f384652827e61ea5f1be7ff300183201d8bd6b4d",
"0xd9f444c382da42c310bd2f05955187163ae7b224e5efd44ab95af332e197d374",
"0x9ef2c5bad361117eedbc2adcb72a2ef5eba4caf3a99a0cbb2a65a94d185e48ae",
"0x7e3e089bc46b00a4174d90003379c382ab5bd84d092b9c4db3189d2bdc24f00b",
"0x94f50fb12eed909d251fe69adb1a1f214776cb029d487360b55c3a2abb663d7e",
"0xd3e1f4244dea40d0741255db2dae72103e263390e0ccfdefcbb2da59ecc5ec9f",
"0x6808bf0cb7d4b677527de762b6db8ddf74a1b272349f34f44505912bd95d62f3",
"0xbf7672ac474b5b849bc086ff8455216f015c8fc7660436dee153522ef6991c04",
"0xe79d27a369cdd5455ddbc6bd9158cd1870aa895b3c3971d07f1555b95ed02ac3",
"0xfa9e20a36c11b0dfbf7e9c62872a6423f5460dfd18e447481461a41176678262",
"0xaafb6c407910341bedc82c0f260cdef75ce5653f644b93a465cb990247a32986",
"0x5058e655e0c179e6c20f48fbd08c2f34f9341f6c07972ff40f55bfabbc783b12",
"0x28d2e7c852de8602a764ff693b6881af18ddadd67fc7eff481f48ac20ebf32f6",
"0xf82e09e7916f61b5cfdc3dcf193bf9d535f2b33f93a06c90fbdc78b3aac6b7ef",
"0x626f3cca9e1a9e5e123e34485c8697c758ffc32213a727665065dd6abd2babe5",
"0xb7f1c07f673d903daa61dec649eb12286a7a0568ee36ecfb1023ec41427c8dd0",
"0x8d1d42bfe88dbe4c621cf68d380dc57e7768121a815546bb4aab29b7486da9ee",
"0x79835acd7266bce85978f481aa3c58f3bab9106d72892df8579e472dc95c6899",
"0x0911c9c804bbe9be0aebab6c92f5b71a893f72a9d0cd35a51b0e8cd19ab0c02a",
"0x7fd2eff10936d8d12fd9a1c6d27e77cbec4e48253465eb7e65876134ff60c8ec",
"0xc739ad4255415e2831c6996673f3d02dc79f6e6d6822f7dee23bff5b94833c3a",
"0x2559faafbae0852fe5a1c924f0e4f6ccdf4fd22f483148b3672a3e7b3692b669",
"0xca37f0aa3d375dbddc0b426c9564fe68f10b0a4cbbf1ab87f97b27b44878f2fb",
"0x00ba40205d1bd46ad5b5e73cd5b1f3418bd892586d5a4647ac9a6d158f15bd93",
"0xfa6d25c829299535e6b80af81a2416d10ed6903117e73c656b979a5f5abe3ee0",
"0xfd82d8944315cfb228a8fa416c18ff82cbd8869c3babbd3389dca6dd66797785",
"0xd8834cc29788cb40ec901725419df8c031a13e190756a6352696de870eaf4671",
"0xdf6843a52bf55e0f4404e7bdf144bb17d5c47a72ef9482e712090ac9730a7f52",
"0x4c2c562f835966c72985f7cca89a3b1a7b0d4cb04623dc96e337daa35a2f5925",
"0x49d2afd87e83a04059dbf3ef4e2598b8d0c495ab1cf91ed3004e16a608e910c2",
"0x5be64774739c001c239efae1ce9f2a5706cc6e3054ddf24b03c09358f2f4852f",
"0x678f789dc8c409653b36f4d2015338165d3bc6a73f2a77ebfe438676b8412d7a",
"0xf87c8fbf02d8e84cf72680e6b9a8b8be39fbae9f1eb1047c536d77535494a301",
"0xe2428b952d2c6d60d4925f56b3d8227cd6bc608da2c1b20264befd8b1ad89454",
"0x561a95eb50c663462bb8af3aab336bd745b0571746b10fefa791bc11be777763",
"0x6945f40e3499d2769ceecf499c701015d93fddb607720b18dbbd5a6a2aa46639",
"0x9c35b0367a2b82270d64f11c5299336b21b9f454077dcf7af3b2e434677a31b6",
"0x454dc6bb2443509381e478f1836cb36808e2ecd1a9944072056c292b710072f4",
"0x0c80566f34a46477592560a883a9c01fa393f7a2c9dbb28a54e46a5c017e8596",
"0xeff6a1255090509eccfdea2e591516886c91191f1f02eaae4808ac95009086fc",
"0x37cf60888e5ec75841e7f0533feef7200185a1c9f3253073216d83923c864829",
"0xb169ebb9e418809a96529835bc293782e4fc6310dba450afe3e95a7abdf7cc01",
"0xa3c8d5c71ce0477a247f56bfe95272ea07f0b7f10a8526b6e3ff9a8de8faa9ab",
"0x2bf18db4ee84bafbbabaf05d1d4d383c0d5fc91be6ae902334496996eb3a8e48",
"0x6c116f0d5809a2c28351a737ef3dbd1808685e1fd656e37df6b6e524aa82c918",
"0x21e2c8e019c687fdb360c9bdd4e3a5133488cd2e0365aee3b823120734aa6f27",
"0x20c9a1db9de894ab4f576265da25f391b32c0805c3da76fbfdd0aaf300f88a39",
"0x23ef1f43af87be7396449fc1f89d9766c59e8adf2660812293c65a27482ddb8e",
"0x04a82d3a4a5e7f2507688ecdcdc300d7fb97aa8be92a671d7d42c0b60fa4532b",
"0x99e204c42afd6d4040faad384517d99bd0e077b03310d32223234d2251d6a07c",
"0xe342c0c4295665b9e25773fc9998e18c460e723d0a14efdb59c19b27b9c7011b",
"0xb654b1b8ede0d54a605cda54b4635d2b3c2bb8efd01ebd416e52cc87b590d4f3",
"0x5daabc41eeb6de98336411a03ec0323995e81549941cf32b7e15c765d1b7b39e",
"0x5103fc7f0fc6df43fb081b580bb01476f2b1cbde73e4d0f9d1fa6d8427fae789",
"0xe2ecf5daba51d2f7b22106033fc43f956bd1db0c5ad02bd941bd3d2b96ca21c5",
"0xf152bce5c6d1efb7e22cde72d6b8ca37f556ffb686a13770c5fab46e04837c92",
"0x306007d8091caa5baaa78643307f5abf9a5f03996fc072a9016ba6b487b2017c",
"0xf57308d0c02c6b8e2416c070554c7e29911fa84ef4cf2d934e2322ca262e987c",
"0xb234fe7433d7fd71fe0c6dfc834e4bcbf84a261b95760a6c4eb67d222b9ff392",
"0x753059f3405f60da3aa7cd1aa0cbcfa4d5ef4f2a6ed34b853b2c5ab2181fd383",
"0x096c6630e821816d9f4bd83fbe0ccfd223282f34aae5a49f969ba30b98c324c3",
"0xd3eec9dedb057fbc839c474fc99cb54d89f3f47d896e06e758c98f1cd194b61f",
"0x0d44cb2a83b9a3fa18daac280cf08b46cc637d705488fd9400cd7300475d0a1c",
"0x2e37a3036db99c4cb1c135f5ca6b527fa13b2e80ee421805b7be5d8b16983602",
"0x381e0ca505308b7d3a083e60b0f9cb44c89f84942430ec9e4c5571796ab6a8eb",
"0x90b04d35906c6f5a59c266c3bce7c2b63cea1486f714e272592ef9ecab25b0ee",
"0x9cbea70e760f2ee97537d058d57f395886a2c3a6e769ccd3433b797b8716517b",
"0x4e2167846e8d6f0f6495b5f1443f59bea143b63f242e40186fc6429434d1136e",
"0xcaa0512739d000bb9783fceb46d0427098886e2b7f2e1140855f1a91f843d5b3",
"0xc14df4e379e84591f618e60b5953aa6764146c7822aa1f0e3c2287e20753985a",
"0xf4443154c04fd378b2c3812fee84b774b37d6e12778674403fb5c995379df866",
"0x1a501c2733cc138fb6ff3716899e08dbcd4d75edc18af8972e8a749e45eaf67a",
"0xfc8cb80bb0d0fb490f29aae3067641eef72e9225c558e7e299e0796a2086969d",
"0x2b7895550febf03070485c02d521e7ddd80b94b7fe33a60b7d7ea3545b13e7dd",
"0xfc4137c3cccd45050b5770a40b2f38c43c62b70b07d17bb6d762b405f3d753dc",
"0x86ed22bbbb9fc6600112b91601af4fff56d0ecbe9b3099f91d4477cab8e300f5",
"0x2273a60405ffb04bd024d880c79010f18d58e3c8ca0dc82795a0125364679fa6",
"0x00dfbfe7be3bb2116d9a603a01ac428c0088a2c1477810cd5d3be0d1bd86beab",
"0x7acfb03315585c79e2a47dbe847d24cab0785791f6af7f179fea4f9d6ecb0e0f",
"0xbf6a2e20ee1da5eec12b792bbaec2531e20766ba54bac423011c1057215851db",
"0xb5e94d1e3ba7363d1d79fb62dedd0b6c26b0485052dd64a7093d41ad2d41b890",
"0x9b0cc26f08708814960de8f280ac26d8ed5089a19bcbd2d765059306da22c196",
"0x22d8af121d3e395d3cb4f6ee43c06e6292f1b5ffda672d2e40dba69a2885f5ac",
"0x04bc174272a57189d76aa17de0f76806e8481f4903575ed8c4df12b042637e0e",
"0x06ebd2b6ec4b80280969a92726df5f9cb12d4288b60af617b7040876116656d3",
"0x0e9430513e63b5173271c89b1c91af0b4818d5d14a3034e1228c56c94186a109",
"0x8dc5422ba98d9e58112b052a00d4b82b1db32e22dd7ff2d845619899bd47f277",
"0xde513d40bdbb1e4956b468cece598d77134626a900066b92fb2ecd6fcb5f81c2",
"0x90746299ec75af1eb444ad14ac666ee444aa020fac3fb57796516d8772ec8f45",
"0xaa91c30c62b24f943ee1eec7586b682289541c0355c2726e44424da8686ca24d",
"0x76eb68baae9fb7ed126097f93842dcadfe6e7188d61549d9c0922a9b3ef8e80a",
"0x5aa5b4045e7fe71559a6e93f4a89b135eaef38b9a7f3a84e383ab1ff902ceca9",
"0x504b78f8fc3646e9722e96a5e97d99f2560d4fa3337fa5faf1cc8c8a05f3520d",
"0xffd7a5d7c3b21e8144f7678a9ddc039cf85eb32b09000a600c9f12aa7d6083ed",
"0xcbb4010000e96ff0b50b9627dae032bd50782ccbd51af8af7cfcd6cd184675f7",
"0xb96fabbdd02371bf4a6a0dc00e3874cf43d47246e27163c910c141b6759a4249",
"0x7358419f4e994ff296a37f2e88b238b3de6ba73062073c9467dec52a2df64422",
"0xca90be9f190a1fd0548becfa719a6e4763e92de0e4da4283a33b5f7d2886b425",
"0xa629364f7d6329b008d9c6a0262327bcc12953aa515cdb7b8817e7fe1d746d46",
"0xc5167bd8cac1ea6d14f305c9d4fe075e1875d96353e5236473b6daca5ae9b4fe",
"0xaf4ce2490e9504172a4393cf14e691e947c86a0ec7b53416384a5832b213d6c5",
"0xbfa4853ef2eecc5d99a90e1abfef37ca10c1f823c1d0ad59a1bb19339861241f",
"0xbb5a6584cdc7e4d06ec5fc1514233cc42970f6c332c3a9590978dc9908e58c0a",
"0xe69d7a0766db411e504f09a8f39f0583b2869016bbe95f21dba432bbe8b88442",
"0x89cf4caaaf200881779f5fa6da8ae91ff1c962045dd0622b5ca65c830d3a9d4f",
"0x82d66c631f4c4167e5301d896dbdfe24d8245b1de041fc85eaeb6e35117ed9a0",
"0x957907bc93879681d8682a188622f9bf2c7d2595dbe3e2e34bb01711cc4124d1",
"0xccb3a3380550586696abd3ac267e85c7516b2b682b3c48f66aca94d57500f3b3",
"0xaf56d4650406e70748dc860a7879d8d522599081f8e7011056c976b860703e43",
"0x5d96ac1d2dff8a054d880a44f5d45a1bd18aba29085fcd633b0608351ff1876c",
"0xe051736dad8b9f93a8f1c13031c2b63249925e152685a2e7ec188ee089861b20",
"0x0db8987339e1fae41af5f08e6fa15da5fd80de3431b54e82cf8edbdc792f870e",
"0xcc99097678110af2be8dc07da8d642dce928b7d9e2728fe6fef1fe2eaa81a72a",
"0x2428c1f94ca57c7913b011a68281eee9ee4855e4ed2c97e34a370e649b21acb1",
"0x501ee9580c89b1f67c5b3b69ae5fd1f83852a2f9330f53565bcd04d8a7c0b776",
"0x16ae47cfa19e8046f93a579fa2557b17aeca7892fc7a82b6d539930c8b7c95c9",
"0xda62590043ca70c1cdfc7969cdfa853bddbcef0ef62aabb9f372805322511014",
"0x481b4aeaaa60504c94dcfea966840b381db85183c34cd25b4857300b5c189003",
"0x035dcc47f8670a9f648bcb0232e42fd4876243a7a3bf737b88d723ba187929a7",
"0xebe9bf09e3577865aeb341a06f67bb6e607f10b04ed9f9d733492a9d0e9ceb1a",
"0xad5d85b58af6aef7f81bd6b2407c6e4884ec82b2ae2aeaa24e379a3d35902375",
"0x0f0dd63d7c6c284659283825624140b31a3adaf7cdbb2255faca443e52ebfe84",
"0x40079be1c9394e95b4823895ed380d79333ca2085aed2abd0d766f84d21b7b42",
"0x7cc40ed01b436ce225a3f9c5c2bc7f6f81aee40bb83a54bca2fe899b15f3e2b6",
"0x1b6356e1a83ca5b0eefda1fd62fa959b118d2a19a6a90f182a53414b3fc7f9f0",
"0xae4a71712cc96a5b30b45e3b92c339c2e975e4ed683f4d1fcadcdc121ff7c6bf",
"0x226f6d8c71ec32c5eaab6b01c0fc1d00ae95e60b383d09560e90549b79eb1447",
"0xf3dec779841c9384df93bcefbba8700a292b570b29d286a7c9c5a442b4788a20",
"0x63ef48e80efa45383857adcb0f31076393260cbad058d1938345ad13faae50b4"
]
},
"nodes": [

View File

@ -62,8 +62,8 @@
"gasLimit": "0x5B8D80"
},
"hardcodedSync": {
"header": "f9023ea00861b3771ffb84fce48b8ba3c54a09f81e91ccb38c401261f06d370098889a43a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479400e6d2b931f55a3f1701c7389d592a7778897879a071cc81d58cdd21d1e17f7389e55c530cd9f94cc15bb32af6477320682327dcffa06090021a7c09ae5e75e443410ebdb76de04f1eafb0ab910daae96ee6eec560eaa032510bf257dd03b11f3b4761b94b495a5b5a18cd6eb17c77785e0f46e2ffc882b901000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000400000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000090fffffffffffffffffffffffffffffffd8381e001837a12008306697a845b83bd6096d583010b068650617269747986312e32372e30826c698416e0ef58b841117e2088e2835bf2afcd5d48f42b3bf2a1f33435f21f089ead2a6bae7d01c1486e645b460bb3c726a827ff1eb50e0579f3410563bae090fc256cf1d8d594b82100",
"totalDifficulty": "2845866505151538604560067685603735513869853136",
"header": "f90247a01865856fb6e4118598117560df31734c74cf725c8edae4db941055ac0afeb207a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479400e6d2b931f55a3f1701c7389d592a7778897879a054563efd593e9682943065880710af9187131127148575efc8bb51d80dfed41aa0a568a1653a6c7d559711be0b91a8e75db76c678dbdd286c75b88e4f0c0d31171a0dab32c5cbe9b9244a7af00afa7f6042a4ac923573e8f2f025b107abe1e3da999b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000004000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000090fffffffffffffffffffffffffffffffd8389b001837a120083046540845bbd803c9fde830200048f5061726974792d457468657265756d86312e32382e30826c698416ef600fb841387b51dae8bc8daa6cde190d3f44797690b4da1ce5fcfcd54bdbb2a6ee6d8c1f7649081ca28b5cd70067ee9f61e27d8184db83705102d5e1a269f2b631b4d5db01",
"totalDifficulty": "3020091077015059097853315484608800838133866777",
"CHTs": [
"0xdb9557458495268ddd69409fc1f66631ed5ff9bf6c479be6eabe5d83a460acac",
"0xd413800c22172be6e0b7a36348c90098955991f119ddad32c5b928e8db4deb02",
@ -4220,7 +4220,257 @@
"0x3ef50c81169af169c100f58f3afcb8e2f926d957b2adbaca8787be5d4e8d7233",
"0x8783eaeb56ca2d7fec84e0e272b77271fdfd6c14452a2e1dd83de770c5d99a1a",
"0x861024460895378ba100c5d0c05e62bb6cac8b21ae529ab5cab39eb6c6cabd90",
"0x1c741ed9eda60e5ac585e2f48f06fb988367c2c40a0d8111bb04b260fe44ec6b"
"0x1c741ed9eda60e5ac585e2f48f06fb988367c2c40a0d8111bb04b260fe44ec6b",
"0x6051d77e0596a911bce132c4bc12be2ae5cf29d113dd52a41b3bc166861149ce",
"0x92c049df5ddb238644015d4e039e169614ed1d926de070952f2407912906cb4b",
"0xa897567fc1ee9437f2876deb3de2b11b8fc00aa07340564031573f0351ec556d",
"0x3e54a8e15218db168960d28369003cdb1a76f8db19384e9e2696ae66a6693d6e",
"0xc5db7ade97cf28f8b61f2c63a0773201ba64f37dadc19c03943b6772aa7a1a50",
"0xda784d1bf64b7efd06558b90cd2436f3e61dc0f7a8370ff92516ed062f461091",
"0xa1d10b0a36ec5169d2df740878d051bf4d38ebc5dc04ae5558daaabc2bfa1471",
"0xcc89a8be2ff74a7bb9e967cfea3cac067aa84cc455a2fdd5449577b52a2b4ff3",
"0xbd23a3e6d3198d81d798c2851c36b954fa6f359bc8fc6e04a0b757e3d0ba053a",
"0x74640f825b9d9f95be69763845aaa0269d3a6ed5aaec88bfd9b5c4139ba7ef41",
"0xc01a29e41af3cc0d0a13ea83f131f3e4828ec3e83dd2fdf9739c139938dfc2b3",
"0x832509e705972acc7efe91475e8d76ac00a12750e194847093825e6c4db9e83b",
"0x63139d1224766ada1318613b9ec5894308efa2473e809d9e37c8305c6965f2cc",
"0x76547e54dc59473093c3fcca1166307cc7d0f4f0e8a35d850507bec216b76476",
"0x3a6a14785272391982cfa690762f5b2aeccc1dc0bb13eab6b9fcfd056f40703a",
"0x603e32b52795c04416d800b6a936343aaaa09898fa97cadc2b157eeaaf3bd6f7",
"0xf241102a3d3f3a9fdc5a1a586b16fdce4280c6c6da04290541eb3cb9c28c7325",
"0x6db6de041bcc7c00104a21bbd487a1e1ddd5e4953f7a503aa992d68a8a7bbc43",
"0x8377d795c55eac07c0acca674e775ed7d8eea35867990c8a776f40965c9ddc68",
"0x48d62d562279641043e405f4d7fbd76050d773103871c5de2c8acc25992db502",
"0xa9ef42d314e15c419537e022753ab46d41318f1fa8784e4363494f395eb6d236",
"0x99572f567eb602a1d9839bd23b41562bb3782eccf9a8893e54b002e685ab378c",
"0xd8cf2fa2291efed46c1a36e1b8837be62e86caacc380aa6397792ae8baf8f3a1",
"0xed2e800df1acb7bba5ee6251592c397a604debd7b0bfc28c8b0002dc40faa8bf",
"0x9ccece195d9e67e318f6d2952bca9486d09f4207c6d8be266cc0eebe41290920",
"0xb20580a5c96c25bb59e1bae6ced3ea5cb69d903f64e648bcb38b799141b3cd5b",
"0x1488647e697452306d2744ca6c709007cf75e2e37da3c7c05006211ba0720824",
"0x009c3dfc5494962c77900fb8da67d7bf2a2f4b855c521b9d50c4aafb1e0735bb",
"0x482428835dfff3ee1da335b36ba3aa1969fa35e89150e5b3c1991f28272d14f5",
"0x6a972044f2076e98833b243c9ed18162d96b46823170ef7c20b1a02d8bbd48c5",
"0x676242effe0fae84110c4933beecfe5ff549b439e54ff5a588add229329e5365",
"0x2441bce77589ebf8019fa8ae870a8529479c6eaa0fed7e0fbd3cc7439dbd4a09",
"0x0b20c25d2c6897c1a8dc9ea1364d3c72d33c97b4d70b9176c3f0a1e3b6ce08a7",
"0x685aa4e279118f8326a90c78e9896e40d9baa62144e2425887dcc704106979c3",
"0xabcab60973f6bc9ec3b596452e7434c4dc89c55c8eea925fc0092d1103c6f86b",
"0xcbf44f106f3f2c0050906b5e344ad22f0e0034067d35402d447311d254516dd0",
"0xcaa67796a8ac69283d7b6304181a988992130ad8441d47b4fdaf236686dc1caa",
"0xad06e6db230bd0bfaa0df59d1ae517ced29d5f11b34f76ef9bb6a73407128b59",
"0x93ef56a4951e4e5c19230918b1219c1f07e9356363503c1410e71486ed338f87",
"0xc6fef02b5bdd4909906c40cf5b999fe9e08e4c0d8bfe59d3c9aa99011136f780",
"0xfed633749700ffdeb0921a537a215ae31c25b85e4f80727376e50c247b4c5a38",
"0xc39d8cc15f4331fb7db2c24ee1163bd164e81ad2ebc43271f841fb25d03835c6",
"0xb13962dcb364ee49e2d0a34dd1a555fa8df363041504ef1e987ce78646d64146",
"0x97e0d3047e2151d53cbd1358da627453558362c6a830910b33f241848b20cffc",
"0x587ea98cbd1da50c0af1986f6ee5e676658c06442e893304708db831fec8e804",
"0x0a1d21212d9bd85a1a39e046c897d1dafb496bfd80762beda2fd3eb1cdc72eb9",
"0x46aad83612f04e7a51fd642de742f713601992e58de4daf24148a3e6f3318aa2",
"0xa65a8a9ed4fb28fcab6ee3af5df4647083c2e735fc652568759fe0426e9a294e",
"0xacd7ed5525cad187f053ba98487cc4abf24f76c8c0e97e71a696d553a3a41b7f",
"0xdcbdcfbaee764bb404bfa5261b5037b9c7ce567a3c1aa9f7280071990320da18",
"0xf195aae79a232b2170a98602efaa2efbdebb3c40d2438e63bf0954e4dc779cb0",
"0xfbb2675a62e2e67baf85e56fcd4cdf2bf89ff7905952155d3cfd4e625fb674d9",
"0x5b955473a35f6b0d24fa8be8009734ecee62f6c4bcf0cafc2335f07c51752fb1",
"0x66f37b268338f4ba1e21eef6884aef245bc36935be1f5eb14ee1d23618f00f5b",
"0xaab809ee86773263043201b83bd445d98a634d8a6da4c389b2336f68381dd481",
"0x509fc38118491458e45c7e8ab1d60c687f50d85fc1c0bf104b531a3b352198ea",
"0x20d1e4f38e83b27b77d55281af40e9f96be098fdbb90730170638c88ab7e435a",
"0xb33711864d62709a98f81d9c5f0a301bd5808d0e8ecef1063c97347af754c8c2",
"0xd69fd6c0fea478bb380b948f5b054f91831cf26d304991d40ebdf0b00a97503c",
"0x87157d452bf57e617ac1dd2372438b0777b83f6087d8223008d823652c634882",
"0x9c54b0172ae0223e6b23f7e000cb6887144e615efb02c74596002dc26d43eb5c",
"0x5b0f87baa8e40f0a2bbc1a76afbe0b21b5e8aae1443f0d38c3ac55c5f942db42",
"0xeb68d93e19860fb9fb76847080edc345972e29ab1ffd417ae5727d3cec79c0eb",
"0xd27026033bba2557c79c4babaf669a399fbc72a2a5cc06c707e24eaacee83bce",
"0x420d887bd82cccac29711c52f4d362b6a7d854e694f8d597d208d0a094fbad8e",
"0x02ff085c6c3c47879a91f511ea4c54a214af8160e07dce8e82a6be9e8299e237",
"0x1f0384e0afaf47ba59aff9f224905950768674c48de0fb0312749b16edb0a347",
"0x55cefaac814e132ff335882a366ea6173bc21fa713e93d8ad92260c84cfd2d85",
"0x58a8dd6e036a05a937a7053be916c0e7f719f2a1905186e7586a9d2dafd5a1a4",
"0x8714d03549461e32a467cefdad60a96788c97172db05c18eb9debf6e6a4d39e8",
"0xd141656c1f57c12feed31dbff3817e1d2af4e1b5cf6aa75d1bb29ea2c0a3ae69",
"0x5ec365177e19fca3c1063e65a9342008aff04ba9d03d53837b598b143504b97a",
"0xc620e23ae73d423bf2628a3de70b1a1f915d80173e0c8d1443a44b91400c5a8a",
"0xc72c2356ed53eae5a4a56bc248d9d2f4e9154f1404780b84781f357cbc7ad2d2",
"0xe60bfe30e5a1a9457ccca65810675e129948b474f391ce64d270200be7ea6beb",
"0xf679887baad8f8e497d60b015156f194b94fc30c6cb1f83fbc4575e99b95a8d5",
"0x654463146799fcfa18a74ffe4f2423fa04c8747c16b789dd24da26d0338d381c",
"0xe8b5406278d9e4622d088976af8b5e6b14cc146a9530c862a42fa5566a247355",
"0x8ecb4735132f769663781f96fb531115190e68390c54e33b250db874e90aebaa",
"0xef13bf38c2ba993c9dea5777e5db348339273d0e6dd1f41867d3b258f24ac4d4",
"0xbbbbeedf7276a857c513f4ebce88e3b531c99cf206eacd1c6c29d3cabab45df4",
"0x89cd50cde2de3ef40de7502241b78e664de53dd4a5e2ed85db62c55be0a4d8a4",
"0x0da2cae061e7dff539c7e39b0b9f63af3217f1a51bc597db957b6a3972cf7186",
"0x57aa87a6daab3c65519de7c1c1360ab33b830d46f169d4e0d3c38e7dadef289b",
"0x85fb1241c4110b4f3a6c197450af8ac47bb24d531219f6cefcc079717b208c84",
"0x52194cfba6bd7d5eb8b438054fbaf5fef387cdb8b1a7ebafe44cdcf4da47b1dd",
"0x7d24eb47a1310f7f4244e825847f634fd4a4224f695a3609c5250dc6052de6d4",
"0x38edeacb93b10653624f77dc05063499daa770b74d6b63ebe656be5a3630b7b8",
"0x4e050f7b9d73c1aea3ce60c8eae8e46b55b6d4c1cd1eae22faf982895871dcd1",
"0xf22b284ed4d97b7d3553600388748721a328052daaf92a58ed5403fd4020a496",
"0xc5fcf858d9a9748045fa0ca1271ba5af780a788c51d693815e0490671be3885b",
"0x2342efdb88226e68173ef84060a0d4dc6c8aa9c9431883beef4a5588f3157fae",
"0xe1599bf452eaacb8dcd51ff835a9ef5761dbce83cfc719813d6a10772ca5fdb3",
"0xb754797393b3216778ea6389361ca5951f365ae4e7ed99ed4cd4c9c76ff442d3",
"0x3fb5f9f3754764155296c6ff4c469109512264c603ece7c78c1231942bb8ac35",
"0xbb347d23c7d703cd2801e2763f1a6c375b5cb2a666ba137c4d6442c3f94688dc",
"0xed3806645b55fd7027dfb7f5f796933049ae558d26ca695a01e1b11333f5e453",
"0xeadb7740432ede4f90c0bc490c15fb377b68de0fc1ee3a56e87e21e7771211fe",
"0xa8c0e907e0b544e7fc3116d47e4cdfc8e8688f5cc4a67cdf600f74be6b79775a",
"0xc6f6b94f2fb4c56066e3c722123b8e85f80ce8baa0427b62c5a2ff937702c481",
"0xfff0b94553a7daaee58a7e15daf9845d1a3ad4917d81d4f23dad27d0262b48ec",
"0xb9084676613e1a063c2b491bef1b984acfbd2dce60a8ed970688239524e31962",
"0x196af717eab2cf09b47db13605ca4864cb0c4189d40c9b618d8a7d3f92831d78",
"0x4fac369653dcfe74d86b7422354d68f7580b1ae0ab359a8b8f8be8582590ea7a",
"0x035ff04f84478354706945480266321d31790f5445028f3e964801fd9a16c78c",
"0x63df70a24370a408bffabbe1c7a4c9b9e40be1cb326ab10d63fe54bb9de50d34",
"0x37b5c558d31128595425ca68deddf5ae7539abc6da838837eb1e0457e092d9ea",
"0x41a9ce82ab27afbc84669368c2e75a15e6386b77034ec316795a896ef9de577d",
"0x08bc6cc18842df4130280823f7676f418f4797d3ddfc544e54267e6456cfac68",
"0xeabc09ffceeb35cc4ec18518d4920bea2f43bf746f23b5524fa405bd874e9d34",
"0x40336744dcfe6f312e17eea83f53538f9999864c41bec43576cfcbef68d12e7d",
"0x3e780dc9c8f2b708527f1eebca75d18507e00e226a00e1b1ddd0b715aa8dd561",
"0xfd6a3c50c4a4d6e1a6fe27fa96f6aa2654573cbb9b839ce8e09a75993e2bf8e5",
"0x166c03d381d6ab94666099024adc95de0ecc9818e5ceb49965767682ca0c73fe",
"0x9805810b802a51a3ae18ce44f6b2c68abfccef2119df2430e4693e291059e222",
"0x353ecd1a0922e819ffdcd634385ebbdb674d247c4fe75e2d5437b659c98424a4",
"0xe75fb8682b706ed6596699d6151db4dcb19f6e71a3b6e34aabc3508c919f5c17",
"0x6e9bab64b10a2341f49e81d862ef3322d3117842e3f1aabc8b774c68484a2a31",
"0x82b5e79ee8d72c3613458c975530bcbba359734a4e9f07015686dfc521230329",
"0x86d48d57ccbe1f1986a4043748b1a0d8d76fd56bc74e7c48c6fd742affa0ee11",
"0x46ee65b9c2fa3e69aa1cd6ba5aaafa7f7aef59224098b60e22994996c927c9c4",
"0xb6983761b177e21899799410dc018f1acd3d417fe35943fbe57207f9f799a100",
"0x594057a8386db6e159d43d136c464c5e3980eae75a73900f7a84ba94803fc6c4",
"0x53c78073c4a4c44d17db85be06f38ab47ecbb7f36ffa87b9db707fd2bc87f391",
"0x4a976673044732e3e8a0987fc8f3c36375e3c4fb3722fcde5259af492ec458c7",
"0x1e2fc8db341a4d9e123ae4ff4f4d8096d8afef47c5d2915c665922bd1de3b00c",
"0x565cd8eb410c6e0b4d67b54d37ff42f6189095965896b0f81566ca502bea34e3",
"0x32d030e4ff6b2f5a560cb7525b5e66ab1f34a1e06531f9b81c48b8a257bd5637",
"0x25a91d756023bb9ae538034bd39b6e698d05fb1393d1328c4fc7e5c14209cce1",
"0x8036f74c4cbaff3bd98820ddd84bc093c95e88d357b341154a3189715225d068",
"0x8bc6bc61f7a57a145b8d728f583e027c8630f0c07e003b189f390ffd11d6f150",
"0xfbeb53fa167d067c9b0a2c0710f7f5931484f7dd90b9456c52c578a15f402d9b",
"0x8d355b208a16b8aa3f7bc5d8864dc7d6a1c4917a97c523274b86e82998d60b63",
"0xc94e45da800d7b56456d55a9aa36ddf9df45e9cfeeacb1116b8c51a0cea34ebd",
"0x81761ec04a8d219aedb2f58aee529e876043b0a476e771957bc03fef9f0780de",
"0x29264094c720151f7448cae053a403aa86fc20649bcf383517e214d1677e893e",
"0x9ac97c7eef9b69dcd73ec7144a0cddfbf0973791beed405202fb4c2d932ec59e",
"0x89611f8e2f9e2e1629f83ec14aaec1656876718c05088e5087887c87b8414c39",
"0x67244fcdba97905472631378fa3a228b649880c2efdd57e5a6c95e9b70ad8456",
"0x0d554cfc4df02560c3e76159d1964c69c39f5df9489bba5516f28a32a4be202e",
"0xce9274a36a0f25a13edef679a5b286bf91a9dc5274354bb6f1ce0ac52557e650",
"0x6017e68689d9f6dca78f42b93a224b445c18b70288a6e4c0d6cc295627dbb1b9",
"0x76791c90f887355878d0a4d8c84ec3990a3159933ecc8d868d196b363153bd5f",
"0xacb6a6c9ec937b3d5cedba26ab6d581fc41cf9a58b0867232e2c8c73d9978cc3",
"0x89f17989ef556a0562c2aa5a2a1d71e5132b89d656bead1ef88ad31073b80cd1",
"0x06efcf8dbadaf28ee719a5b9c017a093fde84a7f4b9966fe3052c0b2fe410ea6",
"0xce16909616f1d97e5853818938b4798030259ddd41e3468f35b940ca901d6817",
"0xd3ff9e9ad14a605a94bdf05dd2639b6fbda28ccf7b2b228f064b0de52410df5b",
"0xb3e8ca9ee88d4c3ce347d82e8f22793ba22b7adc350fd694b1b00b0764c584f9",
"0xe690268a4ec089aced00f9654aa95acb7a8d7270d9428205b103c30a08d142eb",
"0xd685e1460799c51f14273361e31b9739e5212fa538fb8dfbb8e81e8b1d329bbe",
"0x664c293680fb7c5a89ff3c31e81ec8d0c30a6274ef44e4e76bdb9bba83f3c0b3",
"0x44027fd23526685d920d37b032f912159e308286eaac018244006690b4191d4e",
"0x7ea934c3d75a9ecb6a2055dcd5feaf2d4c851eaf360a648d5d87ef40fba2fbd0",
"0xfd97fc801315e5be630ccb3dc983c409a58fc1fc307adc1e4a48fc60c89ea40f",
"0x15aa0c3c732a2c6684d521729dfeb93f62e22e155d85d20e5488e2c86b043142",
"0xba235420ac54100da28cd6f30ff64b8594e73c42f45ca8494fb3d3c4d66651a9",
"0x9948e8489cd94bed4b8e90a8bd35e01ffe38e7c077f587c6c1949caa99cc98e0",
"0xcf66ccdfa85655d7d4c94cffd41f499afdfa2bbddcdaac547223e6ac4d1f9cf1",
"0x7e5382881f710530720b420a3f3ac08211565ecc8fead8ec649cea11f9385c3d",
"0x104576fbb1760c16ce85c3e5757832d53bda83d618500ef677a6a192ff14a5fb",
"0x9e4689bb1ee34635e1106e38ca41833d2dbc1cfacb7635ede5761048a8637c7c",
"0xc8c7f7ac271015da443320f4af650fc71ea0914f4c41252a5b7ec76f329d5268",
"0x46a93ae992001a54119c8d27788e3ef8927dee0a9949b22ece0196a90932c1da",
"0xa69467f9944f1a5e3a46718a99d3cb14930cab6d971baa37bb774cc757e55c2b",
"0x33f7272fdbfb91428a1344df5867300e256fc3cc2e439c777c3feae1cb27b781",
"0x0aaa367f4c7f399edc64ac1754f47aa5c28b0fa208238276de6bd9e424021ce3",
"0xf5f363c3bfa4a23bf221951f4b53a77b27613938babe40f0832d05fdfd252233",
"0xec315af99bdfdcb3cab1f1dcaa5b42ef53f4e3fcf4d921578892a5896fa20e9c",
"0xb580a8e51e875446d7096a20801dded1f7e5b5fac9f47e9361dfc9dd80214013",
"0xb877df38d8f4cebdfb89f26868bdb97ef945da187b44e1cbeafc1d4b7059d713",
"0x78613b9d2d6b639a54ecf1d50a56af80560b436fa632ae636cf354d4a6dd4af8",
"0x80a9d0a5e43558f1d24256baa6940c0074fa84d4b8e7e236054943f9ad5fbe2b",
"0x60f79f699ba1a740c9784f2a8f1b652d4e695ad2d230b110472b95914fd35c8d",
"0xae20de288eb7362a36a1ff236faaed6ddaacf58783d098118bc9fe66b8780651",
"0xcd08003531d6094cabdbe4d971a01b41552784c246bd2a2f749ee9947d1394d6",
"0x676720accf739c380f64748390c1acd2f88d454539866f7326a517c9b629b545",
"0x086b71ac681c0ea369c16b22ca49753b2083ec25b46ba659206433eb060d98c3",
"0x78910ab7d67e67da722ad53b669d8c3a312de3cf362c6254c09581088e920acb",
"0x5bc6e98a830c114cb432091679ac5b3efd25c362d6f99585ce3a027dff95e524",
"0x8d0daff5a97327b615d1535fea44fa33610fd645d93035e1e5e2bb49d4dcef24",
"0xbb46662b884bc6676d98ebf3f2a35ff9190339b72d68520fe40100b4eafaa2a2",
"0x9aa8faaf935c95a60ffae0487844860084a963792ae0bb90a831f825339810ac",
"0xfd77b5d6b6b87bfb0ddcad7b0ed3992e5fe897b16db06b118230b2d292e317e9",
"0xc465a3384c694bc50cbe97ce9f3bc364884651a97a491f7f64e65dc319d1c9f0",
"0xc4634431867d7a302be79e83fb50d01df7f3b950aeede21fcb59b883399b06e4",
"0xfd524c29525cb97a89026ff68048ca6e2a9f522791eadd74447a6c278151d7df",
"0xc7df516c295a58cf4cd5614eee3d2f773a412dcd4926eadad7e935ecae6d8907",
"0xfb915abde0108d6e84354e21a513fa564f5201277e060bb916a9153537fba1f7",
"0x1d3c6a780f1b259e096f4a141ab83cb6bd035407421e2468e743daec211e536f",
"0xb2f47534f060c70f61a7c16f920d0e11b957bb3ef912ed9292f35b8ceda2acea",
"0x03e0ebe6e9992f6921362d463b68f91518d91079c001c6bea7b3452879fdc29c",
"0xd9a7de173a1617ad813a554a56d7c7d2f010ac78d7782e524b35b5c676cb72dc",
"0x90d05d99167e53d34a02c5b66ed6920190370656905465f20efe56499aa0ba6b",
"0x17702606dc895aae35aef034fddf8f7235efcc66e5c9d252347063209c2177b0",
"0x3c416492193d81fc03b5c1964989a314e5ee6d689c638c996f6761b4d7acd6be",
"0x3c6c1162ea9b277f831989ea26e14bb23ce4d72bb9c865e354992559266ceb16",
"0x96de93f849613bb2ffc117bf111d4798b9252649f94f21187da324a3fe363833",
"0x91e50fc6e564cb9d6b7aab3a6e93f6b32944d5a781196a9a8b12ac7f6f527565",
"0xdbefa2bb2ee620d75295d0f3103e06b428f955dba1a792421e435051c46f7933",
"0x78f29df98ef7dce9fe7b4414da90fb4df5d99231ab0a3b7a3e70659986580fe4",
"0x56cf56899c2388d55eb1496ccbe62041d14cf655c9dbc53984d86c22ed281acd",
"0x099f52c675171088550a9e93e1ab17f003190fa3388d956724d422e5925c4813",
"0x9913e4ad8405b8a60fa512fb616c544c6cdc415cb1023aad0669d58cc3810161",
"0xbf5d51369b2510bb57f8fc8e9342890e8bb37049079dc79ab97afc0bcbf3cbf2",
"0x3a012d45d250c818b641fb18b71b622f5bdf0b7a541e0d8de54f61e516ee3ce7",
"0x0233833414d2cff3da0326f7baccf1bd522db5fee290ab4fc0a976934a20358e",
"0x38a0978c955f20cdc32e2013a5373efbfc50924e45e9c4c756291a903f4162b4",
"0x4107f33a14052662a0469ddd646ab6659006df131c4b0f6b0e6cfd331b46fea2",
"0x8074fb5054c755c912bc68b1dc22ae40ba13c06912c8af1c12652eb4d84c6503",
"0xf6d151b8f9c26c3a31366d967dd7338e80e8107b9b81da0a98faf16df9cbc91a",
"0xcebb0256d0a8a4b22d2341ec7c48292c3226caf4aeaa2003ee36dde25cff833b",
"0x5fa9ac499a2642b0cb7ca365062c02588f9c555bcdf584f533ee8e8544b9928d",
"0x800c7f04db30247318b8d4c11d575dca66bf615674fbeb9e8c20f387d907c8e2",
"0xb0a43de06c9d48afefd5411d759e3c6293cbea4a7c6d862b119182ea02af81b7",
"0xb6e7ca0075d28959cf87d716fea885e9e3a0062fc7da1b6e06089c808a632b8a",
"0x734c1b19f0b5972b5215f675cf60c68c12cf6d6bda7b5a95ee9a781482e68365",
"0x1995b08fffb20dedbef592ac23a81d87129ceb396e065265dd4a6cb876beaf09",
"0x051082047a6b579684b5444ce5b75bc630277ec06b0087779387b9d7fcd18fec",
"0x4aabfe145c368e6878e2ccbdfbecf2f1db5c9078650696bb3a584c14fe17177f",
"0x42811ab68b304ce30fe896c52b53d861abc3c8b5e4e740fa97b1695db9a6691f",
"0xd90cdb12ad64f86b2aa7afb781c00301f50206b05f1543b111c2b971ed209c94",
"0x385435507c2ef42b5f1760b97497e8a02a4b5ec4926c3cce8569fc0f4be59ce8",
"0x2d7a4908350c9cf022920cc51e0cad9c3c05d1d14a92d72310b52f984c857101",
"0xceea9c58106f4f806a256f64dc04e1c4b53e6cc5eb048f3df7a14f8de3506e96",
"0x7032f864eb3eae8d198c3f8edd9cc2dfe88b9971cd01b33318dcba004f9b044b",
"0x71bfeb4c183b20fba60e225524c809b0864fa14f5c0137accc36649ed0712e5c",
"0xef0ec5a2761c46827110c20e14fc4aecadc2407541ea046de09a58cda3b2e839",
"0x5e6debf328055c9413fc3eeca28583f917b361a5b5bda9af4306929931a4116a",
"0x1aab81df07eab969189333e5b2930fcc1b88a525ec5bc6af6626fdcb202b8f34",
"0xbdbf97e1558711d4872821b9400e03a811c61096bb838d3126b1c2154f8fb776",
"0x7d8aaee482933ffaa97777af3e4bf69ce7d99afb24e546d2e365d445d3d0190d",
"0x9da421621b14164582b2b877090c9a956f3a7c917031bf743a9ce457b6292369",
"0x050d717f0433a72b17a0e9a1340f26aed5bf17f90c08a5b73e675860ac9c24de",
"0x80551d3ff835aaf987b9ec056a73a3890985ef551431daa9d4aca10c81cac7fd",
"0x625a5b5aed2660d32d2fd8c4d1bfc248365a5cddaf9b5695e3f131629739ec60",
"0x7d86bc2dc5914d16b3d0d882a5db0230b4b688cbd8c81098d2efc5080e589646",
"0xfe42cd832cdffe56426031ba7d837c56d86be72b89ca9f5474bd08db80cfe903",
"0x0ca30e1fd3bf3e16a0e295ecbb442757248b2ad47baf88fc37d6c55901e709f6",
"0x2a83ed111b99844e17fb7aa69854525958255ffea04e0bfdc365264e72b349db",
"0x709779de19590b69864f5b9228b3a1c334724e20be006ef5ae38f8c05eb6f37e",
"0xf09c664d0e2e88ad5418d14481fefdc9e9c46158bc5439ffe0bf6d6d5ecb2eda",
"0xf350785dd3617ef73b0a5bf439ce5c49adca0c041b6b5047a664e5e33967ddf7",
"0x8fcf87571154dc4eb0a73c6ee31cc0db5f4e064cf23a255a408b2f2c7cc9c0e9",
"0x75801fc8867ce7c75b3148c6c022d7702143b93d93c1fc2349e3e969d0179cae",
"0xf14c18bf68ae881d3fb07f631340b00557a83860d0ba0efbfe55fe199176aff6",
"0xbe48c727fb6a32242229eaa09146c76522dcf6bed6d1c6fc1bebf86b5e4ccdb4",
"0x8487b971e383272df82cd812a0bf3a2026b85bc3897b4ce9ce48afa00849fe00",
"0x60d18b465172f59c0d71594b5273a90cb41db24a5d4c9fc37020f9d8c467a4a2",
"0xab4e36d9f17c748c87d89c23b667e3f4e3265e77b62dbd9c92659026f8a53d12"
]
},
"accounts": {

View File

@ -15,9 +15,14 @@
},
"772000": {
"safeContract": "0x83451c8bc04d4ee9745ccc58edfab88037bc48cc"
},
"5329160": {
"safeContract": "0xa105Db0e6671C7B5f4f350ff1Af6460E6C696e71"
}
}
}
},
"blockRewardContractAddress": "0x4d0153D434384128D17243409e02fca1B3EE21D6",
"blockRewardContractTransition": 5761140
}
}
},

View File

@ -62,8 +62,8 @@
"gasLimit": "0x1000000"
},
"hardcodedSync":{
"header": "f9020fa0a415a8dcd55fe9c93372da415ff6897036e48cd3c1a5ff8ffe119eea1096ecd6a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479443d58f2096e015db88e44346e73d8c59cb1753bda0100f05d66d36782b7c061c724d8d07619cc61053eda41badc8d2cb9292898ebaa00a60317b490365f40f0528e1f559b0f49facb6638c82a9490d368e963647c704a0118b536c3bdabf90273d527dfc26914c7878176fff16cee8fbb150e00ffcdd29b9010000000000000000040000002040000000000000000000000000000000000000000040020000000000010800000000000010000000000200000800000000600400000000080100c000004002080000000045000000008000080000000020000200404010010200010004000000000008020000008000000000000000108010440000800080000400010000080010820008000410800000100000000000000000000240244000000010000000000010010000000000002000000000000000000004000000020000001000002000000000000000013000000100000800008000200000104000000000000080000080200402010000000000000000001020000008008501602a8414833bc8018347b7a983476d40845b838083904d696e656420627920416e74506f6f6ca0f540bc9cfa258b97576bfb9a79518b2c07ed73a98bc6baa61cf7af4b40ad5b6988965658a406315a8a",
"totalDifficulty": "9811143388018700",
"header": "f90217a00f0e017311206b97b47403eba05a16ada760a691a36f844ab8bc9082a4efedc9a067baeee20ae4f4216ab4b0c41198efd376aca23e44b1d6575c5949955547b72a946a9ecfa04e99726ec105517ac7ae1aba550bea6ca0e64d4fe9bee34d98e127f7f94f17535582d5bc6eeb6219f323b046b9a98c72b5a02d33ce5daab0436707c6d958dcf0bcd311ec7a72d7b33c20784178d5d95bc6e9a0a5b9cd4802fafaa9381ec0aa745cdb7ac953675e9df89474e5fe14fee134cf87b90100000008018000100000000000800000010000000050004000800000800014200010000001000000000001009001000000000000000000000000000000006004020600000000200001000108088002260441000020204000000000000000000280000000000200010001000000041008002000000004004c000000001000000000008000000000000800000400000201000000044001145000000000000001000a0200c04000a00010080100000020000000400002040000000000040000000040200001020000401000000800080080000400010000000200000008020020200000101000000000100400000000004400010020000200000000000001000000008453461c8683402001837a1200832c5216845bbd359199d88301080f846765746888676f312e31302e31856c696e7578a0c1da176f6642888b4369e14349ca7dc125ef7d4f5f7abad61bd7f6b95bfd46bf887d1a171a9f55dd67",
"totalDifficulty": "12027449412394243",
"CHTs": [
"0x614648fc0a459451850bdfe353a932b5ff824e1b568478394f78b3ed5427e37a",
"0x1eae561c582dbb7f4e041998e084e165d0332c915d3a6da367638a8d24f3fafc",
@ -1977,7 +1977,146 @@
"0xb652952de1bf9e1174e5f6a37b069b437792672a37a9e0159c4f36b6e64306b4",
"0xb72dd6cb5df1b00dbbd84e097e2da79af2ce60559697ab4c93b0a8b85b2ee406",
"0xb96fd4a94ac30c10f757691f7f06f25a4900fe424f4eb7ccf322e2f95249b914",
"0x99fd442599036f161ccef1ae8088c5ef694c1819f5b76d9d2fa8f979935f69f8"
"0x99fd442599036f161ccef1ae8088c5ef694c1819f5b76d9d2fa8f979935f69f8",
"0x3e53574f6ae31a45ef928f9c37bea6c61e6d728a5ade9851567d3167f5ca3314",
"0xd7e3d08c5b71a7ad8338e8b51ec54cb11ad4d643d129a371af07376f8c47c1d4",
"0x1033c8aed4ec46377f75cc9a6b3297e1da0a7d1e74df20bae9fdf6d037afdc28",
"0x924d621544f3301f9e212fbb95872fce9eb4a4172a11693674de733bfc2b0018",
"0x7f61884149ea4def1444a70c022da1c23f31ecc51bb175905b492236a57c7fde",
"0x40c50785bc0665ab4eb3cec95405e17510c571570a5859ead804530dbcbd1387",
"0xf806491cf778f4796c0f73428e6eaf237da8488af99e9b61d72c56fa03e7051c",
"0x7a9670842dcb12c66f11e357a84849cee227ea5a7351e7c6c9370e9ef2560129",
"0x1c974da4e1073157c10deac8b256c8ced77a030e0500b2b8a90b6ca1d32ab4fa",
"0x97ebcc81ba9c1e04865ee4617daa967dec39f65501be21fbbe929db869d57dd8",
"0xa36e4506065d8b9c662697b18ffe50ed2f6ccfe6d07a065bdad048778cc53668",
"0xb9d5566eb0d40bbb03114d333d1d1dc85b0e780ec63229f3b93b2c84af5f9509",
"0xcd16693573724880c3c83834d516be65c35a861b76b43878e28aa7fcbc961361",
"0x4f60ecd7811acc087fc4557fdfaa1a0b522fe30da1cbae5e7740eec3cff04c00",
"0x9e58573b152bf5008e0ea3fc0d64573211916521a62fb08ba0f1b44c5da12e7d",
"0x2c6693cfd7e5bf9a3d8cef9e186b3da25d07af983564ced6238f9191b020f105",
"0x8cc6149caeafef85ec7b2456f33530459c52b30a5365a2a0022b1c308357f7b4",
"0x6f66863bd9909f687523128569cd0894c4cf41e2eddd5cd9c20d30c446b1711b",
"0x402317752053e7b6d7e2d5512d6397112d80ace0873f5f9d32c023a402ec03b3",
"0x2fcd50a79495057908bd34875e3531e6298488f0d06d043fb6fb0b140895d379",
"0x533ba9669dcee2c6e35713c7eca3bca168a326a36b0e39fcde76cbd35ab3d99d",
"0xdc2e86503e8066bc5fac91fe63544e33568a3c744967b9360458101c3d9df096",
"0xf994b38ba312d8bfb00d428b13a088738d93965b525eae81b45b9be344f99fd2",
"0x0721f3f772958d6a58dba638453b8d004e0c76dc8b4cf6d595b712edddcf002f",
"0x3c650c2c7ebbe7879a15882c3157552e8ae1adebea8f0c65a2dda272cc4ed838",
"0x649fe38e87546703245a7adf5925e8c7a07942750e14d39553a56ca3fcbd8c65",
"0xad204bf42d2a444faa864df8e9d023483a6b6daaa8001e00bb5373a45ed064a3",
"0x2c5cdc73d8ddef2e5c0d47358ac180043e7e246e590a7e8ad2b0a3f9b4e9375d",
"0xf38f6c364bbbbe626e849ca9bb9324c54cf0ba8dfc0b2741a3ff87ce7734adbc",
"0x317efc1cea774849d6219d31c8464a15956da4f3810bf15d4353443f79d98e75",
"0xb6796dccdf4d3cab16b5ec9567237cb988ee94131f3262c2a581180b775e76de",
"0x1fde3fdf2303d080d400c43345a424f50f6551a6a06ad50c6e277d49e8034df3",
"0x4d7bc44a3b56f5e69fd3e5e8c0cd8f5f839a775c4ee381b4b1d0a36656cf91cc",
"0x6051b60fdced0c51aa6a1cab2418c8f21c5d174109d514a4c6de758b2056611b",
"0x3c2f7be830078af3c2c6d1557b3da74d1d5bbfd8094f98886a959aa71ce70b15",
"0x8f296b90a0ece0a3dbec19a801072497c5840f9c0491062cd402db00c2b69f2a",
"0x6c14c4697f8291dbdfdbfea5522798e3f8b17204f80d8370e6d379e6ee659e77",
"0x4e98f63afaa50f8a30b0d352eb5fcb5403c635cf54b41545aa8b48465d23fb1d",
"0xad3059433e981ff12cd0d7dbc11a8d92a65cb39c6e936e9c7db5934d45806492",
"0x1cbb21f28ad2d191d6850c97487e5a733306f2f6ba370723fd5ed37cf6c880a0",
"0x82a0010a1b20d383bff0e5d7ba3751bc0d9161a4817554432558c5c2825babb3",
"0x33e54e93443e87c003d582dc51d0b9981ddcaeac4df0993877739651cbf52a58",
"0x1de8bc150f4142cd45b5d0784e5952abd8de7cba9654af959498c0fd0bcac404",
"0x3ee852f48a1a930d671e53c9c8d8c3c38353ee1737c093960c3f841e6c682e94",
"0xa9c6e05ec91e2a2f2f003419063fe033e37e5353c6e233706e29c08693e35eb8",
"0x649f7328064c55c03249d527dadaedcdbb4cb0e939d94c866844192d99469e05",
"0x3a407d00efcd5fe7bb765347b1a3f231b744349269b3aeb44099f4bdd068eb9e",
"0xa1a20af2f7e61082810ce7e7afe6118bc0ad95e9641e6129027f46af28048107",
"0x0d68fc5e58cacb2d16d99a0e9e612d674754ea51cbee2c68a21f4b0aa926688c",
"0x9b3e58144c014343271c9dc90daa8d2f642954b3eda223d64bbb0ac41380e512",
"0xd3de08b676d4f06bbf4322ed4340caab76e6ab7144c97af91c2bc9c749e65b38",
"0x21d626c9c38087aac6262b64f09398be6e4cbf246100d8c2416cab57e9ac1b68",
"0x563a450e35f40279f5946641a823f596ef3ad22a45b8ec280128546aeb0faf14",
"0xadd9c7128e14e670c7d21d6dfa5c09a11dfd237e90709b087e3329d3cd89b5fd",
"0x258cc0f845d8e7438a707f590f55203c6c51302cef4cfbf788b1c7054688da14",
"0x4309676aa14fa8244e0a089c7013b89c9adf57fa952295b8ddb23fc6545c9870",
"0x5db769765dfb41aefc0f40f06f3d005b30ce1f14f04f653e0c5500f651cd61cb",
"0xbef131c9f19572b05d295d7122fd1a09fe4a8afd4e20c5a0f3cd2785b7eb9882",
"0x3f235228ea537332a041ec75cc6cb5663edaa1c2ed1c1700273af73a5d49bf1c",
"0xc081811bb077c6ebe224b560eb6b81f3f813b26789cb06d96110071ffc25fcb4",
"0x912444c19a5e458b79c89969ed5336f2873267baf2fe729b6f218b74d269b797",
"0x5846fc726eb9627e9d070041b92d76191c4b32e315d33ad18121b8acd01634fd",
"0xc899f45494660034d343670856c13a32b230d047434a4d54a772132ddfe3e182",
"0x11a699c18b04e8cdcd96a43b7465f7bd81f8f64d7ebe79dcaf9201cc897f2746",
"0x8e09b134dc8a1735c060175e9688fd001974bf2e3baa5a8e88dc4c87365e0e07",
"0xa086797ebca0a1d446a9289b7eda920b926e1b595c288a9dea31ad225e6de86f",
"0x0cc04369b6036dff78a9856a5173bb2dde380359a8dbe0126e06d6e763a01c36",
"0x4b5efcac86e03d1f67774769b8bcc5d131c181cd4fa297eaa6cea5ec0cdfaa6f",
"0x47272a21a07ad5e14e3f97b237dab7e33344da4db5b2d31bc7cd0cc2d2c9f1db",
"0x9540755fd321d125b73cb6f1884c2f0b2a821d29362194f5029a5e7ba2d3ed44",
"0x229b88922fe52a78090673775f264cd665fe222002d6add2ed29b7ffd98de717",
"0x8fa2d755d5cc0efb01d9fd6f5ae1f7864404ae111d8ba17e23686ea9b6566336",
"0x33a8f2e0775fd19b1302b985bd6c29d4ab5fc63060bcf3df2c3685ab1b19ce67",
"0xf6d6bebb541ef9b84d779c62adb76774bb38a8eba3823e74e0790dc7401bebbc",
"0xa1f421108d49ed23996e55012613fc05e0f86e00f17251b1ff1e0824d35befc7",
"0x2cc572ed83dc6c604bb455ab050c550184a923f4b13815f06d10ef19dffb3c7a",
"0x28220e7d1a9583d68656f03ef4d6fa3e249c71d1b42698f87ba1fc582493e194",
"0xe8aa37b3214abb1bc167fdb6f10119a4019541f31c76b3b3f8c363bb138bd09e",
"0x825189c2c836dda454b457a03ff83d422bf78df1f368434768690fa7f51c57e0",
"0x5dad65d275e69478c81ecaec5b872660205735d9649ac020f65f5ea6ae972dda",
"0x84a1184d8f94fab280e0593479179348f9184d6fe5a2b2ea9697894c42574473",
"0xbef5a05bc7e1fb94465570144499672d95f31fa241b4c510011f6677e2bf72fb",
"0xd08235ebe6d79a8549bcd3d2414cd8afd2a3e2ca22ced226c60aacad1361ff89",
"0xbab5204ad45ec52860023e7474579e7c95397f3c4ac01db7e446e92c19dceef0",
"0x6c81acf2ff161d423a904c457166ff454ef41571d01e73d56bf9ab892790248d",
"0xaf4a603b808e3ddece42e3e123ea02defb9f8ef2546a95c5a617b6ecdb89c306",
"0xeecdbda25b04eb764e322d9a1e5eefad399c9ced8c77b1e4ecfbefcc90bb403d",
"0x9463f4677a2039ca372b61b16d5bcb7c043b26af04aea4d3f0dcdec7bd222070",
"0x27bfd92799b4cf9699d2bfcb158f6727bb986fc0dee780fc1052366ebc4e6364",
"0x63c3faa1a8fc0d531261cd241b1299d4fc13629abb4cd357eeb130505fbddf94",
"0x9a4535b07ff68862f3396b14b88fa07cff7abdd5744775aeeec6868606eb4712",
"0xae59e7c3e0a1df32f6e027da2983d3c55b4ba4d99e85329361561bd7f13ac629",
"0xcc5dc26b9be8fd8432537d967afe12fc668949e4fcf72d97a40f9214975fa57a",
"0x8f11634c83c7a43be8b98335ba617a64c6379f5f92664055c5e1620791134ddb",
"0x14ce2a69d844e6a46aa244c5aca9fb74c127f2151c7c16f4611ca030df365d8b",
"0xb06f220566a5e62570b9e9e49a8b9d5663501ba145b12260fbf9d4a18a4b19e3",
"0x6274f3cf553c45e6ba7ef644d75bf208e08a8c6325e336aefd35dda9cca3c4d2",
"0xd0d685497c2f2b923d0b9f1590a748da8c684a915a470db58c3105c83d8304e7",
"0xf37fab515f96e655f182f0b6e6aa3602f2cd74773329094772151e8c33d1f9a4",
"0xf6efd731481e8553f1d18b5735166499e787009b484b0dfbe4d35e7930f0d837",
"0xc96132b510863e553e08c54e98b5e9c0067f26e421980a6a3bfd4f07480c4396",
"0xdca9d8182c573871b6d6a184cb9819256398080bcb7fd765e6c69cd972a28d8d",
"0xd632ca6f5d45646726ecd2977ffea5c71a867890633f571b359657c0d096f840",
"0xfe3884dbca6bd3b0087466b04e6a5857ad59d7a25021e1d994d059d20005185b",
"0x7f40eb6fb94b05bb43873a98e9d4eb5f7ac90fb8913240bc0909c6be42922b30",
"0x5113a0808666815cfc52b8ed63c649d96f35c365def36ae623f536241b163c3f",
"0x8e6dbacfb5c593d7d7c2650d3d0115c3702cbb55f73011823a202e69ca33cc70",
"0x8f069ac7caa48bce09fe93f4aaef6784d8a6f7a3a09edb82c7512ec18acc3ab9",
"0xa5525e51fd789c59d3b208efffe09abca47cfd6981d36ab44084b86706c69888",
"0xcb4a7e60d5e8b9d22887ef1e8ce339cfcea0ae1fcbfa9adb766ad05d84182de7",
"0x0a14f23f9066ebdb67df31e66f6b8ab1c089025c0ba56ea56d15f73749f47cb7",
"0x0963e3eba12e41d21af7625b8dc487b637b1789a6ac05fb23062e0166942df68",
"0xcb7ec271b2f42cae0027d22b688b19b9288f2b5d9c43bc5b1ea23b35f5542828",
"0x9b97e6f4b2eeee29ecccf9584dc020c8caa3cae51c82f5b58d279eaf0c6ab4e3",
"0xad7f1963ce9993e6172c2ae90c6e1d4d3d3c52e14284fcc1b1e9a56776afb97e",
"0x52ef2ad7bc2921742dcbac9772f13d5c31be938eb1ad6aceb2fa8a163389cefa",
"0x369ead6d900e64ae0b5028df8574e59b67c61dca418c87ce6461eb4c8535fd30",
"0x7e1a18f6199f05f21f9eb5463e9ffd87637d2fd24a23047fe095895c533cb6a5",
"0xe1b8813a95e511aaec9b358d515e624fbc20e551c56328f843ae90b3c895d3a2",
"0xc2ea59f3d1e7bbe115390a4c210142fe9f9dcb1959764450f5b5292ad90e0fcf",
"0x97d235c3f18e6819c08dab4efe66d0f11f0d06f8ffc9686e3f28400e057e6f4a",
"0xea64f817770252b77b08ca2f579b440ec02e833fc88af7c9c96a8e1e07b2cb2c",
"0x185f5fd1f7001b533dc01783c83b7ab0828a4e2f188cc4e26768c515b4c421f6",
"0x0c9de9844e856a1e4340bf54dcaf9dc66b489304765b5c3c6ca20284f5a0dca6",
"0x4dd1d52da1d260d1f0f63bafc4c816b30cea8ec3434e7d4b63a0eff86997254c",
"0x0b3eb94aa246f7c8c871535ae2d3abe5c1b951e76b77510140ef52d5ea2457ee",
"0x27102708eea5d715799642f213049d8ac9abc3b12c76d147ce443dab28af96d8",
"0x81fb3c4e8dc6c658af2901b7aebf7467b9ae045dd0f58fe8d77f8770ac517fb6",
"0xf68dba4eee635d7494bae6fb9f0c44e739b3121d4bc6f6f21b495a716af3cf52",
"0xcf87b723dc473d313bf9ddfa233056036c5658777e831796f1f56647cd040c8d",
"0x49927c2100039ac496d9c16dd12f0a05c9441b8616c69c726fd2e79ae65e130c",
"0x088195c7251f6b9fa2105e77df5620211b8ca783a77f1a98de6752fc442c26c7",
"0x604de480bcb88e908b90451c4142b99b9cbb479167473befca7bea9b4ca427a3",
"0x642fdaf6bc1abbf261a9480fcf9bb48cf03fb80bdd434c6ab63401856c74fa39",
"0xe6b596393fce7a3023a316ac34a1fac18e18779ca5983791866f857f257592e1",
"0x40384a52564fae5df8c3e41827cdf584e38f3f555a54ca749b7b516619071d85",
"0xe52f7c17a4106594563ae7b724e5613e87d8442177f39a36b946b0e335be0e5b",
"0x7726202a7c255a9d7be47af6f3b44c1e379cda61237866554396fb6ec043482c",
"0x665da353f296cde80e3cbcb9c7f93b107d5676e5cd694b0bd33334d74789beb9"
]
},
"nodes": [

View File

@ -118,7 +118,7 @@ pub struct TestBlockChainClient {
}
/// Used for generating test client blocks.
#[derive(Clone)]
#[derive(Clone, Copy)]
pub enum EachBlockWith {
/// Plain block.
Nothing,
@ -242,69 +242,68 @@ impl TestBlockChainClient {
*self.error_on_logs.write() = val;
}
/// Add blocks to test client.
pub fn add_blocks(&self, count: usize, with: EachBlockWith) {
let len = self.numbers.read().len();
for n in len..(len + count) {
let mut header = BlockHeader::new();
header.set_difficulty(From::from(n));
header.set_parent_hash(self.last_hash.read().clone());
header.set_number(n as BlockNumber);
header.set_gas_limit(U256::from(1_000_000));
header.set_extra_data(self.extra_data.clone());
let uncles = match with {
EachBlockWith::Uncle | EachBlockWith::UncleAndTransaction => {
let mut uncles = RlpStream::new_list(1);
let mut uncle_header = BlockHeader::new();
uncle_header.set_difficulty(From::from(n));
uncle_header.set_parent_hash(self.last_hash.read().clone());
uncle_header.set_number(n as BlockNumber);
uncles.append(&uncle_header);
header.set_uncles_hash(keccak(uncles.as_raw()));
uncles
},
_ => RlpStream::new_list(0)
};
let txs = match with {
EachBlockWith::Transaction | EachBlockWith::UncleAndTransaction => {
let mut txs = RlpStream::new_list(1);
let keypair = Random.generate().unwrap();
// Update nonces value
self.nonces.write().insert(keypair.address(), U256::one());
let tx = Transaction {
action: Action::Create,
value: U256::from(100),
data: "3331600055".from_hex().unwrap(),
gas: U256::from(100_000),
gas_price: U256::from(200_000_000_000u64),
nonce: U256::zero()
};
let signed_tx = tx.sign(keypair.secret(), None);
txs.append(&signed_tx);
txs.out()
},
_ => ::rlp::EMPTY_LIST_RLP.to_vec()
};
/// Add a block to test client.
pub fn add_block<F>(&self, with: EachBlockWith, hook: F)
where F: Fn(BlockHeader) -> BlockHeader
{
let n = self.numbers.read().len();
let mut rlp = RlpStream::new_list(3);
rlp.append(&header);
rlp.append_raw(&txs, 1);
rlp.append_raw(uncles.as_raw(), 1);
let unverified = Unverified::from_rlp(rlp.out()).unwrap();
self.import_block(unverified).unwrap();
}
}
let mut header = BlockHeader::new();
header.set_difficulty(From::from(n));
header.set_parent_hash(self.last_hash.read().clone());
header.set_number(n as BlockNumber);
header.set_gas_limit(U256::from(1_000_000));
header.set_extra_data(self.extra_data.clone());
header = hook(header);
let uncles = match with {
EachBlockWith::Uncle | EachBlockWith::UncleAndTransaction => {
let mut uncles = RlpStream::new_list(1);
let mut uncle_header = BlockHeader::new();
uncle_header.set_difficulty(From::from(n));
uncle_header.set_parent_hash(self.last_hash.read().clone());
uncle_header.set_number(n as BlockNumber);
uncles.append(&uncle_header);
header.set_uncles_hash(keccak(uncles.as_raw()));
uncles
},
_ => RlpStream::new_list(0)
};
let txs = match with {
EachBlockWith::Transaction | EachBlockWith::UncleAndTransaction => {
let mut txs = RlpStream::new_list(1);
let keypair = Random.generate().unwrap();
// Update nonces value
self.nonces.write().insert(keypair.address(), U256::one());
let tx = Transaction {
action: Action::Create,
value: U256::from(100),
data: "3331600055".from_hex().unwrap(),
gas: U256::from(100_000),
gas_price: U256::from(200_000_000_000u64),
nonce: U256::zero()
};
let signed_tx = tx.sign(keypair.secret(), None);
txs.append(&signed_tx);
txs.out()
},
_ => ::rlp::EMPTY_LIST_RLP.to_vec()
};
/// Make a bad block by setting invalid extra data.
pub fn corrupt_block(&self, n: BlockNumber) {
let hash = self.block_hash(BlockId::Number(n)).unwrap();
let mut header: BlockHeader = self.block_header(BlockId::Number(n)).unwrap().decode().expect("decoding failed");
header.set_extra_data(b"This extra data is way too long to be considered valid".to_vec());
let mut rlp = RlpStream::new_list(3);
rlp.append(&header);
rlp.append_raw(&::rlp::NULL_RLP, 1);
rlp.append_raw(&::rlp::NULL_RLP, 1);
self.blocks.write().insert(hash, rlp.out());
rlp.append_raw(&txs, 1);
rlp.append_raw(uncles.as_raw(), 1);
let unverified = Unverified::from_rlp(rlp.out()).unwrap();
self.import_block(unverified).unwrap();
}
/// Add a sequence of blocks to test client.
pub fn add_blocks(&self, count: usize, with: EachBlockWith) {
for _ in 0..count {
self.add_block(with, |header| header);
}
}
/// Make a bad block by setting invalid parent hash.

View File

@ -44,7 +44,7 @@ use self::epoch::PendingTransition;
use account_provider::AccountProvider;
use builtin::Builtin;
use vm::{EnvInfo, Schedule, CreateContractAddress};
use vm::{EnvInfo, Schedule, CreateContractAddress, CallType, ActionValue};
use error::Error;
use header::{Header, BlockNumber};
use snapshot::SnapshotComponents;
@ -163,8 +163,10 @@ pub fn default_system_or_code_call<'a>(machine: &'a ::machine::EthereumMachine,
None,
Some(code),
Some(code_hash),
Some(ActionValue::Apparent(U256::zero())),
U256::max_value(),
Some(data),
Some(CallType::StaticCall),
)
},
};

View File

@ -135,8 +135,10 @@ impl EthereumMachine {
Some(contract_address),
code,
code_hash,
None,
gas,
data
data,
None,
)
}
@ -149,8 +151,10 @@ impl EthereumMachine {
contract_address: Option<Address>,
code: Option<Arc<Vec<u8>>>,
code_hash: Option<H256>,
value: Option<ActionValue>,
gas: U256,
data: Option<Vec<u8>>
data: Option<Vec<u8>>,
call_type: Option<CallType>,
) -> Result<Vec<u8>, Error> {
let env_info = {
let mut env_info = block.env_info();
@ -167,11 +171,11 @@ impl EthereumMachine {
origin: SYSTEM_ADDRESS,
gas,
gas_price: 0.into(),
value: ActionValue::Transfer(0.into()),
value: value.unwrap_or(ActionValue::Transfer(0.into())),
code,
code_hash,
data,
call_type: CallType::Call,
call_type: call_type.unwrap_or(CallType::Call),
params_type: ParamsType::Separate,
};
let schedule = self.schedule(env_info.number);

View File

@ -28,6 +28,7 @@ use ethcore::client::{BlockStatus, BlockId, BlockImportError, BlockImportErrorKi
use ethcore::error::{ImportErrorKind, QueueErrorKind, BlockError};
use sync_io::SyncIo;
use blocks::{BlockCollection, SyncBody, SyncHeader};
use chain::BlockSet;
const MAX_HEADERS_TO_REQUEST: usize = 128;
const MAX_BODIES_TO_REQUEST: usize = 32;
@ -35,6 +36,26 @@ const MAX_RECEPITS_TO_REQUEST: usize = 128;
const SUBCHAIN_SIZE: u64 = 256;
const MAX_ROUND_PARENTS: usize = 16;
const MAX_PARALLEL_SUBCHAIN_DOWNLOAD: usize = 5;
const MAX_USELESS_HEADERS_PER_ROUND: usize = 3;
// logging macros prepend BlockSet context for log filtering
macro_rules! trace_sync {
($self:ident, $fmt:expr, $($arg:tt)+) => {
trace!(target: "sync", concat!("{:?}: ", $fmt), $self.block_set, $($arg)+);
};
($self:ident, $fmt:expr) => {
trace!(target: "sync", concat!("{:?}: ", $fmt), $self.block_set);
};
}
macro_rules! debug_sync {
($self:ident, $fmt:expr, $($arg:tt)+) => {
debug!(target: "sync", concat!("{:?}: ", $fmt), $self.block_set, $($arg)+);
};
($self:ident, $fmt:expr) => {
debug!(target: "sync", concat!("{:?}: ", $fmt), $self.block_set);
};
}
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
/// Downloader state
@ -65,6 +86,7 @@ pub enum BlockRequest {
}
/// Indicates sync action
#[derive(Eq, PartialEq, Debug)]
pub enum DownloadAction {
/// Do nothing
None,
@ -89,15 +111,17 @@ impl From<rlp::DecoderError> for BlockDownloaderImportError {
/// Block downloader strategy.
/// Manages state and block data for a block download process.
pub struct BlockDownloader {
/// Which set of blocks to download
block_set: BlockSet,
/// Downloader state
state: State,
/// Highest block number seen
highest_block: Option<BlockNumber>,
/// Downloaded blocks, holds `H`, `B` and `S`
blocks: BlockCollection,
/// Last impoted block number
/// Last imported block number
last_imported_block: BlockNumber,
/// Last impoted block hash
/// Last imported block hash
last_imported_hash: H256,
/// Number of blocks imported this round
imported_this_round: Option<usize>,
@ -114,13 +138,20 @@ pub struct BlockDownloader {
retract_step: u64,
/// Whether reorg should be limited.
limit_reorg: bool,
/// consecutive useless headers this round
useless_headers_count: usize,
}
impl BlockDownloader {
/// Create a new instance of syncing strategy. This won't reorganize to before the
/// last kept state.
pub fn new(sync_receipts: bool, start_hash: &H256, start_number: BlockNumber) -> Self {
/// Create a new instance of syncing strategy.
/// For BlockSet::NewBlocks this won't reorganize to before the last kept state.
pub fn new(block_set: BlockSet, start_hash: &H256, start_number: BlockNumber) -> Self {
let (limit_reorg, sync_receipts) = match block_set {
BlockSet::NewBlocks => (true, false),
BlockSet::OldBlocks => (false, true)
};
BlockDownloader {
block_set: block_set,
state: State::Idle,
highest_block: None,
last_imported_block: start_number,
@ -133,32 +164,15 @@ impl BlockDownloader {
download_receipts: sync_receipts,
target_hash: None,
retract_step: 1,
limit_reorg: true,
}
}
/// Create a new instance of sync with unlimited reorg allowed.
pub fn with_unlimited_reorg(sync_receipts: bool, start_hash: &H256, start_number: BlockNumber) -> Self {
BlockDownloader {
state: State::Idle,
highest_block: None,
last_imported_block: start_number,
last_imported_hash: start_hash.clone(),
last_round_start: start_number,
last_round_start_hash: start_hash.clone(),
blocks: BlockCollection::new(sync_receipts),
imported_this_round: None,
round_parents: VecDeque::new(),
download_receipts: sync_receipts,
target_hash: None,
retract_step: 1,
limit_reorg: false,
limit_reorg: limit_reorg,
useless_headers_count: 0,
}
}
/// Reset sync. Clear all local downloaded data.
pub fn reset(&mut self) {
self.blocks.clear();
self.useless_headers_count = 0;
self.state = State::Idle;
}
@ -220,45 +234,65 @@ impl BlockDownloader {
}
/// Add new block headers.
pub fn import_headers(&mut self, io: &mut SyncIo, r: &Rlp, expected_hash: Option<H256>) -> Result<DownloadAction, BlockDownloaderImportError> {
pub fn import_headers(&mut self, io: &mut SyncIo, r: &Rlp, expected_hash: H256) -> Result<DownloadAction, BlockDownloaderImportError> {
let item_count = r.item_count().unwrap_or(0);
if self.state == State::Idle {
trace!(target: "sync", "Ignored unexpected block headers");
trace_sync!(self, "Ignored unexpected block headers");
return Ok(DownloadAction::None)
}
if item_count == 0 && (self.state == State::Blocks) {
return Err(BlockDownloaderImportError::Invalid);
}
// The request is generated in ::request_blocks.
let (max_count, skip) = if self.state == State::ChainHead {
(SUBCHAIN_SIZE as usize, (MAX_HEADERS_TO_REQUEST - 2) as u64)
} else {
(MAX_HEADERS_TO_REQUEST, 0)
};
if item_count > max_count {
debug!(target: "sync", "Headers response is larger than expected");
return Err(BlockDownloaderImportError::Invalid);
}
let mut headers = Vec::new();
let mut hashes = Vec::new();
let mut valid_response = item_count == 0; //empty response is valid
let mut any_known = false;
let mut last_header = None;
for i in 0..item_count {
let info = SyncHeader::from_rlp(r.at(i)?.as_raw().to_vec())?;
let number = BlockNumber::from(info.header.number());
let hash = info.header.hash();
// Check if any of the headers matches the hash we requested
if !valid_response {
if let Some(expected) = expected_hash {
valid_response = expected == hash;
let valid_response = match last_header {
// First header must match expected hash.
None => expected_hash == hash,
Some((last_number, last_hash)) => {
// Subsequent headers must be spaced by skip interval.
let skip_valid = number == last_number + skip + 1;
// Consecutive headers must be linked by parent hash.
let parent_valid = (number != last_number + 1) || *info.header.parent_hash() == last_hash;
skip_valid && parent_valid
}
}
any_known = any_known || self.blocks.contains_head(&hash);
if self.blocks.contains(&hash) {
trace!(target: "sync", "Skipping existing block header {} ({:?})", number, hash);
continue;
};
// Disable the peer for this syncing round if it gives invalid chain
if !valid_response {
debug!(target: "sync", "Invalid headers response");
return Err(BlockDownloaderImportError::Invalid);
}
if self.highest_block.as_ref().map_or(true, |n| number > *n) {
self.highest_block = Some(number);
last_header = Some((number, hash));
if self.blocks.contains(&hash) {
trace_sync!(self, "Skipping existing block header {} ({:?})", number, hash);
continue;
}
match io.chain().block_status(BlockId::Hash(hash.clone())) {
BlockStatus::InChain | BlockStatus::Queued => {
match self.state {
State::Blocks => trace!(target: "sync", "Header already in chain {} ({})", number, hash),
_ => trace!(target: "sync", "Header already in chain {} ({}), state = {:?}", number, hash, self.state),
State::Blocks => trace_sync!(self, "Header already in chain {} ({})", number, hash),
_ => trace_sync!(self, "Header already in chain {} ({}), state = {:?}", number, hash, self.state),
}
headers.push(info);
hashes.push(hash);
@ -273,17 +307,16 @@ impl BlockDownloader {
}
}
// Disable the peer for this syncing round if it gives invalid chain
if !valid_response {
trace!(target: "sync", "Invalid headers response");
return Err(BlockDownloaderImportError::Invalid);
if let Some((number, _)) = last_header {
if self.highest_block.as_ref().map_or(true, |n| number > *n) {
self.highest_block = Some(number);
}
}
match self.state {
State::ChainHead => {
if !headers.is_empty() {
// TODO: validate heads better. E.g. check that there is enough distance between blocks.
trace!(target: "sync", "Received {} subchain heads, proceeding to download", headers.len());
trace_sync!(self, "Received {} subchain heads, proceeding to download", headers.len());
self.blocks.reset_to(hashes);
self.state = State::Blocks;
return Ok(DownloadAction::Reset);
@ -292,34 +325,41 @@ impl BlockDownloader {
let oldest_reorg = io.chain().pruning_info().earliest_state;
let last = self.last_imported_block;
if self.limit_reorg && best > last && (last == 0 || last < oldest_reorg) {
trace!(target: "sync", "No common block, disabling peer");
trace_sync!(self, "No common block, disabling peer");
return Err(BlockDownloaderImportError::Invalid);
}
}
},
State::Blocks => {
let count = headers.len();
// At least one of the heades must advance the subchain. Otherwise they are all useless.
if count == 0 || !any_known {
trace!(target: "sync", "No useful headers");
// At least one of the headers must advance the subchain. Otherwise they are all useless.
if count == 0 {
self.useless_headers_count += 1;
trace_sync!(self, "No useful headers ({:?} this round), expected hash {:?}", self.useless_headers_count, expected_hash);
// only reset download if we have multiple subchain heads, to avoid unnecessary resets
// when we are at the head of the chain when we may legitimately receive no useful headers
if self.blocks.heads_len() > 1 && self.useless_headers_count >= MAX_USELESS_HEADERS_PER_ROUND {
trace_sync!(self, "Received {:?} useless responses this round. Resetting sync", MAX_USELESS_HEADERS_PER_ROUND);
self.reset();
}
return Err(BlockDownloaderImportError::Useless);
}
self.blocks.insert_headers(headers);
trace!(target: "sync", "Inserted {} headers", count);
trace_sync!(self, "Inserted {} headers", count);
},
_ => trace!(target: "sync", "Unexpected headers({})", headers.len()),
_ => trace_sync!(self, "Unexpected headers({})", headers.len()),
}
Ok(DownloadAction::None)
}
/// Called by peer once it has new block bodies
pub fn import_bodies(&mut self, r: &Rlp) -> Result<(), BlockDownloaderImportError> {
pub fn import_bodies(&mut self, r: &Rlp, expected_hashes: &[H256]) -> Result<(), BlockDownloaderImportError> {
let item_count = r.item_count().unwrap_or(0);
if item_count == 0 {
return Err(BlockDownloaderImportError::Useless);
} else if self.state != State::Blocks {
trace!(target: "sync", "Ignored unexpected block bodies");
trace_sync!(self, "Ignored unexpected block bodies");
} else {
let mut bodies = Vec::with_capacity(item_count);
for i in 0..item_count {
@ -327,8 +367,13 @@ impl BlockDownloader {
bodies.push(body);
}
if self.blocks.insert_bodies(bodies) != item_count {
trace!(target: "sync", "Deactivating peer for giving invalid block bodies");
let hashes = self.blocks.insert_bodies(bodies);
if hashes.len() != item_count {
trace_sync!(self, "Deactivating peer for giving invalid block bodies");
return Err(BlockDownloaderImportError::Invalid);
}
if !all_expected(hashes.as_slice(), expected_hashes, |&a, &b| a == b) {
trace_sync!(self, "Deactivating peer for giving unexpected block bodies");
return Err(BlockDownloaderImportError::Invalid);
}
}
@ -336,25 +381,30 @@ impl BlockDownloader {
}
/// Called by peer once it has new block bodies
pub fn import_receipts(&mut self, _io: &mut SyncIo, r: &Rlp) -> Result<(), BlockDownloaderImportError> {
pub fn import_receipts(&mut self, r: &Rlp, expected_hashes: &[H256]) -> Result<(), BlockDownloaderImportError> {
let item_count = r.item_count().unwrap_or(0);
if item_count == 0 {
return Err(BlockDownloaderImportError::Useless);
}
else if self.state != State::Blocks {
trace!(target: "sync", "Ignored unexpected block receipts");
trace_sync!(self, "Ignored unexpected block receipts");
}
else {
let mut receipts = Vec::with_capacity(item_count);
for i in 0..item_count {
let receipt = r.at(i).map_err(|e| {
trace!(target: "sync", "Error decoding block receipts RLP: {:?}", e);
trace_sync!(self, "Error decoding block receipts RLP: {:?}", e);
BlockDownloaderImportError::Invalid
})?;
receipts.push(receipt.as_raw().to_vec());
}
if self.blocks.insert_receipts(receipts) != item_count {
trace!(target: "sync", "Deactivating peer for giving invalid block receipts");
let hashes = self.blocks.insert_receipts(receipts);
if hashes.len() != item_count {
trace_sync!(self, "Deactivating peer for giving invalid block receipts");
return Err(BlockDownloaderImportError::Invalid);
}
if !all_expected(hashes.as_slice(), expected_hashes, |a, b| a.contains(b)) {
trace_sync!(self, "Deactivating peer for giving unexpected block receipts");
return Err(BlockDownloaderImportError::Invalid);
}
}
@ -363,7 +413,7 @@ impl BlockDownloader {
fn start_sync_round(&mut self, io: &mut SyncIo) {
self.state = State::ChainHead;
trace!(target: "sync", "Starting round (last imported count = {:?}, last started = {}, block = {:?}", self.imported_this_round, self.last_round_start, self.last_imported_block);
trace_sync!(self, "Starting round (last imported count = {:?}, last started = {}, block = {:?}", self.imported_this_round, self.last_round_start, self.last_imported_block);
// Check if need to retract to find the common block. The problem is that the peers still return headers by hash even
// from the non-canonical part of the tree. So we also retract if nothing has been imported last round.
let start = self.last_round_start;
@ -375,12 +425,12 @@ impl BlockDownloader {
if let Some(&(_, p)) = self.round_parents.iter().find(|&&(h, _)| h == start_hash) {
self.last_imported_block = start - 1;
self.last_imported_hash = p.clone();
trace!(target: "sync", "Searching common header from the last round {} ({})", self.last_imported_block, self.last_imported_hash);
trace_sync!(self, "Searching common header from the last round {} ({})", self.last_imported_block, self.last_imported_hash);
} else {
let best = io.chain().chain_info().best_block_number;
let oldest_reorg = io.chain().pruning_info().earliest_state;
if self.limit_reorg && best > start && start < oldest_reorg {
debug!(target: "sync", "Could not revert to previous ancient block, last: {} ({})", start, start_hash);
debug_sync!(self, "Could not revert to previous ancient block, last: {} ({})", start, start_hash);
self.reset();
} else {
let n = start - cmp::min(self.retract_step, start);
@ -389,10 +439,10 @@ impl BlockDownloader {
Some(h) => {
self.last_imported_block = n;
self.last_imported_hash = h;
trace!(target: "sync", "Searching common header in the blockchain {} ({})", start, self.last_imported_hash);
trace_sync!(self, "Searching common header in the blockchain {} ({})", start, self.last_imported_hash);
}
None => {
debug!(target: "sync", "Could not revert to previous block, last: {} ({})", start, self.last_imported_hash);
debug_sync!(self, "Could not revert to previous block, last: {} ({})", start, self.last_imported_hash);
self.reset();
}
}
@ -420,7 +470,7 @@ impl BlockDownloader {
State::ChainHead => {
if num_active_peers < MAX_PARALLEL_SUBCHAIN_DOWNLOAD {
// Request subchain headers
trace!(target: "sync", "Starting sync with better chain");
trace_sync!(self, "Starting sync with better chain");
// Request MAX_HEADERS_TO_REQUEST - 2 headers apart so that
// MAX_HEADERS_TO_REQUEST would include headers for neighbouring subchains
return Some(BlockRequest::Headers {
@ -463,8 +513,9 @@ impl BlockDownloader {
}
/// Checks if there are blocks fully downloaded that can be imported into the blockchain and does the import.
pub fn collect_blocks(&mut self, io: &mut SyncIo, allow_out_of_order: bool) -> Result<(), BlockDownloaderImportError> {
let mut bad = false;
/// Returns DownloadAction::Reset if it is imported all the the blocks it can and all downloading peers should be reset
pub fn collect_blocks(&mut self, io: &mut SyncIo, allow_out_of_order: bool) -> DownloadAction {
let mut download_action = DownloadAction::None;
let mut imported = HashSet::new();
let blocks = self.blocks.drain();
let count = blocks.len();
@ -478,8 +529,8 @@ impl BlockDownloader {
if self.target_hash.as_ref().map_or(false, |t| t == &h) {
self.state = State::Complete;
trace!(target: "sync", "Sync target reached");
return Ok(());
trace_sync!(self, "Sync target reached");
return download_action;
}
let result = if let Some(receipts) = receipts {
@ -490,15 +541,15 @@ impl BlockDownloader {
match result {
Err(BlockImportError(BlockImportErrorKind::Import(ImportErrorKind::AlreadyInChain), _)) => {
trace!(target: "sync", "Block already in chain {:?}", h);
trace_sync!(self, "Block already in chain {:?}", h);
self.block_imported(&h, number, &parent);
},
Err(BlockImportError(BlockImportErrorKind::Import(ImportErrorKind::AlreadyQueued), _)) => {
trace!(target: "sync", "Block already queued {:?}", h);
trace_sync!(self, "Block already queued {:?}", h);
self.block_imported(&h, number, &parent);
},
Ok(_) => {
trace!(target: "sync", "Block queued {:?}", h);
trace_sync!(self, "Block queued {:?}", h);
imported.insert(h.clone());
self.block_imported(&h, number, &parent);
},
@ -506,37 +557,34 @@ impl BlockDownloader {
break;
},
Err(BlockImportError(BlockImportErrorKind::Block(BlockError::UnknownParent(_)), _)) => {
trace!(target: "sync", "Unknown new block parent, restarting sync");
trace_sync!(self, "Unknown new block parent, restarting sync");
break;
},
Err(BlockImportError(BlockImportErrorKind::Block(BlockError::TemporarilyInvalid(_)), _)) => {
debug!(target: "sync", "Block temporarily invalid, restarting sync");
debug_sync!(self, "Block temporarily invalid: {:?}, restarting sync", h);
break;
},
Err(BlockImportError(BlockImportErrorKind::Queue(QueueErrorKind::Full(limit)), _)) => {
debug!(target: "sync", "Block import queue full ({}), restarting sync", limit);
debug_sync!(self, "Block import queue full ({}), restarting sync", limit);
download_action = DownloadAction::Reset;
break;
},
Err(e) => {
debug!(target: "sync", "Bad block {:?} : {:?}", h, e);
bad = true;
debug_sync!(self, "Bad block {:?} : {:?}", h, e);
download_action = DownloadAction::Reset;
break;
}
}
}
trace!(target: "sync", "Imported {} of {}", imported.len(), count);
trace_sync!(self, "Imported {} of {}", imported.len(), count);
self.imported_this_round = Some(self.imported_this_round.unwrap_or(0) + imported.len());
if bad {
return Err(BlockDownloaderImportError::Invalid);
}
if self.blocks.is_empty() {
// complete sync round
trace!(target: "sync", "Sync round complete");
self.reset();
trace_sync!(self, "Sync round complete");
download_action = DownloadAction::Reset;
}
Ok(())
download_action
}
fn block_imported(&mut self, hash: &H256, number: BlockNumber, parent: &H256) {
@ -549,4 +597,392 @@ impl BlockDownloader {
}
}
//TODO: module tests
// Determines if the first argument matches an ordered subset of the second, according to some predicate.
fn all_expected<A, B, F>(values: &[A], expected_values: &[B], is_expected: F) -> bool
where F: Fn(&A, &B) -> bool
{
let mut expected_iter = expected_values.iter();
values.iter().all(|val1| {
while let Some(val2) = expected_iter.next() {
if is_expected(val1, val2) {
return true;
}
}
false
})
}
#[cfg(test)]
mod tests {
use super::*;
use ethcore::client::TestBlockChainClient;
use ethcore::header::Header as BlockHeader;
use ethcore::spec::Spec;
use ethkey::{Generator,Random};
use hash::keccak;
use parking_lot::RwLock;
use rlp::{encode_list,RlpStream};
use tests::helpers::TestIo;
use tests::snapshot::TestSnapshotService;
use transaction::{Transaction,SignedTransaction};
use triehash_ethereum::ordered_trie_root;
fn dummy_header(number: u64, parent_hash: H256) -> BlockHeader {
let mut header = BlockHeader::new();
header.set_gas_limit(0.into());
header.set_difficulty((number * 100).into());
header.set_timestamp(number * 10);
header.set_number(number);
header.set_parent_hash(parent_hash);
header.set_state_root(H256::zero());
header
}
fn dummy_signed_tx() -> SignedTransaction {
let keypair = Random.generate().unwrap();
Transaction::default().sign(keypair.secret(), None)
}
fn import_headers(headers: &[BlockHeader], downloader: &mut BlockDownloader, io: &mut SyncIo) -> Result<DownloadAction, BlockDownloaderImportError> {
let mut stream = RlpStream::new();
stream.append_list(headers);
let bytes = stream.out();
let rlp = Rlp::new(&bytes);
let expected_hash = headers.first().unwrap().hash();
downloader.import_headers(io, &rlp, expected_hash)
}
fn import_headers_ok(headers: &[BlockHeader], downloader: &mut BlockDownloader, io: &mut SyncIo) {
let res = import_headers(headers, downloader, io);
assert!(res.is_ok());
}
#[test]
fn import_headers_in_chain_head_state() {
::env_logger::try_init().ok();
let spec = Spec::new_test();
let genesis_hash = spec.genesis_header().hash();
let mut downloader = BlockDownloader::new(BlockSet::NewBlocks, &genesis_hash, 0);
downloader.state = State::ChainHead;
let mut chain = TestBlockChainClient::new();
let snapshot_service = TestSnapshotService::new();
let queue = RwLock::new(VecDeque::new());
let mut io = TestIo::new(&mut chain, &snapshot_service, &queue, None);
// Valid headers sequence.
let valid_headers = [
spec.genesis_header(),
dummy_header(127, H256::random()),
dummy_header(254, H256::random()),
];
let rlp_data = encode_list(&valid_headers);
let valid_rlp = Rlp::new(&rlp_data);
match downloader.import_headers(&mut io, &valid_rlp, genesis_hash) {
Ok(DownloadAction::Reset) => assert_eq!(downloader.state, State::Blocks),
_ => panic!("expected transition to Blocks state"),
};
// Headers are rejected because the expected hash does not match.
let invalid_start_block_headers = [
dummy_header(0, H256::random()),
dummy_header(127, H256::random()),
dummy_header(254, H256::random()),
];
let rlp_data = encode_list(&invalid_start_block_headers);
let invalid_start_block_rlp = Rlp::new(&rlp_data);
match downloader.import_headers(&mut io, &invalid_start_block_rlp, genesis_hash) {
Err(BlockDownloaderImportError::Invalid) => (),
_ => panic!("expected BlockDownloaderImportError"),
};
// Headers are rejected because they are not spaced as expected.
let invalid_skip_headers = [
spec.genesis_header(),
dummy_header(128, H256::random()),
dummy_header(256, H256::random()),
];
let rlp_data = encode_list(&invalid_skip_headers);
let invalid_skip_rlp = Rlp::new(&rlp_data);
match downloader.import_headers(&mut io, &invalid_skip_rlp, genesis_hash) {
Err(BlockDownloaderImportError::Invalid) => (),
_ => panic!("expected BlockDownloaderImportError"),
};
// Invalid because the packet size is too large.
let mut too_many_headers = Vec::with_capacity((SUBCHAIN_SIZE + 1) as usize);
too_many_headers.push(spec.genesis_header());
for i in 1..(SUBCHAIN_SIZE + 1) {
too_many_headers.push(dummy_header((MAX_HEADERS_TO_REQUEST as u64 - 1) * i, H256::random()));
}
let rlp_data = encode_list(&too_many_headers);
let too_many_rlp = Rlp::new(&rlp_data);
match downloader.import_headers(&mut io, &too_many_rlp, genesis_hash) {
Err(BlockDownloaderImportError::Invalid) => (),
_ => panic!("expected BlockDownloaderImportError"),
};
}
#[test]
fn import_headers_in_blocks_state() {
::env_logger::try_init().ok();
let mut chain = TestBlockChainClient::new();
let snapshot_service = TestSnapshotService::new();
let queue = RwLock::new(VecDeque::new());
let mut io = TestIo::new(&mut chain, &snapshot_service, &queue, None);
let mut headers = Vec::with_capacity(3);
let parent_hash = H256::random();
headers.push(dummy_header(127, parent_hash));
let parent_hash = headers[0].hash();
headers.push(dummy_header(128, parent_hash));
let parent_hash = headers[1].hash();
headers.push(dummy_header(129, parent_hash));
let mut downloader = BlockDownloader::new(BlockSet::NewBlocks, &H256::random(), 0);
downloader.state = State::Blocks;
downloader.blocks.reset_to(vec![headers[0].hash()]);
let rlp_data = encode_list(&headers);
let headers_rlp = Rlp::new(&rlp_data);
match downloader.import_headers(&mut io, &headers_rlp, headers[0].hash()) {
Ok(DownloadAction::None) => (),
_ => panic!("expected successful import"),
};
// Invalidate parent_hash link.
headers[2] = dummy_header(129, H256::random());
let rlp_data = encode_list(&headers);
let headers_rlp = Rlp::new(&rlp_data);
match downloader.import_headers(&mut io, &headers_rlp, headers[0].hash()) {
Err(BlockDownloaderImportError::Invalid) => (),
_ => panic!("expected BlockDownloaderImportError"),
};
// Invalidate header sequence by skipping a header.
headers[2] = dummy_header(130, headers[1].hash());
let rlp_data = encode_list(&headers);
let headers_rlp = Rlp::new(&rlp_data);
match downloader.import_headers(&mut io, &headers_rlp, headers[0].hash()) {
Err(BlockDownloaderImportError::Invalid) => (),
_ => panic!("expected BlockDownloaderImportError"),
};
}
#[test]
fn import_bodies() {
::env_logger::try_init().ok();
let mut chain = TestBlockChainClient::new();
let snapshot_service = TestSnapshotService::new();
let queue = RwLock::new(VecDeque::new());
let mut io = TestIo::new(&mut chain, &snapshot_service, &queue, None);
// Import block headers.
let mut headers = Vec::with_capacity(4);
let mut bodies = Vec::with_capacity(4);
let mut parent_hash = H256::zero();
for i in 0..4 {
// Construct the block body
let mut uncles = if i > 0 {
encode_list(&[dummy_header(i - 1, H256::random())]).into_vec()
} else {
::rlp::EMPTY_LIST_RLP.to_vec()
};
let mut txs = encode_list(&[dummy_signed_tx()]);
let tx_root = ordered_trie_root(Rlp::new(&txs).iter().map(|r| r.as_raw()));
let mut rlp = RlpStream::new_list(2);
rlp.append_raw(&txs, 1);
rlp.append_raw(&uncles, 1);
bodies.push(rlp.out());
// Construct the block header
let mut header = dummy_header(i, parent_hash);
header.set_transactions_root(tx_root);
header.set_uncles_hash(keccak(&uncles));
parent_hash = header.hash();
headers.push(header);
}
let mut downloader = BlockDownloader::new(BlockSet::NewBlocks, &headers[0].hash(), 0);
downloader.state = State::Blocks;
downloader.blocks.reset_to(vec![headers[0].hash()]);
// Only import the first three block headers.
let rlp_data = encode_list(&headers[0..3]);
let headers_rlp = Rlp::new(&rlp_data);
assert!(downloader.import_headers(&mut io, &headers_rlp, headers[0].hash()).is_ok());
// Import first body successfully.
let mut rlp_data = RlpStream::new_list(1);
rlp_data.append_raw(&bodies[0], 1);
let bodies_rlp = Rlp::new(rlp_data.as_raw());
assert!(downloader.import_bodies(&bodies_rlp, &[headers[0].hash(), headers[1].hash()]).is_ok());
// Import second body successfully.
let mut rlp_data = RlpStream::new_list(1);
rlp_data.append_raw(&bodies[1], 1);
let bodies_rlp = Rlp::new(rlp_data.as_raw());
assert!(downloader.import_bodies(&bodies_rlp, &[headers[0].hash(), headers[1].hash()]).is_ok());
// Import unexpected third body.
let mut rlp_data = RlpStream::new_list(1);
rlp_data.append_raw(&bodies[2], 1);
let bodies_rlp = Rlp::new(rlp_data.as_raw());
match downloader.import_bodies(&bodies_rlp, &[headers[0].hash(), headers[1].hash()]) {
Err(BlockDownloaderImportError::Invalid) => (),
_ => panic!("expected BlockDownloaderImportError"),
};
}
#[test]
fn import_receipts() {
::env_logger::try_init().ok();
let mut chain = TestBlockChainClient::new();
let snapshot_service = TestSnapshotService::new();
let queue = RwLock::new(VecDeque::new());
let mut io = TestIo::new(&mut chain, &snapshot_service, &queue, None);
// Import block headers.
let mut headers = Vec::with_capacity(4);
let mut receipts = Vec::with_capacity(4);
let mut parent_hash = H256::zero();
for i in 0..4 {
// Construct the receipts. Receipt root for the first two blocks is the same.
//
// The RLP-encoded integers are clearly not receipts, but the BlockDownloader treats
// all receipts as byte blobs, so it does not matter.
let mut receipts_rlp = if i < 2 {
encode_list(&[0u32])
} else {
encode_list(&[i as u32])
};
let receipts_root = ordered_trie_root(Rlp::new(&receipts_rlp).iter().map(|r| r.as_raw()));
receipts.push(receipts_rlp);
// Construct the block header.
let mut header = dummy_header(i, parent_hash);
header.set_receipts_root(receipts_root);
parent_hash = header.hash();
headers.push(header);
}
let mut downloader = BlockDownloader::new(BlockSet::OldBlocks, &headers[0].hash(), 0);
downloader.state = State::Blocks;
downloader.blocks.reset_to(vec![headers[0].hash()]);
// Only import the first three block headers.
let rlp_data = encode_list(&headers[0..3]);
let headers_rlp = Rlp::new(&rlp_data);
assert!(downloader.import_headers(&mut io, &headers_rlp, headers[0].hash()).is_ok());
// Import second and third receipts successfully.
let mut rlp_data = RlpStream::new_list(2);
rlp_data.append_raw(&receipts[1], 1);
rlp_data.append_raw(&receipts[2], 1);
let receipts_rlp = Rlp::new(rlp_data.as_raw());
assert!(downloader.import_receipts(&receipts_rlp, &[headers[1].hash(), headers[2].hash()]).is_ok());
// Import unexpected fourth receipt.
let mut rlp_data = RlpStream::new_list(1);
rlp_data.append_raw(&receipts[3], 1);
let bodies_rlp = Rlp::new(rlp_data.as_raw());
match downloader.import_bodies(&bodies_rlp, &[headers[1].hash(), headers[2].hash()]) {
Err(BlockDownloaderImportError::Invalid) => (),
_ => panic!("expected BlockDownloaderImportError"),
};
}
#[test]
fn reset_after_multiple_sets_of_useless_headers() {
::env_logger::try_init().ok();
let spec = Spec::new_test();
let genesis_hash = spec.genesis_header().hash();
let mut downloader = BlockDownloader::new(BlockSet::NewBlocks, &genesis_hash, 0);
downloader.state = State::ChainHead;
let mut chain = TestBlockChainClient::new();
let snapshot_service = TestSnapshotService::new();
let queue = RwLock::new(VecDeque::new());
let mut io = TestIo::new(&mut chain, &snapshot_service, &queue, None);
let heads = [
spec.genesis_header(),
dummy_header(127, H256::random()),
dummy_header(254, H256::random()),
];
let short_subchain = [dummy_header(1, genesis_hash)];
import_headers_ok(&heads, &mut downloader, &mut io);
import_headers_ok(&short_subchain, &mut downloader, &mut io);
assert_eq!(downloader.state, State::Blocks);
assert!(!downloader.blocks.is_empty());
// simulate receiving useless headers
let head = vec![short_subchain.last().unwrap().clone()];
for _ in 0..MAX_USELESS_HEADERS_PER_ROUND {
let res = import_headers(&head, &mut downloader, &mut io);
assert!(res.is_err());
}
assert_eq!(downloader.state, State::Idle);
assert!(downloader.blocks.is_empty());
}
#[test]
fn dont_reset_after_multiple_sets_of_useless_headers_for_chain_head() {
::env_logger::try_init().ok();
let spec = Spec::new_test();
let genesis_hash = spec.genesis_header().hash();
let mut downloader = BlockDownloader::new(BlockSet::NewBlocks, &genesis_hash, 0);
downloader.state = State::ChainHead;
let mut chain = TestBlockChainClient::new();
let snapshot_service = TestSnapshotService::new();
let queue = RwLock::new(VecDeque::new());
let mut io = TestIo::new(&mut chain, &snapshot_service, &queue, None);
let heads = [
spec.genesis_header()
];
let short_subchain = [dummy_header(1, genesis_hash)];
import_headers_ok(&heads, &mut downloader, &mut io);
import_headers_ok(&short_subchain, &mut downloader, &mut io);
assert_eq!(downloader.state, State::Blocks);
assert!(!downloader.blocks.is_empty());
// simulate receiving useless headers
let head = vec![short_subchain.last().unwrap().clone()];
for _ in 0..MAX_USELESS_HEADERS_PER_ROUND {
let res = import_headers(&head, &mut downloader, &mut io);
assert!(res.is_err());
}
// download shouldn't be reset since this is the chain head for a single subchain.
// this state usually occurs for NewBlocks when it has reached the chain head.
assert_eq!(downloader.state, State::Blocks);
assert!(!downloader.blocks.is_empty());
}
}

View File

@ -215,32 +215,28 @@ impl BlockCollection {
}
/// Insert a collection of block bodies for previously downloaded headers.
pub fn insert_bodies(&mut self, bodies: Vec<SyncBody>) -> usize {
let mut inserted = 0;
for b in bodies {
if let Err(e) = self.insert_body(b) {
trace!(target: "sync", "Ignored invalid body: {:?}", e);
} else {
inserted += 1;
}
}
inserted
pub fn insert_bodies(&mut self, bodies: Vec<SyncBody>) -> Vec<H256> {
bodies.into_iter()
.filter_map(|b| {
self.insert_body(b)
.map_err(|e| trace!(target: "sync", "Ignored invalid body: {:?}", e))
.ok()
})
.collect()
}
/// Insert a collection of block receipts for previously downloaded headers.
pub fn insert_receipts(&mut self, receipts: Vec<Bytes>) -> usize {
pub fn insert_receipts(&mut self, receipts: Vec<Bytes>) -> Vec<Vec<H256>> {
if !self.need_receipts {
return 0;
return Vec::new();
}
let mut inserted = 0;
for r in receipts {
if let Err(e) = self.insert_receipt(r) {
trace!(target: "sync", "Ignored invalid receipt: {:?}", e);
} else {
inserted += 1;
}
}
inserted
receipts.into_iter()
.filter_map(|r| {
self.insert_receipt(r)
.map_err(|e| trace!(target: "sync", "Ignored invalid receipt: {:?}", e))
.ok()
})
.collect()
}
/// Returns a set of block hashes that require a body download. The returned set is marked as being downloaded.
@ -401,9 +397,9 @@ impl BlockCollection {
self.blocks.contains_key(hash)
}
/// Check if collection contains a block header.
pub fn contains_head(&self, hash: &H256) -> bool {
self.heads.contains(hash)
/// Check the number of heads
pub fn heads_len(&self) -> usize {
self.heads.len()
}
/// Return used heap size.
@ -421,7 +417,7 @@ impl BlockCollection {
self.downloading_headers.contains(hash) || self.downloading_bodies.contains(hash)
}
fn insert_body(&mut self, body: SyncBody) -> Result<(), network::Error> {
fn insert_body(&mut self, body: SyncBody) -> Result<H256, network::Error> {
let header_id = {
let tx_root = ordered_trie_root(Rlp::new(&body.transactions_bytes).iter().map(|r| r.as_raw()));
let uncles = keccak(&body.uncles_bytes);
@ -438,7 +434,7 @@ impl BlockCollection {
Some(ref mut block) => {
trace!(target: "sync", "Got body {}", h);
block.body = Some(body);
Ok(())
Ok(h)
},
None => {
warn!("Got body with no header {}", h);
@ -453,7 +449,7 @@ impl BlockCollection {
}
}
fn insert_receipt(&mut self, r: Bytes) -> Result<(), network::Error> {
fn insert_receipt(&mut self, r: Bytes) -> Result<Vec<H256>, network::Error> {
let receipt_root = {
let receipts = Rlp::new(&r);
ordered_trie_root(receipts.iter().map(|r| r.as_raw()))
@ -461,7 +457,8 @@ impl BlockCollection {
self.downloading_receipts.remove(&receipt_root);
match self.receipt_ids.entry(receipt_root) {
hash_map::Entry::Occupied(entry) => {
for h in entry.remove() {
let block_hashes = entry.remove();
for h in block_hashes.iter() {
match self.blocks.get_mut(&h) {
Some(ref mut block) => {
trace!(target: "sync", "Got receipt {}", h);
@ -473,7 +470,7 @@ impl BlockCollection {
}
}
}
Ok(())
Ok(block_hashes.to_vec())
},
hash_map::Entry::Vacant(_) => {
trace!(target: "sync", "Ignored unknown/stale block receipt {:?}", receipt_root);

View File

@ -28,6 +28,7 @@ use network::PeerId;
use rlp::Rlp;
use snapshot::ChunkType;
use std::cmp;
use std::mem;
use std::collections::HashSet;
use std::time::Instant;
use sync_io::SyncIo;
@ -292,10 +293,19 @@ impl SyncHandler {
let block_set = sync.peers.get(&peer_id)
.and_then(|p| p.block_set)
.unwrap_or(BlockSet::NewBlocks);
if !sync.reset_peer_asking(peer_id, PeerAsking::BlockBodies) {
let allowed = sync.peers.get(&peer_id).map(|p| p.is_allowed()).unwrap_or(false);
if !sync.reset_peer_asking(peer_id, PeerAsking::BlockBodies) || !allowed {
trace!(target: "sync", "{}: Ignored unexpected bodies", peer_id);
return Ok(());
}
let expected_blocks = match sync.peers.get_mut(&peer_id) {
Some(peer) => mem::replace(&mut peer.asking_blocks, Vec::new()),
None => {
trace!(target: "sync", "{}: Ignored unexpected bodies (peer not found)", peer_id);
return Ok(());
}
};
let item_count = r.item_count()?;
trace!(target: "sync", "{} -> BlockBodies ({} entries), set = {:?}", peer_id, item_count, block_set);
if item_count == 0 {
@ -315,7 +325,7 @@ impl SyncHandler {
Some(ref mut blocks) => blocks,
}
};
downloader.import_bodies(r)?;
downloader.import_bodies(r, expected_blocks.as_slice())?;
}
sync.collect_blocks(io, block_set);
Ok(())
@ -368,10 +378,23 @@ impl SyncHandler {
let expected_hash = sync.peers.get(&peer_id).and_then(|p| p.asking_hash);
let allowed = sync.peers.get(&peer_id).map(|p| p.is_allowed()).unwrap_or(false);
let block_set = sync.peers.get(&peer_id).and_then(|p| p.block_set).unwrap_or(BlockSet::NewBlocks);
if !sync.reset_peer_asking(peer_id, PeerAsking::BlockHeaders) || expected_hash.is_none() || !allowed {
trace!(target: "sync", "{}: Ignored unexpected headers, expected_hash = {:?}", peer_id, expected_hash);
if !sync.reset_peer_asking(peer_id, PeerAsking::BlockHeaders) {
debug!(target: "sync", "{}: Ignored unexpected headers", peer_id);
return Ok(());
}
let expected_hash = match expected_hash {
Some(hash) => hash,
None => {
debug!(target: "sync", "{}: Ignored unexpected headers (expected_hash is None)", peer_id);
return Ok(());
}
};
if !allowed {
debug!(target: "sync", "{}: Ignored unexpected headers (peer not allowed)", peer_id);
return Ok(());
}
let item_count = r.item_count()?;
trace!(target: "sync", "{} -> BlockHeaders ({} entries), state = {:?}, set = {:?}", peer_id, item_count, sync.state, block_set);
if (sync.state == SyncState::Idle || sync.state == SyncState::WaitingPeers) && sync.old_blocks.is_none() {
@ -399,12 +422,8 @@ impl SyncHandler {
downloader.import_headers(io, r, expected_hash)?
};
if let DownloadAction::Reset = result {
// mark all outstanding requests as expired
trace!("Resetting downloads for {:?}", block_set);
for (_, ref mut p) in sync.peers.iter_mut().filter(|&(_, ref p)| p.block_set == Some(block_set)) {
p.reset_asking();
}
if result == DownloadAction::Reset {
sync.reset_downloads(block_set);
}
sync.collect_blocks(io, block_set);
@ -415,10 +434,18 @@ impl SyncHandler {
fn on_peer_block_receipts(sync: &mut ChainSync, io: &mut SyncIo, peer_id: PeerId, r: &Rlp) -> Result<(), DownloaderImportError> {
sync.clear_peer_download(peer_id);
let block_set = sync.peers.get(&peer_id).and_then(|p| p.block_set).unwrap_or(BlockSet::NewBlocks);
if !sync.reset_peer_asking(peer_id, PeerAsking::BlockReceipts) {
let allowed = sync.peers.get(&peer_id).map(|p| p.is_allowed()).unwrap_or(false);
if !sync.reset_peer_asking(peer_id, PeerAsking::BlockReceipts) || !allowed {
trace!(target: "sync", "{}: Ignored unexpected receipts", peer_id);
return Ok(());
}
let expected_blocks = match sync.peers.get_mut(&peer_id) {
Some(peer) => mem::replace(&mut peer.asking_blocks, Vec::new()),
None => {
trace!(target: "sync", "{}: Ignored unexpected bodies (peer not found)", peer_id);
return Ok(());
}
};
let item_count = r.item_count()?;
trace!(target: "sync", "{} -> BlockReceipts ({} entries)", peer_id, item_count);
if item_count == 0 {
@ -438,7 +465,7 @@ impl SyncHandler {
Some(ref mut blocks) => blocks,
}
};
downloader.import_receipts(io, r)?;
downloader.import_receipts(r, expected_blocks.as_slice())?;
}
sync.collect_blocks(io, block_set);
Ok(())

View File

@ -109,7 +109,7 @@ use ethcore::client::{BlockChainClient, BlockStatus, BlockId, BlockChainInfo, Bl
use ethcore::snapshot::{RestorationStatus};
use sync_io::SyncIo;
use super::{WarpSync, SyncConfig};
use block_sync::{BlockDownloader, BlockDownloaderImportError as DownloaderImportError};
use block_sync::{BlockDownloader, DownloadAction};
use rand::Rng;
use snapshot::{Snapshot};
use api::{EthProtocolInfo as PeerInfoDigest, WARP_SYNC_PROTOCOL_ID};
@ -429,7 +429,7 @@ impl ChainSync {
peers: HashMap::new(),
handshaking_peers: HashMap::new(),
active_peers: HashSet::new(),
new_blocks: BlockDownloader::new(false, &chain_info.best_block_hash, chain_info.best_block_number),
new_blocks: BlockDownloader::new(BlockSet::NewBlocks, &chain_info.best_block_hash, chain_info.best_block_number),
old_blocks: None,
last_sent_block_number: 0,
network_id: config.network_id,
@ -638,13 +638,13 @@ impl ChainSync {
pub fn update_targets(&mut self, chain: &BlockChainClient) {
// Do not assume that the block queue/chain still has our last_imported_block
let chain = chain.chain_info();
self.new_blocks = BlockDownloader::new(false, &chain.best_block_hash, chain.best_block_number);
self.new_blocks = BlockDownloader::new(BlockSet::NewBlocks, &chain.best_block_hash, chain.best_block_number);
self.old_blocks = None;
if self.download_old_blocks {
if let (Some(ancient_block_hash), Some(ancient_block_number)) = (chain.ancient_block_hash, chain.ancient_block_number) {
trace!(target: "sync", "Downloading old blocks from {:?} (#{}) till {:?} (#{:?})", ancient_block_hash, ancient_block_number, chain.first_block_hash, chain.first_block_number);
let mut downloader = BlockDownloader::with_unlimited_reorg(true, &ancient_block_hash, ancient_block_number);
let mut downloader = BlockDownloader::new(BlockSet::OldBlocks, &ancient_block_hash, ancient_block_number);
if let Some(hash) = chain.first_block_hash {
trace!(target: "sync", "Downloader target set to {:?}", hash);
downloader.set_target(&hash);
@ -763,12 +763,10 @@ impl ChainSync {
}
}
// Only ask for old blocks if the peer has a higher difficulty than the last imported old block
let last_imported_old_block_difficulty = self.old_blocks.as_mut().and_then(|d| {
io.chain().block_total_difficulty(BlockId::Number(d.last_imported_block_number()))
});
// Only ask for old blocks if the peer has an equal or higher difficulty
let equal_or_higher_difficulty = peer_difficulty.map_or(false, |pd| pd >= syncing_difficulty);
if force || last_imported_old_block_difficulty.map_or(true, |ld| peer_difficulty.map_or(true, |pd| pd > ld)) {
if force || equal_or_higher_difficulty {
if let Some(request) = self.old_blocks.as_mut().and_then(|d| d.request_blocks(io, num_active_peers)) {
SyncRequester::request_blocks(self, io, peer_id, request, BlockSet::OldBlocks);
return;
@ -776,9 +774,9 @@ impl ChainSync {
} else {
trace!(
target: "sync",
"peer {:?} is not suitable for requesting old blocks, last_imported_old_block_difficulty={:?}, peer_difficulty={:?}",
"peer {:?} is not suitable for requesting old blocks, syncing_difficulty={:?}, peer_difficulty={:?}",
peer_id,
last_imported_old_block_difficulty,
syncing_difficulty,
peer_difficulty
);
self.deactivate_peer(io, peer_id);
@ -856,18 +854,39 @@ impl ChainSync {
fn collect_blocks(&mut self, io: &mut SyncIo, block_set: BlockSet) {
match block_set {
BlockSet::NewBlocks => {
if self.new_blocks.collect_blocks(io, self.state == SyncState::NewBlocks) == Err(DownloaderImportError::Invalid) {
self.restart(io);
if self.new_blocks.collect_blocks(io, self.state == SyncState::NewBlocks) == DownloadAction::Reset {
self.reset_downloads(block_set);
self.new_blocks.reset();
}
},
BlockSet::OldBlocks => {
if self.old_blocks.as_mut().map_or(false, |downloader| { downloader.collect_blocks(io, false) == Err(DownloaderImportError::Invalid) }) {
self.restart(io);
} else if self.old_blocks.as_ref().map_or(false, |downloader| { downloader.is_complete() }) {
let mut is_complete = false;
let mut download_action = DownloadAction::None;
if let Some(downloader) = self.old_blocks.as_mut() {
download_action = downloader.collect_blocks(io, false);
is_complete = downloader.is_complete();
}
if download_action == DownloadAction::Reset {
self.reset_downloads(block_set);
if let Some(downloader) = self.old_blocks.as_mut() {
downloader.reset();
}
}
if is_complete {
trace!(target: "sync", "Background block download is complete");
self.old_blocks = None;
}
}
};
}
/// Mark all outstanding requests as expired
fn reset_downloads(&mut self, block_set: BlockSet) {
trace!(target: "sync", "Resetting downloads for {:?}", block_set);
for (_, ref mut p) in self.peers.iter_mut().filter(|&(_, ref p)| p.block_set == Some(block_set)) {
p.reset_asking();
}
}

View File

@ -225,32 +225,28 @@ fn propagate_blocks() {
#[test]
fn restart_on_malformed_block() {
::env_logger::try_init().ok();
let mut net = TestNet::new(2);
net.peer(1).chain.add_blocks(10, EachBlockWith::Uncle);
net.peer(1).chain.corrupt_block(6);
net.peer(1).chain.add_blocks(5, EachBlockWith::Nothing);
net.peer(1).chain.add_block(EachBlockWith::Nothing, |mut header| {
header.set_extra_data(b"This extra data is way too long to be considered valid".to_vec());
header
});
net.sync_steps(20);
assert_eq!(net.peer(0).chain.chain_info().best_block_number, 5);
// This gets accepted just fine since the TestBlockChainClient performs no validation.
// Probably remove this test?
assert_eq!(net.peer(0).chain.chain_info().best_block_number, 6);
}
#[test]
fn restart_on_broken_chain() {
fn reject_on_broken_chain() {
let mut net = TestNet::new(2);
net.peer(1).chain.add_blocks(10, EachBlockWith::Uncle);
net.peer(1).chain.add_blocks(10, EachBlockWith::Nothing);
net.peer(1).chain.corrupt_block_parent(6);
net.sync_steps(20);
assert_eq!(net.peer(0).chain.chain_info().best_block_number, 5);
}
#[test]
fn high_td_attach() {
let mut net = TestNet::new(2);
net.peer(1).chain.add_blocks(10, EachBlockWith::Uncle);
net.peer(1).chain.corrupt_block_parent(6);
net.sync_steps(20);
assert_eq!(net.peer(0).chain.chain_info().best_block_number, 5);
assert_eq!(net.peer(0).chain.chain_info().best_block_number, 0);
}
#[test]