Example #1
0
 public NbxChainWatchInterface(ExplorerClient nbxplorerClient, ILogger <NbxChainWatchInterface> logger, NRustLightningNetwork network)
 {
     _logger         = logger;
     _network        = network;
     NbxplorerClient = nbxplorerClient;
     util            = new ChainWatchInterfaceUtil(network.NBitcoinNetwork);
 }
Example #2
0
 public Channel <FeeRateSet> GetFeeRateChannel(NRustLightningNetwork n)
 {
     if (!_feeRateChannels.TryGetValue(n.CryptoCode, out var feeRateChannel))
     {
         throw new Exception($"Channel not found for {n.CryptoCode}! this should never happen");
     }
     return(feeRateChannel);
 }
        public Task <BitcoinAddress> GetNewAddressAsync(NRustLightningNetwork network, CancellationToken ct = default)
        {
            var p = this.GetBaseXPriv(network);
            var t = Task.FromResult(p.Derive(_derivationCount).Neuter().ExtPubKey.PubKey.WitHash.GetAddress(network.NBitcoinNetwork));

            _derivationCount++;
            return(t);
        }
Example #4
0
        public async Task <BitcoinAddress> GetNewAddressAsync(NRustLightningNetwork network, CancellationToken ct = default)
        {
            var cli   = _nbXplorerClientProvider.GetClient(network);
            var deriv = await GetOurDerivationStrategyAsync(network, ct);

            var a = await cli.GetUnusedAsync(deriv, DerivationFeature.Deposit, 0, false, ct);

            return(a.Address);
        }
Example #5
0
        private PSBT SignPSBT(PSBT psbt, NRustLightningNetwork network)
        {
            if (BaseXPrivs.TryGetValue(network, out var xpriv))
            {
                psbt.SignAll(ScriptPubKeyType.Segwit, xpriv);
            }

            return(psbt);
        }
Example #6
0
 private BitcoinExtKey GetBaseXPriv(NRustLightningNetwork network)
 {
     if (BaseXPrivs.TryGetValue(network, out var baseKey))
     {
         return(baseKey);
     }
     baseKey = new BitcoinExtKey(new ExtKey(_keysRepository.GetNodeSecret().ToBytes()).Derive(network.BaseKeyPath), network.NBitcoinNetwork);
     BaseXPrivs.TryAdd(network, baseKey);
     return(baseKey);
 }
Example #7
0
        public async Task TrackSpendableOutput(NRustLightningNetwork network,
                                               SpendableOutputDescriptor desc, CancellationToken ct = default)
        {
            var client = _nbXplorerClientProvider.GetClient(network);

            switch (desc)
            {
            case SpendableOutputDescriptor.StaticOutput staticOutput:
            {
                var addr = staticOutput.Item.Output.ScriptPubKey.GetDestinationAddress(network.NBitcoinNetwork);
                var s    = new AddressTrackedSource(addr);
                await client.TrackAsync(s, ct);

                await client.RPCClient.ImportAddressAsync(addr);

                break;
            }

            case SpendableOutputDescriptor.DynamicOutputP2WSH p2wshOutput:
            {
                var(param1, param2) = p2wshOutput.Item.KeyDerivationParams.ToValueTuple();
                var amountSat              = (ulong)p2wshOutput.Item.Output.Value.Satoshi;
                var channelKeys            = _keysRepository.DeriveChannelKeys(amountSat, param1, param2);
                var delayedPaymentKey      = Generators.derivePrivKey(_secp256k1Ctx, channelKeys.DelayedPaymentBaseKey, p2wshOutput.Item.PerCommitmentPoint.PubKey);
                var toSelfDelay            = p2wshOutput.Item.ToSelfDelay;
                var revokeableRedeemScript = _keysRepository.GetRevokeableRedeemScript(p2wshOutput.Item.RemoteRevocationPubKey, toSelfDelay, delayedPaymentKey.PubKey);
                Debug.Assert(p2wshOutput.Item.Output.ScriptPubKey.Equals(revokeableRedeemScript.WitHash.ScriptPubKey));

                var addr =
                    revokeableRedeemScript.WitHash.ScriptPubKey.GetDestinationAddress(network.NBitcoinNetwork);
                var s = new AddressTrackedSource(addr);
                await client.TrackAsync(s, ct);

                await client.RPCClient.ImportAddressAsync(addr);

                break;
            }

            case SpendableOutputDescriptor.StaticOutputRemotePayment remoteOutput:
            {
                var(p1, p2) = remoteOutput.Item.KeyDerivationParams.ToValueTuple();
                var amountSat = (ulong)remoteOutput.Item.Output.Value;
                var keys      = _keysRepository.DeriveChannelKeys(amountSat, p1, p2);
                Debug.Assert(
                    keys.PaymentKey.PubKey.WitHash.ScriptPubKey.Equals(remoteOutput.Item.Output.ScriptPubKey));

                var addr = remoteOutput.Item.Output.ScriptPubKey.GetDestinationAddress(network.NBitcoinNetwork);
                await client.TrackAsync(new AddressTrackedSource(addr), ct);

                await client.RPCClient.ImportAddressAsync(addr);

                break;
            }
            }
        }
