internal bool Synchronize(ChainedHeader newTip) { if (newTip?.HashBlock == this.PollsRepository.CurrentTip?.Hash) { return(true); } ChainedHeader repoTip = GetPollsRepositoryTip(); bool bSuccess = true; this.PollsRepository.Synchronous(() => { // Remove blocks as required. if (repoTip != null) { ChainedHeader fork = repoTip.FindFork(newTip); if (repoTip.Height > fork.Height) { this.PollsRepository.WithTransaction(transaction => { List <IFederationMember> modifiedFederation = this.GetFederationAtPollsRepositoryTip(repoTip); for (ChainedHeader header = repoTip; header.Height > fork.Height; header = header.Previous) { Block block = this.blockRepository.GetBlock(header.HashBlock); this.UnProcessBlock(transaction, new ChainedHeaderBlock(block, header)); } transaction.Commit(); }); repoTip = fork; } } // Add blocks as required. var headers = new List <ChainedHeader>(); for (int height = (repoTip?.Height ?? 0) + 1; height <= newTip.Height; height++) { ChainedHeader header = this.chainIndexer.GetHeader(height); headers.Add(header); } if (headers.Count > 0) { DBreeze.Transactions.Transaction currentTransaction = this.PollsRepository.GetTransaction(); int i = 0; foreach (Block block in this.blockRepository.EnumerateBatch(headers)) { if (this.nodeLifetime.ApplicationStopping.IsCancellationRequested) { this.logger.LogTrace("(-)[NODE_DISPOSED]"); this.PollsRepository.SaveCurrentTip(currentTransaction); currentTransaction.Commit(); currentTransaction.Dispose(); bSuccess = false; return; } ChainedHeader header = headers[i++]; this.ProcessBlock(currentTransaction, new ChainedHeaderBlock(block, header)); if (header.Height % 10000 == 0) { var progress = (int)((decimal)header.Height / this.chainIndexer.Tip.Height * 100); var progressString = $"Synchronizing voting data at height {header.Height} / {this.chainIndexer.Tip.Height} ({progress} %)."; this.logger.LogInformation(progressString); this.signals.Publish(new FullNodeEvent() { Message = progressString, State = FullNodeState.Initializing.ToString() }); this.PollsRepository.SaveCurrentTip(currentTransaction); currentTransaction.Commit(); currentTransaction.Dispose(); currentTransaction = this.PollsRepository.GetTransaction(); } } // If we ended the synchronization at say block 10100, the current transaction would still be open and // thus we need to commit and dispose of it. // If we ended at block 10000, then the current transaction would have been committed and // disposed and re-opened. this.PollsRepository.SaveCurrentTip(currentTransaction); currentTransaction.Commit(); currentTransaction.Dispose(); } }); return(bSuccess); }