Create a helper case class called FundRawTxHelper (#4544)

* Create a helper case class called FundRawTxHelper to encapsulate the values returned by fundRawTransactionInternal

* Return FundRawTxHelper[ShufflingNonInteractiveFinalizer]

* make FundRawTxHelper.signedTx be a lazy val
This commit is contained in:
Chris Stewart 2022-07-27 17:12:42 -05:00 committed by GitHub
parent b69e487d04
commit f608c5d5e4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 151 additions and 119 deletions

View File

@ -18,6 +18,10 @@ import org.bitcoins.core.protocol.transaction.{
TransactionOutput
}
import org.bitcoins.core.util.{FutureUtil, StartStopAsync}
import org.bitcoins.core.wallet.builder.{
FundRawTxHelper,
ShufflingNonInteractiveFinalizer
}
import org.bitcoins.core.wallet.fee.FeeUnit
import org.bitcoins.core.wallet.utxo.{
AddressTag,
@ -85,7 +89,8 @@ trait WalletApi extends StartStopAsync[WalletApi] {
destinations: Vector[TransactionOutput],
feeRate: FeeUnit,
fromTagOpt: Option[AddressTag],
markAsReserved: Boolean): Future[Transaction]
markAsReserved: Boolean): Future[
FundRawTxHelper[ShufflingNonInteractiveFinalizer]]
def listTransactions(): Future[Vector[TransactionDb]]

View File

@ -0,0 +1,19 @@
package org.bitcoins.core.wallet.builder
import org.bitcoins.core.protocol.transaction.Transaction
import org.bitcoins.core.wallet.fee.FeeUnit
import org.bitcoins.core.wallet.utxo.{InputInfo, ScriptSignatureParams}
case class FundRawTxHelper[T <: RawTxFinalizer](
txBuilderWithFinalizer: RawTxBuilderWithFinalizer[T],
scriptSigParams: Vector[ScriptSignatureParams[InputInfo]],
feeRate: FeeUnit) {
/** Produces the unsigned transaction built by fundrawtransaction */
def unsignedTx: Transaction = txBuilderWithFinalizer.buildTx()
/** Produces a signed bitcoin transaction with the given fee rate */
lazy val signedTx: Transaction = {
RawTxSigner.sign(unsignedTx, scriptSigParams, feeRate)
}
}

View File

@ -22,7 +22,7 @@ import org.bitcoins.core.protocol.tlv._
import org.bitcoins.core.protocol.transaction._
import org.bitcoins.core.util.{FutureUtil, TimeUtil}
import org.bitcoins.core.wallet.builder.{
RawTxBuilderWithFinalizer,
FundRawTxHelper,
ShufflingNonInteractiveFinalizer
}
import org.bitcoins.core.wallet.fee.SatoshisPerVirtualByte
@ -352,7 +352,7 @@ abstract class DLCWallet
nextIndex <- getNextAvailableIndex(account, chainType)
_ <- writeDLCKeysToAddressDb(account, chainType, nextIndex)
(txBuilder, spendingInfos) <- fundRawTransactionInternal(
fundRawTxHelper <- fundRawTransactionInternal(
destinations = Vector(TransactionOutput(collateral, EmptyScriptPubKey)),
feeRate = feeRate,
fromAccount = account,
@ -360,6 +360,7 @@ abstract class DLCWallet
markAsReserved = true
)
spendingInfos = fundRawTxHelper.scriptSigParams
serialIds = DLCMessage.genSerialIds(spendingInfos.size)
utxos = spendingInfos.zip(serialIds).map { case (utxo, id) =>
DLCFundingInput.fromInputSigningInfo(
@ -377,6 +378,7 @@ abstract class DLCWallet
used = false)
}
txBuilder = fundRawTxHelper.txBuilderWithFinalizer
changeAddr = externalChangeAddressOpt.getOrElse {
val changeSPK = txBuilder.finalizer.changeSPK
BitcoinAddress.fromScriptPubKey(changeSPK, networkParameters)
@ -487,8 +489,7 @@ abstract class DLCWallet
private def initDLCForAccept(
offer: DLCOffer,
account: AccountDb,
txBuilder: RawTxBuilderWithFinalizer[ShufflingNonInteractiveFinalizer],
spendingInfos: Vector[ScriptSignatureParams[InputInfo]],
fundRawTxHelper: FundRawTxHelper[ShufflingNonInteractiveFinalizer],
collateral: CurrencyUnit,
peerAddressOpt: Option[InetSocketAddress],
externalPayoutAddressOpt: Option[BitcoinAddress],
@ -544,8 +545,7 @@ abstract class DLCWallet
keyIndex = nextIndex,
chainType = chainType,
offer = offer,
txBuilder = txBuilder,
spendingInfos = spendingInfos,
fundRawTxHelper = fundRawTxHelper,
account = account,
fundingPrivKey = getFundingPrivKey(account, nextIndex),
collateral = collateral,
@ -574,7 +574,7 @@ abstract class DLCWallet
dlcAcceptWithoutSigs,
dlcPubKeys = dlcPubKeys,
collateral = collateral)
acceptInputs = spendingInfos
acceptInputs = fundRawTxHelper.scriptSigParams
.zip(dlcAcceptWithoutSigs.fundingInputs)
.zipWithIndex
.map { case ((utxo, fundingInput), idx) =>
@ -722,14 +722,12 @@ abstract class DLCWallet
private def fundDLCAcceptMsg(
offer: DLCOffer,
collateral: CurrencyUnit,
account: AccountDb): Future[(
RawTxBuilderWithFinalizer[ShufflingNonInteractiveFinalizer],
Vector[ScriptSignatureParams[InputInfo]])] = {
val txBuilderAndSpendingInfosF: Future[(
RawTxBuilderWithFinalizer[ShufflingNonInteractiveFinalizer],
Vector[ScriptSignatureParams[InputInfo]])] = {
account: AccountDb): Future[
FundRawTxHelper[ShufflingNonInteractiveFinalizer]] = {
val txBuilderAndSpendingInfosF: Future[
FundRawTxHelper[ShufflingNonInteractiveFinalizer]] = {
for {
(txBuilder, spendingInfos) <- fundRawTransactionInternal(
fundRawTxHelper <- fundRawTransactionInternal(
destinations =
Vector(TransactionOutput(collateral, EmptyScriptPubKey)),
feeRate = offer.feeRate,
@ -737,7 +735,7 @@ abstract class DLCWallet
fromTagOpt = None,
markAsReserved = true
)
} yield (txBuilder, spendingInfos)
} yield fundRawTxHelper
}
txBuilderAndSpendingInfosF
}
@ -764,16 +762,15 @@ abstract class DLCWallet
s"Creating DLC Accept for tempContractId ${offer.tempContractId.hex}")
val result = for {
account <- getDefaultAccountForType(AddressType.SegWit)
(txBuilder, spendingInfos) <- fundDLCAcceptMsg(offer = offer,
collateral = collateral,
account = account)
fundRawTxHelper <- fundDLCAcceptMsg(offer = offer,
collateral = collateral,
account = account)
initializedAccept <-
initDLCForAccept(
offer = offer,
account = account,
txBuilder = txBuilder,
spendingInfos = spendingInfos,
fundRawTxHelper = fundRawTxHelper,
collateral = collateral,
externalPayoutAddressOpt = externalPayoutAddressOpt,
externalChangeAddressOpt = externalChangeAddressOpt,
@ -795,12 +792,13 @@ abstract class DLCWallet
contractId = builder.calcContractId
signer = DLCTxSigner(builder = builder,
isInitiator = false,
fundingKey = fundingPrivKey,
finalAddress =
initializedAccept.pubKeys.payoutAddress,
fundingUtxos = spendingInfos)
signer = DLCTxSigner(
builder = builder,
isInitiator = false,
fundingKey = fundingPrivKey,
finalAddress = initializedAccept.pubKeys.payoutAddress,
fundingUtxos = fundRawTxHelper.scriptSigParams
)
spkDb = ScriptPubKeyDb(builder.fundingSPK)
// only update spk db if we don't have it

View File

@ -18,10 +18,9 @@ import org.bitcoins.core.protocol.dlc.models._
import org.bitcoins.core.protocol.transaction.TransactionConstants
import org.bitcoins.core.util.TimeUtil
import org.bitcoins.core.wallet.builder.{
RawTxBuilderWithFinalizer,
FundRawTxHelper,
ShufflingNonInteractiveFinalizer
}
import org.bitcoins.core.wallet.utxo.{InputInfo, ScriptSignatureParams}
import org.bitcoins.crypto.{AdaptorSign, Sha256Digest}
import org.bitcoins.dlc.wallet.models.{
DLCAcceptDb,
@ -40,8 +39,7 @@ object DLCAcceptUtil extends Logging {
keyIndex: Int,
chainType: HDChainType,
offer: DLCOffer,
txBuilder: RawTxBuilderWithFinalizer[ShufflingNonInteractiveFinalizer],
spendingInfos: Vector[ScriptSignatureParams[InputInfo]],
fundRawTxHelper: FundRawTxHelper[ShufflingNonInteractiveFinalizer],
account: AccountDb,
fundingPrivKey: AdaptorSign,
collateral: CurrencyUnit,
@ -50,6 +48,8 @@ object DLCAcceptUtil extends Logging {
externalChangeAddressOpt: Option[BitcoinAddress]): (
DLCAcceptWithoutSigs,
DLCPublicKeys) = {
val spendingInfos = fundRawTxHelper.scriptSigParams
val txBuilder = fundRawTxHelper.txBuilderWithFinalizer
val serialIds = DLCMessage.genSerialIds(
spendingInfos.size,
offer.fundingInputs.map(_.inputSerialId))

View File

@ -3,7 +3,6 @@ package org.bitcoins.wallet
import org.bitcoins.core.currency._
import org.bitcoins.core.hd.HDChainType
import org.bitcoins.core.protocol.transaction.TransactionOutput
import org.bitcoins.core.wallet.builder.RawTxSigner
import org.bitcoins.core.wallet.fee.SatoshisPerVirtualByte
import org.bitcoins.core.wallet.utxo.{InternalAddressTag, StorageLocationTag}
import org.bitcoins.server.BitcoindRpcBackendUtil
@ -79,7 +78,7 @@ class AddressTagIntegrationTest extends BitcoinSWalletTest {
account <- wallet.getDefaultAccount()
feeRate <- wallet.getFeeRate()
(txBuilder, utxoInfos) <- bitcoind.getNewAddress.flatMap { addr =>
rawTxHelper <- bitcoind.getNewAddress.flatMap { addr =>
val output = TransactionOutput(valueToBitcoind, addr.scriptPubKey)
wallet
.fundRawTransactionInternal(destinations = Vector(output),
@ -88,8 +87,7 @@ class AddressTagIntegrationTest extends BitcoinSWalletTest {
fromTagOpt = Some(exampleTag),
markAsReserved = true)
}
utx = txBuilder.buildTx()
signedTx = RawTxSigner.sign(utx, utxoInfos, feeRate)
signedTx = rawTxHelper.signedTx
_ <- wallet.processTransaction(signedTx, None)
utxos <- wallet.listUtxos()
@ -108,7 +106,7 @@ class AddressTagIntegrationTest extends BitcoinSWalletTest {
// change UTXO should be smaller than what we had, but still have money in it
assert(tagBalancePostSend > 0.sats)
assert(tagBalancePostSend < valueFromBitcoind)
val utxoInfos = rawTxHelper.scriptSigParams
val feePaid =
utxoInfos.map(_.output.value).sum - signedTx.outputs.map(_.value).sum
assert(

View File

@ -2,7 +2,6 @@ package org.bitcoins.wallet
import org.bitcoins.core.currency.Bitcoins
import org.bitcoins.core.protocol.transaction.TransactionOutput
import org.bitcoins.core.wallet.builder.RawTxSigner
import org.bitcoins.core.wallet.utxo.StorageLocationTag.HotStorage
import org.bitcoins.core.wallet.utxo._
import org.bitcoins.testkit.wallet.{
@ -40,12 +39,13 @@ class FundTransactionHandlingTest
val wallet = fundedWallet.wallet
for {
feeRate <- wallet.getFeeRate()
fundedTx <- wallet.fundRawTransaction(destinations =
Vector(destination),
feeRate = feeRate,
fromTagOpt = None,
markAsReserved = false)
fundRawTxHelper <- wallet.fundRawTransaction(destinations =
Vector(destination),
feeRate = feeRate,
fromTagOpt = None,
markAsReserved = false)
} yield {
val fundedTx = fundRawTxHelper.unsignedTx
assert(fundedTx.inputs.length == 1,
s"We should only need one input to fund this tx")
assert(fundedTx.outputs.contains(destination))
@ -61,12 +61,13 @@ class FundTransactionHandlingTest
val wallet = fundedWallet.wallet
for {
feeRate <- wallet.getFeeRate()
fundedTx <- wallet.fundRawTransaction(destinations =
Vector(newDestination),
feeRate = feeRate,
fromTagOpt = None,
markAsReserved = false)
fundRawTxHelper <- wallet.fundRawTransaction(destinations =
Vector(newDestination),
feeRate = feeRate,
fromTagOpt = None,
markAsReserved = false)
} yield {
val fundedTx = fundRawTxHelper.unsignedTx
assert(fundedTx.inputs.length == 3,
s"We should need 3 inputs to fund this tx")
assert(fundedTx.outputs.contains(newDestination))
@ -82,11 +83,13 @@ class FundTransactionHandlingTest
for {
feeRate <- wallet.getFeeRate()
fundedTx <- wallet.fundRawTransaction(destinations = destinations,
feeRate = feeRate,
fromTagOpt = None,
markAsReserved = false)
fundRawTxHelper <- wallet.fundRawTransaction(destinations =
destinations,
feeRate = feeRate,
fromTagOpt = None,
markAsReserved = false)
} yield {
val fundedTx = fundRawTxHelper.unsignedTx
// Can be different depending on waste calculation
assert(fundedTx.inputs.length == 1 || fundedTx.inputs.length == 2,
s"We should only need one or two inputs to fund this tx")
@ -152,10 +155,11 @@ class FundTransactionHandlingTest
for {
feeRate <- wallet.getFeeRate()
account1DbOpt <- account1DbF
fundedTx <- wallet.fundRawTransaction(Vector(newDestination),
feeRate,
account1DbOpt.get)
fundRawTxHelper <- wallet.fundRawTransaction(Vector(newDestination),
feeRate,
account1DbOpt.get)
} yield {
val fundedTx = fundRawTxHelper.unsignedTx
assert(fundedTx.inputs.nonEmpty)
assert(fundedTx.outputs.contains(newDestination))
assert(fundedTx.outputs.length == 2)
@ -216,13 +220,14 @@ class FundTransactionHandlingTest
val wallet = fundedWallet.wallet
for {
feeRate <- wallet.getFeeRate()
fundedTx <- wallet.fundRawTransaction(destinations =
Vector(destination),
feeRate = feeRate,
fromTagOpt = None,
markAsReserved = true)
fundRawTxHelper <- wallet.fundRawTransaction(destinations =
Vector(destination),
feeRate = feeRate,
fromTagOpt = None,
markAsReserved = true)
spendingInfos <- wallet.spendingInfoDAO.findOutputsBeingSpent(fundedTx)
spendingInfos <- wallet.spendingInfoDAO.findOutputsBeingSpent(
fundRawTxHelper.unsignedTx)
reserved <- wallet.spendingInfoDAO.findByTxoState(TxoState.Reserved)
} yield {
assert(spendingInfos.exists(_.state == TxoState.Reserved))
@ -243,7 +248,7 @@ class FundTransactionHandlingTest
_ = assert(taggedBalance == destination.value * 2)
expectedUtxos <- wallet.listUtxos(account.hdAccount, tag)
(txBuilder, utxoInfos) <-
fundRawTxHelper <-
wallet
.fundRawTransactionInternal(
destinations = Vector(destination),
@ -253,8 +258,7 @@ class FundTransactionHandlingTest
markAsReserved = true
)
} yield {
val utx = txBuilder.buildTx()
val tx = RawTxSigner.sign(utx, utxoInfos, feeRate)
val tx = fundRawTxHelper.signedTx
assert(tx.inputs.forall(input =>
expectedUtxos.exists(_.outPoint == input.previousOutput)))

View File

@ -180,14 +180,14 @@ class ProcessTransactionTest extends BitcoinSWalletTest {
wallet <- processedFundingTxF
destinations = Vector(
TransactionOutput(amount, receivingAddress.scriptPubKey))
spendingTx <- wallet.fundRawTransaction(
rawTxHelper <- wallet.fundRawTransaction(
destinations = destinations,
feeRate = SatoshisPerByte.one,
fromTagOpt = None,
markAsReserved = true
)
processedSpendingTx <- wallet.processTransaction(transaction =
spendingTx,
rawTxHelper.signedTx,
blockHash = None)
balance <- processedSpendingTx.getBalance()
} yield assert(balance == amount)

View File

@ -296,11 +296,12 @@ class UTXOLifeCycleTest
for {
oldTransactions <- wallet.listTransactions()
feeRate <- wallet.getFeeRate()
tx <- wallet.fundRawTransaction(Vector(dummyOutput),
feeRate,
fromTagOpt = None,
markAsReserved = true)
rawTxHelper <- wallet.fundRawTransaction(Vector(dummyOutput),
feeRate,
fromTagOpt = None,
markAsReserved = true)
tx = rawTxHelper.unsignedTx
updatedCoins <- wallet.spendingInfoDAO.findOutputsBeingSpent(tx)
reserved <- wallet.listUtxos(TxoState.Reserved)
newTransactions <- wallet.listTransactions()
@ -322,11 +323,12 @@ class UTXOLifeCycleTest
for {
oldTransactions <- wallet.listTransactions()
feeRate <- wallet.getFeeRate()
tx <- wallet.fundRawTransaction(Vector(dummyOutput),
feeRate,
fromTagOpt = None,
markAsReserved = true)
rawTxHelper <- wallet.fundRawTransaction(Vector(dummyOutput),
feeRate,
fromTagOpt = None,
markAsReserved = true)
tx = rawTxHelper.unsignedTx
reservedUtxos <- wallet.spendingInfoDAO.findOutputsBeingSpent(tx)
allReserved <- wallet.listUtxos(TxoState.Reserved)
_ = assert(reservedUtxos.forall(_.state == TxoState.Reserved))
@ -352,10 +354,12 @@ class UTXOLifeCycleTest
for {
oldTransactions <- wallet.listTransactions()
feeRate <- wallet.getFeeRate()
tx <- wallet.fundRawTransaction(Vector(dummyOutput),
feeRate,
fromTagOpt = None,
markAsReserved = true)
rawTxHelper <- wallet.fundRawTransaction(Vector(dummyOutput),
feeRate,
fromTagOpt = None,
markAsReserved = true)
tx = rawTxHelper.unsignedTx
allReserved <- wallet.listUtxos(TxoState.Reserved)
_ = assert(
tx.inputs
@ -382,16 +386,17 @@ class UTXOLifeCycleTest
for {
oldTransactions <- wallet.listTransactions()
account <- accountF
(txBuilder, params) <- wallet.fundRawTransactionInternal(
rawTxHelper <- wallet.fundRawTransactionInternal(
destinations = Vector(dummyOutput),
feeRate = SatoshisPerVirtualByte.one,
fromAccount = account,
fromTagOpt = None,
markAsReserved = true
)
builderResult = txBuilder.builder.result()
unsignedTx = txBuilder.finalizer.buildTx(builderResult)
tx = RawTxSigner.sign(unsignedTx, params)
builderResult = rawTxHelper.txBuilderWithFinalizer.builder.result()
unsignedTx = rawTxHelper.txBuilderWithFinalizer.finalizer.buildTx(
builderResult)
tx = RawTxSigner.sign(unsignedTx, rawTxHelper.scriptSigParams)
allReserved <- wallet.listUtxos(TxoState.Reserved)
_ = assert(
tx.inputs

View File

@ -385,17 +385,16 @@ abstract class Wallet
* finalizing and signing the transaction, then correctly processing and logging it
*/
private def finishSend[F <: RawTxFinalizer](
txBuilder: RawTxBuilderWithFinalizer[F],
utxoInfos: Vector[ScriptSignatureParams[InputInfo]],
rawTxHelper: FundRawTxHelper[F],
sentAmount: CurrencyUnit,
feeRate: FeeUnit,
newTags: Vector[AddressTag]): Future[Transaction] = {
val utx = txBuilder.buildTx()
val signed = RawTxSigner.sign(utx, utxoInfos, feeRate)
val signed = rawTxHelper.signedTx
val processedTxF = for {
ourOuts <- findOurOuts(signed)
creditingAmount = utxoInfos.foldLeft(CurrencyUnits.zero)(_ + _.amount)
creditingAmount = rawTxHelper.scriptSigParams.foldLeft(
CurrencyUnits.zero)(_ + _.amount)
_ <- processOurTransaction(transaction = signed,
feeRate = feeRate,
inputAmount = creditingAmount,
@ -466,9 +465,8 @@ abstract class Wallet
_ = require(
tmp.outputs.size == 1,
s"Created tx is not as expected, does not have 1 output, got $tmp")
tx <- finishSend(withFinalizer,
utxos,
rawTxHelper = FundRawTxHelper(withFinalizer, utxos, feeRate)
tx <- finishSend(rawTxHelper,
tmp.outputs.head.value,
feeRate,
Vector.empty)
@ -515,8 +513,8 @@ abstract class Wallet
utxos,
feeRate,
changeAddr.scriptPubKey)
tx <- finishSend(txBuilder, utxos, amount, feeRate, newTags)
rawTxHelper = FundRawTxHelper(txBuilder, utxos, feeRate)
tx <- finishSend(rawTxHelper, amount, feeRate, newTags)
} yield tx
}
@ -616,8 +614,9 @@ abstract class Wallet
sequence)
amount = outputs.foldLeft(CurrencyUnits.zero)(_ + _.value)
rawTxHelper = FundRawTxHelper(txBuilder, spendingInfos, newFeeRate)
tx <-
finishSend(txBuilder, spendingInfos, amount, newFeeRate, Vector.empty)
finishSend(rawTxHelper, amount, newFeeRate, Vector.empty)
} yield tx
}
@ -636,15 +635,14 @@ abstract class Wallet
logger.info(s"Sending $amount to $address at feerate $feeRate")
val destination = TransactionOutput(amount, address.scriptPubKey)
for {
(txBuilder, utxoInfos) <- fundRawTransactionInternal(
destinations = Vector(destination),
feeRate = feeRate,
fromAccount = fromAccount,
coinSelectionAlgo = algo,
fromTagOpt = None,
markAsReserved = true)
tx <- finishSend(txBuilder, utxoInfos, amount, feeRate, newTags)
rawTxHelper <- fundRawTransactionInternal(destinations =
Vector(destination),
feeRate = feeRate,
fromAccount = fromAccount,
coinSelectionAlgo = algo,
fromTagOpt = None,
markAsReserved = true)
tx <- finishSend(rawTxHelper, amount, feeRate, newTags)
} yield tx
}
@ -718,7 +716,7 @@ abstract class Wallet
val output = TransactionOutput(0.satoshis, scriptPubKey)
for {
(txBuilder, utxoInfos) <- fundRawTransactionInternal(
fundRawTxHelper <- fundRawTransactionInternal(
destinations = Vector(output),
feeRate = feeRate,
fromAccount = fromAccount,
@ -726,8 +724,7 @@ abstract class Wallet
fromTagOpt = None,
markAsReserved = true
)
tx <- finishSend(txBuilder,
utxoInfos,
tx <- finishSend(fundRawTxHelper,
CurrencyUnits.zero,
feeRate,
Vector.empty)
@ -741,14 +738,13 @@ abstract class Wallet
newTags: Vector[AddressTag])(implicit
ec: ExecutionContext): Future[Transaction] = {
for {
(txBuilder, utxoInfos) <- fundRawTransactionInternal(
destinations = outputs,
feeRate = feeRate,
fromAccount = fromAccount,
fromTagOpt = None,
markAsReserved = true)
fundRawTxHelper <- fundRawTransactionInternal(destinations = outputs,
feeRate = feeRate,
fromAccount = fromAccount,
fromTagOpt = None,
markAsReserved = true)
sentAmount = outputs.foldLeft(CurrencyUnits.zero)(_ + _.value)
tx <- finishSend(txBuilder, utxoInfos, sentAmount, feeRate, newTags)
tx <- finishSend(fundRawTxHelper, sentAmount, feeRate, newTags)
} yield tx
}

View File

@ -35,6 +35,10 @@ import org.bitcoins.core.protocol.transaction.{
}
import org.bitcoins.core.protocol.{BitcoinAddress, BlockStamp}
import org.bitcoins.core.psbt.PSBT
import org.bitcoins.core.wallet.builder.{
FundRawTxHelper,
ShufflingNonInteractiveFinalizer
}
import org.bitcoins.core.wallet.fee.{FeeUnit, SatoshisPerVirtualByte}
import org.bitcoins.core.wallet.keymanagement.KeyManagerParams
import org.bitcoins.core.wallet.rescan.RescanState
@ -158,7 +162,8 @@ class WalletHolder(implicit ec: ExecutionContext)
destinations: Vector[TransactionOutput],
feeRate: FeeUnit,
fromTagOpt: Option[AddressTag],
markAsReserved: Boolean): Future[Transaction] = delegate(
markAsReserved: Boolean): Future[
FundRawTxHelper[ShufflingNonInteractiveFinalizer]] = delegate(
_.fundRawTransaction(destinations, feeRate, fromTagOpt, markAsReserved))
override def listTransactions(): Future[Vector[TransactionDb]] = delegate(

View File

@ -18,7 +18,8 @@ trait FundTransactionHandling extends WalletLogger { self: Wallet =>
destinations: Vector[TransactionOutput],
feeRate: FeeUnit,
fromTagOpt: Option[AddressTag],
markAsReserved: Boolean): Future[Transaction] = {
markAsReserved: Boolean): Future[
FundRawTxHelper[ShufflingNonInteractiveFinalizer]] = {
for {
account <- getDefaultAccount()
funded <- fundRawTransaction(destinations = destinations,
@ -34,13 +35,13 @@ trait FundTransactionHandling extends WalletLogger { self: Wallet =>
feeRate: FeeUnit,
fromAccount: AccountDb,
fromTagOpt: Option[AddressTag] = None,
markAsReserved: Boolean = false): Future[Transaction] = {
markAsReserved: Boolean = false): Future[
FundRawTxHelper[ShufflingNonInteractiveFinalizer]] = {
fundRawTransactionInternal(destinations = destinations,
feeRate = feeRate,
fromAccount = fromAccount,
fromTagOpt = fromTagOpt,
markAsReserved = markAsReserved)
.map(_._1.buildTx())
}
/** This returns a [[RawTxBuilder]] that can be used to generate an unsigned transaction with [[RawTxBuilder.result()]]
@ -54,9 +55,8 @@ trait FundTransactionHandling extends WalletLogger { self: Wallet =>
fromAccount: AccountDb,
coinSelectionAlgo: CoinSelectionAlgo = CoinSelectionAlgo.LeastWaste,
fromTagOpt: Option[AddressTag],
markAsReserved: Boolean): Future[(
RawTxBuilderWithFinalizer[ShufflingNonInteractiveFinalizer],
Vector[ScriptSignatureParams[InputInfo]])] = {
markAsReserved: Boolean): Future[
FundRawTxHelper[ShufflingNonInteractiveFinalizer]] = {
val amts = destinations.map(_.value)
//need to allow 0 for OP_RETURN outputs
require(amts.forall(_.satoshis.toBigInt >= 0),
@ -133,7 +133,9 @@ trait FundTransactionHandling extends WalletLogger { self: Wallet =>
feeRate,
change.scriptPubKey)
(txBuilder, utxoSpendingInfos)
FundRawTxHelper(txBuilderWithFinalizer = txBuilder,
scriptSigParams = utxoSpendingInfos,
feeRate)
}
resultF.recoverWith { case NonFatal(error) =>