private async Task UpdateUTXO(UpdatePSBTRequest update, Repository repo, BitcoinDWaiter rpc)
        {
            AnnotatedTransactionCollection txs = null;

            // First, we check for data in our history
            foreach (var input in update.PSBT.Inputs.Where(NeedUTXO))
            {
                txs = txs ?? await GetAnnotatedTransactions(repo, ChainProvider.GetChain(repo.Network), new DerivationSchemeTrackedSource(update.DerivationScheme));

                if (txs.GetByTxId(input.PrevOut.Hash) is AnnotatedTransaction tx)
                {
                    if (!tx.Record.Key.IsPruned)
                    {
                        input.NonWitnessUtxo = tx.Record.Transaction;
                    }
                    else
                    {
                        input.WitnessUtxo = tx.Record.ReceivedCoins.FirstOrDefault(c => c.Outpoint.N == input.Index)?.TxOut;
                    }
                }
            }

            // then, we search data in the saved transactions
            await Task.WhenAll(update.PSBT.Inputs
                               .Where(NeedUTXO)
                               .Select(async(input) =>
            {
                // If this is not segwit, or we are unsure of it, let's try to grab from our saved transactions
                if (input.NonWitnessUtxo == null)
                {
                    var prev = await repo.GetSavedTransactions(input.PrevOut.Hash);
                    if (prev.FirstOrDefault() is Repository.SavedTransaction saved)
                    {
                        input.NonWitnessUtxo = saved.Transaction;
                    }
                }
            }).ToArray());

            // finally, we check with rpc's txindex
            if (rpc?.RPCAvailable is true && rpc?.HasTxIndex is true)
            {
                var batch           = rpc.RPC.PrepareBatch();
                var getTransactions = Task.WhenAll(update.PSBT.Inputs
                                                   .Where(NeedUTXO)
                                                   .Where(input => input.NonWitnessUtxo == null)
                                                   .Select(async input =>
                {
                    var tx = await batch.GetRawTransactionAsync(input.PrevOut.Hash, false);
                    if (tx != null)
                    {
                        input.NonWitnessUtxo = tx;
                    }
                }).ToArray());
                await batch.SendBatchAsync();

                await getTransactions;
            }
        }
예제 #2
0
 private void FillUTXOsInformation(List <UTXO> utxos, AnnotatedTransactionCollection transactions, int currentHeight)
 {
     for (int i = 0; i < utxos.Count; i++)
     {
         var utxo = utxos[i];
         utxo.KeyPath = transactions.GetKeyPath(utxo.ScriptPubKey);
         utxo.Feature = DerivationStrategyBase.GetFeature(utxo.KeyPath);
         var txHeight = transactions.GetByTxId(utxo.Outpoint.Hash)
                        .Select(t => t.Height)
                        .Where(h => h.HasValue)
                        .Select(t => t.Value)
                        .Concat(MaxValue)
                        .Min();
         var firstSeen = transactions
                         .GetByTxId(utxo.Outpoint.Hash)
                         .Select(o => o.Record.FirstSeen)
                         .FirstOrDefault();
         var isUnconf = txHeight == MaxValue[0];
         utxo.Confirmations = isUnconf ? 0 : currentHeight - txHeight + 1;
         utxo.Timestamp     = firstSeen;
     }
 }
예제 #3
0
        private void FillUTXOsInformation(List <UTXO> utxos, Func <Script[], KeyPath[]> getKeyPaths, AnnotatedTransactionCollection transactionsById, int currentHeight)
        {
            var keyPaths = getKeyPaths(utxos.Select(u => u.Output.ScriptPubKey).ToArray());

            for (int i = 0; i < utxos.Count; i++)
            {
                var utxo = utxos[i];
                utxo.KeyPath = keyPaths[i];
                var txHeight = transactionsById.GetByTxId(utxo.Outpoint.Hash).Select(r => r.Height).Min();
                txHeight           = txHeight == MempoolHeight ? currentHeight + 1 : txHeight;
                utxo.Confirmations = currentHeight - txHeight + 1;
            }
        }