-
Notifications
You must be signed in to change notification settings - Fork 170
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
Signature Aggregation #210
Conversation
…n Sign and Aggregate. Added BLS12-381 parameters.
@bvohaska what sort of review are you looking for right now? |
@whyrusleeping: I’m looking for any feedback to make sure this spec is heading in the right direction. No deep review needed yet. Should have most or all of this spec ready for deep review by 28 March. Sent with GitHawk |
…edMessage. Added exposition for Aggregates.
…nged Signature interface methods. Removed redundant references to Address since address is contained in SignedMessage. Reworked the references section. REmoved libsecp256k1 wire format b/c it is too complicated; added a reference to the authoritative code. :-(
@whyrusleeping added a very rough description for BLS public key recovery based on this. Please update with corrections. This update should represent the last update for signature.md. All reviewers should feel free to commence a deep review on that file. |
…nature must implement the Signature interface.
signatures.md
Outdated
// | ||
Verify(m Messgage, pk PublicKey, sig SignatureBytes) (valid bool, err error) | ||
VerifyAggregate(smsgs SignedMessgage, pks []PublicKeys) (valid bool, err 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.
are there multiple signed messages here? also does the signature get passed in? or how does this work?
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.
Updating name "smgs" --> "smsg" to reduce confusion. Any SignedMessage
containing a signature aggregate will contain the signature aggregate as well as all messages contained therein. So we only need the one SignedMessage
as input.
Setting aside golang syntax, suppose there is X = SignedMessage
. To verify a signature aggregate, VerifyAggregate will perform something like:
- For all messages
m_i
inX.Msgs
,h_i = hash2curve(m_i)
- Compute
S = deserialize(X.SignatureBytes)
- Compute
T = e(h_1, pk_i)*...*e(h_n, pk_n)
- If
T = e(S, P2)
=> valid
signatures.md
Outdated
|
||
Currently, Filecoin uses secp256k1 signatures to fulfill the above interface. All signatures on messages, blocks, and tickets currently use the same scheme and format. | ||
```go | ||
Type SignedMessage 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.
where does this type actually get used? This is not the signed message that gets sent over the network for message propogation, its something else, right?
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 should be only one SignedMessage
--> https://github.com/filecoin-project/go-filecoin/blob/master/types/signed_message.go#L22-L28
If there are more than one, then we should do some disambiguation.
good detail on the base cryptographic primitives (are there RFCs for some of that? seems like stuff that should go in the standard) A bit more still needed before completion:
probably more questions, but once the above is done, let's get dev to review. A sign-off from them is what we're after. |
… 'smgs'--> 'smsg', commented out the Sign method for the Signature interface as it will need to be a method on a privateKey
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.
Overall nice shape 👍
I haven't found any documentation about how hashing is done, and what exactly is hashed in terms of bytes. Maybe this is supposed to be defined somewhere else, but needs to be there eventually
- Avg. processing power available to a CPU | ||
- Affects ability to verify signature aggregates | ||
- Each signature or collection of signatures should be validated with no impact to the consumption of the chain | ||
- `Gas` cost - `Gas(ECDSA) > Gas(BLS)` |
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 clarify which operations are more costly than others, eg Gas(ECDSA_Sign)
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 have this information. Ping @whyrusleeping : can you answer 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.
This is really thorough, nice work!
I have a couple questions about the assumptions we are making wrt addresses using protocol 0.
signatures.md
Outdated
Input: Address | ||
Output: "BLS", "ECDSA", or "INVALID" | ||
|
||
1. If Address.protocol = 0 output "BLS" and stop |
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 believe this could be ECDSA, BLS or INVALID. Protocol 0 indicates the address represents an ID and ID's are issued to for all actors. Some discussion was had here about creating a mapping from ID to PublicKey, I think we will want to consider this 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.
I see you have covered this case here: #123 (comment)
Does Address.protocol specify 0? If so, fetch actor with ID = Address.payload, return BLS or ECDSA. <--this method needs to be specified in actors.md and should distinguish between BLS and ECDSA signatures.
signatures.md
Outdated
Output: "Aggregate" or "INVALID" | ||
|
||
1. If SignedMessage.Address[i].protocol != {0 OR 3} for all i output "INVALID" and stop | ||
2. If len(SignedMessage.Msgs) > 1 output "Aggregate" else output "INVALID" |
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.
Would the case len(SignedMessage.Msgs) == 1
indicate the the SignedMessage
contains a ECDSA signature?
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 the case of no addresses and one message? Is an aggregate of one explicitly invalid? While that's what the pseudocode implied, explicit clarification would help.
What about the case of multiple addresses and multiple messages? I'm guessing this means an aggregate (but should it check the lengths are equal)? An enumeration of all possible cases of {1, many}-messages ⨯ {0, many}-addresses would help (perhaps in the prose above).
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.
@frrist: yes. ECDSA signatures can't be aggregated in this scheme so if we encounter them we should error. Maybe "INVALID" is not the right wording. We should probably specify input validation. Alex alludes to this below.
@anorth: Good point. Request someone from go-filecoin to work on this (input validation).
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.
Added note about ECDSA not being aggregatable in the "Aggregating Signed Messages" section
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 love us to work on input validation, but we need you to specify what inputs should be valid. Please enumerate all combinations that are semantically valid and explicitly state that other combinations are meaningless.
signatures.md
Outdated
} | ||
``` | ||
|
||
### Signed Message | ||
|
||
This is the container for a signature that combines a message with an address and signature. |
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'm confused by the plurality of addresses and messages in the structure given this description.
I understand the use case for multiple addresses, but what is the case for multiple different messages? This seems like redundant data in the case of multiple signers of an identical message.
A brief outline of use cases and capabilities at the top of this doc would help greatly if my understanding of the motivations and context is lacking.
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'm note sure I quite understand but I've reworked the description. Agree it is very confusing. Will push. Let me know if that answers your 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.
I still don't understand why there are multiple messages in the container. The comment uses the singular "a message and an address" which disagrees with the code directly below. Please clarify the intended role of a SignedMessage
. E.g. you could write:
A container for one or multiple messages and an aggregation of the signatures of those messages by corresponding addresses. In the case of a single message and address, the signature is a vanilla signature, not an aggregate. In the case of multiple messages, the signature is assumed to be an aggregate. See *Determining signature type* below for more detail.
But I don't know whether that is in fact correct or complete.
|
||
} | ||
If there is more then one message in `SignedMessage.Msgs` then the `SignedMessage` is assumed to be a signature aggregate. If `Address` is empty then `Verify` will assume the `SignedMessage` is a signature aggregate. The procedure below uses `len()` to indicate a function that returns the number of elements in an array. | ||
|
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.
As a practical matter, I recommend an explicit representation of the "type" of signed message rather than assuming from the number of messages and/or addresses. An explicit byte identifying the semantics will simplify future changes and make code easier to understand and more likely to be correct.
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.
@whyrusleeping: ^ . It would make things easier to understand but would cost a bit or two on-chain. What do you think?
signatures.md
Outdated
Output: "Aggregate" or "INVALID" | ||
|
||
1. If SignedMessage.Address[i].protocol != {0 OR 3} for all i output "INVALID" and stop | ||
2. If len(SignedMessage.Msgs) > 1 output "Aggregate" else output "INVALID" |
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 the case of no addresses and one message? Is an aggregate of one explicitly invalid? While that's what the pseudocode implied, explicit clarification would help.
What about the case of multiple addresses and multiple messages? I'm guessing this means an aggregate (but should it check the lengths are equal)? An enumeration of all possible cases of {1, many}-messages ⨯ {0, many}-addresses would help (perhaps in the prose above).
…hods for signature interface. Added note indicating ECDSA signatures are not aggregatable.
@@ -107,7 +107,7 @@ Chain selection is a crucial component of how the Filecoin blockchain works. Eve | |||
|
|||
### Block Validation | |||
|
|||
The block structure and serialization is detailed in [the datastructures spec](data-structures.md#block). Check there for details on fields and types. | |||
The block structure and serialization is detailed in [the datastructures spec](data-structures.md#block). Check there for details on fields and types. All references to `VaidateSignature` must implement the `Signature` interface found [here](https://github.com/filecoin-project/specs/blob/master/signatures.md). |
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 addition is confusing. Why not just say that signature validation is covered in detail in the signature spec?
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 good point. I've been mulling over how to best represent that ValidateSignature
must use the verification method in signatures.md. The current phrasing is confusing b/c it should read: "Block
implements the Signature
interface" and ValidateSignature
--> Block.Verify(SignedMessage_Block, PublicKey)
. in this case, the internal block messages would be represented as a single value (hashed), SignatureBytes
would be the actual signature of the message and Address
would be the address of the block proposer.
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 also need a place that implements verification of the aggregated signatures, e.g. a method like VerfiyAggregates([]Message, SignatureBytes) bool
for use inside the block validation.
@anorth, @whyrusleeping: This PR is suffering a bit of scope creep. Let's close it out and push to master. I'd like to ship this so we can move a bit faster. We can create a new PR for other concerns captured in this PR. I believe most of the concerns are captured in this GH issue. |
@bvohaska I don't think its scope creeping. The scope of signature aggregation should be every change needed to the protocol to support it. I don't want to merge a partial spec change which would leave the spec in a weird place 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.
I have unresolved two questions about the specific semantics of the SignedMessage
structure.
I would also like an explicit call, perhaps from @whyrusleeping, on an explicit type identifier to distinguish possible interpretations. If that call is "no", then the exhaustive enumeration of valid and invalid combinations is important to understanding the avenues open for change in the future.
Beyond that, this LGTM, but I expect my approval isn't sufficient to merge.
signatures.md
Outdated
} | ||
``` | ||
|
||
### Signed Message | ||
|
||
This is the container for a signature that combines a message with an address and signature. |
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 still don't understand why there are multiple messages in the container. The comment uses the singular "a message and an address" which disagrees with the code directly below. Please clarify the intended role of a SignedMessage
. E.g. you could write:
A container for one or multiple messages and an aggregation of the signatures of those messages by corresponding addresses. In the case of a single message and address, the signature is a vanilla signature, not an aggregate. In the case of multiple messages, the signature is assumed to be an aggregate. See *Determining signature type* below for more detail.
But I don't know whether that is in fact correct or complete.
signatures.md
Outdated
Output: "Aggregate" or "INVALID" | ||
|
||
1. If SignedMessage.Address[i].protocol != {0 OR 3} for all i output "INVALID" and stop | ||
2. If len(SignedMessage.Msgs) > 1 output "Aggregate" else output "INVALID" |
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 love us to work on input validation, but we need you to specify what inputs should be valid. Please enumerate all combinations that are semantically valid and explicitly state that other combinations are meaningless.
suggestion: have a set of diagrams describing the constituent elements as well as the process flow with concise, precise definitions |
…ge to better comply with current understanding. Moved SignedMessage to data-structures.md; updated Ticket definition to comply with SignedMessage.
…ts in the PR and sync meetings
Moved content of this comment to the tracking issue here |
GasPrice Integer | ||
GasLimit Integer | ||
|
||
GasPrice Integer |
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.
@whyrusleeping, @dignifiedquire: is there a canonical description for Integer
? In other words, what exactly do we mean by integer here? Is this a 32 byte binary quantity? Perhaps it's a bigInt in form LEB128?
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.
Do we know the size of these Integers?
type Ticket struct { | ||
|
||
// The VDF Result is derived from the prior ticket in the ticket chain | ||
VDFResult BigInteger |
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.
@sternhenri, @ZenGround0: Do we have a language-independent description of BigInteger here? What is the binary representation? Maybe we could point to a spec that defines this for us.
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 is what LEB128 is for
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.
Do we have a size for these bigInts?
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.
They are variably length sized, to support arbitrary numbers. But if you have a max range you want to represent then I can tell you the size.
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.
Understood. Someone will have to update the spec comments to expound on this. As for the typing, we are using inconsistent type nomenclature for big integers. It would be nice to go through and standardize these. So far I've seen Integer
, BigInteger
, BigInt
; they no doubt mean the same thing --> LEB128 encoded integers of arbitrary size but we should specifically call that out here.
If the spec owners acknowledge that this is what they mean when they write an element from the list above, I'll go ahead and change it. Don't want to misinterpret the authors intent.
|
||
// MessageReceipts is a set of receipts matching to the sending of the `Messages`. | ||
// TODO: should be the same type of merkletree-list thing that the messages are | ||
// TODO: should be the same type of merkletree-list thing that the messages are | ||
MessageReceipts []MessageReceipt |
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.
@whyrusleeping: what are MessageReceipts
?
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.
They are defined below and store the result of applying the message
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 see the struct
definition. Do we have any exposition as to why we need them? Given that they are an on-chain quantity, I would claim that it's important to declare exactly why we have them. This would be the best place to put that explanation.
|
||
// ElectionProof is a signature over the final ticket that proves this miner | ||
// is the leader at this round | ||
ElectionProof SignatureBytes |
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.
Is it defined somewhere what kind of signature this is cc @sternhenri
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 took a guess at this. Previously, it read Signature
. Will need @sternhenri to verify this is a BLS signature.
## Block | ||
|
||
A block represents an individual point in time that the network may achieve consensus on. It contains (via merkle links) the full state of the system, references to the previous state, and some notion of a 'weight' for deciding which block is the 'best'. | ||
|
||
```go | ||
// Block is a block in the blockchain. | ||
type Block struct { | ||
|
||
// Miner is the address of the miner actor that mined this block. | ||
Miner Address | ||
|
||
// Tickets are the winning ticket that were submitted with this block. | ||
Tickets []Ticket |
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.
Could we aggregate the signatures on the tickets as well?
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 the EC spec can be updated to support it, I don't see why not. We'll need to make sure that the EC spec is using SignedMessages
and the Signature
interface.
^ thoughts @sternhenri?
|
||
// BLSMessages is the set of messages with associated BLS signatures contained | ||
// in BLSSignatureAggregate. | ||
BLSMessages []Message |
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 general I like this structure, but we are now unable to present an ordering of messages in the form of
- bls message
- ecdsa message
- bls message
In regards to execution order.
I would argue this is fine, and miners are simply asked to process these not together, but first one kind, then the other kind. But this is an explicit design decision that might have other implications.
@whyrusleeping: from mining.md (https://github.com/filecoin-project/specs/blob/master/mining.md#block-validation), it doesn't look like on-chain message signatures are validated during block validation. Maybe I'm missing something? |
outdated |
Initial changes to Signature spec