From 41e22b9ae5b758c6afe46c576e48b1974441e70a Mon Sep 17 00:00:00 2001 From: ffranr Date: Thu, 4 Jan 2024 12:04:08 +0000 Subject: [PATCH 1/2] tapgarden: refactor Custodian.receiveProof so that it's sync agnostic This commit refactors the method `Custodian.receiveProof` such that it's sync/goroutine agnostic (can be run with/without a goroutine). This change moves all goroutine wait group management code to the point where the goroutine is started. This commit modifies `receiveProof` such that it returns an error rather than writes an error directly to log. This means that we can pass the error to the custodian's error channel. --- tapgarden/custodian.go | 53 +++++++++++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 16 deletions(-) diff --git a/tapgarden/custodian.go b/tapgarden/custodian.go index 8d5b6b352..8cd8bf607 100644 --- a/tapgarden/custodian.go +++ b/tapgarden/custodian.go @@ -288,7 +288,14 @@ func (c *Custodian) watchInboundAssets() { // If we didn't find a proof, we'll launch a goroutine to use // the ProofCourier to import the proof into our local DB. c.Wg.Add(1) - go c.receiveProof(event.Addr.Tap, event.Outpoint) + go func() { + defer c.Wg.Done() + + recErr := c.receiveProof(event.Addr.Tap, event.Outpoint) + if recErr != nil { + reportErr(recErr) + } + }() } // Read all on-chain transactions and make sure they are mapped to an @@ -402,7 +409,17 @@ func (c *Custodian) inspectWalletTx(walletTx *lndclient.Transaction) error { // ProofCourier to import the proof into our // local DB. c.Wg.Add(1) - go c.receiveProof(event.Addr.Tap, op) + go func() { + defer c.Wg.Done() + + recErr := c.receiveProof( + event.Addr.Tap, op, + ) + if recErr != nil { + log.Errorf("Unable to receive "+ + "proof: %v", recErr) + } + }() } continue @@ -434,7 +451,15 @@ func (c *Custodian) inspectWalletTx(walletTx *lndclient.Transaction) error { // launch a goroutine to use the ProofCourier to import the // proof into our local DB. c.Wg.Add(1) - go c.receiveProof(addr, op) + go func() { + defer c.Wg.Done() + + recErr := c.receiveProof(addr, op) + if recErr != nil { + log.Errorf("Unable to receive proof: %v", + recErr) + } + }() } return nil @@ -442,11 +467,7 @@ func (c *Custodian) inspectWalletTx(walletTx *lndclient.Transaction) error { // receiveProof attempts to receive a proof for the given address and outpoint // via the proof courier service. -// -// NOTE: This must be called as a goroutine. -func (c *Custodian) receiveProof(addr *address.Tap, op wire.OutPoint) { - defer c.Wg.Done() - +func (c *Custodian) receiveProof(addr *address.Tap, op wire.OutPoint) error { ctx, cancel := c.WithCtxQuitNoTimeout() defer cancel() @@ -466,9 +487,8 @@ func (c *Custodian) receiveProof(addr *address.Tap, op wire.OutPoint) { &addr.ProofCourierAddr, recipient, ) if err != nil { - log.Errorf("Unable to initiate proof courier service handle: "+ - "%v", err) - return + return fmt.Errorf("unable to initiate proof courier service "+ + "handle: %w", err) } // Update courier handle events subscribers before attempting to @@ -484,7 +504,7 @@ func (c *Custodian) receiveProof(addr *address.Tap, op wire.OutPoint) { select { case <-time.After(c.cfg.ProofRetrievalDelay): case <-ctx.Done(): - return + return nil } // Attempt to receive proof via proof courier service. @@ -496,8 +516,8 @@ func (c *Custodian) receiveProof(addr *address.Tap, op wire.OutPoint) { } addrProof, err := courier.ReceiveProof(ctx, loc) if err != nil { - log.Errorf("Unable to receive proof using courier: %v", err) - return + return fmt.Errorf("unable to receive proof using courier: %w", + err) } log.Debugf("Received proof for: script_key=%x, asset_id=%x", @@ -511,9 +531,10 @@ func (c *Custodian) receiveProof(addr *address.Tap, op wire.OutPoint) { ctx, headerVerifier, c.cfg.GroupVerifier, false, addrProof, ) if err != nil { - log.Errorf("Unable to import proofs: %v", err) - return + return fmt.Errorf("unable to import proofs: %w", err) } + + return nil } // mapToTapAddr attempts to match a transaction output to a Taproot Asset From 58d4baa2c471676b16de83d80672739c123c0751 Mon Sep 17 00:00:00 2001 From: ffranr Date: Fri, 5 Jan 2024 14:55:46 +0000 Subject: [PATCH 2/2] tapgarden: handle proof received from courier using subscription channel This commit ensures that a proof received within a proof courier goroutine is fed into the proof subscription channel. This ensures that any event associated with the new proof will be cleaned up. --- tapgarden/custodian.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tapgarden/custodian.go b/tapgarden/custodian.go index 8cd8bf607..4184d164e 100644 --- a/tapgarden/custodian.go +++ b/tapgarden/custodian.go @@ -534,6 +534,11 @@ func (c *Custodian) receiveProof(addr *address.Tap, op wire.OutPoint) error { return fmt.Errorf("unable to import proofs: %w", err) } + // The proof is now verified and in our local archive. We will now + // finalize handling the proof like we would with any other newly + // received proof. + c.proofSubscription.NewItemCreated.ChanIn() <- addrProof.Blob + return nil }