コード例 #1
0
        private void EnqueueJobs(NodeBlocksRepository repo, ChainBase chain, CloudBlockBlob blobLock, string lease)
        {
            int          cumul      = 0;
            ChainedBlock from       = chain.Genesis;
            int          blockCount = 0;

            foreach (var block in repo.GetBlocks(new[] { chain.Genesis }.Concat(chain.EnumerateAfter(chain.Genesis)).Where(c => c.Height % BlockGranularity == 0).Select(c => c.HashBlock), default(CancellationToken)))
            {
                cumul      += block.Transactions.Count * BlockGranularity;
                blockCount += BlockGranularity;
                if (cumul > TransactionsPerWork)
                {
                    var nextFrom = chain.GetBlock(chain.GetBlock(block.GetHash()).Height + BlockGranularity);
                    if (nextFrom == null)
                    {
                        break;
                    }
                    EnqueueRange(chain, from, blockCount);
                    from       = nextFrom;
                    blockCount = 0;
                    cumul      = 0;
                }
            }

            blockCount = (chain.Tip.Height - from.Height) + 1;
            EnqueueRange(chain, from, blockCount);

            var bytes = chain.Tip.GetLocator().ToBytes();

            blobLock.UploadText(Encoders.Hex.EncodeData(bytes), null, new AccessCondition()
            {
                LeaseId = lease
            });
        }
コード例 #2
0
        public static void UpdateChain(this IEnumerable <ChainBlockHeader> entries, ChainBase chain)
        {
            Stack <ChainBlockHeader> toApply = new Stack <ChainBlockHeader>();

            foreach (var entry in entries)
            {
                var prev = chain.GetBlock(entry.Header.HashPrevBlock);
                if (prev == null)
                {
                    toApply.Push(entry);
                }
                else
                {
                    toApply.Push(entry);
                    break;
                }
            }
            while (toApply.Count > 0)
            {
                var newTip = toApply.Pop();

                var chained = new ChainedBlock(newTip.Header, newTip.BlockId, chain.GetBlock(newTip.Header.HashPrevBlock));
                chain.SetTip(chained);
            }
        }
コード例 #3
0
        public static async Task UpdateChain(this IAsyncEnumerable <ChainBlockHeader> entries, ChainBase chain, CancellationToken cancellation = default(CancellationToken))
        {
            var enumerator = await entries.GetAsyncEnumeratorAsync(cancellation).ConfigureAwait(false);

            Stack <ChainBlockHeader> toApply = new Stack <ChainBlockHeader>();

            while (await enumerator.MoveNextAsync(cancellation).ConfigureAwait(false))
            {
                var entry = enumerator.Current;
                var prev  = chain.GetBlock(entry.Header.HashPrevBlock);
                if (prev == null)
                {
                    toApply.Push(entry);
                }
                else
                {
                    toApply.Push(entry);
                    break;
                }
            }
            while (toApply.Count > 0)
            {
                var newTip = toApply.Pop();

                var chained = new ChainedBlock(newTip.Header, newTip.BlockId, chain.GetBlock(newTip.Header.HashPrevBlock));
                chain.SetTip(chained);
            }
        }
コード例 #4
0
        public ChainedBlock GetChainedBlock(ChainBase chain)
        {
            ChainedBlock chainedBlock;

            if (Special != null && Special.Value == SpecialFeature.Last)
            {
                chainedBlock = chain.Tip;
            }
            else if (Height != -1)
            {
                var h = chain.GetBlock(Height);
                if (h == null)
                {
                    return(null);
                }
                chainedBlock = h;
            }
            else
            {
                chainedBlock = chain.GetBlock(BlockId);
            }
            if (chainedBlock != null)
            {
                var height = chainedBlock.Height + Offset;
                height       = Math.Max(0, height);
                chainedBlock = chain.GetBlock(height);
            }
            return(chainedBlock);
        }
