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