Skip to content

Commit 566b409

Browse files
authored
Merge pull request #1115 from guggero/fix-bi86-keys-only
[wallet]: only select BIP-86 script keys for channel funding, add flag to FundVirtualPsbt
2 parents 7177a5a + d942981 commit 566b409

File tree

13 files changed

+568
-364
lines changed

13 files changed

+568
-364
lines changed

itest/mint_fund_seal_test.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,27 @@ func testMintFundSealAssets(t *harnessTest) {
385385
Amt: assetTweakedScriptKey.Amount / 2,
386386
})
387387
require.NoError(t.t, err)
388+
389+
// We only have script encumbered assets now, so selecting BIP-086 only
390+
// assets should result in an error.
391+
const bip86Only = wrpc.CoinSelectType_COIN_SELECT_BIP86_ONLY
392+
_, err = aliceTapd.FundVirtualPsbt(
393+
ctxt, &wrpc.FundVirtualPsbtRequest{
394+
Template: &wrpc.FundVirtualPsbtRequest_Raw{
395+
Raw: &wrpc.TxTemplate{
396+
Recipients: map[string]uint64{
397+
bobAddr.Encoded: 1,
398+
},
399+
},
400+
},
401+
CoinSelectType: bip86Only,
402+
},
403+
)
404+
require.ErrorContains(
405+
t.t, err, "failed to find coin(s) that satisfy given "+
406+
"constraints",
407+
)
408+
388409
signedAddrPsbt, signedPassivePsbts := signTransferWithTweakedScriptKey(
389410
t, ctxt, aliceTapd, bobAddr, &tweakedScript, 2,
390411
tweakedScriptSigLock, tweakedScriptTapTree,

rpcserver.go

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2019,6 +2019,12 @@ func (r *rpcServer) FundVirtualPsbt(ctx context.Context,
20192019
req *wrpc.FundVirtualPsbtRequest) (*wrpc.FundVirtualPsbtResponse,
20202020
error) {
20212021

2022+
coinSelectType, err := unmarshalCoinSelectType(req.CoinSelectType)
2023+
if err != nil {
2024+
return nil, fmt.Errorf("error parsing coin select type: %w",
2025+
err)
2026+
}
2027+
20222028
var fundedVPkt *tapfreighter.FundedVPacket
20232029
switch {
20242030
case req.GetPsbt() != nil:
@@ -2040,9 +2046,8 @@ func (r *rpcServer) FundVirtualPsbt(ctx context.Context,
20402046
"recipients: %w", err)
20412047
}
20422048

2043-
fundedVPkt, err = r.cfg.AssetWallet.FundPacket(
2044-
ctx, desc, vPkt,
2045-
)
2049+
desc.CoinSelectType = coinSelectType
2050+
fundedVPkt, err = r.cfg.AssetWallet.FundPacket(ctx, desc, vPkt)
20462051
if err != nil {
20472052
return nil, fmt.Errorf("error funding packet: %w", err)
20482053
}
@@ -2073,7 +2078,9 @@ func (r *rpcServer) FundVirtualPsbt(ctx context.Context,
20732078
return nil, fmt.Errorf("no recipients specified")
20742079
}
20752080

2076-
fundedVPkt, err = r.cfg.AssetWallet.FundAddressSend(ctx, addr)
2081+
fundedVPkt, err = r.cfg.AssetWallet.FundAddressSend(
2082+
ctx, coinSelectType, addr,
2083+
)
20772084
if err != nil {
20782085
return nil, fmt.Errorf("error funding address send: "+
20792086
"%w", err)
@@ -2117,6 +2124,26 @@ func (r *rpcServer) FundVirtualPsbt(ctx context.Context,
21172124
return response, nil
21182125
}
21192126

2127+
// unmarshalCoinSelectType converts an RPC select type into a native one.
2128+
func unmarshalCoinSelectType(
2129+
coinSelectType wrpc.CoinSelectType) (tapsend.CoinSelectType, error) {
2130+
2131+
switch coinSelectType {
2132+
case wrpc.CoinSelectType_COIN_SELECT_DEFAULT:
2133+
return tapsend.DefaultCoinSelectType, nil
2134+
2135+
case wrpc.CoinSelectType_COIN_SELECT_BIP86_ONLY:
2136+
return tapsend.Bip86Only, nil
2137+
2138+
case wrpc.CoinSelectType_COIN_SELECT_SCRIPT_TREES_ALLOWED:
2139+
return tapsend.ScriptTreesAllowed, nil
2140+
2141+
default:
2142+
return 0, fmt.Errorf("unknown coin select type: %d",
2143+
coinSelectType)
2144+
}
2145+
}
2146+
21202147
// SignVirtualPsbt signs the inputs of a virtual transaction and prepares the
21212148
// commitments of the inputs and outputs.
21222149
func (r *rpcServer) SignVirtualPsbt(ctx context.Context,

tapchannel/aux_funding_controller.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -697,6 +697,7 @@ func (f *FundingController) fundVirtualPacket(ctx context.Context,
697697

698698
// Fund the packet. This will derive an anchor internal key for us, but
699699
// we'll overwrite that later on.
700+
fundDesc.CoinSelectType = tapsend.Bip86Only
700701
return f.cfg.AssetWallet.FundPacket(ctx, fundDesc, pktTemplate)
701702
}
702703

tapdb/assets_store.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"github.com/lightninglabs/taproot-assets/tapdb/sqlc"
2424
"github.com/lightninglabs/taproot-assets/tapfreighter"
2525
"github.com/lightninglabs/taproot-assets/tappsbt"
26+
"github.com/lightninglabs/taproot-assets/tapsend"
2627
"github.com/lightningnetwork/lnd/clock"
2728
"github.com/lightningnetwork/lnd/keychain"
2829
)
@@ -873,7 +874,11 @@ func (a *AssetStore) constraintsToDbFilter(
873874
// TODO(roasbeef): only want to allow asset ID or other and not
874875
// both?
875876

876-
if query.Bip86ScriptKeysOnly {
877+
switch query.CoinSelectType {
878+
case tapsend.ScriptTreesAllowed:
879+
assetFilter.Bip86ScriptKeysOnly = false
880+
881+
default:
877882
assetFilter.Bip86ScriptKeysOnly = true
878883
}
879884
}

tapdb/assets_store_test.go

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"github.com/lightninglabs/taproot-assets/proof"
2424
"github.com/lightninglabs/taproot-assets/tapfreighter"
2525
"github.com/lightninglabs/taproot-assets/tapscript"
26+
"github.com/lightninglabs/taproot-assets/tapsend"
2627
"github.com/lightningnetwork/lnd/input"
2728
"github.com/lightningnetwork/lnd/keychain"
2829
"github.com/stretchr/testify/require"
@@ -758,11 +759,11 @@ func TestFetchAllAssets(t *testing.T) {
758759
scriptKey: scriptKeyWithScript,
759760
}}
760761
makeFilter := func(amt uint64, anchorHeight int32,
761-
bip86ScriptKeysOnly bool) *AssetQueryFilters {
762+
coinSelectType tapsend.CoinSelectType) *AssetQueryFilters {
762763

763764
constraints := tapfreighter.CommitmentConstraints{
764-
MinAmt: amt,
765-
Bip86ScriptKeysOnly: bip86ScriptKeysOnly,
765+
MinAmt: amt,
766+
CoinSelectType: coinSelectType,
766767
}
767768
return &AssetQueryFilters{
768769
CommitmentConstraints: constraints,
@@ -795,41 +796,41 @@ func TestFetchAllAssets(t *testing.T) {
795796
numAssets: 10,
796797
}, {
797798
name: "min amount",
798-
filter: makeFilter(12, 0, false),
799+
filter: makeFilter(12, 0, tapsend.ScriptTreesAllowed),
799800
numAssets: 2,
800801
}, {
801802
name: "min amount, include spent",
802-
filter: makeFilter(12, 0, false),
803+
filter: makeFilter(12, 0, tapsend.ScriptTreesAllowed),
803804
includeSpent: true,
804805
numAssets: 4,
805806
}, {
806807
name: "min amount, include leased",
807-
filter: makeFilter(12, 0, false),
808+
filter: makeFilter(12, 0, tapsend.ScriptTreesAllowed),
808809
includeLeased: true,
809810
numAssets: 5,
810811
}, {
811812
name: "min amount, include leased, include spent",
812-
filter: makeFilter(12, 0, false),
813+
filter: makeFilter(12, 0, tapsend.ScriptTreesAllowed),
813814
includeLeased: true,
814815
includeSpent: true,
815816
numAssets: 8,
816817
}, {
817818
name: "default min height, include spent",
818-
filter: makeFilter(0, 500, false),
819+
filter: makeFilter(0, 500, tapsend.ScriptTreesAllowed),
819820
includeSpent: true,
820821
numAssets: 6,
821822
}, {
822823
name: "specific height",
823-
filter: makeFilter(0, 502, false),
824+
filter: makeFilter(0, 502, tapsend.ScriptTreesAllowed),
824825
numAssets: 0,
825826
}, {
826827
name: "default min height, include spent",
827-
filter: makeFilter(0, 502, false),
828+
filter: makeFilter(0, 502, tapsend.ScriptTreesAllowed),
828829
includeSpent: true,
829830
numAssets: 1,
830831
}, {
831832
name: "script key with tapscript",
832-
filter: makeFilter(100, 0, true),
833+
filter: makeFilter(100, 0, tapsend.Bip86Only),
833834
numAssets: 0,
834835
}}
835836

tapfreighter/chain_porter.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -994,7 +994,7 @@ func (p *ChainPorter) stateStep(currentPkg sendPackage) (*sendPackage, error) {
994994
"address parcel")
995995
}
996996
fundSendRes, err := p.cfg.AssetWallet.FundAddressSend(
997-
ctx, addrParcel.destAddrs...,
997+
ctx, tapsend.Bip86Only, addrParcel.destAddrs...,
998998
)
999999
if err != nil {
10001000
return nil, fmt.Errorf("unable to fund address send: "+

tapfreighter/coin_select.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ func (s *CoinSelect) SelectCoins(ctx context.Context,
5454
listConstraints := CommitmentConstraints{
5555
AssetSpecifier: constraints.AssetSpecifier,
5656
MinAmt: 1,
57+
CoinSelectType: constraints.CoinSelectType,
5758
}
5859
eligibleCommitments, err := s.coinLister.ListEligibleCoins(
5960
ctx, listConstraints,

tapfreighter/interface.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"github.com/lightninglabs/taproot-assets/tapgarden"
1818
"github.com/lightninglabs/taproot-assets/tappsbt"
1919
"github.com/lightninglabs/taproot-assets/tapscript"
20+
"github.com/lightninglabs/taproot-assets/tapsend"
2021
"github.com/lightningnetwork/lnd/keychain"
2122
)
2223

@@ -34,9 +35,8 @@ type CommitmentConstraints struct {
3435
// to satisfy the constraints.
3536
MinAmt uint64
3637

37-
// Bip86ScriptKeysOnly is a flag that when set, will exclude any assets
38-
// that have a script key with a tapscript tree (a non-empty tweak).
39-
Bip86ScriptKeysOnly bool
38+
// CoinSelectType is the type of coins that should be selected.
39+
CoinSelectType tapsend.CoinSelectType
4040
}
4141

4242
// String returns the string representation of the commitment constraints.
@@ -131,8 +131,7 @@ type CoinSelector interface {
131131
SelectCoins(ctx context.Context, constraints CommitmentConstraints,
132132
strategy MultiCommitmentSelectStrategy,
133133
maxVersion commitment.TapCommitmentVersion,
134-
) ([]*AnchoredCommitment,
135-
error)
134+
) ([]*AnchoredCommitment, error)
136135

137136
// ReleaseCoins releases/unlocks coins that were previously leased and
138137
// makes them available for coin selection again.

tapfreighter/wallet.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ type Wallet interface {
6868
// asset re-anchors and the Taproot Asset level commitment of the
6969
// selected assets.
7070
FundAddressSend(ctx context.Context,
71+
coinSelectType tapsend.CoinSelectType,
7172
receiverAddrs ...*address.Tap) (*FundedVPacket, error)
7273

7374
// FundPacket funds a virtual transaction, selecting assets to spend
@@ -234,6 +235,7 @@ type FundedVPacket struct {
234235
//
235236
// NOTE: This is part of the Wallet interface.
236237
func (f *AssetWallet) FundAddressSend(ctx context.Context,
238+
coinSelectType tapsend.CoinSelectType,
237239
receiverAddrs ...*address.Tap) (*FundedVPacket, error) {
238240

239241
// We start by creating a new virtual transaction that will be used to
@@ -251,6 +253,7 @@ func (f *AssetWallet) FundAddressSend(ctx context.Context,
251253
return nil, fmt.Errorf("unable to describe recipients: %w", err)
252254
}
253255

256+
fundDesc.CoinSelectType = coinSelectType
254257
fundedVPkt, err := f.FundPacket(ctx, fundDesc, vPkt)
255258
if err != nil {
256259
return nil, err
@@ -365,9 +368,9 @@ func (f *AssetWallet) FundPacket(ctx context.Context,
365368
// send request. We'll map the address to a set of constraints, so we
366369
// can use that to do Taproot asset coin selection.
367370
constraints := CommitmentConstraints{
368-
AssetSpecifier: fundDesc.AssetSpecifier,
369-
MinAmt: fundDesc.Amount,
370-
Bip86ScriptKeysOnly: true,
371+
AssetSpecifier: fundDesc.AssetSpecifier,
372+
MinAmt: fundDesc.Amount,
373+
CoinSelectType: fundDesc.CoinSelectType,
371374
}
372375

373376
anchorVersion, err := tappsbt.CommitmentVersion(vPkt.Version)

0 commit comments

Comments
 (0)