Ejemplo n.º 1
0
        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);
        }