コード例 #5
0
        public void SynchronizeChain(ChainBase chain)
        {
            Dictionary <uint256, Block>        blocks        = new Dictionary <uint256, Block>();
            Dictionary <uint256, ChainedBlock> chainedBlocks = new Dictionary <uint256, ChainedBlock>();
            HashSet <uint256> inChain = new HashSet <uint256>();

            inChain.Add(chain.GetBlock(0).HashBlock);
            chainedBlocks.Add(chain.GetBlock(0).HashBlock, chain.GetBlock(0));

            foreach (var block in this.Enumerate(false).Select(b => b.Item))
            {
                var hash = block.GetHash();
                blocks.Add(hash, block);
            }
            List <uint256> toRemove = new List <uint256>();

            while (blocks.Count != 0)
            {
                // to optimize keep a track of the last block
                ChainedBlock last = chain.GetBlock(0);
                foreach (var block in blocks)
                {
                    if (inChain.Contains(block.Value.Header.HashPrevBlock))
                    {
                        toRemove.Add(block.Key);
                        ChainedBlock chainedBlock;
                        if (last.HashBlock == block.Value.Header.HashPrevBlock)
                        {
                            chainedBlock = last;
                        }
                        else
                        {
                            if (!chainedBlocks.TryGetValue(block.Value.Header.HashPrevBlock, out chainedBlock))
                            {
                                break;
                            }
                        }
                        var chainedHeader = new ChainedBlock(block.Value.Header, block.Value.GetHash(), chainedBlock);
                        chain.SetTip(chainedHeader);
                        chainedBlocks.TryAdd(chainedHeader.HashBlock, chainedHeader);
                        inChain.Add(block.Key);
                        last = chainedHeader;
                    }
                }
                foreach (var item in toRemove)
                {
                    blocks.Remove(item);
                }
                if (toRemove.Count == 0)
                {
                    break;
                }
                toRemove.Clear();
            }
        }
コード例 #6
0
        public IEnumerator <BlockInfo> GetEnumerator()
        {
            Queue <DateTime> lastLogs    = new Queue <DateTime>();
            Queue <int>      lastHeights = new Queue <int>();

            var fork    = _BlockHeaders.FindFork(_Checkpoint.BlockLocator);
            var headers = _BlockHeaders.EnumerateAfter(fork);

            headers = headers.Where(h => h.Height <= ToHeight);
            var first = headers.FirstOrDefault();

            if (first == null)
            {
                yield break;
            }
            var height = first.Height;

            if (first.Height == 1)
            {
                headers = new[] { fork }.Concat(headers);
                height  = 0;
            }

            foreach (var block in _BlocksRepository.GetBlocks(headers.Select(b => b.HashBlock), CancellationToken))
            {
                var header = _BlockHeaders.GetBlock(height);

                if (block == null)
                {
                    var storeTip = _BlocksRepository.GetStoreTip();
                    if (storeTip != null)
                    {
                        // Store is caught up with Chain but the block is missing from the store.
                        if (header.Header.BlockTime <= storeTip.Header.BlockTime)
                        {
                            throw new InvalidOperationException($"Chained block not found in store (height = { height }). Re-create the block store.");
                        }
                    }
                    // Allow Store to catch up with Chain.
                    break;
                }

                _LastProcessed = header;
                yield return(new BlockInfo()
                {
                    Block = block,
                    BlockId = header.HashBlock,
                    Height = header.Height
                });

                IndexerTrace.Processed(height, Math.Min(ToHeight, _BlockHeaders.Tip.Height), lastLogs, lastHeights);
                height++;
            }
        }
コード例 #7
0
        public void SynchronizeChain(ChainBase chain)
        {
            Dictionary <uint256, BlockHeader> headers = new Dictionary <uint256, BlockHeader>();
            HashSet <uint256> inChain = new HashSet <uint256>();

            inChain.Add(chain.GetBlock(0).HashBlock);
            foreach (var header in Enumerate(true).Select(b => b.Item.Header))
            {
                var hash = header.GetHash();
                headers.Add(hash, header);
            }
            List <uint256> toRemove = new List <uint256>();

            while (headers.Count != 0)
            {
                foreach (var header in headers)
                {
                    if (inChain.Contains(header.Value.HashPrevBlock))
                    {
                        toRemove.Add(header.Key);
                        chain.SetTip(header.Value);
                        inChain.Add(header.Key);
                    }
                }
                foreach (var item in toRemove)
                {
                    headers.Remove(item);
                }
                if (toRemove.Count == 0)
                {
                    break;
                }
                toRemove.Clear();
            }
        }
コード例 #8
0
        public BalanceSheet(IEnumerable<OrderedBalanceChange> changes, ChainBase chain)
        {
            if (chain == null)
                throw new ArgumentNullException("chain");
            _Chain = chain;

            var all = changes
                        .Where(c => c.SpentCoins != null) //Remove line whose previous coins have not been loadedcould not be deduced
                        .Where(c => c.MempoolEntry || chain.GetBlock(c.BlockId) != null) //Take only mempool entry, or confirmed one
                        .Where(c => !(c.IsCoinbase && c.MempoolEntry)) //There is no such thing as a Coinbase unconfirmed, by definition a coinbase appear in a block
                        .ToList(); 
            var confirmed = all.Where(o => o.BlockId != null).ToDictionary(o => o.TransactionId);
            Dictionary<uint256, OrderedBalanceChange> unconfirmed = new Dictionary<uint256, OrderedBalanceChange>();

            foreach(var item in all.Where(o => o.MempoolEntry && !confirmed.ContainsKey(o.TransactionId)))
            {
                unconfirmed.AddOrReplace(item.TransactionId, item);
            }

            _Prunable = all.Where(o => o.BlockId == null && confirmed.ContainsKey(o.TransactionId)).ToList();
            _All = all.Where(o => 
                (unconfirmed.ContainsKey(o.TransactionId) || confirmed.ContainsKey(o.TransactionId)) 
                    &&
                    !(o.BlockId == null && confirmed.ContainsKey(o.TransactionId))
                ).ToList();
            _Confirmed = _All.Where(o => o.BlockId != null && confirmed.ContainsKey(o.TransactionId)).ToList();
            _Unconfirmed = _All.Where(o => o.BlockId == null && unconfirmed.ContainsKey(o.TransactionId)).ToList();
        }
