insertChain will execute the actual chain insertion and event aggregation. The only reason this method exists as a separate one is to make locking cleaner with deferred statements.
(chain types.Blocks)
| 1302 | // only reason this method exists as a separate one is to make locking cleaner |
| 1303 | // with deferred statements. |
| 1304 | func (bc *BlockChain) insertChain(chain types.Blocks) (int, []interface{}, []*types.Log, error) { |
| 1305 | // Sanity check that we have something meaningful to import |
| 1306 | if len(chain) == 0 { |
| 1307 | return 0, nil, nil, nil |
| 1308 | } |
| 1309 | // Do a sanity check that the provided chain is actually ordered and linked |
| 1310 | for i := 1; i < len(chain); i++ { |
| 1311 | if chain[i].NumberU64() != chain[i-1].NumberU64()+1 || chain[i].ParentHash() != chain[i-1].Hash() { |
| 1312 | // Chain broke ancestry, log a messge (programming error) and skip insertion |
| 1313 | log.Error("Non contiguous block insert", "number", chain[i].Number(), "hash", chain[i].Hash().Hex(), |
| 1314 | "parent", chain[i].ParentHash().Hex(), "prevnumber", chain[i-1].Number(), "prevhash", chain[i-1].Hash().Hex()) |
| 1315 | return 0, nil, nil, ErrInvalidChain |
| 1316 | } |
| 1317 | } |
| 1318 | |
| 1319 | bc.chainmu.Lock() |
| 1320 | defer bc.chainmu.Unlock() |
| 1321 | |
| 1322 | // A queued approach to delivering events. This is generally |
| 1323 | // faster than direct delivery and requires much less mutex |
| 1324 | // acquiring. |
| 1325 | var ( |
| 1326 | stats = insertStats{startTime: mclock.Now()} |
| 1327 | events = make([]interface{}, 0, len(chain)) |
| 1328 | lastCanon *types.Block |
| 1329 | coalescedLogs []*types.Log |
| 1330 | ) |
| 1331 | // Start the parallel header verifier |
| 1332 | headers := make([]*types.Header, len(chain)) |
| 1333 | refHeaders := make([]*types.Header, len(chain)) |
| 1334 | verifySigs := make([]bool, len(chain)) |
| 1335 | |
| 1336 | for i, block := range chain { |
| 1337 | headers[i] = block.Header() |
| 1338 | refHeaders[i] = block.RefHeader() |
| 1339 | verifySigs[i] = true |
| 1340 | } |
| 1341 | abort, results := bc.engine.VerifyHeaders(bc, headers, verifySigs, refHeaders) |
| 1342 | defer close(abort) |
| 1343 | |
| 1344 | // Start a parallel signature recovery (signer will fluke on fork transition, minimal perf loss) |
| 1345 | senderCacher.recoverFromBlocks(types.MakeSigner(bc.chainConfig), chain) |
| 1346 | |
| 1347 | // Iterate over the blocks and insert when the verifier permits |
| 1348 | for i, block := range chain { |
| 1349 | // update known head if it is necessary |
| 1350 | _, headN := bc.KnownHead() |
| 1351 | |
| 1352 | if bc.CurrentBlock() != nil && bc.CurrentBlock().NumberU64() > headN { |
| 1353 | bc.SetKnownHead(bc.CurrentBlock().Hash(), bc.CurrentBlock().NumberU64()) |
| 1354 | } |
| 1355 | |
| 1356 | // If the chain is terminating, stop processing blocks |
| 1357 | if atomic.LoadInt32(&bc.procInterrupt) == 1 { |
| 1358 | log.Debug("Premature abort during blocks processing") |
| 1359 | break |
| 1360 | } |
| 1361 | // If the header is a banned one, straight out abort |
no test coverage detected