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); }
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)); }
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); }