コード例 #9
0
ファイル: Tracker.cs プロジェクト: zzms/NBitcoin
            public WalletTransaction ToWalletTransaction(ChainBase chain, string wallet)
            {
                var chainHeight = chain.Height;
                var tx          = new WalletTransaction()
                {
                    Proof           = Proof,
                    Transaction     = Transaction,
                    UnconfirmedSeen = UnconfirmedSeen,
                    AddedDate       = AddedDate
                };

                tx.ReceivedCoins = GetCoins(ReceivedCoins, _TrackedScripts, wallet);
                tx.SpentCoins    = GetCoins(SpentCoins, _TrackedScripts, wallet);

                if (BlockId != null)
                {
                    var header = chain.GetBlock(BlockId);
                    if (header != null)
                    {
                        tx.BlockInformation = new BlockInformation()
                        {
                            Confirmations = chainHeight - header.Height + 1,
                            Height        = header.Height,
                            Header        = header.Header
                        };
                    }
                }
                return(tx);
            }
コード例 #10
0
        internal void Index(ChainBase chain, int startHeight, CancellationToken cancellationToken = default(CancellationToken))
        {
            List <ChainPartEntry> entries = new List <ChainPartEntry>(((chain.Height - startHeight) / BlockHeaderPerRow) + 5);

            startHeight = startHeight - (startHeight % BlockHeaderPerRow);
            ChainPartEntry chainPart = null;

            for (int i = startHeight; i <= chain.Tip.Height; i++)
            {
                if (chainPart == null)
                {
                    chainPart = new ChainPartEntry()
                    {
                        ChainOffset = i
                    }
                }
                ;

                var block = chain.GetBlock(i);
                chainPart.BlockHeaders.Add(block.Header);
                if (chainPart.BlockHeaders.Count == BlockHeaderPerRow)
                {
                    entries.Add(chainPart);
                    chainPart = null;
                }
            }
            if (chainPart != null)
            {
                entries.Add(chainPart);
            }
            this.Index(entries, cancellationToken);
        }
コード例 #11
0
        public BalanceSheet(IEnumerable <OrderedBalanceChange> changes, ChainBase chain, bool colored)
        {
            if (chain == null)
            {
                throw new ArgumentNullException("chain");
            }
            _Chain = chain;

            var all = changes
                      .Where(c => c.SpentCoins != null)                                //Remove line whose previous coins have not been loaded
                      .Where(c => !colored || c.ColoredBalanceChangeEntry != null)     //Remove live whose color could not be deduced
                      .Where(c => c.MempoolEntry || chain.GetBlock(c.BlockId) != null) //Take only mempool entry, or confirmed one
                      .Where(c => !(c.IsCoinbase && c.MempoolEntry))                   //There is no such thing as a Coinbase unconfirmed, by definition a coinbase appear in a block
                      .ToList();
            var confirmed   = all.Where(o => o.BlockId != null).ToDictionary(o => o.TransactionId);
            var unconfirmed = all.Where(o => o.MempoolEntry && !confirmed.ContainsKey(o.TransactionId)).ToDictionary(o => o.TransactionId);

            _Prunable = all.Where(o => o.BlockId == null && confirmed.ContainsKey(o.TransactionId)).ToList();
            _All      = all.Where(o =>
                                  (unconfirmed.ContainsKey(o.TransactionId) || confirmed.ContainsKey(o.TransactionId))
                                  &&
                                  !(o.BlockId == null && confirmed.ContainsKey(o.TransactionId))
                                  ).ToList();
            _Confirmed   = _All.Where(o => o.BlockId != null && confirmed.ContainsKey(o.TransactionId)).ToList();
            _Unconfirmed = _All.Where(o => o.BlockId == null && unconfirmed.ContainsKey(o.TransactionId)).ToList();
        }
