mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2024-11-19 09:52:09 +01:00
Use SubtractFeeFromOutputsFinalizer when sending full utxos (#2072)
This commit is contained in:
parent
4c202fd016
commit
ed5228310b
@ -308,7 +308,7 @@ class RawTxSignerTest extends BitcoinSAsyncTest {
|
||||
}
|
||||
}
|
||||
|
||||
it should "dummy sign a mix of spks in a tx and then have fail verification" in {
|
||||
it should "dummy sign a mix of spks in a tx and fill it with dummy signatures" in {
|
||||
forAllAsync(CreditingTxGen.inputsAndOutputs(),
|
||||
ScriptGenerators.scriptPubKey) {
|
||||
case ((creditingTxsInfo, destinations), (changeSPK, _)) =>
|
||||
|
@ -250,7 +250,16 @@ case class AddWitnessDataFinalizer(inputInfos: Vector[InputInfo])
|
||||
|
||||
override def buildTx(txBuilderResult: RawTxBuilderResult)(implicit
|
||||
ec: ExecutionContext): Future[Transaction] = {
|
||||
val witnesses = inputInfos.map(InputInfo.getScriptWitness)
|
||||
|
||||
val result = txBuilderResult.toBaseTransaction
|
||||
|
||||
val sortedInputInfos = result.inputs
|
||||
.flatMap(input => inputInfos.find(_.outPoint == input.previousOutput))
|
||||
.toVector
|
||||
|
||||
require(sortedInputInfos.size == inputInfos.size, "Missing input infos")
|
||||
|
||||
val witnesses = sortedInputInfos.map(InputInfo.getScriptWitness)
|
||||
TransactionWitness.fromWitOpt(witnesses) match {
|
||||
case _: EmptyWitness =>
|
||||
Future.successful(txBuilderResult.toBaseTransaction)
|
||||
|
@ -9,7 +9,6 @@ import org.bitcoins.core.script.control.OP_RETURN
|
||||
import org.bitcoins.core.wallet.fee._
|
||||
import org.bitcoins.core.wallet.utxo.TxoState
|
||||
import org.bitcoins.crypto.CryptoUtil
|
||||
import org.bitcoins.testkit.core.gen.{CurrencyUnitGenerator, FeeUnitGen}
|
||||
import org.bitcoins.testkit.wallet.BitcoinSWalletTest
|
||||
import org.bitcoins.testkit.wallet.BitcoinSWalletTest.RandomFeeProvider
|
||||
import org.bitcoins.testkit.wallet.FundWalletUtil.FundedWallet
|
||||
|
@ -13,19 +13,14 @@ import org.bitcoins.core.crypto.ExtPublicKey
|
||||
import org.bitcoins.core.currency._
|
||||
import org.bitcoins.core.gcs.{GolombFilter, SimpleFilterMatcher}
|
||||
import org.bitcoins.core.hd.{HDAccount, HDCoin, HDPurpose, HDPurposes}
|
||||
import org.bitcoins.core.policy.Policy
|
||||
import org.bitcoins.core.protocol.BitcoinAddress
|
||||
import org.bitcoins.core.protocol.blockchain.ChainParams
|
||||
import org.bitcoins.core.protocol.script.{EmptyScriptPubKey, ScriptPubKey}
|
||||
import org.bitcoins.core.protocol.script.ScriptPubKey
|
||||
import org.bitcoins.core.protocol.transaction._
|
||||
import org.bitcoins.core.script.constant.ScriptConstant
|
||||
import org.bitcoins.core.script.control.OP_RETURN
|
||||
import org.bitcoins.core.util.{BitcoinScriptUtil, FutureUtil, HDUtil}
|
||||
import org.bitcoins.core.wallet.builder.{
|
||||
RawTxBuilderWithFinalizer,
|
||||
RawTxSigner,
|
||||
ShufflingNonInteractiveFinalizer
|
||||
}
|
||||
import org.bitcoins.core.wallet.builder._
|
||||
import org.bitcoins.core.wallet.fee._
|
||||
import org.bitcoins.core.wallet.keymanagement.{
|
||||
KeyManagerParams,
|
||||
@ -361,8 +356,8 @@ abstract class Wallet
|
||||
/** Takes a [[RawTxBuilderWithFinalizer]] for a transaction to be sent, and completes it by:
|
||||
* finalizing and signing the transaction, then correctly processing and logging it
|
||||
*/
|
||||
private def finishSend(
|
||||
txBuilder: RawTxBuilderWithFinalizer[ShufflingNonInteractiveFinalizer],
|
||||
private def finishSend[F <: RawTxFinalizer](
|
||||
txBuilder: RawTxBuilderWithFinalizer[F],
|
||||
utxoInfos: Vector[ScriptSignatureParams[InputInfo]],
|
||||
sentAmount: CurrencyUnit,
|
||||
feeRate: FeeUnit,
|
||||
@ -416,28 +411,30 @@ abstract class Wallet
|
||||
.findByOutPoint(utxo.outPoint)
|
||||
.map(txDb => utxo.toUTXOInfo(keyManager, txDb.get.transaction)))
|
||||
}
|
||||
inputInfos = utxos.map(_.inputInfo)
|
||||
|
||||
utxoAmount = utxoDbs.map(_.output.value).sum
|
||||
dummyOutput = TransactionOutput(utxoAmount, address.scriptPubKey)
|
||||
inputs = InputUtil.calcSequenceForInputs(utxos)
|
||||
|
||||
dummyTx <-
|
||||
TxUtil.buildDummyTx(utxos.map(_.inputInfo), Vector(dummyOutput))
|
||||
txBuilder = RawTxBuilder() ++= inputs += dummyOutput
|
||||
finalizer = SubtractFeeFromOutputsFinalizer(inputInfos, feeRate)
|
||||
.andThen(ShuffleFinalizer)
|
||||
.andThen(AddWitnessDataFinalizer(inputInfos))
|
||||
|
||||
fee = feeRate * dummyTx
|
||||
amount = utxoAmount - fee
|
||||
withFinalizer = txBuilder.setFinalizer(finalizer)
|
||||
|
||||
_ = require(amount > Policy.dustThreshold,
|
||||
"Utxos are not large enough to send at this fee rate")
|
||||
tmp <- withFinalizer.buildTx()
|
||||
|
||||
output = TransactionOutput(amount, address.scriptPubKey)
|
||||
txBuilder = ShufflingNonInteractiveFinalizer.txBuilderFrom(
|
||||
Vector(output),
|
||||
utxos,
|
||||
feeRate,
|
||||
EmptyScriptPubKey // There will be no change
|
||||
)
|
||||
_ = require(
|
||||
tmp.outputs.size == 1,
|
||||
s"Created tx is not as expected, does not have 1 output, got $tmp")
|
||||
|
||||
tx <- finishSend(txBuilder, utxos, amount, feeRate, Vector.empty)
|
||||
tx <- finishSend(withFinalizer,
|
||||
utxos,
|
||||
tmp.outputs.head.value,
|
||||
feeRate,
|
||||
Vector.empty)
|
||||
} yield tx
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user