Example #8
0
        /// <summary>
        /// Get total UTXO originated as <see cref="SpendableOutputDescriptor"/> which we currently have.
        /// TODO: Stop using Bitcoin-core RPC feature (TrackAsync and ListUnspentAsync) and batch query to nbx when https://github.com/dgarage/NBXplorer/issues/291 is ready.
        /// </summary>
        /// <returns></returns>
        private async Task <Money> GetAmountForLNOutput(NRustLightningNetwork network)
        {
            var repo        = _repositoryProvider.GetRepository(network);
            var cli         = _nbXplorerClientProvider.GetClient(network);
            var ourAddreses = repo.GetAllSpendableOutputDescriptors().ToEnumerable().Select(desc =>
                                                                                            desc.Output.ScriptPubKey.GetDestinationAddress(network.NBitcoinNetwork)).ToArray();
            var currentHeight = await cli.RPCClient.GetBlockCountAsync();

            var coins = await cli.RPCClient.ListUnspentAsync(0, currentHeight, ourAddreses);

            return(coins.Where(coin => ourAddreses.Contains(coin.Address)).Sum(x => x.Amount));
        }
Example #9
0
        internal RPCClient ConfigureRPCClient(NRustLightningNetwork nRustLightningNetwork, ILogger logger)
        {
            var       n         = nRustLightningNetwork.NBitcoinNetwork;
            RPCClient rpcClient = null;

            if (Url != null && User != null && Password != null)
            {
                rpcClient = new RPCClient(new NetworkCredential(User, Password), Url, n);
            }

            if (rpcClient is null)
            {
                if (CookieFile != null)
                {
                    try
                    {
                        rpcClient = new RPCClient(new RPCCredentialString {
                            CookieFile = CookieFile
                        }, Url, n);
                    }
                    catch (IOException)
                    {
                        logger.LogWarning($"{nRustLightningNetwork.CryptoCode}: RPC Cookie file not found at " + (CookieFile ?? RPCClient.GetDefaultCookieFilePath(n)));
                    }
                }

                if (AuthenticationString != null)
                {
                    rpcClient = new RPCClient(RPCCredentialString.Parse(AuthenticationString), Url, n);
                }

                if (rpcClient is null)
                {
                    try
                    {
                        rpcClient = new RPCClient(null as NetworkCredential, Url, n);
                    }
                    catch
                    {
                        // ignored
                    }

                    if (rpcClient == null)
                    {
                        logger.LogError($"{nRustLightningNetwork.CryptoCode}: RPC connection settings not configured");
                        throw new ConfigException();
                    }
                }
            }

            return(rpcClient);
        }
