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

[1/2] custodian: look up proofs in local universe as well #726

Merged
merged 11 commits into from
Jan 12, 2024

Conversation

guggero
Copy link
Member

@guggero guggero commented Dec 6, 2023

Depends on #712.

Fixes #578.

This PR updates the proof notification publish/subscribe mechanism in a way that allows us to pass in multiple proof sources to the custodian so it can detect incoming proofs from multiple sources.

Copy link
Member

@Roasbeef Roasbeef left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work! Main comment is if we really want to overload Blob (tho it already kinda is) vs using distinct types, and then an Either to allow them both be used in instances where either of them will work.

Reading over this change, it struck me (once again), that we should probably try to consolidate all the different proof storage interfaces we have. At times it isn't super easy to follow where a proof if coming from or why, but the multi wrappers do help a bit.

proof/courier.go Show resolved Hide resolved
tapdb/assets_store.go Outdated Show resolved Hide resolved
tapdb/multiverse.go Outdated Show resolved Hide resolved
// Blob represents a serialized proof file, including the checksum.
// Blob either represents a serialized proof file, including the checksum or a
// single serialized issuance/transition proof. Which one it is can be found out
// from the leading magic bytes (or the helper methods that inspect those).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I wonder if we would be better of making these into different types instead. We added the magic prefix bytes partially to avoid confusing them in the first place. With the type route, we'd break compilation if one was attempted to be passed in where the other was accepted. As is, we reply on runtime checks to avoid such classes of bugs.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could use the Either type added in the multiverse root PR as an example. Then you can still use Blob everywhere, but rely on type safety re protection of trying to use one vs the other.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think distinguishing between a single proof or a proof file would help a lot in the clarity of the code. But I think that would be a bigger refactor and should probably be done in a separate PR.
Do you think this is a reasonable temporary step for this PR?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SGTM, down to make an issue for it so we can move on here. Main thing is we can supplement the byte level prefix with a type, and then accept that type contextually to cut down on possible bugs in this area.

tapgarden/custodian.go Outdated Show resolved Hide resolved
tapgarden/custodian.go Show resolved Hide resolved
itest/send_test.go Show resolved Hide resolved
@guggero guggero force-pushed the custodian-local-universe branch 2 times, most recently from c534ce1 to 994837f Compare December 13, 2023 14:22
@guggero guggero requested a review from Roasbeef December 13, 2023 14:23
@guggero guggero force-pushed the custodian-local-universe branch from 994837f to 54bc8e7 Compare December 13, 2023 18:10
@jharveyb jharveyb self-requested a review December 14, 2023 00:17
Copy link
Contributor

@jharveyb jharveyb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A wonderful PR and itest 🎉

The callback for proof fetching is pretty neat also. Small Q on how we're fetching proofs overall + some nits.

fn/iter.go Show resolved Hide resolved
proof/archive.go Show resolved Hide resolved
tapdb/multiverse.go Show resolved Hide resolved
tapdb/assets_store.go Show resolved Hide resolved
@jharveyb
Copy link
Contributor

Actually, given that some parts of this only handle transfer proofs, do these changes enable 'sideloaded' issuance proofs to get added to our local universe state?

I think for transfers it's implicit as the transfer proof includes the issuance proof, but for those who want to manually sync issuance i'm not sure if we test that rn.

@guggero guggero changed the title custodian: look up proofs in local universe as well [1/2] custodian: look up proofs in local universe as well Dec 14, 2023
@ffranr
Copy link
Contributor

ffranr commented Dec 20, 2023

This PR has two reviewers. I've had a review request for this. @guggero would you like me to review also?

@guggero
Copy link
Member Author

guggero commented Dec 20, 2023

This PR has two reviewers. I've had a review request for this. @guggero would you like me to review also?

No, it's fine, thank you. You basically already reviewed this PR since the commits of this one used to be included in #730 which you did look at.

@guggero guggero removed the request for review from ffranr December 20, 2023 14:21
@guggero
Copy link
Member Author

guggero commented Dec 20, 2023

Actually, given that some parts of this only handle transfer proofs, do these changes enable 'sideloaded' issuance proofs to get added to our local universe state?

Yes, since the only way to side load a proof currently (without using dev mode), is the universe RPC's InsertProof method which does allow you to insert an issuance proof directly into the universe.
And that does insert the meta data and genesis information into the asset DB as well.
But it does sound like a good integration test case, so I'll add it.

@guggero guggero force-pushed the custodian-local-universe branch from 54bc8e7 to 32fe75c Compare December 20, 2023 15:28
@guggero guggero requested a review from jharveyb December 20, 2023 15:28
@guggero guggero force-pushed the custodian-local-universe branch from 32fe75c to dc08080 Compare December 20, 2023 15:31
@jharveyb
Copy link
Contributor