コード例 #12
0
        public static bool TryGetHeight(this ChainBase chain, uint256 blockId, out int height)
        {
            height = 0;
            var block = chain.GetBlock(blockId);

            if (block == null)
            {
                return(false);
            }
            height = block.Height;
            return(true);
        }
コード例 #13
0
        public IEnumerator <BlockInfo> GetEnumerator()
        {
            Queue <DateTime> lastLogs    = new Queue <DateTime>();
            Queue <int>      lastHeights = new Queue <int>();

            var fork = _BlockHeaders.FindFork(_Checkpoint.BlockLocator);

            _LastProcessed = fork;
            var headers = _BlockHeaders.EnumerateAfter(fork);

            headers = headers.Where(h => h.Height >= FromHeight && h.Height <= ToHeight);
            var first = headers.FirstOrDefault();

            if (first == null)
            {
                yield break;
            }
            var height = first.Height;

            if (first.Height == 1)
            {
                headers = new[] { fork }.Concat(headers);
                height  = 0;
            }

            foreach (var block in _BlocksRepository.GetBlocks(headers.Select(b => b.HashBlock), CancellationToken).TakeWhile(b => b != null))
            {
                var header = _BlockHeaders.GetBlock(height);
                _LastProcessed = header;
                yield return(new BlockInfo()
                {
                    Block = block,
                    BlockId = header.HashBlock,
                    Height = header.Height
                });

                IndexerTrace.Processed(height, Math.Min(ToHeight, _BlockHeaders.Tip.Height), lastLogs, lastHeights);
                height++;
            }
        }
コード例 #14
0
		public static void UpdateChain(this IEnumerable<ChainBlockHeader> entries, ChainBase chain)
		{
			Stack<ChainBlockHeader> toApply = new Stack<ChainBlockHeader>();
			foreach(var entry in entries)
			{
				var prev = chain.GetBlock(entry.Header.HashPrevBlock);
				if(prev == null)
					toApply.Push(entry);
				else
				{
					toApply.Push(entry);
					break;
				}
			}
			while(toApply.Count > 0)
			{
				var newTip = toApply.Pop();

				var chained = new ChainedBlock(newTip.Header, newTip.BlockId, chain.GetBlock(newTip.Header.HashPrevBlock));
				chain.SetTip(chained);
			}
		}
コード例 #15
0
ファイル: AzureIndexer.cs プロジェクト: w1r2p1/BlockExplorer
        public void IndexChain(ChainBase chain, CancellationToken cancellationToken = default(CancellationToken))
        {
            this.logger.LogTrace("()");

            if (chain == null)
            {
                throw new ArgumentNullException("chain");
            }
            this.SetThrottling();

            using (IndexerTrace.NewCorrelation("Index main chain to azure started"))
            {
                this.Configuration.GetChainTable().CreateIfNotExistsAsync().GetAwaiter().GetResult();
                IndexerTrace.InputChainTip(chain.Tip);
                var client  = this.Configuration.CreateIndexerClient();
                var changes = client.GetChainChangesUntilFork(chain.Tip, true, cancellationToken).ToList();

                var height = 0;
                if (changes.Count != 0)
                {
                    this.logger.LogTrace("Changes count: {0}", changes.Count);

                    IndexerTrace.IndexedChainTip(changes[0].BlockId, changes[0].Height);
                    if (changes[0].Height > chain.Tip.Height)
                    {
                        IndexerTrace.InputChainIsLate();

                        this.logger.LogTrace("(-):LATE");
                        return;
                    }
                    height = changes[changes.Count - 1].Height + 1;
                    if (height > chain.Height)
                    {
                        IndexerTrace.IndexedChainIsUpToDate(chain.Tip);

                        this.logger.LogTrace("(-):UP_TO_DATE");
                        return;
                    }
                }
                else
                {
                    this.logger.LogTrace("No work found");
                    IndexerTrace.NoForkFoundWithStored();
                }

                IndexerTrace.IndexingChain(chain.GetBlock(height), chain.Tip);
                this.Index(chain, height, cancellationToken);
            }

            this.logger.LogTrace("(-)");
        }
コード例 #16
0
        public BalanceOperation(OrderedBalanceChange balanceChange, ChainBase chain)
        {
            ReceivedCoins = balanceChange.ReceivedCoins.ToList();
            SpentCoins    = balanceChange.SpentCoins.ToList();
            Amount        = balanceChange.Amount;
            TransactionId = balanceChange.TransactionId;

            if (balanceChange.BlockId != null)
            {
                BlockId       = balanceChange.BlockId;
                Height        = chain.GetBlock(balanceChange.BlockId).Height;
                Confirmations = (chain.Tip.Height - Height) + 1;
            }
        }
