Skip to content

Commit

Permalink
sweep: add required TxOuts to sweep tx
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
halseth committed Nov 20, 2020
1 parent 7f9df26 commit 616503d
Showing 1 changed file with 55 additions and 10 deletions.
65 changes: 55 additions & 10 deletions sweep/txgenerator.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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),
})
}

Expand Down Expand Up @@ -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
Expand All @@ -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)
}

Expand Down

0 comments on commit 616503d

Please sign in to comment.