Example #10
0
        public async Task <Money> GetBalanceAsync(NRustLightningNetwork network, CancellationToken ct = default)
        {
            var cli = _nbXplorerClientProvider.GetClient(network);
            var derivationScheme = await GetOurDerivationStrategyAsync(network, ct);

            var b = await cli.GetBalanceAsync(derivationScheme, ct);

            if (b.Total is Money m)
            {
                return(m);
            }
            throw new NRustLightningException($"Unexpected money type {b.Total.GetType().Name}");
        }
 public WorkQueueProcessor(ChannelProvider channelProvider, P2PConnectionHandler p2PConnectionHandler,
                           ILogger <WorkQueueProcessor> logger, PeerManagerProvider peerManagerProvider, NRustLightningNetwork network,
                           IWalletService walletService, IRepository repo)
 {
     _channelProvider      = channelProvider;
     _p2PConnectionHandler = p2PConnectionHandler;
     _logger = logger;
     _peerManagerProvider = peerManagerProvider;
     _network             = network;
     _walletService       = walletService;
     _repo  = repo;
     _tasks = new [] { HandleOutboundConnectQueue(), HandleSpendableOutputEventQueue() };
 }
 public NBXplorerListener(
     ExplorerClient explorerClient,
     PeerManagerProvider peerManagerProvider,
     ILogger <NBXplorerListener> logger,
     ChannelWriter <FeeRateSet> feeRateWriter,
     NRustLightningNetwork network)
 {
     _explorerClient      = explorerClient;
     _peerManagerProvider = peerManagerProvider;
     _logger        = logger;
     _feeRateWriter = feeRateWriter;
     _network       = network;
 }
Example #13
0
        public async Task <PaymentRequest> GetNewInvoice(NRustLightningNetwork network, InvoiceCreationOption option)
        {
            if (network == null)
            {
                throw new ArgumentNullException(nameof(network));
            }

            Primitives.PaymentPreimage paymentPreimage = Primitives.PaymentPreimage.Create(RandomUtils.GetBytes(32));

            var nodeId       = Primitives.NodeId.NewNodeId(_keysRepository.GetNodeId());
            var paymentHash  = paymentPreimage.Hash;
            var taggedFields =
                new List <TaggedField>
            {
                TaggedField.NewPaymentHashTaggedField(paymentHash),
                TaggedField.NewNodeIdTaggedField(nodeId),
                (option.EncodeDescriptionWithHash.HasValue && option.EncodeDescriptionWithHash.Value) ?
                TaggedField.NewDescriptionHashTaggedField(new uint256(Hashes.SHA256(Encoding.UTF8.GetBytes(option.Description)), false)) :
                TaggedField.NewDescriptionTaggedField(option.Description),
            };

            if (option.PaymentSecret != null)
            {
                taggedFields.Add(TaggedField.NewPaymentSecretTaggedField(option.PaymentSecret));
            }

            var t = new TaggedFields(taggedFields.ToFSharpList());
            var r = PaymentRequest.TryCreate(network.BOLT11InvoicePrefix, option.Amount.ToFSharpOption(), _systemClock.UtcNow, nodeId, t, _keysRepository.AsMessageSigner());

            if (r.IsError)
            {
                throw new InvalidDataException($"Error when creating our payment request: {r.ErrorValue}");
            }

            _logger.LogDebug($"Publish new invoice with hash {paymentHash}");

            using var tx = await _engine.OpenTransaction();

            var table = tx.GetTable(DBKeys.HashToPreimage);
            await table.Insert(paymentHash.ToBytes(false), paymentPreimage.ToByteArray());

            var table2 = tx.GetTable(DBKeys.HashToInvoice);
            await table2.Insert(paymentHash.ToBytes(false).ToHexString(), r.ResultValue.ToString());

            await tx.Commit();

            return(r.ResultValue);
        }
