InsertChain attempts to insert the given batch of blocks in to the canonical chain or, otherwise, create a fork. If an error is returned it will return the index number of the failing block as well an error describing what went wrong. After insertion is done, all accumulated events will be fired.
(chain types.Blocks)
| 1180 | // |
| 1181 | // After insertion is done, all accumulated events will be fired. |
| 1182 | func (bc *BlockChain) InsertChain(chain types.Blocks) (int, error) { |
| 1183 | bc.insertChainProtectLock.Lock() |
| 1184 | defer bc.insertChainProtectLock.Unlock() |
| 1185 | |
| 1186 | // do not stop blockchain if the insertion is not finished |
| 1187 | bc.wg.Add(1) |
| 1188 | defer bc.wg.Done() |
| 1189 | |
| 1190 | if len(chain) == 0 { |
| 1191 | return 0, nil |
| 1192 | } |
| 1193 | |
| 1194 | var ( |
| 1195 | last = chain[len(chain)-1].NumberU64() |
| 1196 | current = bc.CurrentBlock().NumberU64() |
| 1197 | ) |
| 1198 | |
| 1199 | // if the last block is already in local chain, return early |
| 1200 | if last <= current { |
| 1201 | return len(chain), nil |
| 1202 | } |
| 1203 | |
| 1204 | // find the first block that is not in local chain |
| 1205 | var outset int |
| 1206 | for index, block := range chain { |
| 1207 | if block.NumberU64() > current { |
| 1208 | outset = index |
| 1209 | break |
| 1210 | } |
| 1211 | } |
| 1212 | |
| 1213 | // remove useless prefix |
| 1214 | chain = chain[outset:] |
| 1215 | |
| 1216 | if bc.mux != nil { |
| 1217 | bc.mux.Post(InsertionStartEvent{}) |
| 1218 | log.Debug("posted InsertionStartEvent when inserting blocks") |
| 1219 | |
| 1220 | defer func() { |
| 1221 | bc.mux.Post(InsertionDoneEvent{}) |
| 1222 | log.Debug("posted InsertionDoneEvent when inserted blocks") |
| 1223 | }() |
| 1224 | } |
| 1225 | |
| 1226 | _, headN := bc.KnownHead() |
| 1227 | |
| 1228 | // if the first item in the chain is in range (head-pivot, head), insert one by one. |
| 1229 | if headN < configs.DefaultFullSyncPivot || chain[len(chain)-1].NumberU64() > headN-configs.DefaultFullSyncPivot { |
| 1230 | |
| 1231 | rN, rErr := 0, error(nil) |
| 1232 | |
| 1233 | for iter := 0; iter < len(chain); iter++ { |
| 1234 | n, events, logs, err := bc.insertChain(chain[iter : iter+1]) |
| 1235 | |
| 1236 | rN, rErr = rN+n, err |
| 1237 | |
| 1238 | bc.CommitStateDB() |
| 1239 | bc.PostChainEvents(events, logs) |