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

Add Aggregator interface and implement fake aggregator #35

Merged
merged 16 commits into from
Jan 24, 2024

Conversation

ranchalp
Copy link
Contributor

Builds upon #32, which in turn builds upon #34, so merge those first.

f3/api.go Outdated
// Aggregates signatures from a participant to an existing signature.
Aggregate(sig []byte, aggSignature []byte) []byte
// VerifyAggregate verifies an aggregate signature.
VerifyAggregate(payload, aggSig []byte, signers map[ActorID]struct{}) bool
Copy link
Member

Choose a reason for hiding this comment

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

This API seems to assume that the implementor knows how to get a public key for an ActorID somewhere. It works for the fake impl, but I don't think will for the real one. I think instead signers should just be a list of public keys, so that it becomes a pure function.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

Copy link
Contributor

Choose a reason for hiding this comment

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

Actually, I think it would be most natural for aggregate signature itself to encode the list of signers (e.g., as a bitmask with respect to the publicly known power table).

Copy link
Contributor

Choose a reason for hiding this comment

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

f3 will need to know about public keys either way, as it needs to store them in the power table/state. Yes, we could abstract pubkeys out in this interface, but then it means that the implementer of the API has to have access to the context-sensitive (per granite instance) power table

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Implemented the verification of the proper public keys as listed suggested in a previous PR

@ranchalp
Copy link
Contributor Author

Thanks again! addressed the comment

Copy link
Member

@anorth anorth left a comment

Choose a reason for hiding this comment

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

Let's merge the Signer.Verify method into the Aggregator interface (but rename it to SignatureVerifier), and then the SIgner interface only does actual signing (in non-fake this will delegate all the way out to Lotus).

Change the signing scheme to be concat the pubkey to the message, and verification (which should take the pubkey as a parameter instead of ActorID) to check that concatenation.

For aggregation, output payload ++ pubkeys (you can read the pubkey out of the input signature). Verify the new signature is unique before aggregation (error if not). Then verifying the aggregate is easy because the parameters are exactly payload and pubkeys.

There is coupling between the signing algorithm and verification, but that's the case for real signatures too!

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, aggSignature []byte) []byte
Copy link
Member

Choose a reason for hiding this comment

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

I suggest having this interface take a vector of signatures to be aggregated into the output all at once. The implementation can do the loop over one-at-a-time if that's the only way to implement it, but if faster methods exist for batch operations, it can do them too.

Allow the accumulator aggSignature to be an empty slice.

f3/api.go Outdated
// Aggregates signatures from a participant to an existing signature.
Aggregate(sig []byte, aggSignature []byte) []byte
// VerifyAggregate verifies an aggregate signature.
VerifyAggregate(payload, aggSig []byte, signers [][]byte) bool
Copy link
Member

Choose a reason for hiding this comment

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

Looks good, but let's define a type PubKey []byte to distinguish what the different byte slices are.

@ranchalp ranchalp force-pushed the aggregator branch 4 times, most recently from b676a04 to 6ee56ae Compare January 19, 2024 18:47
@Kubuxu Kubuxu self-requested a review January 23, 2024 18:18
@ranchalp
Copy link
Contributor Author

@Kubuxu new commits in the PR removed code from previous commits. Probably much better to check files changed instead of reviewing commit by commit.

sim/network.go Outdated
}

for i := 0; i < len(sigs); i++ {
if !reflect.DeepEqual(msg, sigs[i][pubKeyLen:]) {
Copy link
Contributor

@Kubuxu Kubuxu Jan 23, 2024

Choose a reason for hiding this comment

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

Use bytes.Equal

sim/network.go Outdated Show resolved Hide resolved
// Fake implementation.
// Just appends signature to aggregate signature.
// This fake aggregation is not commutative (order matters)
// But determinism is preserved by sorting by weight both here and in VerifyAggregate
Copy link
Contributor

Choose a reason for hiding this comment

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

IMO: the deterministic sorting should happen outside the interface to match real signature schemes which can also have this behaviour.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

But that would mean forcing outside the interface a sorting that may not be required by all signature schemes. Would it not be better to have it inside the signature schemes that need it only?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

(I get optimizing if the real BLS is not commutative, and coupling in that particular instantiation of the interface, but I also mean in particular in the case of the sorting required by this general-purpose (or so-intending) fake aggregation and verification scheme, that just happens to need to sort)

Copy link
Contributor

Choose a reason for hiding this comment

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

I see your point, and I don't know which approach is better at this moment. I mentioned it because this requirement was unclear to me, and I immediately highlighted it as a possible difference between test/sim and reality.

We can keep order independence internal, but then we should highlight it in the interface documentation.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We can keep order independence internal, but then we should highlight it in the interface documentation.

Sounds good, I suggest going back to this when we discuss interfaces in #42 not to duplicate discussions.

Verify(sender ActorID, msg, sig []byte) bool
Verify(pubKey PubKey, msg, sig []byte) bool
// Aggregates signatures from a participant to an existing signature.
Aggregate(sig [][]byte, aggSignature []byte) []byte
Copy link
Contributor

@Kubuxu Kubuxu Jan 23, 2024

Choose a reason for hiding this comment

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

I see that you are assuming that aggregate signatures can be combined. I think the conclusion is that it is not true, but we can address that later.

@ranchalp
Copy link
Contributor Author

Just rebased right now.

@ranchalp ranchalp merged commit 5b2adbf into filecoin-project:main Jan 24, 2024
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants