sweep: add required TxOuts to sweep tx

Now that inputs might have accompanied outputs to be added to the sweep
tx, we add them to the sweep transaction first, and account for it when
calculating the change amount.
This commit is contained in:
Johan T. Halseth 2020-11-16 12:52:22 +01:00
parent 7f9df26efd
commit 616503de3e
No known key found for this signature in database
GPG Key ID: 15BAADA29DA20D26

View File

@ -147,15 +147,23 @@ func createSweepTx(inputs []input.Input, outputPkScript []byte,
// Track whether any of the inputs require a certain locktime.
locktime := int32(-1)
// Sum up the total value contained in the inputs, and add all inputs
// to the sweep transaction. Ensure that for each csvInput, we set the
// sequence number properly.
var totalSum btcutil.Amount
// We start by adding all inputs that commit to an output. We do this
// since the input and output index must stay the same for the
// signatures to be valid.
var (
totalInput btcutil.Amount
requiredOutput btcutil.Amount
)
for _, o := range inputs {
if o.RequiredTxOut() == nil {
continue
}
sweepTx.AddTxIn(&wire.TxIn{
PreviousOutPoint: *o.OutPoint(),
Sequence: o.BlocksToMaturity(),
})
sweepTx.AddTxOut(o.RequiredTxOut())
if lt, ok := o.RequiredLockTime(); ok {
// If another input commits to a different locktime,
@ -167,18 +175,44 @@ func createSweepTx(inputs []input.Input, outputPkScript []byte,
locktime = int32(lt)
}
totalSum += btcutil.Amount(o.SignDesc().Output.Value)
totalInput += btcutil.Amount(o.SignDesc().Output.Value)
requiredOutput += btcutil.Amount(o.RequiredTxOut().Value)
}
// Sweep as much possible, after subtracting txn fees.
sweepAmt := totalSum - txFee
// Sum up the value contained in the remaining inputs, and add them to
// the sweep transaction.
for _, o := range inputs {
if o.RequiredTxOut() != nil {
continue
}
sweepTx.AddTxIn(&wire.TxIn{
PreviousOutPoint: *o.OutPoint(),
Sequence: o.BlocksToMaturity(),
})
if lt, ok := o.RequiredLockTime(); ok {
if locktime != -1 && locktime != int32(lt) {
return nil, fmt.Errorf("incompatible locktime")
}
locktime = int32(lt)
}
totalInput += btcutil.Amount(o.SignDesc().Output.Value)
}
// The value remaining after the required output and fees, go to
// change. Not that this fee is what we would have to pay in case the
// sweep tx has a change output.
changeAmt := totalInput - requiredOutput - txFee
// The txn will sweep the amount after fees to the pkscript generated
// above.
if sweepAmt >= dustLimit {
if changeAmt >= dustLimit {
sweepTx.AddTxOut(&wire.TxOut{
PkScript: outputPkScript,
Value: int64(sweepAmt),
Value: int64(changeAmt),
})
}
@ -255,7 +289,12 @@ func getWeightEstimate(inputs []input.Input, feeRate chainfee.SatPerKWeight) (
weightEstimate := newWeightEstimator(feeRate)
// Our sweep transaction will pay to a single segwit p2wkh address,
// ensure it contributes to our weight estimate.
// ensure it contributes to our weight estimate. If the inputs we add
// have required TxOuts, then this will be our change address. Note
// that if we have required TxOuts, we might end up creating a sweep tx
// without a change output. It is okay to add the change output to the
// weight estimate regardless, since the estimated fee will just be
// subtracted from this already dust output, and trimmed.
weightEstimate.addP2WKHOutput()
// For each output, use its witness type to determine the estimate
@ -274,6 +313,12 @@ func getWeightEstimate(inputs []input.Input, feeRate chainfee.SatPerKWeight) (
continue
}
// If this input comes with a committed output, add that as
// well.
if inp.RequiredTxOut() != nil {
weightEstimate.addOutput(inp.RequiredTxOut())
}
sweepInputs = append(sweepInputs, inp)
}