Example #14
0
 public RustLightningEventReactor(
     P2PConnectionHandler connectionHandler,
     IPeerManagerProvider peerManagerProvider,
     IWalletService walletService,
     NRustLightningNetwork network,
     EventAggregator eventAggregator,
     ILogger logger,
     IInvoiceRepository invoiceRepository)
 {
     _pool = MemoryPool <byte> .Shared;
     _connectionHandler   = connectionHandler;
     _peerManagerProvider = peerManagerProvider;
     _walletService       = walletService;
     _network             = network;
     _eventAggregator     = eventAggregator;
     _logger            = logger;
     _invoiceRepository = invoiceRepository;
     _peerManager       = peerManagerProvider.TryGetPeerManager(network.CryptoCode);
 }
        public NRustLightningClient(string baseUrl, NRustLightningNetwork network, X509Certificate2?certificate = null)
        {
            var handler = new HttpClientHandler()
            {
                ClientCertificateOptions = ClientCertificateOption.Automatic,
            };

            if (certificate != null)
            {
                handler.ClientCertificates.Add(certificate);
            }

            cryptoCode = network.CryptoCode;
            var ser = new RepositorySerializer(network);

            ser.ConfigureSerializer(jsonSerializerOptions);
            HttpClient = new HttpClient(handler);
            _baseUri   = new Uri(baseUrl);
        }
        public async Task <PaymentRequest> GetNewInvoice(NRustLightningNetwork network, InvoiceCreationOption option, CancellationToken ct = default)
        {
            if (network == null)
            {
                throw new ArgumentNullException(nameof(network));
            }

            Primitives.PaymentPreimage paymentPreimage = Primitives.PaymentPreimage.Create(RandomUtils.GetBytes(32));

            var nodeId       = Primitives.NodeId.NewNodeId(_keysRepository.GetNodeId());
            var paymentHash  = paymentPreimage.Hash;
            var taggedFields =
                new List <TaggedField>
            {
                TaggedField.NewPaymentHashTaggedField(paymentHash),
                TaggedField.NewNodeIdTaggedField(nodeId),
                (option.EncodeDescriptionWithHash.HasValue && option.EncodeDescriptionWithHash.Value) ?
                TaggedField.NewDescriptionHashTaggedField(new uint256(Hashes.SHA256(Encoding.UTF8.GetBytes(option.Description)), false)) :
                TaggedField.NewDescriptionTaggedField(option.Description),
            };

            if (option.PaymentSecret != null)
            {
                taggedFields.Add(TaggedField.NewPaymentSecretTaggedField(option.PaymentSecret));
            }

            var t = new TaggedFields(taggedFields.ToFSharpList());
            var r = PaymentRequest.TryCreate(network.BOLT11InvoicePrefix, option.Amount.ToFSharpOption(), DateTimeOffset.UtcNow, nodeId, t, _keysRepository.AsMessageSigner());

            if (r.IsError)
            {
                throw new InvalidDataException($"Error when creating our payment request: {r.ErrorValue}");
            }

            _logger.LogDebug($"Publish new invoice with hash {paymentHash}");
            await _repository.SetInvoice(r.ResultValue, ct);

            await _repository.SetPreimage(paymentPreimage, ct);

            return(r.ResultValue);
        }
        public Task <UTXOChangesWithMetadata> ListUnspent(NRustLightningNetwork network)
        {
            var res         = new UTXOChangesWithMetadata();
            var confirmed   = new UTXOChangeWithSpentOutput();
            var unconfirmed = new UTXOChangeWithSpentOutput();

            confirmed.SpentOutPoint = new List <OutPoint>()
            {
                OutPoint.Zero
            };
            var coinBaseTx =
                Transaction.Parse(
                    "020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401750101ffffffff0200f2052a0100000017a914d4bb8bf5f987cd463a2f5e6e4f04618c7aaed1b5870000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000", network.NBitcoinNetwork);

            confirmed.UTXO = new List <UTXOChangeWithMetadata>()
            {
                new UTXOChangeWithMetadata(new UTXO(new NBXplorer.Models.UTXO(coinBaseTx.Outputs.AsCoins().First())), UTXOKind.UserDeposit, new AddressTrackedSource(coinBaseTx.Outputs[0].ScriptPubKey.GetDestinationAddress(network.NBitcoinNetwork)))
            };
            res.Confirmed   = confirmed;
            res.UnConfirmed = unconfirmed;
            return(Task.FromResult(res));
        }
 public RustLightningEventReactor(
     P2PConnectionHandler connectionHandler,
     PeerManagerProvider peerManagerProvider,
     IWalletService walletService,
     NRustLightningNetwork network,
     EventAggregator eventAggregator,
     ILogger logger,
     InvoiceService invoiceService,
     ChannelProvider channelProvider,
     IRepository repository)
 {
     _pool = MemoryPool <byte> .Shared;
     _connectionHandler   = connectionHandler;
     _peerManagerProvider = peerManagerProvider;
     _walletService       = walletService;
     _network             = network;
     _eventAggregator     = eventAggregator;
     _logger          = logger;
     _invoiceService  = invoiceService;
     _channelProvider = channelProvider;
     _repository      = repository;
 }
