示例#1
0
        private ScannedItems GetScannedItems(ScanUTXOWorkItem workItem, ScanUTXOProgress progress)
        {
            var items = new ScannedItems();
            var derivationStrategy = workItem.DerivationStrategy;

            foreach (var feature in workItem.Options.DerivationFeatures)
            {
                var path           = DerivationStrategyBase.GetKeyPath(feature);
                var lineDerivation = workItem.DerivationStrategy.DerivationStrategy.GetLineFor(feature);
                Enumerable.Range(progress.From, progress.Count)
                .Select(index =>
                {
                    var derivation = lineDerivation.Derive((uint)index);
                    var info       = new KeyPathInformation()
                    {
                        ScriptPubKey       = derivation.ScriptPubKey,
                        Redeem             = derivation.Redeem,
                        TrackedSource      = derivationStrategy,
                        DerivationStrategy = derivationStrategy.DerivationStrategy,
                        Feature            = feature,
                        KeyPath            = path.Derive(index, false)
                    };
                    items.Descriptors.Add(new ScanTxoutSetObject(ScanTxoutDescriptor.Raw(info.ScriptPubKey)));
                    items.KeyPathInformations.TryAdd(info.ScriptPubKey, info);
                    return(info);
                }).All(_ => true);
            }
            Logs.Explorer.LogInformation($"{workItem.Network.CryptoCode}: Start scanning batch {progress.BatchNumber} of {workItem.DerivationStrategy.ToPrettyString()} from index {progress.From}");
            return(items);
        }
示例#2
0
        private ScannedItems GetScannedItems(ScanUTXOWorkItem workItem, ScanUTXOProgress progress, NBXplorerNetwork network)
        {
            var items = new ScannedItems();
            var derivationStrategy = workItem.DerivationStrategy;

            foreach (var feature in keyPathTemplates.GetSupportedDerivationFeatures())
            {
                var keyPathTemplate = keyPathTemplates.GetKeyPathTemplate(feature);
                var lineDerivation  = workItem.DerivationStrategy.DerivationStrategy.GetLineFor(keyPathTemplate);
                Enumerable.Range(progress.From, progress.Count)
                .Select(index =>
                {
                    var derivation = lineDerivation.Derive((uint)index);
                    var info       = new KeyPathInformation(derivation, derivationStrategy, feature,
                                                            keyPathTemplate.GetKeyPath(index, false), network);
                    items.Descriptors.Add(new ScanTxoutSetObject(ScanTxoutDescriptor.Raw(info.ScriptPubKey)));
                    items.KeyPathInformations.TryAdd(info.ScriptPubKey, info);
                    return(info);
                }).All(_ => true);
            }
            Logs.Explorer.LogInformation($"{workItem.Network.CryptoCode}: Start scanning batch {progress.BatchNumber} of {workItem.DerivationStrategy.ToPrettyString()} from index {progress.From}");
            return(items);
        }
示例#3
0
        private async Task UpdateRepository(DerivationSchemeTrackedSource trackedSource, Repository repo, SlimChain chain, ScanTxoutOutput[] outputs, ScannedItems scannedItems, ScanUTXOProgress progressObj)
        {
            var data = outputs
                       .GroupBy(o => o.Coin.Outpoint.Hash)
                       .Select(o => (Coins: o.Select(c => c.Coin).ToList(),
                                     BlockId: chain.GetBlock(o.First().Height)?.Hash,
                                     TxId: o.Select(c => c.Coin.Outpoint.Hash).FirstOrDefault(),
                                     KeyPathInformations: o.Select(c => scannedItems.KeyPathInformations[c.Coin.ScriptPubKey]).ToList()))
                       .Where(o => o.BlockId != null)
                       .Select(o =>
            {
                foreach (var keyInfo in o.KeyPathInformations)
                {
                    var index   = keyInfo.KeyPath.Indexes.Last();
                    var highest = progressObj.HighestKeyIndexFound[keyInfo.Feature];
                    if (highest == null || index > highest.Value)
                    {
                        progressObj.HighestKeyIndexFound[keyInfo.Feature] = (int)index;
                    }
                }
                return(o);
            }).ToList();

            await repo.SaveKeyInformations(scannedItems.
                                           KeyPathInformations.
                                           Select(p => p.Value).
                                           Where(p =>
            {
                var highest = progressObj.HighestKeyIndexFound[p.Feature];
                if (highest == null)
                {
                    return(false);
                }
                return(p.KeyPath.Indexes.Last() <= highest.Value);
            }).ToArray());

            await repo.UpdateAddressPool(trackedSource, progressObj.HighestKeyIndexFound);

            DateTimeOffset now = DateTimeOffset.UtcNow;
            await repo.SaveMatches(data.Select(o => new TrackedTransaction(new TrackedTransactionKey(o.TxId, o.BlockId, true), trackedSource, o.Coins, o.KeyPathInformations)).ToArray());
        }
