From e710ea5e8f34fd2b591d5468e0d509a8d2656f16 Mon Sep 17 00:00:00 2001 From: Slyghtning Date: Thu, 19 Feb 2026 09:54:58 +0100 Subject: [PATCH] openchannel: reject duplicate outpoints in open channel request Duplicate outpoints in the request lead to fee miscalculation and an invalid PSBT with the same input listed twice. Validate early and return a clear error message. --- staticaddr/openchannel/manager.go | 12 +++++++++++ staticaddr/openchannel/manager_test.go | 28 ++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/staticaddr/openchannel/manager.go b/staticaddr/openchannel/manager.go index b7472c57..acf18732 100644 --- a/staticaddr/openchannel/manager.go +++ b/staticaddr/openchannel/manager.go @@ -299,6 +299,18 @@ func (m *Manager) OpenChannel(ctx context.Context, err) } + // Check for duplicate outpoints which would lead to fee + // miscalculation and an invalid PSBT with the same input + // listed twice. + seen := make(map[wire.OutPoint]struct{}, len(outpoints)) + for _, op := range outpoints { + if _, ok := seen[op]; ok { + return nil, fmt.Errorf("duplicate outpoint "+ + "%v in request", op) + } + seen[op] = struct{}{} + } + deposits, allActive = m.cfg.DepositManager.AllOutpointsActiveDeposits( outpoints, deposit.Deposited, diff --git a/staticaddr/openchannel/manager_test.go b/staticaddr/openchannel/manager_test.go index 807d275f..db330e01 100644 --- a/staticaddr/openchannel/manager_test.go +++ b/staticaddr/openchannel/manager_test.go @@ -210,6 +210,34 @@ func testOutPoint(b byte) wire.OutPoint { } } +func TestOpenChannelDuplicateOutpoints(t *testing.T) { + t.Parallel() + + op := testOutPoint(1) + manager := &Manager{ + cfg: &Config{}, + } + + req := &lnrpc.OpenChannelRequest{ + NodePubkey: make([]byte, 33), + LocalFundingAmount: 100000, + SatPerVbyte: 10, + Outpoints: []*lnrpc.OutPoint{ + { + TxidStr: op.Hash.String(), + OutputIndex: op.Index, + }, + { + TxidStr: op.Hash.String(), + OutputIndex: op.Index, + }, + }, + } + + _, err := manager.OpenChannel(context.Background(), req) + require.ErrorContains(t, err, "duplicate outpoint") +} + func TestValidateInitialPsbtFlags(t *testing.T) { t.Parallel()