Example #19
0
        public async ValueTask <DerivationStrategyBase> GetOurDerivationStrategyAsync(NRustLightningNetwork network, CancellationToken ct = default)
        {
            DerivationStrategyBase strategy;

            if (DerivationStrategyBaseCache.TryGetValue(network, out strategy))
            {
                return(strategy);
            }
            var baseKey = GetBaseXPriv(network);

            strategy = network.NbXplorerNetwork.DerivationStrategyFactory.CreateDirectDerivationStrategy(baseKey.Neuter(),
                                                                                                         new DerivationStrategyOptions
            {
                ScriptPubKeyType = ScriptPubKeyType.Segwit,
            });

            _logger.LogInformation($"Tracking new xpub ({strategy}) for {network.CryptoCode} with nbxplorer");
            var cli = _nbXplorerClientProvider.GetClient(network);
            await cli.TrackAsync(strategy, ct);

            DerivationStrategyBaseCache[network] = strategy;
            return(strategy);
        }
 public Task <Transaction> GetSendingTxAsync(BitcoinAddress destination, Money amount, NRustLightningNetwork network,
                                             CancellationToken cancellationToken = default)
 {
     return(Task.FromResult(network.NBitcoinNetwork.CreateTransaction()));
 }
Example #21
0
        private async Task <PSBT> SignPSBT(PSBT psbt, NRustLightningNetwork network)
        {
            var repo        = _repositoryProvider.GetRepository(network);
            var outpoints   = psbt.Inputs.Select(txIn => txIn.PrevOut);
            var signingKeys = new List <Key>();

            await foreach (var(desc, i) in repo.GetSpendableOutputDescriptors(outpoints).Select((x, i) => (x, i)))
            {
                if (desc is null)
                {
                    // We don't have any information in repo. This probably means the UTXO is not LN-origin
                    // (i.e. those are the funds user provided by on-chain)
                    continue;
                }
                switch (desc)
                {
                case SpendableOutputDescriptor.StaticOutput _:
                    // signature for this input will be generated by Destination key (see below).
                    // so no need for any operation.
                    break;

                case SpendableOutputDescriptor.DynamicOutputP2WSH p2wshOutput:
                {
                    var(param1, param2) = p2wshOutput.Item.KeyDerivationParams.ToValueTuple();
                    var amountSat         = (ulong)p2wshOutput.Item.Output.Value.Satoshi;
                    var channelKeys       = _keysRepository.DeriveChannelKeys(amountSat, param1, param2);
                    var delayedPaymentKey = Generators.derivePrivKey(_secp256k1Ctx,
                                                                     channelKeys.DelayedPaymentBaseKey, p2wshOutput.Item.PerCommitmentPoint.PubKey);
                    var toSelfDelay            = p2wshOutput.Item.ToSelfDelay;
                    var revokeableRedeemScript =
                        _keysRepository.GetRevokeableRedeemScript(p2wshOutput.Item.RemoteRevocationPubKey,
                                                                  toSelfDelay, delayedPaymentKey.PubKey);
                    Debug.Assert(
                        p2wshOutput.Item.Output.ScriptPubKey.Equals(revokeableRedeemScript.WitHash.ScriptPubKey));
                    psbt.AddScripts(revokeableRedeemScript);
                    psbt.Inputs[i].SetSequence(toSelfDelay);
                    signingKeys.Add(delayedPaymentKey);
                    break;
                }

                case SpendableOutputDescriptor.StaticOutputRemotePayment remoteOutput:
                {
                    var(p1, p2) = remoteOutput.Item.KeyDerivationParams.ToValueTuple();
                    var amountSat = (ulong)remoteOutput.Item.Output.Value;
                    var keys      = _keysRepository.DeriveChannelKeys(amountSat, p1, p2);
                    Debug.Assert(
                        keys.PaymentKey.PubKey.WitHash.ScriptPubKey.Equals(remoteOutput.Item.Output.ScriptPubKey));
                    signingKeys.Add(keys.PaymentKey);
                    break;
                }

                default:
                    throw new Exception($"Unreachable! Unknown output descriptor type {desc}");
                }
            }

            // sign for user provided on-chain funds utxos.
            if (BaseXPrivs.TryGetValue(network, out var xpriv))
            {
                psbt.SignAll(ScriptPubKeyType.Segwit, xpriv);
            }

            // sign for static-outputs. Which RL gave us as a result of off-chain balance handling.
            var destinationKey = _keysRepository.GetDestinationKey();

            psbt.SignWithKeys(destinationKey);

            // sign with other keys which we have saved in repo.
            foreach (var sk in signingKeys)
            {
                psbt.SignWithKeys(sk);
            }

            return(psbt);
        }
