-
Notifications
You must be signed in to change notification settings - Fork 7
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
Explicit message justification (Opt: generalization of quorumState) #31
Conversation
ab5b69d
to
56ed7d1
Compare
dd73283
to
6ed3e3d
Compare
641fbaf
to
529793e
Compare
More refactoring and optimizations to do (e.g. |
db678ed
to
17421fa
Compare
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 interface-based "generalization of quorumState" way of doing both at once here has introduced a lot of code, some copy paste, and plumbing of values around more than necessary. The message justificaition check should be performed at the same place the implicit justification is checked. Everything after that should just be able to assume justified messages. I don't think quorumState needs generalisation - it should know nothing about explicit validation and can instead be simplified if we go that route. State and justification will be completely separate, which will be great.
I'm still not that confident that supporting both at once in the codebase is reasonable. This method is not one that's just an easy removal of a single call and the block of code that it calls – it's had a large impact on the existing code structure.
This has identified the need for an improved PowerTable type, though, so let's break that out into a PR ahead of this one.
f3/api.go
Outdated
@@ -51,11 +51,19 @@ type Signer interface { | |||
Verify(sender ActorID, msg, sig []byte) bool | |||
} | |||
|
|||
type Aggregator interface { | |||
// Aggregates signatures from a participant to an existing signature. | |||
Aggregate(sig []byte, senderID ActorID, aggSignature []byte, signers *BitSet, actor2Index map[ActorID]uint64) ([]byte, *BitSet) |
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.
Putting the bitset and lookup table as parameters here implies that the host has the responsibility of interpreting these to work out what order to put the signatures together. I don't think that's right – the F3 code should do that. The host is the one that knows how to actually aggregate the signatures, but I think this API should be simple to implement, rather than simple to call. For example, we shouldn't re-implement this association in the fake/testing host (only the actual signing should be fake).
f3/chain.go
Outdated
func ZeroECChain() ECChain { | ||
return ECChain{} | ||
} | ||
|
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 it's better to just use ECChain{}
inline where needed. Here the canonical Go zero value is what we want. Having a method to construct the zero value implies that the canonical one is somehow not valid. (Note that nil
is also valid, maybe everywhere, and perhaps we should switch to using that).
sim/network.go
Outdated
func (n *Network) Aggregate(sig []byte, actorID f3.ActorID, aggSignature []byte, signers *f3.BitSet, actor2Index map[f3.ActorID]uint64) ([]byte, *f3.BitSet) { | ||
// Fake implementation. | ||
// Just appends signature to aggregate signature. | ||
// This fake aggregation is not commutative (order matters), unlike the real one. |
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 bit of an issue if it has any chance of constraining the calling code. Can you make it commute if the real one does? E.g. xor.
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 problem with XOR is that the verifier would have to somehow get the individual signatures in order to verify the aggregate, changing the interface of the aggregator
w.r.t. the non-fake implementation. I have instead ensured determinism of the aggregate and this determinism is checked in the verifyAggregate
, which is essentially equivalent for the purposes of the code outside the aggregator (the resulting signature is the same for everyone from aggregating and the verify only is correct if the signature is the same).
Left a comment in the Aggregate function.
panic("signers size is less than actor2Index") | ||
} | ||
|
||
signers.Set(actor2Index[actorID]) |
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.
Following on my comment about this API, having it mutate the parameter is very unexpected. The caller should do this (and drop the parameter).
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 (in dedicated PR #35 )
// GossiPBFT instance number | ||
Instance uint32 | ||
// GossiPBFT round | ||
Round uint32 |
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.
Put these in the same order as they are in GMessage. Remove the copy-pasta comments.
|
||
func ZeroAggEvidence() AggEvidence { | ||
return AggEvidence{} | ||
} |
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 don't think we need this method if the canonical Go zero value is what we want.
f3/granite.go
Outdated
} | ||
|
||
func (a AggEvidence) isZero() bool { | ||
return a.Step == "" && a.Value.IsZero() && a.Instance == 0 && a.Round == 0 && a.Signers.Size() == 0 && len(a.Signature) == 0 |
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.
Just check for a == AggEvidence{}
. It's debatable whether you need this method, since the caller can just do that.
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.
AggEvidence contains fields that make it not comparable with ==
such as Signers
(bitfield.Bitfield | BitSet), Signature
([] byte) and Value
(ECChain, which is []Tipset
).
f3/granite.go
Outdated
@@ -728,6 +1039,99 @@ func (c *convergeState) findMinTicketProposal() ECChain { | |||
return minValue | |||
} | |||
|
|||
// BitSet is a bitset implementation. | |||
type BitSet struct { |
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 import and use https://github.com/filecoin-project/go-bitfield/blob/master/bitfield.go instead
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.
|
||
// SenderIndex maps ActorID to a unique index in the range [0, len(powerTable.Entries)). | ||
// This is used to index into a BitSet. index2Actor is the reverse mapping. | ||
type SenderIndex struct { |
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.
Rather than this we probably want to build a stronger PowerTable type that is an ordered map, so we can just look up entries by index. The host should build it for us. I think defining and implementing that should be a PR of its own that you can do before this one.
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.
Just did this one: see here.
f3/granite.go
Outdated
} | ||
|
||
// Sort the keys | ||
sort.Slice(keys, func(i, j int) bool { return keys[i] < keys[j] }) |
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 probably isn't the ordering we will want - probably want descending by power instead.
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.
17421fa
to
fabf199
Compare
d1f0d2d
to
e8c84db
Compare
e8c84db
to
d5f3ee3
Compare
Resolves #16.
Incomplete, and so far mostly created just to allow for discussion of design decisions.