コード例 #17
0
 public AnnotatedTransaction(TrackedTransaction tracked, ChainBase chain)
 {
     Record = tracked;
     if (tracked.BlockHash == null)
     {
         Type = AnnotatedTransactionType.Unconfirmed;
     }
     else
     {
         var block = chain.GetBlock(tracked.BlockHash);
         Type   = block == null ? AnnotatedTransactionType.Orphan : AnnotatedTransactionType.Confirmed;
         Height = block?.Height;
     }
 }
コード例 #18
0
 public PosBlockModel(Block block, ChainBase chain)
 {
     this.Hash              = block.GetHash().ToString();
     this.Size              = block.ToBytes().Length;
     this.Version           = block.Header.Version;
     this.Bits              = block.Header.Bits.ToCompact().ToString("x8");
     this.Time              = block.Header.BlockTime;
     this.Nonce             = block.Header.Nonce;
     this.PreviousBlockHash = block.Header.HashPrevBlock.ToString();
     this.MerkleRoot        = block.Header.HashMerkleRoot.ToString();
     this.Difficulty        = block.Header.Bits.Difficulty;
     this.Transactions      = block.Transactions.Select(trx => new TransactionVerboseModel(trx, chain.Network)).ToArray();
     this.Height            = chain.GetBlock(block.GetHash()).Height;
 }
コード例 #19
0
ファイル: Extensions.cs プロジェクト: w1r2p1/BlockExplorer
        private static bool IsMinConf(OrderedBalanceChange e, int minConfirmation, ChainBase chain)
        {
            if (e.BlockId == null)
            {
                return(minConfirmation == 0);
            }

            var b = chain.GetBlock(e.BlockId);

            if (b == null)
            {
                return(false);
            }
            return((chain.Height - b.Height) + 1 >= minConfirmation);
        }
コード例 #20
0
        /// <summary>
        /// Retrieves a transaction block given a valid hash.
        /// This function is used by other methods in this class and not explicitly by RPC/API.
        /// </summary>
        /// <param name="trxid">A valid uint256 hash</param>
        /// <param name="fullNode">The full node. Used to access <see cref="IBlockStore"/>.</param>
        /// <param name="chain">The full node's chain. Used to get <see cref="ChainedHeader"/> block.</param>
        /// <returns>A <see cref="ChainedHeader"/> for the given transaction hash. Returns <c>null</c> if fails.</returns>
        /// <exception cref="ArgumentNullException">Thrown if fullnode is not provided.</exception>
        internal static async Task <ChainedHeader> GetTransactionBlockAsync(uint256 trxid,
                                                                            IFullNode fullNode, ChainBase chain)
        {
            Guard.NotNull(fullNode, nameof(fullNode));

            ChainedHeader block      = null;
            var           blockStore = fullNode.NodeFeature <IBlockStore>();
            uint256       blockid    = blockStore != null ? await blockStore.GetBlockIdByTransactionIdAsync(trxid).ConfigureAwait(false) : null;

            if (blockid != null)
            {
                block = chain?.GetBlock(blockid);
            }

            return(block);
        }
コード例 #21
0
        public IEnumerator <BlockInfo> GetEnumerator()
        {
            Queue <DateTime> lastLogs    = new Queue <DateTime>();
            Queue <int>      lastHeights = new Queue <int>();

            var locator = DisableSaving ? new BlockLocator(new List <uint256>()
            {
                _Checkpoint.Genesis
            }) : _Checkpoint.BlockLocator;

            var fork    = _BlockHeaders.FindFork(locator);
            var headers = _BlockHeaders.EnumerateAfter(fork);

            headers = headers.Where(h => h.Height >= FromHeight && h.Height <= ToHeight);
            var first = headers.FirstOrDefault();

            if (first == null)
            {
                yield break;
            }
            var height = first.Height;

            if (first.Height == 1)
            {
                headers = new[] { fork }.Concat(headers);
                height  = 0;
            }

            foreach (var block in _Node.GetBlocks(headers.Select(b => b.HashBlock)))
            {
                var header = _BlockHeaders.GetBlock(height);
                _LastProcessed = header;
                yield return(new BlockInfo()
                {
                    Block = block,
                    BlockId = header.HashBlock,
                    Height = header.Height
                });

                IndexerTrace.Processed(height, Math.Min(ToHeight, _BlockHeaders.Tip.Height), lastLogs, lastHeights);
                height++;
            }
        }
