From 1e2769d07cd9b6ab2ba3556d327f9bfdad20e254 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Szil=C3=A1gyi?= Date: Thu, 20 Aug 2020 13:01:24 +0300 Subject: [PATCH 01/15] core: define and test chain rewind corner cases (#21409) * core: define and test chain reparation cornercases * core: write up a variety of set-head tests * core, eth: unify chain rollbacks, handle all the cases * core: make linter smile * core: remove commented out legacy code * core, eth/downloader: fix review comments * core: revert a removed recovery mechanism --- alfa.json | 138 ++ asd | 1 + core/blockchain.go | 208 ++- core/blockchain_repair_test.go | 1653 ++++++++++++++++++++++++ core/blockchain_sethead_test.go | 1949 +++++++++++++++++++++++++++++ core/blockchain_test.go | 46 +- core/headerchain.go | 52 +- core/rawdb/accessors_chain.go | 26 + core/rawdb/database.go | 17 + core/rawdb/freezer.go | 93 +- core/rawdb/schema.go | 3 + eth/downloader/downloader.go | 70 +- eth/downloader/downloader_test.go | 53 +- eth/sync.go | 61 +- foo | 141 +++ genesis.json | 88 ++ geth | 107 ++ hmmm | 27 + rc.json | 133 ++ start.sh | 25 + trie/sync.go | 6 +- 21 files changed, 4667 insertions(+), 230 deletions(-) create mode 100644 alfa.json create mode 100644 asd create mode 100644 core/blockchain_repair_test.go create mode 100644 core/blockchain_sethead_test.go create mode 100644 foo create mode 100644 genesis.json create mode 100644 geth create mode 100644 hmmm create mode 100644 rc.json create mode 100755 start.sh diff --git a/alfa.json b/alfa.json new file mode 100644 index 0000000000..3db4bc03ce --- /dev/null +++ b/alfa.json @@ -0,0 +1,138 @@ +{ + "config": { + "homesteadBlock": 0, + "eip150Block": 0, + "eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "eip155Block": 0, + "eip158Block": 0, + "byzantiumBlock": 0, + "constantinopleBlock": 0, + "petersburgBlock": 0, + "chainId": 44786, + "istanbul": { + "policy": 2, + "blockperiod": 5, + "requesttimeout": 10000, + "epoch": 17280, + "lookbackwindow": 12 + } + }, + "nonce": "0x0", + "timestamp": "0x5b843511", + "gasLimit": "0x8000000", + "extraData": "0x0000000000000000000000000000000000000000000000000000000000000000f905bbf8d294456f41406b32c45d59e539e4bba3d7898c3584da94dd1f519f63423045f526b8c83edc0eb4ba6434a494050f34537f5b2a00b9b9c752cb8500a3fce3da7d94cda518f6b5a797c3ec45d37c65b83e0b0748edca94b4e92c94a2712e98c020a81868264bde52c188cb94ae1ec841923811219b98aceb1db297aade2f46f394621843731fe33418007c06ee48cfd71e0ea828d9942a43f97f8bf959e31f69a894ebd80a88572c855394ad682035be6ab6f06e478d2bdab0eab6477b460e9430d060f129817c4de5fbc1366d53e19f43c8c64ff903d4b86011877b768127c8eb0f122fbe69553bc9d142d27c06a85c6eeb7b8b457f511e50c33a57fcbc5fd6d1823f69a111f8010151a17f6a8798a25343f5403b1e6a595c7d9698af3db78b013d26a761fc201b3cf793be5f0a0a849b3f68a8bfa81e7001b860d882cd4cc09109928e9517644d5303610155978cf5e3b7ad6122daa19c3dab3da8c439bc763d6d3eef18a38ebb0d3200664b94fab11adbb3f44b963969763b590af45931c482396be88a185214c9c8690615aae5197e852bc1d04b3dbd03ab80b86051588d46ba8998d944a30cde93bfe946e774ef1f6fe2fb559a74ffebf60d1ad967b876a038c6e312d0c20752cbc8440012293b6ea417f32a163caedeaaae7aad3c1b31be1fe86c405924b1be7d0aaae6f3ba567ee907d0d4c00dce5091442380b8601f2becc31c1f0141e8c5768c5f07d02d1342c086c037cce70aaf3629b40ea017884a81163f58697b020b21fe39c440006970bc1f52b847d7262599ae92ee7db45ad38efe5612c8ed42d9db9380da0769bab713f5259b7c015998296bf02a0a01b860d02ec615b916bba4fe7e65a3d79e607aa27bb5a84b0c2f242e9d8f379512cf40051a43030e55aca965d91c905b656d006434d95b7034bfc2e5e2ef7384e8cd640efae740558216f6f9db24c6d1acf755746dfbb68c76961593741105725d5680b860d6e86d5e73db3b3a2c96c6caa1a7e153e17adb13fb541943a44bfa90beab38aa73ad453d918fea2ba57c0a67115d0401c56946d8894f346d796864e9344fd1439dd1345de762f85d7e18e311b35c3cbe492886ef8bc872b4aabfa23c2e38a901b8601cf59939da60cdb9aff09f76e6070a17fa21356ca7016390ef4444243e12ab7ed7a233d7ca48b0d17870ba015a4410014e5cac8d456e03ec2908d347627d5e9ecd496ce990d10900ddc529300eef3d037e48d79f03ad2b6bcd48affe2ddf2681b8601cfe8876c0b89ef15128bb27eb69e7939b4a888b0a81195d5fd1bbda748a29838274e652dcf857f4090bb85343055300ca3e75a980b100403d3b6d34f62c6a86bbd75203391c63dd405725c69241a828e6892f623ed5b35c8dc132b032061201b860a6fc71d63c5adedb7b30b9e0ba3d83debf86d12ba235c13584a9cbad410f082030427be4f8a9127889979c3eea58860031af128deece487df5aef9d999c8dc2fb51f308eb1ee229e6bbd6860138d4fcf4209eb7bec62ca70dd8643104003c200b8606b7adb5d01e3fd72ae2c4ff17e6620dc383431e0ebe06c9af5b94207f380287429043e7bbe417b82d0aed2e43dc7b8002bb52886773e4a2c23bf0ebfd401471e8da3cf3a0a7e0949d9ad4de38138a787a975993ba311525ce8be331cd60d670080b8410000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f86480b86000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080f86480b86000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080", + "difficulty": "0x1", + "coinbase": "0x0000000000000000000000000000000000000000", + "alloc": { + "456f41406B32c45D59E539e4BBA3D7898c3584dA": { + "balance": "103010030000000000000000000" + }, + "DD1F519F63423045F526b8c83edC0eB4BA6434a4": { + "balance": "10011000000000000000000" + }, + "050f34537F5b2a00B9B9C752Cb8500a3fcE3DA7d": { + "balance": "10011000000000000000000" + }, + "Cda518F6b5a797C3EC45D37c65b83e0b0748eDca": { + "balance": "10011000000000000000000" + }, + "b4e92c94A2712e98c020A81868264bdE52C188Cb": { + "balance": "10011000000000000000000" + }, + "Ae1ec841923811219b98ACeB1db297AADE2F46F3": { + "balance": "10011000000000000000000" + }, + "621843731fe33418007C06ee48CfD71e0ea828d9": { + "balance": "10011000000000000000000" + }, + "2A43f97f8BF959E31F69A894ebD80A88572C8553": { + "balance": "10011000000000000000000" + }, + "AD682035bE6Ab6f06e478D2BDab0EAb6477B460E": { + "balance": "10011000000000000000000" + }, + "30D060F129817c4DE5fBc1366d53e19f43c8c64f": { + "balance": "10011000000000000000000" + }, + "22579CA45eE22E2E16dDF72D955D6cf4c767B0eF": { + "balance": "10011000000000000000000" + }, + "1173C5A50bf025e8356823a068E396ccF2bE696C": { + "balance": "10011000000000000000000" + }, + "40F71B525A96baa8d14Eaa7Bcd19929782659c64": { + "balance": "10011000000000000000000" + }, + "b923626C6f1d237252793FB2aA12BA21328C51BC": { + "balance": "10011000000000000000000" + }, + "B70f9ABf41F36B3ab60cc9aE1a85Ddda3C88D261": { + "balance": "10011000000000000000000" + }, + "d4369DB59eaDc4Cfa089c0a3c1004ceAb1b318D8": { + "balance": "10011000000000000000000" + }, + "2fd430d3a96eadc38cc1B38b6685C5f52Cf7a083": { + "balance": "10011000000000000000000" + }, + "Fecc71C8f33Ca5952534fd346ADdeDC38DBb9cb7": { + "balance": "10011000000000000000000" + }, + "0de78C89e7BF5060f28dd3f820C15C4A6A81AFB5": { + "balance": "10011000000000000000000" + }, + "75411b92fcE120C1e7fd171b1c2bF802f2E3CF48": { + "balance": "10011000000000000000000" + }, + "563433bD8357b06982Fe001df20B2b43393d21d2": { + "balance": "10011000000000000000000" + }, + "79dfB9d2367E7921d4139D7841d24ED82F48907F": { + "balance": "10011000000000000000000" + }, + "5809369FC5121a071eE67659a975e88ae40fBE3b": { + "balance": "10011000000000000000000" + }, + "7517E54a456bcc6c5c695B5d9f97EBc05d29a824": { + "balance": "10011000000000000000000" + }, + "B0a1A5Ffcb34E6Fa278D2b40613f0AE1042d32f8": { + "balance": "10011000000000000000000" + }, + "EeE9f4DDf49976251E84182AbfD3300Ee58D12aa": { + "balance": "10011000000000000000000" + }, + "Eb5Fd57f87a4e1c7bAa53ec1c0d021bb1710B743": { + "balance": "10011000000000000000000" + }, + "B7Dd51bFb73c5753778e5Af56f1D9669BCe6777F": { + "balance": "10011000000000000000000" + }, + "33C222BB13C63295AF32D6C91278AA34b573e776": { + "balance": "10011000000000000000000" + }, + "83c58603bF72DA067D7f6238E7bF390d91B2f531": { + "balance": "10011000000000000000000" + }, + "6651112198C0da05921355642a2B8dF1fA3Ede93": { + "balance": "10011000000000000000000" + }, + "4EE72A98549eA7CF774C3E2E1b39fF166b4b68BE": { + "balance": "10011000000000000000000" + }, + "840b32F30e1a3b2E8b9E6C0972eBa0148E22B847": { + "balance": "100000000000000000000" + }, + "000000000000000000000000000000000000ce10": { + "code": "0x60806040526004361061004a5760003560e01c806303386ba3146101e757806342404e0714610280578063bb913f41146102d7578063d29d44ee14610328578063f7e6af8014610379575b6000600160405180807f656970313936372e70726f78792e696d706c656d656e746174696f6e00000000815250601c019050604051809103902060001c0360001b9050600081549050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610136576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f4e6f20496d706c656d656e746174696f6e20736574000000000000000000000081525060200191505060405180910390fd5b61013f816103d0565b6101b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f496e76616c696420636f6e74726163742061646472657373000000000000000081525060200191505060405180910390fd5b60405136810160405236600082376000803683855af43d604051818101604052816000823e82600081146101e3578282f35b8282fd5b61027e600480360360408110156101fd57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019064010000000081111561023a57600080fd5b82018360208201111561024c57600080fd5b8035906020019184600183028401116401000000008311171561026e57600080fd5b909192939192939050505061041b565b005b34801561028c57600080fd5b506102956105c1565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156102e357600080fd5b50610326600480360360208110156102fa57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061060d565b005b34801561033457600080fd5b506103776004803603602081101561034b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506107bd565b005b34801561038557600080fd5b5061038e610871565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b60008060007fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47060001b9050833f915080821415801561041257506000801b8214155b92505050919050565b610423610871565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146104c3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f73656e64657220776173206e6f74206f776e657200000000000000000000000081525060200191505060405180910390fd5b6104cc8361060d565b600060608473ffffffffffffffffffffffffffffffffffffffff168484604051808383808284378083019250505092505050600060405180830381855af49150503d8060008114610539576040519150601f19603f3d011682016040523d82523d6000602084013e61053e565b606091505b508092508193505050816105ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f696e697469616c697a6174696f6e2063616c6c6261636b206661696c6564000081525060200191505060405180910390fd5b5050505050565b600080600160405180807f656970313936372e70726f78792e696d706c656d656e746174696f6e00000000815250601c019050604051809103902060001c0360001b9050805491505090565b610615610871565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146106b5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f73656e64657220776173206e6f74206f776e657200000000000000000000000081525060200191505060405180910390fd5b6000600160405180807f656970313936372e70726f78792e696d706c656d656e746174696f6e00000000815250601c019050604051809103902060001c0360001b9050610701826103d0565b610773576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f496e76616c696420636f6e74726163742061646472657373000000000000000081525060200191505060405180910390fd5b8181558173ffffffffffffffffffffffffffffffffffffffff167fab64f92ab780ecbf4f3866f57cee465ff36c89450dcce20237ca7a8d81fb7d1360405160405180910390a25050565b6107c5610871565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610865576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f73656e64657220776173206e6f74206f776e657200000000000000000000000081525060200191505060405180910390fd5b61086e816108bd565b50565b600080600160405180807f656970313936372e70726f78792e61646d696e000000000000000000000000008152506013019050604051809103902060001c0360001b9050805491505090565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610960576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f6f776e65722063616e6e6f74206265203000000000000000000000000000000081525060200191505060405180910390fd5b6000600160405180807f656970313936372e70726f78792e61646d696e000000000000000000000000008152506013019050604051809103902060001c0360001b90508181558173ffffffffffffffffffffffffffffffffffffffff167f50146d0e3c60aa1d17a70635b05494f864e86144a2201275021014fbf08bafe260405160405180910390a2505056fea165627a7a723058202fea0aaff5e8ef394bc5402f16883d44f3d1c8ecb844dbd140aa075b8492ee060029", + "storage": { + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "456f41406B32c45D59E539e4BBA3D7898c3584dA" + }, + "balance": "0" + } + }, + "number": "0x0", + "gasUsed": "0x0", + "mixHash": "0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000" +} \ No newline at end of file diff --git a/asd b/asd new file mode 100644 index 0000000000..d72af31460 --- /dev/null +++ b/asd @@ -0,0 +1 @@ +asd diff --git a/core/blockchain.go b/core/blockchain.go index 1bab34863e..66c5c03bcb 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -119,6 +119,16 @@ type CacheConfig struct { TrieTimeLimit time.Duration // Time limit after which to flush the current in-memory trie to disk } +// defaultCacheConfig are the default caching values if none are specified by the +// user (also used during testing). +var defaultCacheConfig = &CacheConfig{ + TrieCleanLimit: 256, + TrieDirtyLimit: 256, + TrieTimeLimit: 5 * time.Minute, + SnapshotLimit: 256, + SnapshotWait: true, +} + // BlockChain represents the canonical chain given a database with a genesis // block. The Blockchain manages chain imports, reverts, chain reorganisations. // @@ -186,11 +196,7 @@ type BlockChain struct { // Processor. func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *params.ChainConfig, engine consensus.Engine, vmConfig vm.Config, shouldPreserve func(block *types.Block) bool) (*BlockChain, error) { if cacheConfig == nil { - cacheConfig = &CacheConfig{ - TrieCleanLimit: 256, - TrieDirtyLimit: 256, - TrieTimeLimit: 5 * time.Minute, - } + cacheConfig = defaultCacheConfig } bodyCache, _ := lru.New(bodyCacheLimit) bodyRLPCache, _ := lru.New(bodyCacheLimit) @@ -240,14 +246,18 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par if bc.empty() { rawdb.InitDatabaseFromFreezer(bc.db) } - if err := bc.loadLastState(); err != nil { return nil, err } - // The first thing the node will do is reconstruct the verification data for - // the head block. Might as well do it in advance. - bc.engine.VerifyHeader(bc, bc.CurrentHeader(), true) - + // Make sure the state associated with the block is available + head := bc.CurrentBlock() + if _, err := state.New(head.Root(), bc.stateCache, bc.snaps); err != nil { + log.Warn("Head state missing, repairing", "number", head.Number(), "hash", head.Hash()) + if err := bc.SetHead(head.NumberU64()); err != nil { + return nil, err + } + } + // Ensure that a previous crash in SetHead doesn't leave extra ancients if frozen, err := bc.db.Ancients(); err == nil && frozen > 0 { var ( needRewind bool @@ -257,7 +267,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par // blockchain repair. If the head full block is even lower than the ancient // chain, truncate the ancient store. fullBlock := bc.CurrentBlock() - if fullBlock != nil && fullBlock != bc.genesisBlock && fullBlock.NumberU64() < frozen-1 { + if fullBlock != nil && fullBlock.Hash() != bc.genesisBlock.Hash() && fullBlock.NumberU64() < frozen-1 { needRewind = true low = fullBlock.NumberU64() } @@ -272,15 +282,17 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par } } if needRewind { - var hashes []common.Hash - previous := bc.CurrentHeader().Number.Uint64() - for i := low + 1; i <= bc.CurrentHeader().Number.Uint64(); i++ { - hashes = append(hashes, rawdb.ReadCanonicalHash(bc.db, i)) + log.Error("Truncating ancient chain", "from", bc.CurrentHeader().Number.Uint64(), "to", low) + if err := bc.SetHead(low); err != nil { + return nil, err } - bc.Rollback(hashes, true) - log.Warn("Truncate ancient chain", "from", previous, "to", low) } } + // The first thing the node will do is reconstruct the verification data for + // the head block (ethash cache or clique voting snapshot). Might as well do + // it in advance. + bc.engine.VerifyHeader(bc, bc.CurrentHeader(), true) + // Check the current state of the block hashes and make sure that we do not have any of the bad blocks in our chain for hash := range BadHashes { if header := bc.GetHeaderByHash(hash); header != nil { @@ -289,7 +301,9 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par // make sure the headerByNumber (if present) is in our current canonical chain if headerByNumber != nil && headerByNumber.Hash() == header.Hash() { log.Error("Found bad hash, rewinding chain", "number", header.Number, "hash", header.ParentHash) - bc.SetHead(header.Number.Uint64() - 1) + if err := bc.SetHead(header.Number.Uint64() - 1); err != nil { + return nil, err + } log.Error("Chain rewind was successful, resuming normal operation") } } @@ -344,15 +358,6 @@ func (bc *BlockChain) loadLastState() error { log.Warn("Head block missing, resetting chain", "hash", head) return bc.Reset() } - // Make sure the state associated with the block is available - if _, err := state.New(currentBlock.Root(), bc.stateCache); err != nil { - // Dangling block without a state associated, init from scratch - log.Warn("Head state missing, repairing chain", "number", currentBlock.Number(), "hash", currentBlock.Hash()) - if err := bc.repair(¤tBlock); err != nil { - return err - } - rawdb.WriteHeadBlockHash(bc.db, currentBlock.Hash()) - } // Everything seems to be fine, set as the head block bc.currentBlock.Store(currentBlock) headBlockGauge.Update(int64(currentBlock.NumberU64())) @@ -387,30 +392,48 @@ func (bc *BlockChain) loadLastState() error { log.Info("Loaded most recent local header", "number", currentHeader.Number, "hash", currentHeader.Hash(), "td", headerTd, "age", common.PrettyAge(time.Unix(int64(currentHeader.Time), 0))) log.Info("Loaded most recent local full block", "number", currentBlock.Number(), "hash", currentBlock.Hash(), "td", blockTd, "age", common.PrettyAge(time.Unix(int64(currentBlock.Time()), 0))) log.Info("Loaded most recent local fast block", "number", currentFastBlock.Number(), "hash", currentFastBlock.Hash(), "td", fastTd, "age", common.PrettyAge(time.Unix(int64(currentFastBlock.Time()), 0))) - + if pivot := rawdb.ReadLastPivotNumber(bc.db); pivot != nil { + log.Info("Loaded last fast-sync pivot marker", "number", *pivot) + } return nil } -// SetHead rewinds the local chain to a new head. In the case of headers, everything -// above the new head will be deleted and the new one set. In the case of blocks -// though, the head may be further rewound if block bodies are missing (non-archive -// nodes after a fast sync). +// SetHead rewinds the local chain to a new head. Depending on whether the node +// was fast synced or full synced and in which state, the method will try to +// delete minimal data from disk whilst retaining chain consistency. func (bc *BlockChain) SetHead(head uint64) error { - log.Warn("Rewinding blockchain", "target", head) - bc.chainmu.Lock() defer bc.chainmu.Unlock() - updateFn := func(db ethdb.KeyValueWriter, header *types.Header) { - // Rewind the block chain, ensuring we don't end up with a stateless head block - if currentBlock := bc.CurrentBlock(); currentBlock != nil && header.Number.Uint64() < currentBlock.NumberU64() { + // Retrieve the last pivot block to short circuit rollbacks beyond it and the + // current freezer limit to start nuking id underflown + pivot := rawdb.ReadLastPivotNumber(bc.db) + frozen, _ := bc.db.Ancients() + + updateFn := func(db ethdb.KeyValueWriter, header *types.Header) (uint64, bool) { + // Rewind the block chain, ensuring we don't end up with a stateless head + // block. Note, depth equality is permitted to allow using SetHead as a + // chain reparation mechanism without deleting any data! + if currentBlock := bc.CurrentBlock(); currentBlock != nil && header.Number.Uint64() <= currentBlock.NumberU64() { newHeadBlock := bc.GetBlock(header.Hash(), header.Number.Uint64()) if newHeadBlock == nil { + log.Error("Gap in the chain, rewinding to genesis", "number", header.Number, "hash", header.Hash()) newHeadBlock = bc.genesisBlock } else { - if _, err := state.New(newHeadBlock.Root(), bc.stateCache); err != nil { - // Rewound state missing, rolled back to before pivot, reset to genesis - newHeadBlock = bc.genesisBlock + // Block exists, keep rewinding until we find one with state + for { + if _, err := state.New(newHeadBlock.Root(), bc.stateCache, bc.snaps); err != nil { + log.Trace("Block state missing, rewinding further", "number", newHeadBlock.NumberU64(), "hash", newHeadBlock.Hash()) + if pivot == nil || newHeadBlock.NumberU64() > *pivot { + newHeadBlock = bc.GetBlock(newHeadBlock.ParentHash(), newHeadBlock.NumberU64()-1) + continue + } else { + log.Trace("Rewind passed pivot, aiming genesis", "number", newHeadBlock.NumberU64(), "hash", newHeadBlock.Hash(), "pivot", *pivot) + newHeadBlock = bc.genesisBlock + } + } + log.Debug("Rewound to block with state", "number", newHeadBlock.NumberU64(), "hash", newHeadBlock.Hash()) + break } } rawdb.WriteHeadBlockHash(db, newHeadBlock.Hash()) @@ -422,7 +445,6 @@ func (bc *BlockChain) SetHead(head uint64) error { bc.currentBlock.Store(newHeadBlock) headBlockGauge.Update(int64(newHeadBlock.NumberU64())) } - // Rewind the fast block in a simpleton way to the target head if currentFastBlock := bc.CurrentFastBlock(); currentFastBlock != nil && header.Number.Uint64() < currentFastBlock.NumberU64() { newHeadFastBlock := bc.GetBlock(header.Hash(), header.Number.Uint64()) @@ -439,8 +461,17 @@ func (bc *BlockChain) SetHead(head uint64) error { bc.currentFastBlock.Store(newHeadFastBlock) headFastBlockGauge.Update(int64(newHeadFastBlock.NumberU64())) } - } + head := bc.CurrentBlock().NumberU64() + // If setHead underflown the freezer threshold and the block processing + // intent afterwards is full block importing, delete the chain segment + // between the stateful-block and the sethead target. + var wipe bool + if head+1 < frozen { + wipe = pivot == nil || head >= *pivot + } + return head, wipe // Only force wipe if full synced + } // Rewind the header chain, deleting all block bodies until then delFn := func(db ethdb.KeyValueWriter, hash common.Hash, num uint64) { // Ignore the error here since light client won't hit this path @@ -448,10 +479,9 @@ func (bc *BlockChain) SetHead(head uint64) error { if num+1 <= frozen { // Truncate all relative data(header, total difficulty, body, receipt // and canonical hash) from ancient store. - if err := bc.db.TruncateAncients(num + 1); err != nil { + if err := bc.db.TruncateAncients(num); err != nil { log.Crit("Failed to truncate ancient data", "number", num, "err", err) } - // Remove the hash <-> number mapping from the active store. rawdb.DeleteHeaderNumber(db, hash) } else { @@ -463,8 +493,18 @@ func (bc *BlockChain) SetHead(head uint64) error { } // Todo(rjl493456442) txlookup, bloombits, etc } - bc.hc.SetHead(head, updateFn, delFn) - + // If SetHead was only called as a chain reparation method, try to skip + // touching the header chain altogether, unless the freezer is broken + if block := bc.CurrentBlock(); block.NumberU64() == head { + if target, force := updateFn(bc.db, block.Header()); force { + bc.hc.SetHead(target, updateFn, delFn) + } + } else { + // Rewind the chain to the requested head and keep going backwards until a + // block with a state is found or fast sync pivot is passed + log.Warn("Rewinding blockchain", "target", head) + bc.hc.SetHead(head, updateFn, delFn) + } // Clear out any stale content from the caches bc.bodyCache.Purge() bc.bodyRLPCache.Purge() @@ -569,36 +609,6 @@ func (bc *BlockChain) ResetWithGenesisBlock(genesis *types.Block) error { return nil } -// repair tries to repair the current blockchain by rolling back the current block -// until one with associated state is found. This is needed to fix incomplete db -// writes caused either by crashes/power outages, or simply non-committed tries. -// -// This method only rolls back the current block. The current header and current -// fast block are left intact. -func (bc *BlockChain) repair(head **types.Block) error { - batch := bc.db.NewBatch() - - for { - // Abort if we've rewound to a head block that does have associated state - if _, err := state.New((*head).Root(), bc.stateCache); err == nil { - log.Info("Rewound blockchain to past state", "number", (*head).Number(), "hash", (*head).Hash()) - if err := batch.Write(); err != nil { - log.Error("Error when removing sidechain", "err", err) - } - bc.purge() - return nil - } - // Otherwise rewind one block and recheck state availability there - block := bc.GetBlock((*head).ParentHash(), (*head).NumberU64()-1) - if block == nil { - return fmt.Errorf("missing block %d [%x]", (*head).NumberU64()-1, (*head).ParentHash()) - } - // It's safest to remove these blocks - rawdb.DeleteBlock(batch, (*head).Hash(), (*head).NumberU64()) - *head = block - } -} - // Export writes the active chain to the given writer. func (bc *BlockChain) Export(w io.Writer) error { return bc.ExportN(w, uint64(0), bc.CurrentBlock().NumberU64()) @@ -893,52 +903,6 @@ const ( SideStatTy ) -// Rollback is designed to remove a chain of links from the database that aren't -// certain enough to be valid. -func (bc *BlockChain) Rollback(chain []common.Hash, fullHeaderChainAvailable bool) { - bc.chainmu.Lock() - defer bc.chainmu.Unlock() - - batch := bc.db.NewBatch() - for i := len(chain) - 1; i >= 0; i-- { - hash := chain[i] - - // Degrade the chain markers if they are explicitly reverted. - // In theory we should update all in-memory markers in the - // last step, however the direction of rollback is from high - // to low, so it's safe the update in-memory markers directly. - currentHeader := bc.hc.CurrentHeader() - if currentHeader.Hash() == hash { - newHeadHeader := bc.GetHeader(currentHeader.ParentHash, currentHeader.Number.Uint64()-1) - rawdb.WriteHeadHeaderHash(batch, currentHeader.ParentHash) - bc.hc.SetCurrentHeader(newHeadHeader) - } - if currentFastBlock := bc.CurrentFastBlock(); currentFastBlock.Hash() == hash { - newFastBlock := bc.GetBlock(currentFastBlock.ParentHash(), currentFastBlock.NumberU64()-1) - rawdb.WriteHeadFastBlockHash(batch, currentFastBlock.ParentHash()) - bc.currentFastBlock.Store(newFastBlock) - headFastBlockGauge.Update(int64(newFastBlock.NumberU64())) - } - if currentBlock := bc.CurrentBlock(); currentBlock.Hash() == hash { - newBlock := bc.GetBlock(currentBlock.ParentHash(), currentBlock.NumberU64()-1) - rawdb.WriteHeadBlockHash(batch, currentBlock.ParentHash()) - bc.currentBlock.Store(newBlock) - headBlockGauge.Update(int64(newBlock.NumberU64())) - } - } - if err := batch.Write(); err != nil { - log.Crit("Failed to rollback chain markers", "err", err) - } - // Truncate ancient data which exceeds the current header. - // - // Notably, it can happen that system crashes without truncating the ancient data - // but the head indicator has been updated in the active store. Regarding this issue, - // system will self recovery by truncating the extra data during the setup phase. - if err := bc.truncateAncient(bc.hc.CurrentHeader().Number.Uint64()); err != nil { - log.Crit("Truncate ancient store failed", "err", err) - } -} - // truncateAncient rewinds the blockchain to the specified header and deletes all // data in the ancient store that exceeds the specified header. func (bc *BlockChain) truncateAncient(head uint64) error { diff --git a/core/blockchain_repair_test.go b/core/blockchain_repair_test.go new file mode 100644 index 0000000000..27903dd06b --- /dev/null +++ b/core/blockchain_repair_test.go @@ -0,0 +1,1653 @@ +// Copyright 2020 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +// Tests that abnormal program termination (i.e.crash) and restart doesn't leave +// the database in some strange state with gaps in the chain, nor with block data +// dangling in the future. + +package core + +import ( + "io/ioutil" + "math/big" + "os" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/consensus/ethash" + "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/params" +) + +// Tests a recovery for a short canonical chain where a recent block was already +// committed to disk and then the process crashed. In this case we expect the full +// chain to be rolled back to the committed block, but the chain data itself left +// in the database for replaying. +func TestShortRepair(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) + // + // Frozen: none + // Commit: G, C4 + // Pivot : none + // + // CRASH + // + // ------------------------------ + // + // Expected in leveldb: + // G->C1->C2->C3->C4->C5->C6->C7->C8 + // + // Expected head header : C8 + // Expected head fast block: C8 + // Expected head block : C4 + testRepair(t, &rewindTest{ + canonicalBlocks: 8, + sidechainBlocks: 0, + freezeThreshold: 16, + commitBlock: 4, + pivotBlock: nil, + expCanonicalBlocks: 8, + expSidechainBlocks: 0, + expFrozen: 0, + expHeadHeader: 8, + expHeadFastBlock: 8, + expHeadBlock: 4, + }) +} + +// Tests a recovery for a short canonical chain where the fast sync pivot point was +// already committed, after which the process crashed. In this case we expect the full +// chain to be rolled back to the committed block, but the chain data itself left in +// the database for replaying. +func TestShortFastSyncedRepair(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) + // + // Frozen: none + // Commit: G, C4 + // Pivot : C4 + // + // CRASH + // + // ------------------------------ + // + // Expected in leveldb: + // G->C1->C2->C3->C4->C5->C6->C7->C8 + // + // Expected head header : C8 + // Expected head fast block: C8 + // Expected head block : C4 + testRepair(t, &rewindTest{ + canonicalBlocks: 8, + sidechainBlocks: 0, + freezeThreshold: 16, + commitBlock: 4, + pivotBlock: uint64ptr(4), + expCanonicalBlocks: 8, + expSidechainBlocks: 0, + expFrozen: 0, + expHeadHeader: 8, + expHeadFastBlock: 8, + expHeadBlock: 4, + }) +} + +// Tests a recovery for a short canonical chain where the fast sync pivot point was +// not yet committed, but the process crashed. In this case we expect the chain to +// detect that it was fast syncing and not delete anything, since we can just pick +// up directly where we left off. +func TestShortFastSyncingRepair(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) + // + // Frozen: none + // Commit: G + // Pivot : C4 + // + // CRASH + // + // ------------------------------ + // + // Expected in leveldb: + // G->C1->C2->C3->C4->C5->C6->C7->C8 + // + // Expected head header : C8 + // Expected head fast block: C8 + // Expected head block : G + testRepair(t, &rewindTest{ + canonicalBlocks: 8, + sidechainBlocks: 0, + freezeThreshold: 16, + commitBlock: 0, + pivotBlock: uint64ptr(4), + expCanonicalBlocks: 8, + expSidechainBlocks: 0, + expFrozen: 0, + expHeadHeader: 8, + expHeadFastBlock: 8, + expHeadBlock: 0, + }) +} + +// Tests a recovery for a short canonical chain and a shorter side chain, where a +// recent block was already committed to disk and then the process crashed. In this +// test scenario the side chain is below the committed block. In this case we expect +// the canonical chain to be rolled back to the committed block, but the chain data +// itself left in the database for replaying. +func TestShortOldForkedRepair(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) + // └->S1->S2->S3 + // + // Frozen: none + // Commit: G, C4 + // Pivot : none + // + // CRASH + // + // ------------------------------ + // + // Expected in leveldb: + // G->C1->C2->C3->C4->C5->C6->C7->C8 + // └->S1->S2->S3 + // + // Expected head header : C8 + // Expected head fast block: C8 + // Expected head block : C4 + testRepair(t, &rewindTest{ + canonicalBlocks: 8, + sidechainBlocks: 3, + freezeThreshold: 16, + commitBlock: 4, + pivotBlock: nil, + expCanonicalBlocks: 8, + expSidechainBlocks: 3, + expFrozen: 0, + expHeadHeader: 8, + expHeadFastBlock: 8, + expHeadBlock: 4, + }) +} + +// Tests a recovery for a short canonical chain and a shorter side chain, where +// the fast sync pivot point was already committed to disk and then the process +// crashed. In this test scenario the side chain is below the committed block. In +// this case we expect the canonical chain to be rolled back to the committed block, +// but the chain data itself left in the database for replaying. +func TestShortOldForkedFastSyncedRepair(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) + // └->S1->S2->S3 + // + // Frozen: none + // Commit: G, C4 + // Pivot : C4 + // + // CRASH + // + // ------------------------------ + // + // Expected in leveldb: + // G->C1->C2->C3->C4->C5->C6->C7->C8 + // └->S1->S2->S3 + // + // Expected head header : C8 + // Expected head fast block: C8 + // Expected head block : C4 + testRepair(t, &rewindTest{ + canonicalBlocks: 8, + sidechainBlocks: 3, + freezeThreshold: 16, + commitBlock: 4, + pivotBlock: uint64ptr(4), + expCanonicalBlocks: 8, + expSidechainBlocks: 3, + expFrozen: 0, + expHeadHeader: 8, + expHeadFastBlock: 8, + expHeadBlock: 4, + }) +} + +// Tests a recovery for a short canonical chain and a shorter side chain, where +// the fast sync pivot point was not yet committed, but the process crashed. In this +// test scenario the side chain is below the committed block. In this case we expect +// the chain to detect that it was fast syncing and not delete anything, since we +// can just pick up directly where we left off. +func TestShortOldForkedFastSyncingRepair(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) + // └->S1->S2->S3 + // + // Frozen: none + // Commit: G + // Pivot : C4 + // + // CRASH + // + // ------------------------------ + // + // Expected in leveldb: + // G->C1->C2->C3->C4->C5->C6->C7->C8 + // └->S1->S2->S3 + // + // Expected head header : C8 + // Expected head fast block: C8 + // Expected head block : G + testRepair(t, &rewindTest{ + canonicalBlocks: 8, + sidechainBlocks: 3, + freezeThreshold: 16, + commitBlock: 0, + pivotBlock: uint64ptr(4), + expCanonicalBlocks: 8, + expSidechainBlocks: 3, + expFrozen: 0, + expHeadHeader: 8, + expHeadFastBlock: 8, + expHeadBlock: 0, + }) +} + +// Tests a recovery for a short canonical chain and a shorter side chain, where a +// recent block was already committed to disk and then the process crashed. In this +// test scenario the side chain reaches above the committed block. In this case we +// expect the canonical chain to be rolled back to the committed block, but the +// chain data itself left in the database for replaying. +func TestShortNewlyForkedRepair(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) + // └->S1->S2->S3->S4->S5->S6 + // + // Frozen: none + // Commit: G, C4 + // Pivot : none + // + // CRASH + // + // ------------------------------ + // + // Expected in leveldb: + // G->C1->C2->C3->C4->C5->C6->C7->C8 + // └->S1->S2->S3->S4->S5->S6 + // + // Expected head header : C8 + // Expected head fast block: C8 + // Expected head block : C4 + testRepair(t, &rewindTest{ + canonicalBlocks: 8, + sidechainBlocks: 6, + freezeThreshold: 16, + commitBlock: 4, + pivotBlock: nil, + expCanonicalBlocks: 8, + expSidechainBlocks: 6, + expFrozen: 0, + expHeadHeader: 8, + expHeadFastBlock: 8, + expHeadBlock: 4, + }) +} + +// Tests a recovery for a short canonical chain and a shorter side chain, where +// the fast sync pivot point was already committed to disk and then the process +// crashed. In this test scenario the side chain reaches above the committed block. +// In this case we expect the canonical chain to be rolled back to the committed +// block, but the chain data itself left in the database for replaying. +func TestShortNewlyForkedFastSyncedRepair(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) + // └->S1->S2->S3->S4->S5->S6 + // + // Frozen: none + // Commit: G, C4 + // Pivot : C4 + // + // CRASH + // + // ------------------------------ + // + // Expected in leveldb: + // G->C1->C2->C3->C4->C5->C6->C7->C8 + // └->S1->S2->S3->S4->S5->S6 + // + // Expected head header : C8 + // Expected head fast block: C8 + // Expected head block : C4 + testRepair(t, &rewindTest{ + canonicalBlocks: 8, + sidechainBlocks: 6, + freezeThreshold: 16, + commitBlock: 4, + pivotBlock: uint64ptr(4), + expCanonicalBlocks: 8, + expSidechainBlocks: 6, + expFrozen: 0, + expHeadHeader: 8, + expHeadFastBlock: 8, + expHeadBlock: 4, + }) +} + +// Tests a recovery for a short canonical chain and a shorter side chain, where +// the fast sync pivot point was not yet committed, but the process crashed. In +// this test scenario the side chain reaches above the committed block. In this +// case we expect the chain to detect that it was fast syncing and not delete +// anything, since we can just pick up directly where we left off. +func TestShortNewlyForkedFastSyncingRepair(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) + // └->S1->S2->S3->S4->S5->S6 + // + // Frozen: none + // Commit: G + // Pivot : C4 + // + // CRASH + // + // ------------------------------ + // + // Expected in leveldb: + // G->C1->C2->C3->C4->C5->C6->C7->C8 + // └->S1->S2->S3->S4->S5->S6 + // + // Expected head header : C8 + // Expected head fast block: C8 + // Expected head block : G + testRepair(t, &rewindTest{ + canonicalBlocks: 8, + sidechainBlocks: 6, + freezeThreshold: 16, + commitBlock: 0, + pivotBlock: uint64ptr(4), + expCanonicalBlocks: 8, + expSidechainBlocks: 6, + expFrozen: 0, + expHeadHeader: 8, + expHeadFastBlock: 8, + expHeadBlock: 0, + }) +} + +// Tests a recovery for a short canonical chain and a longer side chain, where a +// recent block was already committed to disk and then the process crashed. In this +// case we expect the canonical chain to be rolled back to the committed block, but +// the chain data itself left in the database for replaying. +func TestShortReorgedRepair(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) + // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 + // + // Frozen: none + // Commit: G, C4 + // Pivot : none + // + // CRASH + // + // ------------------------------ + // + // Expected in leveldb: + // G->C1->C2->C3->C4->C5->C6->C7->C8 + // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 + // + // Expected head header : C8 + // Expected head fast block: C8 + // Expected head block : C4 + testRepair(t, &rewindTest{ + canonicalBlocks: 8, + sidechainBlocks: 10, + freezeThreshold: 16, + commitBlock: 4, + pivotBlock: nil, + expCanonicalBlocks: 8, + expSidechainBlocks: 10, + expFrozen: 0, + expHeadHeader: 8, + expHeadFastBlock: 8, + expHeadBlock: 4, + }) +} + +// Tests a recovery for a short canonical chain and a longer side chain, where +// the fast sync pivot point was already committed to disk and then the process +// crashed. In this case we expect the canonical chain to be rolled back to the +// committed block, but the chain data itself left in the database for replaying. +func TestShortReorgedFastSyncedRepair(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) + // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 + // + // Frozen: none + // Commit: G, C4 + // Pivot : C4 + // + // CRASH + // + // ------------------------------ + // + // Expected in leveldb: + // G->C1->C2->C3->C4->C5->C6->C7->C8 + // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 + // + // Expected head header : C8 + // Expected head fast block: C8 + // Expected head block : C4 + testRepair(t, &rewindTest{ + canonicalBlocks: 8, + sidechainBlocks: 10, + freezeThreshold: 16, + commitBlock: 4, + pivotBlock: uint64ptr(4), + expCanonicalBlocks: 8, + expSidechainBlocks: 10, + expFrozen: 0, + expHeadHeader: 8, + expHeadFastBlock: 8, + expHeadBlock: 4, + }) +} + +// Tests a recovery for a short canonical chain and a longer side chain, where +// the fast sync pivot point was not yet committed, but the process crashed. In +// this case we expect the chain to detect that it was fast syncing and not delete +// anything, since we can just pick up directly where we left off. +func TestShortReorgedFastSyncingRepair(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) + // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 + // + // Frozen: none + // Commit: G + // Pivot : C4 + // + // CRASH + // + // ------------------------------ + // + // Expected in leveldb: + // G->C1->C2->C3->C4->C5->C6->C7->C8 + // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 + // + // Expected head header : C8 + // Expected head fast block: C8 + // Expected head block : G + testRepair(t, &rewindTest{ + canonicalBlocks: 8, + sidechainBlocks: 10, + freezeThreshold: 16, + commitBlock: 0, + pivotBlock: uint64ptr(4), + expCanonicalBlocks: 8, + expSidechainBlocks: 10, + expFrozen: 0, + expHeadHeader: 8, + expHeadFastBlock: 8, + expHeadBlock: 0, + }) +} + +// Tests a recovery for a long canonical chain with frozen blocks where a recent +// block - newer than the ancient limit - was already committed to disk and then +// the process crashed. In this case we expect the chain to be rolled back to the +// committed block, with everything afterwads kept as fast sync data. +func TestLongShallowRepair(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) + // + // Frozen: + // G->C1->C2 + // + // Commit: G, C4 + // Pivot : none + // + // CRASH + // + // ------------------------------ + // + // Expected in freezer: + // G->C1->C2 + // + // Expected in leveldb: + // C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 + // + // Expected head header : C18 + // Expected head fast block: C18 + // Expected head block : C4 + testRepair(t, &rewindTest{ + canonicalBlocks: 18, + sidechainBlocks: 0, + freezeThreshold: 16, + commitBlock: 4, + pivotBlock: nil, + expCanonicalBlocks: 18, + expSidechainBlocks: 0, + expFrozen: 3, + expHeadHeader: 18, + expHeadFastBlock: 18, + expHeadBlock: 4, + }) +} + +// Tests a recovery for a long canonical chain with frozen blocks where a recent +// block - older than the ancient limit - was already committed to disk and then +// the process crashed. In this case we expect the chain to be rolled back to the +// committed block, with everything afterwads deleted. +func TestLongDeepRepair(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) + // + // Frozen: + // G->C1->C2->C3->C4->C5->C6->C7->C8 + // + // Commit: G, C4 + // Pivot : none + // + // CRASH + // + // ------------------------------ + // + // Expected in freezer: + // G->C1->C2->C3->C4 + // + // Expected in leveldb: none + // + // Expected head header : C4 + // Expected head fast block: C4 + // Expected head block : C4 + testRepair(t, &rewindTest{ + canonicalBlocks: 24, + sidechainBlocks: 0, + freezeThreshold: 16, + commitBlock: 4, + pivotBlock: nil, + expCanonicalBlocks: 4, + expSidechainBlocks: 0, + expFrozen: 5, + expHeadHeader: 4, + expHeadFastBlock: 4, + expHeadBlock: 4, + }) +} + +// Tests a recovery for a long canonical chain with frozen blocks where the fast +// sync pivot point - newer than the ancient limit - was already committed, after +// which the process crashed. In this case we expect the chain to be rolled back +// to the committed block, with everything afterwads kept as fast sync data. +func TestLongFastSyncedShallowRepair(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) + // + // Frozen: + // G->C1->C2 + // + // Commit: G, C4 + // Pivot : C4 + // + // CRASH + // + // ------------------------------ + // + // Expected in freezer: + // G->C1->C2 + // + // Expected in leveldb: + // C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 + // + // Expected head header : C18 + // Expected head fast block: C18 + // Expected head block : C4 + testRepair(t, &rewindTest{ + canonicalBlocks: 18, + sidechainBlocks: 0, + freezeThreshold: 16, + commitBlock: 4, + pivotBlock: uint64ptr(4), + expCanonicalBlocks: 18, + expSidechainBlocks: 0, + expFrozen: 3, + expHeadHeader: 18, + expHeadFastBlock: 18, + expHeadBlock: 4, + }) +} + +// Tests a recovery for a long canonical chain with frozen blocks where the fast +// sync pivot point - older than the ancient limit - was already committed, after +// which the process crashed. In this case we expect the chain to be rolled back +// to the committed block, with everything afterwads deleted. +func TestLongFastSyncedDeepRepair(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) + // + // Frozen: + // G->C1->C2->C3->C4->C5->C6->C7->C8 + // + // Commit: G, C4 + // Pivot : C4 + // + // CRASH + // + // ------------------------------ + // + // Expected in freezer: + // G->C1->C2->C3->C4 + // + // Expected in leveldb: none + // + // Expected head header : C4 + // Expected head fast block: C4 + // Expected head block : C4 + testRepair(t, &rewindTest{ + canonicalBlocks: 24, + sidechainBlocks: 0, + freezeThreshold: 16, + commitBlock: 4, + pivotBlock: uint64ptr(4), + expCanonicalBlocks: 4, + expSidechainBlocks: 0, + expFrozen: 5, + expHeadHeader: 4, + expHeadFastBlock: 4, + expHeadBlock: 4, + }) +} + +// Tests a recovery for a long canonical chain with frozen blocks where the fast +// sync pivot point - older than the ancient limit - was not yet committed, but the +// process crashed. In this case we expect the chain to detect that it was fast +// syncing and not delete anything, since we can just pick up directly where we +// left off. +func TestLongFastSyncingShallowRepair(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) + // + // Frozen: + // G->C1->C2 + // + // Commit: G + // Pivot : C4 + // + // CRASH + // + // ------------------------------ + // + // Expected in freezer: + // G->C1->C2 + // + // Expected in leveldb: + // C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 + // + // Expected head header : C18 + // Expected head fast block: C18 + // Expected head block : G + testRepair(t, &rewindTest{ + canonicalBlocks: 18, + sidechainBlocks: 0, + freezeThreshold: 16, + commitBlock: 0, + pivotBlock: uint64ptr(4), + expCanonicalBlocks: 18, + expSidechainBlocks: 0, + expFrozen: 3, + expHeadHeader: 18, + expHeadFastBlock: 18, + expHeadBlock: 0, + }) +} + +// Tests a recovery for a long canonical chain with frozen blocks where the fast +// sync pivot point - newer than the ancient limit - was not yet committed, but the +// process crashed. In this case we expect the chain to detect that it was fast +// syncing and not delete anything, since we can just pick up directly where we +// left off. +func TestLongFastSyncingDeepRepair(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) + // + // Frozen: + // G->C1->C2->C3->C4->C5->C6->C7->C8 + // + // Commit: G + // Pivot : C4 + // + // CRASH + // + // ------------------------------ + // + // Expected in freezer: + // G->C1->C2->C3->C4->C5->C6->C7->C8 + // + // Expected in leveldb: + // C8)->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 + // + // Expected head header : C24 + // Expected head fast block: C24 + // Expected head block : G + testRepair(t, &rewindTest{ + canonicalBlocks: 24, + sidechainBlocks: 0, + freezeThreshold: 16, + commitBlock: 0, + pivotBlock: uint64ptr(4), + expCanonicalBlocks: 24, + expSidechainBlocks: 0, + expFrozen: 9, + expHeadHeader: 24, + expHeadFastBlock: 24, + expHeadBlock: 0, + }) +} + +// Tests a recovery for a long canonical chain with frozen blocks and a shorter +// side chain, where a recent block - newer than the ancient limit - was already +// committed to disk and then the process crashed. In this test scenario the side +// chain is below the committed block. In this case we expect the chain to be +// rolled back to the committed block, with everything afterwads kept as fast +// sync data; the side chain completely nuked by the freezer. +func TestLongOldForkedShallowRepair(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) + // └->S1->S2->S3 + // + // Frozen: + // G->C1->C2 + // + // Commit: G, C4 + // Pivot : none + // + // CRASH + // + // ------------------------------ + // + // Expected in freezer: + // G->C1->C2 + // + // Expected in leveldb: + // C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 + // + // Expected head header : C18 + // Expected head fast block: C18 + // Expected head block : C4 + testRepair(t, &rewindTest{ + canonicalBlocks: 18, + sidechainBlocks: 3, + freezeThreshold: 16, + commitBlock: 4, + pivotBlock: nil, + expCanonicalBlocks: 18, + expSidechainBlocks: 0, + expFrozen: 3, + expHeadHeader: 18, + expHeadFastBlock: 18, + expHeadBlock: 4, + }) +} + +// Tests a recovery for a long canonical chain with frozen blocks and a shorter +// side chain, where a recent block - older than the ancient limit - was already +// committed to disk and then the process crashed. In this test scenario the side +// chain is below the committed block. In this case we expect the canonical chain +// to be rolled back to the committed block, with everything afterwads deleted; +// the side chain completely nuked by the freezer. +func TestLongOldForkedDeepRepair(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) + // └->S1->S2->S3 + // + // Frozen: + // G->C1->C2->C3->C4->C5->C6->C7->C8 + // + // Commit: G, C4 + // Pivot : none + // + // CRASH + // + // ------------------------------ + // + // Expected in freezer: + // G->C1->C2->C3->C4 + // + // Expected in leveldb: none + // + // Expected head header : C4 + // Expected head fast block: C4 + // Expected head block : C4 + testRepair(t, &rewindTest{ + canonicalBlocks: 24, + sidechainBlocks: 3, + freezeThreshold: 16, + commitBlock: 4, + pivotBlock: nil, + expCanonicalBlocks: 4, + expSidechainBlocks: 0, + expFrozen: 5, + expHeadHeader: 4, + expHeadFastBlock: 4, + expHeadBlock: 4, + }) +} + +// Tests a recovery for a long canonical chain with frozen blocks and a shorter +// side chain, where the fast sync pivot point - newer than the ancient limit - +// was already committed to disk and then the process crashed. In this test scenario +// the side chain is below the committed block. In this case we expect the chain +// to be rolled back to the committed block, with everything afterwads kept as +// fast sync data; the side chain completely nuked by the freezer. +func TestLongOldForkedFastSyncedShallowRepair(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) + // └->S1->S2->S3 + // + // Frozen: + // G->C1->C2 + // + // Commit: G, C4 + // Pivot : C4 + // + // CRASH + // + // ------------------------------ + // + // Expected in freezer: + // G->C1->C2 + // + // Expected in leveldb: + // C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 + // + // Expected head header : C18 + // Expected head fast block: C18 + // Expected head block : C4 + testRepair(t, &rewindTest{ + canonicalBlocks: 18, + sidechainBlocks: 3, + freezeThreshold: 16, + commitBlock: 4, + pivotBlock: uint64ptr(4), + expCanonicalBlocks: 18, + expSidechainBlocks: 0, + expFrozen: 3, + expHeadHeader: 18, + expHeadFastBlock: 18, + expHeadBlock: 4, + }) +} + +// Tests a recovery for a long canonical chain with frozen blocks and a shorter +// side chain, where the fast sync pivot point - older than the ancient limit - +// was already committed to disk and then the process crashed. In this test scenario +// the side chain is below the committed block. In this case we expect the canonical +// chain to be rolled back to the committed block, with everything afterwads deleted; +// the side chain completely nuked by the freezer. +func TestLongOldForkedFastSyncedDeepRepair(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) + // └->S1->S2->S3 + // + // Frozen: + // G->C1->C2->C3->C4->C5->C6->C7->C8 + // + // Commit: G, C4 + // Pivot : C4 + // + // CRASH + // + // ------------------------------ + // + // Expected in freezer: + // G->C1->C2->C3->C4 + // + // Expected in leveldb: none + // + // Expected head header : C4 + // Expected head fast block: C4 + // Expected head block : C4 + testRepair(t, &rewindTest{ + canonicalBlocks: 24, + sidechainBlocks: 3, + freezeThreshold: 16, + commitBlock: 4, + pivotBlock: uint64ptr(4), + expCanonicalBlocks: 4, + expSidechainBlocks: 0, + expFrozen: 5, + expHeadHeader: 4, + expHeadFastBlock: 4, + expHeadBlock: 4, + }) +} + +// Tests a recovery for a long canonical chain with frozen blocks and a shorter +// side chain, where the fast sync pivot point - older than the ancient limit - +// was not yet committed, but the process crashed. In this test scenario the side +// chain is below the committed block. In this case we expect the chain to detect +// that it was fast syncing and not delete anything. The side chain is completely +// nuked by the freezer. +func TestLongOldForkedFastSyncingShallowRepair(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) + // └->S1->S2->S3 + // + // Frozen: + // G->C1->C2 + // + // Commit: G + // Pivot : C4 + // + // CRASH + // + // ------------------------------ + // + // Expected in freezer: + // G->C1->C2 + // + // Expected in leveldb: + // C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 + // + // Expected head header : C18 + // Expected head fast block: C18 + // Expected head block : G + testRepair(t, &rewindTest{ + canonicalBlocks: 18, + sidechainBlocks: 3, + freezeThreshold: 16, + commitBlock: 0, + pivotBlock: uint64ptr(4), + expCanonicalBlocks: 18, + expSidechainBlocks: 0, + expFrozen: 3, + expHeadHeader: 18, + expHeadFastBlock: 18, + expHeadBlock: 0, + }) +} + +// Tests a recovery for a long canonical chain with frozen blocks and a shorter +// side chain, where the fast sync pivot point - older than the ancient limit - +// was not yet committed, but the process crashed. In this test scenario the side +// chain is below the committed block. In this case we expect the chain to detect +// that it was fast syncing and not delete anything. The side chain is completely +// nuked by the freezer. +func TestLongOldForkedFastSyncingDeepRepair(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) + // └->S1->S2->S3 + // + // Frozen: + // G->C1->C2->C3->C4->C5->C6->C7->C8 + // + // Commit: G + // Pivot : C4 + // + // CRASH + // + // ------------------------------ + // + // Expected in freezer: + // G->C1->C2->C3->C4->C5->C6->C7->C8 + // + // Expected in leveldb: + // C8)->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 + // + // Expected head header : C24 + // Expected head fast block: C24 + // Expected head block : G + testRepair(t, &rewindTest{ + canonicalBlocks: 24, + sidechainBlocks: 3, + freezeThreshold: 16, + commitBlock: 0, + pivotBlock: uint64ptr(4), + expCanonicalBlocks: 24, + expSidechainBlocks: 0, + expFrozen: 9, + expHeadHeader: 24, + expHeadFastBlock: 24, + expHeadBlock: 0, + }) +} + +// Tests a recovery for a long canonical chain with frozen blocks and a shorter +// side chain, where a recent block - newer than the ancient limit - was already +// committed to disk and then the process crashed. In this test scenario the side +// chain is above the committed block. In this case we expect the chain to be +// rolled back to the committed block, with everything afterwads kept as fast +// sync data; the side chain completely nuked by the freezer. +func TestLongNewerForkedShallowRepair(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) + // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12 + // + // Frozen: + // G->C1->C2 + // + // Commit: G, C4 + // Pivot : none + // + // CRASH + // + // ------------------------------ + // + // Expected in freezer: + // G->C1->C2 + // + // Expected in leveldb: + // C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 + // + // Expected head header : C18 + // Expected head fast block: C18 + // Expected head block : C4 + testRepair(t, &rewindTest{ + canonicalBlocks: 18, + sidechainBlocks: 12, + freezeThreshold: 16, + commitBlock: 4, + pivotBlock: nil, + expCanonicalBlocks: 18, + expSidechainBlocks: 0, + expFrozen: 3, + expHeadHeader: 18, + expHeadFastBlock: 18, + expHeadBlock: 4, + }) +} + +// Tests a recovery for a long canonical chain with frozen blocks and a shorter +// side chain, where a recent block - older than the ancient limit - was already +// committed to disk and then the process crashed. In this test scenario the side +// chain is above the committed block. In this case we expect the canonical chain +// to be rolled back to the committed block, with everything afterwads deleted; +// the side chain completely nuked by the freezer. +func TestLongNewerForkedDeepRepair(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) + // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12 + // + // Frozen: + // G->C1->C2->C3->C4->C5->C6->C7->C8 + // + // Commit: G, C4 + // Pivot : none + // + // CRASH + // + // ------------------------------ + // + // Expected in freezer: + // G->C1->C2->C3->C4 + // + // Expected in leveldb: none + // + // Expected head header : C4 + // Expected head fast block: C4 + // Expected head block : C4 + testRepair(t, &rewindTest{ + canonicalBlocks: 24, + sidechainBlocks: 12, + freezeThreshold: 16, + commitBlock: 4, + pivotBlock: nil, + expCanonicalBlocks: 4, + expSidechainBlocks: 0, + expFrozen: 5, + expHeadHeader: 4, + expHeadFastBlock: 4, + expHeadBlock: 4, + }) +} + +// Tests a recovery for a long canonical chain with frozen blocks and a shorter +// side chain, where the fast sync pivot point - newer than the ancient limit - +// was already committed to disk and then the process crashed. In this test scenario +// the side chain is above the committed block. In this case we expect the chain +// to be rolled back to the committed block, with everything afterwads kept as fast +// sync data; the side chain completely nuked by the freezer. +func TestLongNewerForkedFastSyncedShallowRepair(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) + // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12 + // + // Frozen: + // G->C1->C2 + // + // Commit: G, C4 + // Pivot : C4 + // + // CRASH + // + // ------------------------------ + // + // Expected in freezer: + // G->C1->C2 + // + // Expected in leveldb: + // C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 + // + // Expected head header : C18 + // Expected head fast block: C18 + // Expected head block : C4 + testRepair(t, &rewindTest{ + canonicalBlocks: 18, + sidechainBlocks: 12, + freezeThreshold: 16, + commitBlock: 4, + pivotBlock: uint64ptr(4), + expCanonicalBlocks: 18, + expSidechainBlocks: 0, + expFrozen: 3, + expHeadHeader: 18, + expHeadFastBlock: 18, + expHeadBlock: 4, + }) +} + +// Tests a recovery for a long canonical chain with frozen blocks and a shorter +// side chain, where the fast sync pivot point - older than the ancient limit - +// was already committed to disk and then the process crashed. In this test scenario +// the side chain is above the committed block. In this case we expect the canonical +// chain to be rolled back to the committed block, with everything afterwads deleted; +// the side chain completely nuked by the freezer. +func TestLongNewerForkedFastSyncedDeepRepair(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) + // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12 + // + // Frozen: + // G->C1->C2->C3->C4->C5->C6->C7->C8 + // + // Commit: G, C4 + // Pivot : C4 + // + // CRASH + // + // ------------------------------ + // + // Expected in freezer: + // G->C1->C2->C3->C4 + // + // Expected in leveldb: none + // + // Expected head header : C4 + // Expected head fast block: C4 + // Expected head block : C4 + testRepair(t, &rewindTest{ + canonicalBlocks: 24, + sidechainBlocks: 12, + freezeThreshold: 16, + commitBlock: 4, + pivotBlock: uint64ptr(4), + expCanonicalBlocks: 4, + expSidechainBlocks: 0, + expFrozen: 5, + expHeadHeader: 4, + expHeadFastBlock: 4, + expHeadBlock: 4, + }) +} + +// Tests a recovery for a long canonical chain with frozen blocks and a shorter +// side chain, where the fast sync pivot point - older than the ancient limit - +// was not yet committed, but the process crashed. In this test scenario the side +// chain is above the committed block. In this case we expect the chain to detect +// that it was fast syncing and not delete anything. The side chain is completely +// nuked by the freezer. +func TestLongNewerForkedFastSyncingShallowRepair(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) + // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12 + // + // Frozen: + // G->C1->C2 + // + // Commit: G + // Pivot : C4 + // + // CRASH + // + // ------------------------------ + // + // Expected in freezer: + // G->C1->C2 + // + // Expected in leveldb: + // C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 + // + // Expected head header : C18 + // Expected head fast block: C18 + // Expected head block : G + testRepair(t, &rewindTest{ + canonicalBlocks: 18, + sidechainBlocks: 12, + freezeThreshold: 16, + commitBlock: 0, + pivotBlock: uint64ptr(4), + expCanonicalBlocks: 18, + expSidechainBlocks: 0, + expFrozen: 3, + expHeadHeader: 18, + expHeadFastBlock: 18, + expHeadBlock: 0, + }) +} + +// Tests a recovery for a long canonical chain with frozen blocks and a shorter +// side chain, where the fast sync pivot point - older than the ancient limit - +// was not yet committed, but the process crashed. In this test scenario the side +// chain is above the committed block. In this case we expect the chain to detect +// that it was fast syncing and not delete anything. The side chain is completely +// nuked by the freezer. +func TestLongNewerForkedFastSyncingDeepRepair(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) + // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12 + // + // Frozen: + // G->C1->C2->C3->C4->C5->C6->C7->C8 + // + // Commit: G + // Pivot : C4 + // + // CRASH + // + // ------------------------------ + // + // Expected in freezer: + // G->C1->C2->C3->C4->C5->C6->C7->C8 + // + // Expected in leveldb: + // C8)->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 + // + // Expected head header : C24 + // Expected head fast block: C24 + // Expected head block : G + testRepair(t, &rewindTest{ + canonicalBlocks: 24, + sidechainBlocks: 12, + freezeThreshold: 16, + commitBlock: 0, + pivotBlock: uint64ptr(4), + expCanonicalBlocks: 24, + expSidechainBlocks: 0, + expFrozen: 9, + expHeadHeader: 24, + expHeadFastBlock: 24, + expHeadBlock: 0, + }) +} + +// Tests a recovery for a long canonical chain with frozen blocks and a longer side +// chain, where a recent block - newer than the ancient limit - was already committed +// to disk and then the process crashed. In this case we expect the chain to be +// rolled back to the committed block, with everything afterwads kept as fast sync +// data. The side chain completely nuked by the freezer. +func TestLongReorgedShallowRepair(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) + // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12->S13->S14->S15->S16->S17->S18->S19->S20->S21->S22->S23->S24->S25->S26 + // + // Frozen: + // G->C1->C2 + // + // Commit: G, C4 + // Pivot : none + // + // CRASH + // + // ------------------------------ + // + // Expected in freezer: + // G->C1->C2 + // + // Expected in leveldb: + // C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 + // + // Expected head header : C18 + // Expected head fast block: C18 + // Expected head block : C4 + testRepair(t, &rewindTest{ + canonicalBlocks: 18, + sidechainBlocks: 26, + freezeThreshold: 16, + commitBlock: 4, + pivotBlock: nil, + expCanonicalBlocks: 18, + expSidechainBlocks: 0, + expFrozen: 3, + expHeadHeader: 18, + expHeadFastBlock: 18, + expHeadBlock: 4, + }) +} + +// Tests a recovery for a long canonical chain with frozen blocks and a longer side +// chain, where a recent block - older than the ancient limit - was already committed +// to disk and then the process crashed. In this case we expect the canonical chains +// to be rolled back to the committed block, with everything afterwads deleted. The +// side chain completely nuked by the freezer. +func TestLongReorgedDeepRepair(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) + // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12->S13->S14->S15->S16->S17->S18->S19->S20->S21->S22->S23->S24->S25->S26 + // + // Frozen: + // G->C1->C2->C3->C4->C5->C6->C7->C8 + // + // Commit: G, C4 + // Pivot : none + // + // CRASH + // + // ------------------------------ + // + // Expected in freezer: + // G->C1->C2->C3->C4 + // + // Expected in leveldb: none + // + // Expected head header : C4 + // Expected head fast block: C4 + // Expected head block : C4 + testRepair(t, &rewindTest{ + canonicalBlocks: 24, + sidechainBlocks: 26, + freezeThreshold: 16, + commitBlock: 4, + pivotBlock: nil, + expCanonicalBlocks: 4, + expSidechainBlocks: 0, + expFrozen: 5, + expHeadHeader: 4, + expHeadFastBlock: 4, + expHeadBlock: 4, + }) +} + +// Tests a recovery for a long canonical chain with frozen blocks and a longer +// side chain, where the fast sync pivot point - newer than the ancient limit - +// was already committed to disk and then the process crashed. In this case we +// expect the chain to be rolled back to the committed block, with everything +// afterwads kept as fast sync data. The side chain completely nuked by the +// freezer. +func TestLongReorgedFastSyncedShallowRepair(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) + // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12->S13->S14->S15->S16->S17->S18->S19->S20->S21->S22->S23->S24->S25->S26 + // + // Frozen: + // G->C1->C2 + // + // Commit: G, C4 + // Pivot : C4 + // + // CRASH + // + // ------------------------------ + // + // Expected in freezer: + // G->C1->C2 + // + // Expected in leveldb: + // C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 + // + // Expected head header : C18 + // Expected head fast block: C18 + // Expected head block : C4 + testRepair(t, &rewindTest{ + canonicalBlocks: 18, + sidechainBlocks: 26, + freezeThreshold: 16, + commitBlock: 4, + pivotBlock: uint64ptr(4), + expCanonicalBlocks: 18, + expSidechainBlocks: 0, + expFrozen: 3, + expHeadHeader: 18, + expHeadFastBlock: 18, + expHeadBlock: 4, + }) +} + +// Tests a recovery for a long canonical chain with frozen blocks and a longer +// side chain, where the fast sync pivot point - older than the ancient limit - +// was already committed to disk and then the process crashed. In this case we +// expect the canonical chains to be rolled back to the committed block, with +// everything afterwads deleted. The side chain completely nuked by the freezer. +func TestLongReorgedFastSyncedDeepRepair(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) + // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12->S13->S14->S15->S16->S17->S18->S19->S20->S21->S22->S23->S24->S25->S26 + // + // Frozen: + // G->C1->C2->C3->C4->C5->C6->C7->C8 + // + // Commit: G, C4 + // Pivot : C4 + // + // CRASH + // + // ------------------------------ + // + // Expected in freezer: + // G->C1->C2->C3->C4 + // + // Expected in leveldb: none + // + // Expected head header : C4 + // Expected head fast block: C4 + // Expected head block : C4 + testRepair(t, &rewindTest{ + canonicalBlocks: 24, + sidechainBlocks: 26, + freezeThreshold: 16, + commitBlock: 4, + pivotBlock: uint64ptr(4), + expCanonicalBlocks: 4, + expSidechainBlocks: 0, + expFrozen: 5, + expHeadHeader: 4, + expHeadFastBlock: 4, + expHeadBlock: 4, + }) +} + +// Tests a recovery for a long canonical chain with frozen blocks and a longer +// side chain, where the fast sync pivot point - newer than the ancient limit - +// was not yet committed, but the process crashed. In this case we expect the +// chain to detect that it was fast syncing and not delete anything, since we +// can just pick up directly where we left off. +func TestLongReorgedFastSyncingShallowRepair(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) + // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12->S13->S14->S15->S16->S17->S18->S19->S20->S21->S22->S23->S24->S25->S26 + // + // Frozen: + // G->C1->C2 + // + // Commit: G + // Pivot : C4 + // + // CRASH + // + // ------------------------------ + // + // Expected in freezer: + // G->C1->C2 + // + // Expected in leveldb: + // C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 + // + // Expected head header : C18 + // Expected head fast block: C18 + // Expected head block : G + testRepair(t, &rewindTest{ + canonicalBlocks: 18, + sidechainBlocks: 26, + freezeThreshold: 16, + commitBlock: 0, + pivotBlock: uint64ptr(4), + expCanonicalBlocks: 18, + expSidechainBlocks: 0, + expFrozen: 3, + expHeadHeader: 18, + expHeadFastBlock: 18, + expHeadBlock: 0, + }) +} + +// Tests a recovery for a long canonical chain with frozen blocks and a longer +// side chain, where the fast sync pivot point - older than the ancient limit - +// was not yet committed, but the process crashed. In this case we expect the +// chain to detect that it was fast syncing and not delete anything, since we +// can just pick up directly where we left off. +func TestLongReorgedFastSyncingDeepRepair(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) + // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12->S13->S14->S15->S16->S17->S18->S19->S20->S21->S22->S23->S24->S25->S26 + // + // Frozen: + // G->C1->C2->C3->C4->C5->C6->C7->C8 + // + // Commit: G + // Pivot : C4 + // + // CRASH + // + // ------------------------------ + // + // Expected in freezer: + // G->C1->C2->C3->C4->C5->C6->C7->C8 + // + // Expected in leveldb: + // C8)->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 + // + // Expected head header : C24 + // Expected head fast block: C24 + // Expected head block : G + testRepair(t, &rewindTest{ + canonicalBlocks: 24, + sidechainBlocks: 26, + freezeThreshold: 16, + commitBlock: 0, + pivotBlock: uint64ptr(4), + expCanonicalBlocks: 24, + expSidechainBlocks: 0, + expFrozen: 9, + expHeadHeader: 24, + expHeadFastBlock: 24, + expHeadBlock: 0, + }) +} + +func testRepair(t *testing.T, tt *rewindTest) { + // It's hard to follow the test case, visualize the input + //log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true)))) + //fmt.Println(tt.dump(true)) + + // Create a temporary persistent database + datadir, err := ioutil.TempDir("", "") + if err != nil { + t.Fatalf("Failed to create temporary datadir: %v", err) + } + os.RemoveAll(datadir) + + db, err := rawdb.NewLevelDBDatabaseWithFreezer(datadir, 0, 0, datadir, "") + if err != nil { + t.Fatalf("Failed to create persistent database: %v", err) + } + defer db.Close() // Might double close, should be fine + + // Initialize a fresh chain + var ( + genesis = new(Genesis).MustCommit(db) + engine = ethash.NewFullFaker() + ) + chain, err := NewBlockChain(db, nil, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil) + if err != nil { + t.Fatalf("Failed to create chain: %v", err) + } + // If sidechain blocks are needed, make a light chain and import it + var sideblocks types.Blocks + if tt.sidechainBlocks > 0 { + sideblocks, _ = GenerateChain(params.TestChainConfig, genesis, engine, rawdb.NewMemoryDatabase(), tt.sidechainBlocks, func(i int, b *BlockGen) { + b.SetCoinbase(common.Address{0x01}) + }) + if _, err := chain.InsertChain(sideblocks); err != nil { + t.Fatalf("Failed to import side chain: %v", err) + } + } + canonblocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, rawdb.NewMemoryDatabase(), tt.canonicalBlocks, func(i int, b *BlockGen) { + b.SetCoinbase(common.Address{0x02}) + b.SetDifficulty(big.NewInt(1000000)) + }) + if _, err := chain.InsertChain(canonblocks[:tt.commitBlock]); err != nil { + t.Fatalf("Failed to import canonical chain start: %v", err) + } + if tt.commitBlock > 0 { + chain.stateCache.TrieDB().Commit(canonblocks[tt.commitBlock-1].Root(), true, nil) + } + if _, err := chain.InsertChain(canonblocks[tt.commitBlock:]); err != nil { + t.Fatalf("Failed to import canonical chain tail: %v", err) + } + // Force run a freeze cycle + type freezer interface { + Freeze(threshold uint64) + Ancients() (uint64, error) + } + db.(freezer).Freeze(tt.freezeThreshold) + + // Set the simulated pivot block + if tt.pivotBlock != nil { + rawdb.WriteLastPivotNumber(db, *tt.pivotBlock) + } + // Pull the plug on the database, simulating a hard crash + db.Close() + + // Start a new blockchain back up and see where the repait leads us + db, err = rawdb.NewLevelDBDatabaseWithFreezer(datadir, 0, 0, datadir, "") + if err != nil { + t.Fatalf("Failed to reopen persistent database: %v", err) + } + defer db.Close() + + chain, err = NewBlockChain(db, nil, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil) + if err != nil { + t.Fatalf("Failed to recreate chain: %v", err) + } + defer chain.Stop() + + // Iterate over all the remaining blocks and ensure there are no gaps + verifyNoGaps(t, chain, true, canonblocks) + verifyNoGaps(t, chain, false, sideblocks) + verifyCutoff(t, chain, true, canonblocks, tt.expCanonicalBlocks) + verifyCutoff(t, chain, false, sideblocks, tt.expSidechainBlocks) + + if head := chain.CurrentHeader(); head.Number.Uint64() != tt.expHeadHeader { + t.Errorf("Head header mismatch: have %d, want %d", head.Number, tt.expHeadHeader) + } + if head := chain.CurrentFastBlock(); head.NumberU64() != tt.expHeadFastBlock { + t.Errorf("Head fast block mismatch: have %d, want %d", head.NumberU64(), tt.expHeadFastBlock) + } + if head := chain.CurrentBlock(); head.NumberU64() != tt.expHeadBlock { + t.Errorf("Head block mismatch: have %d, want %d", head.NumberU64(), tt.expHeadBlock) + } + if frozen, err := db.(freezer).Ancients(); err != nil { + t.Errorf("Failed to retrieve ancient count: %v\n", err) + } else if int(frozen) != tt.expFrozen { + t.Errorf("Frozen block count mismatch: have %d, want %d", frozen, tt.expFrozen) + } +} diff --git a/core/blockchain_sethead_test.go b/core/blockchain_sethead_test.go new file mode 100644 index 0000000000..dc1368ff4b --- /dev/null +++ b/core/blockchain_sethead_test.go @@ -0,0 +1,1949 @@ +// Copyright 2020 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +// Tests that setting the chain head backwards doesn't leave the database in some +// strange state with gaps in the chain, nor with block data dangling in the future. + +package core + +import ( + "fmt" + "io/ioutil" + "math/big" + "os" + "strings" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/consensus/ethash" + "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/params" +) + +// rewindTest is a test case for chain rollback upon user request. +type rewindTest struct { + canonicalBlocks int // Number of blocks to generate for the canonical chain (heavier) + sidechainBlocks int // Number of blocks to generate for the side chain (lighter) + freezeThreshold uint64 // Block number until which to move things into the freezer + commitBlock uint64 // Block number for which to commit the state to disk + pivotBlock *uint64 // Pivot block number in case of fast sync + + setheadBlock uint64 // Block number to set head back to + expCanonicalBlocks int // Number of canonical blocks expected to remain in the database (excl. genesis) + expSidechainBlocks int // Number of sidechain blocks expected to remain in the database (excl. genesis) + expFrozen int // Number of canonical blocks expected to be in the freezer (incl. genesis) + expHeadHeader uint64 // Block number of the expected head header + expHeadFastBlock uint64 // Block number of the expected head fast sync block + expHeadBlock uint64 // Block number of the expected head full block +} + +func (tt *rewindTest) dump(crash bool) string { + buffer := new(strings.Builder) + + fmt.Fprint(buffer, "Chain:\n G") + for i := 0; i < tt.canonicalBlocks; i++ { + fmt.Fprintf(buffer, "->C%d", i+1) + } + fmt.Fprint(buffer, " (HEAD)\n") + if tt.sidechainBlocks > 0 { + fmt.Fprintf(buffer, " └") + for i := 0; i < tt.sidechainBlocks; i++ { + fmt.Fprintf(buffer, "->S%d", i+1) + } + fmt.Fprintf(buffer, "\n") + } + fmt.Fprintf(buffer, "\n") + + if tt.canonicalBlocks > int(tt.freezeThreshold) { + fmt.Fprint(buffer, "Frozen:\n G") + for i := 0; i < tt.canonicalBlocks-int(tt.freezeThreshold); i++ { + fmt.Fprintf(buffer, "->C%d", i+1) + } + fmt.Fprintf(buffer, "\n\n") + } else { + fmt.Fprintf(buffer, "Frozen: none\n") + } + fmt.Fprintf(buffer, "Commit: G") + if tt.commitBlock > 0 { + fmt.Fprintf(buffer, ", C%d", tt.commitBlock) + } + fmt.Fprint(buffer, "\n") + + if tt.pivotBlock == nil { + fmt.Fprintf(buffer, "Pivot : none\n") + } else { + fmt.Fprintf(buffer, "Pivot : C%d\n", *tt.pivotBlock) + } + if crash { + fmt.Fprintf(buffer, "\nCRASH\n\n") + } else { + fmt.Fprintf(buffer, "\nSetHead(%d)\n\n", tt.setheadBlock) + } + fmt.Fprintf(buffer, "------------------------------\n\n") + + if tt.expFrozen > 0 { + fmt.Fprint(buffer, "Expected in freezer:\n G") + for i := 0; i < tt.expFrozen-1; i++ { + fmt.Fprintf(buffer, "->C%d", i+1) + } + fmt.Fprintf(buffer, "\n\n") + } + if tt.expFrozen > 0 { + if tt.expFrozen >= tt.expCanonicalBlocks { + fmt.Fprintf(buffer, "Expected in leveldb: none\n") + } else { + fmt.Fprintf(buffer, "Expected in leveldb:\n C%d)", tt.expFrozen-1) + for i := tt.expFrozen - 1; i < tt.expCanonicalBlocks; i++ { + fmt.Fprintf(buffer, "->C%d", i+1) + } + fmt.Fprint(buffer, "\n") + if tt.expSidechainBlocks > tt.expFrozen { + fmt.Fprintf(buffer, " └") + for i := tt.expFrozen - 1; i < tt.expSidechainBlocks; i++ { + fmt.Fprintf(buffer, "->S%d", i+1) + } + fmt.Fprintf(buffer, "\n") + } + } + } else { + fmt.Fprint(buffer, "Expected in leveldb:\n G") + for i := tt.expFrozen; i < tt.expCanonicalBlocks; i++ { + fmt.Fprintf(buffer, "->C%d", i+1) + } + fmt.Fprint(buffer, "\n") + if tt.expSidechainBlocks > tt.expFrozen { + fmt.Fprintf(buffer, " └") + for i := tt.expFrozen; i < tt.expSidechainBlocks; i++ { + fmt.Fprintf(buffer, "->S%d", i+1) + } + fmt.Fprintf(buffer, "\n") + } + } + fmt.Fprintf(buffer, "\n") + fmt.Fprintf(buffer, "Expected head header : C%d\n", tt.expHeadHeader) + fmt.Fprintf(buffer, "Expected head fast block: C%d\n", tt.expHeadFastBlock) + if tt.expHeadBlock == 0 { + fmt.Fprintf(buffer, "Expected head block : G\n") + } else { + fmt.Fprintf(buffer, "Expected head block : C%d\n", tt.expHeadBlock) + } + return buffer.String() +} + +// Tests a sethead for a short canonical chain where a recent block was already +// committed to disk and then the sethead called. In this case we expect the full +// chain to be rolled back to the committed block. Everything above the sethead +// point should be deleted. In between the committed block and the requested head +// the data can remain as "fast sync" data to avoid redownloading it. +func TestShortSetHead(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) + // + // Frozen: none + // Commit: G, C4 + // Pivot : none + // + // SetHead(7) + // + // ------------------------------ + // + // Expected in leveldb: + // G->C1->C2->C3->C4->C5->C6->C7 + // + // Expected head header : C7 + // Expected head fast block: C7 + // Expected head block : C4 + testSetHead(t, &rewindTest{ + canonicalBlocks: 8, + sidechainBlocks: 0, + freezeThreshold: 16, + commitBlock: 4, + pivotBlock: nil, + setheadBlock: 7, + expCanonicalBlocks: 7, + expSidechainBlocks: 0, + expFrozen: 0, + expHeadHeader: 7, + expHeadFastBlock: 7, + expHeadBlock: 4, + }) +} + +// Tests a sethead for a short canonical chain where the fast sync pivot point was +// already committed, after which sethead was called. In this case we expect the +// chain to behave like in full sync mode, rolling back to the committed block +// Everything above the sethead point should be deleted. In between the committed +// block and the requested head the data can remain as "fast sync" data to avoid +// redownloading it. +func TestShortFastSyncedSetHead(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) + // + // Frozen: none + // Commit: G, C4 + // Pivot : C4 + // + // SetHead(7) + // + // ------------------------------ + // + // Expected in leveldb: + // G->C1->C2->C3->C4->C5->C6->C7 + // + // Expected head header : C7 + // Expected head fast block: C7 + // Expected head block : C4 + testSetHead(t, &rewindTest{ + canonicalBlocks: 8, + sidechainBlocks: 0, + freezeThreshold: 16, + commitBlock: 4, + pivotBlock: uint64ptr(4), + setheadBlock: 7, + expCanonicalBlocks: 7, + expSidechainBlocks: 0, + expFrozen: 0, + expHeadHeader: 7, + expHeadFastBlock: 7, + expHeadBlock: 4, + }) +} + +// Tests a sethead for a short canonical chain where the fast sync pivot point was +// not yet committed, but sethead was called. In this case we expect the chain to +// detect that it was fast syncing and delete everything from the new head, since +// we can just pick up fast syncing from there. The head full block should be set +// to the genesis. +func TestShortFastSyncingSetHead(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) + // + // Frozen: none + // Commit: G + // Pivot : C4 + // + // SetHead(7) + // + // ------------------------------ + // + // Expected in leveldb: + // G->C1->C2->C3->C4->C5->C6->C7 + // + // Expected head header : C7 + // Expected head fast block: C7 + // Expected head block : G + testSetHead(t, &rewindTest{ + canonicalBlocks: 8, + sidechainBlocks: 0, + freezeThreshold: 16, + commitBlock: 0, + pivotBlock: uint64ptr(4), + setheadBlock: 7, + expCanonicalBlocks: 7, + expSidechainBlocks: 0, + expFrozen: 0, + expHeadHeader: 7, + expHeadFastBlock: 7, + expHeadBlock: 0, + }) +} + +// Tests a sethead for a short canonical chain and a shorter side chain, where a +// recent block was already committed to disk and then sethead was called. In this +// test scenario the side chain is below the committed block. In this case we expect +// the canonical full chain to be rolled back to the committed block. Everything +// above the sethead point should be deleted. In between the committed block and +// the requested head the data can remain as "fast sync" data to avoid redownloading +// it. The side chain should be left alone as it was shorter. +func TestShortOldForkedSetHead(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) + // └->S1->S2->S3 + // + // Frozen: none + // Commit: G, C4 + // Pivot : none + // + // SetHead(7) + // + // ------------------------------ + // + // Expected in leveldb: + // G->C1->C2->C3->C4->C5->C6->C7 + // └->S1->S2->S3 + // + // Expected head header : C7 + // Expected head fast block: C7 + // Expected head block : C4 + testSetHead(t, &rewindTest{ + canonicalBlocks: 8, + sidechainBlocks: 3, + freezeThreshold: 16, + commitBlock: 4, + pivotBlock: nil, + setheadBlock: 7, + expCanonicalBlocks: 7, + expSidechainBlocks: 3, + expFrozen: 0, + expHeadHeader: 7, + expHeadFastBlock: 7, + expHeadBlock: 4, + }) +} + +// Tests a sethead for a short canonical chain and a shorter side chain, where +// the fast sync pivot point was already committed to disk and then sethead was +// called. In this test scenario the side chain is below the committed block. In +// this case we expect the canonical full chain to be rolled back to the committed +// block. Everything above the sethead point should be deleted. In between the +// committed block and the requested head the data can remain as "fast sync" data +// to avoid redownloading it. The side chain should be left alone as it was shorter. +func TestShortOldForkedFastSyncedSetHead(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) + // └->S1->S2->S3 + // + // Frozen: none + // Commit: G, C4 + // Pivot : C4 + // + // SetHead(7) + // + // ------------------------------ + // + // Expected in leveldb: + // G->C1->C2->C3->C4->C5->C6->C7 + // └->S1->S2->S3 + // + // Expected head header : C7 + // Expected head fast block: C7 + // Expected head block : C4 + testSetHead(t, &rewindTest{ + canonicalBlocks: 8, + sidechainBlocks: 3, + freezeThreshold: 16, + commitBlock: 4, + pivotBlock: uint64ptr(4), + setheadBlock: 7, + expCanonicalBlocks: 7, + expSidechainBlocks: 3, + expFrozen: 0, + expHeadHeader: 7, + expHeadFastBlock: 7, + expHeadBlock: 4, + }) +} + +// Tests a sethead for a short canonical chain and a shorter side chain, where +// the fast sync pivot point was not yet committed, but sethead was called. In this +// test scenario the side chain is below the committed block. In this case we expect +// the chain to detect that it was fast syncing and delete everything from the new +// head, since we can just pick up fast syncing from there. The head full block +// should be set to the genesis. +func TestShortOldForkedFastSyncingSetHead(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) + // └->S1->S2->S3 + // + // Frozen: none + // Commit: G + // Pivot : C4 + // + // SetHead(7) + // + // ------------------------------ + // + // Expected in leveldb: + // G->C1->C2->C3->C4->C5->C6->C7 + // └->S1->S2->S3 + // + // Expected head header : C7 + // Expected head fast block: C7 + // Expected head block : G + testSetHead(t, &rewindTest{ + canonicalBlocks: 8, + sidechainBlocks: 3, + freezeThreshold: 16, + commitBlock: 0, + pivotBlock: uint64ptr(4), + setheadBlock: 7, + expCanonicalBlocks: 7, + expSidechainBlocks: 3, + expFrozen: 0, + expHeadHeader: 7, + expHeadFastBlock: 7, + expHeadBlock: 0, + }) +} + +// Tests a sethead for a short canonical chain and a shorter side chain, where a +// recent block was already committed to disk and then sethead was called. In this +// test scenario the side chain reaches above the committed block. In this case we +// expect the canonical full chain to be rolled back to the committed block. All +// data above the sethead point should be deleted. In between the committed block +// and the requested head the data can remain as "fast sync" data to avoid having +// to redownload it. The side chain should be truncated to the head set. +// +// The side chain could be left to be if the fork point was before the new head +// we are deleting to, but it would be exceedingly hard to detect that case and +// properly handle it, so we'll trade extra work in exchange for simpler code. +func TestShortNewlyForkedSetHead(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10 (HEAD) + // └->S1->S2->S3->S4->S5->S6->S7->S8 + // + // Frozen: none + // Commit: G, C4 + // Pivot : none + // + // SetHead(7) + // + // ------------------------------ + // + // Expected in leveldb: + // G->C1->C2->C3->C4->C5->C6->C7 + // └->S1->S2->S3->S4->S5->S6->S7 + // + // Expected head header : C7 + // Expected head fast block: C7 + // Expected head block : C4 + testSetHead(t, &rewindTest{ + canonicalBlocks: 10, + sidechainBlocks: 8, + freezeThreshold: 16, + commitBlock: 4, + pivotBlock: nil, + setheadBlock: 7, + expCanonicalBlocks: 7, + expSidechainBlocks: 7, + expFrozen: 0, + expHeadHeader: 7, + expHeadFastBlock: 7, + expHeadBlock: 4, + }) +} + +// Tests a sethead for a short canonical chain and a shorter side chain, where +// the fast sync pivot point was already committed to disk and then sethead was +// called. In this case we expect the canonical full chain to be rolled back to +// between the committed block and the requested head the data can remain as +// "fast sync" data to avoid having to redownload it. The side chain should be +// truncated to the head set. +// +// The side chain could be left to be if the fork point was before the new head +// we are deleting to, but it would be exceedingly hard to detect that case and +// properly handle it, so we'll trade extra work in exchange for simpler code. +func TestShortNewlyForkedFastSyncedSetHead(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10 (HEAD) + // └->S1->S2->S3->S4->S5->S6->S7->S8 + // + // Frozen: none + // Commit: G, C4 + // Pivot : C4 + // + // SetHead(7) + // + // ------------------------------ + // + // Expected in leveldb: + // G->C1->C2->C3->C4->C5->C6->C7 + // └->S1->S2->S3->S4->S5->S6->S7 + // + // Expected head header : C7 + // Expected head fast block: C7 + // Expected head block : C4 + testSetHead(t, &rewindTest{ + canonicalBlocks: 10, + sidechainBlocks: 8, + freezeThreshold: 16, + commitBlock: 4, + pivotBlock: uint64ptr(4), + setheadBlock: 7, + expCanonicalBlocks: 7, + expSidechainBlocks: 7, + expFrozen: 0, + expHeadHeader: 7, + expHeadFastBlock: 7, + expHeadBlock: 4, + }) +} + +// Tests a sethead for a short canonical chain and a shorter side chain, where +// the fast sync pivot point was not yet committed, but sethead was called. In +// this test scenario the side chain reaches above the committed block. In this +// case we expect the chain to detect that it was fast syncing and delete +// everything from the new head, since we can just pick up fast syncing from +// there. +// +// The side chain could be left to be if the fork point was before the new head +// we are deleting to, but it would be exceedingly hard to detect that case and +// properly handle it, so we'll trade extra work in exchange for simpler code. +func TestShortNewlyForkedFastSyncingSetHead(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10 (HEAD) + // └->S1->S2->S3->S4->S5->S6->S7->S8 + // + // Frozen: none + // Commit: G + // Pivot : C4 + // + // SetHead(7) + // + // ------------------------------ + // + // Expected in leveldb: + // G->C1->C2->C3->C4->C5->C6->C7 + // └->S1->S2->S3->S4->S5->S6->S7 + // + // Expected head header : C7 + // Expected head fast block: C7 + // Expected head block : G + testSetHead(t, &rewindTest{ + canonicalBlocks: 10, + sidechainBlocks: 8, + freezeThreshold: 16, + commitBlock: 0, + pivotBlock: uint64ptr(4), + setheadBlock: 7, + expCanonicalBlocks: 7, + expSidechainBlocks: 7, + expFrozen: 0, + expHeadHeader: 7, + expHeadFastBlock: 7, + expHeadBlock: 0, + }) +} + +// Tests a sethead for a short canonical chain and a longer side chain, where a +// recent block was already committed to disk and then sethead was called. In this +// case we expect the canonical full chain to be rolled back to the committed block. +// All data above the sethead point should be deleted. In between the committed +// block and the requested head the data can remain as "fast sync" data to avoid +// having to redownload it. The side chain should be truncated to the head set. +// +// The side chain could be left to be if the fork point was before the new head +// we are deleting to, but it would be exceedingly hard to detect that case and +// properly handle it, so we'll trade extra work in exchange for simpler code. +func TestShortReorgedSetHead(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) + // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 + // + // Frozen: none + // Commit: G, C4 + // Pivot : none + // + // SetHead(7) + // + // ------------------------------ + // + // Expected in leveldb: + // G->C1->C2->C3->C4->C5->C6->C7 + // └->S1->S2->S3->S4->S5->S6->S7 + // + // Expected head header : C7 + // Expected head fast block: C7 + // Expected head block : C4 + testSetHead(t, &rewindTest{ + canonicalBlocks: 8, + sidechainBlocks: 10, + freezeThreshold: 16, + commitBlock: 4, + pivotBlock: nil, + setheadBlock: 7, + expCanonicalBlocks: 7, + expSidechainBlocks: 7, + expFrozen: 0, + expHeadHeader: 7, + expHeadFastBlock: 7, + expHeadBlock: 4, + }) +} + +// Tests a sethead for a short canonical chain and a longer side chain, where +// the fast sync pivot point was already committed to disk and then sethead was +// called. In this case we expect the canonical full chain to be rolled back to +// the committed block. All data above the sethead point should be deleted. In +// between the committed block and the requested head the data can remain as +// "fast sync" data to avoid having to redownload it. The side chain should be +// truncated to the head set. +// +// The side chain could be left to be if the fork point was before the new head +// we are deleting to, but it would be exceedingly hard to detect that case and +// properly handle it, so we'll trade extra work in exchange for simpler code. +func TestShortReorgedFastSyncedSetHead(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) + // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 + // + // Frozen: none + // Commit: G, C4 + // Pivot : C4 + // + // SetHead(7) + // + // ------------------------------ + // + // Expected in leveldb: + // G->C1->C2->C3->C4->C5->C6->C7 + // └->S1->S2->S3->S4->S5->S6->S7 + // + // Expected head header : C7 + // Expected head fast block: C7 + // Expected head block : C4 + testSetHead(t, &rewindTest{ + canonicalBlocks: 8, + sidechainBlocks: 10, + freezeThreshold: 16, + commitBlock: 4, + pivotBlock: uint64ptr(4), + setheadBlock: 7, + expCanonicalBlocks: 7, + expSidechainBlocks: 7, + expFrozen: 0, + expHeadHeader: 7, + expHeadFastBlock: 7, + expHeadBlock: 4, + }) +} + +// Tests a sethead for a short canonical chain and a longer side chain, where +// the fast sync pivot point was not yet committed, but sethead was called. In +// this case we expect the chain to detect that it was fast syncing and delete +// everything from the new head, since we can just pick up fast syncing from +// there. +// +// The side chain could be left to be if the fork point was before the new head +// we are deleting to, but it would be exceedingly hard to detect that case and +// properly handle it, so we'll trade extra work in exchange for simpler code. +func TestShortReorgedFastSyncingSetHead(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) + // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 + // + // Frozen: none + // Commit: G + // Pivot : C4 + // + // SetHead(7) + // + // ------------------------------ + // + // Expected in leveldb: + // G->C1->C2->C3->C4->C5->C6->C7 + // └->S1->S2->S3->S4->S5->S6->S7 + // + // Expected head header : C7 + // Expected head fast block: C7 + // Expected head block : G + testSetHead(t, &rewindTest{ + canonicalBlocks: 8, + sidechainBlocks: 10, + freezeThreshold: 16, + commitBlock: 0, + pivotBlock: uint64ptr(4), + setheadBlock: 7, + expCanonicalBlocks: 7, + expSidechainBlocks: 7, + expFrozen: 0, + expHeadHeader: 7, + expHeadFastBlock: 7, + expHeadBlock: 0, + }) +} + +// Tests a sethead for a long canonical chain with frozen blocks where a recent +// block - newer than the ancient limit - was already committed to disk and then +// sethead was called. In this case we expect the full chain to be rolled back +// to the committed block. Everything above the sethead point should be deleted. +// In between the committed block and the requested head the data can remain as +// "fast sync" data to avoid redownloading it. +func TestLongShallowSetHead(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) + // + // Frozen: + // G->C1->C2 + // + // Commit: G, C4 + // Pivot : none + // + // SetHead(6) + // + // ------------------------------ + // + // Expected in freezer: + // G->C1->C2 + // + // Expected in leveldb: + // C2)->C3->C4->C5->C6 + // + // Expected head header : C6 + // Expected head fast block: C6 + // Expected head block : C4 + testSetHead(t, &rewindTest{ + canonicalBlocks: 18, + sidechainBlocks: 0, + freezeThreshold: 16, + commitBlock: 4, + pivotBlock: nil, + setheadBlock: 6, + expCanonicalBlocks: 6, + expSidechainBlocks: 0, + expFrozen: 3, + expHeadHeader: 6, + expHeadFastBlock: 6, + expHeadBlock: 4, + }) +} + +// Tests a sethead for a long canonical chain with frozen blocks where a recent +// block - older than the ancient limit - was already committed to disk and then +// sethead was called. In this case we expect the full chain to be rolled back +// to the committed block. Since the ancient limit was underflown, everything +// needs to be deleted onwards to avoid creating a gap. +func TestLongDeepSetHead(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) + // + // Frozen: + // G->C1->C2->C3->C4->C5->C6->C7->C8 + // + // Commit: G, C4 + // Pivot : none + // + // SetHead(6) + // + // ------------------------------ + // + // Expected in freezer: + // G->C1->C2->C3->C4 + // + // Expected in leveldb: none + // + // Expected head header : C4 + // Expected head fast block: C4 + // Expected head block : C4 + testSetHead(t, &rewindTest{ + canonicalBlocks: 24, + sidechainBlocks: 0, + freezeThreshold: 16, + commitBlock: 4, + pivotBlock: nil, + setheadBlock: 6, + expCanonicalBlocks: 4, + expSidechainBlocks: 0, + expFrozen: 5, + expHeadHeader: 4, + expHeadFastBlock: 4, + expHeadBlock: 4, + }) +} + +// Tests a sethead for a long canonical chain with frozen blocks where the fast +// sync pivot point - newer than the ancient limit - was already committed, after +// which sethead was called. In this case we expect the full chain to be rolled +// back to the committed block. Everything above the sethead point should be +// deleted. In between the committed block and the requested head the data can +// remain as "fast sync" data to avoid redownloading it. +func TestLongFastSyncedShallowSetHead(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) + // + // Frozen: + // G->C1->C2 + // + // Commit: G, C4 + // Pivot : C4 + // + // SetHead(6) + // + // ------------------------------ + // + // Expected in freezer: + // G->C1->C2 + // + // Expected in leveldb: + // C2)->C3->C4->C5->C6 + // + // Expected head header : C6 + // Expected head fast block: C6 + // Expected head block : C4 + testSetHead(t, &rewindTest{ + canonicalBlocks: 18, + sidechainBlocks: 0, + freezeThreshold: 16, + commitBlock: 4, + pivotBlock: uint64ptr(4), + setheadBlock: 6, + expCanonicalBlocks: 6, + expSidechainBlocks: 0, + expFrozen: 3, + expHeadHeader: 6, + expHeadFastBlock: 6, + expHeadBlock: 4, + }) +} + +// Tests a sethead for a long canonical chain with frozen blocks where the fast +// sync pivot point - older than the ancient limit - was already committed, after +// which sethead was called. In this case we expect the full chain to be rolled +// back to the committed block. Since the ancient limit was underflown, everything +// needs to be deleted onwards to avoid creating a gap. +func TestLongFastSyncedDeepSetHead(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) + // + // Frozen: + // G->C1->C2->C3->C4->C5->C6->C7->C8 + // + // Commit: G, C4 + // Pivot : C4 + // + // SetHead(6) + // + // ------------------------------ + // + // Expected in freezer: + // G->C1->C2->C3->C4 + // + // Expected in leveldb: none + // + // Expected head header : C4 + // Expected head fast block: C4 + // Expected head block : C4 + testSetHead(t, &rewindTest{ + canonicalBlocks: 24, + sidechainBlocks: 0, + freezeThreshold: 16, + commitBlock: 4, + pivotBlock: uint64ptr(4), + setheadBlock: 6, + expCanonicalBlocks: 4, + expSidechainBlocks: 0, + expFrozen: 5, + expHeadHeader: 4, + expHeadFastBlock: 4, + expHeadBlock: 4, + }) +} + +// Tests a sethead for a long canonical chain with frozen blocks where the fast +// sync pivot point - newer than the ancient limit - was not yet committed, but +// sethead was called. In this case we expect the chain to detect that it was fast +// syncing and delete everything from the new head, since we can just pick up fast +// syncing from there. +func TestLongFastSyncingShallowSetHead(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) + // + // Frozen: + // G->C1->C2 + // + // Commit: G + // Pivot : C4 + // + // SetHead(6) + // + // ------------------------------ + // + // Expected in freezer: + // G->C1->C2 + // + // Expected in leveldb: + // C2)->C3->C4->C5->C6 + // + // Expected head header : C6 + // Expected head fast block: C6 + // Expected head block : G + testSetHead(t, &rewindTest{ + canonicalBlocks: 18, + sidechainBlocks: 0, + freezeThreshold: 16, + commitBlock: 0, + pivotBlock: uint64ptr(4), + setheadBlock: 6, + expCanonicalBlocks: 6, + expSidechainBlocks: 0, + expFrozen: 3, + expHeadHeader: 6, + expHeadFastBlock: 6, + expHeadBlock: 0, + }) +} + +// Tests a sethead for a long canonical chain with frozen blocks where the fast +// sync pivot point - older than the ancient limit - was not yet committed, but +// sethead was called. In this case we expect the chain to detect that it was fast +// syncing and delete everything from the new head, since we can just pick up fast +// syncing from there. +func TestLongFastSyncingDeepSetHead(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) + // + // Frozen: + // G->C1->C2->C3->C4->C5->C6->C7->C8 + // + // Commit: G + // Pivot : C4 + // + // SetHead(6) + // + // ------------------------------ + // + // Expected in freezer: + // G->C1->C2->C3->C4->C5->C6 + // + // Expected in leveldb: none + // + // Expected head header : C6 + // Expected head fast block: C6 + // Expected head block : G + testSetHead(t, &rewindTest{ + canonicalBlocks: 24, + sidechainBlocks: 0, + freezeThreshold: 16, + commitBlock: 0, + pivotBlock: uint64ptr(4), + setheadBlock: 6, + expCanonicalBlocks: 6, + expSidechainBlocks: 0, + expFrozen: 7, + expHeadHeader: 6, + expHeadFastBlock: 6, + expHeadBlock: 0, + }) +} + +// Tests a sethead for a long canonical chain with frozen blocks and a shorter side +// chain, where a recent block - newer than the ancient limit - was already committed +// to disk and then sethead was called. In this case we expect the canonical full +// chain to be rolled back to the committed block. Everything above the sethead point +// should be deleted. In between the committed block and the requested head the data +// can remain as "fast sync" data to avoid redownloading it. The side chain is nuked +// by the freezer. +func TestLongOldForkedShallowSetHead(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) + // └->S1->S2->S3 + // + // Frozen: + // G->C1->C2 + // + // Commit: G, C4 + // Pivot : none + // + // SetHead(6) + // + // ------------------------------ + // + // Expected in freezer: + // G->C1->C2 + // + // Expected in leveldb: + // C2)->C3->C4->C5->C6 + // + // Expected head header : C6 + // Expected head fast block: C6 + // Expected head block : C4 + testSetHead(t, &rewindTest{ + canonicalBlocks: 18, + sidechainBlocks: 3, + freezeThreshold: 16, + commitBlock: 4, + pivotBlock: nil, + setheadBlock: 6, + expCanonicalBlocks: 6, + expSidechainBlocks: 0, + expFrozen: 3, + expHeadHeader: 6, + expHeadFastBlock: 6, + expHeadBlock: 4, + }) +} + +// Tests a sethead for a long canonical chain with frozen blocks and a shorter side +// chain, where a recent block - older than the ancient limit - was already committed +// to disk and then sethead was called. In this case we expect the canonical full +// chain to be rolled back to the committed block. Since the ancient limit was +// underflown, everything needs to be deleted onwards to avoid creating a gap. The +// side chain is nuked by the freezer. +func TestLongOldForkedDeepSetHead(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) + // └->S1->S2->S3 + // + // Frozen: + // G->C1->C2->C3->C4->C5->C6->C7->C8 + // + // Commit: G, C4 + // Pivot : none + // + // SetHead(6) + // + // ------------------------------ + // + // Expected in freezer: + // G->C1->C2->C3->C4 + // + // Expected in leveldb: none + // + // Expected head header : C4 + // Expected head fast block: C4 + // Expected head block : C4 + testSetHead(t, &rewindTest{ + canonicalBlocks: 24, + sidechainBlocks: 3, + freezeThreshold: 16, + commitBlock: 4, + pivotBlock: nil, + setheadBlock: 6, + expCanonicalBlocks: 4, + expSidechainBlocks: 0, + expFrozen: 5, + expHeadHeader: 4, + expHeadFastBlock: 4, + expHeadBlock: 4, + }) +} + +// Tests a sethead for a long canonical chain with frozen blocks and a shorter +// side chain, where the fast sync pivot point - newer than the ancient limit - +// was already committed to disk and then sethead was called. In this test scenario +// the side chain is below the committed block. In this case we expect the canonical +// full chain to be rolled back to the committed block. Everything above the +// sethead point should be deleted. In between the committed block and the +// requested head the data can remain as "fast sync" data to avoid redownloading +// it. The side chain is nuked by the freezer. +func TestLongOldForkedFastSyncedShallowSetHead(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) + // └->S1->S2->S3 + // + // Frozen: + // G->C1->C2 + // + // Commit: G, C4 + // Pivot : C4 + // + // SetHead(6) + // + // ------------------------------ + // + // Expected in freezer: + // G->C1->C2 + // + // Expected in leveldb: + // C2)->C3->C4->C5->C6 + // + // Expected head header : C6 + // Expected head fast block: C6 + // Expected head block : C4 + testSetHead(t, &rewindTest{ + canonicalBlocks: 18, + sidechainBlocks: 3, + freezeThreshold: 16, + commitBlock: 4, + pivotBlock: uint64ptr(4), + setheadBlock: 6, + expCanonicalBlocks: 6, + expSidechainBlocks: 0, + expFrozen: 3, + expHeadHeader: 6, + expHeadFastBlock: 6, + expHeadBlock: 4, + }) +} + +// Tests a sethead for a long canonical chain with frozen blocks and a shorter +// side chain, where the fast sync pivot point - older than the ancient limit - +// was already committed to disk and then sethead was called. In this test scenario +// the side chain is below the committed block. In this case we expect the canonical +// full chain to be rolled back to the committed block. Since the ancient limit was +// underflown, everything needs to be deleted onwards to avoid creating a gap. The +// side chain is nuked by the freezer. +func TestLongOldForkedFastSyncedDeepSetHead(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) + // └->S1->S2->S3 + // + // Frozen: + // G->C1->C2->C3->C4->C5->C6->C7->C8 + // + // Commit: G, C4 + // Pivot : C4 + // + // SetHead(6) + // + // ------------------------------ + // + // Expected in freezer: + // G->C1->C2->C3->C4->C5->C6 + // + // Expected in leveldb: none + // + // Expected head header : C6 + // Expected head fast block: C6 + // Expected head block : C4 + testSetHead(t, &rewindTest{ + canonicalBlocks: 24, + sidechainBlocks: 3, + freezeThreshold: 16, + commitBlock: 4, + pivotBlock: uint64ptr(4), + setheadBlock: 6, + expCanonicalBlocks: 4, + expSidechainBlocks: 0, + expFrozen: 5, + expHeadHeader: 4, + expHeadFastBlock: 4, + expHeadBlock: 4, + }) +} + +// Tests a sethead for a long canonical chain with frozen blocks and a shorter +// side chain, where the fast sync pivot point - newer than the ancient limit - +// was not yet committed, but sethead was called. In this test scenario the side +// chain is below the committed block. In this case we expect the chain to detect +// that it was fast syncing and delete everything from the new head, since we can +// just pick up fast syncing from there. The side chain is completely nuked by the +// freezer. +func TestLongOldForkedFastSyncingShallowSetHead(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) + // └->S1->S2->S3 + // + // Frozen: + // G->C1->C2 + // + // Commit: G + // Pivot : C4 + // + // SetHead(6) + // + // ------------------------------ + // + // Expected in freezer: + // G->C1->C2 + // + // Expected in leveldb: + // C2)->C3->C4->C5->C6 + // + // Expected head header : C6 + // Expected head fast block: C6 + // Expected head block : G + testSetHead(t, &rewindTest{ + canonicalBlocks: 18, + sidechainBlocks: 3, + freezeThreshold: 16, + commitBlock: 0, + pivotBlock: uint64ptr(4), + setheadBlock: 6, + expCanonicalBlocks: 6, + expSidechainBlocks: 0, + expFrozen: 3, + expHeadHeader: 6, + expHeadFastBlock: 6, + expHeadBlock: 0, + }) +} + +// Tests a sethead for a long canonical chain with frozen blocks and a shorter +// side chain, where the fast sync pivot point - older than the ancient limit - +// was not yet committed, but sethead was called. In this test scenario the side +// chain is below the committed block. In this case we expect the chain to detect +// that it was fast syncing and delete everything from the new head, since we can +// just pick up fast syncing from there. The side chain is completely nuked by the +// freezer. +func TestLongOldForkedFastSyncingDeepSetHead(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) + // └->S1->S2->S3 + // + // Frozen: + // G->C1->C2->C3->C4->C5->C6->C7->C8 + // + // Commit: G + // Pivot : C4 + // + // SetHead(6) + // + // ------------------------------ + // + // Expected in freezer: + // G->C1->C2->C3->C4->C5->C6 + // + // Expected in leveldb: none + // + // Expected head header : C6 + // Expected head fast block: C6 + // Expected head block : G + testSetHead(t, &rewindTest{ + canonicalBlocks: 24, + sidechainBlocks: 3, + freezeThreshold: 16, + commitBlock: 0, + pivotBlock: uint64ptr(4), + setheadBlock: 6, + expCanonicalBlocks: 6, + expSidechainBlocks: 0, + expFrozen: 7, + expHeadHeader: 6, + expHeadFastBlock: 6, + expHeadBlock: 0, + }) +} + +// Tests a sethead for a long canonical chain with frozen blocks and a shorter +// side chain, where a recent block - newer than the ancient limit - was already +// committed to disk and then sethead was called. In this test scenario the side +// chain is above the committed block. In this case the freezer will delete the +// sidechain since it's dangling, reverting to TestLongShallowSetHead. +func TestLongNewerForkedShallowSetHead(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) + // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12 + // + // Frozen: + // G->C1->C2 + // + // Commit: G, C4 + // Pivot : none + // + // SetHead(6) + // + // ------------------------------ + // + // Expected in freezer: + // G->C1->C2 + // + // Expected in leveldb: + // C2)->C3->C4->C5->C6 + // + // Expected head header : C6 + // Expected head fast block: C6 + // Expected head block : C4 + testSetHead(t, &rewindTest{ + canonicalBlocks: 18, + sidechainBlocks: 12, + freezeThreshold: 16, + commitBlock: 4, + pivotBlock: nil, + setheadBlock: 6, + expCanonicalBlocks: 6, + expSidechainBlocks: 0, + expFrozen: 3, + expHeadHeader: 6, + expHeadFastBlock: 6, + expHeadBlock: 4, + }) +} + +// Tests a sethead for a long canonical chain with frozen blocks and a shorter +// side chain, where a recent block - older than the ancient limit - was already +// committed to disk and then sethead was called. In this test scenario the side +// chain is above the committed block. In this case the freezer will delete the +// sidechain since it's dangling, reverting to TestLongDeepSetHead. +func TestLongNewerForkedDeepSetHead(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) + // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12 + // + // Frozen: + // G->C1->C2->C3->C4->C5->C6->C7->C8 + // + // Commit: G, C4 + // Pivot : none + // + // SetHead(6) + // + // ------------------------------ + // + // Expected in freezer: + // G->C1->C2->C3->C4 + // + // Expected in leveldb: none + // + // Expected head header : C4 + // Expected head fast block: C4 + // Expected head block : C4 + testSetHead(t, &rewindTest{ + canonicalBlocks: 24, + sidechainBlocks: 12, + freezeThreshold: 16, + commitBlock: 4, + pivotBlock: nil, + setheadBlock: 6, + expCanonicalBlocks: 4, + expSidechainBlocks: 0, + expFrozen: 5, + expHeadHeader: 4, + expHeadFastBlock: 4, + expHeadBlock: 4, + }) +} + +// Tests a sethead for a long canonical chain with frozen blocks and a shorter +// side chain, where the fast sync pivot point - newer than the ancient limit - +// was already committed to disk and then sethead was called. In this test scenario +// the side chain is above the committed block. In this case the freezer will delete +// the sidechain since it's dangling, reverting to TestLongFastSyncedShallowSetHead. +func TestLongNewerForkedFastSyncedShallowSetHead(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) + // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12 + // + // Frozen: + // G->C1->C2 + // + // Commit: G, C4 + // Pivot : C4 + // + // SetHead(6) + // + // ------------------------------ + // + // Expected in freezer: + // G->C1->C2 + // + // Expected in leveldb: + // C2)->C3->C4->C5->C6 + // + // Expected head header : C6 + // Expected head fast block: C6 + // Expected head block : C4 + testSetHead(t, &rewindTest{ + canonicalBlocks: 18, + sidechainBlocks: 12, + freezeThreshold: 16, + commitBlock: 4, + pivotBlock: uint64ptr(4), + setheadBlock: 6, + expCanonicalBlocks: 6, + expSidechainBlocks: 0, + expFrozen: 3, + expHeadHeader: 6, + expHeadFastBlock: 6, + expHeadBlock: 4, + }) +} + +// Tests a sethead for a long canonical chain with frozen blocks and a shorter +// side chain, where the fast sync pivot point - older than the ancient limit - +// was already committed to disk and then sethead was called. In this test scenario +// the side chain is above the committed block. In this case the freezer will delete +// the sidechain since it's dangling, reverting to TestLongFastSyncedDeepSetHead. +func TestLongNewerForkedFastSyncedDeepSetHead(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) + // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12 + // + // Frozen: + // G->C1->C2->C3->C4->C5->C6->C7->C8 + // + // Commit: G, C4 + // Pivot : C4 + // + // SetHead(6) + // + // ------------------------------ + // + // Expected in freezer: + // G->C1->C2->C3->C4 + // + // Expected in leveldb: none + // + // Expected head header : C4 + // Expected head fast block: C4 + // Expected head block : C + testSetHead(t, &rewindTest{ + canonicalBlocks: 24, + sidechainBlocks: 12, + freezeThreshold: 16, + commitBlock: 4, + pivotBlock: uint64ptr(4), + setheadBlock: 6, + expCanonicalBlocks: 4, + expSidechainBlocks: 0, + expFrozen: 5, + expHeadHeader: 4, + expHeadFastBlock: 4, + expHeadBlock: 4, + }) +} + +// Tests a sethead for a long canonical chain with frozen blocks and a shorter +// side chain, where the fast sync pivot point - newer than the ancient limit - +// was not yet committed, but sethead was called. In this test scenario the side +// chain is above the committed block. In this case the freezer will delete the +// sidechain since it's dangling, reverting to TestLongFastSyncinghallowSetHead. +func TestLongNewerForkedFastSyncingShallowSetHead(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) + // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12 + // + // Frozen: + // G->C1->C2 + // + // Commit: G + // Pivot : C4 + // + // SetHead(6) + // + // ------------------------------ + // + // Expected in freezer: + // G->C1->C2 + // + // Expected in leveldb: + // C2)->C3->C4->C5->C6 + // + // Expected head header : C6 + // Expected head fast block: C6 + // Expected head block : G + testSetHead(t, &rewindTest{ + canonicalBlocks: 18, + sidechainBlocks: 12, + freezeThreshold: 16, + commitBlock: 0, + pivotBlock: uint64ptr(4), + setheadBlock: 6, + expCanonicalBlocks: 6, + expSidechainBlocks: 0, + expFrozen: 3, + expHeadHeader: 6, + expHeadFastBlock: 6, + expHeadBlock: 0, + }) +} + +// Tests a sethead for a long canonical chain with frozen blocks and a shorter +// side chain, where the fast sync pivot point - older than the ancient limit - +// was not yet committed, but sethead was called. In this test scenario the side +// chain is above the committed block. In this case the freezer will delete the +// sidechain since it's dangling, reverting to TestLongFastSyncingDeepSetHead. +func TestLongNewerForkedFastSyncingDeepSetHead(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) + // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12 + // + // Frozen: + // G->C1->C2->C3->C4->C5->C6->C7->C8 + // + // Commit: G + // Pivot : C4 + // + // SetHead(6) + // + // ------------------------------ + // + // Expected in freezer: + // G->C1->C2->C3->C4->C5->C6 + // + // Expected in leveldb: none + // + // Expected head header : C6 + // Expected head fast block: C6 + // Expected head block : G + testSetHead(t, &rewindTest{ + canonicalBlocks: 24, + sidechainBlocks: 12, + freezeThreshold: 16, + commitBlock: 0, + pivotBlock: uint64ptr(4), + setheadBlock: 6, + expCanonicalBlocks: 6, + expSidechainBlocks: 0, + expFrozen: 7, + expHeadHeader: 6, + expHeadFastBlock: 6, + expHeadBlock: 0, + }) +} + +// Tests a sethead for a long canonical chain with frozen blocks and a longer side +// chain, where a recent block - newer than the ancient limit - was already committed +// to disk and then sethead was called. In this case the freezer will delete the +// sidechain since it's dangling, reverting to TestLongShallowSetHead. +func TestLongReorgedShallowSetHead(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) + // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12->S13->S14->S15->S16->S17->S18->S19->S20->S21->S22->S23->S24->S25->S26 + // + // Frozen: + // G->C1->C2 + // + // Commit: G, C4 + // Pivot : none + // + // SetHead(6) + // + // ------------------------------ + // + // Expected in freezer: + // G->C1->C2 + // + // Expected in leveldb: + // C2)->C3->C4->C5->C6 + // + // Expected head header : C6 + // Expected head fast block: C6 + // Expected head block : C4 + testSetHead(t, &rewindTest{ + canonicalBlocks: 18, + sidechainBlocks: 26, + freezeThreshold: 16, + commitBlock: 4, + pivotBlock: nil, + setheadBlock: 6, + expCanonicalBlocks: 6, + expSidechainBlocks: 0, + expFrozen: 3, + expHeadHeader: 6, + expHeadFastBlock: 6, + expHeadBlock: 4, + }) +} + +// Tests a sethead for a long canonical chain with frozen blocks and a longer side +// chain, where a recent block - older than the ancient limit - was already committed +// to disk and then sethead was called. In this case the freezer will delete the +// sidechain since it's dangling, reverting to TestLongDeepSetHead. +func TestLongReorgedDeepSetHead(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) + // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12->S13->S14->S15->S16->S17->S18->S19->S20->S21->S22->S23->S24->S25->S26 + // + // Frozen: + // G->C1->C2->C3->C4->C5->C6->C7->C8 + // + // Commit: G, C4 + // Pivot : none + // + // SetHead(6) + // + // ------------------------------ + // + // Expected in freezer: + // G->C1->C2->C3->C4 + // + // Expected in leveldb: none + // + // Expected head header : C4 + // Expected head fast block: C4 + // Expected head block : C4 + testSetHead(t, &rewindTest{ + canonicalBlocks: 24, + sidechainBlocks: 26, + freezeThreshold: 16, + commitBlock: 4, + pivotBlock: nil, + setheadBlock: 6, + expCanonicalBlocks: 4, + expSidechainBlocks: 0, + expFrozen: 5, + expHeadHeader: 4, + expHeadFastBlock: 4, + expHeadBlock: 4, + }) +} + +// Tests a sethead for a long canonical chain with frozen blocks and a longer +// side chain, where the fast sync pivot point - newer than the ancient limit - +// was already committed to disk and then sethead was called. In this case the +// freezer will delete the sidechain since it's dangling, reverting to +// TestLongFastSyncedShallowSetHead. +func TestLongReorgedFastSyncedShallowSetHead(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) + // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12->S13->S14->S15->S16->S17->S18->S19->S20->S21->S22->S23->S24->S25->S26 + // + // Frozen: + // G->C1->C2 + // + // Commit: G, C4 + // Pivot : C4 + // + // SetHead(6) + // + // ------------------------------ + // + // Expected in freezer: + // G->C1->C2 + // + // Expected in leveldb: + // C2)->C3->C4->C5->C6 + // + // Expected head header : C6 + // Expected head fast block: C6 + // Expected head block : C4 + testSetHead(t, &rewindTest{ + canonicalBlocks: 18, + sidechainBlocks: 26, + freezeThreshold: 16, + commitBlock: 4, + pivotBlock: uint64ptr(4), + setheadBlock: 6, + expCanonicalBlocks: 6, + expSidechainBlocks: 0, + expFrozen: 3, + expHeadHeader: 6, + expHeadFastBlock: 6, + expHeadBlock: 4, + }) +} + +// Tests a sethead for a long canonical chain with frozen blocks and a longer +// side chain, where the fast sync pivot point - older than the ancient limit - +// was already committed to disk and then sethead was called. In this case the +// freezer will delete the sidechain since it's dangling, reverting to +// TestLongFastSyncedDeepSetHead. +func TestLongReorgedFastSyncedDeepSetHead(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) + // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12->S13->S14->S15->S16->S17->S18->S19->S20->S21->S22->S23->S24->S25->S26 + // + // Frozen: + // G->C1->C2->C3->C4->C5->C6->C7->C8 + // + // Commit: G, C4 + // Pivot : C4 + // + // SetHead(6) + // + // ------------------------------ + // + // Expected in freezer: + // G->C1->C2->C3->C4 + // + // Expected in leveldb: none + // + // Expected head header : C4 + // Expected head fast block: C4 + // Expected head block : C4 + testSetHead(t, &rewindTest{ + canonicalBlocks: 24, + sidechainBlocks: 26, + freezeThreshold: 16, + commitBlock: 4, + pivotBlock: uint64ptr(4), + setheadBlock: 6, + expCanonicalBlocks: 4, + expSidechainBlocks: 0, + expFrozen: 5, + expHeadHeader: 4, + expHeadFastBlock: 4, + expHeadBlock: 4, + }) +} + +// Tests a sethead for a long canonical chain with frozen blocks and a longer +// side chain, where the fast sync pivot point - newer than the ancient limit - +// was not yet committed, but sethead was called. In this case we expect the +// chain to detect that it was fast syncing and delete everything from the new +// head, since we can just pick up fast syncing from there. The side chain is +// completely nuked by the freezer. +func TestLongReorgedFastSyncingShallowSetHead(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) + // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12->S13->S14->S15->S16->S17->S18->S19->S20->S21->S22->S23->S24->S25->S26 + // + // Frozen: + // G->C1->C2 + // + // Commit: G + // Pivot : C4 + // + // SetHead(6) + // + // ------------------------------ + // + // Expected in freezer: + // G->C1->C2 + // + // Expected in leveldb: + // C2)->C3->C4->C5->C6 + // + // Expected head header : C6 + // Expected head fast block: C6 + // Expected head block : G + testSetHead(t, &rewindTest{ + canonicalBlocks: 18, + sidechainBlocks: 26, + freezeThreshold: 16, + commitBlock: 0, + pivotBlock: uint64ptr(4), + setheadBlock: 6, + expCanonicalBlocks: 6, + expSidechainBlocks: 0, + expFrozen: 3, + expHeadHeader: 6, + expHeadFastBlock: 6, + expHeadBlock: 0, + }) +} + +// Tests a sethead for a long canonical chain with frozen blocks and a longer +// side chain, where the fast sync pivot point - older than the ancient limit - +// was not yet committed, but sethead was called. In this case we expect the +// chain to detect that it was fast syncing and delete everything from the new +// head, since we can just pick up fast syncing from there. The side chain is +// completely nuked by the freezer. +func TestLongReorgedFastSyncingDeepSetHead(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) + // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12->S13->S14->S15->S16->S17->S18->S19->S20->S21->S22->S23->S24->S25->S26 + // + // Frozen: + // G->C1->C2->C3->C4->C5->C6->C7->C8 + // + // Commit: G + // Pivot : C4 + // + // SetHead(6) + // + // ------------------------------ + // + // Expected in freezer: + // G->C1->C2->C3->C4->C5->C6 + // + // Expected in leveldb: none + // + // Expected head header : C6 + // Expected head fast block: C6 + // Expected head block : G + testSetHead(t, &rewindTest{ + canonicalBlocks: 24, + sidechainBlocks: 26, + freezeThreshold: 16, + commitBlock: 0, + pivotBlock: uint64ptr(4), + setheadBlock: 6, + expCanonicalBlocks: 6, + expSidechainBlocks: 0, + expFrozen: 7, + expHeadHeader: 6, + expHeadFastBlock: 6, + expHeadBlock: 0, + }) +} + +func testSetHead(t *testing.T, tt *rewindTest) { + // It's hard to follow the test case, visualize the input + //log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true)))) + //fmt.Println(tt.dump(false)) + + // Create a temporary persistent database + datadir, err := ioutil.TempDir("", "") + if err != nil { + t.Fatalf("Failed to create temporary datadir: %v", err) + } + os.RemoveAll(datadir) + + db, err := rawdb.NewLevelDBDatabaseWithFreezer(datadir, 0, 0, datadir, "") + if err != nil { + t.Fatalf("Failed to create persistent database: %v", err) + } + defer db.Close() + + // Initialize a fresh chain + var ( + genesis = new(Genesis).MustCommit(db) + engine = ethash.NewFullFaker() + ) + chain, err := NewBlockChain(db, nil, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil) + if err != nil { + t.Fatalf("Failed to create chain: %v", err) + } + // If sidechain blocks are needed, make a light chain and import it + var sideblocks types.Blocks + if tt.sidechainBlocks > 0 { + sideblocks, _ = GenerateChain(params.TestChainConfig, genesis, engine, rawdb.NewMemoryDatabase(), tt.sidechainBlocks, func(i int, b *BlockGen) { + b.SetCoinbase(common.Address{0x01}) + }) + if _, err := chain.InsertChain(sideblocks); err != nil { + t.Fatalf("Failed to import side chain: %v", err) + } + } + canonblocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, rawdb.NewMemoryDatabase(), tt.canonicalBlocks, func(i int, b *BlockGen) { + b.SetCoinbase(common.Address{0x02}) + b.SetDifficulty(big.NewInt(1000000)) + }) + if _, err := chain.InsertChain(canonblocks[:tt.commitBlock]); err != nil { + t.Fatalf("Failed to import canonical chain start: %v", err) + } + if tt.commitBlock > 0 { + chain.stateCache.TrieDB().Commit(canonblocks[tt.commitBlock-1].Root(), true, nil) + } + if _, err := chain.InsertChain(canonblocks[tt.commitBlock:]); err != nil { + t.Fatalf("Failed to import canonical chain tail: %v", err) + } + // Manually dereference anything not committed to not have to work with 128+ tries + for _, block := range sideblocks { + chain.stateCache.TrieDB().Dereference(block.Root()) + } + for _, block := range canonblocks { + chain.stateCache.TrieDB().Dereference(block.Root()) + } + // Force run a freeze cycle + type freezer interface { + Freeze(threshold uint64) + Ancients() (uint64, error) + } + db.(freezer).Freeze(tt.freezeThreshold) + + // Set the simulated pivot block + if tt.pivotBlock != nil { + rawdb.WriteLastPivotNumber(db, *tt.pivotBlock) + } + // Set the head of the chain back to the requested number + chain.SetHead(tt.setheadBlock) + + // Iterate over all the remaining blocks and ensure there are no gaps + verifyNoGaps(t, chain, true, canonblocks) + verifyNoGaps(t, chain, false, sideblocks) + verifyCutoff(t, chain, true, canonblocks, tt.expCanonicalBlocks) + verifyCutoff(t, chain, false, sideblocks, tt.expSidechainBlocks) + + if head := chain.CurrentHeader(); head.Number.Uint64() != tt.expHeadHeader { + t.Errorf("Head header mismatch: have %d, want %d", head.Number, tt.expHeadHeader) + } + if head := chain.CurrentFastBlock(); head.NumberU64() != tt.expHeadFastBlock { + t.Errorf("Head fast block mismatch: have %d, want %d", head.NumberU64(), tt.expHeadFastBlock) + } + if head := chain.CurrentBlock(); head.NumberU64() != tt.expHeadBlock { + t.Errorf("Head block mismatch: have %d, want %d", head.NumberU64(), tt.expHeadBlock) + } + if frozen, err := db.(freezer).Ancients(); err != nil { + t.Errorf("Failed to retrieve ancient count: %v\n", err) + } else if int(frozen) != tt.expFrozen { + t.Errorf("Frozen block count mismatch: have %d, want %d", frozen, tt.expFrozen) + } +} + +// verifyNoGaps checks that there are no gaps after the initial set of blocks in +// the database and errors if found. +func verifyNoGaps(t *testing.T, chain *BlockChain, canonical bool, inserted types.Blocks) { + t.Helper() + + var end uint64 + for i := uint64(0); i <= uint64(len(inserted)); i++ { + header := chain.GetHeaderByNumber(i) + if header == nil && end == 0 { + end = i + } + if header != nil && end > 0 { + if canonical { + t.Errorf("Canonical header gap between #%d-#%d", end, i-1) + } else { + t.Errorf("Sidechain header gap between #%d-#%d", end, i-1) + } + end = 0 // Reset for further gap detection + } + } + end = 0 + for i := uint64(0); i <= uint64(len(inserted)); i++ { + block := chain.GetBlockByNumber(i) + if block == nil && end == 0 { + end = i + } + if block != nil && end > 0 { + if canonical { + t.Errorf("Canonical block gap between #%d-#%d", end, i-1) + } else { + t.Errorf("Sidechain block gap between #%d-#%d", end, i-1) + } + end = 0 // Reset for further gap detection + } + } + end = 0 + for i := uint64(1); i <= uint64(len(inserted)); i++ { + receipts := chain.GetReceiptsByHash(inserted[i-1].Hash()) + if receipts == nil && end == 0 { + end = i + } + if receipts != nil && end > 0 { + if canonical { + t.Errorf("Canonical receipt gap between #%d-#%d", end, i-1) + } else { + t.Errorf("Sidechain receipt gap between #%d-#%d", end, i-1) + } + end = 0 // Reset for further gap detection + } + } +} + +// verifyCutoff checks that there are no chain data available in the chain after +// the specified limit, but that it is available before. +func verifyCutoff(t *testing.T, chain *BlockChain, canonical bool, inserted types.Blocks, head int) { + t.Helper() + + for i := 1; i <= len(inserted); i++ { + if i <= head { + if header := chain.GetHeader(inserted[i-1].Hash(), uint64(i)); header == nil { + if canonical { + t.Errorf("Canonical header #%2d [%x...] missing before cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) + } else { + t.Errorf("Sidechain header #%2d [%x...] missing before cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) + } + } + if block := chain.GetBlock(inserted[i-1].Hash(), uint64(i)); block == nil { + if canonical { + t.Errorf("Canonical block #%2d [%x...] missing before cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) + } else { + t.Errorf("Sidechain block #%2d [%x...] missing before cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) + } + } + if receipts := chain.GetReceiptsByHash(inserted[i-1].Hash()); receipts == nil { + if canonical { + t.Errorf("Canonical receipts #%2d [%x...] missing before cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) + } else { + t.Errorf("Sidechain receipts #%2d [%x...] missing before cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) + } + } + } else { + if header := chain.GetHeader(inserted[i-1].Hash(), uint64(i)); header != nil { + if canonical { + t.Errorf("Canonical header #%2d [%x...] present after cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) + } else { + t.Errorf("Sidechain header #%2d [%x...] present after cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) + } + } + if block := chain.GetBlock(inserted[i-1].Hash(), uint64(i)); block != nil { + if canonical { + t.Errorf("Canonical block #%2d [%x...] present after cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) + } else { + t.Errorf("Sidechain block #%2d [%x...] present after cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) + } + } + if receipts := chain.GetReceiptsByHash(inserted[i-1].Hash()); receipts != nil { + if canonical { + t.Errorf("Canonical receipts #%2d [%x...] present after cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) + } else { + t.Errorf("Sidechain receipts #%2d [%x...] present after cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) + } + } + } + } +} + +// uint64ptr is a weird helper to allow 1-line constant pointer creation. +func uint64ptr(n uint64) *uint64 { + return &n +} diff --git a/core/blockchain_test.go b/core/blockchain_test.go index 7fc8898eb8..3b9ae856f2 100644 --- a/core/blockchain_test.go +++ b/core/blockchain_test.go @@ -811,12 +811,12 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) { return db, func() { os.RemoveAll(dir) } } // Configure a subchain to roll back - remove := []common.Hash{} - for _, block := range blocks[height/2:] { - remove = append(remove, block.Hash()) - } + remove := blocks[height/2].NumberU64() + // Create a small assertion method to check the three heads assert := func(t *testing.T, kind string, chain *BlockChain, header uint64, fast uint64, block uint64) { + t.Helper() + if num := chain.CurrentBlock().NumberU64(); num != block { t.Errorf("%s head block mismatch: have #%v, want #%v", kind, num, block) } @@ -830,14 +830,18 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) { // Import the chain as an archive node and ensure all pointers are updated archiveDb, delfn := makeDb() defer delfn() - archive, _ := NewBlockChain(archiveDb, nil, gspec.Config, mockEngine.NewFaker(), vm.Config{}, nil) + + archiveCaching := *defaultCacheConfig + archiveCaching.TrieDirtyDisabled = true + + archive, _ := NewBlockChain(archiveDb, &archiveCaching, gspec.Config, mockEngine.NewFaker(), vm.Config{}, nil, nil) if n, err := archive.InsertChain(blocks); err != nil { t.Fatalf("failed to process block %d: %v", n, err) } defer archive.Stop() assert(t, "archive", archive, height, height, height) - archive.Rollback(remove, true) + archive.SetHead(remove - 1) assert(t, "archive", archive, height/2, height/2, height/2) // Import the chain as a non-archive node and ensure all pointers are updated @@ -857,7 +861,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) { t.Fatalf("failed to insert receipt %d: %v", n, err) } assert(t, "fast", fast, height, height, 0) - fast.Rollback(remove, true) + fast.SetHead(remove - 1) assert(t, "fast", fast, height/2, height/2, 0) // Import the chain as a ancient-first node and ensure all pointers are updated @@ -873,12 +877,12 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) { t.Fatalf("failed to insert receipt %d: %v", n, err) } assert(t, "ancient", ancient, height, height, 0) - ancient.Rollback(remove, true) - assert(t, "ancient", ancient, height/2, height/2, 0) - if frozen, err := ancientDb.Ancients(); err != nil || frozen != height/2+1 { - t.Fatalf("failed to truncate ancient store, want %v, have %v", height/2+1, frozen) - } + ancient.SetHead(remove - 1) + assert(t, "ancient", ancient, 0, 0, 0) + if frozen, err := ancientDb.Ancients(); err != nil || frozen != 1 { + t.Fatalf("failed to truncate ancient store, want %v, have %v", 1, frozen) + } // Import the chain as a light node and ensure all pointers are updated lightDb, delfn := makeDb() defer delfn() @@ -889,7 +893,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) { defer light.Stop() assert(t, "light", light, height, 0, 0) - light.Rollback(remove, true) + light.SetHead(remove - 1) assert(t, "light", light, height/2, 0, 0) } @@ -1724,6 +1728,7 @@ func TestBlockchainRecovery(t *testing.T) { t.Fatalf("failed to create temp freezer dir: %v", err) } defer os.Remove(frdir) + ancientDb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), frdir, "") if err != nil { t.Fatalf("failed to create temp freezer db: %v", err) @@ -1741,6 +1746,7 @@ func TestBlockchainRecovery(t *testing.T) { if n, err := ancient.InsertReceiptChain(blocks, receipts, uint64(3*len(blocks)/4)); err != nil { t.Fatalf("failed to insert receipt %d: %v", n, err) } + rawdb.WriteLastPivotNumber(ancientDb, blocks[len(blocks)-1].NumberU64()) // Force fast sync behavior ancient.Stop() // Destroy head fast block manually @@ -2050,11 +2056,9 @@ func testInsertKnownChainData(t *testing.T, typ string) { asserter(t, blocks[len(blocks)-1]) // Import a long canonical chain with some known data as prefix. - var rollback []common.Hash - for i := len(blocks) / 2; i < len(blocks); i++ { - rollback = append(rollback, blocks[i].Hash()) - } - chain.Rollback(rollback, true) + rollback := blocks[len(blocks)/2].NumberU64() + + chain.SetHead(rollback - 1) if err := inserter(append(blocks, blocks2...), append(receipts, receipts2...)); err != nil { t.Fatalf("failed to insert chain data: %v", err) } @@ -2074,11 +2078,7 @@ func testInsertKnownChainData(t *testing.T, typ string) { asserter(t, blocks3[len(blocks3)-1]) // Rollback the heavier chain and re-insert the longer chain again - for i := 0; i < len(blocks3); i++ { - rollback = append(rollback, blocks3[i].Hash()) - } - chain.Rollback(rollback, true) - + chain.SetHead(rollback - 1) if err := inserter(append(blocks, blocks2...), append(receipts, receipts2...)); err != nil { t.Fatalf("failed to insert chain data: %v", err) } diff --git a/core/headerchain.go b/core/headerchain.go index fb61a8329e..70a6e0f29f 100644 --- a/core/headerchain.go +++ b/core/headerchain.go @@ -506,8 +506,10 @@ func (hc *HeaderChain) SetCurrentHeader(head *types.Header) { type ( // UpdateHeadBlocksCallback is a callback function that is called by SetHead - // before head header is updated. - UpdateHeadBlocksCallback func(ethdb.KeyValueWriter, *types.Header) + // before head header is updated. The method will return the actual block it + // updated the head to (missing state) and a flag if setHead should continue + // rewinding till that forcefully (exceeded ancient limits) + UpdateHeadBlocksCallback func(ethdb.KeyValueWriter, *types.Header) (uint64, bool) // DeleteBlockContentCallback is a callback function that is called by SetHead // before each header is deleted. @@ -520,9 +522,10 @@ func (hc *HeaderChain) SetHead(head uint64, updateFn UpdateHeadBlocksCallback, d var ( parentHash common.Hash batch = hc.chainDb.NewBatch() + origin = true ) for hdr := hc.CurrentHeader(); hdr != nil && hdr.Number.Uint64() > head; hdr = hc.CurrentHeader() { - hash, num := hdr.Hash(), hdr.Number.Uint64() + num := hdr.Number.Uint64() // Rewind block chain to new head. parent := hc.GetHeader(hdr.ParentHash, num-1) @@ -530,16 +533,21 @@ func (hc *HeaderChain) SetHead(head uint64, updateFn UpdateHeadBlocksCallback, d parent = hc.genesisHeader } parentHash = hdr.ParentHash + // Notably, since geth has the possibility for setting the head to a low // height which is even lower than ancient head. // In order to ensure that the head is always no higher than the data in - // the database(ancient store or active store), we need to update head + // the database (ancient store or active store), we need to update head // first then remove the relative data from the database. // // Update head first(head fast block, head full block) before deleting the data. markerBatch := hc.chainDb.NewBatch() if updateFn != nil { - updateFn(markerBatch, parent) + newHead, force := updateFn(markerBatch, parent) + if force && newHead < head { + log.Warn("Force rewinding till ancient limit", "head", newHead) + head = newHead + } } // Update head header then. rawdb.WriteHeadHeaderHash(markerBatch, parentHash) @@ -550,14 +558,34 @@ func (hc *HeaderChain) SetHead(head uint64, updateFn UpdateHeadBlocksCallback, d hc.currentHeaderHash = parentHash headHeaderGauge.Update(parent.Number.Int64()) - // Remove the relative data from the database. - if delFn != nil { - delFn(batch, hash, num) + // If this is the first iteration, wipe any leftover data upwards too so + // we don't end up with dangling daps in the database + var nums []uint64 + if origin { + for n := num + 1; len(rawdb.ReadAllHashes(hc.chainDb, n)) > 0; n++ { + nums = append([]uint64{n}, nums...) // suboptimal, but we don't really expect this path + } + origin = false + } + nums = append(nums, num) + + // Remove the related data from the database on all sidechains + for _, num := range nums { + // Gather all the side fork hashes + hashes := rawdb.ReadAllHashes(hc.chainDb, num) + if len(hashes) == 0 { + // No hashes in the database whatsoever, probably frozen already + hashes = append(hashes, hdr.Hash()) + } + for _, hash := range hashes { + if delFn != nil { + delFn(batch, hash, num) + } + rawdb.DeleteHeader(batch, hash, num) + rawdb.DeleteTd(batch, hash, num) + } + rawdb.DeleteCanonicalHash(batch, num) } - // Rewind header chain to new head. - rawdb.DeleteHeader(batch, hash, num) - rawdb.DeleteTd(batch, hash, num) - rawdb.DeleteCanonicalHash(batch, num) } // Flush all accumulated deletions. if err := batch.Write(); err != nil { diff --git a/core/rawdb/accessors_chain.go b/core/rawdb/accessors_chain.go index 28a4e1cc82..d4feb2fb5c 100644 --- a/core/rawdb/accessors_chain.go +++ b/core/rawdb/accessors_chain.go @@ -154,6 +154,32 @@ func WriteHeadFastBlockHash(db ethdb.KeyValueWriter, hash common.Hash) { } } +// ReadLastPivotNumber retrieves the number of the last pivot block. If the node +// full synced, the last pivot will always be nil. +func ReadLastPivotNumber(db ethdb.KeyValueReader) *uint64 { + data, _ := db.Get(lastPivotKey) + if len(data) == 0 { + return nil + } + var pivot uint64 + if err := rlp.DecodeBytes(data, &pivot); err != nil { + log.Error("Invalid pivot block number in database", "err", err) + return nil + } + return &pivot +} + +// WriteLastPivotNumber stores the number of the last pivot block. +func WriteLastPivotNumber(db ethdb.KeyValueWriter, pivot uint64) { + enc, err := rlp.EncodeToBytes(pivot) + if err != nil { + log.Crit("Failed to encode pivot block number", "err", err) + } + if err := db.Put(lastPivotKey, enc); err != nil { + log.Crit("Failed to store pivot block number", "err", err) + } +} + // ReadFastTrieProgress retrieves the number of tries nodes fast synced to allow // reporting correct numbers across restarts. func ReadFastTrieProgress(db ethdb.KeyValueReader) uint64 { diff --git a/core/rawdb/database.go b/core/rawdb/database.go index aea5bd51b0..fcc83bb349 100644 --- a/core/rawdb/database.go +++ b/core/rawdb/database.go @@ -21,6 +21,7 @@ import ( "errors" "fmt" "os" + "sync/atomic" "time" "github.com/ethereum/go-ethereum/common" @@ -53,6 +54,22 @@ func (frdb *freezerdb) Close() error { return nil } +// Freeze is a helper method used for external testing to trigger and block until +// a freeze cycle completes, without having to sleep for a minute to trigger the +// automatic background run. +func (frdb *freezerdb) Freeze(threshold uint64) { + // Set the freezer threshold to a temporary value + defer func(old uint64) { + atomic.StoreUint64(&frdb.AncientStore.(*freezer).threshold, old) + }(atomic.LoadUint64(&frdb.AncientStore.(*freezer).threshold)) + atomic.StoreUint64(&frdb.AncientStore.(*freezer).threshold, threshold) + + // Trigger a freeze cycle and block until it's done + trigger := make(chan struct{}, 1) + frdb.AncientStore.(*freezer).trigger <- trigger + <-trigger +} + // nofreezedb is a database wrapper that disables freezer data retrievals. type nofreezedb struct { ethdb.KeyValueStore diff --git a/core/rawdb/freezer.go b/core/rawdb/freezer.go index 5497c59d49..b2b51e9e62 100644 --- a/core/rawdb/freezer.go +++ b/core/rawdb/freezer.go @@ -69,10 +69,16 @@ type freezer struct { // WARNING: The `frozen` field is accessed atomically. On 32 bit platforms, only // 64-bit aligned fields can be atomic. The struct is guaranteed to be so aligned, // so take advantage of that (https://golang.org/pkg/sync/atomic/#pkg-note-BUG). - frozen uint64 // Number of blocks already frozen + frozen uint64 // Number of blocks already frozen + threshold uint64 // Number of recent blocks not to freeze (params.FullImmutabilityThreshold apart from tests) tables map[string]*freezerTable // Data tables for storing everything instanceLock fileutil.Releaser // File-system lock to prevent double opens + + trigger chan chan struct{} // Manual blocking freeze trigger, test determinism + + quit chan struct{} + closeOnce sync.Once } // newFreezer creates a chain freezer that moves ancient chain data into @@ -99,8 +105,11 @@ func newFreezer(datadir string, namespace string) (*freezer, error) { } // Open all the supported data tables freezer := &freezer{ + threshold: params.FullImmutabilityThreshold, tables: make(map[string]*freezerTable), instanceLock: lock, + trigger: make(chan chan struct{}), + quit: make(chan struct{}), } for name, disableSnappy := range freezerNoSnappy { table, err := newTable(datadir, name, readMeter, writeMeter, sizeGauge, disableSnappy) @@ -254,7 +263,32 @@ func (f *freezer) Sync() error { func (f *freezer) freeze(db ethdb.KeyValueStore) { nfdb := &nofreezedb{KeyValueStore: db} + var ( + backoff bool + triggered chan struct{} // Used in tests + ) for { + select { + case <-f.quit: + log.Info("Freezer shutting down") + return + default: + } + if backoff { + // If we were doing a manual trigger, notify it + if triggered != nil { + triggered <- struct{}{} + triggered = nil + } + select { + case <-time.NewTimer(freezerRecheckInterval).C: + backoff = false + case triggered = <-f.trigger: + backoff = false + case <-f.quit: + return + } + } // Retrieve the freezing threshold. hash := ReadHeadBlockHash(nfdb) if hash == (common.Hash{}) { @@ -263,18 +297,20 @@ func (f *freezer) freeze(db ethdb.KeyValueStore) { continue } number := ReadHeaderNumber(nfdb, hash) + threshold := atomic.LoadUint64(&f.threshold) + switch { case number == nil: log.Error("Current full block number unavailable", "hash", hash) time.Sleep(freezerRecheckInterval) continue - case *number < params.ImmutabilityThreshold: - log.Debug("Current full block not old enough", "number", *number, "hash", hash, "delay", params.ImmutabilityThreshold) - time.Sleep(freezerRecheckInterval) + case *number < threshold: + log.Debug("Current full block not old enough", "number", *number, "hash", hash, "delay", threshold) + backoff = true continue - case *number-params.ImmutabilityThreshold <= f.frozen: + case *number-threshold <= f.frozen: log.Debug("Ancient blocks frozen already", "number", *number, "hash", hash, "frozen", f.frozen) time.Sleep(freezerRecheckInterval) continue @@ -286,7 +322,7 @@ func (f *freezer) freeze(db ethdb.KeyValueStore) { continue } // Seems we have data ready to be frozen, process in usable batches - limit := *number - params.ImmutabilityThreshold + limit := *number - threshold if limit-f.frozen > freezerBatchLimit { limit = f.frozen + freezerBatchLimit } @@ -295,7 +331,7 @@ func (f *freezer) freeze(db ethdb.KeyValueStore) { first = f.frozen ancients = make([]common.Hash, 0, limit) ) - for f.frozen < limit { + for f.frozen <= limit { // Retrieves all the components of the canonical block hash := ReadCanonicalHash(nfdb, f.frozen) if hash == (common.Hash{}) { @@ -346,11 +382,15 @@ func (f *freezer) freeze(db ethdb.KeyValueStore) { log.Crit("Failed to delete frozen canonical blocks", "err", err) } batch.Reset() - // Wipe out side chain also. + + // Wipe out side chains also and track dangling side chians + var dangling []common.Hash for number := first; number < f.frozen; number++ { // Always keep the genesis block in active database if number != 0 { - for _, hash := range ReadAllHashes(db, number) { + dangling = ReadAllHashes(db, number) + for _, hash := range dangling { + log.Trace("Deleting side chain", "number", number, "hash", hash) DeleteBlock(batch, hash, number) } } @@ -358,6 +398,41 @@ func (f *freezer) freeze(db ethdb.KeyValueStore) { if err := batch.Write(); err != nil { log.Crit("Failed to delete frozen side blocks", "err", err) } + batch.Reset() + + // Step into the future and delete and dangling side chains + if f.frozen > 0 { + tip := f.frozen + for len(dangling) > 0 { + drop := make(map[common.Hash]struct{}) + for _, hash := range dangling { + log.Debug("Dangling parent from freezer", "number", tip-1, "hash", hash) + drop[hash] = struct{}{} + } + children := ReadAllHashes(db, tip) + for i := 0; i < len(children); i++ { + // Dig up the child and ensure it's dangling + child := ReadHeader(nfdb, children[i], tip) + if child == nil { + log.Error("Missing dangling header", "number", tip, "hash", children[i]) + continue + } + if _, ok := drop[child.ParentHash]; !ok { + children = append(children[:i], children[i+1:]...) + i-- + continue + } + // Delete all block data associated with the child + log.Debug("Deleting dangling block", "number", tip, "hash", children[i], "parent", child.ParentHash) + DeleteBlock(batch, children[i], tip) + } + dangling = children + tip++ + } + if err := batch.Write(); err != nil { + log.Crit("Failed to delete dangling side blocks", "err", err) + } + } // Log something friendly for the user context := []interface{}{ "blocks", f.frozen - first, "elapsed", common.PrettyDuration(time.Since(start)), "number", f.frozen - 1, diff --git a/core/rawdb/schema.go b/core/rawdb/schema.go index bba6c4115e..e4dcc2d9db 100644 --- a/core/rawdb/schema.go +++ b/core/rawdb/schema.go @@ -38,6 +38,9 @@ var ( // headFastBlockKey tracks the latest known incomplete block's hash during fast sync. headFastBlockKey = []byte("LastFast") + // lastPivotKey tracks the last pivot block used by fast sync (to reenable on sethead). + lastPivotKey = []byte("LastPivot") + // fastTrieProgressKey tracks the number of trie entries imported during fast sync. fastTrieProgressKey = []byte("TrieSync") diff --git a/eth/downloader/downloader.go b/eth/downloader/downloader.go index 4f2f603d3c..6aba221fb4 100644 --- a/eth/downloader/downloader.go +++ b/eth/downloader/downloader.go @@ -185,10 +185,9 @@ type LightChain interface { // InsertHeaderChain inserts a batch of headers into the local chain. InsertHeaderChain([]*types.Header, int, bool) (int, error) - // Rollback removes a few recently added elements from the local chain. - Rollback([]common.Hash, bool) - Config() *params.ChainConfig + // SetHead rewinds the local chain to a new head. + SetHead(uint64) error } // BlockChain encapsulates functions required to sync a (full or fast) blockchain. @@ -489,6 +488,7 @@ func (d *Downloader) syncWithPeer(p *peerConnection, hash common.Hash, td *big.I if pivot == 0 { origin = 0 } else if pivot <= origin { + rawdb.WriteLastPivotNumber(d.stateDB, pivot) origin = pivot - 1 } } @@ -517,6 +517,7 @@ func (d *Downloader) syncWithPeer(p *peerConnection, hash common.Hash, td *big.I d.ancientLimit = height - maxForkAncestry - 1 } frozen, _ := d.stateDB.Ancients() // Ignore the error here since light client can also hit here. + // If a part of blockchain data has already been written into active store, // disable the ancient style insertion explicitly. if origin >= frozen && frozen != 0 { @@ -527,11 +528,9 @@ func (d *Downloader) syncWithPeer(p *peerConnection, hash common.Hash, td *big.I } // Rewind the ancient store and blockchain if reorg happens. if origin+1 < frozen { - var hashes []common.Hash - for i := origin + 1; i < d.lightchain.CurrentHeader().Number.Uint64(); i++ { - hashes = append(hashes, rawdb.ReadCanonicalHash(d.stateDB, i)) + if err := d.lightchain.SetHead(origin + 1); err != nil { + return err } - d.lightchain.Rollback(hashes, d.Mode.SyncFullHeaderChain()) } } // Initiate the sync using a concurrent header and content retrieval algorithm @@ -1480,32 +1479,33 @@ func (d *Downloader) fetchParts(deliveryCh chan dataPack, deliver func(dataPack) // queue until the stream ends or a failure occurs. func (d *Downloader) processHeaders(origin uint64, pivot uint64, td *big.Int) error { // Keep a count of uncertain headers to roll back - var rollback []*types.Header + var ( + rollback uint64 // Zero means no rollback (fine as you can't unroll the genesis) + rollbackErr error + mode = d.getMode() + ) defer func() { - if len(rollback) > 0 { - // Flatten the headers and roll them back - hashes := make([]common.Hash, len(rollback)) - for i, header := range rollback { - hashes[i] = header.Hash() - } + if rollback > 0 { lastHeader, lastFastBlock, lastBlock := d.lightchain.CurrentHeader().Number, common.Big0, common.Big0 if d.Mode.SyncFullBlockChain() { lastFastBlock = d.blockchain.CurrentFastBlock().Number() lastBlock = d.blockchain.CurrentBlock().Number() } - d.lightchain.Rollback(hashes, d.Mode.SyncFullHeaderChain()) + if err := d.lightchain.SetHead(rollback - 1); err != nil { // -1 to target the parent of the first uncertain block + // We're already unwinding the stack, only print the error to make it more visible + log.Error("Failed to roll back chain segment", "head", rollback-1, "err", err) + } curFastBlock, curBlock := common.Big0, common.Big0 if d.Mode.SyncFullBlockChain() { curFastBlock = d.blockchain.CurrentFastBlock().Number() curBlock = d.blockchain.CurrentBlock().Number() } - log.Warn("Rolled back headers", "count", len(hashes), + log.Warn("Rolled back chain segment", "header", fmt.Sprintf("%d->%d", lastHeader, d.lightchain.CurrentHeader().Number), "fast", fmt.Sprintf("%d->%d", lastFastBlock, curFastBlock), "block", fmt.Sprintf("%d->%d", lastBlock, curBlock)) } }() - // Wait for batches of headers to process gotHeaders := false @@ -1557,7 +1557,7 @@ func (d *Downloader) processHeaders(origin uint64, pivot uint64, td *big.Int) er } } // Disable any rollback and return - rollback = nil + rollback = 0 return nil } // Otherwise split the chunk of headers into batches and process them @@ -1575,34 +1575,28 @@ func (d *Downloader) processHeaders(origin uint64, pivot uint64, td *big.Int) er limit = len(headers) } chunk := headers[:limit] + // In case of header only syncing, validate the chunk immediately - if d.Mode == FastSync || !d.Mode.SyncFullBlockChain() { - // Collect the yet unknown headers to mark them as uncertain - unknown := make([]*types.Header, 0, len(chunk)) - for _, header := range chunk { - if !d.lightchain.HasHeader(header.Hash(), header.Number.Uint64()) { - unknown = append(unknown, header) - } - } + if mode == FastSync || mode == LightSync { // If we're importing pure headers, verify based on their recentness frequency := fsHeaderCheckFrequency if chunk[len(chunk)-1].Number.Uint64()+uint64(fsHeaderForceVerify) > pivot { frequency = 1 } - if n, err := d.lightchain.InsertHeaderChain(chunk, frequency, d.Mode.SyncFullHeaderChain()); err != nil { - // If some headers were inserted, add them too to the rollback list - if n > 0 { - rollback = append(rollback, chunk[:n]...) + if n, err := d.lightchain.InsertHeaderChain(chunk, frequency); err != nil { + rollbackErr = err + + // If some headers were inserted, track them as uncertain + if n > 0 && rollback == 0 { + rollback = chunk[0].Number.Uint64() } log.Debug("Invalid header encountered", "number", chunk[n].Number, "hash", chunk[n].Hash(), "err", err) return errInvalidChain } - // All verifications passed, store newly found uncertain headers - log.Trace(fmt.Sprintf("Adding headers for potential rollback: %v", headersToNumbers(unknown))) - rollback = append(rollback, unknown...) - if len(rollback) > fsHeaderSafetyNet { - log.Debug("Adding some headers for rollback") - rollback = append(rollback[:0], rollback[len(rollback)-fsHeaderSafetyNet:]...) + // All verifications passed, track all headers within the alloted limits + head := chunk[len(chunk)-1].Number.Uint64() + if head-rollback > uint64(fsHeaderSafetyNet) { + rollback = head - uint64(fsHeaderSafetyNet) } } // Unless we're doing light chains, schedule the headers for associated content retrieval @@ -1751,6 +1745,7 @@ func (d *Downloader) processFastSyncContent(latest *types.Header) error { } } go closeOnErr(sync) + // Figure out the ideal pivot block. Note, that this goalpost may move if the // sync takes long enough for the chain head to move significantly. pivot := d.calcPivot(latest.Number.Uint64()) @@ -1790,6 +1785,9 @@ func (d *Downloader) processFastSyncContent(latest *types.Header) error { newPivot := d.calcPivot(height) log.Warn("Pivot became stale, moving", "old", pivot, "new", newPivot) pivot = newPivot + // Write out the pivot into the database so a rollback beyond it will + // reenable fast sync + rawdb.WriteLastPivotNumber(d.stateDB, pivot) } } P, beforeP, afterP := splitAroundPivot(pivot, results) diff --git a/eth/downloader/downloader_test.go b/eth/downloader/downloader_test.go index acecd20492..4bdac2b9df 100644 --- a/eth/downloader/downloader_test.go +++ b/eth/downloader/downloader_test.go @@ -332,25 +332,52 @@ func (dl *downloadTester) InsertReceiptChain(blocks types.Blocks, receipts []typ return len(blocks), nil } -// Rollback removes some recently added elements from the chain. -func (dl *downloadTester) Rollback(hashes []common.Hash, fullHeaderChainAvailable bool) { +// SetHead rewinds the local chain to a new head. +func (dl *downloadTester) SetHead(head uint64) error { dl.lock.Lock() defer dl.lock.Unlock() - for i := len(hashes) - 1; i >= 0; i-- { - if dl.ownHashes[len(dl.ownHashes)-1] == hashes[i] { - dl.ownHashes = dl.ownHashes[:len(dl.ownHashes)-1] + // Find the hash of the head to reset to + var hash common.Hash + for h, header := range dl.ownHeaders { + if header.Number.Uint64() == head { + hash = h + } + } + for h, header := range dl.ancientHeaders { + if header.Number.Uint64() == head { + hash = h + } + } + if hash == (common.Hash{}) { + return fmt.Errorf("unknown head to set: %d", head) + } + // Find the offset in the header chain + var offset int + for o, h := range dl.ownHashes { + if h == hash { + offset = o + break } - delete(dl.ownChainTd, hashes[i]) - delete(dl.ownHeaders, hashes[i]) - delete(dl.ownReceipts, hashes[i]) - delete(dl.ownBlocks, hashes[i]) + } + // Remove all the hashes and associated data afterwards + for i := offset + 1; i < len(dl.ownHashes); i++ { + delete(dl.ownChainTd, dl.ownHashes[i]) + delete(dl.ownHeaders, dl.ownHashes[i]) + delete(dl.ownReceipts, dl.ownHashes[i]) + delete(dl.ownBlocks, dl.ownHashes[i]) - delete(dl.ancientChainTd, hashes[i]) - delete(dl.ancientHeaders, hashes[i]) - delete(dl.ancientReceipts, hashes[i]) - delete(dl.ancientBlocks, hashes[i]) + delete(dl.ancientChainTd, dl.ownHashes[i]) + delete(dl.ancientHeaders, dl.ownHashes[i]) + delete(dl.ancientReceipts, dl.ownHashes[i]) + delete(dl.ancientBlocks, dl.ownHashes[i]) } + dl.ownHashes = dl.ownHashes[:offset+1] + return nil +} + +// Rollback removes some recently added elements from the chain. +func (dl *downloadTester) Rollback(hashes []common.Hash) { } // newPeer registers a new block download source into the downloader. diff --git a/eth/sync.go b/eth/sync.go index 9e180ee200..ba6015f425 100644 --- a/eth/sync.go +++ b/eth/sync.go @@ -170,20 +170,57 @@ func (pm *ProtocolManager) synchronise(peer *peer) { currentBlock := pm.blockchain.CurrentBlock() td := pm.blockchain.GetTd(currentBlock.Hash(), currentBlock.NumberU64()) - pHead, pTd := peer.Head() - if pTd.Cmp(td) <= 0 { - return +func peerToSyncOp(mode downloader.SyncMode, p *peer) *chainSyncOp { + peerHead, peerTD := p.Head() + return &chainSyncOp{mode: mode, peer: p, td: peerTD, head: peerHead} +} + +func (cs *chainSyncer) modeAndLocalHead() (downloader.SyncMode, *big.Int) { + // If we're in fast sync mode, return that directly + if atomic.LoadUint32(&cs.pm.fastSync) == 1 { + block := cs.pm.blockchain.CurrentFastBlock() + td := cs.pm.blockchain.GetTdByHash(block.Hash()) + return downloader.FastSync, td } - // Otherwise try to sync with the downloader - mode := downloader.FullSync - if atomic.LoadUint32(&pm.fastSync) == 1 { - // Fast sync was explicitly requested, and explicitly granted - mode = downloader.FastSync + // We are probably in full sync, but we might have rewound to before the + // fast sync pivot, check if we should reenable + if pivot := rawdb.ReadLastPivotNumber(cs.pm.chaindb); pivot != nil { + if head := cs.pm.blockchain.CurrentBlock(); head.NumberU64() < *pivot { + block := cs.pm.blockchain.CurrentFastBlock() + td := cs.pm.blockchain.GetTdByHash(block.Hash()) + return downloader.FastSync, td + } } - if mode == downloader.FastSync { - // Make sure the peer's total difficulty we are synchronizing is higher. - if pm.blockchain.GetTdByHash(pm.blockchain.CurrentFastBlock().Hash()).Cmp(pTd) >= 0 { - return + // Nope, we're really full syncing + head := cs.pm.blockchain.CurrentHeader() + td := cs.pm.blockchain.GetTd(head.Hash(), head.Number.Uint64()) + return downloader.FullSync, td +} + +// startSync launches doSync in a new goroutine. +func (cs *chainSyncer) startSync(op *chainSyncOp) { + cs.doneCh = make(chan error, 1) + go func() { cs.doneCh <- cs.pm.doSync(op) }() +} + +// doSync synchronizes the local blockchain with a remote peer. +func (pm *ProtocolManager) doSync(op *chainSyncOp) error { + if op.mode == downloader.FastSync { + // Before launch the fast sync, we have to ensure user uses the same + // txlookup limit. + // The main concern here is: during the fast sync Geth won't index the + // block(generate tx indices) before the HEAD-limit. But if user changes + // the limit in the next fast sync(e.g. user kill Geth manually and + // restart) then it will be hard for Geth to figure out the oldest block + // has been indexed. So here for the user-experience wise, it's non-optimal + // that user can't change limit during the fast sync. If changed, Geth + // will just blindly use the original one. + limit := pm.blockchain.TxLookupLimit() + if stored := rawdb.ReadFastTxLookupLimit(pm.chaindb); stored == nil { + rawdb.WriteFastTxLookupLimit(pm.chaindb, limit) + } else if *stored != limit { + pm.blockchain.SetTxLookupLimit(*stored) + log.Warn("Update txLookup limit", "provided", limit, "updated", *stored) } } // Run the sync cycle, and disable fast sync if we've went past the pivot block diff --git a/foo b/foo new file mode 100644 index 0000000000..72d2b63f17 --- /dev/null +++ b/foo @@ -0,0 +1,141 @@ +build/env.sh go run build/ci.go install +>>> /usr/local/go/bin/go install -ldflags -X main.gitCommit=e04a1ae96b6f6df07bac862f6d74dbd689bc2032 -X main.gitDate=20200622 -extldflags -pthread -v ./... +build/env.sh go run build/ci.go test +>>> /usr/local/go/bin/go test -ldflags -X main.gitCommit=e04a1ae96b6f6df07bac862f6d74dbd689bc2032 -X main.gitDate=20200622 -extldflags -pthread -p 1 -timeout 5m ./... +? github.com/ethereum/go-ethereum [no test files] +ok github.com/ethereum/go-ethereum/accounts (cached) +ok github.com/ethereum/go-ethereum/accounts/abi (cached) +ok github.com/ethereum/go-ethereum/accounts/abi/bind (cached) +ok github.com/ethereum/go-ethereum/accounts/abi/bind/backends (cached) +? github.com/ethereum/go-ethereum/accounts/external [no test files] +ok github.com/ethereum/go-ethereum/accounts/keystore 15.948s +? github.com/ethereum/go-ethereum/accounts/scwallet [no test files] +? github.com/ethereum/go-ethereum/accounts/usbwallet [no test files] +ok github.com/ethereum/go-ethereum/accounts/usbwallet/ledger (cached) +? github.com/ethereum/go-ethereum/accounts/usbwallet/trezor [no test files] +? github.com/ethereum/go-ethereum/cmd/abigen [no test files] +ok github.com/ethereum/go-ethereum/cmd/blspopchecker (cached) +? github.com/ethereum/go-ethereum/cmd/bootnode [no test files] +? github.com/ethereum/go-ethereum/cmd/checkpoint-admin [no test files] +? github.com/ethereum/go-ethereum/cmd/clef [no test files] +? github.com/ethereum/go-ethereum/cmd/devp2p [no test files] +ok github.com/ethereum/go-ethereum/cmd/ethkey (cached) +? github.com/ethereum/go-ethereum/cmd/evm [no test files] +? github.com/ethereum/go-ethereum/cmd/evm/internal/compiler [no test files] +? github.com/ethereum/go-ethereum/cmd/faucet [no test files] +ok github.com/ethereum/go-ethereum/cmd/geth (cached) +? github.com/ethereum/go-ethereum/cmd/p2psim [no test files] +? github.com/ethereum/go-ethereum/cmd/rlpdump [no test files] +ok github.com/ethereum/go-ethereum/cmd/utils (cached) +? github.com/ethereum/go-ethereum/cmd/wnode [no test files] +ok github.com/ethereum/go-ethereum/common (cached) +ok github.com/ethereum/go-ethereum/common/bitutil (cached) +ok github.com/ethereum/go-ethereum/common/compiler (cached) +ok github.com/ethereum/go-ethereum/common/fdlimit (cached) +ok github.com/ethereum/go-ethereum/common/hexutil (cached) +ok github.com/ethereum/go-ethereum/common/math (cached) +ok github.com/ethereum/go-ethereum/common/mclock (cached) +ok github.com/ethereum/go-ethereum/common/prque (cached) +ok github.com/ethereum/go-ethereum/common/task (cached) +? github.com/ethereum/go-ethereum/consensus [no test files] +? github.com/ethereum/go-ethereum/consensus/consensustest [no test files] +ok github.com/ethereum/go-ethereum/consensus/istanbul (cached) +ok github.com/ethereum/go-ethereum/consensus/istanbul/backend (cached) +ok github.com/ethereum/go-ethereum/consensus/istanbul/backend/internal/enodes (cached) +ok github.com/ethereum/go-ethereum/consensus/istanbul/core (cached) +ok github.com/ethereum/go-ethereum/consensus/istanbul/validator (cached) +ok github.com/ethereum/go-ethereum/consensus/istanbul/validator/random (cached) +? github.com/ethereum/go-ethereum/consensus/misc [no test files] +ok github.com/ethereum/go-ethereum/console (cached) +? github.com/ethereum/go-ethereum/contract_comm [no test files] +? github.com/ethereum/go-ethereum/contract_comm/blockchain_parameters [no test files] +? github.com/ethereum/go-ethereum/contract_comm/currency [no test files] +? github.com/ethereum/go-ethereum/contract_comm/election [no test files] +? github.com/ethereum/go-ethereum/contract_comm/epoch_rewards [no test files] +? github.com/ethereum/go-ethereum/contract_comm/errors [no test files] +? github.com/ethereum/go-ethereum/contract_comm/freezer [no test files] +? github.com/ethereum/go-ethereum/contract_comm/gasprice_minimum [no test files] +? github.com/ethereum/go-ethereum/contract_comm/gold_token [no test files] +? github.com/ethereum/go-ethereum/contract_comm/random [no test files] +? github.com/ethereum/go-ethereum/contract_comm/transfer_whitelist [no test files] +? github.com/ethereum/go-ethereum/contract_comm/validators [no test files] +ok github.com/ethereum/go-ethereum/contracts/checkpointoracle (cached) +? github.com/ethereum/go-ethereum/contracts/checkpointoracle/contract [no test files] +ok github.com/ethereum/go-ethereum/core (cached) +ok github.com/ethereum/go-ethereum/core/asm (cached) +ok github.com/ethereum/go-ethereum/core/bloombits (cached) +ok github.com/ethereum/go-ethereum/core/forkid (cached) +ok github.com/ethereum/go-ethereum/core/rawdb (cached) +ok github.com/ethereum/go-ethereum/core/state (cached) +ok github.com/ethereum/go-ethereum/core/types (cached) +ok github.com/ethereum/go-ethereum/core/vm (cached) +ok github.com/ethereum/go-ethereum/core/vm/runtime (cached) +ok github.com/ethereum/go-ethereum/crypto (cached) +ok github.com/ethereum/go-ethereum/crypto/blake2b (cached) +ok github.com/ethereum/go-ethereum/crypto/bls (cached) +? github.com/ethereum/go-ethereum/crypto/bn256 [no test files] +ok github.com/ethereum/go-ethereum/crypto/bn256/cloudflare (cached) +ok github.com/ethereum/go-ethereum/crypto/bn256/google (cached) +ok github.com/ethereum/go-ethereum/crypto/ecies (cached) +ok github.com/ethereum/go-ethereum/crypto/secp256k1 (cached) +ok github.com/ethereum/go-ethereum/eth (cached) +ok github.com/ethereum/go-ethereum/eth/downloader (cached) +ok github.com/ethereum/go-ethereum/eth/fetcher (cached) +ok github.com/ethereum/go-ethereum/eth/filters (cached) +ok github.com/ethereum/go-ethereum/eth/tracers (cached) +? github.com/ethereum/go-ethereum/eth/tracers/internal/tracers [no test files] +ok github.com/ethereum/go-ethereum/ethclient (cached) +? github.com/ethereum/go-ethereum/ethdb [no test files] +? github.com/ethereum/go-ethereum/ethdb/dbtest [no test files] +ok github.com/ethereum/go-ethereum/ethdb/leveldb (cached) +ok github.com/ethereum/go-ethereum/ethdb/memorydb (cached) +? github.com/ethereum/go-ethereum/ethstats [no test files] +ok github.com/ethereum/go-ethereum/event (cached) +ok github.com/ethereum/go-ethereum/graphql (cached) +? github.com/ethereum/go-ethereum/internal/build [no test files] +? github.com/ethereum/go-ethereum/internal/cmdtest [no test files] +? github.com/ethereum/go-ethereum/internal/debug [no test files] +? github.com/ethereum/go-ethereum/internal/ethapi [no test files] +ok github.com/ethereum/go-ethereum/internal/guide (cached) +ok github.com/ethereum/go-ethereum/internal/jsre (cached) +? github.com/ethereum/go-ethereum/internal/jsre/deps [no test files] +? github.com/ethereum/go-ethereum/internal/testlog [no test files] +? github.com/ethereum/go-ethereum/internal/web3ext [no test files] +ok github.com/ethereum/go-ethereum/les (cached) +ok github.com/ethereum/go-ethereum/les/flowcontrol (cached) +ok github.com/ethereum/go-ethereum/light (cached) +? github.com/ethereum/go-ethereum/log [no test files] +ok github.com/ethereum/go-ethereum/metrics (cached) +? github.com/ethereum/go-ethereum/metrics/exp [no test files] +? github.com/ethereum/go-ethereum/metrics/influxdb [no test files] +? github.com/ethereum/go-ethereum/metrics/librato [no test files] +? github.com/ethereum/go-ethereum/metrics/prometheus [no test files] +ok github.com/ethereum/go-ethereum/miner (cached) +ok github.com/ethereum/go-ethereum/mobile (cached) +ok github.com/ethereum/go-ethereum/node (cached) +ok github.com/ethereum/go-ethereum/p2p (cached) +ok github.com/ethereum/go-ethereum/p2p/discover (cached) +ok github.com/ethereum/go-ethereum/p2p/discv5 (cached) +ok github.com/ethereum/go-ethereum/p2p/dnsdisc (cached) +ok github.com/ethereum/go-ethereum/p2p/enode (cached) +ok github.com/ethereum/go-ethereum/p2p/enr (cached) +ok github.com/ethereum/go-ethereum/p2p/nat (cached) +ok github.com/ethereum/go-ethereum/p2p/netutil (cached) +ok github.com/ethereum/go-ethereum/p2p/simulations (cached) +ok github.com/ethereum/go-ethereum/p2p/simulations/adapters (cached) +? github.com/ethereum/go-ethereum/p2p/simulations/examples [no test files] +? github.com/ethereum/go-ethereum/p2p/simulations/pipes [no test files] +? github.com/ethereum/go-ethereum/p2p/testing [no test files] +ok github.com/ethereum/go-ethereum/params (cached) +ok github.com/ethereum/go-ethereum/rlp (cached) +ok github.com/ethereum/go-ethereum/rpc (cached) +ok github.com/ethereum/go-ethereum/signer/core (cached) +ok github.com/ethereum/go-ethereum/signer/fourbyte (cached) +ok github.com/ethereum/go-ethereum/signer/rules (cached) +? github.com/ethereum/go-ethereum/signer/rules/deps [no test files] +ok github.com/ethereum/go-ethereum/signer/storage (cached) +ok github.com/ethereum/go-ethereum/tests (cached) +ok github.com/ethereum/go-ethereum/trie (cached) +ok github.com/ethereum/go-ethereum/whisper/mailserver (cached) +? github.com/ethereum/go-ethereum/whisper/shhclient [no test files] +ok github.com/ethereum/go-ethereum/whisper/whisperv6 (cached) diff --git a/genesis.json b/genesis.json new file mode 100644 index 0000000000..ab5224866d --- /dev/null +++ b/genesis.json @@ -0,0 +1,88 @@ +{ + "config": { + "homesteadBlock": 0, + "eip150Block": 0, + "eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "eip155Block": 0, + "eip158Block": 0, + "byzantiumBlock": 0, + "constantinopleBlock": 0, + "petersburgBlock": 0, + "istanbulBlock": 0, + "chainId": 40120, + "istanbul": { + "policy": 2, + "blockperiod": 5, + "requesttimeout": 10000, + "epoch": 17280, + "lookbackwindow": 12 + } + }, + "nonce": "0x0", + "timestamp": "0x5e8ca380", + "gasLimit": "0x8000000", + "extraData": "0x0000000000000000000000000000000000000000000000000000000000000000f918cbf9042f94893c4d601ed879b4ad36fc31f0c0214d547113eb9475af50cac2b2eb330b975c1b999fef571c87087094ffff741c41fb487f4d64fcc9e32fbb38e2a8372c94c496e9791d39a6f0ae54ed52897e581d168a5b4594b182f37daee2285f14b4091b702ceccb00d5031294beeb24d10c9fe58715a0c853db8ddd8e0019177194aa3b76b6618afe574b278da9b71af0e66aa6f64694e2368b04a1d14f286faf8c90153e33dc0b0879fb9472bda6988c4551083c14dddd2709edee96a9b4a894f0d17b624521c0a599b063d73a73f9719307b48f9438f3eebb5a820ba4b83b1f6a324c09ec1db2d2f9942f916156a2dcd5dfb6054eb62a677c55c3a4037a94ee80387e93e4d6d41c4bf51623bc8a42ba55a44994d32e429fe2155971825e14e2fd89785301ab6dc3948c517b3bab0e2d65d5cdf3750ca360ff05b3fc1d9462d56ba5bb3b841fade256d97e7d4d57364fb88194beb2b0ea812caaaea3a1f894fa9138231e2c7d3894430c9d55cf6116c65482379c039584b9b965f32394821a6b00d9f658e1732ce741d91984c688e25c5c948339eae8ee5b8ea60d80711c9fe30ae92c0eba2f94a5f837aa6be966d9f293de6f8cc65fac7064220f94d2462858d04dfdb0c7ad26dfa21933526491c1c39442a237fd620f714536d6f63c0f46d092c9ea012294dce0096c358e90c4645d68a53e897416e786d05f94d10ddf202de766dbaaea7c436a90f5aa71e5bdc4942ec7df44dbbc3d458acc4108aac8d1cb0bec11c094b8f90aed575898c38c11deda226e1294f4d9dfcd948a63fe13a4be506e8b51d296f60f192458672e629480be4e53c6bf959445598965c2910c2c91ec81f7944663bf9f8c6b32f095126e138678732c0d183f7e94bafa573a3d5333fc88560de1c312992c56d517aa948a0d880f275d3741f507a0180e843a2805ec1e2e94cc8c30b74073f537a6f790ae68649788a66f2d7194ba7d40c43dc59e2686fb38edcbdd69c3e53eba34941db8f844aa731e4a20e139c7e7ebfeda26888cc9943acce236f234aa330395d50d6155f86c5169731894cd97f1e7cddff4523f03a5072e9be8ea7edbdaec94537bf2c6227ea6ce4eb250da02e6a6aaa3de4f7b9448cedc58b10af13d688631bc3cb78a05b8a6e56a94f410a55e2f4b49996a1cb884c3107490aee09330944ec65178abe63805b2b0ec2718280454d9b6353d9423836969f0d095afeb652c75523f740898e0c4629423e15d949c13e3010b75afd19b1d3b294310c7e6940ec5a403212d732d8d7ced050e9510f6327453c6940ec5a403212d732d8d7ced050e9510f6327453c694e224ceb83a39d2ffa7eaa0c501e6954db5667e59943c8afff5c9332161a20db995e2c831baf02d9f91940f409814cad27ce583de0d6a10ecf53d48b9535f94f6a969790936c5285f7a7d1af642707d0c8e2418947a450c89257bf0ead22f143493250907411cd1d694fb041f37e22b25e30e10cfd662e6a5f2d1305476f91386b8603695297deb0f970e1cd8c64a852b45ad788e151734ab05a20206be63f7f42817fb5e3e035d7f9dba56917a0bc75a3f0061e767a5cc5a60469709f170f4f7d76dcf6e30f04a520745ac8f3f131d6b854ea2a899c3317cc48bf06cdb07f4514a81b8606b628400822daba0c52481cd1f8708056c40c392b362a9028d17032b6324b114620118a2770e0ddccc717685c2380600d035299ff9fc354180d251acaa778cac2a2eb64466e977204e582ea1342c0100c01ff5ea558be47b1f36cfbaee7a1e80b860f6c310b565f6f975faf4326707551a9154b848a222c14c6e18b87c0bd9bcf3524d95b70d5faffe1d911955186f160d01c82d4df63cc8dbc52ef2e106c89d2b838c57a4e6fd033d7d4cd49698111fd78321a962d03b1a31eefdc84397c0d51b80b860baa5538d5579ce32668fbf4e80cd9fd31f09447ba473da1ae44a51ce6feb4f46d8a14008fc515fa7e0e9d720c83b7001bdbfbce56284c382c5a267e7a245daeaa9e2914dc92cf2aa2ebcde339e309c5d1a0df1533cbd631168fc3e4a1d248801b8605a13510aa9b74ecd0bb7d8bd7f65dd5622ff4a61eebc1976529a26954d70732d591589dcf49e3f8a87f450642336e200391e1e8b57afe3d7240b80020deef9db2d9b260fc3f30ab4168521de586c211baccb505b75af030d47bd1d6fd49ab480b860382d76c49b99ba0d0aab030afe569b89288f399c727e3c1dcefbe1208f0c2d86498f62e1fee2d50486e2d6aa0d61130172cd07019fdfe79cbbec315f53465d9a8121fcdcfe71efede293111915281e82add7252b88b540b3a0dcd2fcfec91c81b860348aa54a71033d583a29d00e3dfb1f696633c6520bc71099fd26a228d1882f380ab86ef19b7efe544d47ba8aeddf770125075f6c15b82611a31e746668c1aa8af2355efe6e4cd297c0f570fce18ecc2f274bef5115a8d8ba9a18a6563e6c6181b86017a5c4c6a8aa852ab1ac7771e3caa6546da92938bda6d4e0c0ea05da85adbe08ca2ee58e657a82b619d1a729b6510401686ca15382abdbd856716fa867573c35ab8605d2d57b0573ff589c087cf57e5408cbf7be57ce5946a6455b1955d9d300b8609887deb26c20c4b5b448e04efe7b18781355f9648feb47d978382aa3c789f545416d20bca757df66b70867ccffeba0014bb1b45fafe0366aff4d513c023a55ee35ccc5a86d5214f813996e2ded810e3cac11cb15b7ca0b97aad1a307897d4d01b86057b5158540d1672de49073e469e5426766094ce6514ac29580803ff9d22cdef3b6fed28a8ad9de63bf938c1c7b0e7a0156fb03f5363d09bf337713d8d45475df48ccea0fa793f591fbb62673545fc846c04e6aa9e2eaaab72c3b9ba4069ea280b860720216212176780b12cd297d1feff6a964329448d821fd69e0a4fcc53c4edc00ca9c89ab2c35abe7b68cd47bc230bd00597450ca0bea04562f78b0102d406f4b651957989c1471674eb16a531c2f762c84c3432ccd7fab87b0a185a942d00301b86068438d70fb61a2d0adc3710b619aa5f9a603168f93bf0504401464df3acb14cc1815bf449b7f8791fef7e309b60e7b0145d425515d1f4f380b66c256a4218700ae48e2d2185a636487d6f531f546b9127b957084d0821acccf5ad0776b06be80b86092b17fb70e62710f3b87642830e23258a0fd1041da9606c7eea7019f86da50ff4cd06ad48a4d0ca93e62a6c7ed6c5e0036f4443d0cfe9122156a346836a9163404d58856bbd447939189bf1cc8a7ee8be156415642992f8e0659526d15bb0c00b860bfd4b2392664c68bbd30d6a77cd1c7230e340ac65ecc07449c0d704096af06926238c60e7764ffcd0b9a53d82d7050009cfd9481ebd7630fd2540b834cef70b5276d07b75913a20222d74f36db8beabfcd39f7c5d57c4a28f87e8e737123bd80b8602a10c24fb6cfb029650a90f10f6586f26e61e3a51d68342785862e666f6c730bb929ff2c5a20f5ceff41cb53a2333c00aa0e4b0e47c821c668d6b84fac85c5b5cd360c53dfdf9a6c48e0f4ff8c3997ff191463f90fa644fc2870174d67885b80b8608aed791b4381c7bd38f8358cbb7f64bb6b74c34b85b27026745df7cae91f5cdd50ba6cadd919494ec9849e628138870188ef21da8282207be4acd30803288e2674a7c46322f41f3ecf685f5b635970c0d19802defc344cc4023f8e41e50e3c00b8605008d7aece8407c044c4a7a77b37690a08b0edbde0942446f31e3362031e689b30872d8732f74dd3e45bbe85c072a4005ad20cf2d9e0824eed9a607b980d0cd5d160bcbd5ffc34a6a87176e257c927cd419ac080df27cce888eb94c7bc5a3880b860a4ef4602775c99871c1f910af02cc997cb6f6b1524450898a1de0a3369750ce17deda194ce40c80650025770e1c60a008916618d314d7008a44e312f2f032fedd08177ef854cf78dc269122dd7eef415989e975f13d501830df4ecd3fe248700b860f01e9ee01d1a76e596827b897e39a1e497b00d6ed276675201e81a07509d4043354c89d0ed515098b0730958cc9dd200fd9cf9d1f2fdd7823937af05e03eb1b043de63e2c8ff7bfebc9cd4f3983243bd275d0266bbaee5e70244126687470f00b8601f599e48d2f04e623c42ae66d379f15ff8c1a3bc4584a27f234fc00e7feb64dcee6a0faa4cfc3737e507b9c38d640401b23b2c6fb9bb7f00a2144b8031b9b2446ac121e7ca7f06e0b6e084b082ada9fc31837d094b0d6c3d24965a9a61fa7a01b860c2cc4ba57abb3768f552b30768ad8de8d6b934d8fd2eca699a2b2f712e8d56b50ea2e59993175a396e471e3a6028b30054cf156b0c75b9df6ea2e15e03811960aa5999411522b01286bc1cf17e4ef366a48e3e075998394e090f46c1d8212c81b8603201cd2f5f5f41b6949a03a600347bf9920c891b883dc4c8a530188fec4f98ac96d6caf9e87a05c81962760c20c30c0198745f18efc87a19ec94a06cb01d72313a71f4ff30e94f04504e609cd495ed4b78dccdbdc6ece12d0200996763439c00b860b1d7e87a67d355c42cf7db5c599da2ce9624372cb941f338d68b80bb8376fc8600e6d925d9902f32270d6372d4215c0068879d52d16dda84ac2efbebbde57d7ca5d451f269aa9903926163d7ce75b68d2547c34e07303b9db69d0044c9219200b860872c5c11351fbe7f31bb38ff5f7b07aa8bc4902a06b81f4fe70e7bc5be86ad260be53c26ef3d1e6293e3308c33ef8d000c13182ad835adf86e816496d6519ae00bd607f6f5d974fab0792802d69688e6ef37078285a1a2e9f8489bfe5a87e600b8606afab29c7f64915ebcd2851799af2f43cebbab8fe051965103989c47e576181533f7bf64619a4ee50bd787bcb65f5b012d60c2eadaad3118cba6088cfb9204f5cc465d47dd4c834b568f313d5b0689c6b6f3734cd19d4df40185d007b22d3681b86055470892fbef78fa87bf31aa738a58fdca928a16d99fff12e8ec3d71fb89489286206e32aed5063f1fdd6294f8a3a2011e19cb83873a777741f3d8521ea33edac732704e36f1aac01f212eaf72405cf8d980dd88bcb88751a6bbe7207a5e1081b860207a4c7a86274921d013932e2f88ec795dfcb1f85df6bba7039fd14526cd44245f29d5916d17bebf40ed08be3d0541006fb3443238819cdf36eff79d8706ceda92b0b3bf05d6dfd9a723da2685acc34e59928fed096dea64f742fb55c7f34c80b8603891197bd1712a3cf13fc13f2f2308bb4acdd4e46e3a62abd28a8e3add64ebcabfb939c743e8e4d54da2a32c39719d013ca29923eb2c685ab851a4f644824d70b1fd36812f513f5f23fa8f82ea228ba2d8f8b771b109e99e1905e16b1899eb00b860efff9b35b865ad56dea6f6c80d96ae4ba88997a60451b1535ea51ef6ae1d26a1c25246f33139f64046909d4a30a90f00a782c6a5a910499b65d7f2c3064dca95cb6dda83c10c2f9dc8f60d1afeb91c067205dff722dfe964f66a9a98e4047800b8606dd6f3f642e00ffc73a2d76c8f58128aa434b526c0487487f193b6717665a2eccff314d7d0769dc17fad47db19981a00c8a11f156a2bdb36164b479cb1bcf636896066e3c3b561c478d357b343bfbc6aed51b08f60b8f804ebd78e2efb525c80b8608202e06fb2d18ad9a85b3af760290ca4aae79fe2d354ec4c462f65e98339f9bfbf6c24503c73b054bfa740ea595241011c0d599d95697238c700a380326dea544cd7b085a3b8db22ae900ac82a5c23ade8c4290e022b0e425a55f742352dc480b860acc4826a9317688bdf782adc5acdf12656ffc2f327ca699418c287a15c2c22e0d16e632e592f5b0748b40a8e374e33009d8cfdfef7f81493a77843054cd006858b1b217043954423bb0924d0387b6609a504e15e6c054fe1288e0bd337253100b8606c93b4d43d69c248efadf8d03a4c9672ea222830a1530b29deab346933fc4492a211223c446ea24af059d9528ab3c100f0c4769fb226335489969277140da7c8c7f036d76f73c1d5f359744018b76b13c0eb07812f08923649e4a45b3b69fc80b86086ef363fcabe2e3c27769de9974f4b8604b47cdb2fe57208f0a59899b77306b7770f7403b222b6222efeb67747d06e01fc2ac657a21f37ab982d8463ba9c7fafaeda20370ec3f6cc565dbec4a69f59f9d7404725e3b701681d41a870b1f42281b86051026c0f52d8612414359ee4e6049a275387d3033cf51a8e23b3e037bd7006d916017b5253da7068532e6242b1d96900d8130a60b9b0b3ecb06a08472728bddd55f778e485188c3717b911039ebe3b2cdd89573229bdacaecba9a220b2decb80b8606a2cc88ae37c395815dcedb56f5ee6b701e06e97bdb6232c2b0e21f719a1504d0f3b259a63e2e54d6b1a27cbb0b051007f0c39d42f699cfc608c25b636ea221500d0eb75fe0f26d35beec47e1161675a7f571ed70684778ee7c4bc6221d8af80b860c5f05101b67ffd245abb878fc8d68058e3a65b4672453b90cb116a0cb8f59879a73944d8a2c25e8a2865e07e1e4e0100cd255dbd7055b5228eb1d4cccea7a1288ef83bab770633b0054f8c8d9ad4e7fc15af631c2b2282337faddb2220e54901b8603178c750f9274f0f1ea4103997e7d469b2ef4b9dd2f1dff7dc33ae5aaa5fdfa32a9e44e844de658502fbd8925e9a8a00d4422f22a7a5c3e4a790d21334eb70a744da6a863c4e060481781b8bb3fd1e9291ebfb548f7d8ec122c2c0c43eb46000b8607983d25868e1915ca8c20603bb70475b398acb04fef221106475f0fc25a3df25d181050214da347bfcd8f8292e5257014ba77cf67ee5f42202257317808f126930b4eaaf4bec801c4465ced54bd78331f8d3dadfdf2f91de294836c13e946001b86061810f2366f415b7b67e0ff9c82ae55fa213a95ff61df8718e806931ce135c0324462a33ccbde34ff901025ac334640064b41f7854c6eabcf3d9f7a4e4ff90522a4ba2681a0df03d08c67fb79f0fe98cd8c6f5ad3df155a0210ff84fc93d1500b8606a50718246d5c167429ce48b757a28441b217eb0903d762a3039d0ee59c00584b05418920be4eacb2fe2051d492a3d003a2a00065986e15815c26434c68caf177cbea44a38a886e86b34dba8a17dca43b729b9d69007e25d735e0ec62f7b6d81b860424b8239213c6f2c3e181b815294b9dd78663e29ee1234e1511e584b7b736571a6799135381cced36dcbd12dd19a5901f479679592608ab7f98aa1f607a3fe4b5b29a6580f724086610c901f143be653dcaf9fd477ac4d21d263e8ad8d048681b860f03d1c933feb791285892c9e6552bc6ccf07dd7f66862ff5554844db033c17a005087b5847718d4611e3ecb293ce670144a99a13ad3356ca56535815a0c6c21c2f84bbc0b40c78f6b63137a17709fa4be124be10e90a42bda72aee977ca86881b860fb9de050c059a11175be23daeef1bfc374a688d8fd776e7d2dc81fe301068a3af03ad522bd915a154dc8b5b8e12d38003f17bf9f3001e8bc682e38cfc93c6901417afe1ddbfe11b04f42ca4f321f7ba73fa98f0e8c8d75781b14c0dea847a500b860fb9de050c059a11175be23daeef1bfc374a688d8fd776e7d2dc81fe301068a3af03ad522bd915a154dc8b5b8e12d38003f17bf9f3001e8bc682e38cfc93c6901417afe1ddbfe11b04f42ca4f321f7ba73fa98f0e8c8d75781b14c0dea847a500b8600fa447ead6255657aa79229944a3ddf36984c7b9011e859f90bc6567ab61133b27b6bfa3a5e322dcf36abff543cc0d0131066520ad92d12b8603c25c561bf48806f178a995d233862038c46e81933e1ab0a7211b9b0933499cbc5867db736481b8602e45f40c799aec72e87e0ba4713056dd17cc9bdb29bb221c8fd6377336ae773afa84b8c0bb8f1f2edc88975b8ec986006f321462e28706618d690d24337a9e1c7b96e74d8c8f2fe740bac461635b4828046227f92f97b13da8540bdcc2f1a380b8602b8ab0795a174e96061dbb8c32bd38468497e56379b2ac79f6a7506f711b817cb57c8c1d8743d88c436cdcde3b51980132c5508f79cfc477bbd1b94fefd5c408a7072e85041f17042c1ad055c04e67a780f497e60aac3c38ddb2f0004237aa01b8603729df3ecff9e168c1ab2b2698251797494847ee14bffe9c4ce121d90d381b0d51f7208c793f55a9cac9d50e25d63d0018ee5daa523319bbd5087dc35cef8ec53338d810adf8b4565f39fccdddd7596a63198f045a2f3d92bd0b72b4487bcd00b86044a466fb5cf01c878071e12dc391753cb59005e39c6604fa0d1444ae36518df771f252891072c26652e12a5a5b1f3c00f479f3e3ace6412768ee5729825bac3529cfde3b44cc258b847dbd87f6d55dd68124d054314eea0a9169b36e46e34081b860c6ec185bce68a0a1fc78f78a5a9da12d39635f94b6981a64d7ed7a095839b6839da577383ddf9ef940d93409ec305801cda7a06f3c3adde48e9060ca396bd8a2821fbc435842bba5ba1dc0b81cfef04cdcf0ca7b02b6e4d70ca9caed8438708080b8410000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f86480b86000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080f86480b86000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080", + "difficulty": "0x1", + "coinbase": "0x0000000000000000000000000000000000000000", + "alloc": { + "0x36940810BfDB329B31e38d3e97aFD673081B497C": { + "balance": "120000000000000000000000000" + }, + "0xfCf982bb4015852e706100B14E21f947a5Bb718E": { + "balance": "200000000000000000000000000" + }, + "0xbA8761304CEc7bE0f83C6F8Fa7EBBa3eE0b6Ae97": { + "balance": "27375005000000000000000000" + }, + "0xDb39DBE5abE42466F122b24c44518b1089ef8fC8": { + "balance": "57291662000000000000000000" + }, + "0x671D520ae3E89Ea5383A5d7162bCed79FD25CdEe": { + "balance": "20000000000000000000000000" + }, + "0x868E39ef6c51b979526c15Fb801a7dD567CBCffF": { + "balance": "20000000000000000000000000" + }, + "0x4eC7a9e67FB05f555d775604cF591Ccb3C47d7b9": { + "balance": "20000000000000000000000000" + }, + "0xaB5FD29Ce411C7b5c0c41d04a11d40f8fbCdA7a2": { + "balance": "20000000000000000000000000" + }, + "0x14F40ca7600B5605D9fE704A949DA41806509497": { + "balance": "19053338000000000000000000" + }, + "0x469be98FE71AFf8F6e7f64F9b732e28A03596B5C": { + "balance": "20000000000000000000000" + }, + "0x1cd43c11CaEaf4a43413258eF7E0704e157F7811": { + "balance": "22000000000000000000000000" + }, + "0x9268f359CAD800a2746FBC96C4A5CF68eE1c4EC2": { + "balance": "22000000000000000000000000" + }, + "0x10E0833be035607feEA41d32b6567D15D12511Ec": { + "balance": "22250000000000000000000000" + }, + "0x8f55CE88b4F62F22c663f5A539414dcCeF969c32": { + "balance": "11000000000000000000000000" + }, + "0xF607d4dd519B4bc963C9c48E8650E67C51DbC35b": { + "balance": "11000000000000000000000000" + }, + "0x515033209a0A29034DC3F037cC72a6014b902341": { + "balance": "10000000000000000000000000" + }, + "000000000000000000000000000000000000ce10": { + "code": "0x60806040526004361061004a5760003560e01c806303386ba3146101e757806342404e0714610280578063bb913f41146102d7578063d29d44ee14610328578063f7e6af8014610379575b6000600160405180807f656970313936372e70726f78792e696d706c656d656e746174696f6e00000000815250601c019050604051809103902060001c0360001b9050600081549050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610136576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f4e6f20496d706c656d656e746174696f6e20736574000000000000000000000081525060200191505060405180910390fd5b61013f816103d0565b6101b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f496e76616c696420636f6e74726163742061646472657373000000000000000081525060200191505060405180910390fd5b60405136810160405236600082376000803683855af43d604051818101604052816000823e82600081146101e3578282f35b8282fd5b61027e600480360360408110156101fd57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019064010000000081111561023a57600080fd5b82018360208201111561024c57600080fd5b8035906020019184600183028401116401000000008311171561026e57600080fd5b909192939192939050505061041b565b005b34801561028c57600080fd5b506102956105c1565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156102e357600080fd5b50610326600480360360208110156102fa57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061060d565b005b34801561033457600080fd5b506103776004803603602081101561034b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506107bd565b005b34801561038557600080fd5b5061038e610871565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b60008060007fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47060001b9050833f915080821415801561041257506000801b8214155b92505050919050565b610423610871565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146104c3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f73656e64657220776173206e6f74206f776e657200000000000000000000000081525060200191505060405180910390fd5b6104cc8361060d565b600060608473ffffffffffffffffffffffffffffffffffffffff168484604051808383808284378083019250505092505050600060405180830381855af49150503d8060008114610539576040519150601f19603f3d011682016040523d82523d6000602084013e61053e565b606091505b508092508193505050816105ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f696e697469616c697a6174696f6e2063616c6c6261636b206661696c6564000081525060200191505060405180910390fd5b5050505050565b600080600160405180807f656970313936372e70726f78792e696d706c656d656e746174696f6e00000000815250601c019050604051809103902060001c0360001b9050805491505090565b610615610871565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146106b5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f73656e64657220776173206e6f74206f776e657200000000000000000000000081525060200191505060405180910390fd5b6000600160405180807f656970313936372e70726f78792e696d706c656d656e746174696f6e00000000815250601c019050604051809103902060001c0360001b9050610701826103d0565b610773576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f496e76616c696420636f6e74726163742061646472657373000000000000000081525060200191505060405180910390fd5b8181558173ffffffffffffffffffffffffffffffffffffffff167fab64f92ab780ecbf4f3866f57cee465ff36c89450dcce20237ca7a8d81fb7d1360405160405180910390a25050565b6107c5610871565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610865576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f73656e64657220776173206e6f74206f776e657200000000000000000000000081525060200191505060405180910390fd5b61086e816108bd565b50565b600080600160405180807f656970313936372e70726f78792e61646d696e000000000000000000000000008152506013019050604051809103902060001c0360001b9050805491505090565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610960576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f6f776e65722063616e6e6f74206265203000000000000000000000000000000081525060200191505060405180910390fd5b6000600160405180807f656970313936372e70726f78792e61646d696e000000000000000000000000008152506013019050604051809103902060001c0360001b90508181558173ffffffffffffffffffffffffffffffffffffffff167f50146d0e3c60aa1d17a70635b05494f864e86144a2201275021014fbf08bafe260405160405180910390a2505056fea165627a7a723058206808dd43e7d765afca53fe439122bc5eac16d708ce7d463451be5042426f101f0029", + "storage": { + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x469be98FE71AFf8F6e7f64F9b732e28A03596B5C" + }, + "balance": "0" + } + }, + "number": "0x0", + "gasUsed": "0x0", + "mixHash": "0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000" +} diff --git a/geth b/geth new file mode 100644 index 0000000000..062930e221 --- /dev/null +++ b/geth @@ -0,0 +1,107 @@ +Google Cloud Platform
+ + + + + + + diff --git a/hmmm b/hmmm new file mode 100644 index 0000000000..38a7057dd2 --- /dev/null +++ b/hmmm @@ -0,0 +1,27 @@ +DEBUG[04-16|16:58:18.450] Sanitizing Go's GC trigger percent=100 +INFO [04-16|16:58:18.450] Setting it here +INFO [04-16|16:58:18.450] Maximum peer count ETH=100 LES=0 total=100 +INFO [04-16|16:58:18.450] Smartcard socket not found, disabling err="stat /run/pcscd/pcscd.comm: no such file or directory" +DEBUG[04-16|16:58:18.450] FS scan times list=45.286µs set=624ns diff=894ns +INFO [04-16|16:58:18.451] Setting baklava id +INFO [04-16|16:58:18.452] Starting peer-to-peer node instance=celo/v1.0.0-unstable-2addf910-20200416/linux-amd64/go1.13.7 +INFO [04-16|16:58:18.452] Allocated trie memory caches clean=512.00MiB dirty=0.00B +INFO [04-16|16:58:18.452] Allocated cache and file handles database=/home/sami/.celo/baklava/celo/chaindata cache=768.00MiB handles=2048 +TRACE[04-16|16:58:18.452] Started watching keystore folder path=/home/sami/.celo/baklava/keystore +DEBUG[04-16|16:58:18.496] Chain freezer table opened database=/home/sami/.celo/baklava/celo/chaindata/ancient table=receipts items=0 size=0.00B +DEBUG[04-16|16:58:18.497] Chain freezer table opened database=/home/sami/.celo/baklava/celo/chaindata/ancient table=diffs items=0 size=0.00B +DEBUG[04-16|16:58:18.497] Chain freezer table opened database=/home/sami/.celo/baklava/celo/chaindata/ancient table=headers items=0 size=0.00B +DEBUG[04-16|16:58:18.498] Chain freezer table opened database=/home/sami/.celo/baklava/celo/chaindata/ancient table=hashes items=0 size=0.00B +DEBUG[04-16|16:58:18.499] Chain freezer table opened database=/home/sami/.celo/baklava/celo/chaindata/ancient table=bodies items=0 size=0.00B +INFO [04-16|16:58:18.499] Opened ancient database database=/home/sami/.celo/baklava/celo/chaindata/ancient +DEBUG[04-16|16:58:18.499] Current full block not old enough number=0 hash=09bb18…0f1d7f delay=90000 +INFO [04-16|16:58:18.499] Persisted trie from memory database nodes=25 size=6.22KiB time=76.902µs gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=-116.00B +INFO [04-16|16:58:18.500] Initialised chain configuration config="{ChainID: 40120 Homestead: 0 DAO: DAOSupport: true EIP150: 0 EIP155: 0 EIP158: 0 Byzantium: 0 Constantinople: 0 Petersburg: 0 Istanbul: 0 Engine: istanbul}" +DEBUG[04-16|16:58:18.500] Setting up Istanbul consensus engine +INFO [04-16|16:58:18.500] Open roundstate db func=newRoundStateDB type=roundStateDB rsdb_path=/home/sami/.celo/baklava/celo/roundstates +INFO [04-16|16:58:18.585] Initialising Ethereum protocol versions="[65 64]" network=40120 dbversion=7 +TRACE[04-16|16:58:18.586] Set current header number=0 +TRACE[04-16|16:58:18.586] Set current header number=0 +INFO [04-16|16:58:18.586] Decoding +ERROR[04-16|16:58:18.586] Invalid block body RLP hash=09bb18…0f1d7f err="rlp: input list has too many elements for types.Body" +Fatal: Error starting protocol stack: genesis not found in chain diff --git a/rc.json b/rc.json new file mode 100644 index 0000000000..7cdd781b32 --- /dev/null +++ b/rc.json @@ -0,0 +1,133 @@ +{ + "config": { + "homesteadBlock": 0, + "eip150Block": 0, + "eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "eip155Block": 0, + "eip158Block": 0, + "byzantiumBlock": 0, + "constantinopleBlock": 0, + "petersburgBlock": 0, + "istanbulBlock": 0, + "chainId": 42220, + "istanbul": { + "policy": 2, + "blockperiod": 5, + "requesttimeout": 3000, + "epoch": 17280, + "lookbackwindow": 12 + } + }, + "nonce": "0x0", + "timestamp": "0x5ea06a00", + "gasLimit": "0x1312d00", + "extraData": "0xecc833a7747eaa8327335e8e0c6b6d8aa3a38d0063591e43ce116ccf5c89753ef91f4df905559427f326ab753d62cdb55018c62e9ee7e671bbb121947eec94733d16b96c6fe877464630bb5be1e5c3f294f0d17b624521c0a599b063d73a73f9719307b48f94a7681958b7f07f4fb8bd5b0e075fb2aa2b021d5994ecc20b5f3d6cdf41fc12707ad7872ff64256e29794e5617da4dfa6ce4912f1d39889fe2dec2f7e66b39439ec4f2a82f9f0f39929415c65db9ea5df54e41d94341dec14b7a56c242ce9cf939815ec7bb11042449469901924e6c045a03cc163c6b8ae8af80fa1ee80940a6641d4736767d1f2bcf2450200ef384391b4419466bdb4d2ff2ee4c68517e6fcd25cc3034c86916094606311948f7426ddfd23c1521b15eddb52e83b29944cb90ebba92141ed3021f5dc4e6c8bb642095846948c6f9aad8281a21e7f6522602f2d6469c950e0bb942a1bff2452aca1ca5ffabbd34b2744109d11e4f594b4fa2d21b238e12ee4a863517cb5092f2330cb1b9442d441b6793e6162b979fbf6ad0af0063cbec96a94436d12f639a32509685080161ff0365fc15545f094e0c5f6172673ad70a76ff264cbc0df783930b47d9421245b0a2c3235f1108d1aa01ae376849d36e68494f27bb4eabc4400a1abe9d80d7537ab0ef1b058bf948440e805b89f48c932265e3c4ad033813669d87a942eb79345089ca6f703f3b3c4235315cbeaad6d3c943aa1fa695aa89958ebdb5346d6760b72250dc1d794173c75c8f1be201ce89cf426fe12c9997d7096269474288dbefa3a55986c039953b67139a466474fc49482f0e7879314516952f7961b15c63fc6b2734dfb9459f7b67e6beae0223ddc91eec010b670c553e8e094e10a8cc6c22cdc320c67bd600a1d8a0a46d7f40094e3020350aceea29b783e0c947ae001692b8f624894b952930a3656a9cbab21df5919f94c61a495bf79942289a63b4b4700eeeca35323ea51785f366dd705940223e40d1f93a6fe5bef63605992ada10740e13b940610b8b4e6f5c3241d53ed3374ddca8969cd053c9463b4b616c5345e3dcc9e21db69297e2129447f4e94c9a7781729f95b88239c3bfc91fb52f92b44a1169456259f876eb6a7264d9f1a59952baad599ff964094f139e74adec329e715ab49a68c5548a00e40cbc29433657019d60a0a41f1b9970bd4b28a3a83dbeafc940f5640bd556b0be19262d1817b213ddb3424d91d94ed8bf82d2e579ff6363aef139f8b147a0105f17e94d8c68ebecb6f074ac5c4fb66a690ac0ad38a5a3c94c6f916ad6e360651bb95f8e67c1c28805745d084943ed95d6d4ce36ea7b349cd401e324316d956331a944a03c4c2e101ac4612d89b79f61c9c5bdd51929d94dd0f3f7beb37fe9d4496f8098446b65ddfb1fa0294642cbe89a58909ba712dd11ed4c4b2359bd8c85d94ffbcf262c1d5c4392ef469ba79f2cd195d2affda9468e0104fd2b5a2c93e97c2ba172c4d2a4223f76f945cab520442de9babc290b25e5e2e6a1194ec670794bc6963fc0e2f5547ba949ed39e80b8388321104f9443882141555003b3e71110f567373b59ac4cb0bd9448cedc58b10af13d688631bc3cb78a05b8a6e56a9465698c9ec5af10345cd1e39472d60fb6133bad6f94d507309fd69635aa37810a65a4da27ec47a1ba0594c46dc0741ff61af883e284daea062ae7382e709194198958f0b860ab0e3937f468fe366aac9eebad2e940ec5a403212d732d8d7ced050e9510f6327453c694464cce7999b3d90a8f1ffaf94a71fbdea1e6543594097095b8cf5cabf0c39e548d8df55dd635d84d0794aa937da037e617e868795eac1dcd43c663014d3294f11073eb2d259b90a91954cae30d0e6e9ecc7f11945b55452bdba5971d606f47647bd383f3c3fa728594439d5e4d7578ecc9efa52a8cf1887b11fd0fb9009492f628b0157d47c992f5c69dbbd038b110e27826f918e2b86005f784c52234d0c40ab13b0636c5728217a8f3100046593c30271d39d59fcdb9a0053a874710e9c65e0d8a030c16a700b4ec430207cc5037c5e2698ef839fa0b7a4372f4b5217deda2a8df087e3b552f300016ce9147a2ff4db4c8a87d77b080b860d3f640c3da685893c41eb6301fdde2920c5a09296438abe5894074592f27547fb4ad02d222b1a330ff5aea065eff5200973d4fcb57808d8d9b09337e09aec279dc3337e758c51a3219596699006ee3683ff0c733f16eb917fad37f7f5d505201b86057b5158540d1672de49073e469e5426766094ce6514ac29580803ff9d22cdef3b6fed28a8ad9de63bf938c1c7b0e7a0156fb03f5363d09bf337713d8d45475df48ccea0fa793f591fbb62673545fc846c04e6aa9e2eaaab72c3b9ba4069ea280b860ca75a4c4e1f2898c0ae0ed53698b0271d1f8869ecd945891ae6a9b02682335af625c29f80572b440f91a3a343f3ea600a49a426960b6c1c5dd7b24540ecb745329312dfdd525fd173418c846f0096acba466a27446114f3a2b2a887986846b01b860b3dff5505fe9ec48fa11a67dbf166e7d5ab3473ff9f5fdc90c690eb1142ad687b17eb8ab0c08615c9397b351c53e79016d593d588f8c607b2d1136713d05066ffd8a30589357afa54a0a7ac8777372787261dde126c4f0c04bf741f809c3be80b860451da71ff5b1e9b4fd587fd76f53808191096cc5869596eda8f3ad697426a98a659f5f4818e57866d4b0dd90f0684900742a167b314f0276e5e6a8bc6f40ce1cd1d35c7f9be56f1240de596b30a4b40010dfd21b7fc9aef400faaa421e27a080b860277d5eedd8cf7d549296a6f8ad2869ec6e90183b9e8ebbf49a9d3ecd817757b50c6acc6cab9f0dbcf4b87251b6e82a0192a00c1e509225ec1ec08dcbeb04ba2808b16f72af90f33277e614dc19383256b3980421441ce3e75356ee35e5f62d80b86007431d3192f7a273382b645bc300cb0161c2395c005bf389698ce4a3ac56cffb9405456102f5b6e41b42bb28e7cb1f0141d3e1be1b066a94cc2befe88b0f5eef63c60a1ab8a1f0cc02e73c0ce5aac464332d3a2c1074a5126807a75323280301b8600d39e1cd00ff4ce5e41fa9ea90526f3e3540b64ba52954e5682f31ec20360b2995d5caac7cee778ff7c13aaca74b9b004032f87a331867e9ebc7ed06c5b77707c88614714f2e0ed30c85c519aa823aa9d1a7a56766a294c7802aad300b408280b860ce9efb226a3c085071c7aea84f66040dc16a1600893eb1e6ef507fa72c6684f24d2c3b4ffee9881142fc41cfbd6b3b01933838ed7bd05c16450cab703b12ee623f8745f7f618981601a9c4de1337fe881975bc8572536281b9dcc51400177680b860075724b0f2fa9ced3440a76107a53b02a0b8b5a5a510d94b02b5c0696db96910204d54ee3138b3e5949464585d98de00a2964d480ca31adf09c962802895ea160d195bce583e59094bf7c11d33eaffef12cb999284bcf842bbab2c87647d8801b8603b0ffa0a101f959879b7e14d830862981d6c311ffd440f214eee0a2891743a25355e9230266aeadbd20f3bde0ccb30008bf326df8fba9b701d4764ad49663da19417132edf4281df4560715649491d9794dc64e9540d16b51b362e139c3aa701b8601a65e75f0f47d7c92da92de15372a0052338b952cc1307d5ee1596a670fedeb3b5ac8bc690f3f5e5f34fb8d18a5441011d6023e3c2b343bffc655972102a7181dffcab47bd0a2d6d46eedc6f2b70cd64025715de2b8ae23c032e61b380663c80b86071ca0f2be942a733074e8e0d92ae0adc2617bcfe503b97f8339c8f1c498d85608fa5966da7abdd9651c9ce4e3411e900c4d65d5c7d858f1e5ee212c9e543d3727aeaa9abbdcb68848e7c990c06aa70a4bf2585959943935549e7a9e2c2ba0d80b8600122d3f6ae5e2bc6fdee3cd35a3522ea519bfa6f365451fa275c4688bcfb5cec418fa053a8859981e973ea273ca68f014e840d0ccf18cc7c498742103c3116732ef197a9f90f50bf64f83754a86ad441fe9691bfdf384a1aaacf38430a2b1001b8601135b86a2587c75c55db8274e498bd3f2887a1a455a665b8314655124c5e8197d3ef892f3dea2bd80b047530f837ae00dc263da929f0135a4f8ee73d47d5c2ffcaaa7b1e3a9cc59e496feeea2323e5eb16c9de2e3b973c35c0a82ca587477201b860e162bf706b79405326d52e29e2ea247a55ebf69ac34900e4e1249c3fe28fd3dabf40d7022f57bc7b16bedbc78bb49000ba7cd92e123b69309a0572cf49b1bdf4c5525ba656decffa5da91ed4fb565d384979e9a58f72986b654908bcc7308580b860e9dbc5c1d073954ad6ace9afb19d8679e8c87fd12cd1356999a8e167390f3de966f3485b500c40c61f829e12f56512001b4d4c4fcb19737735eba15d24d43231ce64cf348de3765fdbd01f4612af6ad7ebf9fafb594ade18a7717c189e9c2080b860bd8e3d6ad24e5a7e4f084b3142c6bebe26d248e09363a9bbfc9cd07ed59a65bc140a39564f6ecdf287c2ee1ed57a930035a92306b6d5925af8785c813bad6113ba42da88d3c0586e438df75bee506bdf9f10c927493524897ba485946f976f00b86030feb59a6804a2df697b3a40c691f176575ffb0d09fa167a59642d041dfec97e97414ea7abc8bc7bdad5f1a684e2bc00fb2c01bc03aa9e8caaaa82ca3210de31f9c7abff6baba5e08e2dbdfa85953ac39bf3b895627e7be493fbb6e346061400b860f24f6f1e6423fd83d1ef275484a5950fed90794d7bfb6224de768bf716646dee263de0d9ed4c681c0def78d16df0f000f1e17b8657f1d8e30dcb7e94cd1c79b9c82d8f04252b078ccf3719c7658dd82b9d93e02671925b5aeb4ae38163129100b860f6a586f1ceb85a23980bdfea738678f5906de5303a7ff6ceb3ad675f93a84fcc502275fd7bd8fde4de89fd381cb8eb000b3d496e248208d00eae4f421ce041d73789e794a372ca788655eb5413c3b7cab1c993e47ff6c568ca4da484bac88b80b86086ab977d6064531b136aba2fbcc50cfb332b939e0af22c7ff3800c804b33aad998ef69a97204076028a6946d627d2f0086992cba351fd538a91986253884325aba6d66ec1ac10eb8e18330180820cc388c22de7d64f9f0592b74ee5b35745a80b860fda02a60f25f87c0fc86be0bf52bf1d0be37db80661a2fa35c7f52a4c5f5edccca04768c762caaa2303f8cac2ba93e016dce7c8382e3d002e751e0bf33563eb8f6e7937ab2998300e96f5ed3d857d081ff389c495febaabe836a7cd06012ae80b8609271a103e5971edd694b3c6363a2517b0676849b05660094baf240ea9677e171169a8eebed5ad6000871b4f42d4ca701b74b10f91c0de059d225ced0222e391cf7bdb5934d1677193837d5a1f17bb710f4747956d819db51c817cbba53324b81b860719b2de30cbcdee6e62445b7c2eedb63520beb4cb6e4a55f7e121a5bc6a1143e1322d3ffea28ab624d30f6da8962b8003eeb056df8e46a49035c0aaf139a372e954d8ebc3cbd2d0b2e5727d54f3f4fcd0e95dc29bfa9f9ddcda98bbe8107ae00b860b054d545899f55cbb84853125d50ed06211ace3eeb6160a85583de508569e65592f5a221a000cb99997c0dd2738527010f2b1e83eeb7ca41c40ad9295b35f1172004a63567f140c1d2b0e04338161e8f1be88c1543ac75d587e42c3ed7dc1880b860e8de954d3100b125b2a3c1e4a81e3ac5f4b38f85c2ed91d752c507d4a37c338ca215e474a48511c599407b85c01d37012cd5012c74c5c0c3f88b4480a73bb52d1ff49848ca014f54cde1a891e6efa483b5f64016a9303515806c45d9f79a7e81b860bfce6153e2c2dabc724d9ccf5cad8916753dce1a495a29053ff7e5b74b0eace4889d5fd2d5859400d82b6bf29cecc9006b6e37152cb1f4f72e7d0c0897439f4ef886e26b4345d2f3e73bcf08d47f02c02976730620d7f844313c099894176980b860d56a6034613c0db14cad99e0d2dc3a2482ff8167a032218ac10508bb04fb8ef91d40a6ef0731f1e162761f09be237800363199f518a1bad98f9f2d179d2028137f9a86588c5cd91534a53d4edcc718b40aab61343571636d052eb7b288578c80b86025138a99de6619b2ad03707f847ac0f5d79b0fba2c67a02f5430a57c7a651d6cd63988cb91aa331acd8b7221a41fc4007be73ad86365de5029c22186d2c90a864fd3d386cc074b25f33b4e5f17839d2780b62390f1fe63ec690c1022c039f500b860c1e12e9c0b26d73c27dd5f60f08aa15c952afaa395dbc8b4cb99453bbf3f14ede8a9fc579f64500497344cb3637aa900ac8618d237580558d9ab5b042ac411fd121713744378c9f4d897907f09a71af9331bfecb3853e3f0577be558c9019881b860c8e6cf45b640fa91385b4f7e891fe68e5ef6847d032d6ee1b52eef0ff577ad796b881537f94adcbd1b52ba3e0e5d7e014e97406029095598a373fd6d9b6c7754aa87b87560e363faee89c11482cae4a063d7cbe65747f2b095cd2f6688a8bd00b86008fb22b9fe04caf62059216dfa1d2274ade1df9e8dc0b3c37c2f04a8b3d30a73f8b7ddd873d08c9b9302b936d303380147ce0e19c4600b780a1814730462147fb8280fbd7fe0aa7290d325a2b7b5092e05c037664a0aaea127b0d95fd13e3d81b86068dd5abe43baf4f4817a49b094c0bb19ed4971c49a6f91863163f655b6f312d80b7c7843b4cb7a27f7e54d48c41c7a01c5e22e1b0e38a5dbb03dfee76076a9af56146359add6003410005332417f6b65db718acce693cfa21a8fd92f6ad72800b86091785b64cfd3ac6025b6b536499ac63868344b8f86660ed73b574b000477807d53dacf1d9da258ee1b113485a01579001c5a510dd3b3c5ff1f417c4d97faf997aecedf7602bd96155f8396f5c9fa53d2c601b0de0241fff49939b8a97ce59f81b86000d869e78871139e8a5ff6d590593d94ea39ea73e87ac8d901f0f524372b93752a488b34e05afe05ab53b1c1b5b9a50040341dc01361110551358c9e982f30755e19ec2ad1c1a40afba9998f763599149b976caaded14c1793fe8c469b17c900b860e87f2bfc49c076239d7522280098c9c4808524c67f3891608c42a510340d64c7e3c1c074c34050007837c13536ee4001108efc87fb2eb8c3236a738122ec086a7b8e6857e82454ff6284a81bf0362424ba96be762d4c06e6aa1b59f20c870780b8608bd2cb218f465c82702aba73a061227cd83dd8e3115ae592811a4d9a8236e3cb99cfe81b2e22e3620635d42f63b7db00cd546bdf9fad7b49d0b4686962c8e0f4544c8df9f41d30d7d489c86745ef9b61a7dfb498f7554eeaf7e24654e5b2e080b8602a5d5145b7a8100575e96cadf2513e7e64dc1354bd891a24f985c2574c9f5f136c6837eab290543d769227785520970133022637837b6e711918f3d2e98291bf3b518247b54e925a0cd080d517731b2725be888fca298ae9ec6f5d2c19146b01b8609cedde7d49e2e115896b789ece09a4e8816fae153de891774f0f716a3088e01754498f8ab82d3a4ef5d53dbe17338f0089d1de1eb60bfe3ec2b9701cd882b1c174bdcfaac2225f57481676bd3ee845825be823b9f9317e407b015159b9ce7e80b8609124b91b223bf9bcb33f75ab8fad0180fdc57536d34349945b80458abc8e59cb06005fabea656b2cd0dc74c0d06160019706965ec3ee0d3b9dd76eb9d39158bd512fe7384bb9e139bc6391d5f7b969397bd85a91bb91670880d861e8fcbd0700b860338fa194daae9ba1245931653fa349ce85d37e2f42f871c6b67397401e190b497d15ff23e8f6e9d8637f84fc2dd4640066fee692f5d38208233e7570c3ed49a4ba032d79c7a974883fa5b5c2a113259b924a346bc4edaf717b3d272ceb152980b8606150a62f3bae3a35a639d66dc37ffbc979dda85d6f5c278a5e3a563ed865018c86563be9b878261ef8d34edd3c313500a4f170e22f386674d538b9e15930f39216a38c2a0b60380a140e5897f42d37077784cd0f1a93746e4da42a5da8de1081b8605fd1581e41fa22e7ea0d3ee0674e80e2168fdb42c1aaa3eb8aa395fdde11de5ca98ee71c50b365ef6ad9850bacf7ab011eb446da79efba3ae91fe1f7d9274dacda39b0b3bfaec7d7904eac59d72683c52b6ea091ca1374d8b744fd1d595c5700b860e04a671c7f9af919093a9c7aaf5c3d04eff31189d65f5a2aef8a08119ed1c150464c40085bfe2fc1b598fc2ebb095101d0103b995e3a762a9063d823ef6686422caa5a390f9cef5ee6c4b911fd2a818f43fa47ab4d21b01cc7b071b517438d81b86014cfe4d455820e0b9189ccb32b565b90d414ed7d315d3e61141f085b6aaea34b0c90d1f502f544408e7ed0573e1d1701d38063b239cf847018daa41b7ef75b4458d2fa23e459e9e8039668aca6bc70df1051a6466a5a5bc636e68bc8e2380a80b86045bab7cfb2814e1e3e1a40779219bb48c5d51419ce4c27359d0dfea9fbf1d193ca1cf07934ebf3d6699093387d0e0f000dc5fd2058e7ac50e67c26e5172567c2e7ba9fefa6376e44de800c8955cb330df27476d8ba9c8ec06bba46fddeb95e81b860a9fc64c64c039cbd8b23c10c706e51e0013289201111cf8c50e22781161df397fa9c1b91dbab44969aa4f8819f222e01bab90190bebfaecff7076de325dae8080bfe921fbb4ca474d45126fe5ae699dadea98a5255c048b955ab9ba1de8f4c01b860aa5729ac27a01f26924e863eea7d7b49e4f8ccb15c758ea5ac4d19691a8df31f70138e7f3011fc1e53d52d7063dd8d01a9b3800a66914956769a13ff8d7960725bf1b9073052f3ff85e57b34165702baede05d4e807bfb565a38c24e3542c780b86014dafe41c0d96b22188f0cf6cb99274e09d8ed0546bb57b28a3590449726aedf809c049663a2fe4e40b91830ac864d006a9c5b41cbddeabeef99cfddf6c298de0d482b6e945993241d8987f7fac004fe159f2206060b69d1f8f7f67f63f26280b860878790bb38b1d31707aa37b5af439d64d4a29ea64418b7c01139a26e4f297da6c61a806361e6fee8e40556500c8a6000183b2a42c54d714a143fe12492081f373e3e27e3921adeb276a8daac8b87a534c0fa1d45195d8a35cbda27f883128680b8607983d25868e1915ca8c20603bb70475b398acb04fef221106475f0fc25a3df25d181050214da347bfcd8f8292e5257014ba77cf67ee5f42202257317808f126930b4eaaf4bec801c4465ced54bd78331f8d3dadfdf2f91de294836c13e946001b860c700f20fab4ebb8ba2f47adf177e3a9dbbfb8d999acbaf0055cc540758f8c00c4564813d910e7be02e4ceaa97fb88000b3e8e6fb4308fb943fa0a3d8ee32c3a16e67eae0817370de54bec1e13193cc845cedb70e48171e097550475684cc6600b8603a3857a5e4a709e1891a13797d55c1698f931755492099926314feec955da31fcea8a8c8e52ce2efd74008f32dbc1c00c1b3d36c1f3097d806f1687eff4a979ff967a8233f923a1af6a3104c12d9d44388bece91a248bd86f253e709cea7a380b860d8704fbf6968ffd9f39f78173726dfebbaaffebd8a33dfe29a72b9a64204debf2016ca94cbecb1b84cab9d5cc168f70082530b8cfab0225a37c8cc3044c288ab0fea2f484b56a33fe6c92d6c50f254e6b1689ac6bb1429cc36a0a7dfa85cf880b86089bc906b5ea07752b1981558fd5d329f6d428bc14dfde022745303eae0077612b9c473cd66e4d91778282ec98bbd74001b61cd71448750df642fb580ce81a62ff2f5ab4378528ccd65acff67ac2175678f598529c768247c77938ca2d529aa01b860fb9de050c059a11175be23daeef1bfc374a688d8fd776e7d2dc81fe301068a3af03ad522bd915a154dc8b5b8e12d38003f17bf9f3001e8bc682e38cfc93c6901417afe1ddbfe11b04f42ca4f321f7ba73fa98f0e8c8d75781b14c0dea847a500b860bef17561ef747e0f11fd339987a9813fa8ac1cbbd6457ab8fae4841f2217de019de7caf421631372b7eec730d9210d0128e6c560948c19ab6141d6699e0283a5b98abb8266d731f2b6435a07b44360a3f5622cff59103ec95938ab74fe1d8f01b860a47fd022dda04d8dd36e0a8127be68736e47e490b946d2d88a9fdcca0a5114a930db2319e7e9f378d1b81da865d38b01a063e9994e620483b08047da39ee2fba35f66df5734e1545d297be0225ddfda34e494c1f09825eed303d166a8b702f01b8605966b41d69c0e94e202f65823338c3ee0357b024a6ef625765bcf3c20e1786258a18221e0b9a34b43380e06984d92f0183d0f86d0dfe0cac237ee38b28876dada3ae9d1a7c1e6627c3b524d0e5d4270bbe159661622821412b3c1162881ead80b8608fad3c2111494834f30e6d8a3368f2aa156c991fa4b9d55c31da88310a61248305697ad5e885404bc474419383de4f006c89c84955321716f6ceb4d5db433fcabe843d566a5e9526d29c58b38fda9ff2a13f7841f25cda8ff091c965bdf91780b8607f9df4fdb96e20e0a480a62c48896646d96982d7fccccdf70c61f2f52ab4ea2901b5ef468203f39d9d8325843ada0d00e9562c64f79ec16d69b5921ad36306ae9ae2ab97806b354af8cb63722a96aed5fa0542fff58d2e41f6aee3cb641f7781b8609cc39207797e5c37f6336c4444cf275d0afd43a9b257a08086f15867886833744c9b5753fcff76fce3790d7f25a45e004af9831464bf43e39634ecfce8da4641da78ad4ba20e540c007dbc19e391ae69cfb7809b2d20627d553a16d7d71b5a80b860e6631bd0b82c41327b582d7b239c9893cd1162cae05f360d8808700b38ee0ee965e9bd9246d79e00c234c87aa7699800c73428f7eccd77337bf79bf6b43f48345be265c38d128d2cd7f37167cadb3565d66e6a7f67b12f4bed63e5d50748010080b8410000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f86480b86000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080f86480b86000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080", + "difficulty": "0x1", + "coinbase": "0x0000000000000000000000000000000000000000", + "alloc": { + "0x11901cf7eEae1E2644995FB2E47Ce46bC7F33246": { + "balance": "120000000000000000000000000" + }, + "0xC1cDA18694F5B86cFB80c1B4f8Cc046B0d7E6326": { + "balance": "20000000000000000000000000" + }, + "0xa5d40D93b01AfBafec84E20018Aff427628F645E": { + "balance": "20000000000000000000000000" + }, + "0x8d485780E84E23437f8F6938D96B964645529127": { + "balance": "20000000000000000000000000" + }, + "0x5F857c501b73ddFA804234f1f1418D6f75554076": { + "balance": "20000000000000000000000000" + }, + "0xaa9064F57F8d7de4b3e08c35561E21Afd6341390": { + "balance": "20000000000000000000000000" + }, + "0x7FA26b50b3e9a2eC8AD1850a4c4FBBF94D806E95": { + "balance": "20000000000000000000000000" + }, + "0x08960Ce6b58BE32FBc6aC1489d04364B4f7dC216": { + "balance": "20000000000000000000000000" + }, + "0x77B68B2e7091D4F242a8Af89F200Af941433C6d8": { + "balance": "20000000000000000000000000" + }, + "0x75Bb69C002C43f5a26a2A620518775795Fd45ecf": { + "balance": "20000000000000000000000000" + }, + "0x19992AE48914a178Bf138665CffDD8CD79b99513": { + "balance": "20000000000000000000000000" + }, + "0xE23a4c6615669526Ab58E9c37088bee4eD2b2dEE": { + "balance": "20000000000000000000000" + }, + "0xDe22679dCA843B424FD0BBd70A22D5F5a4B94fe4": { + "balance": "10200014000000000000000000" + }, + "0x743D80810fe10c5C3346D2940997cC9647035B13": { + "balance": "20513322000000000000000000" + }, + "0x8e1c4355307F1A59E7eD4Ae057c51368b9338C38": { + "balance": "7291740000000000000000000" + }, + "0x417fe63186C388812e342c85FF87187Dc584C630": { + "balance": "20000062000000000000000000" + }, + "0xF5720c180a6Fa14ECcE82FB1bB060A39E93A263c": { + "balance": "30000061000000000000000000" + }, + "0xB80d1e7F9CEbe4b5E1B1Acf037d3a44871105041": { + "balance": "9581366833333333333333335" + }, + "0xf8ed78A113cD2a34dF451Ba3D540FFAE66829AA0": { + "balance": "11218686833333333333333333" + }, + "0x9033ff75af27222c8f36a148800c7331581933F3": { + "balance": "11218686833333333333333333" + }, + "0x8A07541C2eF161F4e3f8de7c7894718dA26626B2": { + "balance": "11218686833333333333333333" + }, + "0xB2fe7AFe178335CEc3564d7671EEbD7634C626B0": { + "balance": "11218686833333333333333333" + }, + "0xc471776eA02705004C451959129bF09423B56526": { + "balance": "11218686833333333333333333" + }, + "0xeF283eca68DE87E051D427b4be152A7403110647": { + "balance": "14375000000000000000000000" + }, + "0x7cf091C954ed7E9304452d31fd59999505Ddcb7a": { + "balance": "14375000000000000000000000" + }, + "0xa5d2944C32a8D7b284fF0b84c20fDcc46937Cf64": { + "balance": "14375000000000000000000000" + }, + "0xFC89C17525f08F2Bc9bA8cb77BcF05055B1F7059": { + "balance": "14375000000000000000000000" + }, + "0x3Fa7C646599F3174380BD9a7B6efCde90b5d129d": { + "balance": "14375000000000000000000000" + }, + "0x989e1a3B344A43911e02cCC609D469fbc15AB1F1": { + "balance": "14375000000000000000000000" + }, + "0xAe1d640648009DbE0Aa4485d3BfBB68C37710924": { + "balance": "20025000000000000000000000" + }, + "0x1B6C64779F42BA6B54C853Ab70171aCd81b072F7": { + "balance": "20025000000000000000000000" + }, + "000000000000000000000000000000000000ce10": { + "code": "0x60806040526004361061004a5760003560e01c806303386ba3146101e757806342404e0714610280578063bb913f41146102d7578063d29d44ee14610328578063f7e6af8014610379575b6000600160405180807f656970313936372e70726f78792e696d706c656d656e746174696f6e00000000815250601c019050604051809103902060001c0360001b9050600081549050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610136576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f4e6f20496d706c656d656e746174696f6e20736574000000000000000000000081525060200191505060405180910390fd5b61013f816103d0565b6101b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f496e76616c696420636f6e74726163742061646472657373000000000000000081525060200191505060405180910390fd5b60405136810160405236600082376000803683855af43d604051818101604052816000823e82600081146101e3578282f35b8282fd5b61027e600480360360408110156101fd57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019064010000000081111561023a57600080fd5b82018360208201111561024c57600080fd5b8035906020019184600183028401116401000000008311171561026e57600080fd5b909192939192939050505061041b565b005b34801561028c57600080fd5b506102956105c1565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156102e357600080fd5b50610326600480360360208110156102fa57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061060d565b005b34801561033457600080fd5b506103776004803603602081101561034b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506107bd565b005b34801561038557600080fd5b5061038e610871565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b60008060007fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47060001b9050833f915080821415801561041257506000801b8214155b92505050919050565b610423610871565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146104c3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f73656e64657220776173206e6f74206f776e657200000000000000000000000081525060200191505060405180910390fd5b6104cc8361060d565b600060608473ffffffffffffffffffffffffffffffffffffffff168484604051808383808284378083019250505092505050600060405180830381855af49150503d8060008114610539576040519150601f19603f3d011682016040523d82523d6000602084013e61053e565b606091505b508092508193505050816105ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f696e697469616c697a6174696f6e2063616c6c6261636b206661696c6564000081525060200191505060405180910390fd5b5050505050565b600080600160405180807f656970313936372e70726f78792e696d706c656d656e746174696f6e00000000815250601c019050604051809103902060001c0360001b9050805491505090565b610615610871565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146106b5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f73656e64657220776173206e6f74206f776e657200000000000000000000000081525060200191505060405180910390fd5b6000600160405180807f656970313936372e70726f78792e696d706c656d656e746174696f6e00000000815250601c019050604051809103902060001c0360001b9050610701826103d0565b610773576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f496e76616c696420636f6e74726163742061646472657373000000000000000081525060200191505060405180910390fd5b8181558173ffffffffffffffffffffffffffffffffffffffff167fab64f92ab780ecbf4f3866f57cee465ff36c89450dcce20237ca7a8d81fb7d1360405160405180910390a25050565b6107c5610871565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610865576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f73656e64657220776173206e6f74206f776e657200000000000000000000000081525060200191505060405180910390fd5b61086e816108bd565b50565b600080600160405180807f656970313936372e70726f78792e61646d696e000000000000000000000000008152506013019050604051809103902060001c0360001b9050805491505090565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610960576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f6f776e65722063616e6e6f74206265203000000000000000000000000000000081525060200191505060405180910390fd5b6000600160405180807f656970313936372e70726f78792e61646d696e000000000000000000000000008152506013019050604051809103902060001c0360001b90508181558173ffffffffffffffffffffffffffffffffffffffff167f50146d0e3c60aa1d17a70635b05494f864e86144a2201275021014fbf08bafe260405160405180910390a2505056fea165627a7a723058206808dd43e7d765afca53fe439122bc5eac16d708ce7d463451be5042426f101f0029", + "storage": { + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0xE23a4c6615669526Ab58E9c37088bee4eD2b2dEE" + }, + "balance": "0" + } + }, + "number": "0x0", + "gasUsed": "0x0", + "mixHash": "0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000" +} diff --git a/start.sh b/start.sh new file mode 100755 index 0000000000..06429adee8 --- /dev/null +++ b/start.sh @@ -0,0 +1,25 @@ +#!/bin/sh + +case "$1" in + validator) + ./build/bin/geth --datadir ~/mydata/datadir --syncmode full --gcmode archive --debug --port 30303 --rpcvhosts='*' --networkid 1101 --verbosity=3 --consoleoutput=stdout --consoleformat=term --nat extip:127.0.0.1 --allow-insecure-unlock --rpc --rpcport 8545 --rpccorsdomain='*' --rpcapi=eth,net,web3,debug,admin,personal,txpool,istanbul --light.serve=0 --mine --minerthreads=10 --nodekeyhex=add67e37fdf5c26743d295b1af6d9b50f2785a6b60bc83a8f05bd1dd4b385c6c --istanbul.blockperiod 10 --nodiscover --password=/dev/null --unlock=0 --ws --wsaddr 0.0.0.0 --rpcaddr 0.0.0.0 --wsapi=eth,net,web3,debug,personal --wsorigins='*' --wsport 8546 + ;; + fast) + ./build/bin/geth --datadir ~/fasttest/validator --syncmode full --gcmode archive --debug --port 30303 --rpcvhosts='*' --networkid 1101 --verbosity=3 --consoleoutput=stdout --consoleformat=term --nat extip:127.0.0.1 --allow-insecure-unlock --rpc --rpcport 8545 --rpccorsdomain='*' --rpcapi=eth,net,web3,debug,admin,personal,txpool,istanbul --light.serve=0 --mine --minerthreads=10 --nodekeyhex=add67e37fdf5c26743d295b1af6d9b50f2785a6b60bc83a8f05bd1dd4b385c6c --istanbul.blockperiod 1 --nodiscover --password=/dev/null --unlock=0 --ws --wsaddr 0.0.0.0 --rpcaddr 0.0.0.0 --wsapi=eth,net,web3,debug,personal --wsorigins='*' --wsport 8546 + ;; + node) + ./build/bin/geth --datadir ~/mydata/nextnode --syncmode full --debug --port 30301 --rpcvhosts='*' --networkid 1101 --verbosity=3 --nat extip:127.0.0.1 --allow-insecure-unlock --rpc --rpcport 9545 --istanbul.blockperiod 1 --rpccorsdomain='*' --rpcapi=eth,net,web3,debug,admin,personal,txpool,istanbul --light.serve=0 --nodiscover --unlock=0xfD5d2142281fbfA75439f94774506fE76641CDd6 --password=asd + ;; + spammer) + celo --datadir ~/mydata/spammer --syncmode full --debug --port 30302 --rpcvhosts='*' --networkid 1101 --verbosity=3 --nat extip:127.0.0.1 --allow-insecure-unlock --rpc --rpcport 10545 --rpccorsdomain='*' --rpcapi=eth,net,web3,debug,admin,personal,txpool,istanbul --light.serve=0 --nodiscover --unlock=0xAdB5B5DfB87dd7652796c3b91Ff27001d55CCca6 --password=asd + ;; + faulty) + celo --datadir ~/mydata/faulty --syncmode full --debug --port 30302 --rpcvhosts='*' --networkid 1101 --verbosity=3 --nat extip:127.0.0.1 --allow-insecure-unlock --rpc --rpcport 10545 --rpccorsdomain='*' --rpcapi=eth,net,web3,debug,admin,personal,txpool,istanbul --light.serve=0 --nodiscover + ;; + connect) + ./build/bin/geth --datadir ~/mydata/datadir attach --exec 'admin.addPeer("enode://619702d99a2c3161ab816e0e1ca82abba8ab95edbb7702903f9052204b2c8194affbf6564d822643f7a24ef97eb42982c966b4b1857a8f3e2b3a9ef32b519570@127.0.0.1:30301")' + ./build/bin/geth --datadir ~/mydata/datadir attach --exec 'admin.addPeer("enode://a1403c44bad29b0efd734f4629484c7da8d52f28dbbc4bc2d96a222aa883549be5abc6f0adbf79259cbe82ec9b8452c2b2b35b960a2f99ef50b33909f48b1f0d@127.0.0.1:30302")' + ;; +esac + +# ./build/bin/geth --datadir ~/mydata/datadir --syncmode full --gcmode archive --debug --port 30303 --rpcvhosts='*' --networkid 1101 --verbosity=3 --consoleoutput=stdout --consoleformat=term --nat extip:127.0.0.1 --allow-insecure-unlock --rpc --rpcport 8545 --rpccorsdomain='*' --rpcapi=eth,net,web3,debug,admin,personal,txpool,istanbul --light.serve=0 --mine --minerthreads=10 --nodekeyhex=add67e37fdf5c26743d295b1af6d9b50f2785a6b60bc83a8f05bd1dd4b385c6c --istanbul.blockperiod 10 --nodiscover --password=/dev/null --unlock=0 --ws --wsaddr 0.0.0.0 --rpcaddr 0.0.0.0 --wsapi=eth,net,web3,debug,personal --wsorigins='*' --wsport 8546 diff --git a/trie/sync.go b/trie/sync.go index e5a0c17493..f21a919c75 100644 --- a/trie/sync.go +++ b/trie/sync.go @@ -99,7 +99,7 @@ func (s *Sync) AddSubTrie(root common.Hash, depth int, parent common.Hash, callb if _, ok := s.membatch.batch[root]; ok { return } - if s.bloom.Contains(root[:]) { + if s.bloom == nil || s.bloom.Contains(root[:]) { // Bloom filter says this might be a duplicate, double check blob, _ := s.database.Get(root[:]) if local, err := decodeNode(root[:], blob); local != nil && err == nil { @@ -138,7 +138,7 @@ func (s *Sync) AddRawEntry(hash common.Hash, depth int, parent common.Hash) { if _, ok := s.membatch.batch[hash]; ok { return } - if s.bloom.Contains(hash[:]) { + if s.bloom == nil || s.bloom.Contains(hash[:]) { // Bloom filter says this might be a duplicate, double check if ok, _ := s.database.Has(hash[:]); ok { return @@ -300,7 +300,7 @@ func (s *Sync) children(req *request, object node) ([]*request, error) { if _, ok := s.membatch.batch[hash]; ok { continue } - if s.bloom.Contains(node) { + if s.bloom == nil || s.bloom.Contains(node) { // Bloom filter says this might be a duplicate, double check if ok, _ := s.database.Has(node); ok { continue From 29822ad47728588a2ce3946deba86703009a55cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sami=20M=C3=A4kel=C3=A4?= Date: Mon, 14 Sep 2020 18:05:14 +0300 Subject: [PATCH 02/15] cleanup --- alfa.json | 138 ---------------------------------- asd | 1 - core/blockchain.go | 6 +- core/rawdb/freezer.go | 1 + eth/downloader/downloader.go | 10 +-- eth/handler.go | 2 + eth/sync.go | 67 +++++------------ foo | 141 ----------------------------------- genesis.json | 88 ---------------------- geth | 107 -------------------------- hmmm | 27 ------- params/network_params.go | 2 +- rc.json | 133 --------------------------------- start.sh | 25 ------- 14 files changed, 31 insertions(+), 717 deletions(-) delete mode 100644 alfa.json delete mode 100644 asd delete mode 100644 foo delete mode 100644 genesis.json delete mode 100644 geth delete mode 100644 hmmm delete mode 100644 rc.json delete mode 100755 start.sh diff --git a/alfa.json b/alfa.json deleted file mode 100644 index 3db4bc03ce..0000000000 --- a/alfa.json +++ /dev/null @@ -1,138 +0,0 @@ -{ - "config": { - "homesteadBlock": 0, - "eip150Block": 0, - "eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "eip155Block": 0, - "eip158Block": 0, - "byzantiumBlock": 0, - "constantinopleBlock": 0, - "petersburgBlock": 0, - "chainId": 44786, - "istanbul": { - "policy": 2, - "blockperiod": 5, - "requesttimeout": 10000, - "epoch": 17280, - "lookbackwindow": 12 - } - }, - "nonce": "0x0", - "timestamp": "0x5b843511", - "gasLimit": "0x8000000", - "extraData": "0x0000000000000000000000000000000000000000000000000000000000000000f905bbf8d294456f41406b32c45d59e539e4bba3d7898c3584da94dd1f519f63423045f526b8c83edc0eb4ba6434a494050f34537f5b2a00b9b9c752cb8500a3fce3da7d94cda518f6b5a797c3ec45d37c65b83e0b0748edca94b4e92c94a2712e98c020a81868264bde52c188cb94ae1ec841923811219b98aceb1db297aade2f46f394621843731fe33418007c06ee48cfd71e0ea828d9942a43f97f8bf959e31f69a894ebd80a88572c855394ad682035be6ab6f06e478d2bdab0eab6477b460e9430d060f129817c4de5fbc1366d53e19f43c8c64ff903d4b86011877b768127c8eb0f122fbe69553bc9d142d27c06a85c6eeb7b8b457f511e50c33a57fcbc5fd6d1823f69a111f8010151a17f6a8798a25343f5403b1e6a595c7d9698af3db78b013d26a761fc201b3cf793be5f0a0a849b3f68a8bfa81e7001b860d882cd4cc09109928e9517644d5303610155978cf5e3b7ad6122daa19c3dab3da8c439bc763d6d3eef18a38ebb0d3200664b94fab11adbb3f44b963969763b590af45931c482396be88a185214c9c8690615aae5197e852bc1d04b3dbd03ab80b86051588d46ba8998d944a30cde93bfe946e774ef1f6fe2fb559a74ffebf60d1ad967b876a038c6e312d0c20752cbc8440012293b6ea417f32a163caedeaaae7aad3c1b31be1fe86c405924b1be7d0aaae6f3ba567ee907d0d4c00dce5091442380b8601f2becc31c1f0141e8c5768c5f07d02d1342c086c037cce70aaf3629b40ea017884a81163f58697b020b21fe39c440006970bc1f52b847d7262599ae92ee7db45ad38efe5612c8ed42d9db9380da0769bab713f5259b7c015998296bf02a0a01b860d02ec615b916bba4fe7e65a3d79e607aa27bb5a84b0c2f242e9d8f379512cf40051a43030e55aca965d91c905b656d006434d95b7034bfc2e5e2ef7384e8cd640efae740558216f6f9db24c6d1acf755746dfbb68c76961593741105725d5680b860d6e86d5e73db3b3a2c96c6caa1a7e153e17adb13fb541943a44bfa90beab38aa73ad453d918fea2ba57c0a67115d0401c56946d8894f346d796864e9344fd1439dd1345de762f85d7e18e311b35c3cbe492886ef8bc872b4aabfa23c2e38a901b8601cf59939da60cdb9aff09f76e6070a17fa21356ca7016390ef4444243e12ab7ed7a233d7ca48b0d17870ba015a4410014e5cac8d456e03ec2908d347627d5e9ecd496ce990d10900ddc529300eef3d037e48d79f03ad2b6bcd48affe2ddf2681b8601cfe8876c0b89ef15128bb27eb69e7939b4a888b0a81195d5fd1bbda748a29838274e652dcf857f4090bb85343055300ca3e75a980b100403d3b6d34f62c6a86bbd75203391c63dd405725c69241a828e6892f623ed5b35c8dc132b032061201b860a6fc71d63c5adedb7b30b9e0ba3d83debf86d12ba235c13584a9cbad410f082030427be4f8a9127889979c3eea58860031af128deece487df5aef9d999c8dc2fb51f308eb1ee229e6bbd6860138d4fcf4209eb7bec62ca70dd8643104003c200b8606b7adb5d01e3fd72ae2c4ff17e6620dc383431e0ebe06c9af5b94207f380287429043e7bbe417b82d0aed2e43dc7b8002bb52886773e4a2c23bf0ebfd401471e8da3cf3a0a7e0949d9ad4de38138a787a975993ba311525ce8be331cd60d670080b8410000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f86480b86000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080f86480b86000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080", - "difficulty": "0x1", - "coinbase": "0x0000000000000000000000000000000000000000", - "alloc": { - "456f41406B32c45D59E539e4BBA3D7898c3584dA": { - "balance": "103010030000000000000000000" - }, - "DD1F519F63423045F526b8c83edC0eB4BA6434a4": { - "balance": "10011000000000000000000" - }, - "050f34537F5b2a00B9B9C752Cb8500a3fcE3DA7d": { - "balance": "10011000000000000000000" - }, - "Cda518F6b5a797C3EC45D37c65b83e0b0748eDca": { - "balance": "10011000000000000000000" - }, - "b4e92c94A2712e98c020A81868264bdE52C188Cb": { - "balance": "10011000000000000000000" - }, - "Ae1ec841923811219b98ACeB1db297AADE2F46F3": { - "balance": "10011000000000000000000" - }, - "621843731fe33418007C06ee48CfD71e0ea828d9": { - "balance": "10011000000000000000000" - }, - "2A43f97f8BF959E31F69A894ebD80A88572C8553": { - "balance": "10011000000000000000000" - }, - "AD682035bE6Ab6f06e478D2BDab0EAb6477B460E": { - "balance": "10011000000000000000000" - }, - "30D060F129817c4DE5fBc1366d53e19f43c8c64f": { - "balance": "10011000000000000000000" - }, - "22579CA45eE22E2E16dDF72D955D6cf4c767B0eF": { - "balance": "10011000000000000000000" - }, - "1173C5A50bf025e8356823a068E396ccF2bE696C": { - "balance": "10011000000000000000000" - }, - "40F71B525A96baa8d14Eaa7Bcd19929782659c64": { - "balance": "10011000000000000000000" - }, - "b923626C6f1d237252793FB2aA12BA21328C51BC": { - "balance": "10011000000000000000000" - }, - "B70f9ABf41F36B3ab60cc9aE1a85Ddda3C88D261": { - "balance": "10011000000000000000000" - }, - "d4369DB59eaDc4Cfa089c0a3c1004ceAb1b318D8": { - "balance": "10011000000000000000000" - }, - "2fd430d3a96eadc38cc1B38b6685C5f52Cf7a083": { - "balance": "10011000000000000000000" - }, - "Fecc71C8f33Ca5952534fd346ADdeDC38DBb9cb7": { - "balance": "10011000000000000000000" - }, - "0de78C89e7BF5060f28dd3f820C15C4A6A81AFB5": { - "balance": "10011000000000000000000" - }, - "75411b92fcE120C1e7fd171b1c2bF802f2E3CF48": { - "balance": "10011000000000000000000" - }, - "563433bD8357b06982Fe001df20B2b43393d21d2": { - "balance": "10011000000000000000000" - }, - "79dfB9d2367E7921d4139D7841d24ED82F48907F": { - "balance": "10011000000000000000000" - }, - "5809369FC5121a071eE67659a975e88ae40fBE3b": { - "balance": "10011000000000000000000" - }, - "7517E54a456bcc6c5c695B5d9f97EBc05d29a824": { - "balance": "10011000000000000000000" - }, - "B0a1A5Ffcb34E6Fa278D2b40613f0AE1042d32f8": { - "balance": "10011000000000000000000" - }, - "EeE9f4DDf49976251E84182AbfD3300Ee58D12aa": { - "balance": "10011000000000000000000" - }, - "Eb5Fd57f87a4e1c7bAa53ec1c0d021bb1710B743": { - "balance": "10011000000000000000000" - }, - "B7Dd51bFb73c5753778e5Af56f1D9669BCe6777F": { - "balance": "10011000000000000000000" - }, - "33C222BB13C63295AF32D6C91278AA34b573e776": { - "balance": "10011000000000000000000" - }, - "83c58603bF72DA067D7f6238E7bF390d91B2f531": { - "balance": "10011000000000000000000" - }, - "6651112198C0da05921355642a2B8dF1fA3Ede93": { - "balance": "10011000000000000000000" - }, - "4EE72A98549eA7CF774C3E2E1b39fF166b4b68BE": { - "balance": "10011000000000000000000" - }, - "840b32F30e1a3b2E8b9E6C0972eBa0148E22B847": { - "balance": "100000000000000000000" - }, - "000000000000000000000000000000000000ce10": { - "code": "0x60806040526004361061004a5760003560e01c806303386ba3146101e757806342404e0714610280578063bb913f41146102d7578063d29d44ee14610328578063f7e6af8014610379575b6000600160405180807f656970313936372e70726f78792e696d706c656d656e746174696f6e00000000815250601c019050604051809103902060001c0360001b9050600081549050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610136576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f4e6f20496d706c656d656e746174696f6e20736574000000000000000000000081525060200191505060405180910390fd5b61013f816103d0565b6101b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f496e76616c696420636f6e74726163742061646472657373000000000000000081525060200191505060405180910390fd5b60405136810160405236600082376000803683855af43d604051818101604052816000823e82600081146101e3578282f35b8282fd5b61027e600480360360408110156101fd57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019064010000000081111561023a57600080fd5b82018360208201111561024c57600080fd5b8035906020019184600183028401116401000000008311171561026e57600080fd5b909192939192939050505061041b565b005b34801561028c57600080fd5b506102956105c1565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156102e357600080fd5b50610326600480360360208110156102fa57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061060d565b005b34801561033457600080fd5b506103776004803603602081101561034b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506107bd565b005b34801561038557600080fd5b5061038e610871565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b60008060007fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47060001b9050833f915080821415801561041257506000801b8214155b92505050919050565b610423610871565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146104c3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f73656e64657220776173206e6f74206f776e657200000000000000000000000081525060200191505060405180910390fd5b6104cc8361060d565b600060608473ffffffffffffffffffffffffffffffffffffffff168484604051808383808284378083019250505092505050600060405180830381855af49150503d8060008114610539576040519150601f19603f3d011682016040523d82523d6000602084013e61053e565b606091505b508092508193505050816105ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f696e697469616c697a6174696f6e2063616c6c6261636b206661696c6564000081525060200191505060405180910390fd5b5050505050565b600080600160405180807f656970313936372e70726f78792e696d706c656d656e746174696f6e00000000815250601c019050604051809103902060001c0360001b9050805491505090565b610615610871565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146106b5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f73656e64657220776173206e6f74206f776e657200000000000000000000000081525060200191505060405180910390fd5b6000600160405180807f656970313936372e70726f78792e696d706c656d656e746174696f6e00000000815250601c019050604051809103902060001c0360001b9050610701826103d0565b610773576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f496e76616c696420636f6e74726163742061646472657373000000000000000081525060200191505060405180910390fd5b8181558173ffffffffffffffffffffffffffffffffffffffff167fab64f92ab780ecbf4f3866f57cee465ff36c89450dcce20237ca7a8d81fb7d1360405160405180910390a25050565b6107c5610871565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610865576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f73656e64657220776173206e6f74206f776e657200000000000000000000000081525060200191505060405180910390fd5b61086e816108bd565b50565b600080600160405180807f656970313936372e70726f78792e61646d696e000000000000000000000000008152506013019050604051809103902060001c0360001b9050805491505090565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610960576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f6f776e65722063616e6e6f74206265203000000000000000000000000000000081525060200191505060405180910390fd5b6000600160405180807f656970313936372e70726f78792e61646d696e000000000000000000000000008152506013019050604051809103902060001c0360001b90508181558173ffffffffffffffffffffffffffffffffffffffff167f50146d0e3c60aa1d17a70635b05494f864e86144a2201275021014fbf08bafe260405160405180910390a2505056fea165627a7a723058202fea0aaff5e8ef394bc5402f16883d44f3d1c8ecb844dbd140aa075b8492ee060029", - "storage": { - "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "456f41406B32c45D59E539e4BBA3D7898c3584dA" - }, - "balance": "0" - } - }, - "number": "0x0", - "gasUsed": "0x0", - "mixHash": "0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365", - "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000" -} \ No newline at end of file diff --git a/asd b/asd deleted file mode 100644 index d72af31460..0000000000 --- a/asd +++ /dev/null @@ -1 +0,0 @@ -asd diff --git a/core/blockchain.go b/core/blockchain.go index 66c5c03bcb..9e7d6e6fa4 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -125,8 +125,6 @@ var defaultCacheConfig = &CacheConfig{ TrieCleanLimit: 256, TrieDirtyLimit: 256, TrieTimeLimit: 5 * time.Minute, - SnapshotLimit: 256, - SnapshotWait: true, } // BlockChain represents the canonical chain given a database with a genesis @@ -251,7 +249,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par } // Make sure the state associated with the block is available head := bc.CurrentBlock() - if _, err := state.New(head.Root(), bc.stateCache, bc.snaps); err != nil { + if _, err := state.New(head.Root(), bc.stateCache); err != nil { log.Warn("Head state missing, repairing", "number", head.Number(), "hash", head.Hash()) if err := bc.SetHead(head.NumberU64()); err != nil { return nil, err @@ -422,7 +420,7 @@ func (bc *BlockChain) SetHead(head uint64) error { } else { // Block exists, keep rewinding until we find one with state for { - if _, err := state.New(newHeadBlock.Root(), bc.stateCache, bc.snaps); err != nil { + if _, err := state.New(newHeadBlock.Root(), bc.stateCache); err != nil { log.Trace("Block state missing, rewinding further", "number", newHeadBlock.NumberU64(), "hash", newHeadBlock.Hash()) if pivot == nil || newHeadBlock.NumberU64() > *pivot { newHeadBlock = bc.GetBlock(newHeadBlock.ParentHash(), newHeadBlock.NumberU64()-1) diff --git a/core/rawdb/freezer.go b/core/rawdb/freezer.go index b2b51e9e62..2d3953bd80 100644 --- a/core/rawdb/freezer.go +++ b/core/rawdb/freezer.go @@ -22,6 +22,7 @@ import ( "math" "os" "path/filepath" + "sync" "sync/atomic" "time" diff --git a/eth/downloader/downloader.go b/eth/downloader/downloader.go index 6aba221fb4..7f23282311 100644 --- a/eth/downloader/downloader.go +++ b/eth/downloader/downloader.go @@ -62,7 +62,7 @@ var ( maxQueuedHeaders = 32 * 1024 // [eth/62] Maximum number of headers to queue for import (DOS protection) maxHeadersProcess = 2048 // Number of header download results to import at once into the chain maxResultsProcess = 2048 // Number of content download results to import at once into the chain - maxForkAncestry uint64 = params.ImmutabilityThreshold // Maximum chain reorganisation (locally redeclared so tests can reduce it) + maxForkAncestry uint64 = params.FullImmutabilityThreshold // Maximum chain reorganisation (locally redeclared so tests can reduce it) reorgProtThreshold = 48 // Threshold number of recent blocks to disable mini reorg protection reorgProtHeaderDelay = 2 // Number of headers to delay delivering to cover mini reorgs @@ -1482,7 +1482,7 @@ func (d *Downloader) processHeaders(origin uint64, pivot uint64, td *big.Int) er var ( rollback uint64 // Zero means no rollback (fine as you can't unroll the genesis) rollbackErr error - mode = d.getMode() + mode = d.Mode ) defer func() { if rollback > 0 { @@ -1503,7 +1503,7 @@ func (d *Downloader) processHeaders(origin uint64, pivot uint64, td *big.Int) er log.Warn("Rolled back chain segment", "header", fmt.Sprintf("%d->%d", lastHeader, d.lightchain.CurrentHeader().Number), "fast", fmt.Sprintf("%d->%d", lastFastBlock, curFastBlock), - "block", fmt.Sprintf("%d->%d", lastBlock, curBlock)) + "block", fmt.Sprintf("%d->%d", lastBlock, curBlock), "reason", rollbackErr) } }() // Wait for batches of headers to process @@ -1577,13 +1577,13 @@ func (d *Downloader) processHeaders(origin uint64, pivot uint64, td *big.Int) er chunk := headers[:limit] // In case of header only syncing, validate the chunk immediately - if mode == FastSync || mode == LightSync { + if mode == FastSync || !mode.SyncFullBlockChain() { // If we're importing pure headers, verify based on their recentness frequency := fsHeaderCheckFrequency if chunk[len(chunk)-1].Number.Uint64()+uint64(fsHeaderForceVerify) > pivot { frequency = 1 } - if n, err := d.lightchain.InsertHeaderChain(chunk, frequency); err != nil { + if n, err := d.lightchain.InsertHeaderChain(chunk, frequency, d.Mode.SyncFullHeaderChain()); err != nil { rollbackErr = err // If some headers were inserted, track them as uncertain diff --git a/eth/handler.go b/eth/handler.go index ae98413bb5..8a603a469e 100644 --- a/eth/handler.go +++ b/eth/handler.go @@ -77,6 +77,7 @@ type ProtocolManager struct { txpool txPool blockchain *core.BlockChain + chaindb ethdb.Database maxPeers int downloader *downloader.Downloader @@ -118,6 +119,7 @@ func NewProtocolManager(config *params.ChainConfig, checkpoint *params.TrustedCh eventMux: mux, txpool: txpool, blockchain: blockchain, + chaindb: chaindb, peers: newPeerSet(), whitelist: whitelist, newPeerCh: make(chan *peer), diff --git a/eth/sync.go b/eth/sync.go index ba6015f425..fe6d227bc9 100644 --- a/eth/sync.go +++ b/eth/sync.go @@ -22,6 +22,7 @@ import ( "time" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/eth/downloader" "github.com/ethereum/go-ethereum/log" @@ -170,59 +171,31 @@ func (pm *ProtocolManager) synchronise(peer *peer) { currentBlock := pm.blockchain.CurrentBlock() td := pm.blockchain.GetTd(currentBlock.Hash(), currentBlock.NumberU64()) -func peerToSyncOp(mode downloader.SyncMode, p *peer) *chainSyncOp { - peerHead, peerTD := p.Head() - return &chainSyncOp{mode: mode, peer: p, td: peerTD, head: peerHead} -} - -func (cs *chainSyncer) modeAndLocalHead() (downloader.SyncMode, *big.Int) { - // If we're in fast sync mode, return that directly - if atomic.LoadUint32(&cs.pm.fastSync) == 1 { - block := cs.pm.blockchain.CurrentFastBlock() - td := cs.pm.blockchain.GetTdByHash(block.Hash()) - return downloader.FastSync, td - } - // We are probably in full sync, but we might have rewound to before the - // fast sync pivot, check if we should reenable - if pivot := rawdb.ReadLastPivotNumber(cs.pm.chaindb); pivot != nil { - if head := cs.pm.blockchain.CurrentBlock(); head.NumberU64() < *pivot { - block := cs.pm.blockchain.CurrentFastBlock() - td := cs.pm.blockchain.GetTdByHash(block.Hash()) - return downloader.FastSync, td + // Otherwise try to sync with the downloader + mode := downloader.FullSync + if atomic.LoadUint32(&pm.fastSync) == 1 { + // Fast sync was explicitly requested, and explicitly granted + mode = downloader.FastSync + } else if pivot := rawdb.ReadLastPivotNumber(pm.chaindb); pivot != nil { + if currentBlock.NumberU64() < *pivot { + block := pm.blockchain.CurrentFastBlock() + td = pm.blockchain.GetTdByHash(block.Hash()) + mode = downloader.FastSync } } - // Nope, we're really full syncing - head := cs.pm.blockchain.CurrentHeader() - td := cs.pm.blockchain.GetTd(head.Hash(), head.Number.Uint64()) - return downloader.FullSync, td -} -// startSync launches doSync in a new goroutine. -func (cs *chainSyncer) startSync(op *chainSyncOp) { - cs.doneCh = make(chan error, 1) - go func() { cs.doneCh <- cs.pm.doSync(op) }() -} + pHead, pTd := peer.Head() + if pTd.Cmp(td) <= 0 { + return + } -// doSync synchronizes the local blockchain with a remote peer. -func (pm *ProtocolManager) doSync(op *chainSyncOp) error { - if op.mode == downloader.FastSync { - // Before launch the fast sync, we have to ensure user uses the same - // txlookup limit. - // The main concern here is: during the fast sync Geth won't index the - // block(generate tx indices) before the HEAD-limit. But if user changes - // the limit in the next fast sync(e.g. user kill Geth manually and - // restart) then it will be hard for Geth to figure out the oldest block - // has been indexed. So here for the user-experience wise, it's non-optimal - // that user can't change limit during the fast sync. If changed, Geth - // will just blindly use the original one. - limit := pm.blockchain.TxLookupLimit() - if stored := rawdb.ReadFastTxLookupLimit(pm.chaindb); stored == nil { - rawdb.WriteFastTxLookupLimit(pm.chaindb, limit) - } else if *stored != limit { - pm.blockchain.SetTxLookupLimit(*stored) - log.Warn("Update txLookup limit", "provided", limit, "updated", *stored) + if mode == downloader.FastSync { + // Make sure the peer's total difficulty we are synchronizing is higher. + if pm.blockchain.GetTdByHash(pm.blockchain.CurrentFastBlock().Hash()).Cmp(pTd) >= 0 { + return } } + // Run the sync cycle, and disable fast sync if we've went past the pivot block if err := pm.downloader.Synchronise(peer.id, pHead, pTd, mode); err != nil { return diff --git a/foo b/foo deleted file mode 100644 index 72d2b63f17..0000000000 --- a/foo +++ /dev/null @@ -1,141 +0,0 @@ -build/env.sh go run build/ci.go install ->>> /usr/local/go/bin/go install -ldflags -X main.gitCommit=e04a1ae96b6f6df07bac862f6d74dbd689bc2032 -X main.gitDate=20200622 -extldflags -pthread -v ./... -build/env.sh go run build/ci.go test ->>> /usr/local/go/bin/go test -ldflags -X main.gitCommit=e04a1ae96b6f6df07bac862f6d74dbd689bc2032 -X main.gitDate=20200622 -extldflags -pthread -p 1 -timeout 5m ./... -? github.com/ethereum/go-ethereum [no test files] -ok github.com/ethereum/go-ethereum/accounts (cached) -ok github.com/ethereum/go-ethereum/accounts/abi (cached) -ok github.com/ethereum/go-ethereum/accounts/abi/bind (cached) -ok github.com/ethereum/go-ethereum/accounts/abi/bind/backends (cached) -? github.com/ethereum/go-ethereum/accounts/external [no test files] -ok github.com/ethereum/go-ethereum/accounts/keystore 15.948s -? github.com/ethereum/go-ethereum/accounts/scwallet [no test files] -? github.com/ethereum/go-ethereum/accounts/usbwallet [no test files] -ok github.com/ethereum/go-ethereum/accounts/usbwallet/ledger (cached) -? github.com/ethereum/go-ethereum/accounts/usbwallet/trezor [no test files] -? github.com/ethereum/go-ethereum/cmd/abigen [no test files] -ok github.com/ethereum/go-ethereum/cmd/blspopchecker (cached) -? github.com/ethereum/go-ethereum/cmd/bootnode [no test files] -? github.com/ethereum/go-ethereum/cmd/checkpoint-admin [no test files] -? github.com/ethereum/go-ethereum/cmd/clef [no test files] -? github.com/ethereum/go-ethereum/cmd/devp2p [no test files] -ok github.com/ethereum/go-ethereum/cmd/ethkey (cached) -? github.com/ethereum/go-ethereum/cmd/evm [no test files] -? github.com/ethereum/go-ethereum/cmd/evm/internal/compiler [no test files] -? github.com/ethereum/go-ethereum/cmd/faucet [no test files] -ok github.com/ethereum/go-ethereum/cmd/geth (cached) -? github.com/ethereum/go-ethereum/cmd/p2psim [no test files] -? github.com/ethereum/go-ethereum/cmd/rlpdump [no test files] -ok github.com/ethereum/go-ethereum/cmd/utils (cached) -? github.com/ethereum/go-ethereum/cmd/wnode [no test files] -ok github.com/ethereum/go-ethereum/common (cached) -ok github.com/ethereum/go-ethereum/common/bitutil (cached) -ok github.com/ethereum/go-ethereum/common/compiler (cached) -ok github.com/ethereum/go-ethereum/common/fdlimit (cached) -ok github.com/ethereum/go-ethereum/common/hexutil (cached) -ok github.com/ethereum/go-ethereum/common/math (cached) -ok github.com/ethereum/go-ethereum/common/mclock (cached) -ok github.com/ethereum/go-ethereum/common/prque (cached) -ok github.com/ethereum/go-ethereum/common/task (cached) -? github.com/ethereum/go-ethereum/consensus [no test files] -? github.com/ethereum/go-ethereum/consensus/consensustest [no test files] -ok github.com/ethereum/go-ethereum/consensus/istanbul (cached) -ok github.com/ethereum/go-ethereum/consensus/istanbul/backend (cached) -ok github.com/ethereum/go-ethereum/consensus/istanbul/backend/internal/enodes (cached) -ok github.com/ethereum/go-ethereum/consensus/istanbul/core (cached) -ok github.com/ethereum/go-ethereum/consensus/istanbul/validator (cached) -ok github.com/ethereum/go-ethereum/consensus/istanbul/validator/random (cached) -? github.com/ethereum/go-ethereum/consensus/misc [no test files] -ok github.com/ethereum/go-ethereum/console (cached) -? github.com/ethereum/go-ethereum/contract_comm [no test files] -? github.com/ethereum/go-ethereum/contract_comm/blockchain_parameters [no test files] -? github.com/ethereum/go-ethereum/contract_comm/currency [no test files] -? github.com/ethereum/go-ethereum/contract_comm/election [no test files] -? github.com/ethereum/go-ethereum/contract_comm/epoch_rewards [no test files] -? github.com/ethereum/go-ethereum/contract_comm/errors [no test files] -? github.com/ethereum/go-ethereum/contract_comm/freezer [no test files] -? github.com/ethereum/go-ethereum/contract_comm/gasprice_minimum [no test files] -? github.com/ethereum/go-ethereum/contract_comm/gold_token [no test files] -? github.com/ethereum/go-ethereum/contract_comm/random [no test files] -? github.com/ethereum/go-ethereum/contract_comm/transfer_whitelist [no test files] -? github.com/ethereum/go-ethereum/contract_comm/validators [no test files] -ok github.com/ethereum/go-ethereum/contracts/checkpointoracle (cached) -? github.com/ethereum/go-ethereum/contracts/checkpointoracle/contract [no test files] -ok github.com/ethereum/go-ethereum/core (cached) -ok github.com/ethereum/go-ethereum/core/asm (cached) -ok github.com/ethereum/go-ethereum/core/bloombits (cached) -ok github.com/ethereum/go-ethereum/core/forkid (cached) -ok github.com/ethereum/go-ethereum/core/rawdb (cached) -ok github.com/ethereum/go-ethereum/core/state (cached) -ok github.com/ethereum/go-ethereum/core/types (cached) -ok github.com/ethereum/go-ethereum/core/vm (cached) -ok github.com/ethereum/go-ethereum/core/vm/runtime (cached) -ok github.com/ethereum/go-ethereum/crypto (cached) -ok github.com/ethereum/go-ethereum/crypto/blake2b (cached) -ok github.com/ethereum/go-ethereum/crypto/bls (cached) -? github.com/ethereum/go-ethereum/crypto/bn256 [no test files] -ok github.com/ethereum/go-ethereum/crypto/bn256/cloudflare (cached) -ok github.com/ethereum/go-ethereum/crypto/bn256/google (cached) -ok github.com/ethereum/go-ethereum/crypto/ecies (cached) -ok github.com/ethereum/go-ethereum/crypto/secp256k1 (cached) -ok github.com/ethereum/go-ethereum/eth (cached) -ok github.com/ethereum/go-ethereum/eth/downloader (cached) -ok github.com/ethereum/go-ethereum/eth/fetcher (cached) -ok github.com/ethereum/go-ethereum/eth/filters (cached) -ok github.com/ethereum/go-ethereum/eth/tracers (cached) -? github.com/ethereum/go-ethereum/eth/tracers/internal/tracers [no test files] -ok github.com/ethereum/go-ethereum/ethclient (cached) -? github.com/ethereum/go-ethereum/ethdb [no test files] -? github.com/ethereum/go-ethereum/ethdb/dbtest [no test files] -ok github.com/ethereum/go-ethereum/ethdb/leveldb (cached) -ok github.com/ethereum/go-ethereum/ethdb/memorydb (cached) -? github.com/ethereum/go-ethereum/ethstats [no test files] -ok github.com/ethereum/go-ethereum/event (cached) -ok github.com/ethereum/go-ethereum/graphql (cached) -? github.com/ethereum/go-ethereum/internal/build [no test files] -? github.com/ethereum/go-ethereum/internal/cmdtest [no test files] -? github.com/ethereum/go-ethereum/internal/debug [no test files] -? github.com/ethereum/go-ethereum/internal/ethapi [no test files] -ok github.com/ethereum/go-ethereum/internal/guide (cached) -ok github.com/ethereum/go-ethereum/internal/jsre (cached) -? github.com/ethereum/go-ethereum/internal/jsre/deps [no test files] -? github.com/ethereum/go-ethereum/internal/testlog [no test files] -? github.com/ethereum/go-ethereum/internal/web3ext [no test files] -ok github.com/ethereum/go-ethereum/les (cached) -ok github.com/ethereum/go-ethereum/les/flowcontrol (cached) -ok github.com/ethereum/go-ethereum/light (cached) -? github.com/ethereum/go-ethereum/log [no test files] -ok github.com/ethereum/go-ethereum/metrics (cached) -? github.com/ethereum/go-ethereum/metrics/exp [no test files] -? github.com/ethereum/go-ethereum/metrics/influxdb [no test files] -? github.com/ethereum/go-ethereum/metrics/librato [no test files] -? github.com/ethereum/go-ethereum/metrics/prometheus [no test files] -ok github.com/ethereum/go-ethereum/miner (cached) -ok github.com/ethereum/go-ethereum/mobile (cached) -ok github.com/ethereum/go-ethereum/node (cached) -ok github.com/ethereum/go-ethereum/p2p (cached) -ok github.com/ethereum/go-ethereum/p2p/discover (cached) -ok github.com/ethereum/go-ethereum/p2p/discv5 (cached) -ok github.com/ethereum/go-ethereum/p2p/dnsdisc (cached) -ok github.com/ethereum/go-ethereum/p2p/enode (cached) -ok github.com/ethereum/go-ethereum/p2p/enr (cached) -ok github.com/ethereum/go-ethereum/p2p/nat (cached) -ok github.com/ethereum/go-ethereum/p2p/netutil (cached) -ok github.com/ethereum/go-ethereum/p2p/simulations (cached) -ok github.com/ethereum/go-ethereum/p2p/simulations/adapters (cached) -? github.com/ethereum/go-ethereum/p2p/simulations/examples [no test files] -? github.com/ethereum/go-ethereum/p2p/simulations/pipes [no test files] -? github.com/ethereum/go-ethereum/p2p/testing [no test files] -ok github.com/ethereum/go-ethereum/params (cached) -ok github.com/ethereum/go-ethereum/rlp (cached) -ok github.com/ethereum/go-ethereum/rpc (cached) -ok github.com/ethereum/go-ethereum/signer/core (cached) -ok github.com/ethereum/go-ethereum/signer/fourbyte (cached) -ok github.com/ethereum/go-ethereum/signer/rules (cached) -? github.com/ethereum/go-ethereum/signer/rules/deps [no test files] -ok github.com/ethereum/go-ethereum/signer/storage (cached) -ok github.com/ethereum/go-ethereum/tests (cached) -ok github.com/ethereum/go-ethereum/trie (cached) -ok github.com/ethereum/go-ethereum/whisper/mailserver (cached) -? github.com/ethereum/go-ethereum/whisper/shhclient [no test files] -ok github.com/ethereum/go-ethereum/whisper/whisperv6 (cached) diff --git a/genesis.json b/genesis.json deleted file mode 100644 index ab5224866d..0000000000 --- a/genesis.json +++ /dev/null @@ -1,88 +0,0 @@ -{ - "config": { - "homesteadBlock": 0, - "eip150Block": 0, - "eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "eip155Block": 0, - "eip158Block": 0, - "byzantiumBlock": 0, - "constantinopleBlock": 0, - "petersburgBlock": 0, - "istanbulBlock": 0, - "chainId": 40120, - "istanbul": { - "policy": 2, - "blockperiod": 5, - "requesttimeout": 10000, - "epoch": 17280, - "lookbackwindow": 12 - } - }, - "nonce": "0x0", - "timestamp": "0x5e8ca380", - "gasLimit": "0x8000000", - "extraData": "0x0000000000000000000000000000000000000000000000000000000000000000f918cbf9042f94893c4d601ed879b4ad36fc31f0c0214d547113eb9475af50cac2b2eb330b975c1b999fef571c87087094ffff741c41fb487f4d64fcc9e32fbb38e2a8372c94c496e9791d39a6f0ae54ed52897e581d168a5b4594b182f37daee2285f14b4091b702ceccb00d5031294beeb24d10c9fe58715a0c853db8ddd8e0019177194aa3b76b6618afe574b278da9b71af0e66aa6f64694e2368b04a1d14f286faf8c90153e33dc0b0879fb9472bda6988c4551083c14dddd2709edee96a9b4a894f0d17b624521c0a599b063d73a73f9719307b48f9438f3eebb5a820ba4b83b1f6a324c09ec1db2d2f9942f916156a2dcd5dfb6054eb62a677c55c3a4037a94ee80387e93e4d6d41c4bf51623bc8a42ba55a44994d32e429fe2155971825e14e2fd89785301ab6dc3948c517b3bab0e2d65d5cdf3750ca360ff05b3fc1d9462d56ba5bb3b841fade256d97e7d4d57364fb88194beb2b0ea812caaaea3a1f894fa9138231e2c7d3894430c9d55cf6116c65482379c039584b9b965f32394821a6b00d9f658e1732ce741d91984c688e25c5c948339eae8ee5b8ea60d80711c9fe30ae92c0eba2f94a5f837aa6be966d9f293de6f8cc65fac7064220f94d2462858d04dfdb0c7ad26dfa21933526491c1c39442a237fd620f714536d6f63c0f46d092c9ea012294dce0096c358e90c4645d68a53e897416e786d05f94d10ddf202de766dbaaea7c436a90f5aa71e5bdc4942ec7df44dbbc3d458acc4108aac8d1cb0bec11c094b8f90aed575898c38c11deda226e1294f4d9dfcd948a63fe13a4be506e8b51d296f60f192458672e629480be4e53c6bf959445598965c2910c2c91ec81f7944663bf9f8c6b32f095126e138678732c0d183f7e94bafa573a3d5333fc88560de1c312992c56d517aa948a0d880f275d3741f507a0180e843a2805ec1e2e94cc8c30b74073f537a6f790ae68649788a66f2d7194ba7d40c43dc59e2686fb38edcbdd69c3e53eba34941db8f844aa731e4a20e139c7e7ebfeda26888cc9943acce236f234aa330395d50d6155f86c5169731894cd97f1e7cddff4523f03a5072e9be8ea7edbdaec94537bf2c6227ea6ce4eb250da02e6a6aaa3de4f7b9448cedc58b10af13d688631bc3cb78a05b8a6e56a94f410a55e2f4b49996a1cb884c3107490aee09330944ec65178abe63805b2b0ec2718280454d9b6353d9423836969f0d095afeb652c75523f740898e0c4629423e15d949c13e3010b75afd19b1d3b294310c7e6940ec5a403212d732d8d7ced050e9510f6327453c6940ec5a403212d732d8d7ced050e9510f6327453c694e224ceb83a39d2ffa7eaa0c501e6954db5667e59943c8afff5c9332161a20db995e2c831baf02d9f91940f409814cad27ce583de0d6a10ecf53d48b9535f94f6a969790936c5285f7a7d1af642707d0c8e2418947a450c89257bf0ead22f143493250907411cd1d694fb041f37e22b25e30e10cfd662e6a5f2d1305476f91386b8603695297deb0f970e1cd8c64a852b45ad788e151734ab05a20206be63f7f42817fb5e3e035d7f9dba56917a0bc75a3f0061e767a5cc5a60469709f170f4f7d76dcf6e30f04a520745ac8f3f131d6b854ea2a899c3317cc48bf06cdb07f4514a81b8606b628400822daba0c52481cd1f8708056c40c392b362a9028d17032b6324b114620118a2770e0ddccc717685c2380600d035299ff9fc354180d251acaa778cac2a2eb64466e977204e582ea1342c0100c01ff5ea558be47b1f36cfbaee7a1e80b860f6c310b565f6f975faf4326707551a9154b848a222c14c6e18b87c0bd9bcf3524d95b70d5faffe1d911955186f160d01c82d4df63cc8dbc52ef2e106c89d2b838c57a4e6fd033d7d4cd49698111fd78321a962d03b1a31eefdc84397c0d51b80b860baa5538d5579ce32668fbf4e80cd9fd31f09447ba473da1ae44a51ce6feb4f46d8a14008fc515fa7e0e9d720c83b7001bdbfbce56284c382c5a267e7a245daeaa9e2914dc92cf2aa2ebcde339e309c5d1a0df1533cbd631168fc3e4a1d248801b8605a13510aa9b74ecd0bb7d8bd7f65dd5622ff4a61eebc1976529a26954d70732d591589dcf49e3f8a87f450642336e200391e1e8b57afe3d7240b80020deef9db2d9b260fc3f30ab4168521de586c211baccb505b75af030d47bd1d6fd49ab480b860382d76c49b99ba0d0aab030afe569b89288f399c727e3c1dcefbe1208f0c2d86498f62e1fee2d50486e2d6aa0d61130172cd07019fdfe79cbbec315f53465d9a8121fcdcfe71efede293111915281e82add7252b88b540b3a0dcd2fcfec91c81b860348aa54a71033d583a29d00e3dfb1f696633c6520bc71099fd26a228d1882f380ab86ef19b7efe544d47ba8aeddf770125075f6c15b82611a31e746668c1aa8af2355efe6e4cd297c0f570fce18ecc2f274bef5115a8d8ba9a18a6563e6c6181b86017a5c4c6a8aa852ab1ac7771e3caa6546da92938bda6d4e0c0ea05da85adbe08ca2ee58e657a82b619d1a729b6510401686ca15382abdbd856716fa867573c35ab8605d2d57b0573ff589c087cf57e5408cbf7be57ce5946a6455b1955d9d300b8609887deb26c20c4b5b448e04efe7b18781355f9648feb47d978382aa3c789f545416d20bca757df66b70867ccffeba0014bb1b45fafe0366aff4d513c023a55ee35ccc5a86d5214f813996e2ded810e3cac11cb15b7ca0b97aad1a307897d4d01b86057b5158540d1672de49073e469e5426766094ce6514ac29580803ff9d22cdef3b6fed28a8ad9de63bf938c1c7b0e7a0156fb03f5363d09bf337713d8d45475df48ccea0fa793f591fbb62673545fc846c04e6aa9e2eaaab72c3b9ba4069ea280b860720216212176780b12cd297d1feff6a964329448d821fd69e0a4fcc53c4edc00ca9c89ab2c35abe7b68cd47bc230bd00597450ca0bea04562f78b0102d406f4b651957989c1471674eb16a531c2f762c84c3432ccd7fab87b0a185a942d00301b86068438d70fb61a2d0adc3710b619aa5f9a603168f93bf0504401464df3acb14cc1815bf449b7f8791fef7e309b60e7b0145d425515d1f4f380b66c256a4218700ae48e2d2185a636487d6f531f546b9127b957084d0821acccf5ad0776b06be80b86092b17fb70e62710f3b87642830e23258a0fd1041da9606c7eea7019f86da50ff4cd06ad48a4d0ca93e62a6c7ed6c5e0036f4443d0cfe9122156a346836a9163404d58856bbd447939189bf1cc8a7ee8be156415642992f8e0659526d15bb0c00b860bfd4b2392664c68bbd30d6a77cd1c7230e340ac65ecc07449c0d704096af06926238c60e7764ffcd0b9a53d82d7050009cfd9481ebd7630fd2540b834cef70b5276d07b75913a20222d74f36db8beabfcd39f7c5d57c4a28f87e8e737123bd80b8602a10c24fb6cfb029650a90f10f6586f26e61e3a51d68342785862e666f6c730bb929ff2c5a20f5ceff41cb53a2333c00aa0e4b0e47c821c668d6b84fac85c5b5cd360c53dfdf9a6c48e0f4ff8c3997ff191463f90fa644fc2870174d67885b80b8608aed791b4381c7bd38f8358cbb7f64bb6b74c34b85b27026745df7cae91f5cdd50ba6cadd919494ec9849e628138870188ef21da8282207be4acd30803288e2674a7c46322f41f3ecf685f5b635970c0d19802defc344cc4023f8e41e50e3c00b8605008d7aece8407c044c4a7a77b37690a08b0edbde0942446f31e3362031e689b30872d8732f74dd3e45bbe85c072a4005ad20cf2d9e0824eed9a607b980d0cd5d160bcbd5ffc34a6a87176e257c927cd419ac080df27cce888eb94c7bc5a3880b860a4ef4602775c99871c1f910af02cc997cb6f6b1524450898a1de0a3369750ce17deda194ce40c80650025770e1c60a008916618d314d7008a44e312f2f032fedd08177ef854cf78dc269122dd7eef415989e975f13d501830df4ecd3fe248700b860f01e9ee01d1a76e596827b897e39a1e497b00d6ed276675201e81a07509d4043354c89d0ed515098b0730958cc9dd200fd9cf9d1f2fdd7823937af05e03eb1b043de63e2c8ff7bfebc9cd4f3983243bd275d0266bbaee5e70244126687470f00b8601f599e48d2f04e623c42ae66d379f15ff8c1a3bc4584a27f234fc00e7feb64dcee6a0faa4cfc3737e507b9c38d640401b23b2c6fb9bb7f00a2144b8031b9b2446ac121e7ca7f06e0b6e084b082ada9fc31837d094b0d6c3d24965a9a61fa7a01b860c2cc4ba57abb3768f552b30768ad8de8d6b934d8fd2eca699a2b2f712e8d56b50ea2e59993175a396e471e3a6028b30054cf156b0c75b9df6ea2e15e03811960aa5999411522b01286bc1cf17e4ef366a48e3e075998394e090f46c1d8212c81b8603201cd2f5f5f41b6949a03a600347bf9920c891b883dc4c8a530188fec4f98ac96d6caf9e87a05c81962760c20c30c0198745f18efc87a19ec94a06cb01d72313a71f4ff30e94f04504e609cd495ed4b78dccdbdc6ece12d0200996763439c00b860b1d7e87a67d355c42cf7db5c599da2ce9624372cb941f338d68b80bb8376fc8600e6d925d9902f32270d6372d4215c0068879d52d16dda84ac2efbebbde57d7ca5d451f269aa9903926163d7ce75b68d2547c34e07303b9db69d0044c9219200b860872c5c11351fbe7f31bb38ff5f7b07aa8bc4902a06b81f4fe70e7bc5be86ad260be53c26ef3d1e6293e3308c33ef8d000c13182ad835adf86e816496d6519ae00bd607f6f5d974fab0792802d69688e6ef37078285a1a2e9f8489bfe5a87e600b8606afab29c7f64915ebcd2851799af2f43cebbab8fe051965103989c47e576181533f7bf64619a4ee50bd787bcb65f5b012d60c2eadaad3118cba6088cfb9204f5cc465d47dd4c834b568f313d5b0689c6b6f3734cd19d4df40185d007b22d3681b86055470892fbef78fa87bf31aa738a58fdca928a16d99fff12e8ec3d71fb89489286206e32aed5063f1fdd6294f8a3a2011e19cb83873a777741f3d8521ea33edac732704e36f1aac01f212eaf72405cf8d980dd88bcb88751a6bbe7207a5e1081b860207a4c7a86274921d013932e2f88ec795dfcb1f85df6bba7039fd14526cd44245f29d5916d17bebf40ed08be3d0541006fb3443238819cdf36eff79d8706ceda92b0b3bf05d6dfd9a723da2685acc34e59928fed096dea64f742fb55c7f34c80b8603891197bd1712a3cf13fc13f2f2308bb4acdd4e46e3a62abd28a8e3add64ebcabfb939c743e8e4d54da2a32c39719d013ca29923eb2c685ab851a4f644824d70b1fd36812f513f5f23fa8f82ea228ba2d8f8b771b109e99e1905e16b1899eb00b860efff9b35b865ad56dea6f6c80d96ae4ba88997a60451b1535ea51ef6ae1d26a1c25246f33139f64046909d4a30a90f00a782c6a5a910499b65d7f2c3064dca95cb6dda83c10c2f9dc8f60d1afeb91c067205dff722dfe964f66a9a98e4047800b8606dd6f3f642e00ffc73a2d76c8f58128aa434b526c0487487f193b6717665a2eccff314d7d0769dc17fad47db19981a00c8a11f156a2bdb36164b479cb1bcf636896066e3c3b561c478d357b343bfbc6aed51b08f60b8f804ebd78e2efb525c80b8608202e06fb2d18ad9a85b3af760290ca4aae79fe2d354ec4c462f65e98339f9bfbf6c24503c73b054bfa740ea595241011c0d599d95697238c700a380326dea544cd7b085a3b8db22ae900ac82a5c23ade8c4290e022b0e425a55f742352dc480b860acc4826a9317688bdf782adc5acdf12656ffc2f327ca699418c287a15c2c22e0d16e632e592f5b0748b40a8e374e33009d8cfdfef7f81493a77843054cd006858b1b217043954423bb0924d0387b6609a504e15e6c054fe1288e0bd337253100b8606c93b4d43d69c248efadf8d03a4c9672ea222830a1530b29deab346933fc4492a211223c446ea24af059d9528ab3c100f0c4769fb226335489969277140da7c8c7f036d76f73c1d5f359744018b76b13c0eb07812f08923649e4a45b3b69fc80b86086ef363fcabe2e3c27769de9974f4b8604b47cdb2fe57208f0a59899b77306b7770f7403b222b6222efeb67747d06e01fc2ac657a21f37ab982d8463ba9c7fafaeda20370ec3f6cc565dbec4a69f59f9d7404725e3b701681d41a870b1f42281b86051026c0f52d8612414359ee4e6049a275387d3033cf51a8e23b3e037bd7006d916017b5253da7068532e6242b1d96900d8130a60b9b0b3ecb06a08472728bddd55f778e485188c3717b911039ebe3b2cdd89573229bdacaecba9a220b2decb80b8606a2cc88ae37c395815dcedb56f5ee6b701e06e97bdb6232c2b0e21f719a1504d0f3b259a63e2e54d6b1a27cbb0b051007f0c39d42f699cfc608c25b636ea221500d0eb75fe0f26d35beec47e1161675a7f571ed70684778ee7c4bc6221d8af80b860c5f05101b67ffd245abb878fc8d68058e3a65b4672453b90cb116a0cb8f59879a73944d8a2c25e8a2865e07e1e4e0100cd255dbd7055b5228eb1d4cccea7a1288ef83bab770633b0054f8c8d9ad4e7fc15af631c2b2282337faddb2220e54901b8603178c750f9274f0f1ea4103997e7d469b2ef4b9dd2f1dff7dc33ae5aaa5fdfa32a9e44e844de658502fbd8925e9a8a00d4422f22a7a5c3e4a790d21334eb70a744da6a863c4e060481781b8bb3fd1e9291ebfb548f7d8ec122c2c0c43eb46000b8607983d25868e1915ca8c20603bb70475b398acb04fef221106475f0fc25a3df25d181050214da347bfcd8f8292e5257014ba77cf67ee5f42202257317808f126930b4eaaf4bec801c4465ced54bd78331f8d3dadfdf2f91de294836c13e946001b86061810f2366f415b7b67e0ff9c82ae55fa213a95ff61df8718e806931ce135c0324462a33ccbde34ff901025ac334640064b41f7854c6eabcf3d9f7a4e4ff90522a4ba2681a0df03d08c67fb79f0fe98cd8c6f5ad3df155a0210ff84fc93d1500b8606a50718246d5c167429ce48b757a28441b217eb0903d762a3039d0ee59c00584b05418920be4eacb2fe2051d492a3d003a2a00065986e15815c26434c68caf177cbea44a38a886e86b34dba8a17dca43b729b9d69007e25d735e0ec62f7b6d81b860424b8239213c6f2c3e181b815294b9dd78663e29ee1234e1511e584b7b736571a6799135381cced36dcbd12dd19a5901f479679592608ab7f98aa1f607a3fe4b5b29a6580f724086610c901f143be653dcaf9fd477ac4d21d263e8ad8d048681b860f03d1c933feb791285892c9e6552bc6ccf07dd7f66862ff5554844db033c17a005087b5847718d4611e3ecb293ce670144a99a13ad3356ca56535815a0c6c21c2f84bbc0b40c78f6b63137a17709fa4be124be10e90a42bda72aee977ca86881b860fb9de050c059a11175be23daeef1bfc374a688d8fd776e7d2dc81fe301068a3af03ad522bd915a154dc8b5b8e12d38003f17bf9f3001e8bc682e38cfc93c6901417afe1ddbfe11b04f42ca4f321f7ba73fa98f0e8c8d75781b14c0dea847a500b860fb9de050c059a11175be23daeef1bfc374a688d8fd776e7d2dc81fe301068a3af03ad522bd915a154dc8b5b8e12d38003f17bf9f3001e8bc682e38cfc93c6901417afe1ddbfe11b04f42ca4f321f7ba73fa98f0e8c8d75781b14c0dea847a500b8600fa447ead6255657aa79229944a3ddf36984c7b9011e859f90bc6567ab61133b27b6bfa3a5e322dcf36abff543cc0d0131066520ad92d12b8603c25c561bf48806f178a995d233862038c46e81933e1ab0a7211b9b0933499cbc5867db736481b8602e45f40c799aec72e87e0ba4713056dd17cc9bdb29bb221c8fd6377336ae773afa84b8c0bb8f1f2edc88975b8ec986006f321462e28706618d690d24337a9e1c7b96e74d8c8f2fe740bac461635b4828046227f92f97b13da8540bdcc2f1a380b8602b8ab0795a174e96061dbb8c32bd38468497e56379b2ac79f6a7506f711b817cb57c8c1d8743d88c436cdcde3b51980132c5508f79cfc477bbd1b94fefd5c408a7072e85041f17042c1ad055c04e67a780f497e60aac3c38ddb2f0004237aa01b8603729df3ecff9e168c1ab2b2698251797494847ee14bffe9c4ce121d90d381b0d51f7208c793f55a9cac9d50e25d63d0018ee5daa523319bbd5087dc35cef8ec53338d810adf8b4565f39fccdddd7596a63198f045a2f3d92bd0b72b4487bcd00b86044a466fb5cf01c878071e12dc391753cb59005e39c6604fa0d1444ae36518df771f252891072c26652e12a5a5b1f3c00f479f3e3ace6412768ee5729825bac3529cfde3b44cc258b847dbd87f6d55dd68124d054314eea0a9169b36e46e34081b860c6ec185bce68a0a1fc78f78a5a9da12d39635f94b6981a64d7ed7a095839b6839da577383ddf9ef940d93409ec305801cda7a06f3c3adde48e9060ca396bd8a2821fbc435842bba5ba1dc0b81cfef04cdcf0ca7b02b6e4d70ca9caed8438708080b8410000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f86480b86000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080f86480b86000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080", - "difficulty": "0x1", - "coinbase": "0x0000000000000000000000000000000000000000", - "alloc": { - "0x36940810BfDB329B31e38d3e97aFD673081B497C": { - "balance": "120000000000000000000000000" - }, - "0xfCf982bb4015852e706100B14E21f947a5Bb718E": { - "balance": "200000000000000000000000000" - }, - "0xbA8761304CEc7bE0f83C6F8Fa7EBBa3eE0b6Ae97": { - "balance": "27375005000000000000000000" - }, - "0xDb39DBE5abE42466F122b24c44518b1089ef8fC8": { - "balance": "57291662000000000000000000" - }, - "0x671D520ae3E89Ea5383A5d7162bCed79FD25CdEe": { - "balance": "20000000000000000000000000" - }, - "0x868E39ef6c51b979526c15Fb801a7dD567CBCffF": { - "balance": "20000000000000000000000000" - }, - "0x4eC7a9e67FB05f555d775604cF591Ccb3C47d7b9": { - "balance": "20000000000000000000000000" - }, - "0xaB5FD29Ce411C7b5c0c41d04a11d40f8fbCdA7a2": { - "balance": "20000000000000000000000000" - }, - "0x14F40ca7600B5605D9fE704A949DA41806509497": { - "balance": "19053338000000000000000000" - }, - "0x469be98FE71AFf8F6e7f64F9b732e28A03596B5C": { - "balance": "20000000000000000000000" - }, - "0x1cd43c11CaEaf4a43413258eF7E0704e157F7811": { - "balance": "22000000000000000000000000" - }, - "0x9268f359CAD800a2746FBC96C4A5CF68eE1c4EC2": { - "balance": "22000000000000000000000000" - }, - "0x10E0833be035607feEA41d32b6567D15D12511Ec": { - "balance": "22250000000000000000000000" - }, - "0x8f55CE88b4F62F22c663f5A539414dcCeF969c32": { - "balance": "11000000000000000000000000" - }, - "0xF607d4dd519B4bc963C9c48E8650E67C51DbC35b": { - "balance": "11000000000000000000000000" - }, - "0x515033209a0A29034DC3F037cC72a6014b902341": { - "balance": "10000000000000000000000000" - }, - "000000000000000000000000000000000000ce10": { - "code": "0x60806040526004361061004a5760003560e01c806303386ba3146101e757806342404e0714610280578063bb913f41146102d7578063d29d44ee14610328578063f7e6af8014610379575b6000600160405180807f656970313936372e70726f78792e696d706c656d656e746174696f6e00000000815250601c019050604051809103902060001c0360001b9050600081549050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610136576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f4e6f20496d706c656d656e746174696f6e20736574000000000000000000000081525060200191505060405180910390fd5b61013f816103d0565b6101b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f496e76616c696420636f6e74726163742061646472657373000000000000000081525060200191505060405180910390fd5b60405136810160405236600082376000803683855af43d604051818101604052816000823e82600081146101e3578282f35b8282fd5b61027e600480360360408110156101fd57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019064010000000081111561023a57600080fd5b82018360208201111561024c57600080fd5b8035906020019184600183028401116401000000008311171561026e57600080fd5b909192939192939050505061041b565b005b34801561028c57600080fd5b506102956105c1565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156102e357600080fd5b50610326600480360360208110156102fa57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061060d565b005b34801561033457600080fd5b506103776004803603602081101561034b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506107bd565b005b34801561038557600080fd5b5061038e610871565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b60008060007fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47060001b9050833f915080821415801561041257506000801b8214155b92505050919050565b610423610871565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146104c3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f73656e64657220776173206e6f74206f776e657200000000000000000000000081525060200191505060405180910390fd5b6104cc8361060d565b600060608473ffffffffffffffffffffffffffffffffffffffff168484604051808383808284378083019250505092505050600060405180830381855af49150503d8060008114610539576040519150601f19603f3d011682016040523d82523d6000602084013e61053e565b606091505b508092508193505050816105ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f696e697469616c697a6174696f6e2063616c6c6261636b206661696c6564000081525060200191505060405180910390fd5b5050505050565b600080600160405180807f656970313936372e70726f78792e696d706c656d656e746174696f6e00000000815250601c019050604051809103902060001c0360001b9050805491505090565b610615610871565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146106b5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f73656e64657220776173206e6f74206f776e657200000000000000000000000081525060200191505060405180910390fd5b6000600160405180807f656970313936372e70726f78792e696d706c656d656e746174696f6e00000000815250601c019050604051809103902060001c0360001b9050610701826103d0565b610773576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f496e76616c696420636f6e74726163742061646472657373000000000000000081525060200191505060405180910390fd5b8181558173ffffffffffffffffffffffffffffffffffffffff167fab64f92ab780ecbf4f3866f57cee465ff36c89450dcce20237ca7a8d81fb7d1360405160405180910390a25050565b6107c5610871565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610865576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f73656e64657220776173206e6f74206f776e657200000000000000000000000081525060200191505060405180910390fd5b61086e816108bd565b50565b600080600160405180807f656970313936372e70726f78792e61646d696e000000000000000000000000008152506013019050604051809103902060001c0360001b9050805491505090565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610960576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f6f776e65722063616e6e6f74206265203000000000000000000000000000000081525060200191505060405180910390fd5b6000600160405180807f656970313936372e70726f78792e61646d696e000000000000000000000000008152506013019050604051809103902060001c0360001b90508181558173ffffffffffffffffffffffffffffffffffffffff167f50146d0e3c60aa1d17a70635b05494f864e86144a2201275021014fbf08bafe260405160405180910390a2505056fea165627a7a723058206808dd43e7d765afca53fe439122bc5eac16d708ce7d463451be5042426f101f0029", - "storage": { - "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x469be98FE71AFf8F6e7f64F9b732e28A03596B5C" - }, - "balance": "0" - } - }, - "number": "0x0", - "gasUsed": "0x0", - "mixHash": "0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365", - "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000" -} diff --git a/geth b/geth deleted file mode 100644 index 062930e221..0000000000 --- a/geth +++ /dev/null @@ -1,107 +0,0 @@ -Google Cloud Platform
- - - - - - - diff --git a/hmmm b/hmmm deleted file mode 100644 index 38a7057dd2..0000000000 --- a/hmmm +++ /dev/null @@ -1,27 +0,0 @@ -DEBUG[04-16|16:58:18.450] Sanitizing Go's GC trigger percent=100 -INFO [04-16|16:58:18.450] Setting it here -INFO [04-16|16:58:18.450] Maximum peer count ETH=100 LES=0 total=100 -INFO [04-16|16:58:18.450] Smartcard socket not found, disabling err="stat /run/pcscd/pcscd.comm: no such file or directory" -DEBUG[04-16|16:58:18.450] FS scan times list=45.286µs set=624ns diff=894ns -INFO [04-16|16:58:18.451] Setting baklava id -INFO [04-16|16:58:18.452] Starting peer-to-peer node instance=celo/v1.0.0-unstable-2addf910-20200416/linux-amd64/go1.13.7 -INFO [04-16|16:58:18.452] Allocated trie memory caches clean=512.00MiB dirty=0.00B -INFO [04-16|16:58:18.452] Allocated cache and file handles database=/home/sami/.celo/baklava/celo/chaindata cache=768.00MiB handles=2048 -TRACE[04-16|16:58:18.452] Started watching keystore folder path=/home/sami/.celo/baklava/keystore -DEBUG[04-16|16:58:18.496] Chain freezer table opened database=/home/sami/.celo/baklava/celo/chaindata/ancient table=receipts items=0 size=0.00B -DEBUG[04-16|16:58:18.497] Chain freezer table opened database=/home/sami/.celo/baklava/celo/chaindata/ancient table=diffs items=0 size=0.00B -DEBUG[04-16|16:58:18.497] Chain freezer table opened database=/home/sami/.celo/baklava/celo/chaindata/ancient table=headers items=0 size=0.00B -DEBUG[04-16|16:58:18.498] Chain freezer table opened database=/home/sami/.celo/baklava/celo/chaindata/ancient table=hashes items=0 size=0.00B -DEBUG[04-16|16:58:18.499] Chain freezer table opened database=/home/sami/.celo/baklava/celo/chaindata/ancient table=bodies items=0 size=0.00B -INFO [04-16|16:58:18.499] Opened ancient database database=/home/sami/.celo/baklava/celo/chaindata/ancient -DEBUG[04-16|16:58:18.499] Current full block not old enough number=0 hash=09bb18…0f1d7f delay=90000 -INFO [04-16|16:58:18.499] Persisted trie from memory database nodes=25 size=6.22KiB time=76.902µs gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=-116.00B -INFO [04-16|16:58:18.500] Initialised chain configuration config="{ChainID: 40120 Homestead: 0 DAO: DAOSupport: true EIP150: 0 EIP155: 0 EIP158: 0 Byzantium: 0 Constantinople: 0 Petersburg: 0 Istanbul: 0 Engine: istanbul}" -DEBUG[04-16|16:58:18.500] Setting up Istanbul consensus engine -INFO [04-16|16:58:18.500] Open roundstate db func=newRoundStateDB type=roundStateDB rsdb_path=/home/sami/.celo/baklava/celo/roundstates -INFO [04-16|16:58:18.585] Initialising Ethereum protocol versions="[65 64]" network=40120 dbversion=7 -TRACE[04-16|16:58:18.586] Set current header number=0 -TRACE[04-16|16:58:18.586] Set current header number=0 -INFO [04-16|16:58:18.586] Decoding -ERROR[04-16|16:58:18.586] Invalid block body RLP hash=09bb18…0f1d7f err="rlp: input list has too many elements for types.Body" -Fatal: Error starting protocol stack: genesis not found in chain diff --git a/params/network_params.go b/params/network_params.go index bba24721c1..68255b70c0 100644 --- a/params/network_params.go +++ b/params/network_params.go @@ -57,5 +57,5 @@ const ( // considered immutable (i.e. soft finality). It is used by the downloader as a // hard limit against deep ancestors, by the blockchain against deep reorgs, by // the freezer as the cutoff treshold and by clique as the snapshot trust limit. - ImmutabilityThreshold = 90000 + FullImmutabilityThreshold = 90000 ) diff --git a/rc.json b/rc.json deleted file mode 100644 index 7cdd781b32..0000000000 --- a/rc.json +++ /dev/null @@ -1,133 +0,0 @@ -{ - "config": { - "homesteadBlock": 0, - "eip150Block": 0, - "eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "eip155Block": 0, - "eip158Block": 0, - "byzantiumBlock": 0, - "constantinopleBlock": 0, - "petersburgBlock": 0, - "istanbulBlock": 0, - "chainId": 42220, - "istanbul": { - "policy": 2, - "blockperiod": 5, - "requesttimeout": 3000, - "epoch": 17280, - "lookbackwindow": 12 - } - }, - "nonce": "0x0", - "timestamp": "0x5ea06a00", - "gasLimit": "0x1312d00", - "extraData": "0xecc833a7747eaa8327335e8e0c6b6d8aa3a38d0063591e43ce116ccf5c89753ef91f4df905559427f326ab753d62cdb55018c62e9ee7e671bbb121947eec94733d16b96c6fe877464630bb5be1e5c3f294f0d17b624521c0a599b063d73a73f9719307b48f94a7681958b7f07f4fb8bd5b0e075fb2aa2b021d5994ecc20b5f3d6cdf41fc12707ad7872ff64256e29794e5617da4dfa6ce4912f1d39889fe2dec2f7e66b39439ec4f2a82f9f0f39929415c65db9ea5df54e41d94341dec14b7a56c242ce9cf939815ec7bb11042449469901924e6c045a03cc163c6b8ae8af80fa1ee80940a6641d4736767d1f2bcf2450200ef384391b4419466bdb4d2ff2ee4c68517e6fcd25cc3034c86916094606311948f7426ddfd23c1521b15eddb52e83b29944cb90ebba92141ed3021f5dc4e6c8bb642095846948c6f9aad8281a21e7f6522602f2d6469c950e0bb942a1bff2452aca1ca5ffabbd34b2744109d11e4f594b4fa2d21b238e12ee4a863517cb5092f2330cb1b9442d441b6793e6162b979fbf6ad0af0063cbec96a94436d12f639a32509685080161ff0365fc15545f094e0c5f6172673ad70a76ff264cbc0df783930b47d9421245b0a2c3235f1108d1aa01ae376849d36e68494f27bb4eabc4400a1abe9d80d7537ab0ef1b058bf948440e805b89f48c932265e3c4ad033813669d87a942eb79345089ca6f703f3b3c4235315cbeaad6d3c943aa1fa695aa89958ebdb5346d6760b72250dc1d794173c75c8f1be201ce89cf426fe12c9997d7096269474288dbefa3a55986c039953b67139a466474fc49482f0e7879314516952f7961b15c63fc6b2734dfb9459f7b67e6beae0223ddc91eec010b670c553e8e094e10a8cc6c22cdc320c67bd600a1d8a0a46d7f40094e3020350aceea29b783e0c947ae001692b8f624894b952930a3656a9cbab21df5919f94c61a495bf79942289a63b4b4700eeeca35323ea51785f366dd705940223e40d1f93a6fe5bef63605992ada10740e13b940610b8b4e6f5c3241d53ed3374ddca8969cd053c9463b4b616c5345e3dcc9e21db69297e2129447f4e94c9a7781729f95b88239c3bfc91fb52f92b44a1169456259f876eb6a7264d9f1a59952baad599ff964094f139e74adec329e715ab49a68c5548a00e40cbc29433657019d60a0a41f1b9970bd4b28a3a83dbeafc940f5640bd556b0be19262d1817b213ddb3424d91d94ed8bf82d2e579ff6363aef139f8b147a0105f17e94d8c68ebecb6f074ac5c4fb66a690ac0ad38a5a3c94c6f916ad6e360651bb95f8e67c1c28805745d084943ed95d6d4ce36ea7b349cd401e324316d956331a944a03c4c2e101ac4612d89b79f61c9c5bdd51929d94dd0f3f7beb37fe9d4496f8098446b65ddfb1fa0294642cbe89a58909ba712dd11ed4c4b2359bd8c85d94ffbcf262c1d5c4392ef469ba79f2cd195d2affda9468e0104fd2b5a2c93e97c2ba172c4d2a4223f76f945cab520442de9babc290b25e5e2e6a1194ec670794bc6963fc0e2f5547ba949ed39e80b8388321104f9443882141555003b3e71110f567373b59ac4cb0bd9448cedc58b10af13d688631bc3cb78a05b8a6e56a9465698c9ec5af10345cd1e39472d60fb6133bad6f94d507309fd69635aa37810a65a4da27ec47a1ba0594c46dc0741ff61af883e284daea062ae7382e709194198958f0b860ab0e3937f468fe366aac9eebad2e940ec5a403212d732d8d7ced050e9510f6327453c694464cce7999b3d90a8f1ffaf94a71fbdea1e6543594097095b8cf5cabf0c39e548d8df55dd635d84d0794aa937da037e617e868795eac1dcd43c663014d3294f11073eb2d259b90a91954cae30d0e6e9ecc7f11945b55452bdba5971d606f47647bd383f3c3fa728594439d5e4d7578ecc9efa52a8cf1887b11fd0fb9009492f628b0157d47c992f5c69dbbd038b110e27826f918e2b86005f784c52234d0c40ab13b0636c5728217a8f3100046593c30271d39d59fcdb9a0053a874710e9c65e0d8a030c16a700b4ec430207cc5037c5e2698ef839fa0b7a4372f4b5217deda2a8df087e3b552f300016ce9147a2ff4db4c8a87d77b080b860d3f640c3da685893c41eb6301fdde2920c5a09296438abe5894074592f27547fb4ad02d222b1a330ff5aea065eff5200973d4fcb57808d8d9b09337e09aec279dc3337e758c51a3219596699006ee3683ff0c733f16eb917fad37f7f5d505201b86057b5158540d1672de49073e469e5426766094ce6514ac29580803ff9d22cdef3b6fed28a8ad9de63bf938c1c7b0e7a0156fb03f5363d09bf337713d8d45475df48ccea0fa793f591fbb62673545fc846c04e6aa9e2eaaab72c3b9ba4069ea280b860ca75a4c4e1f2898c0ae0ed53698b0271d1f8869ecd945891ae6a9b02682335af625c29f80572b440f91a3a343f3ea600a49a426960b6c1c5dd7b24540ecb745329312dfdd525fd173418c846f0096acba466a27446114f3a2b2a887986846b01b860b3dff5505fe9ec48fa11a67dbf166e7d5ab3473ff9f5fdc90c690eb1142ad687b17eb8ab0c08615c9397b351c53e79016d593d588f8c607b2d1136713d05066ffd8a30589357afa54a0a7ac8777372787261dde126c4f0c04bf741f809c3be80b860451da71ff5b1e9b4fd587fd76f53808191096cc5869596eda8f3ad697426a98a659f5f4818e57866d4b0dd90f0684900742a167b314f0276e5e6a8bc6f40ce1cd1d35c7f9be56f1240de596b30a4b40010dfd21b7fc9aef400faaa421e27a080b860277d5eedd8cf7d549296a6f8ad2869ec6e90183b9e8ebbf49a9d3ecd817757b50c6acc6cab9f0dbcf4b87251b6e82a0192a00c1e509225ec1ec08dcbeb04ba2808b16f72af90f33277e614dc19383256b3980421441ce3e75356ee35e5f62d80b86007431d3192f7a273382b645bc300cb0161c2395c005bf389698ce4a3ac56cffb9405456102f5b6e41b42bb28e7cb1f0141d3e1be1b066a94cc2befe88b0f5eef63c60a1ab8a1f0cc02e73c0ce5aac464332d3a2c1074a5126807a75323280301b8600d39e1cd00ff4ce5e41fa9ea90526f3e3540b64ba52954e5682f31ec20360b2995d5caac7cee778ff7c13aaca74b9b004032f87a331867e9ebc7ed06c5b77707c88614714f2e0ed30c85c519aa823aa9d1a7a56766a294c7802aad300b408280b860ce9efb226a3c085071c7aea84f66040dc16a1600893eb1e6ef507fa72c6684f24d2c3b4ffee9881142fc41cfbd6b3b01933838ed7bd05c16450cab703b12ee623f8745f7f618981601a9c4de1337fe881975bc8572536281b9dcc51400177680b860075724b0f2fa9ced3440a76107a53b02a0b8b5a5a510d94b02b5c0696db96910204d54ee3138b3e5949464585d98de00a2964d480ca31adf09c962802895ea160d195bce583e59094bf7c11d33eaffef12cb999284bcf842bbab2c87647d8801b8603b0ffa0a101f959879b7e14d830862981d6c311ffd440f214eee0a2891743a25355e9230266aeadbd20f3bde0ccb30008bf326df8fba9b701d4764ad49663da19417132edf4281df4560715649491d9794dc64e9540d16b51b362e139c3aa701b8601a65e75f0f47d7c92da92de15372a0052338b952cc1307d5ee1596a670fedeb3b5ac8bc690f3f5e5f34fb8d18a5441011d6023e3c2b343bffc655972102a7181dffcab47bd0a2d6d46eedc6f2b70cd64025715de2b8ae23c032e61b380663c80b86071ca0f2be942a733074e8e0d92ae0adc2617bcfe503b97f8339c8f1c498d85608fa5966da7abdd9651c9ce4e3411e900c4d65d5c7d858f1e5ee212c9e543d3727aeaa9abbdcb68848e7c990c06aa70a4bf2585959943935549e7a9e2c2ba0d80b8600122d3f6ae5e2bc6fdee3cd35a3522ea519bfa6f365451fa275c4688bcfb5cec418fa053a8859981e973ea273ca68f014e840d0ccf18cc7c498742103c3116732ef197a9f90f50bf64f83754a86ad441fe9691bfdf384a1aaacf38430a2b1001b8601135b86a2587c75c55db8274e498bd3f2887a1a455a665b8314655124c5e8197d3ef892f3dea2bd80b047530f837ae00dc263da929f0135a4f8ee73d47d5c2ffcaaa7b1e3a9cc59e496feeea2323e5eb16c9de2e3b973c35c0a82ca587477201b860e162bf706b79405326d52e29e2ea247a55ebf69ac34900e4e1249c3fe28fd3dabf40d7022f57bc7b16bedbc78bb49000ba7cd92e123b69309a0572cf49b1bdf4c5525ba656decffa5da91ed4fb565d384979e9a58f72986b654908bcc7308580b860e9dbc5c1d073954ad6ace9afb19d8679e8c87fd12cd1356999a8e167390f3de966f3485b500c40c61f829e12f56512001b4d4c4fcb19737735eba15d24d43231ce64cf348de3765fdbd01f4612af6ad7ebf9fafb594ade18a7717c189e9c2080b860bd8e3d6ad24e5a7e4f084b3142c6bebe26d248e09363a9bbfc9cd07ed59a65bc140a39564f6ecdf287c2ee1ed57a930035a92306b6d5925af8785c813bad6113ba42da88d3c0586e438df75bee506bdf9f10c927493524897ba485946f976f00b86030feb59a6804a2df697b3a40c691f176575ffb0d09fa167a59642d041dfec97e97414ea7abc8bc7bdad5f1a684e2bc00fb2c01bc03aa9e8caaaa82ca3210de31f9c7abff6baba5e08e2dbdfa85953ac39bf3b895627e7be493fbb6e346061400b860f24f6f1e6423fd83d1ef275484a5950fed90794d7bfb6224de768bf716646dee263de0d9ed4c681c0def78d16df0f000f1e17b8657f1d8e30dcb7e94cd1c79b9c82d8f04252b078ccf3719c7658dd82b9d93e02671925b5aeb4ae38163129100b860f6a586f1ceb85a23980bdfea738678f5906de5303a7ff6ceb3ad675f93a84fcc502275fd7bd8fde4de89fd381cb8eb000b3d496e248208d00eae4f421ce041d73789e794a372ca788655eb5413c3b7cab1c993e47ff6c568ca4da484bac88b80b86086ab977d6064531b136aba2fbcc50cfb332b939e0af22c7ff3800c804b33aad998ef69a97204076028a6946d627d2f0086992cba351fd538a91986253884325aba6d66ec1ac10eb8e18330180820cc388c22de7d64f9f0592b74ee5b35745a80b860fda02a60f25f87c0fc86be0bf52bf1d0be37db80661a2fa35c7f52a4c5f5edccca04768c762caaa2303f8cac2ba93e016dce7c8382e3d002e751e0bf33563eb8f6e7937ab2998300e96f5ed3d857d081ff389c495febaabe836a7cd06012ae80b8609271a103e5971edd694b3c6363a2517b0676849b05660094baf240ea9677e171169a8eebed5ad6000871b4f42d4ca701b74b10f91c0de059d225ced0222e391cf7bdb5934d1677193837d5a1f17bb710f4747956d819db51c817cbba53324b81b860719b2de30cbcdee6e62445b7c2eedb63520beb4cb6e4a55f7e121a5bc6a1143e1322d3ffea28ab624d30f6da8962b8003eeb056df8e46a49035c0aaf139a372e954d8ebc3cbd2d0b2e5727d54f3f4fcd0e95dc29bfa9f9ddcda98bbe8107ae00b860b054d545899f55cbb84853125d50ed06211ace3eeb6160a85583de508569e65592f5a221a000cb99997c0dd2738527010f2b1e83eeb7ca41c40ad9295b35f1172004a63567f140c1d2b0e04338161e8f1be88c1543ac75d587e42c3ed7dc1880b860e8de954d3100b125b2a3c1e4a81e3ac5f4b38f85c2ed91d752c507d4a37c338ca215e474a48511c599407b85c01d37012cd5012c74c5c0c3f88b4480a73bb52d1ff49848ca014f54cde1a891e6efa483b5f64016a9303515806c45d9f79a7e81b860bfce6153e2c2dabc724d9ccf5cad8916753dce1a495a29053ff7e5b74b0eace4889d5fd2d5859400d82b6bf29cecc9006b6e37152cb1f4f72e7d0c0897439f4ef886e26b4345d2f3e73bcf08d47f02c02976730620d7f844313c099894176980b860d56a6034613c0db14cad99e0d2dc3a2482ff8167a032218ac10508bb04fb8ef91d40a6ef0731f1e162761f09be237800363199f518a1bad98f9f2d179d2028137f9a86588c5cd91534a53d4edcc718b40aab61343571636d052eb7b288578c80b86025138a99de6619b2ad03707f847ac0f5d79b0fba2c67a02f5430a57c7a651d6cd63988cb91aa331acd8b7221a41fc4007be73ad86365de5029c22186d2c90a864fd3d386cc074b25f33b4e5f17839d2780b62390f1fe63ec690c1022c039f500b860c1e12e9c0b26d73c27dd5f60f08aa15c952afaa395dbc8b4cb99453bbf3f14ede8a9fc579f64500497344cb3637aa900ac8618d237580558d9ab5b042ac411fd121713744378c9f4d897907f09a71af9331bfecb3853e3f0577be558c9019881b860c8e6cf45b640fa91385b4f7e891fe68e5ef6847d032d6ee1b52eef0ff577ad796b881537f94adcbd1b52ba3e0e5d7e014e97406029095598a373fd6d9b6c7754aa87b87560e363faee89c11482cae4a063d7cbe65747f2b095cd2f6688a8bd00b86008fb22b9fe04caf62059216dfa1d2274ade1df9e8dc0b3c37c2f04a8b3d30a73f8b7ddd873d08c9b9302b936d303380147ce0e19c4600b780a1814730462147fb8280fbd7fe0aa7290d325a2b7b5092e05c037664a0aaea127b0d95fd13e3d81b86068dd5abe43baf4f4817a49b094c0bb19ed4971c49a6f91863163f655b6f312d80b7c7843b4cb7a27f7e54d48c41c7a01c5e22e1b0e38a5dbb03dfee76076a9af56146359add6003410005332417f6b65db718acce693cfa21a8fd92f6ad72800b86091785b64cfd3ac6025b6b536499ac63868344b8f86660ed73b574b000477807d53dacf1d9da258ee1b113485a01579001c5a510dd3b3c5ff1f417c4d97faf997aecedf7602bd96155f8396f5c9fa53d2c601b0de0241fff49939b8a97ce59f81b86000d869e78871139e8a5ff6d590593d94ea39ea73e87ac8d901f0f524372b93752a488b34e05afe05ab53b1c1b5b9a50040341dc01361110551358c9e982f30755e19ec2ad1c1a40afba9998f763599149b976caaded14c1793fe8c469b17c900b860e87f2bfc49c076239d7522280098c9c4808524c67f3891608c42a510340d64c7e3c1c074c34050007837c13536ee4001108efc87fb2eb8c3236a738122ec086a7b8e6857e82454ff6284a81bf0362424ba96be762d4c06e6aa1b59f20c870780b8608bd2cb218f465c82702aba73a061227cd83dd8e3115ae592811a4d9a8236e3cb99cfe81b2e22e3620635d42f63b7db00cd546bdf9fad7b49d0b4686962c8e0f4544c8df9f41d30d7d489c86745ef9b61a7dfb498f7554eeaf7e24654e5b2e080b8602a5d5145b7a8100575e96cadf2513e7e64dc1354bd891a24f985c2574c9f5f136c6837eab290543d769227785520970133022637837b6e711918f3d2e98291bf3b518247b54e925a0cd080d517731b2725be888fca298ae9ec6f5d2c19146b01b8609cedde7d49e2e115896b789ece09a4e8816fae153de891774f0f716a3088e01754498f8ab82d3a4ef5d53dbe17338f0089d1de1eb60bfe3ec2b9701cd882b1c174bdcfaac2225f57481676bd3ee845825be823b9f9317e407b015159b9ce7e80b8609124b91b223bf9bcb33f75ab8fad0180fdc57536d34349945b80458abc8e59cb06005fabea656b2cd0dc74c0d06160019706965ec3ee0d3b9dd76eb9d39158bd512fe7384bb9e139bc6391d5f7b969397bd85a91bb91670880d861e8fcbd0700b860338fa194daae9ba1245931653fa349ce85d37e2f42f871c6b67397401e190b497d15ff23e8f6e9d8637f84fc2dd4640066fee692f5d38208233e7570c3ed49a4ba032d79c7a974883fa5b5c2a113259b924a346bc4edaf717b3d272ceb152980b8606150a62f3bae3a35a639d66dc37ffbc979dda85d6f5c278a5e3a563ed865018c86563be9b878261ef8d34edd3c313500a4f170e22f386674d538b9e15930f39216a38c2a0b60380a140e5897f42d37077784cd0f1a93746e4da42a5da8de1081b8605fd1581e41fa22e7ea0d3ee0674e80e2168fdb42c1aaa3eb8aa395fdde11de5ca98ee71c50b365ef6ad9850bacf7ab011eb446da79efba3ae91fe1f7d9274dacda39b0b3bfaec7d7904eac59d72683c52b6ea091ca1374d8b744fd1d595c5700b860e04a671c7f9af919093a9c7aaf5c3d04eff31189d65f5a2aef8a08119ed1c150464c40085bfe2fc1b598fc2ebb095101d0103b995e3a762a9063d823ef6686422caa5a390f9cef5ee6c4b911fd2a818f43fa47ab4d21b01cc7b071b517438d81b86014cfe4d455820e0b9189ccb32b565b90d414ed7d315d3e61141f085b6aaea34b0c90d1f502f544408e7ed0573e1d1701d38063b239cf847018daa41b7ef75b4458d2fa23e459e9e8039668aca6bc70df1051a6466a5a5bc636e68bc8e2380a80b86045bab7cfb2814e1e3e1a40779219bb48c5d51419ce4c27359d0dfea9fbf1d193ca1cf07934ebf3d6699093387d0e0f000dc5fd2058e7ac50e67c26e5172567c2e7ba9fefa6376e44de800c8955cb330df27476d8ba9c8ec06bba46fddeb95e81b860a9fc64c64c039cbd8b23c10c706e51e0013289201111cf8c50e22781161df397fa9c1b91dbab44969aa4f8819f222e01bab90190bebfaecff7076de325dae8080bfe921fbb4ca474d45126fe5ae699dadea98a5255c048b955ab9ba1de8f4c01b860aa5729ac27a01f26924e863eea7d7b49e4f8ccb15c758ea5ac4d19691a8df31f70138e7f3011fc1e53d52d7063dd8d01a9b3800a66914956769a13ff8d7960725bf1b9073052f3ff85e57b34165702baede05d4e807bfb565a38c24e3542c780b86014dafe41c0d96b22188f0cf6cb99274e09d8ed0546bb57b28a3590449726aedf809c049663a2fe4e40b91830ac864d006a9c5b41cbddeabeef99cfddf6c298de0d482b6e945993241d8987f7fac004fe159f2206060b69d1f8f7f67f63f26280b860878790bb38b1d31707aa37b5af439d64d4a29ea64418b7c01139a26e4f297da6c61a806361e6fee8e40556500c8a6000183b2a42c54d714a143fe12492081f373e3e27e3921adeb276a8daac8b87a534c0fa1d45195d8a35cbda27f883128680b8607983d25868e1915ca8c20603bb70475b398acb04fef221106475f0fc25a3df25d181050214da347bfcd8f8292e5257014ba77cf67ee5f42202257317808f126930b4eaaf4bec801c4465ced54bd78331f8d3dadfdf2f91de294836c13e946001b860c700f20fab4ebb8ba2f47adf177e3a9dbbfb8d999acbaf0055cc540758f8c00c4564813d910e7be02e4ceaa97fb88000b3e8e6fb4308fb943fa0a3d8ee32c3a16e67eae0817370de54bec1e13193cc845cedb70e48171e097550475684cc6600b8603a3857a5e4a709e1891a13797d55c1698f931755492099926314feec955da31fcea8a8c8e52ce2efd74008f32dbc1c00c1b3d36c1f3097d806f1687eff4a979ff967a8233f923a1af6a3104c12d9d44388bece91a248bd86f253e709cea7a380b860d8704fbf6968ffd9f39f78173726dfebbaaffebd8a33dfe29a72b9a64204debf2016ca94cbecb1b84cab9d5cc168f70082530b8cfab0225a37c8cc3044c288ab0fea2f484b56a33fe6c92d6c50f254e6b1689ac6bb1429cc36a0a7dfa85cf880b86089bc906b5ea07752b1981558fd5d329f6d428bc14dfde022745303eae0077612b9c473cd66e4d91778282ec98bbd74001b61cd71448750df642fb580ce81a62ff2f5ab4378528ccd65acff67ac2175678f598529c768247c77938ca2d529aa01b860fb9de050c059a11175be23daeef1bfc374a688d8fd776e7d2dc81fe301068a3af03ad522bd915a154dc8b5b8e12d38003f17bf9f3001e8bc682e38cfc93c6901417afe1ddbfe11b04f42ca4f321f7ba73fa98f0e8c8d75781b14c0dea847a500b860bef17561ef747e0f11fd339987a9813fa8ac1cbbd6457ab8fae4841f2217de019de7caf421631372b7eec730d9210d0128e6c560948c19ab6141d6699e0283a5b98abb8266d731f2b6435a07b44360a3f5622cff59103ec95938ab74fe1d8f01b860a47fd022dda04d8dd36e0a8127be68736e47e490b946d2d88a9fdcca0a5114a930db2319e7e9f378d1b81da865d38b01a063e9994e620483b08047da39ee2fba35f66df5734e1545d297be0225ddfda34e494c1f09825eed303d166a8b702f01b8605966b41d69c0e94e202f65823338c3ee0357b024a6ef625765bcf3c20e1786258a18221e0b9a34b43380e06984d92f0183d0f86d0dfe0cac237ee38b28876dada3ae9d1a7c1e6627c3b524d0e5d4270bbe159661622821412b3c1162881ead80b8608fad3c2111494834f30e6d8a3368f2aa156c991fa4b9d55c31da88310a61248305697ad5e885404bc474419383de4f006c89c84955321716f6ceb4d5db433fcabe843d566a5e9526d29c58b38fda9ff2a13f7841f25cda8ff091c965bdf91780b8607f9df4fdb96e20e0a480a62c48896646d96982d7fccccdf70c61f2f52ab4ea2901b5ef468203f39d9d8325843ada0d00e9562c64f79ec16d69b5921ad36306ae9ae2ab97806b354af8cb63722a96aed5fa0542fff58d2e41f6aee3cb641f7781b8609cc39207797e5c37f6336c4444cf275d0afd43a9b257a08086f15867886833744c9b5753fcff76fce3790d7f25a45e004af9831464bf43e39634ecfce8da4641da78ad4ba20e540c007dbc19e391ae69cfb7809b2d20627d553a16d7d71b5a80b860e6631bd0b82c41327b582d7b239c9893cd1162cae05f360d8808700b38ee0ee965e9bd9246d79e00c234c87aa7699800c73428f7eccd77337bf79bf6b43f48345be265c38d128d2cd7f37167cadb3565d66e6a7f67b12f4bed63e5d50748010080b8410000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f86480b86000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080f86480b86000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080", - "difficulty": "0x1", - "coinbase": "0x0000000000000000000000000000000000000000", - "alloc": { - "0x11901cf7eEae1E2644995FB2E47Ce46bC7F33246": { - "balance": "120000000000000000000000000" - }, - "0xC1cDA18694F5B86cFB80c1B4f8Cc046B0d7E6326": { - "balance": "20000000000000000000000000" - }, - "0xa5d40D93b01AfBafec84E20018Aff427628F645E": { - "balance": "20000000000000000000000000" - }, - "0x8d485780E84E23437f8F6938D96B964645529127": { - "balance": "20000000000000000000000000" - }, - "0x5F857c501b73ddFA804234f1f1418D6f75554076": { - "balance": "20000000000000000000000000" - }, - "0xaa9064F57F8d7de4b3e08c35561E21Afd6341390": { - "balance": "20000000000000000000000000" - }, - "0x7FA26b50b3e9a2eC8AD1850a4c4FBBF94D806E95": { - "balance": "20000000000000000000000000" - }, - "0x08960Ce6b58BE32FBc6aC1489d04364B4f7dC216": { - "balance": "20000000000000000000000000" - }, - "0x77B68B2e7091D4F242a8Af89F200Af941433C6d8": { - "balance": "20000000000000000000000000" - }, - "0x75Bb69C002C43f5a26a2A620518775795Fd45ecf": { - "balance": "20000000000000000000000000" - }, - "0x19992AE48914a178Bf138665CffDD8CD79b99513": { - "balance": "20000000000000000000000000" - }, - "0xE23a4c6615669526Ab58E9c37088bee4eD2b2dEE": { - "balance": "20000000000000000000000" - }, - "0xDe22679dCA843B424FD0BBd70A22D5F5a4B94fe4": { - "balance": "10200014000000000000000000" - }, - "0x743D80810fe10c5C3346D2940997cC9647035B13": { - "balance": "20513322000000000000000000" - }, - "0x8e1c4355307F1A59E7eD4Ae057c51368b9338C38": { - "balance": "7291740000000000000000000" - }, - "0x417fe63186C388812e342c85FF87187Dc584C630": { - "balance": "20000062000000000000000000" - }, - "0xF5720c180a6Fa14ECcE82FB1bB060A39E93A263c": { - "balance": "30000061000000000000000000" - }, - "0xB80d1e7F9CEbe4b5E1B1Acf037d3a44871105041": { - "balance": "9581366833333333333333335" - }, - "0xf8ed78A113cD2a34dF451Ba3D540FFAE66829AA0": { - "balance": "11218686833333333333333333" - }, - "0x9033ff75af27222c8f36a148800c7331581933F3": { - "balance": "11218686833333333333333333" - }, - "0x8A07541C2eF161F4e3f8de7c7894718dA26626B2": { - "balance": "11218686833333333333333333" - }, - "0xB2fe7AFe178335CEc3564d7671EEbD7634C626B0": { - "balance": "11218686833333333333333333" - }, - "0xc471776eA02705004C451959129bF09423B56526": { - "balance": "11218686833333333333333333" - }, - "0xeF283eca68DE87E051D427b4be152A7403110647": { - "balance": "14375000000000000000000000" - }, - "0x7cf091C954ed7E9304452d31fd59999505Ddcb7a": { - "balance": "14375000000000000000000000" - }, - "0xa5d2944C32a8D7b284fF0b84c20fDcc46937Cf64": { - "balance": "14375000000000000000000000" - }, - "0xFC89C17525f08F2Bc9bA8cb77BcF05055B1F7059": { - "balance": "14375000000000000000000000" - }, - "0x3Fa7C646599F3174380BD9a7B6efCde90b5d129d": { - "balance": "14375000000000000000000000" - }, - "0x989e1a3B344A43911e02cCC609D469fbc15AB1F1": { - "balance": "14375000000000000000000000" - }, - "0xAe1d640648009DbE0Aa4485d3BfBB68C37710924": { - "balance": "20025000000000000000000000" - }, - "0x1B6C64779F42BA6B54C853Ab70171aCd81b072F7": { - "balance": "20025000000000000000000000" - }, - "000000000000000000000000000000000000ce10": { - "code": "0x60806040526004361061004a5760003560e01c806303386ba3146101e757806342404e0714610280578063bb913f41146102d7578063d29d44ee14610328578063f7e6af8014610379575b6000600160405180807f656970313936372e70726f78792e696d706c656d656e746174696f6e00000000815250601c019050604051809103902060001c0360001b9050600081549050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610136576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f4e6f20496d706c656d656e746174696f6e20736574000000000000000000000081525060200191505060405180910390fd5b61013f816103d0565b6101b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f496e76616c696420636f6e74726163742061646472657373000000000000000081525060200191505060405180910390fd5b60405136810160405236600082376000803683855af43d604051818101604052816000823e82600081146101e3578282f35b8282fd5b61027e600480360360408110156101fd57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019064010000000081111561023a57600080fd5b82018360208201111561024c57600080fd5b8035906020019184600183028401116401000000008311171561026e57600080fd5b909192939192939050505061041b565b005b34801561028c57600080fd5b506102956105c1565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156102e357600080fd5b50610326600480360360208110156102fa57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061060d565b005b34801561033457600080fd5b506103776004803603602081101561034b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506107bd565b005b34801561038557600080fd5b5061038e610871565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b60008060007fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47060001b9050833f915080821415801561041257506000801b8214155b92505050919050565b610423610871565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146104c3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f73656e64657220776173206e6f74206f776e657200000000000000000000000081525060200191505060405180910390fd5b6104cc8361060d565b600060608473ffffffffffffffffffffffffffffffffffffffff168484604051808383808284378083019250505092505050600060405180830381855af49150503d8060008114610539576040519150601f19603f3d011682016040523d82523d6000602084013e61053e565b606091505b508092508193505050816105ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f696e697469616c697a6174696f6e2063616c6c6261636b206661696c6564000081525060200191505060405180910390fd5b5050505050565b600080600160405180807f656970313936372e70726f78792e696d706c656d656e746174696f6e00000000815250601c019050604051809103902060001c0360001b9050805491505090565b610615610871565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146106b5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f73656e64657220776173206e6f74206f776e657200000000000000000000000081525060200191505060405180910390fd5b6000600160405180807f656970313936372e70726f78792e696d706c656d656e746174696f6e00000000815250601c019050604051809103902060001c0360001b9050610701826103d0565b610773576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f496e76616c696420636f6e74726163742061646472657373000000000000000081525060200191505060405180910390fd5b8181558173ffffffffffffffffffffffffffffffffffffffff167fab64f92ab780ecbf4f3866f57cee465ff36c89450dcce20237ca7a8d81fb7d1360405160405180910390a25050565b6107c5610871565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610865576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f73656e64657220776173206e6f74206f776e657200000000000000000000000081525060200191505060405180910390fd5b61086e816108bd565b50565b600080600160405180807f656970313936372e70726f78792e61646d696e000000000000000000000000008152506013019050604051809103902060001c0360001b9050805491505090565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610960576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f6f776e65722063616e6e6f74206265203000000000000000000000000000000081525060200191505060405180910390fd5b6000600160405180807f656970313936372e70726f78792e61646d696e000000000000000000000000008152506013019050604051809103902060001c0360001b90508181558173ffffffffffffffffffffffffffffffffffffffff167f50146d0e3c60aa1d17a70635b05494f864e86144a2201275021014fbf08bafe260405160405180910390a2505056fea165627a7a723058206808dd43e7d765afca53fe439122bc5eac16d708ce7d463451be5042426f101f0029", - "storage": { - "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0xE23a4c6615669526Ab58E9c37088bee4eD2b2dEE" - }, - "balance": "0" - } - }, - "number": "0x0", - "gasUsed": "0x0", - "mixHash": "0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365", - "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000" -} diff --git a/start.sh b/start.sh deleted file mode 100755 index 06429adee8..0000000000 --- a/start.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/sh - -case "$1" in - validator) - ./build/bin/geth --datadir ~/mydata/datadir --syncmode full --gcmode archive --debug --port 30303 --rpcvhosts='*' --networkid 1101 --verbosity=3 --consoleoutput=stdout --consoleformat=term --nat extip:127.0.0.1 --allow-insecure-unlock --rpc --rpcport 8545 --rpccorsdomain='*' --rpcapi=eth,net,web3,debug,admin,personal,txpool,istanbul --light.serve=0 --mine --minerthreads=10 --nodekeyhex=add67e37fdf5c26743d295b1af6d9b50f2785a6b60bc83a8f05bd1dd4b385c6c --istanbul.blockperiod 10 --nodiscover --password=/dev/null --unlock=0 --ws --wsaddr 0.0.0.0 --rpcaddr 0.0.0.0 --wsapi=eth,net,web3,debug,personal --wsorigins='*' --wsport 8546 - ;; - fast) - ./build/bin/geth --datadir ~/fasttest/validator --syncmode full --gcmode archive --debug --port 30303 --rpcvhosts='*' --networkid 1101 --verbosity=3 --consoleoutput=stdout --consoleformat=term --nat extip:127.0.0.1 --allow-insecure-unlock --rpc --rpcport 8545 --rpccorsdomain='*' --rpcapi=eth,net,web3,debug,admin,personal,txpool,istanbul --light.serve=0 --mine --minerthreads=10 --nodekeyhex=add67e37fdf5c26743d295b1af6d9b50f2785a6b60bc83a8f05bd1dd4b385c6c --istanbul.blockperiod 1 --nodiscover --password=/dev/null --unlock=0 --ws --wsaddr 0.0.0.0 --rpcaddr 0.0.0.0 --wsapi=eth,net,web3,debug,personal --wsorigins='*' --wsport 8546 - ;; - node) - ./build/bin/geth --datadir ~/mydata/nextnode --syncmode full --debug --port 30301 --rpcvhosts='*' --networkid 1101 --verbosity=3 --nat extip:127.0.0.1 --allow-insecure-unlock --rpc --rpcport 9545 --istanbul.blockperiod 1 --rpccorsdomain='*' --rpcapi=eth,net,web3,debug,admin,personal,txpool,istanbul --light.serve=0 --nodiscover --unlock=0xfD5d2142281fbfA75439f94774506fE76641CDd6 --password=asd - ;; - spammer) - celo --datadir ~/mydata/spammer --syncmode full --debug --port 30302 --rpcvhosts='*' --networkid 1101 --verbosity=3 --nat extip:127.0.0.1 --allow-insecure-unlock --rpc --rpcport 10545 --rpccorsdomain='*' --rpcapi=eth,net,web3,debug,admin,personal,txpool,istanbul --light.serve=0 --nodiscover --unlock=0xAdB5B5DfB87dd7652796c3b91Ff27001d55CCca6 --password=asd - ;; - faulty) - celo --datadir ~/mydata/faulty --syncmode full --debug --port 30302 --rpcvhosts='*' --networkid 1101 --verbosity=3 --nat extip:127.0.0.1 --allow-insecure-unlock --rpc --rpcport 10545 --rpccorsdomain='*' --rpcapi=eth,net,web3,debug,admin,personal,txpool,istanbul --light.serve=0 --nodiscover - ;; - connect) - ./build/bin/geth --datadir ~/mydata/datadir attach --exec 'admin.addPeer("enode://619702d99a2c3161ab816e0e1ca82abba8ab95edbb7702903f9052204b2c8194affbf6564d822643f7a24ef97eb42982c966b4b1857a8f3e2b3a9ef32b519570@127.0.0.1:30301")' - ./build/bin/geth --datadir ~/mydata/datadir attach --exec 'admin.addPeer("enode://a1403c44bad29b0efd734f4629484c7da8d52f28dbbc4bc2d96a222aa883549be5abc6f0adbf79259cbe82ec9b8452c2b2b35b960a2f99ef50b33909f48b1f0d@127.0.0.1:30302")' - ;; -esac - -# ./build/bin/geth --datadir ~/mydata/datadir --syncmode full --gcmode archive --debug --port 30303 --rpcvhosts='*' --networkid 1101 --verbosity=3 --consoleoutput=stdout --consoleformat=term --nat extip:127.0.0.1 --allow-insecure-unlock --rpc --rpcport 8545 --rpccorsdomain='*' --rpcapi=eth,net,web3,debug,admin,personal,txpool,istanbul --light.serve=0 --mine --minerthreads=10 --nodekeyhex=add67e37fdf5c26743d295b1af6d9b50f2785a6b60bc83a8f05bd1dd4b385c6c --istanbul.blockperiod 10 --nodiscover --password=/dev/null --unlock=0 --ws --wsaddr 0.0.0.0 --rpcaddr 0.0.0.0 --wsapi=eth,net,web3,debug,personal --wsorigins='*' --wsport 8546 From 7787ba18d94b1bab7689a88be49b516d8e9a0da5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sami=20M=C3=A4kel=C3=A4?= Date: Tue, 15 Sep 2020 15:36:57 +0300 Subject: [PATCH 03/15] tests seem to wokr --- core/blockchain_repair_test.go | 254 +++++++++++++-------------- core/blockchain_sethead_test.go | 292 ++++++++++++++++---------------- core/blockchain_test.go | 2 +- core/rawdb/freezer.go | 10 +- p2p/discv5/node_test.go | 2 +- 5 files changed, 283 insertions(+), 277 deletions(-) diff --git a/core/blockchain_repair_test.go b/core/blockchain_repair_test.go index 27903dd06b..a33c01e375 100644 --- a/core/blockchain_repair_test.go +++ b/core/blockchain_repair_test.go @@ -21,13 +21,13 @@ package core import ( +// "fmt" "io/ioutil" - "math/big" "os" "testing" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/consensus/ethash" + mockEngine "github.com/ethereum/go-ethereum/consensus/consensustest" "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" @@ -385,123 +385,6 @@ func TestShortNewlyForkedFastSyncingRepair(t *testing.T) { }) } -// Tests a recovery for a short canonical chain and a longer side chain, where a -// recent block was already committed to disk and then the process crashed. In this -// case we expect the canonical chain to be rolled back to the committed block, but -// the chain data itself left in the database for replaying. -func TestShortReorgedRepair(t *testing.T) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) - // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 - // - // Frozen: none - // Commit: G, C4 - // Pivot : none - // - // CRASH - // - // ------------------------------ - // - // Expected in leveldb: - // G->C1->C2->C3->C4->C5->C6->C7->C8 - // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 - // - // Expected head header : C8 - // Expected head fast block: C8 - // Expected head block : C4 - testRepair(t, &rewindTest{ - canonicalBlocks: 8, - sidechainBlocks: 10, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: nil, - expCanonicalBlocks: 8, - expSidechainBlocks: 10, - expFrozen: 0, - expHeadHeader: 8, - expHeadFastBlock: 8, - expHeadBlock: 4, - }) -} - -// Tests a recovery for a short canonical chain and a longer side chain, where -// the fast sync pivot point was already committed to disk and then the process -// crashed. In this case we expect the canonical chain to be rolled back to the -// committed block, but the chain data itself left in the database for replaying. -func TestShortReorgedFastSyncedRepair(t *testing.T) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) - // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 - // - // Frozen: none - // Commit: G, C4 - // Pivot : C4 - // - // CRASH - // - // ------------------------------ - // - // Expected in leveldb: - // G->C1->C2->C3->C4->C5->C6->C7->C8 - // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 - // - // Expected head header : C8 - // Expected head fast block: C8 - // Expected head block : C4 - testRepair(t, &rewindTest{ - canonicalBlocks: 8, - sidechainBlocks: 10, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: uint64ptr(4), - expCanonicalBlocks: 8, - expSidechainBlocks: 10, - expFrozen: 0, - expHeadHeader: 8, - expHeadFastBlock: 8, - expHeadBlock: 4, - }) -} - -// Tests a recovery for a short canonical chain and a longer side chain, where -// the fast sync pivot point was not yet committed, but the process crashed. In -// this case we expect the chain to detect that it was fast syncing and not delete -// anything, since we can just pick up directly where we left off. -func TestShortReorgedFastSyncingRepair(t *testing.T) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) - // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 - // - // Frozen: none - // Commit: G - // Pivot : C4 - // - // CRASH - // - // ------------------------------ - // - // Expected in leveldb: - // G->C1->C2->C3->C4->C5->C6->C7->C8 - // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 - // - // Expected head header : C8 - // Expected head fast block: C8 - // Expected head block : G - testRepair(t, &rewindTest{ - canonicalBlocks: 8, - sidechainBlocks: 10, - freezeThreshold: 16, - commitBlock: 0, - pivotBlock: uint64ptr(4), - expCanonicalBlocks: 8, - expSidechainBlocks: 10, - expFrozen: 0, - expHeadHeader: 8, - expHeadFastBlock: 8, - expHeadBlock: 0, - }) -} - // Tests a recovery for a long canonical chain with frozen blocks where a recent // block - newer than the ancient limit - was already committed to disk and then // the process crashed. In this case we expect the chain to be rolled back to the @@ -1295,6 +1178,125 @@ func TestLongNewerForkedFastSyncingDeepRepair(t *testing.T) { // to disk and then the process crashed. In this case we expect the chain to be // rolled back to the committed block, with everything afterwads kept as fast sync // data. The side chain completely nuked by the freezer. +/* + +// Tests a recovery for a short canonical chain and a longer side chain, where a +// recent block was already committed to disk and then the process crashed. In this +// case we expect the canonical chain to be rolled back to the committed block, but +// the chain data itself left in the database for replaying. +func TestShortReorgedRepair(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) + // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 + // + // Frozen: none + // Commit: G, C4 + // Pivot : none + // + // CRASH + // + // ------------------------------ + // + // Expected in leveldb: + // G->C1->C2->C3->C4->C5->C6->C7->C8 + // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 + // + // Expected head header : C8 + // Expected head fast block: C8 + // Expected head block : C4 + testRepair(t, &rewindTest{ + canonicalBlocks: 8, + sidechainBlocks: 10, + freezeThreshold: 16, + commitBlock: 4, + pivotBlock: nil, + expCanonicalBlocks: 8, + expSidechainBlocks: 10, + expFrozen: 0, + expHeadHeader: 8, + expHeadFastBlock: 8, + expHeadBlock: 4, + }) +} + +// Tests a recovery for a short canonical chain and a longer side chain, where +// the fast sync pivot point was already committed to disk and then the process +// crashed. In this case we expect the canonical chain to be rolled back to the +// committed block, but the chain data itself left in the database for replaying. +func TestShortReorgedFastSyncedRepair(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) + // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 + // + // Frozen: none + // Commit: G, C4 + // Pivot : C4 + // + // CRASH + // + // ------------------------------ + // + // Expected in leveldb: + // G->C1->C2->C3->C4->C5->C6->C7->C8 + // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 + // + // Expected head header : C8 + // Expected head fast block: C8 + // Expected head block : C4 + testRepair(t, &rewindTest{ + canonicalBlocks: 8, + sidechainBlocks: 10, + freezeThreshold: 16, + commitBlock: 4, + pivotBlock: uint64ptr(4), + expCanonicalBlocks: 8, + expSidechainBlocks: 10, + expFrozen: 0, + expHeadHeader: 8, + expHeadFastBlock: 8, + expHeadBlock: 4, + }) +} + +// Tests a recovery for a short canonical chain and a longer side chain, where +// the fast sync pivot point was not yet committed, but the process crashed. In +// this case we expect the chain to detect that it was fast syncing and not delete +// anything, since we can just pick up directly where we left off. +func TestShortReorgedFastSyncingRepair(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) + // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 + // + // Frozen: none + // Commit: G + // Pivot : C4 + // + // CRASH + // + // ------------------------------ + // + // Expected in leveldb: + // G->C1->C2->C3->C4->C5->C6->C7->C8 + // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 + // + // Expected head header : C8 + // Expected head fast block: C8 + // Expected head block : G + testRepair(t, &rewindTest{ + canonicalBlocks: 8, + sidechainBlocks: 10, + freezeThreshold: 16, + commitBlock: 0, + pivotBlock: uint64ptr(4), + expCanonicalBlocks: 8, + expSidechainBlocks: 10, + expFrozen: 0, + expHeadHeader: 8, + expHeadFastBlock: 8, + expHeadBlock: 0, + }) +} + func TestLongReorgedShallowRepair(t *testing.T) { // Chain: // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) @@ -1552,6 +1554,7 @@ func TestLongReorgedFastSyncingDeepRepair(t *testing.T) { expHeadBlock: 0, }) } +*/ func testRepair(t *testing.T, tt *rewindTest) { // It's hard to follow the test case, visualize the input @@ -1574,9 +1577,9 @@ func testRepair(t *testing.T, tt *rewindTest) { // Initialize a fresh chain var ( genesis = new(Genesis).MustCommit(db) - engine = ethash.NewFullFaker() + engine = mockEngine.NewFaker() ) - chain, err := NewBlockChain(db, nil, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil) + chain, err := NewBlockChain(db, nil, params.IstanbulTestChainConfig, engine, vm.Config{}, nil) if err != nil { t.Fatalf("Failed to create chain: %v", err) } @@ -1592,13 +1595,13 @@ func testRepair(t *testing.T, tt *rewindTest) { } canonblocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, rawdb.NewMemoryDatabase(), tt.canonicalBlocks, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{0x02}) - b.SetDifficulty(big.NewInt(1000000)) + // b.SetDifficulty(big.NewInt(1000000)) }) if _, err := chain.InsertChain(canonblocks[:tt.commitBlock]); err != nil { t.Fatalf("Failed to import canonical chain start: %v", err) } if tt.commitBlock > 0 { - chain.stateCache.TrieDB().Commit(canonblocks[tt.commitBlock-1].Root(), true, nil) + chain.stateCache.TrieDB().Commit(canonblocks[tt.commitBlock-1].Root(), true) } if _, err := chain.InsertChain(canonblocks[tt.commitBlock:]); err != nil { t.Fatalf("Failed to import canonical chain tail: %v", err) @@ -1617,14 +1620,13 @@ func testRepair(t *testing.T, tt *rewindTest) { // Pull the plug on the database, simulating a hard crash db.Close() - // Start a new blockchain back up and see where the repait leads us + // Start a new blockchain back up and see where the repair leads us db, err = rawdb.NewLevelDBDatabaseWithFreezer(datadir, 0, 0, datadir, "") if err != nil { t.Fatalf("Failed to reopen persistent database: %v", err) } defer db.Close() - - chain, err = NewBlockChain(db, nil, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil) + chain, err = NewBlockChain(db, nil, params.IstanbulTestChainConfig, engine, vm.Config{}, nil) if err != nil { t.Fatalf("Failed to recreate chain: %v", err) } diff --git a/core/blockchain_sethead_test.go b/core/blockchain_sethead_test.go index dc1368ff4b..08a58dc73a 100644 --- a/core/blockchain_sethead_test.go +++ b/core/blockchain_sethead_test.go @@ -22,13 +22,12 @@ package core import ( "fmt" "io/ioutil" - "math/big" "os" "strings" "testing" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/consensus/ethash" + mockEngine "github.com/ethereum/go-ethereum/consensus/consensustest" "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" @@ -530,144 +529,6 @@ func TestShortNewlyForkedFastSyncingSetHead(t *testing.T) { }) } -// Tests a sethead for a short canonical chain and a longer side chain, where a -// recent block was already committed to disk and then sethead was called. In this -// case we expect the canonical full chain to be rolled back to the committed block. -// All data above the sethead point should be deleted. In between the committed -// block and the requested head the data can remain as "fast sync" data to avoid -// having to redownload it. The side chain should be truncated to the head set. -// -// The side chain could be left to be if the fork point was before the new head -// we are deleting to, but it would be exceedingly hard to detect that case and -// properly handle it, so we'll trade extra work in exchange for simpler code. -func TestShortReorgedSetHead(t *testing.T) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) - // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 - // - // Frozen: none - // Commit: G, C4 - // Pivot : none - // - // SetHead(7) - // - // ------------------------------ - // - // Expected in leveldb: - // G->C1->C2->C3->C4->C5->C6->C7 - // └->S1->S2->S3->S4->S5->S6->S7 - // - // Expected head header : C7 - // Expected head fast block: C7 - // Expected head block : C4 - testSetHead(t, &rewindTest{ - canonicalBlocks: 8, - sidechainBlocks: 10, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: nil, - setheadBlock: 7, - expCanonicalBlocks: 7, - expSidechainBlocks: 7, - expFrozen: 0, - expHeadHeader: 7, - expHeadFastBlock: 7, - expHeadBlock: 4, - }) -} - -// Tests a sethead for a short canonical chain and a longer side chain, where -// the fast sync pivot point was already committed to disk and then sethead was -// called. In this case we expect the canonical full chain to be rolled back to -// the committed block. All data above the sethead point should be deleted. In -// between the committed block and the requested head the data can remain as -// "fast sync" data to avoid having to redownload it. The side chain should be -// truncated to the head set. -// -// The side chain could be left to be if the fork point was before the new head -// we are deleting to, but it would be exceedingly hard to detect that case and -// properly handle it, so we'll trade extra work in exchange for simpler code. -func TestShortReorgedFastSyncedSetHead(t *testing.T) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) - // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 - // - // Frozen: none - // Commit: G, C4 - // Pivot : C4 - // - // SetHead(7) - // - // ------------------------------ - // - // Expected in leveldb: - // G->C1->C2->C3->C4->C5->C6->C7 - // └->S1->S2->S3->S4->S5->S6->S7 - // - // Expected head header : C7 - // Expected head fast block: C7 - // Expected head block : C4 - testSetHead(t, &rewindTest{ - canonicalBlocks: 8, - sidechainBlocks: 10, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: uint64ptr(4), - setheadBlock: 7, - expCanonicalBlocks: 7, - expSidechainBlocks: 7, - expFrozen: 0, - expHeadHeader: 7, - expHeadFastBlock: 7, - expHeadBlock: 4, - }) -} - -// Tests a sethead for a short canonical chain and a longer side chain, where -// the fast sync pivot point was not yet committed, but sethead was called. In -// this case we expect the chain to detect that it was fast syncing and delete -// everything from the new head, since we can just pick up fast syncing from -// there. -// -// The side chain could be left to be if the fork point was before the new head -// we are deleting to, but it would be exceedingly hard to detect that case and -// properly handle it, so we'll trade extra work in exchange for simpler code. -func TestShortReorgedFastSyncingSetHead(t *testing.T) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) - // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 - // - // Frozen: none - // Commit: G - // Pivot : C4 - // - // SetHead(7) - // - // ------------------------------ - // - // Expected in leveldb: - // G->C1->C2->C3->C4->C5->C6->C7 - // └->S1->S2->S3->S4->S5->S6->S7 - // - // Expected head header : C7 - // Expected head fast block: C7 - // Expected head block : G - testSetHead(t, &rewindTest{ - canonicalBlocks: 8, - sidechainBlocks: 10, - freezeThreshold: 16, - commitBlock: 0, - pivotBlock: uint64ptr(4), - setheadBlock: 7, - expCanonicalBlocks: 7, - expSidechainBlocks: 7, - expFrozen: 0, - expHeadHeader: 7, - expHeadFastBlock: 7, - expHeadBlock: 0, - }) -} - // Tests a sethead for a long canonical chain with frozen blocks where a recent // block - newer than the ancient limit - was already committed to disk and then // sethead was called. In this case we expect the full chain to be rolled back @@ -1477,6 +1338,145 @@ func TestLongNewerForkedFastSyncingDeepSetHead(t *testing.T) { }) } +/* +// Tests a sethead for a short canonical chain and a longer side chain, where a +// recent block was already committed to disk and then sethead was called. In this +// case we expect the canonical full chain to be rolled back to the committed block. +// All data above the sethead point should be deleted. In between the committed +// block and the requested head the data can remain as "fast sync" data to avoid +// having to redownload it. The side chain should be truncated to the head set. +// +// The side chain could be left to be if the fork point was before the new head +// we are deleting to, but it would be exceedingly hard to detect that case and +// properly handle it, so we'll trade extra work in exchange for simpler code. +func TestShortReorgedSetHead(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) + // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 + // + // Frozen: none + // Commit: G, C4 + // Pivot : none + // + // SetHead(7) + // + // ------------------------------ + // + // Expected in leveldb: + // G->C1->C2->C3->C4->C5->C6->C7 + // └->S1->S2->S3->S4->S5->S6->S7 + // + // Expected head header : C7 + // Expected head fast block: C7 + // Expected head block : C4 + testSetHead(t, &rewindTest{ + canonicalBlocks: 8, + sidechainBlocks: 10, + freezeThreshold: 16, + commitBlock: 4, + pivotBlock: nil, + setheadBlock: 7, + expCanonicalBlocks: 7, + expSidechainBlocks: 7, + expFrozen: 0, + expHeadHeader: 7, + expHeadFastBlock: 7, + expHeadBlock: 4, + }) +} + +// Tests a sethead for a short canonical chain and a longer side chain, where +// the fast sync pivot point was already committed to disk and then sethead was +// called. In this case we expect the canonical full chain to be rolled back to +// the committed block. All data above the sethead point should be deleted. In +// between the committed block and the requested head the data can remain as +// "fast sync" data to avoid having to redownload it. The side chain should be +// truncated to the head set. +// +// The side chain could be left to be if the fork point was before the new head +// we are deleting to, but it would be exceedingly hard to detect that case and +// properly handle it, so we'll trade extra work in exchange for simpler code. +func TestShortReorgedFastSyncedSetHead(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) + // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 + // + // Frozen: none + // Commit: G, C4 + // Pivot : C4 + // + // SetHead(7) + // + // ------------------------------ + // + // Expected in leveldb: + // G->C1->C2->C3->C4->C5->C6->C7 + // └->S1->S2->S3->S4->S5->S6->S7 + // + // Expected head header : C7 + // Expected head fast block: C7 + // Expected head block : C4 + testSetHead(t, &rewindTest{ + canonicalBlocks: 8, + sidechainBlocks: 10, + freezeThreshold: 16, + commitBlock: 4, + pivotBlock: uint64ptr(4), + setheadBlock: 7, + expCanonicalBlocks: 7, + expSidechainBlocks: 7, + expFrozen: 0, + expHeadHeader: 7, + expHeadFastBlock: 7, + expHeadBlock: 4, + }) +} + +// Tests a sethead for a short canonical chain and a longer side chain, where +// the fast sync pivot point was not yet committed, but sethead was called. In +// this case we expect the chain to detect that it was fast syncing and delete +// everything from the new head, since we can just pick up fast syncing from +// there. +// +// The side chain could be left to be if the fork point was before the new head +// we are deleting to, but it would be exceedingly hard to detect that case and +// properly handle it, so we'll trade extra work in exchange for simpler code. +func TestShortReorgedFastSyncingSetHead(t *testing.T) { + // Chain: + // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) + // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 + // + // Frozen: none + // Commit: G + // Pivot : C4 + // + // SetHead(7) + // + // ------------------------------ + // + // Expected in leveldb: + // G->C1->C2->C3->C4->C5->C6->C7 + // └->S1->S2->S3->S4->S5->S6->S7 + // + // Expected head header : C7 + // Expected head fast block: C7 + // Expected head block : G + testSetHead(t, &rewindTest{ + canonicalBlocks: 8, + sidechainBlocks: 10, + freezeThreshold: 16, + commitBlock: 0, + pivotBlock: uint64ptr(4), + setheadBlock: 7, + expCanonicalBlocks: 7, + expSidechainBlocks: 7, + expFrozen: 0, + expHeadHeader: 7, + expHeadFastBlock: 7, + expHeadBlock: 0, + }) +} + // Tests a sethead for a long canonical chain with frozen blocks and a longer side // chain, where a recent block - newer than the ancient limit - was already committed // to disk and then sethead was called. In this case the freezer will delete the @@ -1743,6 +1743,7 @@ func TestLongReorgedFastSyncingDeepSetHead(t *testing.T) { expHeadBlock: 0, }) } +*/ func testSetHead(t *testing.T, tt *rewindTest) { // It's hard to follow the test case, visualize the input @@ -1765,9 +1766,9 @@ func testSetHead(t *testing.T, tt *rewindTest) { // Initialize a fresh chain var ( genesis = new(Genesis).MustCommit(db) - engine = ethash.NewFullFaker() + engine = mockEngine.NewFaker() ) - chain, err := NewBlockChain(db, nil, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil) + chain, err := NewBlockChain(db, nil, params.IstanbulTestChainConfig, engine, vm.Config{}, nil) if err != nil { t.Fatalf("Failed to create chain: %v", err) } @@ -1783,13 +1784,13 @@ func testSetHead(t *testing.T, tt *rewindTest) { } canonblocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, rawdb.NewMemoryDatabase(), tt.canonicalBlocks, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{0x02}) - b.SetDifficulty(big.NewInt(1000000)) + // b.SetDifficulty(big.NewInt(1000000)) }) if _, err := chain.InsertChain(canonblocks[:tt.commitBlock]); err != nil { t.Fatalf("Failed to import canonical chain start: %v", err) } if tt.commitBlock > 0 { - chain.stateCache.TrieDB().Commit(canonblocks[tt.commitBlock-1].Root(), true, nil) + chain.stateCache.TrieDB().Commit(canonblocks[tt.commitBlock-1].Root(), true) } if _, err := chain.InsertChain(canonblocks[tt.commitBlock:]); err != nil { t.Fatalf("Failed to import canonical chain tail: %v", err) @@ -1845,6 +1846,7 @@ func verifyNoGaps(t *testing.T, chain *BlockChain, canonical bool, inserted type var end uint64 for i := uint64(0); i <= uint64(len(inserted)); i++ { header := chain.GetHeaderByNumber(i) + // fmt.Printf("header %v\n", header); if header == nil && end == 0 { end = i } @@ -1860,6 +1862,7 @@ func verifyNoGaps(t *testing.T, chain *BlockChain, canonical bool, inserted type end = 0 for i := uint64(0); i <= uint64(len(inserted)); i++ { block := chain.GetBlockByNumber(i) + // fmt.Printf("block %v\n", block); if block == nil && end == 0 { end = i } @@ -1875,6 +1878,7 @@ func verifyNoGaps(t *testing.T, chain *BlockChain, canonical bool, inserted type end = 0 for i := uint64(1); i <= uint64(len(inserted)); i++ { receipts := chain.GetReceiptsByHash(inserted[i-1].Hash()) + // fmt.Printf("receipt %v\n", receipts); if receipts == nil && end == 0 { end = i } diff --git a/core/blockchain_test.go b/core/blockchain_test.go index 3b9ae856f2..8f561fdc8c 100644 --- a/core/blockchain_test.go +++ b/core/blockchain_test.go @@ -834,7 +834,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) { archiveCaching := *defaultCacheConfig archiveCaching.TrieDirtyDisabled = true - archive, _ := NewBlockChain(archiveDb, &archiveCaching, gspec.Config, mockEngine.NewFaker(), vm.Config{}, nil, nil) + archive, _ := NewBlockChain(archiveDb, &archiveCaching, gspec.Config, mockEngine.NewFaker(), vm.Config{}, nil) if n, err := archive.InsertChain(blocks); err != nil { t.Fatalf("failed to process block %d: %v", n, err) } diff --git a/core/rawdb/freezer.go b/core/rawdb/freezer.go index 2d3953bd80..52e5b1b53d 100644 --- a/core/rawdb/freezer.go +++ b/core/rawdb/freezer.go @@ -294,7 +294,7 @@ func (f *freezer) freeze(db ethdb.KeyValueStore) { hash := ReadHeadBlockHash(nfdb) if hash == (common.Hash{}) { log.Debug("Current full block hash unavailable") // new chain, empty database - time.Sleep(freezerRecheckInterval) + backoff = true continue } number := ReadHeaderNumber(nfdb, hash) @@ -303,7 +303,7 @@ func (f *freezer) freeze(db ethdb.KeyValueStore) { switch { case number == nil: log.Error("Current full block number unavailable", "hash", hash) - time.Sleep(freezerRecheckInterval) + backoff = true continue case *number < threshold: @@ -313,13 +313,13 @@ func (f *freezer) freeze(db ethdb.KeyValueStore) { case *number-threshold <= f.frozen: log.Debug("Ancient blocks frozen already", "number", *number, "hash", hash, "frozen", f.frozen) - time.Sleep(freezerRecheckInterval) + backoff = true continue } head := ReadHeader(nfdb, hash, *number) if head == nil { log.Error("Current full block unavailable", "number", *number, "hash", hash) - time.Sleep(freezerRecheckInterval) + backoff = true continue } // Seems we have data ready to be frozen, process in usable batches @@ -445,7 +445,7 @@ func (f *freezer) freeze(db ethdb.KeyValueStore) { // Avoid database thrashing with tiny writes if f.frozen-first < freezerBatchLimit { - time.Sleep(freezerRecheckInterval) + backoff = true } } } diff --git a/p2p/discv5/node_test.go b/p2p/discv5/node_test.go index 439c5a64f1..2b0b4a8d3c 100644 --- a/p2p/discv5/node_test.go +++ b/p2p/discv5/node_test.go @@ -142,7 +142,7 @@ var parseNodeTests = []struct { { // This test checks that errors from url.Parse are handled. rawurl: "://foo", - wantError: `parse ://foo: missing protocol scheme`, + wantError: `parse "://foo": missing protocol scheme`, }, } From 4189d8083261bf8d7a91624a71fc06ce3a8f38ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sami=20M=C3=A4kel=C3=A4?= Date: Wed, 16 Sep 2020 17:47:03 +0300 Subject: [PATCH 04/15] sethead for light sync works --- consensus/istanbul/backend/engine.go | 27 +++++++++++++++++++++++++-- core/genesis.go | 2 ++ core/headerchain.go | 9 ++++++++- eth/sync.go | 4 +++- les/client.go | 14 +++++++++----- light/txpool.go | 10 +++++++++- 6 files changed, 56 insertions(+), 10 deletions(-) diff --git a/consensus/istanbul/backend/engine.go b/consensus/istanbul/backend/engine.go index cad9faf406..72f9b0b2a2 100644 --- a/consensus/istanbul/backend/engine.go +++ b/consensus/istanbul/backend/engine.go @@ -134,6 +134,26 @@ func (sb *Backend) verifyHeader(chain consensus.ChainReader, header *types.Heade return sb.verifyCascadingFields(chain, header, parents) } +func (sb *Backend) sanityCheck(chain consensus.ChainReader, header *types.Header, parents []*types.Header) error { + number := header.Number.Uint64() + // Check that latest epoch block is available + epoch := istanbul.GetEpochNumber(number, sb.config.Epoch) + first := istanbul.GetEpochLastBlockNumber(epoch-1, sb.config.Epoch) + if number == first { + first = istanbul.GetEpochLastBlockNumber(epoch-2, sb.config.Epoch) + } + for _, hdr := range(parents) { + if hdr.Number.Uint64() == first { + return nil + } + } + parent := chain.GetHeaderByNumber(first) + if parent == nil || parent.Number.Uint64() != first { + return consensus.ErrUnknownAncestor + } + return nil +} + // verifyCascadingFields verifies all the header fields that are not standalone, // rather depend on a batch of previous headers. The caller may optionally pass // in a batch of parents (ascending order) to avoid looking those up from the @@ -151,7 +171,7 @@ func (sb *Backend) verifyCascadingFields(chain consensus.ChainReader, header *ty } else { parent = chain.GetHeader(header.ParentHash, number-1) } - if chain.Config().FullHeaderChainAvailable { + if chain.Config().FullHeaderChainAvailable /* || !istanbul.IsLastBlockOfEpoch(number, sb.config.Epoch) */ { if parent == nil || parent.Number.Uint64() != number-1 || parent.Hash() != header.ParentHash { return consensus.ErrUnknownAncestor @@ -163,6 +183,8 @@ func (sb *Backend) verifyCascadingFields(chain consensus.ChainReader, header *ty if err := sb.verifySigner(chain, header, parents); err != nil { return err } + } else if err:= sb.sanityCheck(chain, header, parents); err != nil { + return err } return sb.verifyAggregatedSeals(chain, header, parents) @@ -762,8 +784,9 @@ func (sb *Backend) snapshot(chain consensus.ChainReader, number uint64, hash com if (blockHash != common.Hash{}) { if s, err := loadSnapshot(sb.config.Epoch, sb.db, blockHash); err == nil { - log.Trace("Loaded validator set snapshot from disk", "number", numberIter, "hash", blockHash) + log.Info("Loaded validator set snapshot from disk", "number", numberIter, "hash", blockHash) snap = s + sb.recentSnapshots.Add(numberIter, snap) break } } diff --git a/core/genesis.go b/core/genesis.go index 8723e0b06a..009cd511d0 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -217,6 +217,8 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, genesis *Genesis, override return storedcfg, stored, nil } + log.Info("reading head hash", "hash", rawdb.ReadHeadHeaderHash(db).String()) + // Check config compatibility and write the config. Compatibility errors // are returned to the caller unless we're already at block zero. height := rawdb.ReadHeaderNumber(db, rawdb.ReadHeadHeaderHash(db)) diff --git a/core/headerchain.go b/core/headerchain.go index 70a6e0f29f..bd4ee1f700 100644 --- a/core/headerchain.go +++ b/core/headerchain.go @@ -528,8 +528,14 @@ func (hc *HeaderChain) SetHead(head uint64, updateFn UpdateHeadBlocksCallback, d num := hdr.Number.Uint64() // Rewind block chain to new head. + var nums []uint64 parent := hc.GetHeader(hdr.ParentHash, num-1) if parent == nil { + if !hc.config.FullHeaderChainAvailable { + for i := hc.config.Istanbul.Epoch; i < num; i += hc.config.Istanbul.Epoch { + nums = append(nums, i) + } + } parent = hc.genesisHeader } parentHash = hdr.ParentHash @@ -560,7 +566,6 @@ func (hc *HeaderChain) SetHead(head uint64, updateFn UpdateHeadBlocksCallback, d // If this is the first iteration, wipe any leftover data upwards too so // we don't end up with dangling daps in the database - var nums []uint64 if origin { for n := num + 1; len(rawdb.ReadAllHashes(hc.chainDb, n)) > 0; n++ { nums = append([]uint64{n}, nums...) // suboptimal, but we don't really expect this path @@ -569,6 +574,8 @@ func (hc *HeaderChain) SetHead(head uint64, updateFn UpdateHeadBlocksCallback, d } nums = append(nums, num) + log.Info("removing", "nums", nums) + // Remove the related data from the database on all sidechains for _, num := range nums { // Gather all the side fork hashes diff --git a/eth/sync.go b/eth/sync.go index fe6d227bc9..2bb14b29fd 100644 --- a/eth/sync.go +++ b/eth/sync.go @@ -191,7 +191,9 @@ func (pm *ProtocolManager) synchronise(peer *peer) { if mode == downloader.FastSync { // Make sure the peer's total difficulty we are synchronizing is higher. - if pm.blockchain.GetTdByHash(pm.blockchain.CurrentFastBlock().Hash()).Cmp(pTd) >= 0 { + currentBlock := pm.blockchain.CurrentFastBlock().Hash() + td := pm.blockchain.GetTdByHash(currentBlock) + if td.Cmp(pTd) >= 0 { return } } diff --git a/les/client.go b/les/client.go index 9c605fdaa3..067dfdc8c7 100644 --- a/les/client.go +++ b/les/client.go @@ -114,7 +114,6 @@ func New(ctx *node.ServiceContext, config *eth.Config) (*LightEthereum, error) { engine: eth.CreateConsensusEngine(ctx, chainConfig, config, nil, false, chainDb), networkId: config.NetworkId, bloomRequests: make(chan chan *bloombits.Retrieval), - bloomIndexer: eth.NewBloomIndexer(chainDb, params.BloomBitsBlocksClient, params.HelperTrieConfirmations, fullChainAvailable), serverPool: newServerPool(chainDb, config.UltraLightServers), } @@ -129,9 +128,10 @@ func New(ctx *node.ServiceContext, config *eth.Config) (*LightEthereum, error) { leth.odr = NewLesOdr(chainDb, light.DefaultClientIndexerConfig, leth.retriever) // If the full chain is not available then indexing each block header isn't possible. if fullChainAvailable { + leth.bloomIndexer = eth.NewBloomIndexer(chainDb, params.BloomBitsBlocksClient, params.HelperTrieConfirmations, fullChainAvailable) leth.chtIndexer = light.NewChtIndexer(chainDb, leth.odr, params.CHTFrequency, params.HelperTrieConfirmations, fullChainAvailable) + leth.bloomTrieIndexer = light.NewBloomTrieIndexer(chainDb, leth.odr, params.BloomBitsBlocksClient, params.BloomTrieFrequency, fullChainAvailable) } - leth.bloomTrieIndexer = light.NewBloomTrieIndexer(chainDb, leth.odr, params.BloomBitsBlocksClient, params.BloomTrieFrequency, fullChainAvailable) leth.odr.SetIndexers(leth.chtIndexer, leth.bloomTrieIndexer, leth.bloomIndexer) checkpoint := config.Checkpoint @@ -159,11 +159,13 @@ func New(ctx *node.ServiceContext, config *eth.Config) (*LightEthereum, error) { leth.oracle = checkpointoracle.New(oracle, leth.localCheckpoint) // Note: AddChildIndexer starts the update process for the child - leth.bloomIndexer.AddChildIndexer(leth.bloomTrieIndexer) + if leth.bloomIndexer != nil && leth.bloomTrieIndexer != nil { + leth.bloomIndexer.AddChildIndexer(leth.bloomTrieIndexer) + leth.bloomIndexer.Start(leth.blockchain) + } if leth.chtIndexer != nil { leth.chtIndexer.Start(leth.blockchain) } - leth.bloomIndexer.Start(leth.blockchain) // TODO mcortesi (needs etherbase & gatewayFee?) leth.handler = newClientHandler(syncMode, config.UltraLightServers, config.UltraLightFraction, checkpoint, leth, config.GatewayFee) @@ -306,7 +308,9 @@ func (s *LightEthereum) Stop() error { s.reqDist.close() s.odr.Stop() s.relay.Stop() - s.bloomIndexer.Close() + if s.bloomIndexer != nil { + s.bloomIndexer.Close() + } if s.chtIndexer != nil { s.chtIndexer.Close() } diff --git a/light/txpool.go b/light/txpool.go index bbed500cf7..52dbfe291f 100644 --- a/light/txpool.go +++ b/light/txpool.go @@ -18,6 +18,7 @@ package light import ( "context" + "errors" "fmt" "math/big" "sync" @@ -225,6 +226,10 @@ func (pool *TxPool) rollbackTxs(hash common.Hash, txc txStateChanges) { func (pool *TxPool) reorgOnNewHead(ctx context.Context, newHeader *types.Header) (txStateChanges, error) { txc := make(txStateChanges) oldh := pool.chain.GetHeaderByHash(pool.head) + if oldh == nil { + pool.head = newHeader.Hash() + return nil, errors.New("Old header lost") + } newh := newHeader // find common ancestor, create list of rolled back and new block hashes var oldHashes, newHashes []common.Hash @@ -310,7 +315,10 @@ func (pool *TxPool) setNewHead(head *types.Header) { ctx, cancel := context.WithTimeout(context.Background(), blockCheckTimeout) defer cancel() - txc, _ := pool.reorgOnNewHead(ctx, head) + txc, err := pool.reorgOnNewHead(ctx, head) + if err != nil { + log.Warn("Cannot reorg", "err", err) + } m, r := txc.getLists() pool.relay.NewHead(pool.head, m, r) From 2fff15928bc644843931b2cd1f66615ad22f115a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sami=20M=C3=A4kel=C3=A4?= Date: Thu, 17 Sep 2020 14:14:10 +0300 Subject: [PATCH 05/15] still some errors left --- consensus/istanbul/backend/engine.go | 7 +++++-- core/block_validator.go | 2 ++ core/blockchain.go | 16 +++++++++++++--- core/headerchain.go | 6 +++++- eth/downloader/downloader.go | 23 +++++++++++++---------- light/lightchain.go | 2 +- 6 files changed, 39 insertions(+), 17 deletions(-) diff --git a/consensus/istanbul/backend/engine.go b/consensus/istanbul/backend/engine.go index 72f9b0b2a2..2d45b37f4a 100644 --- a/consensus/istanbul/backend/engine.go +++ b/consensus/istanbul/backend/engine.go @@ -142,13 +142,14 @@ func (sb *Backend) sanityCheck(chain consensus.ChainReader, header *types.Header if number == first { first = istanbul.GetEpochLastBlockNumber(epoch-2, sb.config.Epoch) } - for _, hdr := range(parents) { + for _, hdr := range parents { if hdr.Number.Uint64() == first { return nil } } parent := chain.GetHeaderByNumber(first) if parent == nil || parent.Number.Uint64() != first { + log.Info("insane???") return consensus.ErrUnknownAncestor } return nil @@ -174,6 +175,7 @@ func (sb *Backend) verifyCascadingFields(chain consensus.ChainReader, header *ty if chain.Config().FullHeaderChainAvailable /* || !istanbul.IsLastBlockOfEpoch(number, sb.config.Epoch) */ { if parent == nil || parent.Number.Uint64() != number-1 || parent.Hash() != header.ParentHash { + log.Info("verify: didnt find parent") return consensus.ErrUnknownAncestor } if parent.Time+sb.config.BlockPeriod > header.Time { @@ -183,7 +185,7 @@ func (sb *Backend) verifyCascadingFields(chain consensus.ChainReader, header *ty if err := sb.verifySigner(chain, header, parents); err != nil { return err } - } else if err:= sb.sanityCheck(chain, header, parents); err != nil { + } else if err := sb.sanityCheck(chain, header, parents); err != nil { return err } @@ -208,6 +210,7 @@ func (sb *Backend) VerifyHeaders(chain consensus.ChainReader, headers []*types.H } if err != nil { + log.Info("got error", "err", err) errored = true } diff --git a/core/block_validator.go b/core/block_validator.go index 06c89718ff..a299bf121d 100644 --- a/core/block_validator.go +++ b/core/block_validator.go @@ -23,6 +23,7 @@ import ( "github.com/ethereum/go-ethereum/contract_comm/blockchain_parameters" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" ) @@ -60,6 +61,7 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error { } if !v.bc.HasBlockAndState(block.ParentHash(), block.NumberU64()-1) { if !v.bc.HasBlock(block.ParentHash(), block.NumberU64()-1) { + log.Info("validatebody unknown ancestor") return consensus.ErrUnknownAncestor } return consensus.ErrPrunedAncestor diff --git a/core/blockchain.go b/core/blockchain.go index 9e7d6e6fa4..270956a2b7 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -407,11 +407,13 @@ func (bc *BlockChain) SetHead(head uint64) error { // current freezer limit to start nuking id underflown pivot := rawdb.ReadLastPivotNumber(bc.db) frozen, _ := bc.db.Ancients() + log.Info("Pivot", "pivot", pivot) updateFn := func(db ethdb.KeyValueWriter, header *types.Header) (uint64, bool) { // Rewind the block chain, ensuring we don't end up with a stateless head // block. Note, depth equality is permitted to allow using SetHead as a // chain reparation mechanism without deleting any data! + log.Info("updatefn", "frozen", frozen, "header", header.Number) if currentBlock := bc.CurrentBlock(); currentBlock != nil && header.Number.Uint64() <= currentBlock.NumberU64() { newHeadBlock := bc.GetBlock(header.Hash(), header.Number.Uint64()) if newHeadBlock == nil { @@ -421,7 +423,7 @@ func (bc *BlockChain) SetHead(head uint64) error { // Block exists, keep rewinding until we find one with state for { if _, err := state.New(newHeadBlock.Root(), bc.stateCache); err != nil { - log.Trace("Block state missing, rewinding further", "number", newHeadBlock.NumberU64(), "hash", newHeadBlock.Hash()) + log.Info("Block state missing, rewinding further", "number", newHeadBlock.NumberU64(), "hash", newHeadBlock.Hash()) if pivot == nil || newHeadBlock.NumberU64() > *pivot { newHeadBlock = bc.GetBlock(newHeadBlock.ParentHash(), newHeadBlock.NumberU64()-1) continue @@ -430,7 +432,7 @@ func (bc *BlockChain) SetHead(head uint64) error { newHeadBlock = bc.genesisBlock } } - log.Debug("Rewound to block with state", "number", newHeadBlock.NumberU64(), "hash", newHeadBlock.Hash()) + log.Info("Rewound to block with state", "number", newHeadBlock.NumberU64(), "hash", newHeadBlock.Hash()) break } } @@ -458,9 +460,12 @@ func (bc *BlockChain) SetHead(head uint64) error { // to low, so it's safe the update in-memory markers directly. bc.currentFastBlock.Store(newHeadFastBlock) headFastBlockGauge.Update(int64(newHeadFastBlock.NumberU64())) + log.Info("Rewound fast block", "number", newHeadFastBlock.NumberU64()) } head := bc.CurrentBlock().NumberU64() + log.Info("updatefn2", "frozen", frozen, "head", head) + // If setHead underflown the freezer threshold and the block processing // intent afterwards is full block importing, delete the chain segment // between the stateful-block and the sethead target. @@ -1359,6 +1364,7 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types. // Calculate the total difficulty of the block ptd := bc.GetTd(block.ParentHash(), block.NumberU64()-1) if ptd == nil { + log.Info("getting total difficulty") return NonStatTy, consensus.ErrUnknownAncestor } // Make sure no inconsistent state is leaked during insertion @@ -2186,6 +2192,8 @@ func (bc *BlockChain) InsertHeaderChain(chain []*types.Header, checkFreq int, co return i, err } + log.Info("Inserting validated headers", "freq", checkFreq, "num", len(chain)) + // Make sure only one thread manipulates the chain at once bc.chainmu.Lock() defer bc.chainmu.Unlock() @@ -2197,7 +2205,9 @@ func (bc *BlockChain) InsertHeaderChain(chain []*types.Header, checkFreq int, co _, err := bc.hc.WriteHeader(header) return err } - return bc.hc.InsertHeaderChain(chain, whFunc, start) + res, err := bc.hc.InsertHeaderChain(chain, whFunc, start) + log.Info("Inserted") + return res, err } // CurrentHeader retrieves the current head header of the canonical chain. The diff --git a/core/headerchain.go b/core/headerchain.go index bd4ee1f700..05b46df840 100644 --- a/core/headerchain.go +++ b/core/headerchain.go @@ -152,9 +152,11 @@ func (hc *HeaderChain) WriteHeader(header *types.Header) (status WriteStatus, er // Calculate the total difficulty of the header. // ptd seems to be abbreviation of "parent total difficulty". // In IBFT, the announced td (total difficulty) is 1 + block number. + log.Info("Write header", "num", number) ptd := hc.GetTd(header.ParentHash, number-1) if ptd == nil { if hc.config.FullHeaderChainAvailable { + log.Info("td header") return NonStatTy, consensus.ErrUnknownAncestor } else { localTd = big.NewInt(hc.CurrentHeader().Number.Int64() + 1) @@ -322,7 +324,9 @@ func (hc *HeaderChain) InsertHeaderChain(chain []*types.Header, writeHeader WhCa if hc.HasHeader(hash, header.Number.Uint64()) { externTd := hc.GetTd(hash, header.Number.Uint64()) localTd := hc.GetTd(hc.currentHeaderHash, hc.CurrentHeader().Number.Uint64()) - if externTd == nil || externTd.Cmp(localTd) <= 0 { + log.Info("Had header", "num", header.Number.Uint64(), "td", externTd, "numbered", hc.numberCache.Contains(hash), "cached", hc.headerCache.Contains(hash)) + // if it has no difficulty, it wasn't stored properly + if externTd != nil && externTd.Cmp(localTd) <= 0 { stats.ignored++ continue } diff --git a/eth/downloader/downloader.go b/eth/downloader/downloader.go index 7f23282311..442c0513a8 100644 --- a/eth/downloader/downloader.go +++ b/eth/downloader/downloader.go @@ -49,19 +49,20 @@ var ( MaxReceiptFetch = 256 // Amount of transaction receipts to allow fetching per request MaxStateFetch = 384 // Amount of node state values to allow fetching per request - rttMinEstimate = 2 * time.Second // Minimum round-trip time to target for download requests - rttMaxEstimate = 20 * time.Second // Maximum round-trip time to target for download requests - rttMinConfidence = 0.1 // Worse confidence factor in our estimated RTT value - ttlScaling = 3 // Constant scaling factor for RTT -> TTL conversion - ttlLimit = time.Minute // Maximum TTL allowance to prevent reaching crazy timeouts + rttMinEstimate = 2 * time.Second // Minimum round-trip time to target for download requests + rttMaxEstimate = 20 * time.Second // Maximum round-trip time to target for download requests + rttDefaultEstimate = 5 * time.Second // Maximum round-trip time to target for download requests + rttMinConfidence = 0.1 // Worse confidence factor in our estimated RTT value + ttlScaling = 3 // Constant scaling factor for RTT -> TTL conversion + ttlLimit = time.Minute // Maximum TTL allowance to prevent reaching crazy timeouts qosTuningPeers = 5 // Number of peers to tune based on (best peers) qosConfidenceCap = 10 // Number of peers above which not to modify RTT confidence qosTuningImpact = 0.25 // Impact that a new tuning target has on the previous value - maxQueuedHeaders = 32 * 1024 // [eth/62] Maximum number of headers to queue for import (DOS protection) - maxHeadersProcess = 2048 // Number of header download results to import at once into the chain - maxResultsProcess = 2048 // Number of content download results to import at once into the chain + maxQueuedHeaders = 32 * 1024 // [eth/62] Maximum number of headers to queue for import (DOS protection) + maxHeadersProcess = 2048 // Number of header download results to import at once into the chain + maxResultsProcess = 2048 // Number of content download results to import at once into the chain maxForkAncestry uint64 = params.FullImmutabilityThreshold // Maximum chain reorganisation (locally redeclared so tests can reduce it) reorgProtThreshold = 48 // Threshold number of recent blocks to disable mini reorg protection @@ -247,7 +248,7 @@ func New(checkpoint uint64, stateDb ethdb.Database, stateBloom *trie.SyncBloom, checkpoint: checkpoint, queue: newQueue(), peers: newPeerSet(), - rttEstimate: uint64(rttMaxEstimate), + rttEstimate: uint64(rttDefaultEstimate), rttConfidence: uint64(1000000), blockchain: chain, lightchain: lightchain, @@ -485,10 +486,10 @@ func (d *Downloader) syncWithPeer(p *peerConnection, hash common.Hash, td *big.I pivot := uint64(0) if d.Mode == FastSync { pivot = d.calcPivot(height) + rawdb.WriteLastPivotNumber(d.stateDB, pivot) if pivot == 0 { origin = 0 } else if pivot <= origin { - rawdb.WriteLastPivotNumber(d.stateDB, pivot) origin = pivot - 1 } } @@ -528,6 +529,7 @@ func (d *Downloader) syncWithPeer(p *peerConnection, hash common.Hash, td *big.I } // Rewind the ancient store and blockchain if reorg happens. if origin+1 < frozen { + log.Info("Setting head", "target", origin+1) if err := d.lightchain.SetHead(origin + 1); err != nil { return err } @@ -1491,6 +1493,7 @@ func (d *Downloader) processHeaders(origin uint64, pivot uint64, td *big.Int) er lastFastBlock = d.blockchain.CurrentFastBlock().Number() lastBlock = d.blockchain.CurrentBlock().Number() } + log.Info("Setting head (rollback)", "target", rollback-1) if err := d.lightchain.SetHead(rollback - 1); err != nil { // -1 to target the parent of the first uncertain block // We're already unwinding the stack, only print the error to make it more visible log.Error("Failed to roll back chain segment", "head", rollback-1, "err", err) diff --git a/light/lightchain.go b/light/lightchain.go index 4bc311351b..aea154cbfc 100644 --- a/light/lightchain.go +++ b/light/lightchain.go @@ -174,7 +174,7 @@ func (lc *LightChain) loadLastState() error { func (lc *LightChain) SetHead(head uint64) error { lc.chainmu.Lock() defer lc.chainmu.Unlock() - + log.Info("Light set head", head) lc.hc.SetHead(head, nil, nil) return lc.loadLastState() } From 0550ea10651fe97b8e37f216ba36ca497feadbed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sami=20M=C3=A4kel=C3=A4?= Date: Thu, 17 Sep 2020 21:38:08 +0300 Subject: [PATCH 06/15] debugging --- core/blockchain.go | 4 ++-- core/headerchain.go | 2 +- eth/downloader/downloader.go | 19 +++++++++++++------ 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/core/blockchain.go b/core/blockchain.go index 270956a2b7..414977cbb3 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -413,7 +413,7 @@ func (bc *BlockChain) SetHead(head uint64) error { // Rewind the block chain, ensuring we don't end up with a stateless head // block. Note, depth equality is permitted to allow using SetHead as a // chain reparation mechanism without deleting any data! - log.Info("updatefn", "frozen", frozen, "header", header.Number) + // log.Info("updatefn", "frozen", frozen, "header", header.Number) if currentBlock := bc.CurrentBlock(); currentBlock != nil && header.Number.Uint64() <= currentBlock.NumberU64() { newHeadBlock := bc.GetBlock(header.Hash(), header.Number.Uint64()) if newHeadBlock == nil { @@ -464,7 +464,7 @@ func (bc *BlockChain) SetHead(head uint64) error { } head := bc.CurrentBlock().NumberU64() - log.Info("updatefn2", "frozen", frozen, "head", head) + // log.Info("updatefn2", "frozen", frozen, "head", head) // If setHead underflown the freezer threshold and the block processing // intent afterwards is full block importing, delete the chain segment diff --git a/core/headerchain.go b/core/headerchain.go index 05b46df840..2a1648e8fc 100644 --- a/core/headerchain.go +++ b/core/headerchain.go @@ -578,7 +578,7 @@ func (hc *HeaderChain) SetHead(head uint64, updateFn UpdateHeadBlocksCallback, d } nums = append(nums, num) - log.Info("removing", "nums", nums) + // log.Info("removing", "nums", nums) // Remove the related data from the database on all sidechains for _, num := range nums { diff --git a/eth/downloader/downloader.go b/eth/downloader/downloader.go index 442c0513a8..0b459cfdbe 100644 --- a/eth/downloader/downloader.go +++ b/eth/downloader/downloader.go @@ -649,7 +649,7 @@ func (d *Downloader) fetchHeight(p *peerConnection) (*types.Header, error) { // Make sure the peer actually gave something valid headers := packet.(*headerPack).headers if len(headers) != 1 { - p.log.Debug("Multiple headers for single request", "headers", len(headers)) + p.log.Info("Multiple headers for single request", "headers", len(headers)) return nil, errBadPeer } head := headers[0] @@ -884,7 +884,7 @@ func (d *Downloader) findAncestor(p *peerConnection, remoteHeader *types.Header) // Make sure the peer actually gave something valid headers := packer.(*headerPack).headers if len(headers) != 1 { - p.log.Debug("Multiple headers for single request", "headers", len(headers)) + p.log.Info("Multiple headers for single request", "headers", len(headers)) return 0, errBadPeer } arrived = true @@ -908,7 +908,7 @@ func (d *Downloader) findAncestor(p *peerConnection, remoteHeader *types.Header) } header := d.lightchain.GetHeaderByHash(h) // Independent of sync mode, header surely exists if header.Number.Uint64() != check { - p.log.Debug("Received non requested header", "number", header.Number, "hash", header.Hash(), "request", check) + p.log.Info("Received non requested header", "number", header.Number, "hash", header.Hash(), "request", check) return 0, errBadPeer } start = check @@ -1175,7 +1175,7 @@ func (d *Downloader) fetchHeaders(p *peerConnection, from uint64, pivot uint64, break } // Header retrieval timed out, consider the peer bad and drop - p.log.Debug("Header request timed out", "elapsed", ttl) + p.log.Info("Header request timed out", "elapsed", ttl) headerTimeoutMeter.Mark(1) d.dropPeer(p.id) @@ -1515,6 +1515,7 @@ func (d *Downloader) processHeaders(origin uint64, pivot uint64, td *big.Int) er for { select { case <-d.cancelCh: + rollbackErr = errCanceled return errCanceled case headers := <-d.headerProcCh: @@ -1542,6 +1543,7 @@ func (d *Downloader) processHeaders(origin uint64, pivot uint64, td *big.Int) er if d.Mode.SyncFullBlockChain() { head := d.blockchain.CurrentBlock() if !gotHeaders && td.Cmp(d.blockchain.GetTd(head.Hash(), head.NumberU64())) > 0 { + rollbackErr = errStallingPeer return errStallingPeer } } @@ -1556,6 +1558,7 @@ func (d *Downloader) processHeaders(origin uint64, pivot uint64, td *big.Int) er if d.Mode == FastSync || d.Mode == LightSync { head := d.lightchain.CurrentHeader() if td.Cmp(d.lightchain.GetTd(head.Hash(), head.Number.Uint64())) > 0 { + rollbackErr = errStallingPeer return errStallingPeer } } @@ -1569,6 +1572,7 @@ func (d *Downloader) processHeaders(origin uint64, pivot uint64, td *big.Int) er // Terminate if something failed in between processing chunks select { case <-d.cancelCh: + rollbackErr = errCanceled return errCanceled default: } @@ -1593,7 +1597,8 @@ func (d *Downloader) processHeaders(origin uint64, pivot uint64, td *big.Int) er if n > 0 && rollback == 0 { rollback = chunk[0].Number.Uint64() } - log.Debug("Invalid header encountered", "number", chunk[n].Number, "hash", chunk[n].Hash(), "err", err) + log.Info("Invalid header encountered", "number", chunk[n].Number, "hash", chunk[n].Hash(), "err", err) + return errInvalidChain } // All verifications passed, track all headers within the alloted limits @@ -1608,6 +1613,7 @@ func (d *Downloader) processHeaders(origin uint64, pivot uint64, td *big.Int) er for d.queue.PendingBlocks() >= maxQueuedHeaders || d.queue.PendingReceipts() >= maxQueuedHeaders { select { case <-d.cancelCh: + rollbackErr = errCanceled return errCanceled case <-time.After(time.Second): } @@ -1615,7 +1621,8 @@ func (d *Downloader) processHeaders(origin uint64, pivot uint64, td *big.Int) er // Otherwise insert the headers for content retrieval inserts := d.queue.Schedule(chunk, origin) if len(inserts) != len(chunk) { - log.Debug("Stale headers") + log.Info("Stale headers") + rollbackErr = errBadPeer return errBadPeer } } From 3c25c6f89d5e01e0940dc2dd67a04a936caa6f34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sami=20M=C3=A4kel=C3=A4?= Date: Fri, 18 Sep 2020 14:29:08 +0300 Subject: [PATCH 07/15] cleanup --- consensus/istanbul/backend/engine.go | 7 ++----- core/block_validator.go | 2 -- core/blockchain.go | 8 -------- core/genesis.go | 2 -- core/headerchain.go | 10 ++-------- eth/downloader/downloader.go | 14 ++++++-------- light/lightchain.go | 1 - 7 files changed, 10 insertions(+), 34 deletions(-) diff --git a/consensus/istanbul/backend/engine.go b/consensus/istanbul/backend/engine.go index 2d45b37f4a..5fabc9e488 100644 --- a/consensus/istanbul/backend/engine.go +++ b/consensus/istanbul/backend/engine.go @@ -149,7 +149,6 @@ func (sb *Backend) sanityCheck(chain consensus.ChainReader, header *types.Header } parent := chain.GetHeaderByNumber(first) if parent == nil || parent.Number.Uint64() != first { - log.Info("insane???") return consensus.ErrUnknownAncestor } return nil @@ -172,10 +171,9 @@ func (sb *Backend) verifyCascadingFields(chain consensus.ChainReader, header *ty } else { parent = chain.GetHeader(header.ParentHash, number-1) } - if chain.Config().FullHeaderChainAvailable /* || !istanbul.IsLastBlockOfEpoch(number, sb.config.Epoch) */ { + if chain.Config().FullHeaderChainAvailable { if parent == nil || parent.Number.Uint64() != number-1 || parent.Hash() != header.ParentHash { - log.Info("verify: didnt find parent") return consensus.ErrUnknownAncestor } if parent.Time+sb.config.BlockPeriod > header.Time { @@ -210,7 +208,6 @@ func (sb *Backend) VerifyHeaders(chain consensus.ChainReader, headers []*types.H } if err != nil { - log.Info("got error", "err", err) errored = true } @@ -787,7 +784,7 @@ func (sb *Backend) snapshot(chain consensus.ChainReader, number uint64, hash com if (blockHash != common.Hash{}) { if s, err := loadSnapshot(sb.config.Epoch, sb.db, blockHash); err == nil { - log.Info("Loaded validator set snapshot from disk", "number", numberIter, "hash", blockHash) + log.Trace("Loaded validator set snapshot from disk", "number", numberIter, "hash", blockHash) snap = s sb.recentSnapshots.Add(numberIter, snap) break diff --git a/core/block_validator.go b/core/block_validator.go index a299bf121d..06c89718ff 100644 --- a/core/block_validator.go +++ b/core/block_validator.go @@ -23,7 +23,6 @@ import ( "github.com/ethereum/go-ethereum/contract_comm/blockchain_parameters" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" ) @@ -61,7 +60,6 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error { } if !v.bc.HasBlockAndState(block.ParentHash(), block.NumberU64()-1) { if !v.bc.HasBlock(block.ParentHash(), block.NumberU64()-1) { - log.Info("validatebody unknown ancestor") return consensus.ErrUnknownAncestor } return consensus.ErrPrunedAncestor diff --git a/core/blockchain.go b/core/blockchain.go index 414977cbb3..c4a7efe4fc 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -407,13 +407,11 @@ func (bc *BlockChain) SetHead(head uint64) error { // current freezer limit to start nuking id underflown pivot := rawdb.ReadLastPivotNumber(bc.db) frozen, _ := bc.db.Ancients() - log.Info("Pivot", "pivot", pivot) updateFn := func(db ethdb.KeyValueWriter, header *types.Header) (uint64, bool) { // Rewind the block chain, ensuring we don't end up with a stateless head // block. Note, depth equality is permitted to allow using SetHead as a // chain reparation mechanism without deleting any data! - // log.Info("updatefn", "frozen", frozen, "header", header.Number) if currentBlock := bc.CurrentBlock(); currentBlock != nil && header.Number.Uint64() <= currentBlock.NumberU64() { newHeadBlock := bc.GetBlock(header.Hash(), header.Number.Uint64()) if newHeadBlock == nil { @@ -464,8 +462,6 @@ func (bc *BlockChain) SetHead(head uint64) error { } head := bc.CurrentBlock().NumberU64() - // log.Info("updatefn2", "frozen", frozen, "head", head) - // If setHead underflown the freezer threshold and the block processing // intent afterwards is full block importing, delete the chain segment // between the stateful-block and the sethead target. @@ -1364,7 +1360,6 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types. // Calculate the total difficulty of the block ptd := bc.GetTd(block.ParentHash(), block.NumberU64()-1) if ptd == nil { - log.Info("getting total difficulty") return NonStatTy, consensus.ErrUnknownAncestor } // Make sure no inconsistent state is leaked during insertion @@ -2192,8 +2187,6 @@ func (bc *BlockChain) InsertHeaderChain(chain []*types.Header, checkFreq int, co return i, err } - log.Info("Inserting validated headers", "freq", checkFreq, "num", len(chain)) - // Make sure only one thread manipulates the chain at once bc.chainmu.Lock() defer bc.chainmu.Unlock() @@ -2206,7 +2199,6 @@ func (bc *BlockChain) InsertHeaderChain(chain []*types.Header, checkFreq int, co return err } res, err := bc.hc.InsertHeaderChain(chain, whFunc, start) - log.Info("Inserted") return res, err } diff --git a/core/genesis.go b/core/genesis.go index 009cd511d0..8723e0b06a 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -217,8 +217,6 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, genesis *Genesis, override return storedcfg, stored, nil } - log.Info("reading head hash", "hash", rawdb.ReadHeadHeaderHash(db).String()) - // Check config compatibility and write the config. Compatibility errors // are returned to the caller unless we're already at block zero. height := rawdb.ReadHeaderNumber(db, rawdb.ReadHeadHeaderHash(db)) diff --git a/core/headerchain.go b/core/headerchain.go index 2a1648e8fc..3531c7e674 100644 --- a/core/headerchain.go +++ b/core/headerchain.go @@ -152,15 +152,12 @@ func (hc *HeaderChain) WriteHeader(header *types.Header) (status WriteStatus, er // Calculate the total difficulty of the header. // ptd seems to be abbreviation of "parent total difficulty". // In IBFT, the announced td (total difficulty) is 1 + block number. - log.Info("Write header", "num", number) ptd := hc.GetTd(header.ParentHash, number-1) if ptd == nil { if hc.config.FullHeaderChainAvailable { - log.Info("td header") return NonStatTy, consensus.ErrUnknownAncestor - } else { - localTd = big.NewInt(hc.CurrentHeader().Number.Int64() + 1) } + localTd = big.NewInt(hc.CurrentHeader().Number.Int64() + 1) } else { localTd = hc.GetTd(hc.currentHeaderHash, hc.CurrentHeader().Number.Uint64()) } @@ -324,8 +321,7 @@ func (hc *HeaderChain) InsertHeaderChain(chain []*types.Header, writeHeader WhCa if hc.HasHeader(hash, header.Number.Uint64()) { externTd := hc.GetTd(hash, header.Number.Uint64()) localTd := hc.GetTd(hc.currentHeaderHash, hc.CurrentHeader().Number.Uint64()) - log.Info("Had header", "num", header.Number.Uint64(), "td", externTd, "numbered", hc.numberCache.Contains(hash), "cached", hc.headerCache.Contains(hash)) - // if it has no difficulty, it wasn't stored properly + // If it has no difficulty, it wasn't stored properly if externTd != nil && externTd.Cmp(localTd) <= 0 { stats.ignored++ continue @@ -578,8 +574,6 @@ func (hc *HeaderChain) SetHead(head uint64, updateFn UpdateHeadBlocksCallback, d } nums = append(nums, num) - // log.Info("removing", "nums", nums) - // Remove the related data from the database on all sidechains for _, num := range nums { // Gather all the side fork hashes diff --git a/eth/downloader/downloader.go b/eth/downloader/downloader.go index 0b459cfdbe..625ee21288 100644 --- a/eth/downloader/downloader.go +++ b/eth/downloader/downloader.go @@ -529,7 +529,6 @@ func (d *Downloader) syncWithPeer(p *peerConnection, hash common.Hash, td *big.I } // Rewind the ancient store and blockchain if reorg happens. if origin+1 < frozen { - log.Info("Setting head", "target", origin+1) if err := d.lightchain.SetHead(origin + 1); err != nil { return err } @@ -649,7 +648,7 @@ func (d *Downloader) fetchHeight(p *peerConnection) (*types.Header, error) { // Make sure the peer actually gave something valid headers := packet.(*headerPack).headers if len(headers) != 1 { - p.log.Info("Multiple headers for single request", "headers", len(headers)) + p.log.Debug("Multiple headers for single request", "headers", len(headers)) return nil, errBadPeer } head := headers[0] @@ -884,7 +883,7 @@ func (d *Downloader) findAncestor(p *peerConnection, remoteHeader *types.Header) // Make sure the peer actually gave something valid headers := packer.(*headerPack).headers if len(headers) != 1 { - p.log.Info("Multiple headers for single request", "headers", len(headers)) + p.log.Debug("Multiple headers for single request", "headers", len(headers)) return 0, errBadPeer } arrived = true @@ -908,7 +907,7 @@ func (d *Downloader) findAncestor(p *peerConnection, remoteHeader *types.Header) } header := d.lightchain.GetHeaderByHash(h) // Independent of sync mode, header surely exists if header.Number.Uint64() != check { - p.log.Info("Received non requested header", "number", header.Number, "hash", header.Hash(), "request", check) + p.log.Debug("Received non requested header", "number", header.Number, "hash", header.Hash(), "request", check) return 0, errBadPeer } start = check @@ -1175,7 +1174,7 @@ func (d *Downloader) fetchHeaders(p *peerConnection, from uint64, pivot uint64, break } // Header retrieval timed out, consider the peer bad and drop - p.log.Info("Header request timed out", "elapsed", ttl) + p.log.Debug("Header request timed out", "elapsed", ttl) headerTimeoutMeter.Mark(1) d.dropPeer(p.id) @@ -1493,7 +1492,6 @@ func (d *Downloader) processHeaders(origin uint64, pivot uint64, td *big.Int) er lastFastBlock = d.blockchain.CurrentFastBlock().Number() lastBlock = d.blockchain.CurrentBlock().Number() } - log.Info("Setting head (rollback)", "target", rollback-1) if err := d.lightchain.SetHead(rollback - 1); err != nil { // -1 to target the parent of the first uncertain block // We're already unwinding the stack, only print the error to make it more visible log.Error("Failed to roll back chain segment", "head", rollback-1, "err", err) @@ -1597,7 +1595,7 @@ func (d *Downloader) processHeaders(origin uint64, pivot uint64, td *big.Int) er if n > 0 && rollback == 0 { rollback = chunk[0].Number.Uint64() } - log.Info("Invalid header encountered", "number", chunk[n].Number, "hash", chunk[n].Hash(), "err", err) + log.Debug("Invalid header encountered", "number", chunk[n].Number, "hash", chunk[n].Hash(), "err", err) return errInvalidChain } @@ -1621,7 +1619,7 @@ func (d *Downloader) processHeaders(origin uint64, pivot uint64, td *big.Int) er // Otherwise insert the headers for content retrieval inserts := d.queue.Schedule(chunk, origin) if len(inserts) != len(chunk) { - log.Info("Stale headers") + log.Debug("Stale headers") rollbackErr = errBadPeer return errBadPeer } diff --git a/light/lightchain.go b/light/lightchain.go index aea154cbfc..969413ff9a 100644 --- a/light/lightchain.go +++ b/light/lightchain.go @@ -174,7 +174,6 @@ func (lc *LightChain) loadLastState() error { func (lc *LightChain) SetHead(head uint64) error { lc.chainmu.Lock() defer lc.chainmu.Unlock() - log.Info("Light set head", head) lc.hc.SetHead(head, nil, nil) return lc.loadLastState() } From caf8918454e2ab0e5315b49a4a25391a9cabf284 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sami=20M=C3=A4kel=C3=A4?= Date: Wed, 30 Sep 2020 16:30:16 +0300 Subject: [PATCH 08/15] fixing this --- les/commons.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/les/commons.go b/les/commons.go index d93712e1a5..bb4b24bcac 100644 --- a/les/commons.go +++ b/les/commons.go @@ -115,13 +115,18 @@ func (c *lesCommons) nodeInfo() interface{} { // section index and head hash as a local checkpoint package. func (c *lesCommons) latestLocalCheckpoint() params.TrustedCheckpoint { var sections uint64 + var sections2 uint64 if c.chtIndexer == nil { sections = 0 } else { sections, _, _ = c.chtIndexer.Sections() } - sections2, _, _ := c.bloomTrieIndexer.Sections() + if c.bloomTrieIndexer == nil { + sections2 = 0 + } else { + sections2, _, _ = c.bloomTrieIndexer.Sections() + } // Cap the section index if the two sections are not consistent. if sections > sections2 { sections = sections2 From 84291089433c04d55410e283d0671bc95644c804 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sami=20M=C3=A4kel=C3=A4?= Date: Wed, 30 Sep 2020 16:36:52 +0300 Subject: [PATCH 09/15] lint --- core/blockchain_repair_test.go | 2 +- core/blockchain_sethead_test.go | 2 +- core/rawdb/freezer.go | 4 +--- eth/downloader/downloader.go | 8 -------- eth/handler.go | 2 +- 5 files changed, 4 insertions(+), 14 deletions(-) diff --git a/core/blockchain_repair_test.go b/core/blockchain_repair_test.go index a33c01e375..275f4b1633 100644 --- a/core/blockchain_repair_test.go +++ b/core/blockchain_repair_test.go @@ -21,7 +21,7 @@ package core import ( -// "fmt" + // "fmt" "io/ioutil" "os" "testing" diff --git a/core/blockchain_sethead_test.go b/core/blockchain_sethead_test.go index 08a58dc73a..ce8cee30d0 100644 --- a/core/blockchain_sethead_test.go +++ b/core/blockchain_sethead_test.go @@ -51,7 +51,7 @@ type rewindTest struct { expHeadBlock uint64 // Block number of the expected head full block } -func (tt *rewindTest) dump(crash bool) string { +func (tt *rewindTest) Dump(crash bool) string { buffer := new(strings.Builder) fmt.Fprint(buffer, "Chain:\n G") diff --git a/core/rawdb/freezer.go b/core/rawdb/freezer.go index 52e5b1b53d..e9acee061e 100644 --- a/core/rawdb/freezer.go +++ b/core/rawdb/freezer.go @@ -22,7 +22,6 @@ import ( "math" "os" "path/filepath" - "sync" "sync/atomic" "time" @@ -78,8 +77,7 @@ type freezer struct { trigger chan chan struct{} // Manual blocking freeze trigger, test determinism - quit chan struct{} - closeOnce sync.Once + quit chan struct{} } // newFreezer creates a chain freezer that moves ancient chain data into diff --git a/eth/downloader/downloader.go b/eth/downloader/downloader.go index 625ee21288..b55f154e1e 100644 --- a/eth/downloader/downloader.go +++ b/eth/downloader/downloader.go @@ -1645,14 +1645,6 @@ func (d *Downloader) processHeaders(origin uint64, pivot uint64, td *big.Int) er } } -func headersToNumbers(headers []*types.Header) []*big.Int { - headerNumbers := make([]*big.Int, 0) - for _, header := range headers { - headerNumbers = append(headerNumbers, header.Number) - } - return headerNumbers -} - // processFullSyncContent takes fetch results from the queue and imports them into the chain. func (d *Downloader) processFullSyncContent() error { for { diff --git a/eth/handler.go b/eth/handler.go index 8a603a469e..b5e7885b9d 100644 --- a/eth/handler.go +++ b/eth/handler.go @@ -119,7 +119,7 @@ func NewProtocolManager(config *params.ChainConfig, checkpoint *params.TrustedCh eventMux: mux, txpool: txpool, blockchain: blockchain, - chaindb: chaindb, + chaindb: chaindb, peers: newPeerSet(), whitelist: whitelist, newPeerCh: make(chan *peer), From bf43578045cb6bdfd0e01c99392a54990cd5ab9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sami=20M=C3=A4kel=C3=A4?= Date: Wed, 14 Oct 2020 11:53:19 +0300 Subject: [PATCH 10/15] review comments --- consensus/istanbul/backend/engine.go | 17 +- core/blockchain_repair_test.go | 383 ------------------------- core/blockchain_sethead_test.go | 407 --------------------------- p2p/discv5/node_test.go | 2 +- 4 files changed, 10 insertions(+), 799 deletions(-) diff --git a/consensus/istanbul/backend/engine.go b/consensus/istanbul/backend/engine.go index 5fabc9e488..eb09fcaed0 100644 --- a/consensus/istanbul/backend/engine.go +++ b/consensus/istanbul/backend/engine.go @@ -134,21 +134,22 @@ func (sb *Backend) verifyHeader(chain consensus.ChainReader, header *types.Heade return sb.verifyCascadingFields(chain, header, parents) } -func (sb *Backend) sanityCheck(chain consensus.ChainReader, header *types.Header, parents []*types.Header) error { +// A sanity check for lightest mode. Checks that the correct epoch block exists for this header +func (sb *Backend) checkEpochBlockExists(chain consensus.ChainReader, header *types.Header, parents []*types.Header) error { number := header.Number.Uint64() // Check that latest epoch block is available epoch := istanbul.GetEpochNumber(number, sb.config.Epoch) - first := istanbul.GetEpochLastBlockNumber(epoch-1, sb.config.Epoch) - if number == first { - first = istanbul.GetEpochLastBlockNumber(epoch-2, sb.config.Epoch) + epochBlockNumber := istanbul.GetEpochLastBlockNumber(epoch-1, sb.config.Epoch) + if number == epochBlockNumber { + epochBlockNumber = istanbul.GetEpochLastBlockNumber(epoch-2, sb.config.Epoch) } for _, hdr := range parents { - if hdr.Number.Uint64() == first { + if hdr.Number.Uint64() == epochBlockNumber { return nil } } - parent := chain.GetHeaderByNumber(first) - if parent == nil || parent.Number.Uint64() != first { + parent := chain.GetHeaderByNumber(epochBlockNumber) + if parent == nil || parent.Number.Uint64() != epochBlockNumber { return consensus.ErrUnknownAncestor } return nil @@ -183,7 +184,7 @@ func (sb *Backend) verifyCascadingFields(chain consensus.ChainReader, header *ty if err := sb.verifySigner(chain, header, parents); err != nil { return err } - } else if err := sb.sanityCheck(chain, header, parents); err != nil { + } else if err := sb.checkEpochBlockExists(chain, header, parents); err != nil { return err } diff --git a/core/blockchain_repair_test.go b/core/blockchain_repair_test.go index 275f4b1633..7450546a8f 100644 --- a/core/blockchain_repair_test.go +++ b/core/blockchain_repair_test.go @@ -1173,389 +1173,6 @@ func TestLongNewerForkedFastSyncingDeepRepair(t *testing.T) { }) } -// Tests a recovery for a long canonical chain with frozen blocks and a longer side -// chain, where a recent block - newer than the ancient limit - was already committed -// to disk and then the process crashed. In this case we expect the chain to be -// rolled back to the committed block, with everything afterwads kept as fast sync -// data. The side chain completely nuked by the freezer. -/* - -// Tests a recovery for a short canonical chain and a longer side chain, where a -// recent block was already committed to disk and then the process crashed. In this -// case we expect the canonical chain to be rolled back to the committed block, but -// the chain data itself left in the database for replaying. -func TestShortReorgedRepair(t *testing.T) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) - // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 - // - // Frozen: none - // Commit: G, C4 - // Pivot : none - // - // CRASH - // - // ------------------------------ - // - // Expected in leveldb: - // G->C1->C2->C3->C4->C5->C6->C7->C8 - // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 - // - // Expected head header : C8 - // Expected head fast block: C8 - // Expected head block : C4 - testRepair(t, &rewindTest{ - canonicalBlocks: 8, - sidechainBlocks: 10, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: nil, - expCanonicalBlocks: 8, - expSidechainBlocks: 10, - expFrozen: 0, - expHeadHeader: 8, - expHeadFastBlock: 8, - expHeadBlock: 4, - }) -} - -// Tests a recovery for a short canonical chain and a longer side chain, where -// the fast sync pivot point was already committed to disk and then the process -// crashed. In this case we expect the canonical chain to be rolled back to the -// committed block, but the chain data itself left in the database for replaying. -func TestShortReorgedFastSyncedRepair(t *testing.T) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) - // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 - // - // Frozen: none - // Commit: G, C4 - // Pivot : C4 - // - // CRASH - // - // ------------------------------ - // - // Expected in leveldb: - // G->C1->C2->C3->C4->C5->C6->C7->C8 - // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 - // - // Expected head header : C8 - // Expected head fast block: C8 - // Expected head block : C4 - testRepair(t, &rewindTest{ - canonicalBlocks: 8, - sidechainBlocks: 10, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: uint64ptr(4), - expCanonicalBlocks: 8, - expSidechainBlocks: 10, - expFrozen: 0, - expHeadHeader: 8, - expHeadFastBlock: 8, - expHeadBlock: 4, - }) -} - -// Tests a recovery for a short canonical chain and a longer side chain, where -// the fast sync pivot point was not yet committed, but the process crashed. In -// this case we expect the chain to detect that it was fast syncing and not delete -// anything, since we can just pick up directly where we left off. -func TestShortReorgedFastSyncingRepair(t *testing.T) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) - // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 - // - // Frozen: none - // Commit: G - // Pivot : C4 - // - // CRASH - // - // ------------------------------ - // - // Expected in leveldb: - // G->C1->C2->C3->C4->C5->C6->C7->C8 - // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 - // - // Expected head header : C8 - // Expected head fast block: C8 - // Expected head block : G - testRepair(t, &rewindTest{ - canonicalBlocks: 8, - sidechainBlocks: 10, - freezeThreshold: 16, - commitBlock: 0, - pivotBlock: uint64ptr(4), - expCanonicalBlocks: 8, - expSidechainBlocks: 10, - expFrozen: 0, - expHeadHeader: 8, - expHeadFastBlock: 8, - expHeadBlock: 0, - }) -} - -func TestLongReorgedShallowRepair(t *testing.T) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) - // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12->S13->S14->S15->S16->S17->S18->S19->S20->S21->S22->S23->S24->S25->S26 - // - // Frozen: - // G->C1->C2 - // - // Commit: G, C4 - // Pivot : none - // - // CRASH - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2 - // - // Expected in leveldb: - // C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 - // - // Expected head header : C18 - // Expected head fast block: C18 - // Expected head block : C4 - testRepair(t, &rewindTest{ - canonicalBlocks: 18, - sidechainBlocks: 26, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: nil, - expCanonicalBlocks: 18, - expSidechainBlocks: 0, - expFrozen: 3, - expHeadHeader: 18, - expHeadFastBlock: 18, - expHeadBlock: 4, - }) -} - -// Tests a recovery for a long canonical chain with frozen blocks and a longer side -// chain, where a recent block - older than the ancient limit - was already committed -// to disk and then the process crashed. In this case we expect the canonical chains -// to be rolled back to the committed block, with everything afterwads deleted. The -// side chain completely nuked by the freezer. -func TestLongReorgedDeepRepair(t *testing.T) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) - // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12->S13->S14->S15->S16->S17->S18->S19->S20->S21->S22->S23->S24->S25->S26 - // - // Frozen: - // G->C1->C2->C3->C4->C5->C6->C7->C8 - // - // Commit: G, C4 - // Pivot : none - // - // CRASH - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2->C3->C4 - // - // Expected in leveldb: none - // - // Expected head header : C4 - // Expected head fast block: C4 - // Expected head block : C4 - testRepair(t, &rewindTest{ - canonicalBlocks: 24, - sidechainBlocks: 26, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: nil, - expCanonicalBlocks: 4, - expSidechainBlocks: 0, - expFrozen: 5, - expHeadHeader: 4, - expHeadFastBlock: 4, - expHeadBlock: 4, - }) -} - -// Tests a recovery for a long canonical chain with frozen blocks and a longer -// side chain, where the fast sync pivot point - newer than the ancient limit - -// was already committed to disk and then the process crashed. In this case we -// expect the chain to be rolled back to the committed block, with everything -// afterwads kept as fast sync data. The side chain completely nuked by the -// freezer. -func TestLongReorgedFastSyncedShallowRepair(t *testing.T) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) - // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12->S13->S14->S15->S16->S17->S18->S19->S20->S21->S22->S23->S24->S25->S26 - // - // Frozen: - // G->C1->C2 - // - // Commit: G, C4 - // Pivot : C4 - // - // CRASH - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2 - // - // Expected in leveldb: - // C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 - // - // Expected head header : C18 - // Expected head fast block: C18 - // Expected head block : C4 - testRepair(t, &rewindTest{ - canonicalBlocks: 18, - sidechainBlocks: 26, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: uint64ptr(4), - expCanonicalBlocks: 18, - expSidechainBlocks: 0, - expFrozen: 3, - expHeadHeader: 18, - expHeadFastBlock: 18, - expHeadBlock: 4, - }) -} - -// Tests a recovery for a long canonical chain with frozen blocks and a longer -// side chain, where the fast sync pivot point - older than the ancient limit - -// was already committed to disk and then the process crashed. In this case we -// expect the canonical chains to be rolled back to the committed block, with -// everything afterwads deleted. The side chain completely nuked by the freezer. -func TestLongReorgedFastSyncedDeepRepair(t *testing.T) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) - // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12->S13->S14->S15->S16->S17->S18->S19->S20->S21->S22->S23->S24->S25->S26 - // - // Frozen: - // G->C1->C2->C3->C4->C5->C6->C7->C8 - // - // Commit: G, C4 - // Pivot : C4 - // - // CRASH - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2->C3->C4 - // - // Expected in leveldb: none - // - // Expected head header : C4 - // Expected head fast block: C4 - // Expected head block : C4 - testRepair(t, &rewindTest{ - canonicalBlocks: 24, - sidechainBlocks: 26, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: uint64ptr(4), - expCanonicalBlocks: 4, - expSidechainBlocks: 0, - expFrozen: 5, - expHeadHeader: 4, - expHeadFastBlock: 4, - expHeadBlock: 4, - }) -} - -// Tests a recovery for a long canonical chain with frozen blocks and a longer -// side chain, where the fast sync pivot point - newer than the ancient limit - -// was not yet committed, but the process crashed. In this case we expect the -// chain to detect that it was fast syncing and not delete anything, since we -// can just pick up directly where we left off. -func TestLongReorgedFastSyncingShallowRepair(t *testing.T) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) - // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12->S13->S14->S15->S16->S17->S18->S19->S20->S21->S22->S23->S24->S25->S26 - // - // Frozen: - // G->C1->C2 - // - // Commit: G - // Pivot : C4 - // - // CRASH - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2 - // - // Expected in leveldb: - // C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 - // - // Expected head header : C18 - // Expected head fast block: C18 - // Expected head block : G - testRepair(t, &rewindTest{ - canonicalBlocks: 18, - sidechainBlocks: 26, - freezeThreshold: 16, - commitBlock: 0, - pivotBlock: uint64ptr(4), - expCanonicalBlocks: 18, - expSidechainBlocks: 0, - expFrozen: 3, - expHeadHeader: 18, - expHeadFastBlock: 18, - expHeadBlock: 0, - }) -} - -// Tests a recovery for a long canonical chain with frozen blocks and a longer -// side chain, where the fast sync pivot point - older than the ancient limit - -// was not yet committed, but the process crashed. In this case we expect the -// chain to detect that it was fast syncing and not delete anything, since we -// can just pick up directly where we left off. -func TestLongReorgedFastSyncingDeepRepair(t *testing.T) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) - // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12->S13->S14->S15->S16->S17->S18->S19->S20->S21->S22->S23->S24->S25->S26 - // - // Frozen: - // G->C1->C2->C3->C4->C5->C6->C7->C8 - // - // Commit: G - // Pivot : C4 - // - // CRASH - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2->C3->C4->C5->C6->C7->C8 - // - // Expected in leveldb: - // C8)->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 - // - // Expected head header : C24 - // Expected head fast block: C24 - // Expected head block : G - testRepair(t, &rewindTest{ - canonicalBlocks: 24, - sidechainBlocks: 26, - freezeThreshold: 16, - commitBlock: 0, - pivotBlock: uint64ptr(4), - expCanonicalBlocks: 24, - expSidechainBlocks: 0, - expFrozen: 9, - expHeadHeader: 24, - expHeadFastBlock: 24, - expHeadBlock: 0, - }) -} -*/ - func testRepair(t *testing.T, tt *rewindTest) { // It's hard to follow the test case, visualize the input //log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true)))) diff --git a/core/blockchain_sethead_test.go b/core/blockchain_sethead_test.go index ce8cee30d0..9b7065897e 100644 --- a/core/blockchain_sethead_test.go +++ b/core/blockchain_sethead_test.go @@ -1338,413 +1338,6 @@ func TestLongNewerForkedFastSyncingDeepSetHead(t *testing.T) { }) } -/* -// Tests a sethead for a short canonical chain and a longer side chain, where a -// recent block was already committed to disk and then sethead was called. In this -// case we expect the canonical full chain to be rolled back to the committed block. -// All data above the sethead point should be deleted. In between the committed -// block and the requested head the data can remain as "fast sync" data to avoid -// having to redownload it. The side chain should be truncated to the head set. -// -// The side chain could be left to be if the fork point was before the new head -// we are deleting to, but it would be exceedingly hard to detect that case and -// properly handle it, so we'll trade extra work in exchange for simpler code. -func TestShortReorgedSetHead(t *testing.T) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) - // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 - // - // Frozen: none - // Commit: G, C4 - // Pivot : none - // - // SetHead(7) - // - // ------------------------------ - // - // Expected in leveldb: - // G->C1->C2->C3->C4->C5->C6->C7 - // └->S1->S2->S3->S4->S5->S6->S7 - // - // Expected head header : C7 - // Expected head fast block: C7 - // Expected head block : C4 - testSetHead(t, &rewindTest{ - canonicalBlocks: 8, - sidechainBlocks: 10, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: nil, - setheadBlock: 7, - expCanonicalBlocks: 7, - expSidechainBlocks: 7, - expFrozen: 0, - expHeadHeader: 7, - expHeadFastBlock: 7, - expHeadBlock: 4, - }) -} - -// Tests a sethead for a short canonical chain and a longer side chain, where -// the fast sync pivot point was already committed to disk and then sethead was -// called. In this case we expect the canonical full chain to be rolled back to -// the committed block. All data above the sethead point should be deleted. In -// between the committed block and the requested head the data can remain as -// "fast sync" data to avoid having to redownload it. The side chain should be -// truncated to the head set. -// -// The side chain could be left to be if the fork point was before the new head -// we are deleting to, but it would be exceedingly hard to detect that case and -// properly handle it, so we'll trade extra work in exchange for simpler code. -func TestShortReorgedFastSyncedSetHead(t *testing.T) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) - // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 - // - // Frozen: none - // Commit: G, C4 - // Pivot : C4 - // - // SetHead(7) - // - // ------------------------------ - // - // Expected in leveldb: - // G->C1->C2->C3->C4->C5->C6->C7 - // └->S1->S2->S3->S4->S5->S6->S7 - // - // Expected head header : C7 - // Expected head fast block: C7 - // Expected head block : C4 - testSetHead(t, &rewindTest{ - canonicalBlocks: 8, - sidechainBlocks: 10, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: uint64ptr(4), - setheadBlock: 7, - expCanonicalBlocks: 7, - expSidechainBlocks: 7, - expFrozen: 0, - expHeadHeader: 7, - expHeadFastBlock: 7, - expHeadBlock: 4, - }) -} - -// Tests a sethead for a short canonical chain and a longer side chain, where -// the fast sync pivot point was not yet committed, but sethead was called. In -// this case we expect the chain to detect that it was fast syncing and delete -// everything from the new head, since we can just pick up fast syncing from -// there. -// -// The side chain could be left to be if the fork point was before the new head -// we are deleting to, but it would be exceedingly hard to detect that case and -// properly handle it, so we'll trade extra work in exchange for simpler code. -func TestShortReorgedFastSyncingSetHead(t *testing.T) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) - // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 - // - // Frozen: none - // Commit: G - // Pivot : C4 - // - // SetHead(7) - // - // ------------------------------ - // - // Expected in leveldb: - // G->C1->C2->C3->C4->C5->C6->C7 - // └->S1->S2->S3->S4->S5->S6->S7 - // - // Expected head header : C7 - // Expected head fast block: C7 - // Expected head block : G - testSetHead(t, &rewindTest{ - canonicalBlocks: 8, - sidechainBlocks: 10, - freezeThreshold: 16, - commitBlock: 0, - pivotBlock: uint64ptr(4), - setheadBlock: 7, - expCanonicalBlocks: 7, - expSidechainBlocks: 7, - expFrozen: 0, - expHeadHeader: 7, - expHeadFastBlock: 7, - expHeadBlock: 0, - }) -} - -// Tests a sethead for a long canonical chain with frozen blocks and a longer side -// chain, where a recent block - newer than the ancient limit - was already committed -// to disk and then sethead was called. In this case the freezer will delete the -// sidechain since it's dangling, reverting to TestLongShallowSetHead. -func TestLongReorgedShallowSetHead(t *testing.T) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) - // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12->S13->S14->S15->S16->S17->S18->S19->S20->S21->S22->S23->S24->S25->S26 - // - // Frozen: - // G->C1->C2 - // - // Commit: G, C4 - // Pivot : none - // - // SetHead(6) - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2 - // - // Expected in leveldb: - // C2)->C3->C4->C5->C6 - // - // Expected head header : C6 - // Expected head fast block: C6 - // Expected head block : C4 - testSetHead(t, &rewindTest{ - canonicalBlocks: 18, - sidechainBlocks: 26, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: nil, - setheadBlock: 6, - expCanonicalBlocks: 6, - expSidechainBlocks: 0, - expFrozen: 3, - expHeadHeader: 6, - expHeadFastBlock: 6, - expHeadBlock: 4, - }) -} - -// Tests a sethead for a long canonical chain with frozen blocks and a longer side -// chain, where a recent block - older than the ancient limit - was already committed -// to disk and then sethead was called. In this case the freezer will delete the -// sidechain since it's dangling, reverting to TestLongDeepSetHead. -func TestLongReorgedDeepSetHead(t *testing.T) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) - // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12->S13->S14->S15->S16->S17->S18->S19->S20->S21->S22->S23->S24->S25->S26 - // - // Frozen: - // G->C1->C2->C3->C4->C5->C6->C7->C8 - // - // Commit: G, C4 - // Pivot : none - // - // SetHead(6) - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2->C3->C4 - // - // Expected in leveldb: none - // - // Expected head header : C4 - // Expected head fast block: C4 - // Expected head block : C4 - testSetHead(t, &rewindTest{ - canonicalBlocks: 24, - sidechainBlocks: 26, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: nil, - setheadBlock: 6, - expCanonicalBlocks: 4, - expSidechainBlocks: 0, - expFrozen: 5, - expHeadHeader: 4, - expHeadFastBlock: 4, - expHeadBlock: 4, - }) -} - -// Tests a sethead for a long canonical chain with frozen blocks and a longer -// side chain, where the fast sync pivot point - newer than the ancient limit - -// was already committed to disk and then sethead was called. In this case the -// freezer will delete the sidechain since it's dangling, reverting to -// TestLongFastSyncedShallowSetHead. -func TestLongReorgedFastSyncedShallowSetHead(t *testing.T) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) - // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12->S13->S14->S15->S16->S17->S18->S19->S20->S21->S22->S23->S24->S25->S26 - // - // Frozen: - // G->C1->C2 - // - // Commit: G, C4 - // Pivot : C4 - // - // SetHead(6) - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2 - // - // Expected in leveldb: - // C2)->C3->C4->C5->C6 - // - // Expected head header : C6 - // Expected head fast block: C6 - // Expected head block : C4 - testSetHead(t, &rewindTest{ - canonicalBlocks: 18, - sidechainBlocks: 26, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: uint64ptr(4), - setheadBlock: 6, - expCanonicalBlocks: 6, - expSidechainBlocks: 0, - expFrozen: 3, - expHeadHeader: 6, - expHeadFastBlock: 6, - expHeadBlock: 4, - }) -} - -// Tests a sethead for a long canonical chain with frozen blocks and a longer -// side chain, where the fast sync pivot point - older than the ancient limit - -// was already committed to disk and then sethead was called. In this case the -// freezer will delete the sidechain since it's dangling, reverting to -// TestLongFastSyncedDeepSetHead. -func TestLongReorgedFastSyncedDeepSetHead(t *testing.T) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) - // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12->S13->S14->S15->S16->S17->S18->S19->S20->S21->S22->S23->S24->S25->S26 - // - // Frozen: - // G->C1->C2->C3->C4->C5->C6->C7->C8 - // - // Commit: G, C4 - // Pivot : C4 - // - // SetHead(6) - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2->C3->C4 - // - // Expected in leveldb: none - // - // Expected head header : C4 - // Expected head fast block: C4 - // Expected head block : C4 - testSetHead(t, &rewindTest{ - canonicalBlocks: 24, - sidechainBlocks: 26, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: uint64ptr(4), - setheadBlock: 6, - expCanonicalBlocks: 4, - expSidechainBlocks: 0, - expFrozen: 5, - expHeadHeader: 4, - expHeadFastBlock: 4, - expHeadBlock: 4, - }) -} - -// Tests a sethead for a long canonical chain with frozen blocks and a longer -// side chain, where the fast sync pivot point - newer than the ancient limit - -// was not yet committed, but sethead was called. In this case we expect the -// chain to detect that it was fast syncing and delete everything from the new -// head, since we can just pick up fast syncing from there. The side chain is -// completely nuked by the freezer. -func TestLongReorgedFastSyncingShallowSetHead(t *testing.T) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) - // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12->S13->S14->S15->S16->S17->S18->S19->S20->S21->S22->S23->S24->S25->S26 - // - // Frozen: - // G->C1->C2 - // - // Commit: G - // Pivot : C4 - // - // SetHead(6) - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2 - // - // Expected in leveldb: - // C2)->C3->C4->C5->C6 - // - // Expected head header : C6 - // Expected head fast block: C6 - // Expected head block : G - testSetHead(t, &rewindTest{ - canonicalBlocks: 18, - sidechainBlocks: 26, - freezeThreshold: 16, - commitBlock: 0, - pivotBlock: uint64ptr(4), - setheadBlock: 6, - expCanonicalBlocks: 6, - expSidechainBlocks: 0, - expFrozen: 3, - expHeadHeader: 6, - expHeadFastBlock: 6, - expHeadBlock: 0, - }) -} - -// Tests a sethead for a long canonical chain with frozen blocks and a longer -// side chain, where the fast sync pivot point - older than the ancient limit - -// was not yet committed, but sethead was called. In this case we expect the -// chain to detect that it was fast syncing and delete everything from the new -// head, since we can just pick up fast syncing from there. The side chain is -// completely nuked by the freezer. -func TestLongReorgedFastSyncingDeepSetHead(t *testing.T) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) - // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12->S13->S14->S15->S16->S17->S18->S19->S20->S21->S22->S23->S24->S25->S26 - // - // Frozen: - // G->C1->C2->C3->C4->C5->C6->C7->C8 - // - // Commit: G - // Pivot : C4 - // - // SetHead(6) - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2->C3->C4->C5->C6 - // - // Expected in leveldb: none - // - // Expected head header : C6 - // Expected head fast block: C6 - // Expected head block : G - testSetHead(t, &rewindTest{ - canonicalBlocks: 24, - sidechainBlocks: 26, - freezeThreshold: 16, - commitBlock: 0, - pivotBlock: uint64ptr(4), - setheadBlock: 6, - expCanonicalBlocks: 6, - expSidechainBlocks: 0, - expFrozen: 7, - expHeadHeader: 6, - expHeadFastBlock: 6, - expHeadBlock: 0, - }) -} -*/ - func testSetHead(t *testing.T, tt *rewindTest) { // It's hard to follow the test case, visualize the input //log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true)))) diff --git a/p2p/discv5/node_test.go b/p2p/discv5/node_test.go index 2b0b4a8d3c..439c5a64f1 100644 --- a/p2p/discv5/node_test.go +++ b/p2p/discv5/node_test.go @@ -142,7 +142,7 @@ var parseNodeTests = []struct { { // This test checks that errors from url.Parse are handled. rawurl: "://foo", - wantError: `parse "://foo": missing protocol scheme`, + wantError: `parse ://foo: missing protocol scheme`, }, } From cd150837cd58b2c0fecb14c8d345e3e6c56db79e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sami=20M=C3=A4kel=C3=A4?= Date: Wed, 14 Oct 2020 12:30:13 +0300 Subject: [PATCH 11/15] lint --- consensus/istanbul/backend/engine.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/consensus/istanbul/backend/engine.go b/consensus/istanbul/backend/engine.go index eb09fcaed0..a9019f67e2 100644 --- a/consensus/istanbul/backend/engine.go +++ b/consensus/istanbul/backend/engine.go @@ -134,7 +134,7 @@ func (sb *Backend) verifyHeader(chain consensus.ChainReader, header *types.Heade return sb.verifyCascadingFields(chain, header, parents) } -// A sanity check for lightest mode. Checks that the correct epoch block exists for this header +// A sanity check for lightest mode. Checks that the correct epoch block exists for this header func (sb *Backend) checkEpochBlockExists(chain consensus.ChainReader, header *types.Header, parents []*types.Header) error { number := header.Number.Uint64() // Check that latest epoch block is available From 10365961e4d93838a32858e9b41f96d6058cd6aa Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Fri, 29 May 2020 11:12:43 +0200 Subject: [PATCH 12/15] pick --- .travis.yml | 12 +---------- eth/downloader/downloader.go | 36 +++++++++++++++++++++---------- eth/downloader/downloader_test.go | 27 +++++++++++++---------- eth/downloader/queue.go | 14 ++++++------ 4 files changed, 50 insertions(+), 39 deletions(-) diff --git a/.travis.yml b/.travis.yml index 416a83018d..21ee5ffc76 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,17 +18,7 @@ jobs: - stage: build os: linux dist: xenial - go: 1.11.x - env: - - GO111MODULE=on - script: - - go run build/ci.go install - - go run build/ci.go test -coverage $TEST_PACKAGES - - - stage: build - os: linux - dist: xenial - go: 1.12.x + go: 1.13.x env: - GO111MODULE=on script: diff --git a/eth/downloader/downloader.go b/eth/downloader/downloader.go index b55f154e1e..d1c3cf11ed 100644 --- a/eth/downloader/downloader.go +++ b/eth/downloader/downloader.go @@ -351,13 +351,28 @@ func (d *Downloader) UnregisterPeer(id string) error { // adding various sanity checks as well as wrapping it with various log entries. func (d *Downloader) Synchronise(id string, head common.Hash, td *big.Int, mode SyncMode) error { err := d.synchronise(id, head, td, mode) + switch err { - case nil: - case errBusy, errCanceled: + case nil, errBusy, errCanceled: + return err + } + + if errors.Is(err, errInvalidChain) { + log.Warn("Synchronisation failed, dropping peer", "peer", id, "err", err) + if d.dropPeer == nil { + // The dropPeer method is nil when `--copydb` is used for a local copy. + // Timeouts can occur if e.g. compaction hits at the wrong time, and can be ignored + log.Warn("Downloader wants to drop peer, but peerdrop-function is not set", "peer", id) + } else { + d.dropPeer(id) + } + return err + } + switch err { case errTimeout, errBadPeer, errStallingPeer, errUnsyncedPeer, errEmptyHeaderSet, errPeersUnavailable, errTooOld, - errInvalidAncestor, errInvalidChain: + errInvalidAncestor: log.Warn("Synchronisation failed, dropping peer", "peer", id, "err", err) if d.dropPeer == nil { // The dropPeer method is nil when `--copydb` is used for a local copy. @@ -805,7 +820,7 @@ func (d *Downloader) findAncestor(p *peerConnection, remoteHeader *types.Header) expectNumber := from + int64(i)*int64(skip+1) if number := header.Number.Int64(); number != expectNumber { p.log.Warn("Head headers broke chain ordering", "index", i, "requested", expectNumber, "received", number, "localHeight", localHeight, "remoteHeight", remoteHeight) - return 0, errInvalidChain + return 0, fmt.Errorf("%w: %v", errInvalidChain, errors.New("head headers broke chain ordering")) } } // Check if a common ancestor was found @@ -1084,7 +1099,7 @@ func (d *Downloader) fetchHeaders(p *peerConnection, from uint64, pivot uint64, filled, proced, err := d.fillHeaderSkeleton(from, headers) if err != nil { p.log.Debug("Skeleton chain invalid", "err", err) - return errInvalidChain + return fmt.Errorf("%w: %v", errInvalidChain, err) } headers = filled[proced:] from += uint64(proced) @@ -1328,13 +1343,13 @@ func (d *Downloader) fetchParts(deliveryCh chan dataPack, deliver func(dataPack) if peer := d.peers.Peer(packet.PeerId()); peer != nil { // Deliver the received chunk of data and check chain validity accepted, err := deliver(packet) - if err == errInvalidChain { + if errors.Is(err, errInvalidChain) { return err } // Unless a peer delivered something completely else than requested (usually // caused by a timed out request which came through in the end), set it to // idle. If the delivery's stale, the peer should have already been idled. - if err != errStaleDelivery { + if !errors.Is(err, errStaleDelivery) { setIdle(peer, accepted) } // Issue a log to the user to see what's going on @@ -1596,8 +1611,7 @@ func (d *Downloader) processHeaders(origin uint64, pivot uint64, td *big.Int) er rollback = chunk[0].Number.Uint64() } log.Debug("Invalid header encountered", "number", chunk[n].Number, "hash", chunk[n].Hash(), "err", err) - - return errInvalidChain + return fmt.Errorf("%w: %v", errInvalidChain, err) } // All verifications passed, track all headers within the alloted limits head := chunk[len(chunk)-1].Number.Uint64() @@ -1691,7 +1705,7 @@ func (d *Downloader) importBlockResults(results []*fetchResult) error { // of the blocks delivered from the downloader, and the indexing will be off. log.Debug("Downloaded item processing failed on sidechain import", "index", index, "err", err) } - return errInvalidChain + return fmt.Errorf("%w: %v", errInvalidChain, err) } return nil } @@ -1870,7 +1884,7 @@ func (d *Downloader) commitFastSyncData(results []*fetchResult, stateSync *state } if index, err := d.blockchain.InsertReceiptChain(blocks, receipts, d.ancientLimit); err != nil { log.Debug("Downloaded item processing failed", "number", results[index].Header.Number, "hash", results[index].Header.Hash(), "err", err) - return errInvalidChain + return fmt.Errorf("%w: %v", errInvalidChain, err) } return nil } diff --git a/eth/downloader/downloader_test.go b/eth/downloader/downloader_test.go index 4bdac2b9df..16bb2350ee 100644 --- a/eth/downloader/downloader_test.go +++ b/eth/downloader/downloader_test.go @@ -252,27 +252,32 @@ func (dl *downloadTester) GetTd(hash common.Hash, number uint64) *big.Int { func (dl *downloadTester) InsertHeaderChain(headers []*types.Header, checkFreq int, contiguousHeaders bool) (i int, err error) { dl.lock.Lock() defer dl.lock.Unlock() - // Do a quick check, as the blockchain.InsertHeaderChain doesn't insert anything in case of errors if _, ok := dl.ownHeaders[headers[0].ParentHash]; !ok { - return 0, errors.New("unknown parent") + return 0, errors.New("InsertHeaderChain: unknown parent at first position") } + var hashes []common.Hash for i := 1; i < len(headers); i++ { + hash := headers[i-1].Hash() if headers[i].ParentHash != headers[i-1].Hash() { - return i, errors.New("unknown parent") + return i, fmt.Errorf("non-contiguous import at position %d", i) } + hashes = append(hashes, hash) } + hashes = append(hashes, headers[len(headers)-1].Hash()) // Do a full insert if pre-checks passed for i, header := range headers { - if _, ok := dl.ownHeaders[header.Hash()]; ok { + hash := hashes[i] + if _, ok := dl.ownHeaders[hash]; ok { continue } if _, ok := dl.ownHeaders[header.ParentHash]; !ok { - return i, errors.New("unknown parent") + // This _should_ be impossible, due to precheck and induction + return i, fmt.Errorf("InsertHeaderChain: unknown parent at position %d", i) } - dl.ownHashes = append(dl.ownHashes, header.Hash()) - dl.ownHeaders[header.Hash()] = header - dl.ownChainTd[header.Hash()] = new(big.Int).Add(header.Number, big.NewInt(1)) + dl.ownHashes = append(dl.ownHashes, hash) + dl.ownHeaders[hash] = header + dl.ownChainTd[hash] = new(big.Int).Add(header.Number, big.NewInt(1)) } return len(headers), nil } @@ -284,9 +289,9 @@ func (dl *downloadTester) InsertChain(blocks types.Blocks) (i int, err error) { for i, block := range blocks { if parent, ok := dl.ownBlocks[block.ParentHash()]; !ok { - return i, errors.New("unknown parent") + return i, fmt.Errorf("InsertChain: unknown parent at position %d / %d", i, len(blocks)) } else if _, err := dl.stateDb.Get(parent.Root().Bytes()); err != nil { - return i, fmt.Errorf("unknown parent state %x: %v", parent.Root(), err) + return i, fmt.Errorf("InsertChain: unknown parent state %x: %v", parent.Root(), err) } if _, ok := dl.ownHeaders[block.Hash()]; !ok { dl.ownHashes = append(dl.ownHashes, block.Hash()) @@ -311,7 +316,7 @@ func (dl *downloadTester) InsertReceiptChain(blocks types.Blocks, receipts []typ } if _, ok := dl.ancientBlocks[blocks[i].ParentHash()]; !ok { if _, ok := dl.ownBlocks[blocks[i].ParentHash()]; !ok { - return i, errors.New("unknown parent") + return i, errors.New("InsertReceiptChain: unknown parent") } } if blocks[i].NumberU64() <= ancientLimit { diff --git a/eth/downloader/queue.go b/eth/downloader/queue.go index 2e5b205e74..6c7f0beaf1 100644 --- a/eth/downloader/queue.go +++ b/eth/downloader/queue.go @@ -510,7 +510,7 @@ func (q *queue) reserveHeaders(p *peerConnection, count int, taskPool map[common index := int(header.Number.Int64() - int64(q.resultOffset)) if index >= len(q.resultCache) || index < 0 { common.Report("index allocation went beyond available resultCache space") - return nil, false, errInvalidChain + return nil, false, fmt.Errorf("%w: index allocation went beyond available resultCache space", errInvalidChain) } if q.resultCache[index] == nil { components := 1 @@ -862,14 +862,16 @@ func (q *queue) deliver(id string, taskPool map[common.Hash]*types.Header, taskQ q.active.Signal() } // If none of the data was good, it's a stale delivery - switch { - case failure == nil || failure == errInvalidChain: + if failure == nil { + return accepted, nil + } + if errors.Is(failure, errInvalidChain) { return accepted, failure - case useful: + } + if useful { return accepted, fmt.Errorf("partial failure: %v", failure) - default: - return accepted, errStaleDelivery } + return accepted, fmt.Errorf("%w: %v", failure, errStaleDelivery) } // Prepare configures the result cache to allow accepting and caching inbound From 49c926790fd03a164119553f050d5c60ffd6d5b7 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Tue, 9 Jun 2020 11:39:19 +0200 Subject: [PATCH 13/15] pick --- eth/downloader/downloader_test.go | 23 ++++++++++++++++++----- miner/worker_test.go | 4 +--- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/eth/downloader/downloader_test.go b/eth/downloader/downloader_test.go index 16bb2350ee..9ad6ed4ead 100644 --- a/eth/downloader/downloader_test.go +++ b/eth/downloader/downloader_test.go @@ -154,7 +154,12 @@ func (dl *downloadTester) HasFastBlock(hash common.Hash, number uint64) bool { func (dl *downloadTester) GetHeaderByHash(hash common.Hash) *types.Header { dl.lock.RLock() defer dl.lock.RUnlock() + return dl.getHeaderByHash(hash) +} +// getHeaderByHash returns the header if found either within ancients or own blocks) +// This method assumes that the caller holds at least the read-lock (dl.lock) +func (dl *downloadTester) getHeaderByHash(hash common.Hash) *types.Header { header := dl.ancientHeaders[hash] if header != nil { return header @@ -242,6 +247,13 @@ func (dl *downloadTester) GetTd(hash common.Hash, number uint64) *big.Int { dl.lock.RLock() defer dl.lock.RUnlock() + return dl.getTd(hash) +} + +// getTd retrieves the block's total difficulty if found either within +// ancients or own blocks). +// This method assumes that the caller holds at least the read-lock (dl.lock) +func (dl *downloadTester) getTd(hash common.Hash) *big.Int { if td := dl.ancientChainTd[hash]; td != nil { return td } @@ -253,8 +265,8 @@ func (dl *downloadTester) InsertHeaderChain(headers []*types.Header, checkFreq i dl.lock.Lock() defer dl.lock.Unlock() // Do a quick check, as the blockchain.InsertHeaderChain doesn't insert anything in case of errors - if _, ok := dl.ownHeaders[headers[0].ParentHash]; !ok { - return 0, errors.New("InsertHeaderChain: unknown parent at first position") + if dl.getHeaderByHash(headers[0].ParentHash) == nil { + return 0, fmt.Errorf("InsertHeaderChain: unknown parent at first position, parent of number %d", headers[0].Number) } var hashes []common.Hash for i := 1; i < len(headers); i++ { @@ -268,15 +280,17 @@ func (dl *downloadTester) InsertHeaderChain(headers []*types.Header, checkFreq i // Do a full insert if pre-checks passed for i, header := range headers { hash := hashes[i] - if _, ok := dl.ownHeaders[hash]; ok { + if dl.getHeaderByHash(hash) != nil { continue } - if _, ok := dl.ownHeaders[header.ParentHash]; !ok { + if dl.getHeaderByHash(header.ParentHash) == nil { // This _should_ be impossible, due to precheck and induction return i, fmt.Errorf("InsertHeaderChain: unknown parent at position %d", i) } dl.ownHashes = append(dl.ownHashes, hash) dl.ownHeaders[hash] = header + + td := dl.getTd(header.ParentHash) dl.ownChainTd[hash] = new(big.Int).Add(header.Number, big.NewInt(1)) } return len(headers), nil @@ -286,7 +300,6 @@ func (dl *downloadTester) InsertHeaderChain(headers []*types.Header, checkFreq i func (dl *downloadTester) InsertChain(blocks types.Blocks) (i int, err error) { dl.lock.Lock() defer dl.lock.Unlock() - for i, block := range blocks { if parent, ok := dl.ownBlocks[block.ParentHash()]; !ok { return i, fmt.Errorf("InsertChain: unknown parent at position %d / %d", i, len(blocks)) diff --git a/miner/worker_test.go b/miner/worker_test.go index 5670e970cd..6cd7094267 100644 --- a/miner/worker_test.go +++ b/miner/worker_test.go @@ -305,9 +305,7 @@ func testEmptyWork(t *testing.T, chainConfig *params.ChainConfig, engine consens } w.skipSealHook = func(task *task) bool { return true } w.fullTaskHook = func() { - // Arch64 unit tests are running in a VM on travis, they must - // be given more time to execute. - time.Sleep(time.Second) + time.Sleep(100 * time.Millisecond) } w.start() // Start mining! expectedTasksLen := 1 From 6bc114c95220421147e121f10728493d9178031b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sami=20M=C3=A4kel=C3=A4?= Date: Thu, 15 Oct 2020 11:57:57 +0300 Subject: [PATCH 14/15] fix --- eth/downloader/downloader_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/eth/downloader/downloader_test.go b/eth/downloader/downloader_test.go index 9ad6ed4ead..a772e01e63 100644 --- a/eth/downloader/downloader_test.go +++ b/eth/downloader/downloader_test.go @@ -290,7 +290,6 @@ func (dl *downloadTester) InsertHeaderChain(headers []*types.Header, checkFreq i dl.ownHashes = append(dl.ownHashes, hash) dl.ownHeaders[hash] = header - td := dl.getTd(header.ParentHash) dl.ownChainTd[hash] = new(big.Int).Add(header.Number, big.NewInt(1)) } return len(headers), nil From 8befe8d1c850698f916bb89131ec304439429eca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sami=20M=C3=A4kel=C3=A4?= Date: Thu, 15 Oct 2020 12:41:54 +0300 Subject: [PATCH 15/15] fixed flaky test --- eth/downloader/downloader.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/eth/downloader/downloader.go b/eth/downloader/downloader.go index d1c3cf11ed..d31d5545a3 100644 --- a/eth/downloader/downloader.go +++ b/eth/downloader/downloader.go @@ -1617,6 +1617,8 @@ func (d *Downloader) processHeaders(origin uint64, pivot uint64, td *big.Int) er head := chunk[len(chunk)-1].Number.Uint64() if head-rollback > uint64(fsHeaderSafetyNet) { rollback = head - uint64(fsHeaderSafetyNet) + } else { + rollback = 1 } } // Unless we're doing light chains, schedule the headers for associated content retrieval