jharveyb commented Dec 21, 2023

Yes, since the only way to side load a proof currently (without using dev mode), is the universe RPC's InsertProof method which does allow you to insert an issuance proof directly into the universe. And that does insert the meta data and genesis information into the asset DB as well. But it does sound like a good integration test case, so I'll add it.

With the itest change, I think we still don't exercise import on the genesis proof?

The second node has the default universe server set, so IIUC they sync the genesis proof at that point. Then they receive only the transfer proof, and import that successfully.

What I meant earlier was to actually have the universe server unset for the second node and import the issuance proof manually via ImportProof. Then, perform the transfer and import that proof manually as well (which the test does do right now).

Latest changes LGTM otherwise.

@lightninglabs-deploy
Copy link

@Roasbeef: review reminder
@jharveyb: review reminder

@guggero
Copy link
Member Author

guggero commented Jan 3, 2024

You mean because t.universeServer is still passed in?
We only discussed changing the behavior of this, but currently that variable is required. We do set params.noDefaultUniverseSync = true though, which does disable syncing of any proofs with the universe.

So I think the test does exactly what you propose?
With sendProofUniRPC(t, t.tapd, bob, firstAsset.ScriptKey, firstAssetGen) manually syncing the issuance proof.

Copy link
Contributor

@jharveyb jharveyb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point re: testing issuance insertion as-is. LGTM!

With this commit we change the NotifyArchiver to the bare minimum that
we actually need in the custodian.
With this commit we extract the logic for iteratively retrieving the
full provenance for an asset by starting at the last proof then querying
each previous proof until we arrive at the genesis.
We will want to re-use this logic outside of the proof courier itself,
so it's useful to extract into a general-purpose function where the
actual retrieval of an individual proof is done in a callback and can be
adjusted to the current proof storage (local or remote).
This is an optimization that allows us to only extract the asset from
the proof when fetching the full proof provenance. That saves us a whole
decode/encode round trip per proof.
In some situations we want a quick way to find out if we have a proof
(or not) without actually fetching it, so we add a HasProof method to
the proof.Archive interface.
The MultiArchiver will return false if one of the backends does not have
the proof, so we can use that method to find out if we have a
discrepancy between the backends and should import a proof file.
With this commit we prepare the MultiverseStore to also act as a
NotifyArchiver that can notify about new incoming proofs.
Because the universe only deals with individual proof leaves, we want
the custodian to be able to deal with both proof files and single
proofs.
To make it easy to distinguish and convert between the two, we add some
helper methods to the proof.Blob type.
Since we now might get either a full proof file or just a transition
proof, the custodian needs to be updated to be able to deal with both.
This commit creates a new notifier that can relay registrations for new
proofs to multiple notifier/archiver backends.
We then use that to pass in both the local assets store as well as the
multiverse store to the custodian to detect incoming proofs.
@guggero guggero force-pushed the custodian-local-universe branch from 6cc7b2a to 864b554 Compare January 9, 2024 07:44
@guggero
Copy link
Member Author

guggero commented Jan 9, 2024

Rebased, ready for final review @Roasbeef.

Copy link
Member

@Roasbeef Roasbeef left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 🍉

@@ -130,6 +130,18 @@ func All[T any](xs []T, pred func(T) bool) bool {
return true
}

// AllMapItems returns true if the passed predicate returns true for all items
// in the map.
func AllMapItems[T any, K comparable](xs map[K]T, pred func(T) bool) bool {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool! Looking forward to when/if they add more direct iterator stuff to the Go stdlib, then we'd only need one version of this.

// RegisterSubscriber adds a new subscriber for receiving events. The
// registration request is forwarded to all registered archives.
func (m *MultiArchiveNotifier) RegisterSubscriber(
receiver *fn.EventReceiver[Blob], deliverExisting bool,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leaving review note to self: does the subscriber need to be ready to handle multiple subscriptions notifications from all the archives for the same proof file?

@@ -76,6 +76,10 @@ var testCases = []*testCase{
test: testOfflineReceiverEventuallyReceives,
proofCourierType: proof.HashmailCourierType,
},
{
name: "addr send no proof courier with local universe import",
test: testSendNoCourierUniverseImport,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not gofmt'd?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Linter says: it actually is!

@Roasbeef Roasbeef merged commit 1741b14 into main Jan 12, 2024
14 checks passed
@guggero guggero deleted the custodian-local-universe branch January 12, 2024 08:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: ✅ Done
Development

Successfully merging this pull request may close these issues.

tapgarden/custodian: check the local proof archive/universe when looking to receipt proofs
5 participants