dc4bc/dkg/types.go

171 lines
4.2 KiB
Go

package dkg
import (
"bytes"
"encoding/gob"
"encoding/json"
"fmt"
"go.dedis.ch/kyber/v3"
"go.dedis.ch/kyber/v3/pairing/bn256"
"go.dedis.ch/kyber/v3/share"
)
type PK2Participant struct {
ParticipantID int
Participant string
PK kyber.Point
}
type PKStore []*PK2Participant
func (s *PKStore) Add(newPk *PK2Participant) bool {
for _, pk := range *s {
if pk.Participant == newPk.Participant && pk.PK.Equal(newPk.PK) {
return false
}
}
*s = append(*s, newPk)
return true
}
func (s PKStore) Len() int { return len(s) }
func (s PKStore) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s PKStore) Less(i, j int) bool { return s[i].ParticipantID < s[j].ParticipantID }
func (s PKStore) GetPKs() []kyber.Point {
var out = make([]kyber.Point, len(s))
for idx, val := range s {
out[idx] = val.PK
}
return out
}
func (s PKStore) GetPKByParticipant(p string) (kyber.Point, error) {
for _, val := range s {
if val.Participant == p {
return val.PK, nil
}
}
return nil, fmt.Errorf("participant %s does not exist", p)
}
func (s PKStore) GetPKByIndex(index int) kyber.Point {
if index < 0 || index > len(s) {
return nil
}
return s[index].PK
}
func (s PKStore) GetParticipantByIndex(index int) string {
if index < 0 || index > len(s) {
return ""
}
return s[index].Participant
}
type messageStore struct {
// Common number of messages of the same type from peers
messagesCount int
// Max number of messages of the same type from one peer per round
maxMessagesFromPeer int
// Map which stores messages. Key is a peer's address, value is data
addrToData map[string][]interface{}
// Map which stores messages (same as addrToData). Key is a peer's index, value is data.
indexToData map[int][]interface{}
}
func newMessageStore(n int) *messageStore {
return &messageStore{
maxMessagesFromPeer: n,
addrToData: make(map[string][]interface{}),
indexToData: make(map[int][]interface{}),
}
}
func (ms *messageStore) add(addr string, index int, val interface{}) {
data := ms.addrToData[addr]
if len(data) == ms.maxMessagesFromPeer {
return
}
data = append(data, val)
ms.addrToData[addr] = data
data = ms.indexToData[index]
data = append(data, val)
ms.indexToData[index] = data
ms.messagesCount++
}
type BLSKeyring struct {
PubPoly *share.PubPoly
Share *share.PriShare
}
type blsKeyringJSON struct {
Commitments [][]byte `json:"commitments"`
Share []byte `json:"share"`
}
func (b *BLSKeyring) Bytes() ([]byte, error) {
var shareBuf bytes.Buffer
shareEnc := gob.NewEncoder(&shareBuf)
if err := shareEnc.Encode(b.Share); err != nil {
return nil, fmt.Errorf("failed to encode private key: %v", err)
}
_, commitments := b.PubPoly.Info()
commitmentsBz := make([][]byte, 0, len(commitments))
for _, commitment := range commitments {
data, err := commitment.MarshalBinary()
if err != nil {
return nil, fmt.Errorf("failed to marshal commitment: %w", err)
}
commitmentsBz = append(commitmentsBz, data)
}
var buf bytes.Buffer
enc := gob.NewEncoder(&buf)
if err := enc.Encode(commitmentsBz); err != nil {
return nil, fmt.Errorf("failed to encode commitmentBz: %w", err)
}
blsKeyringJSON := blsKeyringJSON{
Commitments: commitmentsBz,
Share: shareBuf.Bytes(),
}
return json.Marshal(blsKeyringJSON)
}
func LoadBLSKeyringFromBytes(data []byte) (*BLSKeyring, error) {
var (
err error
blsKeyringJson blsKeyringJSON
)
if err = json.Unmarshal(data, &blsKeyringJson); err != nil {
return nil, fmt.Errorf("failed to unmarshal blsKeyringJson: %w", err)
}
commitments := make([]kyber.Point, 0, len(blsKeyringJson.Commitments))
for _, commitmentBz := range blsKeyringJson.Commitments {
commitment := bn256.NewSuiteG2().Point()
if err := commitment.UnmarshalBinary(commitmentBz); err != nil {
return nil, fmt.Errorf("failed to unmarshal commitment: %w", err)
}
commitments = append(commitments, commitment)
}
priShare, privDec := &share.PriShare{V: bn256.NewSuite().G1().Scalar()}, gob.NewDecoder(bytes.NewBuffer(blsKeyringJson.Share))
if err := privDec.Decode(priShare); err != nil {
return nil, fmt.Errorf("failed to share: %v", err)
}
return &BLSKeyring{
PubPoly: share.NewPubPoly(bn256.NewSuiteG2(), nil, commitments),
Share: priShare,
}, nil
}