Example #22
0
        public async Task <UTXOChangesWithMetadata> ListUnspent(NRustLightningNetwork n)
        {
            var _cli  = _nbXplorerClientProvider.GetClient(n);
            var deriv = await GetOurDerivationStrategyAsync(n);

            var confirmedUtxo             = new List <UTXOChangeWithMetadata>();
            var unconfirmedUtxo           = new List <UTXOChangeWithMetadata>();
            var confirmedSpentOutpoints   = new List <OutPoint>();
            var unconfirmedSpentOutpoints = new List <OutPoint>();

            var nativeFundsResponse = await _cli.GetUTXOsAsync(deriv);

            foreach (var utxo in nativeFundsResponse.Confirmed.UTXOs)
            {
                var item = new UTXOChangeWithMetadata(new UTXO(utxo), UTXOKind.UserDeposit, new DerivationSchemeTrackedSource(deriv));
                confirmedUtxo.Add(item);
            }
            foreach (var utxo in nativeFundsResponse.Unconfirmed.UTXOs)
            {
                unconfirmedUtxo.Add(new UTXOChangeWithMetadata(new UTXO(utxo), UTXOKind.UserDeposit, new DerivationSchemeTrackedSource(deriv)));
            }

            confirmedSpentOutpoints.AddRange(nativeFundsResponse.Confirmed.SpentOutpoints);
            unconfirmedSpentOutpoints.AddRange(nativeFundsResponse.Unconfirmed.SpentOutpoints);

            var repo = _repositoryProvider.GetRepository(n);

            // TODO: Refactor when https://github.com/dgarage/NBXplorer/issues/291 is ready
            await foreach (var o in repo.GetAllSpendableOutputDescriptors())
            {
                var addr           = o.Output.ScriptPubKey.GetDestinationAddress(n.NBitcoinNetwork);
                var ts             = new AddressTrackedSource(addr);
                var lnUTXOResposne = await _cli.GetUTXOsAsync(ts);

                foreach (var utxo in lnUTXOResposne.Confirmed.UTXOs)
                {
                    confirmedUtxo.Add(new UTXOChangeWithMetadata(new UTXO(utxo), o.GetKind(), ts));
                }
                foreach (var utxo in lnUTXOResposne.Unconfirmed.UTXOs)
                {
                    unconfirmedUtxo.Add(new UTXOChangeWithMetadata(new UTXO(utxo), o.GetKind(), ts));
                }
                confirmedSpentOutpoints.AddRange(lnUTXOResposne.Confirmed.SpentOutpoints);
                unconfirmedSpentOutpoints.AddRange(lnUTXOResposne.Unconfirmed.SpentOutpoints);
            }
            ;

            var confirmed = new UTXOChangeWithSpentOutput()
            {
                UTXO = confirmedUtxo, SpentOutPoint = confirmedSpentOutpoints
            };
            var unconfirmed = new UTXOChangeWithSpentOutput()
            {
                UTXO = unconfirmedUtxo, SpentOutPoint = unconfirmedSpentOutpoints
            };

            return(new UTXOChangesWithMetadata()
            {
                Confirmed = confirmed, UnConfirmed = unconfirmed, CurrentHeight = nativeFundsResponse.CurrentHeight
            });
        }
 public Task <Money> GetBalanceAsync(NRustLightningNetwork network, CancellationToken ct = default)
 {
     return(Task.FromResult(Money.Zero));
 }
