-
Notifications
You must be signed in to change notification settings - Fork 30
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
Refactor common STR verification functionality #170
Conversation
…to auditor-protocol
We will merge #155 first |
# The first commit's message is: Add TODO to move all generic STR auditing code to a separate module # The 2nd commit message will be skipped: # Use single generic verifySTRConsistency to be used by client and auditor
…r response message generic
protocol/auditor.go
Outdated
// FIXME: check whether the STR was issued on time and whatnot. | ||
// Maybe it has something to do w/ #81 and client transitioning between epochs. | ||
// Try to verify w/ what's been saved | ||
|
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.
I think we should add a FIXME:
// FIXME: we are returning the error immediately
// without saving the inconsistent STR
// see: https://github.com/coniks-sys/coniks-go/pull/74#commitcomment-19804686
here or in AuditDirectory
.
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.
Why is this a FIXME? Why should we be saving inconsistent STRs?
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 makes me think we should do:
Any STR that passes the checks in updateSTR will be stored and used by the client, regardless of whether the rest of the checks pass / fail, and that's fine since it contains proof of being issued.
I think we should have a TODO/FIXME here so we can come back later, when we address client recovery & whistle-blowing issues.
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.
I generally agree with this, but I think auditors should save inconsistent STRs in a separate list. I also agree that this is a whistleblowing and recovery issue. We should open a new issue for this if we don't have one already.
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.
protocol/auditor.go
Outdated
// or the appropriate consistency check error if any of the checks fail, | ||
// or str's epoch is anything other than the same or one ahead of | ||
// a.verifiedSTR. | ||
func (a *AudState) checkSTRAgainstVerified(str *DirSTR) 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.
Please reorder these functions as:
compareWithVerified()
verifySTRConsistency()
checkSTRAgainstVerified()
verifySTRRange()
protocol/auditor.go
Outdated
// the given prevSTR and the first STR in the given range, and | ||
// then verifies the consistency between each subsequent STR pair. | ||
func (a *AudState) verifySTRRange(prevSTR *DirSTR, strs []*DirSTR) 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.
Nitpicking: can we remove this empty line? Here and some other places.
if str == nil { | ||
// FIXME: if this comes from the auditor, this | ||
// should really be an ErrMalformedAuditorMessage | ||
return ErrMalformedDirectoryMessage |
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.
I also encountered this problem, and I think we should just change this error and ErrMalformedClientMessage
to ErrMalformedResquest
and ErrMalformedResponse
.
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.
I can open a separate pull later, since I already have this.
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.
Sounds good to me.
protocol/consistencychecks.go
Outdated
@@ -45,18 +43,48 @@ func NewCC(savedSTR *DirSTR, useTBs bool, signKey sign.PublicKey) *ConsistencyCh | |||
if !useTBs { | |||
panic("[coniks] Currently the server is forced to use TBs") | |||
} | |||
aud := NewAuditor(signKey, savedSTR) | |||
cc := &ConsistencyChecks{ |
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.
It is easier for readers when we use field:value initializers.
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.
I agree. This isn't currently consistent in all of the code, so we should fix this everywhere.
// the cc.verifiedSTR. | ||
// CheckEquivocation() is called when a client receives a response to a | ||
// message.AuditingRequest from an auditor. | ||
func (cc *ConsistencyChecks) CheckEquivocation(msg *Response) 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.
IMHO, we should open a separate pull for this feature, since I think we should cover something like the number of chosen auditors, and design a set of APIs for the /protocol
level.
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.
The number of chosen auditors is independent of the core equivocation check protocol -- that's what this is. What other APIs do we need for equivocation checking on the client?
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.
How about taking an array of auditors' Response
and passing them to CheckEquivocation
? I have no strong opinion about this, though.
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.
I thought about doing this, although that I think that already imposes a requirement on the client to check multiple auditors. I think that detail should be implemented at the application layer to make the use of auditors more flexible in the client.
If it's possible, please remove the empty line after the function name. |
protocol/auditlog.go
Outdated
signKey sign.PublicKey | ||
snapshots map[uint64]*DirSTR | ||
latestSTR *DirSTR | ||
snapshots []*DirSTR |
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.
Can we keep using the map as before? Is there any advantages over using a map?
I'm afraid that we may accidentally insert 2 same DirSTR into snapshots if we use slice.
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 a possibility, but the slice makes it much easier to append a whole batch of STRs. I wanted to avoid having to loop through a range twice, once for the verification, and one for the insertion into snapshots
. But maybe this wouldn't be a huge performance issue?
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 at current code, there are insertion and search operations, which are O(1), so I think it wouldn't be a huge performance issue.
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.
Also addressing this as part of #182
protocol/consistencychecks.go
Outdated
// TODO: if the auditor has returned a more recent STR, | ||
// should the client update its savedSTR? Should this | ||
// force a new round of monitoring? | ||
return cc.checkSTRAgainstVerified(LatestSTRInRange(strs.STR)) |
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.
Last-minute nitpicking: should we remove LatestSTRInRange
and just do
latestSTRInRange := strs[len(strs)-1]
return cc.checkSTRAgainstVerified(latestSTRInRange)
?
(or even pass strs[len(strs)-1]
directly to checkSTRAgainstVerified)
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.
LatestSTRInRange
is only used here, right? I added this when I using a slice for the snapshots
instead of a map, but it's no longer necessary now. I'll remove it.
// range if the message contains more than one STR. | ||
// AuditDirectory() returns the appropriate consistency check error | ||
// if any of the checks fail, or nil if the checks pass. | ||
func (a *AudState) AuditDirectory(strs []*DirSTR) 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.
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.
Hmm, I generally assume that the caller hasn't validated the parameters. In the case of AuditDirectory
, both ConsistencyChecks
and AuditLog
, both will call it inside of Audit
, so in that case I think it would be safe to assume that the caller did a validation beforehand. OTOH, adding a parameter validation here is trivial, so I think we can add it here to be safe.
|
||
// Auditor provides a generic interface allowing different | ||
// auditor types to implement specific auditing functionality. | ||
type Auditor interface { |
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 we should add a TODO "this interface is used nowhere, we should use it everywhere in ConsistencyChecks and AuditLog instead of AudState." ?
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.
I agree that ConsistencyChecks
and AuditLog
should "extend" Auditor
rather than AudState
, but to me this problem is more about how we can express what we mean.
Ideally, what I would have liked to do here is declare a generic auditor type/interface, as one would in Java for example, and have the AuditLog
and ConsistencyChecks
extend that class and implement something like an abstract AuditDirectory
method. I think what we have now comes closest to this. Maybe the solution would be to rename AudState
to Auditor
and rename Auditor
to something like AbstractAuditor
? Please feel free to suggest an alternative approach if there's a more Go-like way of expressing what I had in mind.
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.
Also, thinking ahead to implementing a CoSi-compatible auditor, AFAICT, it should be able to directly use AudState
(or whatever we call it) and implement AuditDirectory()
like we've done so far.
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.
I agree, though I have no idea what it should be :(. Thus, I suggest we add a TODO here or open an issue so we can address it later.
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.
Tbh, the way it's implemented right now was according to a suggestion you made to make AudState
implement Auditor
and have the other two use AudState
so that other kinds of auditors could implement something different. I'm a bit confused why you're suggesting now that we should change this again ;)
I need to think about it some more, but I think that the only new type of auditor which would have to implement the Auditor
interface would be a blockchain based auditor. What we have right now does express what we intended, so I don't think we need to change what we have. Maybe @arlolra and @liamsi can weigh in on this, too?
var _ Auditor = (*AudState)(nil) | ||
|
||
// NewAuditor instantiates a new auditor state from a persistance storage. | ||
func NewAuditor(signKey sign.PublicKey, verified *DirSTR) *AudState { |
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.
I would expect the return type here is Auditor
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 discussed about this at #170 (comment). For now, AudState
has some methods which shouldn't belong to the Auditor
interface.
protocol/auditlog.go
Outdated
func (h *directoryHistory) updateLatestSTR(newLatest *DirSTR) { | ||
h.snapshots[newLatest.Epoch] = newLatest | ||
h.latestSTR = newLatest | ||
// updateVerifiedSTR inserts a new range of STRs into a directory history; |
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.
range of STRs
?
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.
done.
protocol/auditlog.go
Outdated
h.updateLatestSTR(initSTR) | ||
return h | ||
// Audit checks that a directory's STR history | ||
// is linear and updates the audtor's state |
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.
auditor
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.
done.
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 @c633 for taking care of this!
Am I right to assume that this is ready to be merged? No new comments in over a week. |
Since the client and auditor both need to perform some common consistency checks on the STRs, all this functionality should be refactored into a generic auditor module. This will also require the implementation of STR verification over a range of epochs.
See #155 (comment)