コード例 #22
0
ファイル: BlockStore.cs プロジェクト: glasgowdev/purple
        public void SynchronizeChain(ChainBase chain)
        {
            var headers = new Dictionary <uint256, BlockHeader>();
            var inChain = new HashSet <uint256>();

            inChain.Add(chain.GetBlock(0).HashBlock);

            foreach (BlockHeader header in Enumerate(true).Select(b => b.Item.Header))
            {
                uint256 hash = header.GetHash(this.Network.NetworkOptions);
                headers.Add(hash, header);
            }

            var toRemove = new List <uint256>();

            while (headers.Any())
            {
                foreach (KeyValuePair <uint256, BlockHeader> header in headers)
                {
                    if (inChain.Contains(header.Value.HashPrevBlock))
                    {
                        toRemove.Add(header.Key);
                        chain.SetTip(header.Value);
                        inChain.Add(header.Key);
                    }
                }

                foreach (uint256 item in toRemove)
                {
                    headers.Remove(item);
                }

                if (!toRemove.Any())
                {
                    break;
                }

                toRemove.Clear();
            }
        }
コード例 #23
0
        public void IndexChain(ChainBase chain)
        {
            if (chain == null)
            {
                throw new ArgumentNullException("chain");
            }
            SetThrottling();

            using (IndexerTrace.NewCorrelation("Index main chain to azure started"))
            {
                Configuration.GetChainTable().CreateIfNotExistsAsync().GetAwaiter().GetResult();
                IndexerTrace.InputChainTip(chain.Tip);
                var client  = Configuration.CreateIndexerClient();
                var changes = client.GetChainChangesUntilFork(chain.Tip, true).ToList();

                var height = 0;
                if (changes.Count != 0)
                {
                    IndexerTrace.IndexedChainTip(changes[0].BlockId, changes[0].Height);
                    if (changes[0].Height > chain.Tip.Height)
                    {
                        IndexerTrace.InputChainIsLate();
                        return;
                    }
                    height = changes[changes.Count - 1].Height + 1;
                    if (height > chain.Height)
                    {
                        IndexerTrace.IndexedChainIsUpToDate(chain.Tip);
                        return;
                    }
                }
                else
                {
                    IndexerTrace.NoForkFoundWithStored();
                }

                IndexerTrace.IndexingChain(chain.GetBlock(height), chain.Tip);
                Index(chain, height);
            }
        }
コード例 #24
0
        static void Main(string[] args)
        {
            try
            {
                var options = new IndexerOptions();
                if (args.Length == 0)
                {
                    System.Console.WriteLine(options.GetUsage());
                }
                if (Parser.Default.ParseArguments(args, options))
                {
                    System.Console.WriteLine("NBitcoin.Indexer " + typeof(AzureIndexer).Assembly.GetName().Version);

                    if (options.All)
                    {
                        options.IndexAddresses    = true;
                        options.IndexBlocks       = true;
                        options.IndexWallets      = true;
                        options.IndexChain        = true;
                        options.IndexTransactions = true;
                    }

                    var indexer = AzureIndexer.CreateIndexer();
                    indexer.Configuration.EnsureSetup();
                    indexer.TaskScheduler      = new CustomThreadPoolTaskScheduler(30, 100);
                    indexer.CheckpointInterval = TimeSpan.Parse(options.CheckpointInterval);
                    indexer.IgnoreCheckpoints  = options.IgnoreCheckpoints;
                    indexer.FromHeight         = options.From;
                    indexer.ToHeight           = options.To;

                    ChainBase chain = null;
                    var       checkpointRepository = indexer.GetCheckpointRepository();
                    checkpointRepository.CheckpointSet = null;
                    if (options.ListCheckpoints)
                    {
                        foreach (var checkpoint in checkpointRepository.GetCheckpointsAsync().Result)
                        {
                            chain = chain ?? indexer.GetNodeChain();
                            var fork = chain.FindFork(checkpoint.BlockLocator);
                            System.Console.WriteLine("Name : " + checkpoint.CheckpointName);
                            if (fork != null)
                            {
                                System.Console.WriteLine("Height : " + fork.Height);
                                System.Console.WriteLine("Hash : " + fork.HashBlock);
                            }
                            System.Console.WriteLine();
                        }
                    }
                    if (options.DeleteCheckpoint != null)
                    {
                        checkpointRepository.GetCheckpoint(options.DeleteCheckpoint).DeleteAsync().Wait();
                        System.Console.WriteLine("Checkpoint " + options.DeleteCheckpoint + " deleted");
                    }
                    if (options.AddCheckpoint != null)
                    {
                        chain = chain ?? indexer.GetNodeChain();
                        var split  = options.AddCheckpoint.Split(':');
                        var name   = split[0];
                        var height = int.Parse(split[1]);
                        var b      = chain.GetBlock(height);

                        var checkpoint = checkpointRepository.GetCheckpoint(name);
                        checkpoint.SaveProgress(b.GetLocator());
                        System.Console.WriteLine("Checkpoint " + options.AddCheckpoint + " saved to height " + b.Height);
                    }
                    if (ConfigurationManager.AppSettings["MainDirectory"] != null)
                    {
                        System.Console.WriteLine("Warning : obsolete appsetting detected, MainDirectory");
                        string[] oldCheckpoints = new string[] { "transactions", "blocks", "wallets", "balances" };
                        foreach (var chk in oldCheckpoints)
                        {
                            var path = GetFilePath(indexer.Configuration, chk);
                            if (File.Exists(path))
                            {
                                var onlineCheckpoint = checkpointRepository.GetCheckpointsAsync().Result.FirstOrDefault(r => r.CheckpointName.ToLowerInvariant() == chk);
                                if (onlineCheckpoint == null)
                                {
                                    onlineCheckpoint = checkpointRepository.GetCheckpoint(indexer.Configuration.CheckpointSetName + "/" + chk);
                                    BlockLocator offlineLocator = new BlockLocator();
                                    offlineLocator.FromBytes(File.ReadAllBytes(path));
                                    onlineCheckpoint.SaveProgress(offlineLocator);
                                    System.Console.WriteLine("Local checkpoint " + chk + " saved in azure");
                                }
                                File.Delete(path);
                                System.Console.WriteLine("Checkpoint File deleted " + path);
                            }
                        }
                    }


                    if (options.IndexBlocks)
                    {
                        chain = chain ?? indexer.GetNodeChain();
                        indexer.IndexBlocks(chain);
                    }
                    if (options.IndexTransactions)
                    {
                        chain = chain ?? indexer.GetNodeChain();
                        indexer.IndexTransactions(chain);
                    }
                    if (options.IndexAddresses)
                    {
                        chain = chain ?? indexer.GetNodeChain();
                        indexer.IndexOrderedBalances(chain);
                    }
                    if (options.IndexWallets)
                    {
                        chain = chain ?? indexer.GetNodeChain();
                        indexer.IndexWalletBalances(chain);
                    }
                    if (options.IndexChain)
                    {
                        chain = chain ?? indexer.GetNodeChain();
                        indexer.IndexChain(chain);
                    }
                }
            }
            catch (ConfigurationErrorsException ex)
            {
                System.Console.WriteLine("LocalSettings.config missing settings : " + ex.Message);
            }
        }
