mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2024-11-19 09:52:09 +01:00
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:
parent
b69e487d04
commit
f608c5d5e4
@ -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]]
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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))
|
||||
|
@ -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(
|
||||
|
@ -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)))
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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(
|
||||
|
@ -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) =>
|
||||
|
Loading…
Reference in New Issue
Block a user