Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[wallet]: only select BIP-86 script keys for channel funding, add flag to FundVirtualPsbt #1115

Merged
merged 4 commits into from
Sep 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.
guggero marked this conversation as resolved.
Show resolved Hide resolved
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(
guggero marked this conversation as resolved.
Show resolved Hide resolved
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
Loading