mirror of
https://source.quilibrium.com/quilibrium/ceremonyclient.git
synced 2024-12-27 09:05:18 +00:00
220 lines
5.1 KiB
Go
220 lines
5.1 KiB
Go
|
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
|
||
|
}
|