Skip to content

Commit 23ee318

Browse files
committed
sweepbatcher: consider change in unsigned batch tx
Optional change of a swap is encoded in its sweeps as a pointer to the same change output. This change is taken into account when constructing the unsigned batch transaction when it comes to tx weight and outputs.
1 parent 8464bd2 commit 23ee318

File tree

2 files changed

+54
-9
lines changed

2 files changed

+54
-9
lines changed

sweepbatcher/sweep_batch.go

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,9 @@ type sweep struct {
125125

126126
// presigned is set, if the sweep should be handled in presigned mode.
127127
presigned bool
128+
129+
// change is the optional change output of the sweep.
130+
change *wire.TxOut
128131
}
129132

130133
// batchState is the state of the batch.
@@ -1238,6 +1241,7 @@ func (b *batch) createPsbt(unsignedTx *wire.MsgTx, sweeps []sweep) ([]byte,
12381241
// constructUnsignedTx creates unsigned tx from the sweeps, paying to the addr.
12391242
// It also returns absolute fee (from weight and clamped).
12401243
func constructUnsignedTx(sweeps []sweep, address btcutil.Address,
1244+
changeOutputs map[*wire.TxOut]btcutil.Address,
12411245
currentHeight int32, feeRate chainfee.SatPerKWeight) (*wire.MsgTx,
12421246
lntypes.WeightUnit, btcutil.Amount, btcutil.Amount, error) {
12431247

@@ -1297,6 +1301,20 @@ func constructUnsignedTx(sweeps []sweep, address btcutil.Address,
12971301
"failed: %w", err)
12981302
}
12991303

1304+
// Add the optional change outputs to weight estimates.
1305+
if len(changeOutputs) > 0 {
1306+
for _, addr := range changeOutputs {
1307+
// Add the output to weight estimates.
1308+
err = sweeppkg.AddOutputEstimate(
1309+
&weightEstimate, addr,
1310+
)
1311+
if err != nil {
1312+
return nil, 0, 0, 0, fmt.Errorf("sweep."+
1313+
"AddOutputEstimate failed: %w", err)
1314+
}
1315+
}
1316+
}
1317+
13001318
// Keep track of the total amount this batch is sweeping back.
13011319
batchAmt := btcutil.Amount(0)
13021320
for _, sweep := range sweeps {
@@ -1318,11 +1336,29 @@ func constructUnsignedTx(sweeps []sweep, address btcutil.Address,
13181336
fee := clampBatchFee(feeForWeight, batchAmt)
13191337

13201338
// Add the batch transaction output, which excludes the fees paid to
1321-
// miners.
1322-
batchTx.AddTxOut(&wire.TxOut{
1323-
PkScript: batchPkScript,
1324-
Value: int64(batchAmt - fee),
1325-
})
1339+
// miners. Reduce the amount by the sum of change outputs, if any.
1340+
if len(changeOutputs) == 0 {
1341+
batchTx.AddTxOut(&wire.TxOut{
1342+
PkScript: batchPkScript,
1343+
Value: int64(batchAmt - fee),
1344+
})
1345+
} else if len(changeOutputs) > 0 {
1346+
// Reduce the batch output by the sum of change outputs.
1347+
var sumChange int64
1348+
for change := range changeOutputs {
1349+
sumChange += change.Value
1350+
}
1351+
batchTx.AddTxOut(&wire.TxOut{
1352+
PkScript: batchPkScript,
1353+
Value: int64(batchAmt-fee) - sumChange,
1354+
})
1355+
for txOut := range changeOutputs {
1356+
batchTx.AddTxOut(&wire.TxOut{
1357+
PkScript: txOut.PkScript,
1358+
Value: txOut.Value,
1359+
})
1360+
}
1361+
}
13261362

13271363
return batchTx, weight, feeForWeight, fee, nil
13281364
}
@@ -1396,9 +1432,13 @@ func (b *batch) publishMixedBatch(ctx context.Context) (btcutil.Amount, error,
13961432
attempt)
13971433

13981434
// Construct unsigned batch transaction.
1399-
var err error
1435+
var (
1436+
err error
1437+
changeOutputs map[*wire.TxOut]btcutil.Address
1438+
)
14001439
tx, weight, feeForWeight, fee, err = constructUnsignedTx(
1401-
sweeps, address, b.currentHeight, b.rbfCache.FeeRate,
1440+
sweeps, address, changeOutputs, b.currentHeight,
1441+
b.rbfCache.FeeRate,
14021442
)
14031443
if err != nil {
14041444
return 0, fmt.Errorf("failed to construct tx: %w", err),

sweepbatcher/sweep_batch_test.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -338,9 +338,14 @@ func TestConstructUnsignedTx(t *testing.T) {
338338

339339
for _, tc := range cases {
340340
t.Run(tc.name, func(t *testing.T) {
341+
changeOutputs, err := getChangeOutputs(
342+
tc.sweeps, &chaincfg.RegressionNetParams,
343+
)
344+
require.NoError(t, err)
345+
341346
tx, weight, feeForW, fee, err := constructUnsignedTx(
342-
tc.sweeps, tc.address, tc.currentHeight,
343-
tc.feeRate,
347+
tc.sweeps, tc.address, changeOutputs,
348+
tc.currentHeight, tc.feeRate,
344349
)
345350
if tc.wantErr != "" {
346351
require.Error(t, err)

0 commit comments

Comments
 (0)