Skip to content

Commit

Permalink
Merge pull request #1115 from guggero/fix-bi86-keys-only
Browse files Browse the repository at this point in the history
[wallet]: only select BIP-86 script keys for channel funding, add flag to FundVirtualPsbt
  • Loading branch information
Roasbeef authored Sep 10, 2024
2 parents 7177a5a + d942981 commit 566b409
Show file tree
Hide file tree
Showing 13 changed files with 568 additions and 364 deletions.
21 changes: 21 additions & 0 deletions itest/mint_fund_seal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,27 @@ func testMintFundSealAssets(t *harnessTest) {
Amt: assetTweakedScriptKey.Amount / 2,
})
require.NoError(t.t, err)

// We only have script encumbered assets now, so selecting BIP-086 only
// assets should result in an error.
const bip86Only = wrpc.CoinSelectType_COIN_SELECT_BIP86_ONLY
_, err = aliceTapd.FundVirtualPsbt(
ctxt, &wrpc.FundVirtualPsbtRequest{
Template: &wrpc.FundVirtualPsbtRequest_Raw{
Raw: &wrpc.TxTemplate{
Recipients: map[string]uint64{
bobAddr.Encoded: 1,
},
},
},
CoinSelectType: bip86Only,
},
)
require.ErrorContains(
t.t, err, "failed to find coin(s) that satisfy given "+
"constraints",
)

