Skip to content

Commit

Permalink
multi: allow proof courier to short cut with local archive
Browse files Browse the repository at this point in the history
With this commit we allow the universe RPC courier to short cut the
iterative proof retrieval process if we arrive at a proof in the chain
that we already have in the local archive. And since the local archive
only stores full chains of proofs, once we get one from it, the full
retrieval process is complete.
  • Loading branch information
guggero committed Dec 12, 2023
1 parent c534ce1 commit 34d139a
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 18 deletions.
69 changes: 62 additions & 7 deletions proof/courier.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,8 +220,8 @@ func (h *UniverseRpcCourierAddr) NewCourier(_ context.Context,
return &UniverseRpcCourier{
recipient: recipient,
client: client,
cfg: cfg,
backoffHandle: backoffHandle,
transfer: cfg.TransferLog,
subscribers: subscribers,
}, nil
}
Expand Down Expand Up @@ -267,6 +267,10 @@ type CourierCfg struct {
// TransferLog is a log for recording proof delivery and retrieval
// attempts.
TransferLog TransferLog

// LocalArchive is an archive that can be used to fetch proofs from the
// local archive.
LocalArchive Archiver
}

// ProofMailbox represents an abstract store-and-forward mailbox that can be
Expand Down Expand Up @@ -1030,14 +1034,13 @@ type UniverseRpcCourier struct {
// the universe RPC server.
client unirpc.UniverseClient

// cfg is the general courier configuration.
cfg *CourierCfg

// backoffHandle is a handle to the backoff procedure used in proof
// delivery.
backoffHandle *BackoffHandler

// transfer is the log that the courier will use to record the
// attempted delivery of proofs to the receiver.
transfer TransferLog

// subscribers is a map of components that want to be notified on new
// events, keyed by their subscription ID.
subscribers map[uint64]*fn.EventReceiver[fn.Event]
Expand Down Expand Up @@ -1206,7 +1209,9 @@ func (c *UniverseRpcCourier) ReceiveProof(ctx context.Context,
return proofBlob, nil
}

proofFile, err := FetchProofProvenance(ctx, originLocator, fetchProof)
proofFile, err := FetchProofProvenance(
ctx, c.cfg.LocalArchive, originLocator, fetchProof,
)
if err != nil {
return nil, fmt.Errorf("error fetching proof provenance: %w",
err)
Expand Down Expand Up @@ -1283,7 +1288,8 @@ type TransferLog interface {
// FetchProofProvenance iterates backwards through the main chain of proofs
// until it reaches the genesis point (the asset is the genesis asset) and then
// returns the full proof file with the full provenance for the asset.
func FetchProofProvenance(ctx context.Context, originLocator Locator,
func FetchProofProvenance(ctx context.Context, localArchive Archiver,
originLocator Locator,
fetchSingleProof func(context.Context, Locator) (Blob, error)) (*File,
error) {

Expand All @@ -1300,6 +1306,55 @@ func FetchProofProvenance(ctx context.Context, originLocator Locator,
// is a reversal of that found in the proof file.
var reversedProofs []Blob
for {
// Before we attempt to fetch the proof from the potentially
// remote universe, we'll check our local archive to see if we
// already have it. This doesn't make sense in all cases, so we
// allow the local archive to be nil, in which case we just skip
// this step.
var (
fullProof Blob
err error
)
if localArchive != nil {
fullProof, err = localArchive.FetchProof(
ctx, currentLocator,
)
}

// If we don't have a local archive, then the IsFile() check
// returns false, and we skip this block.
if err == nil && fullProof.IsFile() {
// The file in the local archive contains the full
// provenance from the current proof back to the
// genesis.
proofFile, err := fullProof.AsFile()
if err != nil {
return nil, fmt.Errorf("unable to decode "+
"proof file: %w", err)
}

// So if this is the first proof we've fetched, we're
// already done.
if len(reversedProofs) == 0 {
return proofFile, nil
}

// If we have already fetched some proofs, we'll need to
// append them to the proof file we just fetched.
for i := len(reversedProofs) - 1; i >= 0; i-- {
err := proofFile.AppendProofRaw(
reversedProofs[i],
)
if err != nil {
return nil, fmt.Errorf("error "+
"appending proof to proof "+
"file: %w", err)
}
}

return proofFile, nil
}

// Setup proof receive/query routine and start backoff
// procedure.
proofBlob, err := fetchSingleProof(ctx, currentLocator)
Expand Down
15 changes: 5 additions & 10 deletions tapcfg/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -231,16 +231,11 @@ func genServerConfig(cfg *Config, cfgLogger btclog.Logger,
}
}

// TODO(ffranr): This logic is leftover for integration tests which
// do not yet enable a proof courier. Remove once all integration tests
// support a proof courier.
var proofCourierCfg *proof.CourierCfg
if cfg.HashMailCourier != nil {
proofCourierCfg = &proof.CourierCfg{
ReceiverAckTimeout: cfg.HashMailCourier.ReceiverAckTimeout,
BackoffCfg: cfg.HashMailCourier.BackoffCfg,
TransferLog: assetStore,
}
proofCourierCfg := &proof.CourierCfg{
ReceiverAckTimeout: cfg.HashMailCourier.ReceiverAckTimeout,
BackoffCfg: cfg.HashMailCourier.BackoffCfg,
TransferLog: assetStore,
LocalArchive: proofArchive,
}

reOrgWatcher := tapgarden.NewReOrgWatcher(&tapgarden.ReOrgWatcherConfig{
Expand Down
2 changes: 1 addition & 1 deletion tapdb/multiverse.go
Original file line number Diff line number Diff line change
Expand Up @@ -913,7 +913,7 @@ func (b *MultiverseStore) FetchProof(ctx context.Context,
return proofs[0].Leaf.RawProof, nil
}

file, err := proof.FetchProofProvenance(ctx, id, fetchProof)
file, err := proof.FetchProofProvenance(ctx, nil, id, fetchProof)
if err != nil {
return nil, fmt.Errorf("error fetching proof from archive: %w",
err)
Expand Down

0 comments on commit 34d139a

Please sign in to comment.