コード例 #25
0
        internal void Index(ChainBase chain, int startHeight)
        {
            List<ChainPartEntry> entries = new List<ChainPartEntry>(((chain.Height - startHeight) / BlockHeaderPerRow) + 5);
            startHeight = startHeight - (startHeight % BlockHeaderPerRow);
            ChainPartEntry chainPart = null;
            for(int i = startHeight; i <= chain.Tip.Height; i++)
            {
                if(chainPart == null)
                    chainPart = new ChainPartEntry()
                    {
                        ChainOffset = i
                    };

                var block = chain.GetBlock(i);
                chainPart.BlockHeaders.Add(block.Header);
                if(chainPart.BlockHeaders.Count == BlockHeaderPerRow)
                {
                    entries.Add(chainPart);
                    chainPart = null;
                }
            }
            if(chainPart != null)
                entries.Add(chainPart);
            Index(entries);
        }
コード例 #26
0
        public void IndexChain(ChainBase chain)
        {
            if(chain == null)
                throw new ArgumentNullException("chain");
            SetThrottling();

            using(IndexerTrace.NewCorrelation("Index main chain to azure started").Open())
            {
                Configuration.GetChainTable().CreateIfNotExists();
                IndexerTrace.InputChainTip(chain.Tip);
                var client = Configuration.CreateIndexerClient();
                var changes = client.GetChainChangesUntilFork(chain.Tip, true).ToList();

                var height = 0;
                if(changes.Count != 0)
                {
                    IndexerTrace.IndexedChainTip(changes[0].BlockId, changes[0].Height);
                    if(changes[0].Height > chain.Tip.Height)
                    {
                        IndexerTrace.InputChainIsLate();
                        return;
                    }
                    height = changes[changes.Count - 1].Height + 1;
                    if(height > chain.Height)
                    {
                        IndexerTrace.IndexedChainIsUpToDate(chain.Tip);
                        return;
                    }
                }
                else
                {
                    IndexerTrace.NoForkFoundWithStored();
                }

                IndexerTrace.IndexingChain(chain.GetBlock(height), chain.Tip);
                Index(chain, height);

            }
        }
