mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2025-01-09 03:01:19 +00:00
798bbbdc82
* coldstart flags for validator * WIP beacon node flags * wip beacon chain, flag fix in validator, arg fix in validator * checkpoint * Added interop service * working on mock chainstart * save the state lol * fix tests * Save genesis validators * gaz * fix validator help flags * WaitForChainStart actually waits for genesis time * cold start fixes * cache * change back * allow for genesis state too * remove logs * increase mmap size * dont process if head doesn't exist * add 10ms tolerance * enable libp2p debug at debug, fix pubsub * works with checkpt * initialize justified and finalized in db * Removed preloadStatePath from blockchain service * Clean up * Write to disk for now post state * revert b466dd536f8eadbdae2264a545a755370223d917 * Builds * Only RPC test fails now * use minimal config, no demo config * clean up branch * Lint * resolve lint * more lint fixes * lint * fix viz * Fixing RPC test * skip before epoch 2 * RPC time out * Fixed ordering * rename * remove some dbg statements * ensure index is correct * fix some panics * getting closer * fix tests * Fix private key * Fixed RPC test * Fixed beacon chain build for docker * Add interop.go to validator go_image * Fixed docker build * handle errors * skip test, skip disconnecting peers * Fixed docker build * tolerance for attestation processing * revert copy * clearer err message parse * fix launching from dep contract
177 lines
5.6 KiB
Go
177 lines
5.6 KiB
Go
// Package bls implements a go-wrapper around a library implementing the
|
|
// the BLS12-381 curve and signature scheme. This package exposes a public API for
|
|
// verifying and aggregating BLS signatures used by Ethereum 2.0.
|
|
package bls
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"io"
|
|
|
|
g1 "github.com/phoreproject/bls/g1pubs"
|
|
"github.com/pkg/errors"
|
|
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
|
)
|
|
|
|
// CurveOrder for the BLS12-381 curve.
|
|
const CurveOrder = "52435875175126190479447740508185965837690552500527637822603658699938581184513"
|
|
|
|
// Signature used in the BLS signature scheme.
|
|
type Signature struct {
|
|
val *g1.Signature
|
|
}
|
|
|
|
// SecretKey used in the BLS signature scheme.
|
|
type SecretKey struct {
|
|
val *g1.SecretKey
|
|
}
|
|
|
|
// PublicKey used in the BLS signature scheme.
|
|
type PublicKey struct {
|
|
val *g1.PublicKey
|
|
}
|
|
|
|
// RandKey creates a new private key using a random method provided as an io.Reader.
|
|
func RandKey(r io.Reader) (*SecretKey, error) {
|
|
k, err := g1.RandKey(r)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not initialize secret key")
|
|
}
|
|
return &SecretKey{val: k}, nil
|
|
}
|
|
|
|
// SecretKeyFromBytes creates a BLS private key from a byte slice.
|
|
func SecretKeyFromBytes(priv []byte) (*SecretKey, error) {
|
|
k := bytesutil.ToBytes32(priv)
|
|
val := g1.DeserializeSecretKey(k)
|
|
if val.GetFRElement() == nil {
|
|
return nil, errors.New("invalid private key")
|
|
}
|
|
return &SecretKey{val}, nil
|
|
}
|
|
|
|
// PublicKeyFromBytes creates a BLS public key from a byte slice.
|
|
func PublicKeyFromBytes(pub []byte) (*PublicKey, error) {
|
|
b := bytesutil.ToBytes48(pub)
|
|
k, err := g1.DeserializePublicKey(b)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not unmarshal bytes into public key")
|
|
}
|
|
return &PublicKey{val: k}, nil
|
|
}
|
|
|
|
// SignatureFromBytes creates a BLS signature from a byte slice.
|
|
func SignatureFromBytes(sig []byte) (*Signature, error) {
|
|
b := bytesutil.ToBytes96(sig)
|
|
s, err := g1.DeserializeSignature(b)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not unmarshal bytes into signature")
|
|
}
|
|
return &Signature{val: s}, nil
|
|
}
|
|
|
|
// PublicKey obtains the public key corresponding to the BLS secret key.
|
|
func (s *SecretKey) PublicKey() *PublicKey {
|
|
return &PublicKey{val: g1.PrivToPub(s.val)}
|
|
}
|
|
|
|
// Sign a message using a secret key - in a beacon/validator client,
|
|
func (s *SecretKey) Sign(msg []byte, domain uint64) *Signature {
|
|
b := make([]byte, 8)
|
|
binary.LittleEndian.PutUint64(b, domain)
|
|
sig := g1.SignWithDomain(bytesutil.ToBytes32(msg), s.val, bytesutil.ToBytes8(b))
|
|
return &Signature{val: sig}
|
|
}
|
|
|
|
// Marshal a secret key into a byte slice.
|
|
func (s *SecretKey) Marshal() []byte {
|
|
k := s.val.Serialize()
|
|
return k[:]
|
|
}
|
|
|
|
// Marshal a public key into a byte slice.
|
|
func (p *PublicKey) Marshal() []byte {
|
|
k := p.val.Serialize()
|
|
return k[:]
|
|
}
|
|
|
|
// Aggregate two public keys.
|
|
func (p *PublicKey) Aggregate(p2 *PublicKey) *PublicKey {
|
|
p1 := p.val
|
|
p1.Aggregate(p2.val)
|
|
return &PublicKey{val: p1}
|
|
}
|
|
|
|
// Verify a bls signature given a public key, a message, and a domain.
|
|
func (s *Signature) Verify(msg []byte, pub *PublicKey, domain uint64) bool {
|
|
b := make([]byte, 8)
|
|
binary.LittleEndian.PutUint64(b, domain)
|
|
return g1.VerifyWithDomain(bytesutil.ToBytes32(msg), pub.val, s.val, bytesutil.ToBytes8(b))
|
|
}
|
|
|
|
// VerifyAggregate verifies each public key against its respective message.
|
|
// This is vulnerable to rogue public-key attack. Each user must
|
|
// provide a proof-of-knowledge of the public key.
|
|
func (s *Signature) VerifyAggregate(pubKeys []*PublicKey, msg [][32]byte, domain uint64) bool {
|
|
if len(pubKeys) == 0 {
|
|
return false // Otherwise panic in VerifyAggregateCommonWithDomain.
|
|
}
|
|
var keys []*g1.PublicKey
|
|
for _, v := range pubKeys {
|
|
keys = append(keys, v.val)
|
|
}
|
|
b := make([]byte, 8)
|
|
binary.LittleEndian.PutUint64(b, domain)
|
|
return s.val.VerifyAggregateWithDomain(keys, msg, bytesutil.ToBytes8(b))
|
|
}
|
|
|
|
// VerifyAggregateCommon verifies each public key against its respective message.
|
|
// This is vulnerable to rogue public-key attack. Each user must
|
|
// provide a proof-of-knowledge of the public key.
|
|
func (s *Signature) VerifyAggregateCommon(pubKeys []*PublicKey, msg []byte, domain uint64) bool {
|
|
if len(pubKeys) == 0 {
|
|
return false // Otherwise panic in VerifyAggregateCommonWithDomain.
|
|
}
|
|
var keys []*g1.PublicKey
|
|
for _, v := range pubKeys {
|
|
keys = append(keys, v.val)
|
|
}
|
|
b := make([]byte, 8)
|
|
binary.LittleEndian.PutUint64(b, domain)
|
|
return s.val.VerifyAggregateCommonWithDomain(keys, bytesutil.ToBytes32(msg), bytesutil.ToBytes8(b))
|
|
}
|
|
|
|
// Marshal a signature into a byte slice.
|
|
func (s *Signature) Marshal() []byte {
|
|
k := s.val.Serialize()
|
|
return k[:]
|
|
}
|
|
|
|
// AggregateSignatures converts a list of signatures into a single, aggregated sig.
|
|
func AggregateSignatures(sigs []*Signature) *Signature {
|
|
var ss []*g1.Signature
|
|
for _, v := range sigs {
|
|
if v == nil {
|
|
continue
|
|
}
|
|
ss = append(ss, v.val)
|
|
}
|
|
return &Signature{val: g1.AggregateSignatures(ss)}
|
|
}
|
|
|
|
// Domain returns the bls domain given by the domain type and the operation 4 byte fork version.
|
|
//
|
|
// Spec pseudocode definition:
|
|
// def get_domain(state: BeaconState, domain_type: DomainType, message_epoch: Epoch=None) -> Domain:
|
|
// """
|
|
// Return the signature domain (fork version concatenated with domain type) of a message.
|
|
// """
|
|
// epoch = get_current_epoch(state) if message_epoch is None else message_epoch
|
|
// fork_version = state.fork.previous_version if epoch < state.fork.epoch else state.fork.current_version
|
|
// return compute_domain(domain_type, fork_version)
|
|
func Domain(domainType []byte, forkVersion []byte) uint64 {
|
|
b := []byte{}
|
|
b = append(b, domainType[:4]...)
|
|
b = append(b, forkVersion[:4]...)
|
|
return bytesutil.FromBytes8(b)
|
|
}
|