ceremonyclient/node/protobufs/clock.go

220 lines
5.1 KiB
Go
Raw Normal View History

2023-09-03 23:47:09 +00:00
package protobufs
import (
"encoding/binary"
"math/big"
"time"
"github.com/iden3/go-iden3-crypto/ff"
"github.com/iden3/go-iden3-crypto/poseidon"
"github.com/pkg/errors"
"golang.org/x/crypto/sha3"
"source.quilibrium.com/quilibrium/monorepo/nekryptology/pkg/vdf"
)
func ProveMasterClockFrame(
previousFrame *ClockFrame,
difficulty uint32,
) (*ClockFrame, error) {
input := []byte{}
input = append(input, previousFrame.Filter...)
input = binary.BigEndian.AppendUint64(input, previousFrame.FrameNumber+1)
input = binary.BigEndian.AppendUint32(input, difficulty)
input = append(input, previousFrame.Output[:]...)
b := sha3.Sum256(input)
v := vdf.New(difficulty, b)
v.Execute()
o := v.GetOutput()
timestamp := time.Now().UnixMilli()
previousSelectorBytes := [516]byte{}
copy(previousSelectorBytes[:], previousFrame.Output[:516])
parent, err := poseidon.HashBytes(previousSelectorBytes[:])
if err != nil {
return nil, errors.Wrap(err, "prove clock frame")
}
frame := &ClockFrame{
Filter: previousFrame.Filter,
FrameNumber: previousFrame.FrameNumber + 1,
Timestamp: timestamp,
Difficulty: difficulty,
ParentSelector: parent.Bytes(),
Input: previousFrame.Output,
AggregateProofs: []*InclusionAggregateProof{},
Output: o[:],
}
return frame, nil
}
func (frame *ClockFrame) VerifyMasterClockFrame() error {
input := []byte{}
input = append(input, frame.Filter...)
input = binary.BigEndian.AppendUint64(input, frame.FrameNumber)
input = binary.BigEndian.AppendUint32(input, frame.Difficulty)
input = append(input, frame.Input...)
if len(frame.Input) < 516 {
return errors.Wrap(
errors.New("invalid input"),
"verify clock frame",
)
}
if len(frame.AggregateProofs) > 0 {
return errors.Wrap(
errors.New("invalid input"),
"verify clock frame",
)
}
if frame.PublicKeySignature != nil {
return errors.Wrap(
errors.New("invalid input"),
"verify clock frame",
)
}
if len(frame.Input) != 516 {
return errors.Wrap(
errors.New("invalid input"),
"verify clock frame",
)
}
b := sha3.Sum256(input)
v := vdf.New(frame.Difficulty, b)
proof := [516]byte{}
copy(proof[:], frame.Output)
if !v.Verify(proof) {
return errors.Wrap(
errors.New("invalid proof"),
"verify clock frame",
)
}
previousSelectorBytes := [516]byte{}
copy(previousSelectorBytes[:], frame.Input[:516])
parent, err := poseidon.HashBytes(previousSelectorBytes[:])
if err != nil {
return errors.Wrap(err, "verify clock frame")
}
selector := new(big.Int).SetBytes(frame.ParentSelector)
if parent.Cmp(selector) != 0 {
return errors.Wrap(
errors.New("selector did not match input"),
"verify clock frame",
)
}
return nil
}
func (frame *ClockFrame) GetParentSelectorAndDistance() (
*big.Int,
*big.Int,
*big.Int,
error,
) {
outputBytes := [516]byte{}
copy(outputBytes[:], frame.Output[:516])
selector, err := poseidon.HashBytes(outputBytes[:])
if err != nil {
return nil, nil, nil, errors.Wrap(err, "get parent selector and distance")
}
if frame.FrameNumber == 0 {
return big.NewInt(0), big.NewInt(0), selector, nil
}
parentSelector := new(big.Int).SetBytes(frame.ParentSelector)
pubkey := []byte{}
ed448PublicKey := frame.GetPublicKeySignatureEd448()
if ed448PublicKey != nil {
pubkey = ed448PublicKey.PublicKey.KeyValue
} else {
return nil, nil, nil, errors.Wrap(
errors.New("no valid signature provided"),
"get parent selector and distance",
)
}
discriminator, err := poseidon.HashBytes(pubkey)
if err != nil {
return nil, nil, nil, errors.Wrap(err, "get parent selector and distance")
}
l := new(big.Int).Mod(new(big.Int).Sub(selector, discriminator), ff.Modulus())
r := new(big.Int).Mod(new(big.Int).Sub(discriminator, selector), ff.Modulus())
distance := r
if l.Cmp(r) == -1 {
distance = l
}
return parentSelector, distance, selector, nil
}
func (frame *ClockFrame) GetSelector() (*big.Int, error) {
outputBytes := [516]byte{}
copy(outputBytes[:], frame.Output[:516])
selector, err := poseidon.HashBytes(outputBytes[:])
if err != nil {
return nil, errors.Wrap(err, "get selector")
}
return selector, nil
}
func (frame *ClockFrame) GetPublicKey() ([]byte, error) {
if frame.FrameNumber == 0 {
return make([]byte, 32), nil
}
pubkey := []byte{}
ed448PublicKey := frame.GetPublicKeySignatureEd448()
if ed448PublicKey != nil {
pubkey = ed448PublicKey.PublicKey.KeyValue
} else {
return nil, errors.Wrap(
errors.New("no valid signature provided"),
"get address",
)
}
return pubkey, nil
}
func (frame *ClockFrame) GetAddress() ([]byte, error) {
if frame.FrameNumber == 0 {
return make([]byte, 32), nil
}
pubkey := []byte{}
ed448PublicKey := frame.GetPublicKeySignatureEd448()
if ed448PublicKey != nil {
pubkey = ed448PublicKey.PublicKey.KeyValue
} else {
return nil, errors.Wrap(
errors.New("no valid signature provided"),
"get address",
)
}
address, err := poseidon.HashBytes(pubkey)
if err != nil {
return nil, errors.Wrap(err, "get parent selector and distance")
}
addressBytes := address.Bytes()
addressBytes = append(make([]byte, 32-len(addressBytes)), addressBytes...)
return addressBytes, nil
}