Example #24
0
 public Channel <PeerConnectionString> GetOutboundConnectionRequestQueue(NRustLightningNetwork n) =>
 GetOutboundConnectionRequestQueue(n.CryptoCode);
 public Task BroadcastAsync(Transaction tx, NRustLightningNetwork network)
 {
     return(Task.CompletedTask);
 }
Example #26
0
        public async Task <Transaction> GetSendingTxAsync(BitcoinAddress destination, Money amount, NRustLightningNetwork network, CancellationToken cancellationToken = default)
        {
            var deriv = await GetOurDerivationStrategyAsync(network, cancellationToken).ConfigureAwait(false);

            var nbXplorerClient = _nbXplorerClientProvider.GetClient(network);
            await _outpointAssumedAsSpentLock.WaitAsync(cancellationToken);

            try
            {
                var req = new CreatePSBTRequest()
                {
                    Destinations =
                        new[]
                    {
                        amount == Money.Zero ?
                        new CreatePSBTDestination
                        {
                            SweepAll    = true,
                            Destination = destination
                        } :
                        new CreatePSBTDestination
                        {
                            Amount      = amount,
                            Destination = destination
                        }
                        ,
                    }.ToList(),
                    ExcludeOutpoints = _outpointAssumedAsSpent.ToList()
                };
                var psbtResponse = await nbXplorerClient.CreatePSBTAsync(deriv, req, cancellationToken)
                                   .ConfigureAwait(false);

                var psbt = await SignPSBT(psbtResponse.PSBT, network);

                if (!psbt.IsAllFinalized())
                {
                    psbt.Finalize();
                }

                var tx = psbt.ExtractTransaction();
                foreach (var prevOut in tx.Inputs.Select(txIn => txIn.PrevOut))
                {
                    _outpointAssumedAsSpent.Enqueue(prevOut);
                }
                return(tx);
            }
            finally
            {
                _outpointAssumedAsSpentLock.Release();
            }
        }
 public Task TrackSpendableOutput(NRustLightningNetwork network, SpendableOutputDescriptor desc,
                                  CancellationToken ct = default)
 {
     return(Task.CompletedTask);
 }
 public RepositorySerializer(NRustLightningNetwork network)
 {
     _network = network ?? throw new ArgumentNullException(nameof(network));
     ConfigureSerializer(Options);
 }
 public PeerManager?TryGetPeerManager(NRustLightningNetwork network)
 {
     Debug.Assert(network.NBitcoinNetwork.NetworkType == NetworkType.Regtest);
     return(TryGetPeerManager(network.CryptoCode));
 }
Example #30
0
 public async Task BroadcastAsync(Transaction tx, NRustLightningNetwork n)
 {
     await _nbXplorerClientProvider.GetClient(n).BroadcastAsync(tx);
 }