-
Notifications
You must be signed in to change notification settings - Fork 65
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
Flag locally created logs as direct #374
Conversation
Signed-off-by: Carson Farmer <carson.farmer@gmail.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good! Some comments and questions...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the comments @sanderpick. I'm going to address these in the AM, but I think nothing outstanding, all comments and suggestions were clear and helpful 👍
Signed-off-by: Carson Farmer <carson.farmer@gmail.com>
net/net.go
Outdated
@@ -218,6 +218,7 @@ func (n *net) CreateThread(_ context.Context, id thread.ID, opts ...core.NewThre | |||
if !info.Key.Defined() { | |||
info.Key = thread.NewRandomKey() | |||
} | |||
// This may overwrite ThreadKey information if there is a mismatch |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that some existing tests relied on the ability to overwrite read and service keys, so no check or error is thrown when this happens. This seems ok, because it would support things like key rotation etc... but I've added this comment as a reminder and perhaps this should be documented in the public APIs?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about only adding new keys if they don't already exists? So, modifying logstore.AddThread
to not blindly overwrite?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So silently ignore if new/mismatched keys are used? That's an option for sure, would it lead to unexpected results?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe just error if something would be overwritten?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeh that's what I had, but we have some existing tests that rely on being able to overwrite. Hence my comment above... unless I'm missing something here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In particular, this test: https://github.com/textileio/go-threads/blob/master/db/db_test.go#L94
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could modify NewDB
to allow passing in ThreadOptions, so that you could specify the same keys again, and if you didn't, return an error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's what I went with.
Signed-off-by: Carson Farmer <carson.farmer@gmail.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Couple more comments and questions!
net/net.go
Outdated
@@ -218,6 +218,7 @@ func (n *net) CreateThread(_ context.Context, id thread.ID, opts ...core.NewThre | |||
if !info.Key.Defined() { | |||
info.Key = thread.NewRandomKey() | |||
} | |||
// This may overwrite ThreadKey information if there is a mismatch |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about only adding new keys if they don't already exists? So, modifying logstore.AddThread
to not blindly overwrite?
Signed-off-by: Carson Farmer <carson.farmer@gmail.com>
Ok, @sanderpick, this ended up touching a lot more places than I had initially anticipated, but it should now cover all our bases. Checks for all keys types have been added, and errors thrown for any mismatches. One 'own' log per thread is enforced, but multiple 'managed' logs are possible. There are also tests for the expected behavior, and peers can even replicate managed logs which is important for our JS use-cases. |
@@ -68,6 +69,13 @@ func WithNewToken(t thread.Token) NewOption { | |||
} | |||
} | |||
|
|||
// WithNewThreadKey provides control over thread keys to use with a db. | |||
func WithNewThreadKey(key thread.Key) NewOption { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was required to be able to get some tests passing again, but is also useful/required.
@@ -89,13 +92,35 @@ func (ls *logstore) AddThread(info thread.Info) error { | |||
if info.Key.Service() == nil { | |||
return fmt.Errorf("a service-key is required to add a thread") | |||
} | |||
if err := ls.AddServiceKey(info.ID, info.Key.Service()); err != nil { | |||
sk, err := ls.ServiceKey(info.ID) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Keeping these checks in the high-level AddThread function rather than in the individual stores because it might still be useful to override this behavior in certain cases. So seems like the most common operation should fail, but if you're digging into internals, its your fault if something get's messed up.
_, err := n.store.GetThread(id) | ||
if err == nil { | ||
return lstore.ErrThreadExists | ||
func (n *net) ensureUnique(id thread.ID, key crypto.Key) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is now a lot more verbose, as there are multiple different possible scenarios here, but I think the early outs help.
Signed-off-by: Carson Farmer <carson.farmer@gmail.com>
if err != nil { | ||
return err | ||
} | ||
// Early out if no log key required. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we don't care about log keys, then we'll end up creating a random one downstream, with negligible chance of a collision.
return nil | ||
} | ||
// Ensure we don't already have this log in our store. | ||
if _, ok := key.(crypto.PrivKey); ok { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this is a private key, and we don't already have a private key for this thread, we're good to go, otherwise, we fail 'early' here.
} | ||
return nil | ||
} | ||
pubKey, ok := key.(crypto.PubKey) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this is a public key, just make sure we don't already have a log for this key.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome, looks great! This is a great improvement... thanks for hanging in with the back and forth 💥
Thank you @sanderpick! |
feat: own vs managed log concepts and tooling Directly "managed" logs are those logs created or directly added by the local peer. Otherwise, unmanaged logs are those from other peers in a given thread. Related, "owned" logs are those logs for which the peer has the private key. There can only be one "owned" log, versus potentially many "managed" logs.
Fixes #373, and a better alternative to #372.
The approach here is to simply take advantage of the existing metadata store on the logstore to set a flag as to whether a given log is "managed?" by the local peer. Directly "managed" logs are those logs created or directly added by the local peer. Otherwise, unmanaged logs are those from other peers in a given thread. Related, "owned" logs are those logs for which the peer has the private key. There can only be one "owned" log, versus potentially many "managed" logs.
This should support multiple use cases: