rpcserver: return inputs in EstimateFeeResponse
What changed, and why it matters
This commit updates the EstimateFee RPC in LND so that callers can optionally specify which wallet inputs (UTXOs) to use for the fee estimate, and the response now lists the inputs that were actually selected. It is a feature/enhancement change. There is no direct evidence in the commit that this fixes a security vulnerability; it mainly improves transparency and control for API users.
Treat as a routine feature update. Review the duplicate-input check for correctness and ensure the new Inputs field in the protobuf response is documented. No urgent security action is indicated by the diff alone.
Security signals we found
Added duplicate-outpoint validation on user-supplied inputs before passing to wallet coin selection
New response field exposes which inputs were used in the fee estimate, improving auditability
Evidence from the diff
The patch modifies rpcserver.go’s EstimateFee handler. Previously, CreateSimpleTx was called with nil for the selected outpoints parameter, meaning the wallet chose inputs automatically. The change: (1) converts in.Inputs to wire.OutPoints, (2) rejects duplicate outpoints, (3) passes the selected set into CreateSimpleTx, and (4) returns the tx.Tx.TxIn previous outpoints in the new EstimateFeeResponse.Inputs field. The duplicate-check is a minor input-validation hardening, but the dominant nature of the change is adding user-specified coin selection and response fields.
Changed components
rpcserver.go EstimateFee RPC handlerlnrpc.EstimateFeeResponse messagewallet.CreateSimpleTx coin-selection pathInspect captured patch +31 / −2
diff --git a/rpcserver.go b/rpcserver.go
index 29efd15..21563a8 100644
--- a/rpcserver.go
+++ b/rpcserver.go
@@ -1275,14 +1275,29 @@ func (r *rpcServer) EstimateFee(ctx context.Context,
return nil, err
}
+ var selectOutpoints fn.Set[wire.OutPoint]
+ if len(in.Inputs) != 0 {
+ wireOutpoints, err := toWireOutpoints(in.Inputs)
+ if err != nil {
+ return nil, fmt.Errorf("can't create outpoints %w", err)
+ }
+
+ if fn.HasDuplicates(wireOutpoints) {
+ return nil, fmt.Errorf("selected outpoints contain " +
+ "duplicate values")
+ }
+
+ selectOutpoints = fn.NewSet(wireOutpoints...)
+ }
+
// We will ask the wallet to create a tx using this fee rate. We set
// dryRun=true to avoid inflating the change addresses in the db.
var tx *txauthor.AuthoredTx
wallet := r.server.cc.Wallet
err = wallet.WithCoinSelectLock(func() error {
tx, err = wallet.CreateSimpleTx(
- nil, outputs, feePerKw, minConfs, coinSelectionStrategy,
- true,
+ selectOutpoints, outputs, feePerKw, minConfs,
+ coinSelectionStrategy, true,
)
return err
})
@@ -1297,12 +1312,26 @@ func (r *rpcServer) EstimateFee(ctx context.Context,
}
totalFee := int64(tx.TotalInput) - totalOutput
+ // Return the inputs the estimate is for.
+ outStr := make([]string, 0, len(tx.Tx.TxIn))
+ for _, txIn := range tx.Tx.TxIn {
+ outStr = append(
+ outStr, txIn.PreviousOutPoint.String(),
+ )
+ }
+
+ inputs, err := UtxosToOutpoints(outStr)
+ if err != nil {
+ return nil, fmt.Errorf("can't convert outpoints %w", err)
+ }
+
resp := &lnrpc.EstimateFeeResponse{
FeeSat: totalFee,
SatPerVbyte: uint64(feePerKw.FeePerVByte()),
// Deprecated field.
FeerateSatPerByte: int64(feePerKw.FeePerVByte()),
+ Inputs: inputs,
}
rpcsLog.Debugf("[estimatefee] fee estimate for conf target %d: %v",
Why this scored 19/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.