Skip to content

Commit

Permalink
Ensure signing and verifying modifies no input
Browse files Browse the repository at this point in the history
  • Loading branch information
ranchalp committed Jan 19, 2024
1 parent 5da2ee3 commit 6ee56ae
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 152 deletions.
12 changes: 6 additions & 6 deletions f3/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,23 +47,23 @@ type Clock interface {
type Signer interface {
// Signs a message for the given sender ID.
Sign(sender ActorID, msg []byte) []byte
// Verifies a signature for the given sender ID.
Verify(sender ActorID, msg, sig []byte) bool
}

type Aggregator interface {
type Verifier interface {
// Verifies a signature for the given sender ID.
Verify(pubKey PubKey, msg, sig []byte) bool
// Aggregates signatures from a participant to an existing signature.
Aggregate(sig []byte, aggSignature []byte) []byte
Aggregate(sig [][]byte, aggSignature []byte) []byte
// VerifyAggregate verifies an aggregate signature.
VerifyAggregate(payload, aggSig []byte, signers [][]byte) bool
VerifyAggregate(payload, aggSig []byte, signers []PubKey) bool
}

// Participant interface to the host system resources.
type Host interface {
Network
Clock
Signer
Aggregator
Verifier

// Logs a message at the "logic" level
Log(format string, args ...interface{})
Expand Down
12 changes: 9 additions & 3 deletions f3/granite.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ func (i *instance) receiveOne(msg *GMessage) error {
if i.phase == TERMINATED {
return nil // No-op
}
round := i.roundState(msg.Round)

// Drop any messages that can never be valid.
if !i.isValid(msg) {
Expand All @@ -234,7 +235,6 @@ func (i *instance) receiveOne(msg *GMessage) error {
return nil
}

round := i.roundState(msg.Round)
switch msg.Step {
case QUALITY:
// Receive each prefix of the proposal independently.
Expand All @@ -259,6 +259,7 @@ func (i *instance) receiveOne(msg *GMessage) error {
// Try to complete the current phase.
// Every COMMIT phase stays open to new messages even after the protocol moves on to
// a new round. Late-arriving COMMITS can still (must) cause a local decision, *in that round*.

if msg.Step == COMMIT && i.phase != DECIDE {
return i.tryCommit(msg.Round)
}
Expand Down Expand Up @@ -293,16 +294,20 @@ func (i *instance) isValid(msg *GMessage) bool {
i.log("sender with zero power or not in power table")
return false
}

_, pubKey := i.powerTable.Get(msg.Sender)

if !(msg.Value.IsZero() || msg.Value.HasBase(i.input.Base())) {
i.log("unexpected base %s", &msg.Value)
return false
}
if msg.Step == QUALITY {
return msg.Round == 0 && !msg.Value.IsZero()
} else if msg.Step == CONVERGE {

if msg.Round == 0 ||
msg.Value.IsZero() ||
!i.vrf.VerifyTicket(i.beacon, i.instanceID, msg.Round, msg.Sender, msg.Ticket) {
!i.vrf.VerifyTicket(i.beacon, i.instanceID, msg.Round, pubKey, msg.Ticket) {
return false
}
} else if msg.Step == DECIDE {
Expand All @@ -311,7 +316,7 @@ func (i *instance) isValid(msg *GMessage) bool {
}

sigPayload := SignaturePayload(msg.Instance, msg.Round, msg.Step, msg.Value)
if !i.host.Verify(msg.Sender, sigPayload, msg.Signature) {
if !i.host.Verify(pubKey, sigPayload, msg.Signature) {
i.log("invalid signature on %v", msg)
return false
}
Expand Down Expand Up @@ -462,6 +467,7 @@ func (i *instance) tryCommit(round uint32) error {
}

}

i.beginNextRound()
}

Expand Down
2 changes: 1 addition & 1 deletion f3/powertable.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
type PowerEntry struct {
ID ActorID
Power *StoragePower
PubKey []byte
PubKey PubKey
}

// PowerTable maps ActorID to a unique index in the range [0, len(powerTable.Entries)).
Expand Down
2 changes: 2 additions & 0 deletions f3/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ type ActorID uint64

type StoragePower = big.Int

type PubKey []byte

// Creates a new StoragePower struct with a specific value and returns the result
func NewStoragePower(value int64) *StoragePower {
return new(big.Int).SetInt64(value)
Expand Down
14 changes: 8 additions & 6 deletions f3/vrf.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,26 +20,28 @@ type VRFTicketSource interface {
}

type VRFTicketVerifier interface {
VerifyTicket(beacon []byte, instance uint32, round uint32, signer ActorID, ticket Ticket) bool
VerifyTicket(beacon []byte, instance uint32, round uint32, signer PubKey, ticket Ticket) bool
}

// VRF used for the CONVERGE step of GossiPBFT.
type VRF struct {
signer Signer
signer Signer
verifier Verifier
}

func NewVRF(signer Signer) *VRF {
func NewVRF(signer Signer, verifier Verifier) *VRF {
return &VRF{
signer: signer,
signer: signer,
verifier: verifier,
}
}

func (f *VRF) MakeTicket(beacon []byte, instance uint32, round uint32, signer ActorID) Ticket {
return f.signer.Sign(signer, f.serializeSigInput(beacon, instance, round))
}

func (f *VRF) VerifyTicket(beacon []byte, instance uint32, round uint32, signer ActorID, ticket Ticket) bool {
return f.signer.Verify(signer, f.serializeSigInput(beacon, instance, round), ticket)
func (f *VRF) VerifyTicket(beacon []byte, instance uint32, round uint32, signer PubKey, ticket Ticket) bool {
return f.verifier.Verify(signer, f.serializeSigInput(beacon, instance, round), ticket)
}

// Serializes the input to the VRF signature for the CONVERGE step of GossiPBFT.
Expand Down
Loading

0 comments on commit 6ee56ae

Please sign in to comment.