Example #1
0
        private static PSBT Sign(Party party, DerivationStrategyBase derivationStrategy, PSBT psbt)
        {
            psbt = psbt.Clone();

            // NBXplorer does not have knowledge of the account key path, KeyPath are private information of each peer
            // NBXplorer only derive 0/* and 1/* on top of provided account xpubs,
            // This mean that the input keypaths in the PSBT are in the form 0/* (as if the account key was the root)
            // RebaseKeyPaths modifies the PSBT by adding the AccountKeyPath in prefix of all the keypaths of the PSBT

            // Note that this is not necessary to do this if the account key is the same as root key.
            // Note that also that you don't have to do this, if you do not pass the account key path in the later SignAll call.
            // however, this is best practice to rebase the PSBT before signing.
            // If you sign with an offline device (hw wallet), the wallet would need the rebased PSBT.
            psbt.RebaseKeyPaths(party.AccountExtPubKey, party.AccountKeyPath);

            Console.WriteLine("A PSBT is a data structure with all information for a wallet to sign.");
            var spend = psbt.GetBalance(derivationStrategy, party.AccountExtPubKey, party.AccountKeyPath);

            Console.WriteLine($"{party.PartyName}, Do you agree to sign this transaction spending {spend}?");
            // Ok I sign
            psbt.SignAll(derivationStrategy,                            // What addresses to derive?
                         party.RootExtKey.Derive(party.AccountKeyPath), // With which account private keys?
                         party.AccountKeyPath);                         // What is the keypath of the account private key. If you did not rebased the keypath like before, you can remove this parameter
            return(psbt);
        }
Example #2
0
        private PSBT SignPSBT(PSBT psbt, NRustLightningNetwork network)
        {
            if (BaseXPrivs.TryGetValue(network, out var xpriv))
            {
                psbt.SignAll(ScriptPubKeyType.Segwit, xpriv);
            }

            return(psbt);
        }
        public async Task <PSBT> Sign(PSBT psbt)
        {
            var btcPayWallet = parent.PayTester.GetService <BTCPayWalletProvider>()
                               .GetWallet(psbt.Network.NetworkSet.CryptoCode);
            var explorerClient = parent.PayTester.GetService <ExplorerClientProvider>()
                                 .GetExplorerClient(psbt.Network.NetworkSet.CryptoCode);

            psbt = (await explorerClient.UpdatePSBTAsync(new UpdatePSBTRequest()
            {
                DerivationScheme = DerivationScheme, PSBT = psbt
            })).PSBT;
            return(psbt.SignAll(this.DerivationScheme, GenerateWalletResponseV.AccountHDKey,
                                GenerateWalletResponseV.AccountKeyPath));
        }
Example #4
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);
        }
 public void SignPSBT(PSBT psbt)
 {
     psbt.SignAll(key.AsHDScriptPubKey(scriptPubKeyType), key);
 }