From e54fed220a138833f2155f4826734a14962ea51d Mon Sep 17 00:00:00 2001 From: Oliver Gugger <gugger@gmail.com> Date: Thu, 30 Nov 2023 17:56:18 -0600 Subject: [PATCH 1/9] multi: add more context to errors --- proof/verifier.go | 2 +- tapgarden/caretaker.go | 8 +++++--- universe/base.go | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/proof/verifier.go b/proof/verifier.go index 098a1ac17..02deae762 100644 --- a/proof/verifier.go +++ b/proof/verifier.go @@ -331,7 +331,7 @@ func (p *Proof) verfyGenesisGroupKey(groupVerifier GroupVerifier) error { groupKey := p.Asset.GroupKey.GroupPubKey err := groupVerifier(&groupKey) if err != nil { - return ErrGroupKeyUnknown + return fmt.Errorf("%w: %v", ErrGroupKeyUnknown, err) } return nil diff --git a/tapgarden/caretaker.go b/tapgarden/caretaker.go index d60c22dbb..de90b6c04 100644 --- a/tapgarden/caretaker.go +++ b/tapgarden/caretaker.go @@ -1364,8 +1364,8 @@ func GenGroupVerifier(ctx context.Context, ctx, groupKey, ) if err != nil { - return fmt.Errorf("%x: %w", assetGroupKey, - ErrGroupKeyUnknown) + return fmt.Errorf("%x: group verifier: %v: %w", + assetGroupKey[:], err, ErrGroupKeyUnknown) } _, _ = assetGroups.Put(assetGroupKey, emptyCacheVal{}) @@ -1394,7 +1394,9 @@ func GenGroupAnchorVerifier(ctx context.Context, ctx, &groupKey.GroupPubKey, ) if err != nil { - return ErrGroupKeyUnknown + return fmt.Errorf("%x: group anchor verifier: "+ + "%w", assetGroupKey[:], + ErrGroupKeyUnknown) } groupAnchor = newSingleValue(storedGroup.Genesis) diff --git a/universe/base.go b/universe/base.go index 11f09e7f1..07a07de28 100644 --- a/universe/base.go +++ b/universe/base.go @@ -220,7 +220,7 @@ func (a *Archive) UpsertProofLeaf(ctx context.Context, id Identifier, ctx, id, key, &newProof, prevAssetSnapshot, ) if err != nil { - return nil, err + return nil, fmt.Errorf("unable to verify proof: %w", err) } // Now that we know the proof is valid, we'll insert it into the base From bcc86e8f564a19d39783f1dce7aeb56027ce5345 Mon Sep 17 00:00:00 2001 From: Oliver Gugger <gugger@gmail.com> Date: Thu, 30 Nov 2023 17:56:43 -0600 Subject: [PATCH 2/9] multi: fix typos and formatting --- itest/assertions.go | 2 +- itest/universe_test.go | 4 +--- proof/verifier.go | 6 +++--- tapgarden/caretaker.go | 16 ++++++---------- 4 files changed, 11 insertions(+), 17 deletions(-) diff --git a/itest/assertions.go b/itest/assertions.go index 359ac508e..048a397ec 100644 --- a/itest/assertions.go +++ b/itest/assertions.go @@ -870,7 +870,7 @@ func AssertBalanceByID(t *testing.T, client taprpc.TaprootAssetsClient, } require.True(t, ok) - require.Equal(t, uint64(amt), uint64(balance.Balance)) + require.Equal(t, amt, balance.Balance) } // AssertBalanceByGroup asserts that the balance of a single asset group diff --git a/itest/universe_test.go b/itest/universe_test.go index f4340aeab..57597e273 100644 --- a/itest/universe_test.go +++ b/itest/universe_test.go @@ -11,17 +11,15 @@ import ( "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcec/v2/schnorr" - "github.com/lightninglabs/taproot-assets/internal/test" - tap "github.com/lightninglabs/taproot-assets" "github.com/lightninglabs/taproot-assets/asset" "github.com/lightninglabs/taproot-assets/fn" + "github.com/lightninglabs/taproot-assets/internal/test" "github.com/lightninglabs/taproot-assets/mssmt" "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/lightningnetwork/lnd/lntest/wait" "github.com/stretchr/testify/require" "golang.org/x/exp/maps" diff --git a/proof/verifier.go b/proof/verifier.go index 02deae762..18c3e9b81 100644 --- a/proof/verifier.go +++ b/proof/verifier.go @@ -327,7 +327,7 @@ func (p *Proof) verifyGenesisReveal() error { // verifyGenesisGroupKey verifies that the group key attached to the asset in // this proof has already been verified. -func (p *Proof) verfyGenesisGroupKey(groupVerifier GroupVerifier) error { +func (p *Proof) verifyGenesisGroupKey(groupVerifier GroupVerifier) error { groupKey := p.Asset.GroupKey.GroupPubKey err := groupVerifier(&groupKey) if err != nil { @@ -487,7 +487,7 @@ func (p *Proof) Verify(ctx context.Context, prev *AssetSnapshot, case isGenesisAsset && hasGroupKey && !hasGroupKeyReveal: // A reissuance must be for an asset group that has already // been imported and verified. - if err := p.verfyGenesisGroupKey(groupVerifier); err != nil { + if err := p.verifyGenesisGroupKey(groupVerifier); err != nil { return nil, err } @@ -500,7 +500,7 @@ func (p *Proof) Verify(ctx context.Context, prev *AssetSnapshot, // 7. Verify group key for asset transfers. Any asset with a group key // must carry a group key that has already been imported and verified. if !isGenesisAsset && hasGroupKey { - if err := p.verfyGenesisGroupKey(groupVerifier); err != nil { + if err := p.verifyGenesisGroupKey(groupVerifier); err != nil { return nil, err } } diff --git a/tapgarden/caretaker.go b/tapgarden/caretaker.go index de90b6c04..fb1c1c65a 100644 --- a/tapgarden/caretaker.go +++ b/tapgarden/caretaker.go @@ -17,7 +17,6 @@ import ( "github.com/btcsuite/btcd/wire" "github.com/davecgh/go-spew/spew" "github.com/lightninglabs/neutrino/cache/lru" - "github.com/lightninglabs/taproot-assets/asset" "github.com/lightninglabs/taproot-assets/commitment" "github.com/lightninglabs/taproot-assets/fn" @@ -1336,14 +1335,13 @@ func newSingleValue[T any](v T) singleCacheValue[T] { // is used more as a set. type emptyCacheVal = singleCacheValue[emptyVal] -// GenGroupVeifier generates a group key verification callback function given a +// GenGroupVerifier generates a group key verification callback function given a // DB handle. func GenGroupVerifier(ctx context.Context, mintingStore MintingStore) func(*btcec.PublicKey) error { // Cache known group keys that were previously fetched. - assetGroups := lru.NewCache[ - asset.SerializedKey, emptyCacheVal]( + assetGroups := lru.NewCache[asset.SerializedKey, emptyCacheVal]( assetGroupCacheSize, ) @@ -1360,9 +1358,7 @@ func GenGroupVerifier(ctx context.Context, // This query will err if no stored group has a matching // tweaked group key. - _, err = mintingStore.FetchGroupByGroupKey( - ctx, groupKey, - ) + _, err = mintingStore.FetchGroupByGroupKey(ctx, groupKey) if err != nil { return fmt.Errorf("%x: group verifier: %v: %w", assetGroupKey[:], err, ErrGroupKeyUnknown) @@ -1377,12 +1373,12 @@ func GenGroupVerifier(ctx context.Context, // GenGroupAnchorVerifier generates a caching group anchor verification // callback function given a DB handle. func GenGroupAnchorVerifier(ctx context.Context, - mintingStore MintingStore) func(*asset.Genesis, - *asset.GroupKey) error { + mintingStore MintingStore) func(*asset.Genesis, *asset.GroupKey) error { // Cache anchors for groups that were previously fetched. groupAnchors := lru.NewCache[ - asset.SerializedKey, singleCacheValue[*asset.Genesis]]( + asset.SerializedKey, singleCacheValue[*asset.Genesis], + ]( assetGroupCacheSize, ) From ed1a0e9dbfd1a0e57ed26b4f324ffceb8a5b953e Mon Sep 17 00:00:00 2001 From: Oliver Gugger <gugger@gmail.com> Date: Thu, 30 Nov 2023 17:57:01 -0600 Subject: [PATCH 3/9] tapfreighter: don't use proof courier for pre-signed parcel Since a pre-signed parcel (a parcel that uses the RPC driven vPSBT flow) doesn't have proof courier URLs (they aren't part of the vPSBT), the proofs must always be delivered in an interactive manner from sender to receiver and we don't even need to attempt to use a proof courier. --- tapfreighter/chain_porter.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tapfreighter/chain_porter.go b/tapfreighter/chain_porter.go index e5953c99f..8b923f6cc 100644 --- a/tapfreighter/chain_porter.go +++ b/tapfreighter/chain_porter.go @@ -699,8 +699,14 @@ func (p *ChainPorter) transferReceiverProof(pkg *sendPackage) error { } // If we have a proof courier instance active, then we'll launch several - // goroutines to deliver the proof(s) to the receiver(s). - if p.cfg.ProofCourierCfg != nil { + // goroutines to deliver the proof(s) to the receiver(s). Since a + // pre-signed parcel (a parcel that uses the RPC driven vPSBT flow) + // doesn't have proof courier URLs (they aren't part of the vPSBT), the + // proofs must always be delivered in an interactive manner from sender + // to receiver, and we don't even need to attempt to use a proof + // courier. + _, isPreSigned := pkg.Parcel.(*PreSignedParcel) + if p.cfg.ProofCourierCfg != nil && !isPreSigned { ctx, cancel := p.WithCtxQuitNoTimeout() defer cancel() From 5b38a5740de352d433da8e5f92e126001703b7de Mon Sep 17 00:00:00 2001 From: Oliver Gugger <gugger@gmail.com> Date: Thu, 30 Nov 2023 18:05:07 -0600 Subject: [PATCH 4/9] itest: use universe RPC proof courier by default With this commit we remove the use of the proof.DisabledCourier courier by default and instead use the universe RPC proof courier if nothing is specified in the integration test case list. --- itest/test_harness.go | 7 +++---- itest/test_list_on_test.go | 34 +++++++++++++--------------------- 2 files changed, 16 insertions(+), 25 deletions(-) diff --git a/itest/test_harness.go b/itest/test_harness.go index feed49d23..993fbafa5 100644 --- a/itest/test_harness.go +++ b/itest/test_harness.go @@ -275,15 +275,14 @@ func setupHarnesses(t *testing.T, ht *harnessTest, // courier service and attach to test harness. var proofCourier proof.CourierHarness switch proofCourierType { - case proof.DisabledCourier: - // Proof courier disabled, do nothing. - case proof.HashmailCourierType: port := nextAvailablePort() apHarness := NewApertureHarness(ht.t, port) proofCourier = &apHarness - case proof.UniverseRpcCourierType: + // If nothing is specified, we use the universe RPC proof courier by + // default. + default: proofCourier = NewUniverseRPCHarness(t, ht, lndHarness.Bob) } diff --git a/itest/test_list_on_test.go b/itest/test_list_on_test.go index 841db91a1..9f0297038 100644 --- a/itest/test_list_on_test.go +++ b/itest/test_list_on_test.go @@ -2,9 +2,7 @@ package itest -import ( - "github.com/lightninglabs/taproot-assets/proof" -) +import "github.com/lightninglabs/taproot-assets/proof" var testCases = []*testCase{ { @@ -48,14 +46,12 @@ var testCases = []*testCase{ proofCourierType: proof.HashmailCourierType, }, { - name: "basic send universerpc proof courier", - test: testBasicSendUnidirectional, - proofCourierType: proof.UniverseRpcCourierType, + name: "basic send unidirectional", + test: testBasicSendUnidirectional, }, { - name: "restart receiver check balance", - test: testRestartReceiverCheckBalance, - proofCourierType: proof.UniverseRpcCourierType, + name: "restart receiver check balance", + test: testRestartReceiverCheckBalance, }, { name: "resume pending package send", @@ -68,14 +64,12 @@ var testCases = []*testCase{ proofCourierType: proof.HashmailCourierType, }, { - name: "reattempt failed send uni courier", - test: testReattemptFailedSendUniCourier, - proofCourierType: proof.UniverseRpcCourierType, + name: "reattempt failed send uni courier", + test: testReattemptFailedSendUniCourier, }, { - name: "reattempt failed receive uni courier", - test: testReattemptFailedReceiveUniCourier, - proofCourierType: proof.UniverseRpcCourierType, + name: "reattempt failed receive uni courier", + test: testReattemptFailedReceiveUniCourier, }, { name: "offline receiver eventually receives", @@ -109,14 +103,12 @@ var testCases = []*testCase{ proofCourierType: proof.HashmailCourierType, }, { - name: "collectible send rpc courier", - test: testCollectibleSend, - proofCourierType: proof.UniverseRpcCourierType, + name: "collectible send", + test: testCollectibleSend, }, { - name: "collectible group send rpc courier", - test: testCollectibleGroupSend, - proofCourierType: proof.UniverseRpcCourierType, + name: "collectible group send", + test: testCollectibleGroupSend, }, { name: "re-issuance", From d24c0295445cd8183a35368e12185e9ed2ce4946 Mon Sep 17 00:00:00 2001 From: Oliver Gugger <gugger@gmail.com> Date: Thu, 30 Nov 2023 18:07:49 -0600 Subject: [PATCH 5/9] itest: merge server harness and UniverseRPCHarness The original server harness was meant to be the actual universe RPC server from the beginning. So we can merge the two into a single one and start/use that by default. --- itest/aperture_harness.go | 4 +- itest/integration_test.go | 13 ++-- itest/server_harness.go | 108 ------------------------------- itest/tapd_harness.go | 2 +- itest/test_harness.go | 56 ++++++++-------- itest/universe_server_harness.go | 48 ++++++++++++++ itest/universerpc_harness.go | 53 --------------- 7 files changed, 85 insertions(+), 199 deletions(-) delete mode 100644 itest/server_harness.go create mode 100644 itest/universe_server_harness.go delete mode 100644 itest/universerpc_harness.go diff --git a/itest/aperture_harness.go b/itest/aperture_harness.go index 95500363a..e95061e97 100644 --- a/itest/aperture_harness.go +++ b/itest/aperture_harness.go @@ -27,7 +27,7 @@ type ApertureHarness struct { // NewApertureHarness creates a new instance of the aperture service. It returns // a harness which includes useful values for testing. -func NewApertureHarness(t *testing.T, port int) ApertureHarness { +func NewApertureHarness(t *testing.T, port int) *ApertureHarness { // Create a temporary directory for the aperture service to use. baseDir := filepath.Join(t.TempDir(), "aperture") err := os.MkdirAll(baseDir, os.ModePerm) @@ -55,7 +55,7 @@ func NewApertureHarness(t *testing.T, port int) ApertureHarness { } service := aperture.NewAperture(cfg) - return ApertureHarness{ + return &ApertureHarness{ ListenAddr: listenAddr, Service: service, } diff --git a/itest/integration_test.go b/itest/integration_test.go index 41dcf7f81..3f2557c21 100644 --- a/itest/integration_test.go +++ b/itest/integration_test.go @@ -59,11 +59,10 @@ func TestTaprootAssetsDaemon(t *testing.T) { // The universe server and tapd client are both freshly // created and later discarded for each test run to // assure no state is taken over between runs. - tapdHarness, universeServer, proofCourier := - setupHarnesses( - t1, ht, lndHarness, - testCase.proofCourierType, - ) + tapdHarness, uniHarness, proofCourier := setupHarnesses( + t1, ht, lndHarness, + testCase.proofCourierType, + ) lndHarness.EnsureConnected( lndHarness.Alice, lndHarness.Bob, ) @@ -72,8 +71,8 @@ func TestTaprootAssetsDaemon(t *testing.T) { lndHarness.Bob.AddToLogf(logLine) ht := ht.newHarnessTest( - t1, lndHarness, universeServer, - tapdHarness, proofCourier, + t1, lndHarness, uniHarness, tapdHarness, + proofCourier, ) // Now we have everything to run the test case. diff --git a/itest/server_harness.go b/itest/server_harness.go deleted file mode 100644 index 6fee73485..000000000 --- a/itest/server_harness.go +++ /dev/null @@ -1,108 +0,0 @@ -package itest - -import ( - "fmt" - "net" - "os" - "path/filepath" - "sync" - "time" - - "github.com/lightningnetwork/lnd/cert" - "google.golang.org/grpc" - "google.golang.org/grpc/credentials" -) - -const ( - // DefaultAutogenValidity is the default validity of a self-signed - // certificate. The value corresponds to 14 months - // (14 months * 30 days * 24 hours). - DefaultAutogenValidity = 14 * 30 * 24 * time.Hour -) - -type universeServerMock struct { - // TODO: Embed Unimplemented*Server of universe RPCs here to mock them. -} - -type serverHarness struct { - serverHost string - mockServer *grpc.Server - - certFile string - server *universeServerMock - - errChan chan error - - wg sync.WaitGroup -} - -func newServerHarness(serverHost string) *serverHarness { - return &serverHarness{ - serverHost: serverHost, - errChan: make(chan error, 1), - } -} - -func (s *serverHarness) stop() { - s.mockServer.Stop() - s.wg.Wait() -} - -func (s *serverHarness) start() error { - tempDirName, err := os.MkdirTemp("", "tapitest") - if err != nil { - return err - } - - s.certFile = filepath.Join(tempDirName, "proxy.cert") - keyFile := filepath.Join(tempDirName, "proxy.key") - creds, err := genCertPair(s.certFile, keyFile) - if err != nil { - return err - } - - httpListener, err := net.Listen("tcp", s.serverHost) - if err != nil { - return err - } - - s.mockServer = grpc.NewServer(grpc.Creds(creds)) - s.server = &universeServerMock{} - - // TODO(guggero): Register universe RPC servers here. - - s.wg.Add(1) - go func() { - defer s.wg.Done() - s.errChan <- s.mockServer.Serve(httpListener) - }() - - return nil -} - -// genCertPair generates a pair of private key and certificate and returns them -// in different formats needed to spin up test servers and clients. -func genCertPair(certFile, keyFile string) (credentials.TransportCredentials, - error) { - - certBytes, keyBytes, err := cert.GenCertPair( - "itest autogenerated cert", nil, nil, false, - DefaultAutogenValidity, - ) - if err != nil { - return nil, fmt.Errorf("unable to generate cert pair: %v", err) - } - - // Now that we have the certificate and key, we'll store them - // to the file system. - err = cert.WriteCertPair(certFile, keyFile, certBytes, keyBytes) - if err != nil { - return nil, fmt.Errorf("error writing cert pair: %w", err) - } - - creds, err := credentials.NewServerTLSFromFile(certFile, keyFile) - if err != nil { - return nil, fmt.Errorf("unable to load cert file: %v", err) - } - return creds, nil -} diff --git a/itest/tapd_harness.go b/itest/tapd_harness.go index c73bb1fe4..398415650 100644 --- a/itest/tapd_harness.go +++ b/itest/tapd_harness.go @@ -213,7 +213,7 @@ func newTapdHarness(t *testing.T, ht *harnessTest, cfg tapdConfig, typedProofCourier.ListenAddr, ) - case *UniverseRPCHarness: + case *universeServerHarness: finalCfg.DefaultProofCourierAddr = fmt.Sprintf( "%s://%s", proof.UniverseRpcCourierType, typedProofCourier.ListenAddr, diff --git a/itest/test_harness.go b/itest/test_harness.go index 993fbafa5..64cd737bd 100644 --- a/itest/test_harness.go +++ b/itest/test_harness.go @@ -95,7 +95,7 @@ type harnessTest struct { // nil if not yet set up. lndHarness *lntest.HarnessTest - universeServer *serverHarness + universeServer *universeServerHarness tapd *tapdHarness @@ -107,7 +107,7 @@ type harnessTest struct { // newHarnessTest creates a new instance of a harnessTest from a regular // testing.T instance. func (h *harnessTest) newHarnessTest(t *testing.T, net *lntest.HarnessTest, - universeServer *serverHarness, tapd *tapdHarness, + universeServer *universeServerHarness, tapd *tapdHarness, proofCourier proof.CourierHarness) *harnessTest { return &harnessTest{ @@ -174,7 +174,11 @@ func (h *harnessTest) LogfTimestamped(format string, args ...interface{}) { // shutdown stops both the mock universe and tapd server. func (h *harnessTest) shutdown(_ *testing.T) error { - h.universeServer.stop() + err := h.universeServer.Stop() + if err != nil { + return fmt.Errorf("unable to stop universe server harness: "+ + "%w", err) + } if h.proofCourier != nil { err := h.proofCourier.Stop() @@ -184,7 +188,7 @@ func (h *harnessTest) shutdown(_ *testing.T) error { } } - err := h.tapd.stop(!*noDelete) + err = h.tapd.stop(!*noDelete) if err != nil { return fmt.Errorf("unable to stop tapd: %v", err) } @@ -269,7 +273,15 @@ func nextAvailablePort() int { func setupHarnesses(t *testing.T, ht *harnessTest, lndHarness *lntest.HarnessTest, proofCourierType proof.CourierType) (*tapdHarness, - *serverHarness, proof.CourierHarness) { + *universeServerHarness, proof.CourierHarness) { + + universeServer := newUniverseServerHarness(t, ht, lndHarness.Bob) + + t.Logf("Starting universe server harness, listening on %v", + universeServer.ListenAddr) + + err := universeServer.Start(nil) + require.NoError(t, err, "universe server harness") // If a proof courier type is specified, start test specific proof // courier service and attach to test harness. @@ -277,28 +289,18 @@ func setupHarnesses(t *testing.T, ht *harnessTest, switch proofCourierType { case proof.HashmailCourierType: port := nextAvailablePort() - apHarness := NewApertureHarness(ht.t, port) - proofCourier = &apHarness + apertureHarness := NewApertureHarness(ht.t, port) + err := apertureHarness.Start(nil) + require.NoError(t, err, "aperture proof courier harness") + + proofCourier = apertureHarness // If nothing is specified, we use the universe RPC proof courier by // default. default: - proofCourier = NewUniverseRPCHarness(t, ht, lndHarness.Bob) + proofCourier = universeServer } - // Start the proof courier harness if specified. - if proofCourier != nil { - err := proofCourier.Start(nil) - require.NoError(t, err, "unable to start proof courier harness") - } - - mockServerAddr := fmt.Sprintf( - node.ListenerFormat, node.NextAvailablePort(), - ) - universeServer := newServerHarness(mockServerAddr) - err := universeServer.start() - require.NoError(t, err) - // Create a tapd that uses Bob and connect it to the universe server. tapdHarness := setupTapdHarness( t, ht, lndHarness.Alice, universeServer, @@ -351,7 +353,7 @@ type Option func(*tapdHarnessParams) // setupTapdHarness creates a new tapd that connects to the given lnd node // and to the given universe server. func setupTapdHarness(t *testing.T, ht *harnessTest, - node *node.HarnessNode, universe *serverHarness, + node *node.HarnessNode, universe *universeServerHarness, opts ...Option) *tapdHarness { // Set parameters by executing option functions. @@ -379,12 +381,10 @@ func setupTapdHarness(t *testing.T, ht *harnessTest, ho.addrAssetSyncerDisable = params.addrAssetSyncerDisable } - tapdHarness, err := newTapdHarness( - t, ht, tapdConfig{ - NetParams: harnessNetParams, - LndNode: node, - }, harnessOpts, - ) + tapdHarness, err := newTapdHarness(t, ht, tapdConfig{ + NetParams: harnessNetParams, + LndNode: node, + }, harnessOpts) require.NoError(t, err) // Start the tapd harness now. diff --git a/itest/universe_server_harness.go b/itest/universe_server_harness.go new file mode 100644 index 000000000..b461d74da --- /dev/null +++ b/itest/universe_server_harness.go @@ -0,0 +1,48 @@ +package itest + +import ( + "testing" + + "github.com/lightninglabs/taproot-assets/proof" + "github.com/lightningnetwork/lnd/lntest/node" + "github.com/stretchr/testify/require" +) + +type universeServerHarness struct { + // service is the instance of the universe tap service. + service *tapdHarness + + // ListenAddr is the address that the service is listening on. + ListenAddr string +} + +func newUniverseServerHarness(t *testing.T, ht *harnessTest, + lndHarness *node.HarnessNode) *universeServerHarness { + + service, err := newTapdHarness(t, ht, tapdConfig{ + NetParams: harnessNetParams, + LndNode: lndHarness, + }) + require.NoError(t, err) + + return &universeServerHarness{ + service: service, + ListenAddr: service.rpcHost(), + } +} + +// Start starts the service. +func (h *universeServerHarness) Start(_ chan error) error { + return h.service.start(false) +} + +// Stop stops the service. +func (h *universeServerHarness) Stop() error { + // Don't delete temporary data on stop. This will allow us to cleanly + // restart the service mid-test. + return h.service.stop(false) +} + +// Ensure that universeServerHarness implements the proof.CourierHarness +// interface. +var _ proof.CourierHarness = (*universeServerHarness)(nil) diff --git a/itest/universerpc_harness.go b/itest/universerpc_harness.go deleted file mode 100644 index 4f0073fc2..000000000 --- a/itest/universerpc_harness.go +++ /dev/null @@ -1,53 +0,0 @@ -package itest - -import ( - "testing" - - "github.com/lightninglabs/taproot-assets/proof" - "github.com/lightningnetwork/lnd/lntest/node" - "github.com/stretchr/testify/require" -) - -// UniverseRPCHarness is an integration testing harness for the universe tap -// service. -type UniverseRPCHarness struct { - // service is the instance of the universe tap service. - service *tapdHarness - - // ListenAddr is the address that the service is listening on. - ListenAddr string -} - -// NewUniverseRPCHarness creates a new test harness for a universe tap service. -func NewUniverseRPCHarness(t *testing.T, ht *harnessTest, - lndHarness *node.HarnessNode) *UniverseRPCHarness { - - service, err := newTapdHarness( - t, ht, tapdConfig{ - NetParams: harnessNetParams, - LndNode: lndHarness, - }, - ) - require.NoError(t, err) - - return &UniverseRPCHarness{ - service: service, - ListenAddr: service.rpcHost(), - } -} - -// Start starts the service. -func (h *UniverseRPCHarness) Start(_ chan error) error { - return h.service.start(false) -} - -// Stop stops the service. -func (h *UniverseRPCHarness) Stop() error { - // Don't delete temporary data on stop. This will allow us to cleanly - // restart the service mid-test. - return h.service.stop(false) -} - -// Ensure that NewUniverseRPCHarness implements the proof.CourierHarness -// interface. -var _ proof.CourierHarness = (*UniverseRPCHarness)(nil) From 40cec8ce64a6d338c2d759451176dd5ce35699e9 Mon Sep 17 00:00:00 2001 From: Oliver Gugger <gugger@gmail.com> Date: Thu, 30 Nov 2023 18:17:13 -0600 Subject: [PATCH 6/9] itest: remove manual proof transfer for addr sends With this commit we remove all instances of the manual proof transfer from call sites that do an actual non-interactive (address based) transfer, for which a proof courier should now handle the proof transmission. --- itest/addrs_test.go | 17 ----------------- itest/full_value_split_test.go | 8 ++++---- itest/multi_asset_group_test.go | 8 -------- itest/psbt_test.go | 22 ++++++++++++++++++++-- itest/re-issuance_test.go | 26 +++++--------------------- itest/re-org_test.go | 6 ------ itest/round_trip_send_test.go | 8 ++------ itest/send_test.go | 6 ------ 8 files changed, 31 insertions(+), 70 deletions(-) diff --git a/itest/addrs_test.go b/itest/addrs_test.go index b04f556aa..48a23ff9d 100644 --- a/itest/addrs_test.go +++ b/itest/addrs_test.go @@ -79,12 +79,6 @@ func testAddresses(t *harnessTest) { // Eventually the event should be marked as confirmed. AssertAddrEvent(t.t, secondTapd, addr, 1, statusConfirmed) - // To complete the transfer, we'll export the proof from the - // sender and import it into the receiver for each asset set. - sendProof( - t, t.tapd, secondTapd, addr.ScriptKey, a.AssetGenesis, - ) - // Make sure we have imported and finalized all proofs. AssertNonInteractiveRecvComplete(t.t, secondTapd, idx+1) @@ -436,13 +430,11 @@ func runMultiSendTest(ctxt context.Context, t *harnessTest, alice, // In order to force a split, we don't try to send the full asset. const sendAmt = 100 - var bobAddresses []*taprpc.Addr bobAddr1, err := bob.NewAddr(ctxt, &taprpc.NewAddrRequest{ AssetId: genInfo.AssetId, Amt: sendAmt, }) require.NoError(t.t, err) - bobAddresses = append(bobAddresses, bobAddr1) AssertAddrCreated(t.t, bob, mintedAsset, bobAddr1) bobAddr2, err := bob.NewAddr(ctxt, &taprpc.NewAddrRequest{ @@ -450,7 +442,6 @@ func runMultiSendTest(ctxt context.Context, t *harnessTest, alice, Amt: sendAmt, }) require.NoError(t.t, err) - bobAddresses = append(bobAddresses, bobAddr2) AssertAddrCreated(t.t, bob, mintedAsset, bobAddr2) // To test that Alice can also receive to multiple addresses in a single @@ -492,14 +483,6 @@ func runMultiSendTest(ctxt context.Context, t *harnessTest, alice, // this point, so the status should go to completed directly. AssertAddrEventByStatus(t.t, alice, statusCompleted, numRuns*2) - // To complete the transfer, we'll export the proof from the sender and - // import it into the receiver for each asset set. This should not be - // necessary for the sends to Alice, as she is both the sender and - // receiver and should detect the local proof once it's written to disk. - for i := range bobAddresses { - sendProof(t, alice, bob, bobAddresses[i].ScriptKey, genInfo) - } - // Make sure we have imported and finalized all proofs. AssertNonInteractiveRecvComplete(t.t, bob, numRuns*2) AssertNonInteractiveRecvComplete(t.t, alice, numRuns*2) diff --git a/itest/full_value_split_test.go b/itest/full_value_split_test.go index 75854b0ca..c60a53ff6 100644 --- a/itest/full_value_split_test.go +++ b/itest/full_value_split_test.go @@ -88,8 +88,8 @@ func runFullValueSendTests(ctxt context.Context, t *harnessTest, alice, []uint64{0, fullAmount}, senderTransferIdx, senderTransferIdx+1, ) - _ = sendProof( - t, alice, bob, receiverAddr.ScriptKey, genInfo, + AssertNonInteractiveRecvComplete( + t.t, bob, senderTransferIdx+1, ) senderTransferIdx++ } else { @@ -108,8 +108,8 @@ func runFullValueSendTests(ctxt context.Context, t *harnessTest, alice, genInfo.AssetId, []uint64{0, fullAmount}, receiverTransferIdx, receiverTransferIdx+1, ) - _ = sendProof( - t, bob, alice, receiverAddr.ScriptKey, genInfo, + AssertNonInteractiveRecvComplete( + t.t, alice, receiverTransferIdx+1, ) receiverTransferIdx++ } diff --git a/itest/multi_asset_group_test.go b/itest/multi_asset_group_test.go index 9b4add64d..82d9706a0 100644 --- a/itest/multi_asset_group_test.go +++ b/itest/multi_asset_group_test.go @@ -129,10 +129,6 @@ func testMintMultiAssetGroups(t *harnessTest) { normalMember.AssetGenesis.AssetId, []uint64{0, normalMember.Amount}, 0, 1, ) - _ = sendProof( - t, t.tapd, secondTapd, bobNormalAddr.ScriptKey, - normalMemberGenInfo, - ) AssertNonInteractiveRecvComplete(t.t, secondTapd, 1) AssertBalanceByGroup( @@ -170,10 +166,6 @@ func testMintMultiAssetGroups(t *harnessTest) { collectMember.AssetGenesis.AssetId, []uint64{0, collectMember.Amount}, 1, 2, ) - sendProof( - t, t.tapd, secondTapd, bobCollectAddr.ScriptKey, - collectMemberGenInfo, - ) AssertNonInteractiveRecvComplete(t.t, secondTapd, 2) AssertBalanceByGroup( diff --git a/itest/psbt_test.go b/itest/psbt_test.go index d587f2097..c0711ce4e 100644 --- a/itest/psbt_test.go +++ b/itest/psbt_test.go @@ -132,6 +132,10 @@ func testPsbtScriptHashLockSend(t *harnessTest) { t.t, t.lndHarness.Miner.Client, bob, sendResp, genInfo.AssetId, []uint64{numUnits / 2, numUnits / 2}, 0, 1, ) + + // This is an interactive/PSBT based transfer, so we do need to manually + // send the proof from the sender to the receiver because the proof + // courier address gets lost in the address->PSBT conversion. _ = sendProof(t, bob, alice, aliceAddr.ScriptKey, genInfo) AssertNonInteractiveRecvComplete(t.t, alice, 1) @@ -258,6 +262,10 @@ func testPsbtScriptCheckSigSend(t *harnessTest) { t.t, t.lndHarness.Miner.Client, bob, sendResp, genInfo.AssetId, []uint64{numUnits / 2, numUnits / 2}, 0, 1, ) + + // This is an interactive/PSBT based transfer, so we do need to manually + // send the proof from the sender to the receiver because the proof + // courier address gets lost in the address->PSBT conversion. _ = sendProof(t, bob, alice, aliceAddr.ScriptKey, genInfo) AssertNonInteractiveRecvComplete(t.t, alice, 1) @@ -438,6 +446,9 @@ func runPsbtInteractiveFullValueSendTest(ctxt context.Context, t *harnessTest, sendResp, genInfo.AssetId, amounts, i/2, (i/2)+1, numOutputs, ) + + // This is an interactive transfer, so we do need to manually + // send the proof from the sender to the receiver. _ = sendProof( t, sender, receiver, receiverScriptKey.PubKey.SerializeCompressed(), genInfo, @@ -656,6 +667,9 @@ func runPsbtInteractiveSplitSendTest(ctxt context.Context, t *harnessTest, []uint64{sendAmt, changeAmt}, i/2, (i/2)+1, numOutputs, ) + + // This is an interactive transfer, so we do need to manually + // send the proof from the sender to the receiver. _ = sendProof( t, sender, receiver, receiverScriptKey.PubKey.SerializeCompressed(), genInfo, @@ -779,6 +793,9 @@ func testPsbtInteractiveTapscriptSibling(t *harnessTest) { t.t, t.lndHarness.Miner.Client, alice, sendResp, genInfo.AssetId, []uint64{sendAmt, changeAmt}, 0, 1, 2, ) + + // This is an interactive transfer, so we do need to manually send the + // proof from the sender to the receiver. _ = sendProof( t, alice, bob, receiverScriptKey.PubKey.SerializeCompressed(), genInfo, @@ -927,6 +944,9 @@ func testPsbtMultiSend(t *harnessTest) { t.t, t.lndHarness.Miner.Client, sender, sendResp, genInfo.AssetId, outputAmounts, 0, 1, numOutputs, ) + + // This is an interactive transfer, so we do need to manually send the + // proof from the sender to the receiver. _ = sendProof( t, sender, receiver, receiverScriptKey1.PubKey.SerializeCompressed(), genInfo, @@ -1034,7 +1054,6 @@ func sendToTapscriptAddr(ctx context.Context, t *harnessTest, alice, t.t, t.lndHarness.Miner.Client, alice, sendResp, genInfo.AssetId, []uint64{changeUnits, numUnits}, 0, 1, ) - _ = sendProof(t, alice, bob, bobAddr.ScriptKey, genInfo) AssertNonInteractiveRecvComplete(t.t, bob, 1) } @@ -1059,7 +1078,6 @@ func sendAssetAndAssert(ctx context.Context, t *harnessTest, alice, genInfo.AssetId, []uint64{change, numUnits}, outTransferIdx, numOutTransfers, ) - _ = sendProof(t, alice, bob, bobAddr.ScriptKey, genInfo) // There are now two receive events (since only non-interactive sends // appear in that RPC output). diff --git a/itest/re-issuance_test.go b/itest/re-issuance_test.go index b92d27b85..6c140dab2 100644 --- a/itest/re-issuance_test.go +++ b/itest/re-issuance_test.go @@ -78,10 +78,7 @@ func testReIssuance(t *harnessTest) { t.t, t.lndHarness.Miner.Client, t.tapd, firstCollectSend, collectGenInfo.AssetId, []uint64{0, 1}, 0, 1, ) - sendProof( - t, t.tapd, secondTapd, collectGroupAddr.ScriptKey, - collectGenInfo, - ) + AssertNonInteractiveRecvComplete(t.t, secondTapd, 1) // Check the state of both nodes. The first node should show one // zero-value transfer representing the send of the collectible. @@ -107,10 +104,7 @@ func testReIssuance(t *harnessTest) { normalGenInfo.AssetId, []uint64{normalGroupMintHalf, normalGroupMintHalf}, 1, 2, ) - sendProof( - t, t.tapd, secondTapd, normalGroupAddr.ScriptKey, - normalGenInfo, - ) + AssertNonInteractiveRecvComplete(t.t, secondTapd, 2) // Reissue one more collectible and half the original mint amount for // the normal asset. @@ -186,10 +180,7 @@ func testReIssuance(t *harnessTest) { t.t, t.lndHarness.Miner.Client, t.tapd, secondCollectSend, collectReissueInfo.AssetId, []uint64{0, 1}, 2, 3, ) - sendProof( - t, t.tapd, secondTapd, collectReissueAddr.ScriptKey, - collectReissueInfo, - ) + AssertNonInteractiveRecvComplete(t.t, secondTapd, 3) // The second node should show two groups, with two assets in // the collectible group and a total balance of 2 for that group. @@ -220,10 +211,7 @@ func testReIssuance(t *harnessTest) { t.t, secondTapd.ht.lndHarness.Miner.Client, secondTapd, thirdCollectSend, collectGenInfo.AssetId, []uint64{0, 1}, 0, 1, ) - sendProof( - t, secondTapd, t.tapd, collectReissueAddr.ScriptKey, - collectReissueInfo, - ) + AssertNonInteractiveRecvComplete(t.t, t.tapd, 1) // The collectible balance on the minting node should be 1, and there // should still be only two groups. @@ -382,12 +370,8 @@ func testMintWithGroupKeyErrors(t *harnessTest) { t.t, t.lndHarness.Miner.Client, t.tapd, collectSend, collectGenInfo.AssetId, []uint64{0, 1}, 0, 1, ) - sendProof( - t, t.tapd, secondTapd, collectGroupAddr.ScriptKey, - collectGenInfo, - ) - // A reissuance with the second node should still fail because the + // A re-issuance with the second node should still fail because the // group key was not created by that node. _, err = secondTapd.MintAsset(ctxb, reissueRequest) require.ErrorContains(t.t, err, "can't sign with group key") diff --git a/itest/re-org_test.go b/itest/re-org_test.go index b77762f5a..6f3524b08 100644 --- a/itest/re-org_test.go +++ b/itest/re-org_test.go @@ -170,9 +170,6 @@ func testReOrgSend(t *harnessTest) { sendAssetGen.AssetId, []uint64{sendAsset.Amount - sendAmount, sendAmount}, 0, 1, ) - _ = sendProof( - t, t.tapd, secondTapd, bobAddr.ScriptKey, sendAssetGen, - ) AssertNonInteractiveRecvComplete(t.t, secondTapd, 1) initialBlockHash := initialBlock.BlockHash() @@ -291,9 +288,6 @@ func testReOrgMintAndSend(t *harnessTest) { sendAssetGen.AssetId, []uint64{sendAsset.Amount - sendAmount, sendAmount}, 0, 1, ) - _ = sendProof( - t, t.tapd, secondTapd, bobAddr.ScriptKey, sendAssetGen, - ) AssertNonInteractiveRecvComplete(t.t, secondTapd, 1) initialBlockHash := initialBlock.BlockHash() diff --git a/itest/round_trip_send_test.go b/itest/round_trip_send_test.go index 784ca1571..87bdb5ca6 100644 --- a/itest/round_trip_send_test.go +++ b/itest/round_trip_send_test.go @@ -4,7 +4,6 @@ import ( "bytes" "context" "encoding/hex" - "time" "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcutil" @@ -81,7 +80,7 @@ func testRoundTripSend(t *harnessTest) { t.t, t.lndHarness.Miner.Client, t.tapd, sendResp, genInfo.AssetId, []uint64{bobAmt, bobAmt}, 0, 1, ) - _ = sendProof(t, t.tapd, secondTapd, bobAddr.ScriptKey, genInfo) + AssertNonInteractiveRecvComplete(t.t, secondTapd, 1) // Now, Alice will request half of the assets she sent to Bob. aliceAddr, err := t.tapd.NewAddr(ctxb, &taprpc.NewAddrRequest{ @@ -101,10 +100,7 @@ func testRoundTripSend(t *harnessTest) { t.t, t.lndHarness.Miner.Client, secondTapd, sendResp, genInfo.AssetId, []uint64{aliceAmt, aliceAmt}, 0, 1, ) - _ = sendProof(t, secondTapd, t.tapd, aliceAddr.ScriptKey, genInfo) - - // Give both nodes some time to process the final transfer. - time.Sleep(time.Second * 1) + AssertNonInteractiveRecvComplete(t.t, t.tapd, 1) // Check the final state of both nodes. Each node should list // one transfer, and Alice should have 3/4 of the total units. diff --git a/itest/send_test.go b/itest/send_test.go index 2a44335e1..a57301dc6 100644 --- a/itest/send_test.go +++ b/itest/send_test.go @@ -1240,7 +1240,6 @@ func testMultiInputSendNonInteractiveSingleID(t *harnessTest) { genInfo.AssetId, []uint64{4000, 1000}, 0, 1, ) - _ = sendProof(t, t.tapd, bobTapd, addr.ScriptKey, genInfo) AssertNonInteractiveRecvComplete(t.t, bobTapd, 1) // Second of two send events from minting node to the secondary node. @@ -1261,7 +1260,6 @@ func testMultiInputSendNonInteractiveSingleID(t *harnessTest) { genInfo.AssetId, []uint64{0, 4000}, 1, 2, ) - _ = sendProof(t, t.tapd, bobTapd, addr.ScriptKey, genInfo) AssertNonInteractiveRecvComplete(t.t, bobTapd, 2) t.Logf("Two separate send events complete, now attempting to send " + @@ -1285,7 +1283,6 @@ func testMultiInputSendNonInteractiveSingleID(t *harnessTest) { genInfo.AssetId, []uint64{0, 5000}, 0, 1, ) - _ = sendProof(t, bobTapd, t.tapd, addr.ScriptKey, genInfo) AssertNonInteractiveRecvComplete(t.t, t.tapd, 1) } @@ -1388,9 +1385,6 @@ func testSendMultipleCoins(t *harnessTest) { // Now we confirm the 5 transfers and make sure they complete as // expected. _ = MineBlocks(t.t, t.lndHarness.Miner.Client, 1, 5) - for _, addr := range bobAddrs { - _ = sendProof(t, t.tapd, secondTapd, addr.ScriptKey, genInfo) - } AssertNonInteractiveRecvComplete(t.t, secondTapd, 5) } From d48747d81da8108cf363365df8957dc97bf1e6f6 Mon Sep 17 00:00:00 2001 From: Oliver Gugger <gugger@gmail.com> Date: Fri, 1 Dec 2023 18:05:43 -0500 Subject: [PATCH 7/9] itest: add main universe server as federation member By default we want all new tapd instances to be synced with the main universe server, so we add it as a federation member unless specifically disabled. --- itest/addrs_test.go | 10 ++++++++-- itest/mint_batch_stress_test.go | 2 +- itest/test_harness.go | 29 +++++++++++++++++++++++++++++ itest/universe_pagination_test.go | 2 +- itest/universe_test.go | 10 ++++++++-- 5 files changed, 47 insertions(+), 6 deletions(-) diff --git a/itest/addrs_test.go b/itest/addrs_test.go index 48a23ff9d..93a0eda4b 100644 --- a/itest/addrs_test.go +++ b/itest/addrs_test.go @@ -189,7 +189,12 @@ func testMultiAddress(t *harnessTest) { func testAddressAssetSyncer(t *harnessTest) { // We'll kick off the test by making a new node, without hooking it up // to any existing Universe server. - bob := setupTapdHarness(t.t, t, t.lndHarness.Bob, nil) + bob := setupTapdHarness( + t.t, t, t.lndHarness.Bob, t.universeServer, + func(params *tapdHarnessParams) { + params.noDefaultUniverseSync = true + }, + ) defer func() { require.NoError(t.t, bob.stop(!*noDelete)) }() @@ -315,8 +320,9 @@ func testAddressAssetSyncer(t *harnessTest) { restartBobNoUniSync := func(disableSyncer bool) { require.NoError(t.t, bob.stop(!*noDelete)) bob = setupTapdHarness( - t.t, t, t.lndHarness.Bob, nil, + t.t, t, t.lndHarness.Bob, t.universeServer, func(params *tapdHarnessParams) { + params.noDefaultUniverseSync = true params.addrAssetSyncerDisable = disableSyncer }, ) diff --git a/itest/mint_batch_stress_test.go b/itest/mint_batch_stress_test.go index b4103ebc1..124ae44ea 100644 --- a/itest/mint_batch_stress_test.go +++ b/itest/mint_batch_stress_test.go @@ -57,7 +57,7 @@ func testMintBatchNStressTest(t *harnessTest, batchSize int, // If we create a second tapd instance and sync the universe state, // the synced tree should match the source tree. bob := setupTapdHarness( - t.t, t, t.lndHarness.Bob, nil, + t.t, t, t.lndHarness.Bob, t.universeServer, ) defer func() { require.NoError(t.t, bob.stop(!*noDelete)) diff --git a/itest/test_harness.go b/itest/test_harness.go index 64cd737bd..1550f3a7b 100644 --- a/itest/test_harness.go +++ b/itest/test_harness.go @@ -240,6 +240,25 @@ func (h *harnessTest) syncUniverseState(target, syncer *tapdHarness, require.Equal(h.t, numExpectedAssets, numAssets) } +// addFederationServer adds a new federation server to the given tapd harness. +func (h *harnessTest) addFederationServer(host string, target *tapdHarness) { + ctxt, cancel := context.WithTimeout( + context.Background(), defaultWaitTimeout, + ) + defer cancel() + + _, err := target.AddFederationServer( + ctxt, &unirpc.AddFederationServerRequest{ + Servers: []*unirpc.UniverseFederationServer{ + { + Host: host, + }, + }, + }, + ) + require.NoError(h.t, err) +} + // nextAvailablePort returns the first port that is available for listening by // a new node. It panics if no port is found and the maximum available TCP port // is reached. @@ -346,6 +365,10 @@ type tapdHarnessParams struct { // startupSyncNumAssets is the number of assets that are expected to be // synced from the above node. startupSyncNumAssets int + + // noDefaultUniverseSync indicates whether the default universe server + // should be added as a federation server or not. + noDefaultUniverseSync bool } type Option func(*tapdHarnessParams) @@ -391,6 +414,12 @@ func setupTapdHarness(t *testing.T, ht *harnessTest, err = tapdHarness.start(params.expectErrExit) require.NoError(t, err) + // Add the default universe server as a federation server, unless + // specifically indicated by the caller. + if !params.noDefaultUniverseSync { + ht.addFederationServer(universe.service.rpcHost(), tapdHarness) + } + // Before we exit, we'll check to see if we need to sync the universe // state. if params.startupSyncNode != nil { diff --git a/itest/universe_pagination_test.go b/itest/universe_pagination_test.go index 2a639f938..9ef4c1065 100644 --- a/itest/universe_pagination_test.go +++ b/itest/universe_pagination_test.go @@ -36,7 +36,7 @@ func testUniversePaginationSimple(t *harnessTest) { // If we create a second tapd instance and sync the universe state, // the synced tree should match the source tree. bob := setupTapdHarness( - t.t, t, t.lndHarness.Bob, nil, + t.t, t, t.lndHarness.Bob, t.universeServer, ) defer func() { require.NoError(t.t, bob.stop(!*noDelete)) diff --git a/itest/universe_test.go b/itest/universe_test.go index 57597e273..5f9fe5b19 100644 --- a/itest/universe_test.go +++ b/itest/universe_test.go @@ -42,7 +42,10 @@ func testUniverseSync(t *harnessTest) { // With those assets created, we'll now create a new node that we'll // use to exercise the Universe sync. bob := setupTapdHarness( - t.t, t, t.lndHarness.Bob, nil, + t.t, t, t.lndHarness.Bob, t.universeServer, + func(params *tapdHarnessParams) { + params.noDefaultUniverseSync = true + }, ) defer func() { require.NoError(t.t, bob.stop(!*noDelete)) @@ -385,7 +388,10 @@ func testUniverseFederation(t *harnessTest) { // We'll kick off the test by making a new node, without hooking it up to // any existing Universe server. bob := setupTapdHarness( - t.t, t, t.lndHarness.Bob, nil, + t.t, t, t.lndHarness.Bob, t.universeServer, + func(params *tapdHarnessParams) { + params.noDefaultUniverseSync = true + }, ) defer func() { require.NoError(t.t, bob.stop(!*noDelete)) From 88346dc06b8c0cc0f765235fb39c758616d67213 Mon Sep 17 00:00:00 2001 From: Oliver Gugger <gugger@gmail.com> Date: Fri, 1 Dec 2023 18:07:57 -0500 Subject: [PATCH 8/9] itest: extract and tune proof courier backoff config With this commit we optimize the backoff config to enable much faster proof transmission during integration tests. A significant speedup also comes from reducing the time the custodian waits between detecting a transfer on-chain and attempting to fetch the proof with the courier. --- itest/tapd_harness.go | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/itest/tapd_harness.go b/itest/tapd_harness.go index 398415650..fe81f4ef2 100644 --- a/itest/tapd_harness.go +++ b/itest/tapd_harness.go @@ -46,6 +46,20 @@ var ( tapdb.DefaultPostgresFixtureLifetime, "The amount of time to "+ "allow the postgres fixture to run in total. Needs "+ "to be increased for long-running tests.") + + // defaultBackoffConfig is the default backoff config we'll use for + // sending proofs. + defaultBackoffConfig = proof.BackoffCfg{ + BackoffResetWait: time.Second, + NumTries: 5, + InitialBackoff: 300 * time.Millisecond, + MaxBackoff: 600 * time.Millisecond, + } + + // defaultProofRetrievalDelay is the default delay we'll use for the + // custodian to wait from observing a transaction on-chan to retrieving + // the proof from the courier. + defaultProofRetrievalDelay = 200 * time.Millisecond ) const ( @@ -182,14 +196,9 @@ func newTapdHarness(t *testing.T, ht *harnessTest, cfg tapdConfig, // Populate proof courier specific config fields. // // Use passed in backoff config or default config. - backoffCfg := &proof.BackoffCfg{ - BackoffResetWait: 2 * time.Second, - NumTries: 3, - InitialBackoff: 2 * time.Second, - MaxBackoff: 2 * time.Second, - } + backoffCfg := defaultBackoffConfig if opts.proofSendBackoffCfg != nil { - backoffCfg = opts.proofSendBackoffCfg + backoffCfg = *opts.proofSendBackoffCfg } // Used passed in proof receiver ack timeout or default. @@ -203,7 +212,7 @@ func newTapdHarness(t *testing.T, ht *harnessTest, cfg tapdConfig, // config from the hashmail courier config. finalCfg.HashMailCourier = &proof.HashMailCourierCfg{ ReceiverAckTimeout: receiverAckTimeout, - BackoffCfg: backoffCfg, + BackoffCfg: &backoffCfg, } switch typedProofCourier := (opts.proofCourier).(type) { @@ -224,7 +233,11 @@ func newTapdHarness(t *testing.T, ht *harnessTest, cfg tapdConfig, finalCfg.HashMailCourier = nil } + ht.t.Logf("Using proof courier address: %v", + finalCfg.DefaultProofCourierAddr) + // Set the custodian proof retrieval delay if it was specified. + finalCfg.CustodianProofRetrievalDelay = defaultProofRetrievalDelay if opts.custodianProofRetrievalDelay != nil { finalCfg.CustodianProofRetrievalDelay = *opts.custodianProofRetrievalDelay } From 63611604a661385e5225ec0b9a6311ec15cc9cfa Mon Sep 17 00:00:00 2001 From: Oliver Gugger <gugger@gmail.com> Date: Fri, 1 Dec 2023 18:35:27 -0500 Subject: [PATCH 9/9] itest: don't sync test nodes to each other Since we now have a main universe server by default, we can disable test nodes syncing directly to each other by default. --- itest/addrs_test.go | 8 -------- itest/collectible_split_test.go | 4 ---- itest/full_value_split_test.go | 4 ---- itest/multi_asset_group_test.go | 8 -------- itest/psbt_test.go | 32 -------------------------------- itest/re-issuance_test.go | 9 --------- itest/re-org_test.go | 12 ------------ itest/round_trip_send_test.go | 4 ---- itest/send_test.go | 18 ------------------ 9 files changed, 99 deletions(-) diff --git a/itest/addrs_test.go b/itest/addrs_test.go index 93a0eda4b..657cafc64 100644 --- a/itest/addrs_test.go +++ b/itest/addrs_test.go @@ -40,10 +40,6 @@ func testAddresses(t *harnessTest) { // assets made above. secondTapd := setupTapdHarness( t.t, t, t.lndHarness.Bob, t.universeServer, - func(params *tapdHarnessParams) { - params.startupSyncNode = t.tapd - params.startupSyncNumAssets = len(rpcAssets) - }, ) defer func() { require.NoError(t.t, secondTapd.stop(!*noDelete)) @@ -169,10 +165,6 @@ func testMultiAddress(t *harnessTest) { alice := t.tapd bob := setupTapdHarness( t.t, t, t.lndHarness.Bob, t.universeServer, - func(params *tapdHarnessParams) { - params.startupSyncNode = alice - params.startupSyncNumAssets = len(rpcAssets) - }, ) defer func() { require.NoError(t.t, bob.stop(!*noDelete)) diff --git a/itest/collectible_split_test.go b/itest/collectible_split_test.go index f8fd17035..2f987e8e7 100644 --- a/itest/collectible_split_test.go +++ b/itest/collectible_split_test.go @@ -53,10 +53,6 @@ func testCollectibleSend(t *harnessTest) { // serve as the node which'll receive the assets. secondTapd := setupTapdHarness( t.t, t, t.lndHarness.Bob, t.universeServer, - func(params *tapdHarnessParams) { - params.startupSyncNode = t.tapd - params.startupSyncNumAssets = len(rpcAssets) - }, ) defer func() { require.NoError(t.t, secondTapd.stop(!*noDelete)) diff --git a/itest/full_value_split_test.go b/itest/full_value_split_test.go index c60a53ff6..84afb2430 100644 --- a/itest/full_value_split_test.go +++ b/itest/full_value_split_test.go @@ -33,10 +33,6 @@ func testFullValueSend(t *harnessTest) { // serve as the node which'll receive the assets. secondTapd := setupTapdHarness( t.t, t, t.lndHarness.Bob, t.universeServer, - func(params *tapdHarnessParams) { - params.startupSyncNode = t.tapd - params.startupSyncNumAssets = len(rpcAssets) - }, ) defer func() { require.NoError(t.t, secondTapd.stop(!*noDelete)) diff --git a/itest/multi_asset_group_test.go b/itest/multi_asset_group_test.go index 82d9706a0..3dae13188 100644 --- a/itest/multi_asset_group_test.go +++ b/itest/multi_asset_group_test.go @@ -97,10 +97,6 @@ func testMintMultiAssetGroups(t *harnessTest) { // ensure that they can be sent and received correctly. secondTapd := setupTapdHarness( t.t, t, t.lndHarness.Bob, t.universeServer, - func(params *tapdHarnessParams) { - params.startupSyncNode = t.tapd - params.startupSyncNumAssets = 4 - }, ) defer func() { require.NoError(t.t, secondTapd.stop(!*noDelete)) @@ -325,10 +321,6 @@ func testMultiAssetGroupSend(t *harnessTest) { // assets made above. secondTapd := setupTapdHarness( t.t, t, t.lndHarness.Bob, t.universeServer, - func(params *tapdHarnessParams) { - params.startupSyncNode = t.tapd - params.startupSyncNumAssets = groupCount - }, ) defer func() { require.NoError(t.t, secondTapd.stop(!*noDelete)) diff --git a/itest/psbt_test.go b/itest/psbt_test.go index c0711ce4e..245ac0566 100644 --- a/itest/psbt_test.go +++ b/itest/psbt_test.go @@ -44,10 +44,6 @@ func testPsbtScriptHashLockSend(t *harnessTest) { // serve as the node which'll receive the assets. secondTapd := setupTapdHarness( t.t, t, t.lndHarness.Bob, t.universeServer, - func(params *tapdHarnessParams) { - params.startupSyncNode = t.tapd - params.startupSyncNumAssets = len(rpcAssets) - }, ) defer func() { require.NoError(t.t, secondTapd.stop(!*noDelete)) @@ -170,10 +166,6 @@ func testPsbtScriptCheckSigSend(t *harnessTest) { // serve as the node which'll receive the assets. secondTapd := setupTapdHarness( t.t, t, t.lndHarness.Bob, t.universeServer, - func(params *tapdHarnessParams) { - params.startupSyncNode = t.tapd - params.startupSyncNumAssets = len(rpcAssets) - }, ) defer func() { require.NoError(t.t, secondTapd.stop(!*noDelete)) @@ -315,10 +307,6 @@ func testPsbtNormalInteractiveFullValueSend(t *harnessTest) { // serve as the node which'll receive the assets. secondTapd := setupTapdHarness( t.t, t, t.lndHarness.Bob, t.universeServer, - func(params *tapdHarnessParams) { - params.startupSyncNode = t.tapd - params.startupSyncNumAssets = len(rpcAssets) - }, ) defer func() { require.NoError(t.t, secondTapd.stop(!*noDelete)) @@ -366,10 +354,6 @@ func testPsbtGroupedInteractiveFullValueSend(t *harnessTest) { // serve as the node which'll receive the assets. secondTapd := setupTapdHarness( t.t, t, t.lndHarness.Bob, t.universeServer, - func(params *tapdHarnessParams) { - params.startupSyncNode = t.tapd - params.startupSyncNumAssets = len(rpcAssets) - }, ) defer func() { require.NoError(t.t, secondTapd.stop(!*noDelete)) @@ -526,10 +510,6 @@ func testPsbtNormalInteractiveSplitSend(t *harnessTest) { // serve as the node which'll receive the assets. secondTapd := setupTapdHarness( t.t, t, t.lndHarness.Bob, t.universeServer, - func(params *tapdHarnessParams) { - params.startupSyncNode = t.tapd - params.startupSyncNumAssets = len(rpcAssets) - }, ) defer func() { require.NoError(t.t, secondTapd.stop(!*noDelete)) @@ -577,10 +557,6 @@ func testPsbtGroupedInteractiveSplitSend(t *harnessTest) { // serve as the node which'll receive the assets. secondTapd := setupTapdHarness( t.t, t, t.lndHarness.Bob, t.universeServer, - func(params *tapdHarnessParams) { - params.startupSyncNode = t.tapd - params.startupSyncNumAssets = len(rpcAssets) - }, ) defer func() { require.NoError(t.t, secondTapd.stop(!*noDelete)) @@ -735,10 +711,6 @@ func testPsbtInteractiveTapscriptSibling(t *harnessTest) { // serve as the node which'll receive the assets. secondTapd := setupTapdHarness( t.t, t, t.lndHarness.Bob, t.universeServer, - func(p *tapdHarnessParams) { - p.startupSyncNode = t.tapd - p.startupSyncNumAssets = len(rpcAssets) - }, ) defer func() { require.NoError(t.t, secondTapd.stop(!*noDelete)) @@ -863,10 +835,6 @@ func testPsbtMultiSend(t *harnessTest) { // serve as the node which'll receive the assets. secondTapd := setupTapdHarness( t.t, t, t.lndHarness.Bob, t.universeServer, - func(params *tapdHarnessParams) { - params.startupSyncNode = t.tapd - params.startupSyncNumAssets = len(rpcAssets) - }, ) defer func() { require.NoError(t.t, secondTapd.stop(!*noDelete)) diff --git a/itest/re-issuance_test.go b/itest/re-issuance_test.go index 6c140dab2..a043fb1df 100644 --- a/itest/re-issuance_test.go +++ b/itest/re-issuance_test.go @@ -51,13 +51,8 @@ func testReIssuance(t *harnessTest) { // Create a second node, which will have no information about previously // minted assets or asset groups. - numTotalAssets := len(normalGroupGen) + len(collectGroupGen) secondTapd := setupTapdHarness( t.t, t, t.lndHarness.Bob, t.universeServer, - func(params *tapdHarnessParams) { - params.startupSyncNode = t.tapd - params.startupSyncNumAssets = numTotalAssets - }, ) defer func() { require.NoError(t.t, secondTapd.stop(!*noDelete)) @@ -341,10 +336,6 @@ func testMintWithGroupKeyErrors(t *harnessTest) { // minted assets or asset groups. secondTapd := setupTapdHarness( t.t, t, t.lndHarness.Bob, t.universeServer, - func(params *tapdHarnessParams) { - params.startupSyncNode = t.tapd - params.startupSyncNumAssets = len(collectGroupGen) - }, ) defer func() { require.NoError(t.t, secondTapd.stop(!*noDelete)) diff --git a/itest/re-org_test.go b/itest/re-org_test.go index 6f3524b08..21e29a79e 100644 --- a/itest/re-org_test.go +++ b/itest/re-org_test.go @@ -53,10 +53,6 @@ func testReOrgMint(t *harnessTest) { // node will be used to synchronize universe state. secondTapd := setupTapdHarness( t.t, t, t.lndHarness.Bob, t.universeServer, - func(params *tapdHarnessParams) { - params.startupSyncNode = t.tapd - params.startupSyncNumAssets = len(assetList) - }, ) defer func() { require.NoError(t.t, secondTapd.stop(!*noDelete)) @@ -139,10 +135,6 @@ func testReOrgSend(t *harnessTest) { // node will be used to synchronize universe state. secondTapd := setupTapdHarness( t.t, t, t.lndHarness.Bob, t.universeServer, - func(params *tapdHarnessParams) { - params.startupSyncNode = t.tapd - params.startupSyncNumAssets = len(assetList) - }, ) defer func() { require.NoError(t.t, secondTapd.stop(!*noDelete)) @@ -262,10 +254,6 @@ func testReOrgMintAndSend(t *harnessTest) { // node will be used to synchronize universe state. secondTapd := setupTapdHarness( t.t, t, t.lndHarness.Bob, t.universeServer, - func(params *tapdHarnessParams) { - params.startupSyncNode = t.tapd - params.startupSyncNumAssets = len(assetList) - }, ) defer func() { require.NoError(t.t, secondTapd.stop(!*noDelete)) diff --git a/itest/round_trip_send_test.go b/itest/round_trip_send_test.go index 87bdb5ca6..d312eed21 100644 --- a/itest/round_trip_send_test.go +++ b/itest/round_trip_send_test.go @@ -41,10 +41,6 @@ func testRoundTripSend(t *harnessTest) { // serve as the node which'll receive the assets. secondTapd := setupTapdHarness( t.t, t, t.lndHarness.Bob, t.universeServer, - func(params *tapdHarnessParams) { - params.startupSyncNode = t.tapd - params.startupSyncNumAssets = len(rpcAssets) - }, ) defer func() { require.NoError(t.t, secondTapd.stop(!*noDelete)) diff --git a/itest/send_test.go b/itest/send_test.go index a57301dc6..c7ab48f26 100644 --- a/itest/send_test.go +++ b/itest/send_test.go @@ -88,10 +88,6 @@ func testBasicSendUnidirectional(t *harnessTest) { // node will be used to synchronize universe state. secondTapd := setupTapdHarness( t.t, t, t.lndHarness.Bob, t.universeServer, - func(params *tapdHarnessParams) { - params.startupSyncNode = t.tapd - params.startupSyncNumAssets = len(rpcAssets) - }, ) defer func() { require.NoError(t.t, secondTapd.stop(!*noDelete)) @@ -215,8 +211,6 @@ func testRestartReceiverCheckBalance(t *harnessTest) { recvTapd := setupTapdHarness( t.t, t, t.lndHarness.Bob, t.universeServer, func(params *tapdHarnessParams) { - params.startupSyncNode = t.tapd - params.startupSyncNumAssets = len(rpcAssets) params.custodianProofRetrievalDelay = &custodianProofRetrievalDelay }, ) @@ -458,10 +452,6 @@ func testBasicSendPassiveAsset(t *harnessTest) { // Set up a new node that will serve as the receiving node. recvTapd := setupTapdHarness( t.t, t, t.lndHarness.Bob, t.universeServer, - func(params *tapdHarnessParams) { - params.startupSyncNode = t.tapd - params.startupSyncNumAssets = len(rpcAssets) - }, ) defer func() { require.NoError(t.t, recvTapd.stop(!*noDelete)) @@ -1212,10 +1202,6 @@ func testMultiInputSendNonInteractiveSingleID(t *harnessTest) { // node. Sync the new node with the primary node. bobTapd := setupTapdHarness( t.t, t, t.lndHarness.Bob, t.universeServer, - func(params *tapdHarnessParams) { - params.startupSyncNode = t.tapd - params.startupSyncNumAssets = len(rpcAssets) - }, ) defer func() { require.NoError(t.t, bobTapd.stop(!*noDelete)) @@ -1305,10 +1291,6 @@ func testSendMultipleCoins(t *harnessTest) { // node will be used to synchronize universe state. secondTapd := setupTapdHarness( t.t, t, t.lndHarness.Bob, t.universeServer, - func(params *tapdHarnessParams) { - params.startupSyncNode = t.tapd - params.startupSyncNumAssets = len(rpcAssets) - }, ) defer func() { require.NoError(t.t, secondTapd.stop(!*noDelete))