SecureValueRecovery2/host/peer/sequence_number.go
2026-04-08 15:51:52 -07:00

75 lines
1.8 KiB
Go

// Copyright 2023 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
package peer
import (
"errors"
"fmt"
pb "github.com/signalapp/svr2/proto"
)
type sequenceNumber struct {
epoch uint32
seq uint64
}
// follows returns true if this seqeunce number directly follows the provided sequence number.
// This is the case if either it's the next in the sequence, or it is from a greater epoch.
func (s sequenceNumber) follows(pred sequenceNumber) bool {
return (s.epoch > pred.epoch && s.seq == 0) || (s.epoch == pred.epoch && s.seq == pred.seq+1)
}
// next returns the sequenceNumber of the next message within an enclave peer session
func (s sequenceNumber) next() sequenceNumber {
return sequenceNumber{
epoch: s.epoch,
seq: s.seq + 1,
}
}
// nextEpoch returns the sequenceNumber of the next epoch, typically denoting the start of a new
// enclave peer session
func (s sequenceNumber) nextEpoch() sequenceNumber {
return sequenceNumber{
epoch: s.epoch + 1,
seq: 0,
}
}
// cmp compares two sequence numbers
//
// returns:
//
// < 0 if this is less than the provided sequenceNumber
// == 0 if this is equal to the provided sequenceNumber
// > 0 if this is greater than the provided sequenceNumber
func (s sequenceNumber) cmp(o sequenceNumber) int {
if ecmp := int(int32(s.epoch - o.epoch)); ecmp != 0 {
return ecmp
}
return int(s.seq - o.seq)
}
func (s sequenceNumber) proto() *pb.SequenceNumber {
return &pb.SequenceNumber{
Epoch: s.epoch,
Seq: s.seq,
}
}
func makeSeqno(p *pb.SequenceNumber) (sequenceNumber, error) {
if p == nil {
return sequenceNumber{}, errors.New("expected a sequence number present on message")
}
return sequenceNumber{
epoch: p.Epoch,
seq: p.Seq,
}, nil
}
func (s sequenceNumber) String() string {
return fmt.Sprintf("%v:%v", s.epoch, s.seq)
}