@@ -1391,17 +1391,21 @@ func (bc *BlockChain) insertSidechain(block *types.Block, it *insertIterator) (i
13911391 return 0 , nil , nil , nil
13921392}
13931393
1394- // reorgs takes two blocks, an old chain and a new chain and will reconstruct the blocks and inserts them
1395- // to be part of the new canonical chain and accumulates potential missing transactions and post an
1396- // event about them
1394+ // reorg takes two blocks, an old chain and a new chain and will reconstruct the
1395+ // blocks and inserts them to be part of the new canonical chain and accumulates
1396+ // potential missing transactions and post an event about them.
13971397func (bc * BlockChain ) reorg (oldBlock , newBlock * types.Block ) error {
13981398 var (
13991399 newChain types.Blocks
14001400 oldChain types.Blocks
14011401 commonBlock * types.Block
1402- deletedTxs types.Transactions
1402+
1403+ deletedTxs types.Transactions
1404+ addedTxs types.Transactions
1405+
14031406 deletedLogs []* types.Log
14041407 rebirthLogs []* types.Log
1408+
14051409 // collectLogs collects the logs that were generated during the
14061410 // processing of the block that corresponds with the given hash.
14071411 // These logs are later announced as deleted or reborn
@@ -1424,46 +1428,49 @@ func (bc *BlockChain) reorg(oldBlock, newBlock *types.Block) error {
14241428 }
14251429 }
14261430 )
1427-
1428- // first reduce whoever is higher bound
1431+ // Reduce the longer chain to the same number as the shorter one
14291432 if oldBlock .NumberU64 () > newBlock .NumberU64 () {
1430- // reduce old chain
1433+ // Old chain is longer, gather all transactions and logs as deleted ones
14311434 for ; oldBlock != nil && oldBlock .NumberU64 () != newBlock .NumberU64 (); oldBlock = bc .GetBlock (oldBlock .ParentHash (), oldBlock .NumberU64 ()- 1 ) {
14321435 oldChain = append (oldChain , oldBlock )
14331436 deletedTxs = append (deletedTxs , oldBlock .Transactions ()... )
1434-
14351437 collectLogs (oldBlock .Hash (), true )
14361438 }
14371439 } else {
1438- // reduce new chain and append new chain blocks for inserting later on
1440+ // New chain is longer, stash all blocks away for subsequent insertion
14391441 for ; newBlock != nil && newBlock .NumberU64 () != oldBlock .NumberU64 (); newBlock = bc .GetBlock (newBlock .ParentHash (), newBlock .NumberU64 ()- 1 ) {
14401442 newChain = append (newChain , newBlock )
14411443 }
14421444 }
14431445 if oldBlock == nil {
1444- return fmt .Errorf ("Invalid old chain" )
1446+ return fmt .Errorf ("invalid old chain" )
14451447 }
14461448 if newBlock == nil {
1447- return fmt .Errorf ("Invalid new chain" )
1449+ return fmt .Errorf ("invalid new chain" )
14481450 }
1449-
1451+ // Both sides of the reorg are at the same number, reduce both until the common
1452+ // ancestor is found
14501453 for {
1454+ // If the common ancestor was found, bail out
14511455 if oldBlock .Hash () == newBlock .Hash () {
14521456 commonBlock = oldBlock
14531457 break
14541458 }
1455-
1459+ // Remove an old block as well as stash away a new block
14561460 oldChain = append (oldChain , oldBlock )
1457- newChain = append (newChain , newBlock )
14581461 deletedTxs = append (deletedTxs , oldBlock .Transactions ()... )
14591462 collectLogs (oldBlock .Hash (), true )
14601463
1461- oldBlock , newBlock = bc .GetBlock (oldBlock .ParentHash (), oldBlock .NumberU64 ()- 1 ), bc .GetBlock (newBlock .ParentHash (), newBlock .NumberU64 ()- 1 )
1464+ newChain = append (newChain , newBlock )
1465+
1466+ // Step back with both chains
1467+ oldBlock = bc .GetBlock (oldBlock .ParentHash (), oldBlock .NumberU64 ()- 1 )
14621468 if oldBlock == nil {
1463- return fmt .Errorf ("Invalid old chain" )
1469+ return fmt .Errorf ("invalid old chain" )
14641470 }
1471+ newBlock = bc .GetBlock (newBlock .ParentHash (), newBlock .NumberU64 ()- 1 )
14651472 if newBlock == nil {
1466- return fmt .Errorf ("Invalid new chain" )
1473+ return fmt .Errorf ("invalid new chain" )
14671474 }
14681475 }
14691476 // Ensure the user sees large reorgs
@@ -1478,42 +1485,46 @@ func (bc *BlockChain) reorg(oldBlock, newBlock *types.Block) error {
14781485 log .Error ("Impossible reorg, please file an issue" , "oldnum" , oldBlock .Number (), "oldhash" , oldBlock .Hash (), "newnum" , newBlock .Number (), "newhash" , newBlock .Hash ())
14791486 }
14801487 // Insert the new chain, taking care of the proper incremental order
1481- var addedTxs types.Transactions
14821488 for i := len (newChain ) - 1 ; i >= 0 ; i -- {
1483- // insert the block in the canonical way, re-writing history
1489+ // Insert the block in the canonical way, re-writing history
14841490 bc .insert (newChain [i ])
1485- // collect reborn logs due to chain reorg(except head block)
1491+
1492+ // Collect reborn logs due to chain reorg (except head block (reverse order))
14861493 if i != 0 {
14871494 collectLogs (newChain [i ].Hash (), false )
14881495 }
1489- // write lookup entries for hash based transaction/receipt searches
1496+ // Write lookup entries for hash based transaction/receipt searches
14901497 rawdb .WriteTxLookupEntries (bc .db , newChain [i ])
14911498 addedTxs = append (addedTxs , newChain [i ].Transactions ()... )
14921499 }
1493- // calculate the difference between deleted and added transactions
1494- diff := types .TxDifference (deletedTxs , addedTxs )
1495- // When transactions get deleted from the database that means the
1496- // receipts that were created in the fork must also be deleted
1500+ // When transactions get deleted from the database, the receipts that were
1501+ // created in the fork must also be deleted
14971502 batch := bc .db .NewBatch ()
1498- for _ , tx := range diff {
1503+ for _ , tx := range types . TxDifference ( deletedTxs , addedTxs ) {
14991504 rawdb .DeleteTxLookupEntry (batch , tx .Hash ())
15001505 }
15011506 batch .Write ()
15021507
1503- if len (deletedLogs ) > 0 {
1504- go bc .rmLogsFeed .Send (RemovedLogsEvent {deletedLogs })
1505- }
1506- if len (rebirthLogs ) > 0 {
1507- go bc .logsFeed .Send (rebirthLogs )
1508- }
1509- if len (oldChain ) > 0 {
1510- go func () {
1508+ // If any logs need to be fired, do it now. In theory we could avoid creating
1509+ // this goroutine if there are no events to fire, but realistcally that only
1510+ // ever happens if we're reorging empty blocks, which will only happen on idle
1511+ // networks where performance is not an issue either way.
1512+ //
1513+ // TODO(karalabe): Can we get rid of the goroutine somehow to guarantee correct
1514+ // event ordering?
1515+ go func () {
1516+ if len (deletedLogs ) > 0 {
1517+ bc .rmLogsFeed .Send (RemovedLogsEvent {deletedLogs })
1518+ }
1519+ if len (rebirthLogs ) > 0 {
1520+ bc .logsFeed .Send (rebirthLogs )
1521+ }
1522+ if len (oldChain ) > 0 {
15111523 for _ , block := range oldChain {
15121524 bc .chainSideFeed .Send (ChainSideEvent {Block : block })
15131525 }
1514- }()
1515- }
1516-
1526+ }
1527+ }()
15171528 return nil
15181529}
15191530
0 commit comments