signedAddrPsbt, signedPassivePsbts := signTransferWithTweakedScriptKey(
t, ctxt, aliceTapd, bobAddr, &tweakedScript, 2,
tweakedScriptSigLock, tweakedScriptTapTree,
Expand Down
35 changes: 31 additions & 4 deletions rpcserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -2019,6 +2019,12 @@ func (r *rpcServer) FundVirtualPsbt(ctx context.Context,
req *wrpc.FundVirtualPsbtRequest) (*wrpc.FundVirtualPsbtResponse,
error) {

coinSelectType, err := unmarshalCoinSelectType(req.CoinSelectType)
if err != nil {
return nil, fmt.Errorf("error parsing coin select type: %w",
err)
}

var fundedVPkt *tapfreighter.FundedVPacket
switch {
case req.GetPsbt() != nil:
Expand All @@ -2040,9 +2046,8 @@ func (r *rpcServer) FundVirtualPsbt(ctx context.Context,
"recipients: %w", err)
}

fundedVPkt, err = r.cfg.AssetWallet.FundPacket(
ctx, desc, vPkt,
)
desc.CoinSelectType = coinSelectType
fundedVPkt, err = r.cfg.AssetWallet.FundPacket(ctx, desc, vPkt)
if err != nil {
return nil, fmt.Errorf("error funding packet: %w", err)
}
Expand Down Expand Up @@ -2073,7 +2078,9 @@ func (r *rpcServer) FundVirtualPsbt(ctx context.Context,
return nil, fmt.Errorf("no recipients specified")
}

fundedVPkt, err = r.cfg.AssetWallet.FundAddressSend(ctx, addr)
fundedVPkt, err = r.cfg.AssetWallet.FundAddressSend(
ctx, coinSelectType, addr,
)
if err != nil {
return nil, fmt.Errorf("error funding address send: "+
"%w", err)
Expand Down Expand Up @@ -2117,6 +2124,26 @@ func (r *rpcServer) FundVirtualPsbt(ctx context.Context,
return response, nil
}

// unmarshalCoinSelectType converts an RPC select type into a native one.
func unmarshalCoinSelectType(
coinSelectType wrpc.CoinSelectType) (tapsend.CoinSelectType, error) {

switch coinSelectType {
case wrpc.CoinSelectType_COIN_SELECT_DEFAULT:
return tapsend.DefaultCoinSelectType, nil

case wrpc.CoinSelectType_COIN_SELECT_BIP86_ONLY:
return tapsend.Bip86Only, nil

case wrpc.CoinSelectType_COIN_SELECT_SCRIPT_TREES_ALLOWED:
return tapsend.ScriptTreesAllowed, nil

default:
return 0, fmt.Errorf("unknown coin select type: %d",
coinSelectType)
}
}

// SignVirtualPsbt signs the inputs of a virtual transaction and prepares the
// commitments of the inputs and outputs.
func (r *rpcServer) SignVirtualPsbt(ctx context.Context,
Expand Down
1 change: 1 addition & 0 deletions tapchannel/aux_funding_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -697,6 +697,7 @@ func (f *FundingController) fundVirtualPacket(ctx context.Context,

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

Expand Down
7 changes: 6 additions & 1 deletion tapdb/assets_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"github.com/lightninglabs/taproot-assets/tapdb/sqlc"
"github.com/lightninglabs/taproot-assets/tapfreighter"
"github.com/lightninglabs/taproot-assets/tappsbt"
"github.com/lightninglabs/taproot-assets/tapsend"
"github.com/lightningnetwork/lnd/clock"
"github.com/lightningnetwork/lnd/keychain"
)
Expand Down Expand Up @@ -873,7 +874,11 @@ func (a *AssetStore) constraintsToDbFilter(
// TODO(roasbeef): only want to allow asset ID or other and not
// both?

if query.Bip86ScriptKeysOnly {
switch query.CoinSelectType {
case tapsend.ScriptTreesAllowed:
assetFilter.Bip86ScriptKeysOnly = false

default:
assetFilter.Bip86ScriptKeysOnly = true
}
}
Expand Down
23 changes: 12 additions & 11 deletions tapdb/assets_store_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"github.com/lightninglabs/taproot-assets/proof"
"github.com/lightninglabs/taproot-assets/tapfreighter"
"github.com/lightninglabs/taproot-assets/tapscript"
"github.com/lightninglabs/taproot-assets/tapsend"
"github.com/lightningnetwork/lnd/input"
"github.com/lightningnetwork/lnd/keychain"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -758,11 +759,11 @@ func TestFetchAllAssets(t *testing.T) {
scriptKey: scriptKeyWithScript,
}}
makeFilter := func(amt uint64, anchorHeight int32,
bip86ScriptKeysOnly bool) *AssetQueryFilters {
coinSelectType tapsend.CoinSelectType) *AssetQueryFilters {

constraints := tapfreighter.CommitmentConstraints{
MinAmt: amt,
Bip86ScriptKeysOnly: bip86ScriptKeysOnly,
MinAmt: amt,
CoinSelectType: coinSelectType,
}
return &AssetQueryFilters{
CommitmentConstraints: constraints,
Expand Down Expand Up @@ -795,41 +796,41 @@ func TestFetchAllAssets(t *testing.T) {
numAssets: 10,
}, {
name: "min amount",
filter: makeFilter(12, 0, false),
filter: makeFilter(12, 0, tapsend.ScriptTreesAllowed),
numAssets: 2,
}, {
name: "min amount, include spent",
filter: makeFilter(12, 0, false),
filter: makeFilter(12, 0, tapsend.ScriptTreesAllowed),
includeSpent: true,
numAssets: 4,
}, {
name: "min amount, include leased",
filter: makeFilter(12, 0, false),
filter: makeFilter(12, 0, tapsend.ScriptTreesAllowed),
includeLeased: true,
numAssets: 5,
}, {
name: "min amount, include leased, include spent",
filter: makeFilter(12, 0, false),
filter: makeFilter(12, 0, tapsend.ScriptTreesAllowed),
includeLeased: true,
includeSpent: true,
numAssets: 8,
}, {
name: "default min height, include spent",
filter: makeFilter(0, 500, false),
filter: makeFilter(0, 500, tapsend.ScriptTreesAllowed),
includeSpent: true,
numAssets: 6,
}, {
name: "specific height",
filter: makeFilter(0, 502, false),
filter: makeFilter(0, 502, tapsend.ScriptTreesAllowed),
numAssets: 0,
}, {
name: "default min height, include spent",
filter: makeFilter(0, 502, false),
filter: makeFilter(0, 502, tapsend.ScriptTreesAllowed),
includeSpent: true,
numAssets: 1,
}, {
name: "script key with tapscript",
filter: makeFilter(100, 0, true),
filter: makeFilter(100, 0, tapsend.Bip86Only),
numAssets: 0,
}}

Expand Down
2 changes: 1 addition & 1 deletion tapfreighter/chain_porter.go
Original file line number Diff line number Diff line change
Expand Up @@ -994,7 +994,7 @@ func (p *ChainPorter) stateStep(currentPkg sendPackage) (*sendPackage, error) {
"address parcel")
}
fundSendRes, err := p.cfg.AssetWallet.FundAddressSend(
ctx, addrParcel.destAddrs...,
ctx, tapsend.Bip86Only, addrParcel.destAddrs...,
)
if err != nil {
return nil, fmt.Errorf("unable to fund address send: "+
Expand Down
1 change: 1 addition & 0 deletions tapfreighter/coin_select.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ func (s *CoinSelect) SelectCoins(ctx context.Context,
listConstraints := CommitmentConstraints{
AssetSpecifier: constraints.AssetSpecifier,
MinAmt: 1,
CoinSelectType: constraints.CoinSelectType,
}
eligibleCommitments, err := s.coinLister.ListEligibleCoins(
ctx, listConstraints,
Expand Down
9 changes: 4 additions & 5 deletions tapfreighter/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"github.com/lightninglabs/taproot-assets/tapgarden"
"github.com/lightninglabs/taproot-assets/tappsbt"
"github.com/lightninglabs/taproot-assets/tapscript"
"github.com/lightninglabs/taproot-assets/tapsend"
"github.com/lightningnetwork/lnd/keychain"
)

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

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

// String returns the string representation of the commitment constraints.
Expand Down Expand Up @@ -131,8 +131,7 @@ type CoinSelector interface {
SelectCoins(ctx context.Context, constraints CommitmentConstraints,
strategy MultiCommitmentSelectStrategy,
maxVersion commitment.TapCommitmentVersion,
) ([]*AnchoredCommitment,
error)
) ([]*AnchoredCommitment, error)

// ReleaseCoins releases/unlocks coins that were previously leased and
// makes them available for coin selection again.
Expand Down
9 changes: 6 additions & 3 deletions tapfreighter/wallet.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ type Wallet interface {
// asset re-anchors and the Taproot Asset level commitment of the
// selected assets.
FundAddressSend(ctx context.Context,
coinSelectType tapsend.CoinSelectType,
receiverAddrs ...*address.Tap) (*FundedVPacket, error)

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

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

fundDesc.CoinSelectType = coinSelectType
fundedVPkt, err := f.FundPacket(ctx, fundDesc, vPkt)
if err != nil {
return nil, err
Expand Down Expand Up @@ -365,9 +368,9 @@ func (f *AssetWallet) FundPacket(ctx context.Context,
// send request. We'll map the address to a set of constraints, so we
// can use that to do Taproot asset coin selection.
constraints := CommitmentConstraints{
AssetSpecifier: fundDesc.AssetSpecifier,
MinAmt: fundDesc.Amount,
Bip86ScriptKeysOnly: true,
AssetSpecifier: fundDesc.AssetSpecifier,
MinAmt: fundDesc.Amount,
CoinSelectType: fundDesc.CoinSelectType,
}

anchorVersion, err := tappsbt.CommitmentVersion(vPkt.Version)
Expand Down
Loading

0 comments on commit 566b409

Please sign in to comment.