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

[psbt saga part 4/4]: Multisig demo #796

Merged
merged 5 commits into from
Mar 21, 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
15 changes: 12 additions & 3 deletions itest/addrs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -554,11 +554,20 @@ func sendProof(t *harnessTest, src, dst *tapdHarness,
}, defaultWaitTimeout)
require.NoError(t.t, waitErr)

t.Logf("Importing proof %x", proofResp.RawProofFile)
return importProof(t, dst, proofResp.RawProofFile, genInfo.GenesisPoint)
}

// importProof manually imports a proof using the development only ImportProof
// RPC.
func importProof(t *harnessTest, dst *tapdHarness, rawFile []byte,
genesisPoint string) *tapdevrpc.ImportProofResponse {

t.Logf("Importing proof %x", rawFile)

ctxb := context.Background()
importResp, err := dst.ImportProof(ctxb, &tapdevrpc.ImportProofRequest{
ProofFile: proofResp.RawProofFile,
GenesisPoint: genInfo.GenesisPoint,
ProofFile: rawFile,
GenesisPoint: genesisPoint,
})
require.NoError(t.t, err)

Expand Down
9 changes: 4 additions & 5 deletions itest/assertions.go
Original file line number Diff line number Diff line change
Expand Up @@ -956,9 +956,6 @@ func assertProofReveals(t *testing.T, expected *taprpc.Asset,
actual *taprpc.DecodedProof) {

if actual.GenesisReveal != nil {
actual.GenesisReveal.GenesisBaseReveal.Version =
expected.AssetGenesis.Version

require.Equal(
t, expected.AssetGenesis,
actual.GenesisReveal.GenesisBaseReveal,
Expand All @@ -977,7 +974,6 @@ func AssertAssetGenesis(t *testing.T, expected, actual *taprpc.GenesisInfo) {
require.Equal(t, expected.MetaHash, actual.MetaHash)
require.Equal(t, expected.AssetId, actual.AssetId)
require.Equal(t, expected.OutputIndex, actual.OutputIndex)
require.Equal(t, expected.Version, actual.Version)
}

// AssertBalanceByID asserts that the balance of a single asset,
Expand Down Expand Up @@ -1619,7 +1615,10 @@ func AssertAssetBalances(t *testing.T, client taprpc.TaprootAssetsClient,

for _, balance := range assetIDBalances.AssetBalances {
for _, rpcAsset := range allAssets {
if balance.AssetGenesis.Name == rpcAsset.AssetGenesis.Name {
balanceGen := balance.AssetGenesis
targetGen := rpcAsset.AssetGenesis

if balanceGen.Name == targetGen.Name {
require.Equal(
t, balance.Balance, rpcAsset.Amount,
)
Expand Down
8 changes: 4 additions & 4 deletions itest/burn_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,10 @@ func testBurnAssets(t *harnessTest) {
// Preparation: We derive a couple of keys, so we can spread out our
// assets over several outputs, which we are going to use for the first
// couple of test cases.
scriptKey1, anchorInternalKeyDesc1 := deriveKeys(t.t, t.tapd)
scriptKey2, anchorInternalKeyDesc2 := deriveKeys(t.t, t.tapd)
scriptKey3, anchorInternalKeyDesc3 := deriveKeys(t.t, t.tapd)
scriptKey4, _ := deriveKeys(t.t, t.tapd)
scriptKey1, anchorInternalKeyDesc1 := DeriveKeys(t.t, t.tapd)
scriptKey2, anchorInternalKeyDesc2 := DeriveKeys(t.t, t.tapd)
scriptKey3, anchorInternalKeyDesc3 := DeriveKeys(t.t, t.tapd)
scriptKey4, _ := DeriveKeys(t.t, t.tapd)

// We create the following outputs:
// anchor index 0 (anchor internal key 1):
Expand Down
41 changes: 41 additions & 0 deletions itest/loadtest/config.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package loadtest

import (
"fmt"
"time"

"github.com/btcsuite/btcd/chaincfg"
"github.com/jessevdk/go-flags"
"github.com/lightninglabs/taproot-assets/taprpc"
)
Expand All @@ -21,6 +23,7 @@ const (
// User defines the config options for a user in the network.
type User struct {
Tapd *TapConfig `group:"tapd" namespace:"tapd"`
Lnd *LndConfig `group:"lnd" namespace:"lnd"`
}

// TapConfig are the main parameters needed for identifying and creating a grpc
Expand All @@ -34,6 +37,17 @@ type TapConfig struct {
MacPath string `long:"macpath" description:"Path to tapd's macaroon file"`
}

// LndConfig are the main parameters needed for identifying and creating a grpc
// client to a lnd subsystem.
type LndConfig struct {
Name string `long:"name" description:"the name of the lnd instance"`
Host string `long:"host" description:"the host to connect to"`
Port int `long:"port" description:"the port to connect to"`

TLSPath string `long:"tlspath" description:"Path to lnd's TLS certificate, leave empty if TLS is disabled"`
MacPath string `long:"macpath" description:"Path to tlnd's macaroon file"`
}

// BitcoinConfig defines exported config options for the connection to the
// btcd/bitcoind backend.
type BitcoinConfig struct {
Expand All @@ -56,6 +70,9 @@ type Config struct {
// Bob is the configuration for the secondary user in the network.
Bob *User `group:"bob" namespace:"bob" description:"bob related configuration"`

// Network is the network that the nodes are connected to.
Network string `long:"network" description:"the network the nodes are connected to" choice:"regtest" choice:"testnet" choice:"mainnet"`

// Bitcoin is the configuration for the bitcoin backend.
Bitcoin *BitcoinConfig `group:"bitcoin" namespace:"bitcoin" long:"bitcoin" description:"bitcoin client configuration"`

Expand Down Expand Up @@ -96,6 +113,7 @@ func DefaultConfig() Config {
Name: "bob",
},
},
Network: "regtest",
BatchSize: 100,
NumSends: 50,
NumAssets: 1, // We only mint collectibles.
Expand Down Expand Up @@ -140,3 +158,26 @@ func ValidateConfig(cfg Config) (*Config, error) {
// TODO (positiveblue): add validation logic.
return &cfg, nil
}

// networkParams parses the global network flag into a chaincfg.Params.
func networkParams(network string) (*chaincfg.Params, error) {
switch network {
case "mainnet":
return &chaincfg.MainNetParams, nil

case "testnet":
return &chaincfg.TestNet3Params, nil

case "regtest":
return &chaincfg.RegressionNetParams, nil

case "simnet":
return &chaincfg.SimNetParams, nil

case "signet":
return &chaincfg.SigNetParams, nil

default:
return nil, fmt.Errorf("unknown network: %v", network)
}
}
4 changes: 4 additions & 0 deletions itest/loadtest/load_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ var loadTestCases = []testCase{
name: "send",
fn: sendTest,
},
{
name: "multisig",
fn: multisigTest,
},
}

// TestPerformance executes the configured performance tests.
Expand Down
35 changes: 1 addition & 34 deletions itest/loadtest/mint_batch_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,12 @@ import (
"math/rand"
"strings"
"testing"
"time"

"github.com/lightninglabs/taproot-assets/fn"
"github.com/lightninglabs/taproot-assets/itest"
"github.com/lightninglabs/taproot-assets/taprpc"
"github.com/lightninglabs/taproot-assets/taprpc/mintrpc"
unirpc "github.com/lightninglabs/taproot-assets/taprpc/universerpc"
"github.com/lightninglabs/taproot-assets/universe"
"github.com/stretchr/testify/require"
)

Expand Down Expand Up @@ -166,36 +164,5 @@ func mintTest(t *testing.T, ctx context.Context, cfg *Config) {
})
require.True(t, correctOp)

_, err = bob.AddFederationServer(
ctx, &unirpc.AddFederationServerRequest{
Servers: []*unirpc.UniverseFederationServer{
{
Host: aliceHost,
},
},
},
)
if err != nil {
// Only fail the test for other errors than duplicate universe
// errors, as we might have already added the server in a
// previous run.
require.ErrorContains(
t, err, universe.ErrDuplicateUniverse.Error(),
)

// If we've already added the server in a previous run, we'll
// just need to kick off a sync (as that would otherwise be done
// by adding the server request already).
_, err := bob.SyncUniverse(ctx, &unirpc.SyncRequest{
UniverseHost: aliceHost,
SyncMode: unirpc.UniverseSyncMode_SYNC_ISSUANCE_ONLY,
})
require.NoError(t, err)
}

require.Eventually(t, func() bool {
return itest.AssertUniverseStateEqual(
t, alice, bob,
)
}, minterTimeout, time.Second)
itest.SyncUniverses(ctx, t, alice, bob, aliceHost, cfg.TestTimeout)
}
35 changes: 35 additions & 0 deletions itest/loadtest/multisig_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package loadtest

import (
"context"
"fmt"
"testing"

"github.com/lightninglabs/taproot-assets/itest"
"github.com/stretchr/testify/require"
)

// multisigTest tests that we can use multi signature on all levels of the
// Taproot Assets Protocol. This includes the BTC level, the asset level and the
// group key level.
func multisigTest(t *testing.T, ctx context.Context, cfg *Config) {
// Start by initializing all our client connections.
aliceTapd, bobTapd, bitcoinClient := initClients(t, ctx, cfg)

params, err := networkParams(cfg.Network)
require.NoError(t, err)

var (
aliceLnd = aliceTapd.lnd
bobLnd = bobTapd.lnd
)

aliceHost := fmt.Sprintf(
"%s:%d", aliceTapd.cfg.Host, aliceTapd.cfg.Port,
)

itest.MultiSigTest(
t, ctx, aliceTapd, bobTapd, aliceHost, bitcoinClient, aliceLnd,
bobLnd, params, cfg.TestTimeout,
)
}
61 changes: 58 additions & 3 deletions itest/loadtest/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"github.com/lightninglabs/taproot-assets/taprpc/rfqrpc"
"github.com/lightninglabs/taproot-assets/taprpc/tapdevrpc"
"github.com/lightninglabs/taproot-assets/taprpc/universerpc"
"github.com/lightningnetwork/lnd/lntest/rpc"
"github.com/lightningnetwork/lnd/macaroons"
"github.com/stretchr/testify/require"
"google.golang.org/grpc"
Expand All @@ -35,6 +36,7 @@ var (

type rpcClient struct {
cfg *TapConfig
lnd *rpc.HarnessRPC
taprpc.TaprootAssetsClient
assetwalletrpc.AssetWalletClient
tapdevrpc.TapDevClient
Expand Down Expand Up @@ -102,12 +104,12 @@ func initClients(t *testing.T, ctx context.Context,
cfg *Config) (*rpcClient, *rpcClient, *rpcclient.Client) {

// Create tapd clients.
alice := getTapClient(t, ctx, cfg.Alice.Tapd)
alice := getTapClient(t, ctx, cfg.Alice.Tapd, cfg.Alice.Lnd)

_, err := alice.GetInfo(ctx, &taprpc.GetInfoRequest{})
require.NoError(t, err)

bob := getTapClient(t, ctx, cfg.Bob.Tapd)
bob := getTapClient(t, ctx, cfg.Bob.Tapd, cfg.Bob.Lnd)

_, err = bob.GetInfo(ctx, &taprpc.GetInfoRequest{})
require.NoError(t, err)
Expand All @@ -129,7 +131,7 @@ func initClients(t *testing.T, ctx context.Context,
}

func getTapClient(t *testing.T, ctx context.Context,
cfg *TapConfig) *rpcClient {
cfg *TapConfig, lndCfg *LndConfig) *rpcClient {

creds := credentials.NewTLS(&tls.Config{})
if cfg.TLSPath != "" {
Expand Down Expand Up @@ -169,6 +171,8 @@ func getTapClient(t *testing.T, ctx context.Context,
conn, err := grpc.DialContext(ctx, svrAddr, opts...)
require.NoError(t, err)

lnd := getLndClient(t, ctx, lndCfg)

assetsClient := taprpc.NewTaprootAssetsClient(conn)
assetWalletClient := assetwalletrpc.NewAssetWalletClient(conn)
devClient := tapdevrpc.NewTapDevClient(conn)
Expand All @@ -178,6 +182,7 @@ func getTapClient(t *testing.T, ctx context.Context,

client := &rpcClient{
cfg: cfg,
lnd: lnd,
TaprootAssetsClient: assetsClient,
AssetWalletClient: assetWalletClient,
TapDevClient: devClient,
Expand All @@ -194,6 +199,56 @@ func getTapClient(t *testing.T, ctx context.Context,
return client
}

func getLndClient(t *testing.T, ctx context.Context,
cfg *LndConfig) *rpc.HarnessRPC {

creds := credentials.NewTLS(&tls.Config{})
if cfg.TLSPath != "" {
// Load the certificate file now, if specified.
tlsCert, err := os.ReadFile(cfg.TLSPath)
require.NoError(t, err)

cp := x509.NewCertPool()
ok := cp.AppendCertsFromPEM(tlsCert)
require.True(t, ok)

creds = credentials.NewClientTLSFromCert(cp, "")
}

// Create a dial options array.
opts := []grpc.DialOption{
grpc.WithTransportCredentials(creds),
grpc.WithDefaultCallOptions(tap.MaxMsgReceiveSize),
}

if cfg.MacPath != "" {
macBytes, err := os.ReadFile(cfg.MacPath)
require.NoError(t, err)

mac := &macaroon.Macaroon{}
err = mac.UnmarshalBinary(macBytes)
require.NoError(t, err)

macCred, err := macaroons.NewMacaroonCredential(mac)
require.NoError(t, err)

opts = append(opts, grpc.WithPerRPCCredentials(macCred))
}

svrAddr := fmt.Sprintf("%s:%d", cfg.Host, cfg.Port)
conn, err := grpc.DialContext(ctx, svrAddr, opts...)
require.NoError(t, err)

client := rpc.NewHarnessRPC(ctx, t, conn, cfg.Name)

t.Cleanup(func() {
err := conn.Close()
require.NoError(t, err)
})

return client
}

func getBitcoinConn(t *testing.T, cfg *BitcoinConfig) *rpcclient.Client {
var (
rpcCert []byte
Expand Down
Loading
Loading