コード例 #27
0
        public bool Process(ChainBase mainChain, IBlockProvider blockProvider)
        {
            var chainCopy       = Chain.Clone();
            var chainPosition   = chainCopy.Changes.Position;
            var accountCopy     = Account.Clone();
            var accountPosition = accountCopy.Entries.Position;

            bool newChain = false;

            if (!chainCopy.Initialized)
            {
                newChain = true;

                var firstBlock = mainChain.GetBlock(StartHeight);
                chainCopy.Initialize(firstBlock.Header, StartHeight);
            }
            var forkBlock = mainChain.FindFork(chainCopy);

            if (forkBlock.HashBlock != chainCopy.Tip.HashBlock)
            {
                var subChain = chainCopy.CreateSubChain(forkBlock, false, chainCopy.Tip, true);
                chainCopy.SetTip(chainCopy.GetBlock(forkBlock.Height));
                foreach (var e in accountCopy.GetInChain(subChain, true)
                         .Where(c => c.Reason != AccountEntryReason.Lock && c.Reason != AccountEntryReason.Unlock)
                         .Reverse())
                {
                    var neutralized = e.Neutralize();
                    accountCopy.PushAccountEntry(neutralized);
                }
            }

            var unprocessedBlocks = mainChain.ToEnumerable(true)
                                    .TakeWhile(block => block != forkBlock)
                                    .Concat(newChain ? new ChainedBlock[] { forkBlock } : new ChainedBlock[0])
                                    .Reverse().ToArray();

            foreach (var block in unprocessedBlocks)
            {
                List <byte[]> searchedData = new List <byte[]>();
                Scanner.GetScannedPushData(searchedData);
                foreach (var unspent in accountCopy.Unspent)
                {
                    searchedData.Add(unspent.OutPoint.ToBytes());
                }

                var fullBlock = blockProvider.GetBlock(block.HashBlock, searchedData);
                if (fullBlock == null)
                {
                    continue;
                }

                List <Tuple <OutPoint, AccountEntry> > spents = new List <Tuple <OutPoint, AccountEntry> >();
                foreach (var spent in FindSpent(fullBlock, accountCopy.Unspent))
                {
                    var entry = new AccountEntry(AccountEntryReason.Outcome,
                                                 block.HashBlock,
                                                 spent.Spendable, -spent.Spendable.TxOut.Value, spent.TxId);
                    spents.Add(Tuple.Create(entry.Spendable.OutPoint, entry));
                }

                if (CheckDoubleSpend)
                {
                    var spentsDico = spents.ToDictionary(t => t.Item1, t => t.Item2);
                    foreach (var spent in Scanner.FindSpent(fullBlock))
                    {
                        if (!spentsDico.ContainsKey(spent.PrevOut))
                        {
                            return(false);
                        }
                    }
                }

                foreach (var spent in spents)
                {
                    if (accountCopy.PushAccountEntry(spent.Item2) == null)
                    {
                        return(false);
                    }
                }

                foreach (var coins in Scanner.ScanCoins(fullBlock, (int)block.Height))
                {
                    int i = 0;
                    foreach (var output in coins.Coins.Outputs)
                    {
                        if (!output.IsNull)
                        {
                            var entry = new AccountEntry(AccountEntryReason.Income, block.HashBlock,
                                                         new Spendable(new OutPoint(coins.TxId, i), output), output.Value, null);
                            if (accountCopy.PushAccountEntry(entry) == null)
                            {
                                return(false);
                            }
                        }
                        i++;
                    }
                }

                chainCopy.SetTip(block);
            }

            accountCopy.Entries.GoTo(accountPosition);
            Account.PushAccountEntries(accountCopy.Entries);

            chainCopy.Changes.GoTo(chainPosition);
            Chain.PushChanges(chainCopy.Changes);
            return(true);
        }
コード例 #28
0
ファイル: Tracker.cs プロジェクト: xcrash/NBitcoin
			public WalletTransaction ToWalletTransaction(ChainBase chain, ConcurrentDictionary<string, TrackedScript> trackedScripts, string wallet)
			{
				var chainHeight = chain.Height;
				var tx = new WalletTransaction()
				{
					Proof = Proof,
					Transaction = Transaction,
					UnconfirmedSeen = UnconfirmedSeen,
					AddedDate = AddedDate
				};

				tx.ReceivedCoins = GetCoins(ReceivedCoins, trackedScripts, wallet);
				tx.SpentCoins = GetCoins(SpentCoins, trackedScripts, wallet);

				if(BlockId != null)
				{
					var header = chain.GetBlock(BlockId);
					if(header != null)
					{
						tx.BlockInformation = new BlockInformation()
						{
							Confirmations = chainHeight - header.Height + 1,
							Height = header.Height,
							Header = header.Header
						};
					}
				}
				return tx;
			}