Add raw funding of psbt to LndRpc (#4235)

This commit is contained in:
benthecarman 2022-04-19 08:39:24 -04:00 committed by GitHub
parent b0e849c233
commit 5856745398
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 95 additions and 3 deletions

View File

@ -5,15 +5,19 @@ import org.bitcoins.asyncutil.AsyncUtil
import org.bitcoins.core.currency.{currencyUnitNumeric, Bitcoins, Satoshis}
import org.bitcoins.core.number.{Int32, UInt32}
import org.bitcoins.core.protocol.BigSizeUInt
import org.bitcoins.core.protocol.script.EmptyScriptSignature
import org.bitcoins.core.protocol.script.{
EmptyScriptSignature,
P2WPKHWitnessSPKV0
}
import org.bitcoins.core.protocol.tlv.UnknownTLV
import org.bitcoins.core.protocol.transaction._
import org.bitcoins.core.psbt.PSBT
import org.bitcoins.core.wallet.fee.SatoshisPerKW
import org.bitcoins.core.wallet.fee.{SatoshisPerKW, SatoshisPerVirtualByte}
import org.bitcoins.crypto._
import org.bitcoins.testkit.fixtures.DualLndFixture
import scodec.bits.HexStringSyntax
import scala.concurrent.Future
import scala.concurrent.duration.DurationInt
import scala.util.{Failure, Success}
@ -153,6 +157,26 @@ class LndRpcClientPairTest extends DualLndFixture {
}
}
it must "fund from an no input psbt" in { params =>
val (_, lnd, _) = params
val spk = P2WPKHWitnessSPKV0(ECPublicKey.freshPublicKey)
val output = TransactionOutput(Satoshis(10000), spk)
val unsignedTx = BaseTransaction(version = Int32.one,
inputs = Vector.empty,
outputs = Vector(output),
lockTime = UInt32.zero)
for {
unsignedPsbt <- lnd.fundPSBT(PSBT.fromUnsignedTx(unsignedTx),
SatoshisPerVirtualByte.one,
spendUnconfirmed = true)
signed <- lnd.finalizePSBT(unsignedPsbt)
transaction <- Future.fromTry(signed.extractTransactionAndValidate)
errorOpt <- lnd.publishTransaction(transaction)
} yield assert(errorOpt.isEmpty)
}
it must "send and receive a custom message" in { params =>
val (_, lndA, lndB) = params

View File

@ -564,6 +564,59 @@ class LndRpcClient(val instance: LndInstance, binaryOpt: Option[File] = None)(
.map(res => Tx(res.rawTx))
}
def fundPSBT(
inputs: Vector[TransactionOutPoint],
outputs: Map[BitcoinAddress, CurrencyUnit],
feeRate: SatoshisPerVirtualByte,
spendUnconfirmed: Boolean): Future[PSBT] = {
val outputMap = outputs.map { case (addr, amt) =>
addr.toString -> amt.satoshis.toLong
}
val template = TxTemplate(inputs, outputMap)
val rawTemplate = FundPsbtRequest.Template.Raw(template)
val fees = SatPerVbyte(feeRate.toLong)
val request = FundPsbtRequest(template = rawTemplate,
fees = fees,
spendUnconfirmed = spendUnconfirmed)
fundPSBT(request)
}
def fundPSBT(
inputs: Vector[TransactionOutPoint],
outputs: Map[BitcoinAddress, CurrencyUnit],
feeRate: SatoshisPerVirtualByte,
account: String,
spendUnconfirmed: Boolean): Future[PSBT] = {
val outputMap = outputs.map { case (addr, amt) =>
addr.toString -> amt.satoshis.toLong
}
val template = TxTemplate(inputs, outputMap)
val rawTemplate = FundPsbtRequest.Template.Raw(template)
val fees = SatPerVbyte(feeRate.toLong)
val request = FundPsbtRequest(template = rawTemplate,
fees = fees,
account = account,
spendUnconfirmed = spendUnconfirmed)
fundPSBT(request)
}
def fundPSBT(
psbt: PSBT,
feeRate: SatoshisPerVirtualByte,
account: String,
spendUnconfirmed: Boolean): Future[PSBT] = {
val template = Psbt(psbt.bytes)
val fees = SatPerVbyte(feeRate.toLong)
val request = FundPsbtRequest(template = template,
fees = fees,
account = account,
spendUnconfirmed = spendUnconfirmed)
fundPSBT(request)
}
def fundPSBT(
psbt: PSBT,
feeRate: SatoshisPerVirtualByte,

View File

@ -1,8 +1,8 @@
package org.bitcoins.lnd.rpc
import com.google.protobuf.ByteString
import lnrpc.ChannelPoint
import lnrpc.ChannelPoint.FundingTxid.FundingTxidBytes
import lnrpc.{ChannelPoint, OutPoint}
import org.bitcoins.commons.jsonmodels.lnd.TxDetails
import org.bitcoins.core.currency.Satoshis
import org.bitcoins.core.number.UInt32
@ -30,12 +30,27 @@ trait LndUtils {
TransactionOutput(Satoshis(txOut.value),
ScriptPubKey.fromAsmBytes(txOut.pkScript))
implicit def outpointToTxOutPoint(op: OutPoint): TransactionOutPoint =
TransactionOutPoint(DoubleSha256DigestBE(op.txidStr),
UInt32(op.outputIndex))
implicit def txOutpointToOutpoint(outpoint: TransactionOutPoint): OutPoint =
OutPoint(outpoint.txId.bytes, outpoint.txIdBE.hex, outpoint.vout.toInt)
// If other kinds of Iterables are needed, there's a fancy thing to do
// that is done all over the Seq code using params and an implicit CanBuildFrom
implicit def outputVecToTxOuts(
outputs: Vector[TransactionOutput]): Vector[TxOut] =
outputs.map(outputToTxOut)
implicit def outpointVecToTxOutPointVec(
ops: Vector[OutPoint]): Vector[TransactionOutPoint] =
ops.map(outpointToTxOutPoint)
implicit def txOutpointToOutpointVec(
ops: Vector[TransactionOutPoint]): Vector[OutPoint] =
ops.map(txOutpointToOutpoint)
implicit def byteStringVecToByteVecs(
byteStrings: Vector[ByteString]): Vector[ByteVector] =
byteStrings.map(byteStringToByteVec)