示例#4
0
        private async Task UpdateRepository(RPCClient client, DerivationSchemeTrackedSource trackedSource, Repository repo, ScanTxoutOutput[] outputs, ScannedItems scannedItems, ScanUTXOProgress progressObj)
        {
            var clientBatch      = client.PrepareBatch();
            var blockIdsByHeight = new ConcurrentDictionary <int, uint256>();
            await Task.WhenAll(outputs.Select(async o =>
            {
                blockIdsByHeight.TryAdd(o.Height, await clientBatch.GetBlockHashAsync(o.Height));
            }).Concat(new[] { clientBatch.SendBatchAsync() }).ToArray());

            var data = outputs
                       .GroupBy(o => o.Coin.Outpoint.Hash)
                       .Select(o => (Coins: o.Select(c => c.Coin).ToList(),
                                     BlockId: blockIdsByHeight.TryGet(o.First().Height),
                                     TxId: o.Select(c => c.Coin.Outpoint.Hash).FirstOrDefault(),
                                     KeyPathInformations: o.Select(c => scannedItems.KeyPathInformations[c.Coin.ScriptPubKey]).ToList()))
                       .Where(o => o.BlockId != null)
                       .Select(o =>
            {
                foreach (var keyInfo in o.KeyPathInformations)
                {
                    var index   = keyInfo.KeyPath.Indexes.Last();
                    var highest = progressObj.HighestKeyIndexFound[keyInfo.Feature];
                    if (highest == null || index > highest.Value)
                    {
                        progressObj.HighestKeyIndexFound[keyInfo.Feature] = (int)index;
                    }
                }
                return(o);
            }).ToList();

            var blockHeadersByBlockId = new ConcurrentDictionary <uint256, BlockHeader>();

            clientBatch = client.PrepareBatch();
            var gettingBlockHeaders = Task.WhenAll(data.Select(async o =>
            {
                blockHeadersByBlockId.TryAdd(o.BlockId, await clientBatch.GetBlockHeaderAsync(o.BlockId));
            }).Concat(new[] { clientBatch.SendBatchAsync() }).ToArray());
            await repo.SaveKeyInformations(scannedItems.
                                           KeyPathInformations.
                                           Select(p => p.Value).
                                           Where(p =>
            {
                var highest = progressObj.HighestKeyIndexFound[p.Feature];
                if (highest == null)
                {
                    return(false);
                }
                return(p.KeyPath.Indexes.Last() <= highest.Value);
            }).ToArray());

            await repo.UpdateAddressPool(trackedSource, progressObj.HighestKeyIndexFound);

            await          gettingBlockHeaders;
            DateTimeOffset now = DateTimeOffset.UtcNow;
            await repo.SaveMatches(data.Select(o =>
            {
                var trackedTransaction = repo.CreateTrackedTransaction(trackedSource, new TrackedTransactionKey(o.TxId, o.BlockId, true), o.Coins, ToDictionary(o.KeyPathInformations));
                trackedTransaction.Inserted = now;
                trackedTransaction.FirstSeen = blockHeadersByBlockId.TryGetValue(o.BlockId, out var header) && header != null ? header.BlockTime : NBitcoin.Utils.UnixTimeToDateTime(0);
                return(trackedTransaction);
            }).ToArray());
        }