diff --git a/common/bytes.go b/common/bytes.go index 7827bb572e..c7006f49c3 100644 --- a/common/bytes.go +++ b/common/bytes.go @@ -116,6 +116,15 @@ func LeftPadBytes(slice []byte, l int) []byte { return padded } +// PadTo pads a byte slice to the given size. If the byte slice is larger than the given size, the +// original slice is returned. +func PadTo(b []byte, size int) []byte { + if len(b) >= size { + return b + } + return append(b, make([]byte, size-len(b))...) +} + // TrimLeftZeroes returns a subslice of s without leading zeroes func TrimLeftZeroes(s []byte) []byte { idx := 0 @@ -137,3 +146,15 @@ func TrimRightZeroes(s []byte) []byte { } return s[:idx] } + +// Copy2dBytes will copy and return a non-nil 2d byte slice, otherwise it returns nil. +func Copy2dBytes(ary [][]byte) [][]byte { + if ary != nil { + copied := make([][]byte, len(ary)) + for i, a := range ary { + copied[i] = CopyBytes(a) + } + return copied + } + return nil +} diff --git a/common/bytes_go120.go b/common/bytes_go120.go new file mode 100644 index 0000000000..e12b09c7c4 --- /dev/null +++ b/common/bytes_go120.go @@ -0,0 +1,48 @@ +//go:build go1.20 +// +build go1.20 + +package common + +// These methods use go1.20 syntax to convert a byte slice to a fixed size array. + +// ToBytes4 is a convenience method for converting a byte slice to a fix +// sized 4 byte array. This method will truncate the input if it is larger +// than 4 bytes. +func ToBytes4(x []byte) [4]byte { + return [4]byte(PadTo(x, 4)) +} + +// ToBytes20 is a convenience method for converting a byte slice to a fix +// sized 20 byte array. This method will truncate the input if it is larger +// than 20 bytes. +func ToBytes20(x []byte) [20]byte { + return [20]byte(PadTo(x, 20)) +} + +// ToBytes32 is a convenience method for converting a byte slice to a fix +// sized 32 byte array. This method will truncate the input if it is larger +// than 32 bytes. +func ToBytes32(x []byte) [32]byte { + return [32]byte(PadTo(x, 32)) +} + +// ToBytes48 is a convenience method for converting a byte slice to a fix +// sized 48 byte array. This method will truncate the input if it is larger +// than 48 bytes. +func ToBytes48(x []byte) [48]byte { + return [48]byte(PadTo(x, 48)) +} + +// ToBytes64 is a convenience method for converting a byte slice to a fix +// sized 64 byte array. This method will truncate the input if it is larger +// than 64 bytes. +func ToBytes64(x []byte) [64]byte { + return [64]byte(PadTo(x, 64)) +} + +// ToBytes96 is a convenience method for converting a byte slice to a fix +// sized 96 byte array. This method will truncate the input if it is larger +// than 96 bytes. +func ToBytes96(x []byte) [96]byte { + return [96]byte(PadTo(x, 96)) +} diff --git a/crypto/bls/bls.go b/crypto/bls/bls.go new file mode 100644 index 0000000000..eb266d2b7e --- /dev/null +++ b/crypto/bls/bls.go @@ -0,0 +1,75 @@ +// Package bls implements a go-wrapper around a library implementing the +// BLS12-381 curve and signature scheme. This package exposes a public API for +// verifying and aggregating BLS signatures used by Ethereum. +package bls + +import ( + "github.com/ethereum/go-ethereum/crypto/bls/blst" + "github.com/ethereum/go-ethereum/crypto/bls/common" + "github.com/ethereum/go-ethereum/crypto/bls/herumi" +) + +// Initialize herumi temporarily while we transition to blst for ethdo. +func init() { + herumi.HerumiInit() +} + +// SecretKeyFromBytes creates a BLS private key from a BigEndian byte slice. +func SecretKeyFromBytes(privKey []byte) (SecretKey, error) { + return blst.SecretKeyFromBytes(privKey) +} + +// PublicKeyFromBytes creates a BLS public key from a BigEndian byte slice. +func PublicKeyFromBytes(pubKey []byte) (PublicKey, error) { + return blst.PublicKeyFromBytes(pubKey) +} + +// SignatureFromBytes creates a BLS signature from a LittleEndian byte slice. +func SignatureFromBytes(sig []byte) (Signature, error) { + return blst.SignatureFromBytes(sig) +} + +// MultipleSignaturesFromBytes creates a slice of BLS signatures from a LittleEndian 2d-byte slice. +func MultipleSignaturesFromBytes(sigs [][]byte) ([]Signature, error) { + return blst.MultipleSignaturesFromBytes(sigs) +} + +// AggregatePublicKeys aggregates the provided raw public keys into a single key. +func AggregatePublicKeys(pubs [][]byte) (PublicKey, error) { + return blst.AggregatePublicKeys(pubs) +} + +// AggregateMultiplePubkeys aggregates the provided decompressed keys into a single key. +func AggregateMultiplePubkeys(pubs []PublicKey) PublicKey { + return blst.AggregateMultiplePubkeys(pubs) +} + +// AggregateSignatures converts a list of signatures into a single, aggregated sig. +func AggregateSignatures(sigs []common.Signature) common.Signature { + return blst.AggregateSignatures(sigs) +} + +// AggregateCompressedSignatures converts a list of compressed signatures into a single, aggregated sig. +func AggregateCompressedSignatures(multiSigs [][]byte) (common.Signature, error) { + return blst.AggregateCompressedSignatures(multiSigs) +} + +// VerifySignature verifies a single signature. For performance reason, always use VerifyMultipleSignatures if possible. +func VerifySignature(sig []byte, msg [32]byte, pubKey common.PublicKey) (bool, error) { + return blst.VerifySignature(sig, msg, pubKey) +} + +// VerifyMultipleSignatures verifies multiple signatures for distinct messages securely. +func VerifyMultipleSignatures(sigs [][]byte, msgs [][32]byte, pubKeys []common.PublicKey) (bool, error) { + return blst.VerifyMultipleSignatures(sigs, msgs, pubKeys) +} + +// NewAggregateSignature creates a blank aggregate signature. +func NewAggregateSignature() common.Signature { + return blst.NewAggregateSignature() +} + +// RandKey creates a new private key using a random input. +func RandKey() (common.SecretKey, error) { + return blst.RandKey() +} diff --git a/crypto/bls/bls_test.go b/crypto/bls/bls_test.go new file mode 100644 index 0000000000..5c07b4e65f --- /dev/null +++ b/crypto/bls/bls_test.go @@ -0,0 +1,30 @@ +package bls + +import ( + "github.com/stretchr/testify/require" + "testing" + + "github.com/ethereum/go-ethereum/crypto/bls/common" +) + +func TestDisallowZeroSecretKeys(t *testing.T) { + t.Run("blst", func(t *testing.T) { + // Blst does a zero check on the key during deserialization. + _, err := SecretKeyFromBytes(common.ZeroSecretKey[:]) + require.Equal(t, common.ErrSecretUnmarshal, err) + }) +} + +func TestDisallowZeroPublicKeys(t *testing.T) { + t.Run("blst", func(t *testing.T) { + _, err := PublicKeyFromBytes(common.InfinitePublicKey[:]) + require.Equal(t, common.ErrInfinitePubKey, err) + }) +} + +func TestDisallowZeroPublicKeys_AggregatePubkeys(t *testing.T) { + t.Run("blst", func(t *testing.T) { + _, err := AggregatePublicKeys([][]byte{common.InfinitePublicKey[:], common.InfinitePublicKey[:]}) + require.Equal(t, common.ErrInfinitePubKey, err) + }) +} diff --git a/crypto/bls/blst/aliases.go b/crypto/bls/blst/aliases.go new file mode 100644 index 0000000000..8f3028a7eb --- /dev/null +++ b/crypto/bls/blst/aliases.go @@ -0,0 +1,11 @@ +//go:build ((linux && amd64) || (linux && arm64) || (darwin && amd64) || (darwin && arm64) || (windows && amd64)) && !blst_disabled + +package blst + +import blst "github.com/supranational/blst/bindings/go" + +// Internal types for blst. +type blstPublicKey = blst.P1Affine +type blstSignature = blst.P2Affine +type blstAggregateSignature = blst.P2Aggregate +type blstAggregatePublicKey = blst.P1Aggregate diff --git a/crypto/bls/blst/bls_benchmark_test.go b/crypto/bls/blst/bls_benchmark_test.go new file mode 100644 index 0000000000..a11332882d --- /dev/null +++ b/crypto/bls/blst/bls_benchmark_test.go @@ -0,0 +1,64 @@ +//go:build ((linux && amd64) || (linux && arm64) || (darwin && amd64) || (darwin && arm64) || (windows && amd64)) && !blst_disabled + +package blst_test + +import ( + "github.com/stretchr/testify/require" + "testing" + + "github.com/ethereum/go-ethereum/crypto/bls/blst" + "github.com/ethereum/go-ethereum/crypto/bls/common" +) + +func BenchmarkSignature_Verify(b *testing.B) { + sk, err := blst.RandKey() + require.NoError(b, err) + + msg := []byte("Some msg") + sig := sk.Sign(msg) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + if !sig.Verify(sk.PublicKey(), msg) { + b.Fatal("could not verify sig") + } + } +} + +func BenchmarkSignature_AggregateVerify(b *testing.B) { + sigN := 128 // MAX_ATTESTATIONS per block. + + var pks []common.PublicKey + var sigs []common.Signature + var msgs [][32]byte + for i := 0; i < sigN; i++ { + msg := [32]byte{'s', 'i', 'g', 'n', 'e', 'd', byte(i)} + sk, err := blst.RandKey() + require.NoError(b, err) + sig := sk.Sign(msg[:]) + pks = append(pks, sk.PublicKey()) + sigs = append(sigs, sig) + msgs = append(msgs, msg) + } + aggregated := blst.AggregateSignatures(sigs) + + b.ResetTimer() + b.ReportAllocs() + for i := 0; i < b.N; i++ { + if !aggregated.AggregateVerify(pks, msgs) { + b.Fatal("could not verify aggregate sig") + } + } +} + +func BenchmarkSecretKey_Marshal(b *testing.B) { + key, err := blst.RandKey() + require.NoError(b, err) + d := key.Marshal() + + b.ResetTimer() + for i := 0; i < b.N; i++ { + _, err := blst.SecretKeyFromBytes(d) + _ = err + } +} diff --git a/crypto/bls/blst/doc.go b/crypto/bls/blst/doc.go new file mode 100644 index 0000000000..b5f8850833 --- /dev/null +++ b/crypto/bls/blst/doc.go @@ -0,0 +1,6 @@ +// Package blst implements a go-wrapper around a library implementing the +// BLS12-381 curve and signature scheme. This package exposes a public API for +// verifying and aggregating BLS signatures used by Ethereum. +// +// This implementation uses the library written by Supranational, blst. +package blst diff --git a/crypto/bls/blst/init.go b/crypto/bls/blst/init.go new file mode 100644 index 0000000000..ab8be94ca5 --- /dev/null +++ b/crypto/bls/blst/init.go @@ -0,0 +1,18 @@ +//go:build ((linux && amd64) || (linux && arm64) || (darwin && amd64) || (darwin && arm64) || (windows && amd64)) && !blst_disabled + +package blst + +import ( + "runtime" + + blst "github.com/supranational/blst/bindings/go" +) + +func init() { + // Reserve 1 core for general application work + maxProcs := runtime.GOMAXPROCS(0) - 1 + if maxProcs <= 0 { + maxProcs = 1 + } + blst.SetMaxProcs(maxProcs) +} diff --git a/crypto/bls/blst/public_key.go b/crypto/bls/blst/public_key.go new file mode 100644 index 0000000000..f543241057 --- /dev/null +++ b/crypto/bls/blst/public_key.go @@ -0,0 +1,114 @@ +//go:build ((linux && amd64) || (linux && arm64) || (darwin && amd64) || (darwin && arm64) || (windows && amd64)) && !blst_disabled + +package blst + +import ( + "fmt" + "github.com/ethereum/go-ethereum/crypto/bls/common" + "github.com/ethereum/go-ethereum/params" + lru "github.com/hashicorp/golang-lru" + "github.com/pkg/errors" +) + +var maxKeys = 1000000 +var pubkeyCache, _ = lru.New(maxKeys) + +// PublicKey used in the BLS signature scheme. +type PublicKey struct { + p *blstPublicKey +} + +// PublicKeyFromBytes creates a BLS public key from a BigEndian byte slice. +func PublicKeyFromBytes(pubKey []byte) (common.PublicKey, error) { + if len(pubKey) != params.BLSPubkeyLength { + return nil, fmt.Errorf("public key must be %d bytes", params.BLSPubkeyLength) + } + newKey := (*[params.BLSPubkeyLength]byte)(pubKey) + if cv, ok := pubkeyCache.Get(*newKey); ok { + return cv.(*PublicKey).Copy(), nil + } + // Subgroup check NOT done when decompressing pubkey. + p := new(blstPublicKey).Uncompress(pubKey) + if p == nil { + return nil, errors.New("could not unmarshal bytes into public key") + } + // Subgroup and infinity check + if !p.KeyValidate() { + // NOTE: the error is not quite accurate since it includes group check + return nil, common.ErrInfinitePubKey + } + pubKeyObj := &PublicKey{p: p} + copiedKey := pubKeyObj.Copy() + cacheKey := *newKey + pubkeyCache.Add(cacheKey, copiedKey) + return pubKeyObj, nil +} + +// AggregatePublicKeys aggregates the provided raw public keys into a single key. +func AggregatePublicKeys(pubs [][]byte) (common.PublicKey, error) { + if len(pubs) == 0 { + return nil, errors.New("nil or empty public keys") + } + agg := new(blstAggregatePublicKey) + mulP1 := make([]*blstPublicKey, 0, len(pubs)) + for _, pubkey := range pubs { + pubKeyObj, err := PublicKeyFromBytes(pubkey) + if err != nil { + return nil, err + } + mulP1 = append(mulP1, pubKeyObj.(*PublicKey).p) + } + // No group check needed here since it is done in PublicKeyFromBytes + // Note the checks could be moved from PublicKeyFromBytes into Aggregate + // and take advantage of multi-threading. + agg.Aggregate(mulP1, false) + return &PublicKey{p: agg.ToAffine()}, nil +} + +// Marshal a public key into a LittleEndian byte slice. +func (p *PublicKey) Marshal() []byte { + return p.p.Compress() +} + +// Copy the public key to a new pointer reference. +func (p *PublicKey) Copy() common.PublicKey { + np := *p.p + return &PublicKey{p: &np} +} + +// IsInfinite checks if the public key is infinite. +func (p *PublicKey) IsInfinite() bool { + zeroKey := new(blstPublicKey) + return p.p.Equals(zeroKey) +} + +// Equals checks if the provided public key is equal to +// the current one. +func (p *PublicKey) Equals(p2 common.PublicKey) bool { + return p.p.Equals(p2.(*PublicKey).p) +} + +// Aggregate two public keys. +func (p *PublicKey) Aggregate(p2 common.PublicKey) common.PublicKey { + agg := new(blstAggregatePublicKey) + // No group check here since it is checked at decompression time + agg.Add(p.p, false) + agg.Add(p2.(*PublicKey).p, false) + p.p = agg.ToAffine() + + return p +} + +// AggregateMultiplePubkeys aggregates the provided decompressed keys into a single key. +func AggregateMultiplePubkeys(pubkeys []common.PublicKey) common.PublicKey { + mulP1 := make([]*blstPublicKey, 0, len(pubkeys)) + for _, pubkey := range pubkeys { + mulP1 = append(mulP1, pubkey.(*PublicKey).p) + } + agg := new(blstAggregatePublicKey) + // No group check needed here since it is done in PublicKeyFromBytes + // Note the checks could be moved from PublicKeyFromBytes into Aggregate + // and take advantage of multi-threading. + agg.Aggregate(mulP1, false) + return &PublicKey{p: agg.ToAffine()} +} diff --git a/crypto/bls/blst/public_key_test.go b/crypto/bls/blst/public_key_test.go new file mode 100644 index 0000000000..9b9ed5408e --- /dev/null +++ b/crypto/bls/blst/public_key_test.go @@ -0,0 +1,97 @@ +//go:build ((linux && amd64) || (linux && arm64) || (darwin && amd64) || (darwin && arm64) || (windows && amd64)) && !blst_disabled + +package blst_test + +import ( + "bytes" + "errors" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "testing" + + "github.com/ethereum/go-ethereum/crypto/bls/blst" + "github.com/ethereum/go-ethereum/crypto/bls/common" +) + +func TestPublicKeyFromBytes(t *testing.T) { + tests := []struct { + name string + input []byte + err error + }{ + { + name: "Nil", + err: errors.New("public key must be 48 bytes"), + }, + { + name: "Empty", + input: []byte{}, + err: errors.New("public key must be 48 bytes"), + }, + { + name: "Short", + input: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + err: errors.New("public key must be 48 bytes"), + }, + { + name: "Long", + input: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + err: errors.New("public key must be 48 bytes"), + }, + { + name: "Bad", + input: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + err: errors.New("could not unmarshal bytes into public key"), + }, + { + name: "Good", + input: []byte{0xa9, 0x9a, 0x76, 0xed, 0x77, 0x96, 0xf7, 0xbe, 0x22, 0xd5, 0xb7, 0xe8, 0x5d, 0xee, 0xb7, 0xc5, 0x67, 0x7e, 0x88, 0xe5, 0x11, 0xe0, 0xb3, 0x37, 0x61, 0x8f, 0x8c, 0x4e, 0xb6, 0x13, 0x49, 0xb4, 0xbf, 0x2d, 0x15, 0x3f, 0x64, 0x9f, 0x7b, 0x53, 0x35, 0x9f, 0xe8, 0xb9, 0x4a, 0x38, 0xe4, 0x4c}, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + res, err := blst.PublicKeyFromBytes(test.input) + if test.err != nil { + assert.NotEqual(t, nil, err, "No error returned") + assert.ErrorContains(t, test.err, err.Error(), "Unexpected error returned") + } else { + assert.NoError(t, err) + assert.Equal(t, 0, bytes.Compare(res.Marshal(), test.input)) + } + }) + } +} + +func TestPublicKey_Copy(t *testing.T) { + priv, err := blst.RandKey() + require.NoError(t, err) + pubkeyA := priv.PublicKey() + pubkeyBytes := pubkeyA.Marshal() + + pubkeyB := pubkeyA.Copy() + priv2, err := blst.RandKey() + require.NoError(t, err) + pubkeyB.Aggregate(priv2.PublicKey()) + require.Equal(t, pubkeyA.Marshal(), pubkeyBytes, "Pubkey was mutated after copy") +} + +func TestPublicKey_Aggregate(t *testing.T) { + priv, err := blst.RandKey() + require.NoError(t, err) + pubkeyA := priv.PublicKey() + + pubkeyB := pubkeyA.Copy() + priv2, err := blst.RandKey() + require.NoError(t, err) + resKey := pubkeyB.Aggregate(priv2.PublicKey()) + + aggKey := blst.AggregateMultiplePubkeys([]common.PublicKey{priv.PublicKey(), priv2.PublicKey()}) + require.Equal(t, resKey.Marshal(), aggKey.Marshal(), "Pubkey does not match up") +} + +func TestPublicKeysEmpty(t *testing.T) { + var pubs [][]byte + _, err := blst.AggregatePublicKeys(pubs) + require.ErrorContains(t, err, "nil or empty public keys") +} diff --git a/crypto/bls/blst/secret_key.go b/crypto/bls/blst/secret_key.go new file mode 100644 index 0000000000..498922d3a3 --- /dev/null +++ b/crypto/bls/blst/secret_key.go @@ -0,0 +1,83 @@ +//go:build ((linux && amd64) || (linux && arm64) || (darwin && amd64) || (darwin && arm64) || (windows && amd64)) && !blst_disabled + +package blst + +import ( + "crypto/subtle" + "fmt" + "github.com/ethereum/go-ethereum/crypto/bls/common" + "github.com/ethereum/go-ethereum/crypto/rand" + "github.com/ethereum/go-ethereum/params" + blst "github.com/supranational/blst/bindings/go" +) + +// bls12SecretKey used in the BLS signature scheme. +type bls12SecretKey struct { + p *blst.SecretKey +} + +// RandKey creates a new private key using a random method provided as an io.Reader. +func RandKey() (common.SecretKey, error) { + // Generate 32 bytes of randomness + var ikm [32]byte + _, err := rand.NewGenerator().Read(ikm[:]) + if err != nil { + return nil, err + } + // Defensive check, that we have not generated a secret key, + secKey := &bls12SecretKey{blst.KeyGen(ikm[:])} + if IsZero(secKey.Marshal()) { + return nil, common.ErrZeroKey + } + return secKey, nil +} + +// SecretKeyFromBytes creates a BLS private key from a BigEndian byte slice. +func SecretKeyFromBytes(privKey []byte) (common.SecretKey, error) { + if len(privKey) != params.BLSSecretKeyLength { + return nil, fmt.Errorf("secret key must be %d bytes", params.BLSSecretKeyLength) + } + secKey := new(blst.SecretKey).Deserialize(privKey) + if secKey == nil { + return nil, common.ErrSecretUnmarshal + } + wrappedKey := &bls12SecretKey{p: secKey} + if IsZero(privKey) { + return nil, common.ErrZeroKey + } + return wrappedKey, nil +} + +// PublicKey obtains the public key corresponding to the BLS secret key. +func (s *bls12SecretKey) PublicKey() common.PublicKey { + return &PublicKey{p: new(blstPublicKey).From(s.p)} +} + +// IsZero checks if the secret key is a zero key. +func IsZero(sKey []byte) bool { + b := byte(0) + for _, s := range sKey { + b |= s + } + return subtle.ConstantTimeByteEq(b, 0) == 1 +} + +// Sign a message using a secret key - in a beacon/validator client. +// +// In IETF draft BLS specification: +// Sign(SK, message) -> signature: a signing algorithm that generates +// +// a deterministic signature given a secret key SK and a message. +// +// In Ethereum proof of stake specification: +// def Sign(SK: int, message: Bytes) -> BLSSignature +func (s *bls12SecretKey) Sign(msg []byte) common.Signature { + signature := new(blstSignature).Sign(s.p, msg, dst) + return &Signature{s: signature} +} + +// Marshal a secret key into a LittleEndian byte slice. +func (s *bls12SecretKey) Marshal() []byte { + keyBytes := s.p.Serialize() + return keyBytes +} diff --git a/crypto/bls/blst/secret_key_test.go b/crypto/bls/blst/secret_key_test.go new file mode 100644 index 0000000000..0d440ace4a --- /dev/null +++ b/crypto/bls/blst/secret_key_test.go @@ -0,0 +1,98 @@ +//go:build ((linux && amd64) || (linux && arm64) || (darwin && amd64) || (darwin && arm64) || (windows && amd64)) && !blst_disabled + +package blst_test + +import ( + "bytes" + "crypto/rand" + "errors" + byteutil "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "testing" + + "github.com/ethereum/go-ethereum/crypto/bls/blst" + "github.com/ethereum/go-ethereum/crypto/bls/common" +) + +func TestMarshalUnmarshal(t *testing.T) { + priv, err := blst.RandKey() + require.NoError(t, err) + b := priv.Marshal() + b32 := byteutil.ToBytes32(b) + pk, err := blst.SecretKeyFromBytes(b32[:]) + require.NoError(t, err) + pk2, err := blst.SecretKeyFromBytes(b32[:]) + require.NoError(t, err) + assert.Equal(t, pk.Marshal(), pk2.Marshal(), "Keys not equal") +} + +func TestSecretKeyFromBytes(t *testing.T) { + tests := []struct { + name string + input []byte + err error + }{ + { + name: "Nil", + err: errors.New("secret key must be 32 bytes"), + }, + { + name: "Empty", + input: []byte{}, + err: errors.New("secret key must be 32 bytes"), + }, + { + name: "Short", + input: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + err: errors.New("secret key must be 32 bytes"), + }, + { + name: "Long", + input: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + err: errors.New("secret key must be 32 bytes"), + }, + { + name: "Bad", + input: []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + err: common.ErrSecretUnmarshal, + }, + { + name: "Good", + input: []byte{0x25, 0x29, 0x5f, 0x0d, 0x1d, 0x59, 0x2a, 0x90, 0xb3, 0x33, 0xe2, 0x6e, 0x85, 0x14, 0x97, 0x08, 0x20, 0x8e, 0x9f, 0x8e, 0x8b, 0xc1, 0x8f, 0x6c, 0x77, 0xbd, 0x62, 0xf8, 0xad, 0x7a, 0x68, 0x66}, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + res, err := blst.SecretKeyFromBytes(test.input) + if test.err != nil { + assert.NotEqual(t, nil, err, "No error returned") + assert.Contains(t, err.Error(), test.err.Error(), "Unexpected error returned") + } else { + assert.NoError(t, err) + assert.Equal(t, 0, bytes.Compare(res.Marshal(), test.input)) + } + }) + } +} + +func TestSerialize(t *testing.T) { + rk, err := blst.RandKey() + require.NoError(t, err) + b := rk.Marshal() + + _, err = blst.SecretKeyFromBytes(b) + assert.NoError(t, err) +} + +func TestZeroKey(t *testing.T) { + // Is Zero + var zKey [32]byte + assert.Equal(t, true, blst.IsZero(zKey[:])) + + // Is Not Zero + _, err := rand.Read(zKey[:]) + assert.NoError(t, err) + assert.Equal(t, false, blst.IsZero(zKey[:])) +} diff --git a/crypto/bls/blst/signature.go b/crypto/bls/blst/signature.go new file mode 100644 index 0000000000..6467b065ab --- /dev/null +++ b/crypto/bls/blst/signature.go @@ -0,0 +1,269 @@ +//go:build ((linux && amd64) || (linux && arm64) || (darwin && amd64) || (darwin && arm64) || (windows && amd64)) && !blst_disabled + +package blst + +import ( + "bytes" + "fmt" + "github.com/ethereum/go-ethereum/params" + "sync" + + "github.com/ethereum/go-ethereum/crypto/bls/common" + "github.com/ethereum/go-ethereum/crypto/rand" + "github.com/pkg/errors" + blst "github.com/supranational/blst/bindings/go" +) + +var dst = []byte("BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_") + +const scalarBytes = 32 +const randBitsEntropy = 64 + +// Signature used in the BLS signature scheme. +type Signature struct { + s *blstSignature +} + +// SignatureFromBytes creates a BLS signature from a LittleEndian byte slice. +func SignatureFromBytes(sig []byte) (common.Signature, error) { + if len(sig) != params.BLSSignatureLength { + return nil, fmt.Errorf("signature must be %d bytes", params.BLSSignatureLength) + } + signature := new(blstSignature).Uncompress(sig) + if signature == nil { + return nil, errors.New("could not unmarshal bytes into signature") + } + // Group check signature. Do not check for infinity since an aggregated signature + // could be infinite. + if !signature.SigValidate(false) { + return nil, errors.New("signature not in group") + } + return &Signature{s: signature}, nil +} + +// AggregateCompressedSignatures converts a list of compressed signatures into a single, aggregated sig. +func AggregateCompressedSignatures(multiSigs [][]byte) (common.Signature, error) { + signature := new(blstAggregateSignature) + valid := signature.AggregateCompressed(multiSigs, true) + if !valid { + return nil, errors.New("provided signatures fail the group check and cannot be compressed") + } + return &Signature{s: signature.ToAffine()}, nil +} + +// MultipleSignaturesFromBytes creates a group of BLS signatures from a LittleEndian 2d-byte slice. +func MultipleSignaturesFromBytes(multiSigs [][]byte) ([]common.Signature, error) { + if len(multiSigs) == 0 { + return nil, fmt.Errorf("0 signatures provided to the method") + } + for _, s := range multiSigs { + if len(s) != params.BLSSignatureLength { + return nil, fmt.Errorf("signature must be %d bytes", params.BLSSignatureLength) + } + } + multiSignatures := new(blstSignature).BatchUncompress(multiSigs) + if len(multiSignatures) == 0 { + return nil, errors.New("could not unmarshal bytes into signature") + } + if len(multiSignatures) != len(multiSigs) { + return nil, errors.Errorf("wanted %d decompressed signatures but got %d", len(multiSigs), len(multiSignatures)) + } + wrappedSigs := make([]common.Signature, len(multiSignatures)) + for i, signature := range multiSignatures { + // Group check signature. Do not check for infinity since an aggregated signature + // could be infinite. + if !signature.SigValidate(false) { + return nil, errors.New("signature not in group") + } + copiedSig := signature + wrappedSigs[i] = &Signature{s: copiedSig} + } + return wrappedSigs, nil +} + +// Verify a bls signature given a public key, a message. +// +// In IETF draft BLS specification: +// Verify(PK, message, signature) -> VALID or INVALID: a verification +// +// algorithm that outputs VALID if signature is a valid signature of +// message under public key PK, and INVALID otherwise. +// +// In the Ethereum proof of stake specification: +// def Verify(PK: BLSPubkey, message: Bytes, signature: BLSSignature) -> bool +func (s *Signature) Verify(pubKey common.PublicKey, msg []byte) bool { + // Signature and PKs are assumed to have been validated upon decompression! + return s.s.Verify(false, pubKey.(*PublicKey).p, false, msg, dst) +} + +// AggregateVerify 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. +// +// Note: The msgs must be distinct. For maximum performance, this method does not ensure distinct +// messages. +// +// In IETF draft BLS specification: +// AggregateVerify((PK_1, message_1), ..., (PK_n, message_n), +// +// signature) -> VALID or INVALID: an aggregate verification +// algorithm that outputs VALID if signature is a valid aggregated +// signature for a collection of public keys and messages, and +// outputs INVALID otherwise. +// +// In the Ethereum proof of stake specification: +// def AggregateVerify(pairs: Sequence[PK: BLSPubkey, message: Bytes], signature: BLSSignature) -> bool +// +// Deprecated: Use FastAggregateVerify or use this method in spectests only. +func (s *Signature) AggregateVerify(pubKeys []common.PublicKey, msgs [][32]byte) bool { + size := len(pubKeys) + if size == 0 { + return false + } + if size != len(msgs) { + return false + } + msgSlices := make([][]byte, len(msgs)) + rawKeys := make([]*blstPublicKey, len(msgs)) + for i := 0; i < size; i++ { + msgSlices[i] = msgs[i][:] + rawKeys[i] = pubKeys[i].(*PublicKey).p + } + // Signature and PKs are assumed to have been validated upon decompression! + return s.s.AggregateVerify(false, rawKeys, false, msgSlices, dst) +} + +// FastAggregateVerify verifies all the provided public keys with their aggregated signature. +// +// In IETF draft BLS specification: +// FastAggregateVerify(PK_1, ..., PK_n, message, signature) -> VALID +// +// or INVALID: a verification algorithm for the aggregate of multiple +// signatures on the same message. This function is faster than +// AggregateVerify. +// +// In the Ethereum proof of stake specification: +// def FastAggregateVerify(PKs: Sequence[BLSPubkey], message: Bytes, signature: BLSSignature) -> bool +func (s *Signature) FastAggregateVerify(pubKeys []common.PublicKey, msg [32]byte) bool { + if len(pubKeys) == 0 { + return false + } + rawKeys := make([]*blstPublicKey, len(pubKeys)) + for i := 0; i < len(pubKeys); i++ { + rawKeys[i] = pubKeys[i].(*PublicKey).p + } + return s.s.FastAggregateVerify(true, rawKeys, msg[:], dst) +} + +// Eth2FastAggregateVerify implements a wrapper on top of bls's FastAggregateVerify. It accepts G2_POINT_AT_INFINITY signature +// when pubkeys empty. +// +// Spec code: +// def eth2_fast_aggregate_verify(pubkeys: Sequence[BLSPubkey], message: Bytes32, signature: BLSSignature) -> bool: +// +// """ +// Wrapper to ``bls.FastAggregateVerify`` accepting the ``G2_POINT_AT_INFINITY`` signature when ``pubkeys`` is empty. +// """ +// if len(pubkeys) == 0 and signature == G2_POINT_AT_INFINITY: +// return True +// return bls.FastAggregateVerify(pubkeys, message, signature) +func (s *Signature) Eth2FastAggregateVerify(pubKeys []common.PublicKey, msg [32]byte) bool { + if len(pubKeys) == 0 && bytes.Equal(s.Marshal(), common.InfiniteSignature[:]) { + return true + } + return s.FastAggregateVerify(pubKeys, msg) +} + +// NewAggregateSignature creates a blank aggregate signature. +func NewAggregateSignature() common.Signature { + sig := blst.HashToG2([]byte{'m', 'o', 'c', 'k'}, dst).ToAffine() + return &Signature{s: sig} +} + +// AggregateSignatures converts a list of signatures into a single, aggregated sig. +func AggregateSignatures(sigs []common.Signature) common.Signature { + if len(sigs) == 0 { + return nil + } + + rawSigs := make([]*blstSignature, len(sigs)) + for i := 0; i < len(sigs); i++ { + rawSigs[i] = sigs[i].(*Signature).s + } + + // Signature and PKs are assumed to have been validated upon decompression! + signature := new(blstAggregateSignature) + signature.Aggregate(rawSigs, false) + return &Signature{s: signature.ToAffine()} +} + +// VerifySignature verifies a single signature using public key and message. +func VerifySignature(sig []byte, msg [32]byte, pubKey common.PublicKey) (bool, error) { + rSig, err := SignatureFromBytes(sig) + if err != nil { + return false, err + } + return rSig.Verify(pubKey, msg[:]), nil +} + +// VerifyMultipleSignatures verifies a non-singular set of signatures and its respective pubkeys and messages. +// This method provides a safe way to verify multiple signatures at once. We pick a number randomly from 1 to max +// uint64 and then multiply the signature by it. We continue doing this for all signatures and its respective pubkeys. +// S* = S_1 * r_1 + S_2 * r_2 + ... + S_n * r_n +// P'_{i,j} = P_{i,j} * r_i +// e(S*, G) = \prod_{i=1}^n \prod_{j=1}^{m_i} e(P'_{i,j}, M_{i,j}) +// Using this we can verify multiple signatures safely. +func VerifyMultipleSignatures(sigs [][]byte, msgs [][32]byte, pubKeys []common.PublicKey) (bool, error) { + if len(sigs) == 0 || len(pubKeys) == 0 { + return false, nil + } + rawSigs := new(blstSignature).BatchUncompress(sigs) + + length := len(sigs) + if length != len(pubKeys) || length != len(msgs) { + return false, errors.Errorf("provided signatures, pubkeys and messages have differing lengths. S: %d, P: %d,M %d", + length, len(pubKeys), len(msgs)) + } + mulP1Aff := make([]*blstPublicKey, length) + rawMsgs := make([]blst.Message, length) + + for i := 0; i < length; i++ { + mulP1Aff[i] = pubKeys[i].(*PublicKey).p + rawMsgs[i] = msgs[i][:] + } + // Secure source of RNG + randGen := rand.NewGenerator() + randLock := new(sync.Mutex) + + randFunc := func(scalar *blst.Scalar) { + var rbytes [scalarBytes]byte + randLock.Lock() + randGen.Read(rbytes[:]) // #nosec G104 -- Error will always be nil in `read` in math/rand + randLock.Unlock() + // Protect against the generator returning 0. Since the scalar value is + // derived from a big endian byte slice, we take the last byte. + rbytes[len(rbytes)-1] |= 0x01 + scalar.FromBEndian(rbytes[:]) + } + dummySig := new(blstSignature) + + // Validate signatures since we uncompress them here. Public keys should already be validated. + return dummySig.MultipleAggregateVerify(rawSigs, true, mulP1Aff, false, rawMsgs, dst, randFunc, randBitsEntropy), nil +} + +// Marshal a signature into a LittleEndian byte slice. +func (s *Signature) Marshal() []byte { + return s.s.Compress() +} + +// Copy returns a full deep copy of a signature. +func (s *Signature) Copy() common.Signature { + sign := *s.s + return &Signature{s: &sign} +} + +// VerifyCompressed verifies that the compressed signature and pubkey +// are valid from the message provided. +func VerifyCompressed(signature, pub, msg []byte) bool { + // Validate signature and PKs since we will uncompress them here + return new(blstSignature).VerifyCompressed(signature, true, pub, true, msg, dst) +} diff --git a/crypto/bls/blst/signature_test.go b/crypto/bls/blst/signature_test.go new file mode 100644 index 0000000000..39dbb63fa9 --- /dev/null +++ b/crypto/bls/blst/signature_test.go @@ -0,0 +1,309 @@ +//go:build ((linux && amd64) || (linux && arm64) || (darwin && amd64) || (darwin && arm64) || (windows && amd64)) && !blst_disabled + +package blst + +import ( + "bytes" + "errors" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "testing" + + "github.com/ethereum/go-ethereum/crypto/bls/common" +) + +func TestSignVerify(t *testing.T) { + priv, err := RandKey() + require.NoError(t, err) + pub := priv.PublicKey() + msg := []byte("hello") + sig := priv.Sign(msg) + assert.Equal(t, true, sig.Verify(pub, msg), "Signature did not verify") +} + +func TestAggregateVerify(t *testing.T) { + pubkeys := make([]common.PublicKey, 0, 100) + sigs := make([]common.Signature, 0, 100) + var msgs [][32]byte + for i := 0; i < 100; i++ { + msg := [32]byte{'h', 'e', 'l', 'l', 'o', byte(i)} + priv, err := RandKey() + require.NoError(t, err) + pub := priv.PublicKey() + sig := priv.Sign(msg[:]) + pubkeys = append(pubkeys, pub) + sigs = append(sigs, sig) + msgs = append(msgs, msg) + } + aggSig := AggregateSignatures(sigs) + // skipcq: GO-W1009 + assert.Equal(t, true, aggSig.AggregateVerify(pubkeys, msgs), "Signature did not verify") +} + +func TestAggregateVerify_CompressedSignatures(t *testing.T) { + pubkeys := make([]common.PublicKey, 0, 100) + sigs := make([]common.Signature, 0, 100) + var sigBytes [][]byte + var msgs [][32]byte + for i := 0; i < 100; i++ { + msg := [32]byte{'h', 'e', 'l', 'l', 'o', byte(i)} + priv, err := RandKey() + require.NoError(t, err) + pub := priv.PublicKey() + sig := priv.Sign(msg[:]) + pubkeys = append(pubkeys, pub) + sigs = append(sigs, sig) + sigBytes = append(sigBytes, sig.Marshal()) + msgs = append(msgs, msg) + } + aggSig := AggregateSignatures(sigs) + // skipcq: GO-W1009 + assert.Equal(t, true, aggSig.AggregateVerify(pubkeys, msgs), "Signature did not verify") + + aggSig2, err := AggregateCompressedSignatures(sigBytes) + assert.NoError(t, err) + assert.Equal(t, aggSig.Marshal(), aggSig2.Marshal(), "Signature did not match up") +} + +func TestFastAggregateVerify(t *testing.T) { + pubkeys := make([]common.PublicKey, 0, 100) + sigs := make([]common.Signature, 0, 100) + msg := [32]byte{'h', 'e', 'l', 'l', 'o'} + for i := 0; i < 100; i++ { + priv, err := RandKey() + require.NoError(t, err) + pub := priv.PublicKey() + sig := priv.Sign(msg[:]) + pubkeys = append(pubkeys, pub) + sigs = append(sigs, sig) + } + aggSig := AggregateSignatures(sigs) + assert.Equal(t, true, aggSig.FastAggregateVerify(pubkeys, msg), "Signature did not verify") + +} + +func TestVerifyCompressed(t *testing.T) { + priv, err := RandKey() + require.NoError(t, err) + pub := priv.PublicKey() + msg := []byte("hello") + sig := priv.Sign(msg) + assert.Equal(t, true, sig.Verify(pub, msg), "Non compressed signature did not verify") + assert.Equal(t, true, VerifyCompressed(sig.Marshal(), pub.Marshal(), msg), "Compressed signatures and pubkeys did not verify") +} + +func TestVerifySingleSignature_InvalidSignature(t *testing.T) { + priv, err := RandKey() + require.NoError(t, err) + pub := priv.PublicKey() + msgA := [32]byte{'h', 'e', 'l', 'l', 'o'} + msgB := [32]byte{'o', 'l', 'l', 'e', 'h'} + sigA := priv.Sign(msgA[:]).Marshal() + valid, err := VerifySignature(sigA, msgB, pub) + assert.NoError(t, err) + assert.Equal(t, false, valid, "Signature did verify") +} + +func TestVerifySingleSignature_ValidSignature(t *testing.T) { + priv, err := RandKey() + require.NoError(t, err) + pub := priv.PublicKey() + msg := [32]byte{'h', 'e', 'l', 'l', 'o'} + sig := priv.Sign(msg[:]).Marshal() + valid, err := VerifySignature(sig, msg, pub) + assert.NoError(t, err) + assert.Equal(t, true, valid, "Signature did not verify") +} + +func TestMultipleSignatureVerification(t *testing.T) { + pubkeys := make([]common.PublicKey, 0, 100) + sigs := make([][]byte, 0, 100) + var msgs [][32]byte + for i := 0; i < 100; i++ { + msg := [32]byte{'h', 'e', 'l', 'l', 'o', byte(i)} + priv, err := RandKey() + require.NoError(t, err) + pub := priv.PublicKey() + sig := priv.Sign(msg[:]).Marshal() + pubkeys = append(pubkeys, pub) + sigs = append(sigs, sig) + msgs = append(msgs, msg) + } + verify, err := VerifyMultipleSignatures(sigs, msgs, pubkeys) + assert.NoError(t, err, "Signature did not verify") + assert.Equal(t, true, verify, "Signature did not verify") +} + +func TestFastAggregateVerify_ReturnsFalseOnEmptyPubKeyList(t *testing.T) { + var pubkeys []common.PublicKey + msg := [32]byte{'h', 'e', 'l', 'l', 'o'} + + aggSig := NewAggregateSignature() + assert.Equal(t, false, aggSig.FastAggregateVerify(pubkeys, msg), "Expected FastAggregateVerify to return false with empty input ") +} + +func TestEth2FastAggregateVerify(t *testing.T) { + pubkeys := make([]common.PublicKey, 0, 100) + sigs := make([]common.Signature, 0, 100) + msg := [32]byte{'h', 'e', 'l', 'l', 'o'} + for i := 0; i < 100; i++ { + priv, err := RandKey() + require.NoError(t, err) + pub := priv.PublicKey() + sig := priv.Sign(msg[:]) + pubkeys = append(pubkeys, pub) + sigs = append(sigs, sig) + } + aggSig := AggregateSignatures(sigs) + assert.Equal(t, true, aggSig.Eth2FastAggregateVerify(pubkeys, msg), "Signature did not verify") + +} + +func TestEth2FastAggregateVerify_ReturnsFalseOnEmptyPubKeyList(t *testing.T) { + var pubkeys []common.PublicKey + msg := [32]byte{'h', 'e', 'l', 'l', 'o'} + + aggSig := NewAggregateSignature() + assert.Equal(t, false, aggSig.Eth2FastAggregateVerify(pubkeys, msg), "Expected Eth2FastAggregateVerify to return false with empty input ") +} + +func TestEth2FastAggregateVerify_ReturnsTrueOnG2PointAtInfinity(t *testing.T) { + var pubkeys []common.PublicKey + msg := [32]byte{'h', 'e', 'l', 'l', 'o'} + + g2PointAtInfinity := append([]byte{0xC0}, make([]byte, 95)...) + aggSig, err := SignatureFromBytes(g2PointAtInfinity) + require.NoError(t, err) + assert.Equal(t, true, aggSig.Eth2FastAggregateVerify(pubkeys, msg)) +} + +func TestSignatureFromBytes(t *testing.T) { + tests := []struct { + name string + input []byte + err error + }{ + { + name: "Nil", + err: errors.New("signature must be 96 bytes"), + }, + { + name: "Empty", + input: []byte{}, + err: errors.New("signature must be 96 bytes"), + }, + { + name: "Short", + input: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + err: errors.New("signature must be 96 bytes"), + }, + { + name: "Long", + input: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + err: errors.New("signature must be 96 bytes"), + }, + { + name: "Bad", + input: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + err: errors.New("could not unmarshal bytes into signature"), + }, + { + name: "Good", + input: []byte{0xab, 0xb0, 0x12, 0x4c, 0x75, 0x74, 0xf2, 0x81, 0xa2, 0x93, 0xf4, 0x18, 0x5c, 0xad, 0x3c, 0xb2, 0x26, 0x81, 0xd5, 0x20, 0x91, 0x7c, 0xe4, 0x66, 0x65, 0x24, 0x3e, 0xac, 0xb0, 0x51, 0x00, 0x0d, 0x8b, 0xac, 0xf7, 0x5e, 0x14, 0x51, 0x87, 0x0c, 0xa6, 0xb3, 0xb9, 0xe6, 0xc9, 0xd4, 0x1a, 0x7b, 0x02, 0xea, 0xd2, 0x68, 0x5a, 0x84, 0x18, 0x8a, 0x4f, 0xaf, 0xd3, 0x82, 0x5d, 0xaf, 0x6a, 0x98, 0x96, 0x25, 0xd7, 0x19, 0xcc, 0xd2, 0xd8, 0x3a, 0x40, 0x10, 0x1f, 0x4a, 0x45, 0x3f, 0xca, 0x62, 0x87, 0x8c, 0x89, 0x0e, 0xca, 0x62, 0x23, 0x63, 0xf9, 0xdd, 0xb8, 0xf3, 0x67, 0xa9, 0x1e, 0x84}, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + res, err := SignatureFromBytes(test.input) + if test.err != nil { + assert.NotEqual(t, nil, err, "No error returned") + assert.ErrorContains(t, test.err, err.Error(), "Unexpected error returned") + } else { + assert.NoError(t, err) + assert.Equal(t, 0, bytes.Compare(res.Marshal(), test.input)) + } + }) + } +} + +func TestMultipleSignatureFromBytes(t *testing.T) { + tests := []struct { + name string + input [][]byte + err error + }{ + { + name: "Nil", + err: errors.New("0 signatures provided to the method"), + }, + { + name: "Empty", + input: [][]byte{}, + err: errors.New("0 signatures provided to the method"), + }, + { + name: "Short", + input: [][]byte{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + err: errors.New("signature must be 96 bytes"), + }, + { + name: "Long", + input: [][]byte{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + err: errors.New("signature must be 96 bytes"), + }, + { + name: "Bad", + input: [][]byte{{0x8f, 0xc0, 0xb4, 0x9e, 0x2e, 0xac, 0x50, 0x86, 0xe2, 0xe2, 0xaa, 0xf, 0xdc, 0x54, 0x23, 0x51, 0x6, 0xd8, 0x29, 0xf5, 0xae, 0x3, 0x5d, 0xb8, 0x31, 0x4d, 0x26, 0x3, 0x48, 0x18, 0xb9, 0x1f, 0x6b, 0xd7, 0x86, 0xb4, 0xa2, 0x69, 0xc7, 0xe7, 0xf5, 0xc0, 0x93, 0x19, 0x6e, 0xfd, 0x33, 0xb8, 0x1, 0xe1, 0x1f, 0x4e, 0xb4, 0xb1, 0xa0, 0x1, 0x30, 0x48, 0x8a, 0x6c, 0x97, 0x29, 0xd6, 0xcb, 0x1c, 0x45, 0xef, 0x87, 0xba, 0x4f, 0xce, 0x22, 0x84, 0x48, 0xad, 0x16, 0xf7, 0x5c, 0xb2, 0xa8, 0x34, 0xb9, 0xee, 0xb8, 0xbf, 0xe5, 0x58, 0x2c, 0x44, 0x7b, 0x1f, 0x9c, 0x22, 0x26, 0x3a, 0x22}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + err: errors.New("could not unmarshal bytes into signature"), + }, + { + name: "Good", + input: [][]byte{ + {0xab, 0xb0, 0x12, 0x4c, 0x75, 0x74, 0xf2, 0x81, 0xa2, 0x93, 0xf4, 0x18, 0x5c, 0xad, 0x3c, 0xb2, 0x26, 0x81, 0xd5, 0x20, 0x91, 0x7c, 0xe4, 0x66, 0x65, 0x24, 0x3e, 0xac, 0xb0, 0x51, 0x00, 0x0d, 0x8b, 0xac, 0xf7, 0x5e, 0x14, 0x51, 0x87, 0x0c, 0xa6, 0xb3, 0xb9, 0xe6, 0xc9, 0xd4, 0x1a, 0x7b, 0x02, 0xea, 0xd2, 0x68, 0x5a, 0x84, 0x18, 0x8a, 0x4f, 0xaf, 0xd3, 0x82, 0x5d, 0xaf, 0x6a, 0x98, 0x96, 0x25, 0xd7, 0x19, 0xcc, 0xd2, 0xd8, 0x3a, 0x40, 0x10, 0x1f, 0x4a, 0x45, 0x3f, 0xca, 0x62, 0x87, 0x8c, 0x89, 0x0e, 0xca, 0x62, 0x23, 0x63, 0xf9, 0xdd, 0xb8, 0xf3, 0x67, 0xa9, 0x1e, 0x84}, + {0xb7, 0x86, 0xe5, 0x7, 0x43, 0xe2, 0x53, 0x6c, 0x15, 0x51, 0x9c, 0x6, 0x2a, 0xa7, 0xe5, 0x12, 0xf9, 0xb7, 0x77, 0x93, 0x3f, 0x55, 0xb3, 0xaf, 0x38, 0xf7, 0x39, 0xe4, 0x84, 0x6d, 0x88, 0x44, 0x52, 0x77, 0x65, 0x42, 0x95, 0xd9, 0x79, 0x93, 0x7e, 0xc8, 0x12, 0x60, 0xe3, 0x24, 0xea, 0x8, 0x10, 0x52, 0xcd, 0xd2, 0x7f, 0x5d, 0x25, 0x3a, 0xa8, 0x9b, 0xb7, 0x65, 0xa9, 0x31, 0xea, 0x7c, 0x85, 0x13, 0x53, 0xc0, 0xa3, 0x88, 0xd1, 0xa5, 0x54, 0x85, 0x2, 0x2d, 0xf8, 0xa1, 0xd7, 0xc1, 0x60, 0x58, 0x93, 0xec, 0x7c, 0xf9, 0x33, 0x43, 0x4, 0x48, 0x40, 0x97, 0xef, 0x67, 0x2a, 0x27}, + {0xb2, 0x12, 0xd0, 0xec, 0x46, 0x76, 0x6b, 0x24, 0x71, 0x91, 0x2e, 0xa8, 0x53, 0x9a, 0x48, 0xa3, 0x78, 0x30, 0xc, 0xe8, 0xf0, 0x86, 0xa3, 0x68, 0xec, 0xe8, 0x96, 0x43, 0x34, 0xda, 0xf, 0xf4, 0x65, 0x48, 0xbb, 0xe0, 0x92, 0xa1, 0x8, 0x12, 0x18, 0x46, 0xe6, 0x4a, 0xd6, 0x92, 0x88, 0xe, 0x2, 0xf5, 0xf3, 0x2a, 0x96, 0xb1, 0x4, 0xf1, 0x11, 0xa9, 0x92, 0x79, 0x52, 0x0, 0x64, 0x34, 0xeb, 0x25, 0xe, 0xf4, 0x29, 0x6b, 0x39, 0x4e, 0x28, 0x78, 0xfe, 0x25, 0xa3, 0xc0, 0x88, 0x5a, 0x40, 0xfd, 0x71, 0x37, 0x63, 0x79, 0xcd, 0x6b, 0x56, 0xda, 0xee, 0x91, 0x26, 0x72, 0xfc, 0xbc}, + {0x8f, 0xc0, 0xb4, 0x9e, 0x2e, 0xac, 0x50, 0x86, 0xe2, 0xe2, 0xaa, 0xf, 0xdc, 0x54, 0x23, 0x51, 0x6, 0xd8, 0x29, 0xf5, 0xae, 0x3, 0x5d, 0xb8, 0x31, 0x4d, 0x26, 0x3, 0x48, 0x18, 0xb9, 0x1f, 0x6b, 0xd7, 0x86, 0xb4, 0xa2, 0x69, 0xc7, 0xe7, 0xf5, 0xc0, 0x93, 0x19, 0x6e, 0xfd, 0x33, 0xb8, 0x1, 0xe1, 0x1f, 0x4e, 0xb4, 0xb1, 0xa0, 0x1, 0x30, 0x48, 0x8a, 0x6c, 0x97, 0x29, 0xd6, 0xcb, 0x1c, 0x45, 0xef, 0x87, 0xba, 0x4f, 0xce, 0x22, 0x84, 0x48, 0xad, 0x16, 0xf7, 0x5c, 0xb2, 0xa8, 0x34, 0xb9, 0xee, 0xb8, 0xbf, 0xe5, 0x58, 0x2c, 0x44, 0x7b, 0x1f, 0x9c, 0x22, 0x26, 0x3a, 0x22}, + }, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + res, err := MultipleSignaturesFromBytes(test.input) + if test.err != nil { + assert.NotEqual(t, nil, err, "No error returned") + assert.ErrorContains(t, test.err, err.Error(), "Unexpected error returned") + } else { + assert.NoError(t, err) + for i, s := range res { + assert.Equal(t, 0, bytes.Compare(s.Marshal(), test.input[i])) + } + } + }) + } +} + +func TestCopy(t *testing.T) { + priv, err := RandKey() + require.NoError(t, err) + key, ok := priv.(*bls12SecretKey) + require.Equal(t, true, ok) + + signatureA := &Signature{s: new(blstSignature).Sign(key.p, []byte("foo"), dst)} + signatureB, ok := signatureA.Copy().(*Signature) + require.Equal(t, true, ok) + + if signatureA == signatureB { + t.Fatalf("%#v expected not equal to %#v", signatureA, signatureB) + } + + if signatureA.s == signatureB.s { + t.Fatalf("%#v expected not equal to %#v", signatureA.s, signatureB.s) + } + assert.Equal(t, signatureA, signatureB) + + signatureA.s.Sign(key.p, []byte("bar"), dst) + assert.NotEqual(t, signatureA, signatureB) +} diff --git a/crypto/bls/blst/stub.go b/crypto/bls/blst/stub.go new file mode 100644 index 0000000000..a75e7e7338 --- /dev/null +++ b/crypto/bls/blst/stub.go @@ -0,0 +1,154 @@ +//go:build blst_disabled + +package blst + +import ( + "github.com/ethereum/go-ethereum/crypto/bls/common" +) + +// This stub file exists until build issues can be resolved for libfuzz. +const err = "blst is only supported on linux,darwin,windows" + +// SecretKey -- stub +type SecretKey struct{} + +// PublicKey -- stub +func (s SecretKey) PublicKey() common.PublicKey { + panic(err) +} + +// Sign -- stub +func (s SecretKey) Sign(_ []byte) common.Signature { + panic(err) +} + +// Marshal -- stub +func (s SecretKey) Marshal() []byte { + panic(err) +} + +// IsZero -- stub +func (s SecretKey) IsZero() bool { + panic(err) +} + +// PublicKey -- stub +type PublicKey struct{} + +// Marshal -- stub +func (p PublicKey) Marshal() []byte { + panic(err) +} + +// Copy -- stub +func (p PublicKey) Copy() common.PublicKey { + panic(err) +} + +// Aggregate -- stub +func (p PublicKey) Aggregate(_ common.PublicKey) common.PublicKey { + panic(err) +} + +// IsInfinite -- stub +func (p PublicKey) IsInfinite() bool { + panic(err) +} + +// Equals -- stub +func (p PublicKey) Equals(_ common.PublicKey) bool { + panic(err) +} + +// Signature -- stub +type Signature struct{} + +// Verify -- stub +func (s Signature) Verify(_ common.PublicKey, _ []byte) bool { + panic(err) +} + +// AggregateVerify -- stub +func (s Signature) AggregateVerify(_ []common.PublicKey, _ [][32]byte) bool { + panic(err) +} + +// FastAggregateVerify -- stub +func (s Signature) FastAggregateVerify(_ []common.PublicKey, _ [32]byte) bool { + panic(err) +} + +// Eth2FastAggregateVerify -- stub +func (s Signature) Eth2FastAggregateVerify(_ []common.PublicKey, _ [32]byte) bool { + panic(err) +} + +// Marshal -- stub +func (s Signature) Marshal() []byte { + panic(err) +} + +// Copy -- stub +func (s Signature) Copy() common.Signature { + panic(err) +} + +// SecretKeyFromBytes -- stub +func SecretKeyFromBytes(_ []byte) (SecretKey, error) { + panic(err) +} + +// PublicKeyFromBytes -- stub +func PublicKeyFromBytes(_ []byte) (PublicKey, error) { + panic(err) +} + +// SignatureFromBytes -- stub +func SignatureFromBytes(_ []byte) (Signature, error) { + panic(err) +} + +// MultipleSignaturesFromBytes -- stub +func MultipleSignaturesFromBytes(multiSigs [][]byte) ([]common.Signature, error) { + panic(err) +} + +// AggregatePublicKeys -- stub +func AggregatePublicKeys(_ [][]byte) (PublicKey, error) { + panic(err) +} + +// AggregateSignatures -- stub +func AggregateSignatures(_ []common.Signature) common.Signature { + panic(err) +} + +// AggregateMultiplePubkeys -- stub +func AggregateMultiplePubkeys(pubs []common.PublicKey) common.PublicKey { + panic(err) +} + +// AggregateCompressedSignatures -- stub +func AggregateCompressedSignatures(multiSigs [][]byte) (common.Signature, error) { + panic(err) +} + +// VerifyMultipleSignatures -- stub +func VerifyMultipleSignatures(_ [][]byte, _ [][32]byte, _ []common.PublicKey) (bool, error) { + panic(err) +} + +// NewAggregateSignature -- stub +func NewAggregateSignature() common.Signature { + panic(err) +} + +// RandKey -- stub +func RandKey() (common.SecretKey, error) { + panic(err) +} + +// VerifyCompressed -- stub +func VerifyCompressed(_, _, _ []byte) bool { + panic(err) +} diff --git a/crypto/bls/common/constants.go b/crypto/bls/common/constants.go new file mode 100644 index 0000000000..e9e171fb23 --- /dev/null +++ b/crypto/bls/common/constants.go @@ -0,0 +1,12 @@ +package common + +import "github.com/ethereum/go-ethereum/params" + +// ZeroSecretKey represents a zero secret key. +var ZeroSecretKey = [32]byte{} + +// InfinitePublicKey represents an infinite public key (G1 Point at Infinity). +var InfinitePublicKey = [params.BLSPubkeyLength]byte{0xC0} + +// InfiniteSignature represents an infinite signature (G2 Point at Infinity). +var InfiniteSignature = [96]byte{0xC0} diff --git a/crypto/bls/common/error.go b/crypto/bls/common/error.go new file mode 100644 index 0000000000..13cc48eaaa --- /dev/null +++ b/crypto/bls/common/error.go @@ -0,0 +1,13 @@ +package common + +import "errors" + +// ErrZeroKey describes an error due to a zero secret key. +var ErrZeroKey = errors.New("received secret key is zero") + +// ErrSecretUnmarshal describes an error which happens during unmarshalling +// a secret key. +var ErrSecretUnmarshal = errors.New("could not unmarshal bytes into secret key") + +// ErrInfinitePubKey describes an error due to an infinite public key. +var ErrInfinitePubKey = errors.New("received an infinite public key") diff --git a/crypto/bls/common/interface.go b/crypto/bls/common/interface.go new file mode 100644 index 0000000000..db2c770111 --- /dev/null +++ b/crypto/bls/common/interface.go @@ -0,0 +1,33 @@ +// Package common provides the BLS interfaces that are implemented by the various BLS wrappers. +// +// This package should not be used by downstream consumers. These interfaces are re-exporter by +// github.com/ethereum/go-ethereum/crypto/bls. This package exists to prevent an import circular +// dependency. +package common + +// SecretKey represents a BLS secret or private key. +type SecretKey interface { + PublicKey() PublicKey + Sign(msg []byte) Signature + Marshal() []byte +} + +// PublicKey represents a BLS public key. +type PublicKey interface { + Marshal() []byte + Copy() PublicKey + Aggregate(p2 PublicKey) PublicKey + IsInfinite() bool + Equals(p2 PublicKey) bool +} + +// Signature represents a BLS signature. +type Signature interface { + Verify(pubKey PublicKey, msg []byte) bool + // Deprecated: Use FastAggregateVerify or use this method in spectests only. + AggregateVerify(pubKeys []PublicKey, msgs [][32]byte) bool + FastAggregateVerify(pubKeys []PublicKey, msg [32]byte) bool + Eth2FastAggregateVerify(pubKeys []PublicKey, msg [32]byte) bool + Marshal() []byte + Copy() Signature +} diff --git a/crypto/bls/common/mock/interface_mock.go b/crypto/bls/common/mock/interface_mock.go new file mode 100644 index 0000000000..060f635e19 --- /dev/null +++ b/crypto/bls/common/mock/interface_mock.go @@ -0,0 +1,277 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: crypto/bls/common/interface.go + +// Package mock is a generated GoMock package. +package mock + +import ( + reflect "reflect" + + common "github.com/ethereum/go-ethereum/crypto/bls/common" + gomock "github.com/golang/mock/gomock" +) + +// MockSecretKey is a mock of SecretKey interface. +type MockSecretKey struct { + ctrl *gomock.Controller + recorder *MockSecretKeyMockRecorder +} + +// MockSecretKeyMockRecorder is the mock recorder for MockSecretKey. +type MockSecretKeyMockRecorder struct { + mock *MockSecretKey +} + +// NewMockSecretKey creates a new mock instance. +func NewMockSecretKey(ctrl *gomock.Controller) *MockSecretKey { + mock := &MockSecretKey{ctrl: ctrl} + mock.recorder = &MockSecretKeyMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockSecretKey) EXPECT() *MockSecretKeyMockRecorder { + return m.recorder +} + +// Marshal mocks base method. +func (m *MockSecretKey) Marshal() []byte { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Marshal") + ret0, _ := ret[0].([]byte) + return ret0 +} + +// Marshal indicates an expected call of Marshal. +func (mr *MockSecretKeyMockRecorder) Marshal() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Marshal", reflect.TypeOf((*MockSecretKey)(nil).Marshal)) +} + +// PublicKey mocks base method. +func (m *MockSecretKey) PublicKey() common.PublicKey { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "PublicKey") + ret0, _ := ret[0].(common.PublicKey) + return ret0 +} + +// PublicKey indicates an expected call of PublicKey. +func (mr *MockSecretKeyMockRecorder) PublicKey() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PublicKey", reflect.TypeOf((*MockSecretKey)(nil).PublicKey)) +} + +// Sign mocks base method. +func (m *MockSecretKey) Sign(msg []byte) common.Signature { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Sign", msg) + ret0, _ := ret[0].(common.Signature) + return ret0 +} + +// Sign indicates an expected call of Sign. +func (mr *MockSecretKeyMockRecorder) Sign(msg interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Sign", reflect.TypeOf((*MockSecretKey)(nil).Sign), msg) +} + +// MockPublicKey is a mock of PublicKey interface. +type MockPublicKey struct { + ctrl *gomock.Controller + recorder *MockPublicKeyMockRecorder +} + +// MockPublicKeyMockRecorder is the mock recorder for MockPublicKey. +type MockPublicKeyMockRecorder struct { + mock *MockPublicKey +} + +// NewMockPublicKey creates a new mock instance. +func NewMockPublicKey(ctrl *gomock.Controller) *MockPublicKey { + mock := &MockPublicKey{ctrl: ctrl} + mock.recorder = &MockPublicKeyMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockPublicKey) EXPECT() *MockPublicKeyMockRecorder { + return m.recorder +} + +// Aggregate mocks base method. +func (m *MockPublicKey) Aggregate(p2 common.PublicKey) common.PublicKey { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Aggregate", p2) + ret0, _ := ret[0].(common.PublicKey) + return ret0 +} + +// Aggregate indicates an expected call of Aggregate. +func (mr *MockPublicKeyMockRecorder) Aggregate(p2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Aggregate", reflect.TypeOf((*MockPublicKey)(nil).Aggregate), p2) +} + +// Copy mocks base method. +func (m *MockPublicKey) Copy() common.PublicKey { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Copy") + ret0, _ := ret[0].(common.PublicKey) + return ret0 +} + +// Copy indicates an expected call of Copy. +func (mr *MockPublicKeyMockRecorder) Copy() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Copy", reflect.TypeOf((*MockPublicKey)(nil).Copy)) +} + +// Equals mocks base method. +func (m *MockPublicKey) Equals(p2 common.PublicKey) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Equals", p2) + ret0, _ := ret[0].(bool) + return ret0 +} + +// Equals indicates an expected call of Equals. +func (mr *MockPublicKeyMockRecorder) Equals(p2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Equals", reflect.TypeOf((*MockPublicKey)(nil).Equals), p2) +} + +// IsInfinite mocks base method. +func (m *MockPublicKey) IsInfinite() bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "IsInfinite") + ret0, _ := ret[0].(bool) + return ret0 +} + +// IsInfinite indicates an expected call of IsInfinite. +func (mr *MockPublicKeyMockRecorder) IsInfinite() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsInfinite", reflect.TypeOf((*MockPublicKey)(nil).IsInfinite)) +} + +// Marshal mocks base method. +func (m *MockPublicKey) Marshal() []byte { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Marshal") + ret0, _ := ret[0].([]byte) + return ret0 +} + +// Marshal indicates an expected call of Marshal. +func (mr *MockPublicKeyMockRecorder) Marshal() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Marshal", reflect.TypeOf((*MockPublicKey)(nil).Marshal)) +} + +// MockSignature is a mock of Signature interface. +type MockSignature struct { + ctrl *gomock.Controller + recorder *MockSignatureMockRecorder +} + +// MockSignatureMockRecorder is the mock recorder for MockSignature. +type MockSignatureMockRecorder struct { + mock *MockSignature +} + +// NewMockSignature creates a new mock instance. +func NewMockSignature(ctrl *gomock.Controller) *MockSignature { + mock := &MockSignature{ctrl: ctrl} + mock.recorder = &MockSignatureMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockSignature) EXPECT() *MockSignatureMockRecorder { + return m.recorder +} + +// AggregateVerify mocks base method. +func (m *MockSignature) AggregateVerify(pubKeys []common.PublicKey, msgs [][32]byte) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "AggregateVerify", pubKeys, msgs) + ret0, _ := ret[0].(bool) + return ret0 +} + +// AggregateVerify indicates an expected call of AggregateVerify. +func (mr *MockSignatureMockRecorder) AggregateVerify(pubKeys, msgs interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AggregateVerify", reflect.TypeOf((*MockSignature)(nil).AggregateVerify), pubKeys, msgs) +} + +// Copy mocks base method. +func (m *MockSignature) Copy() common.Signature { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Copy") + ret0, _ := ret[0].(common.Signature) + return ret0 +} + +// Copy indicates an expected call of Copy. +func (mr *MockSignatureMockRecorder) Copy() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Copy", reflect.TypeOf((*MockSignature)(nil).Copy)) +} + +// Eth2FastAggregateVerify mocks base method. +func (m *MockSignature) Eth2FastAggregateVerify(pubKeys []common.PublicKey, msg [32]byte) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Eth2FastAggregateVerify", pubKeys, msg) + ret0, _ := ret[0].(bool) + return ret0 +} + +// Eth2FastAggregateVerify indicates an expected call of Eth2FastAggregateVerify. +func (mr *MockSignatureMockRecorder) Eth2FastAggregateVerify(pubKeys, msg interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Eth2FastAggregateVerify", reflect.TypeOf((*MockSignature)(nil).Eth2FastAggregateVerify), pubKeys, msg) +} + +// FastAggregateVerify mocks base method. +func (m *MockSignature) FastAggregateVerify(pubKeys []common.PublicKey, msg [32]byte) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FastAggregateVerify", pubKeys, msg) + ret0, _ := ret[0].(bool) + return ret0 +} + +// FastAggregateVerify indicates an expected call of FastAggregateVerify. +func (mr *MockSignatureMockRecorder) FastAggregateVerify(pubKeys, msg interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FastAggregateVerify", reflect.TypeOf((*MockSignature)(nil).FastAggregateVerify), pubKeys, msg) +} + +// Marshal mocks base method. +func (m *MockSignature) Marshal() []byte { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Marshal") + ret0, _ := ret[0].([]byte) + return ret0 +} + +// Marshal indicates an expected call of Marshal. +func (mr *MockSignatureMockRecorder) Marshal() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Marshal", reflect.TypeOf((*MockSignature)(nil).Marshal)) +} + +// Verify mocks base method. +func (m *MockSignature) Verify(pubKey common.PublicKey, msg []byte) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Verify", pubKey, msg) + ret0, _ := ret[0].(bool) + return ret0 +} + +// Verify indicates an expected call of Verify. +func (mr *MockSignatureMockRecorder) Verify(pubKey, msg interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Verify", reflect.TypeOf((*MockSignature)(nil).Verify), pubKey, msg) +} diff --git a/crypto/bls/constants.go b/crypto/bls/constants.go new file mode 100644 index 0000000000..f66aa5517a --- /dev/null +++ b/crypto/bls/constants.go @@ -0,0 +1,7 @@ +package bls + +// DomainByteLength length of domain byte array. +const DomainByteLength = 4 + +// CurveOrder for the BLS12-381 curve. +const CurveOrder = "52435875175126190479447740508185965837690552500527637822603658699938581184513" diff --git a/crypto/bls/error.go b/crypto/bls/error.go new file mode 100644 index 0000000000..4875668c6d --- /dev/null +++ b/crypto/bls/error.go @@ -0,0 +1 @@ +package bls diff --git a/crypto/bls/herumi/init.go b/crypto/bls/herumi/init.go new file mode 100644 index 0000000000..9afa76ab5e --- /dev/null +++ b/crypto/bls/herumi/init.go @@ -0,0 +1,16 @@ +package herumi + +import "github.com/herumi/bls-eth-go-binary/bls" + +// HerumiInit allows the required curve orders and appropriate sub-groups to be initialized. +func HerumiInit() { + if err := bls.Init(bls.BLS12_381); err != nil { + panic(err) + } + if err := bls.SetETHmode(bls.EthModeDraft07); err != nil { + panic(err) + } + // Check subgroup order for pubkeys and signatures. + bls.VerifyPublicKeyOrder(true) + bls.VerifySignatureOrder(true) +} diff --git a/crypto/bls/interface.go b/crypto/bls/interface.go new file mode 100644 index 0000000000..913ba0529e --- /dev/null +++ b/crypto/bls/interface.go @@ -0,0 +1,14 @@ +package bls + +import ( + "github.com/ethereum/go-ethereum/crypto/bls/common" +) + +// PublicKey represents a BLS public key. +type PublicKey = common.PublicKey + +// SecretKey represents a BLS secret or private key. +type SecretKey = common.SecretKey + +// Signature represents a BLS signature. +type Signature = common.Signature diff --git a/crypto/bls/signature_batch.go b/crypto/bls/signature_batch.go new file mode 100644 index 0000000000..526d0c9430 --- /dev/null +++ b/crypto/bls/signature_batch.go @@ -0,0 +1,204 @@ +package bls + +import ( + "encoding/hex" + "fmt" + + "github.com/pkg/errors" +) + +// AggregatedSignature represents aggregated signature produced by AggregateBatch() +const AggregatedSignature = "bls aggregated signature" + +// SignatureBatch refers to the defined set of +// signatures and its respective public keys and +// messages required to verify it. +type SignatureBatch struct { + Signatures [][]byte + PublicKeys []PublicKey + Messages [][32]byte + Descriptions []string +} + +// NewSet constructs an empty signature batch object. +func NewSet() *SignatureBatch { + return &SignatureBatch{ + Signatures: [][]byte{}, + PublicKeys: []PublicKey{}, + Messages: [][32]byte{}, + Descriptions: []string{}, + } +} + +// Join merges the provided signature batch to out current one. +func (s *SignatureBatch) Join(set *SignatureBatch) *SignatureBatch { + s.Signatures = append(s.Signatures, set.Signatures...) + s.PublicKeys = append(s.PublicKeys, set.PublicKeys...) + s.Messages = append(s.Messages, set.Messages...) + s.Descriptions = append(s.Descriptions, set.Descriptions...) + return s +} + +// Verify the current signature batch using the batch verify algorithm. +func (s *SignatureBatch) Verify() (bool, error) { + return VerifyMultipleSignatures(s.Signatures, s.Messages, s.PublicKeys) +} + +// VerifyVerbosely verifies signatures as a whole at first, if fails, fallback +// to verify each single signature to identify invalid ones. +func (s *SignatureBatch) VerifyVerbosely() (bool, error) { + valid, err := s.Verify() + if err != nil || valid { + return valid, err + } + + // if signature batch is invalid, we then verify signatures one by one. + + errmsg := "some signatures are invalid. details:" + for i := 0; i < len(s.Signatures); i++ { + sig := s.Signatures[i] + msg := s.Messages[i] + pubKey := s.PublicKeys[i] + + valid, err := VerifySignature(sig, msg, pubKey) + if !valid { + desc := s.Descriptions[i] + if err != nil { + errmsg += fmt.Sprintf("\nsignature '%s' is invalid."+ + " signature: 0x%s, public key: 0x%s, message: 0x%v, error: %v", + desc, hex.EncodeToString(sig), hex.EncodeToString(pubKey.Marshal()), + hex.EncodeToString(msg[:]), err) + } else { + errmsg += fmt.Sprintf("\nsignature '%s' is invalid."+ + " signature: 0x%s, public key: 0x%s, message: 0x%v", + desc, hex.EncodeToString(sig), hex.EncodeToString(pubKey.Marshal()), + hex.EncodeToString(msg[:])) + } + } + } + + return false, errors.Errorf(errmsg) +} + +// Copy the attached signature batch and return it +// to the caller. +func (s *SignatureBatch) Copy() *SignatureBatch { + signatures := make([][]byte, len(s.Signatures)) + pubkeys := make([]PublicKey, len(s.PublicKeys)) + messages := make([][32]byte, len(s.Messages)) + descriptions := make([]string, len(s.Descriptions)) + for i := range s.Signatures { + sig := make([]byte, len(s.Signatures[i])) + copy(sig, s.Signatures[i]) + signatures[i] = sig + } + for i := range s.PublicKeys { + pubkeys[i] = s.PublicKeys[i].Copy() + } + for i := range s.Messages { + copy(messages[i][:], s.Messages[i][:]) + } + copy(descriptions, s.Descriptions) + return &SignatureBatch{ + Signatures: signatures, + PublicKeys: pubkeys, + Messages: messages, + Descriptions: descriptions, + } +} + +// RemoveDuplicates removes duplicate signature sets from the signature batch. +func (s *SignatureBatch) RemoveDuplicates() (int, *SignatureBatch, error) { + if len(s.Signatures) == 0 || len(s.PublicKeys) == 0 || len(s.Messages) == 0 { + return 0, s, nil + } + if len(s.Signatures) != len(s.PublicKeys) || len(s.Signatures) != len(s.Messages) { + return 0, s, errors.Errorf("mismatch number of signatures, publickeys and messages in signature batch. "+ + "Signatures %d, Public Keys %d , Messages %d", s.Signatures, s.PublicKeys, s.Messages) + } + sigMap := make(map[string]int) + duplicateSet := make(map[int]bool) + for i := 0; i < len(s.Signatures); i++ { + if sigIdx, ok := sigMap[string(s.Signatures[i])]; ok { + if s.PublicKeys[sigIdx].Equals(s.PublicKeys[i]) && + s.Messages[sigIdx] == s.Messages[i] { + duplicateSet[i] = true + continue + } + } + sigMap[string(s.Signatures[i])] = i + } + + sigs := s.Signatures[:0] + pubs := s.PublicKeys[:0] + msgs := s.Messages[:0] + descs := s.Descriptions[:0] + + for i := 0; i < len(s.Signatures); i++ { + if duplicateSet[i] { + continue + } + sigs = append(sigs, s.Signatures[i]) + pubs = append(pubs, s.PublicKeys[i]) + msgs = append(msgs, s.Messages[i]) + descs = append(descs, s.Descriptions[i]) + } + + s.Signatures = sigs + s.PublicKeys = pubs + s.Messages = msgs + s.Descriptions = descs + + return len(duplicateSet), s, nil +} + +// AggregateBatch aggregates common messages in the provided batch to +// reduce the number of pairings required when we finally verify the +// whole batch. +func (s *SignatureBatch) AggregateBatch() (*SignatureBatch, error) { + if len(s.Signatures) != len(s.PublicKeys) || len(s.Signatures) != len(s.Messages) || len(s.Signatures) != len(s.Descriptions) { + return s, errors.Errorf("mismatch number of signatures, publickeys, messages and descriptions in signature batch. "+ + "Signatures %d, Public Keys %d , Messages %d, Descriptions %d", len(s.Signatures), len(s.PublicKeys), len(s.Messages), len(s.Descriptions)) + } + if len(s.Signatures) == 0 { + return s, nil + } + msgMap := make(map[[32]byte]*SignatureBatch) + + for i := 0; i < len(s.Messages); i++ { + currMsg := s.Messages[i] + currBatch, ok := msgMap[currMsg] + if ok { + currBatch.Signatures = append(currBatch.Signatures, s.Signatures[i]) + currBatch.Messages = append(currBatch.Messages, s.Messages[i]) + currBatch.PublicKeys = append(currBatch.PublicKeys, s.PublicKeys[i]) + currBatch.Descriptions = append(currBatch.Descriptions, s.Descriptions[i]) + continue + } + currBatch = &SignatureBatch{ + Signatures: [][]byte{s.Signatures[i]}, + Messages: [][32]byte{s.Messages[i]}, + PublicKeys: []PublicKey{s.PublicKeys[i]}, + Descriptions: []string{s.Descriptions[i]}, + } + msgMap[currMsg] = currBatch + } + newSt := NewSet() + for rt, b := range msgMap { + if len(b.PublicKeys) > 1 { + aggPub := AggregateMultiplePubkeys(b.PublicKeys) + aggSig, err := AggregateCompressedSignatures(b.Signatures) + if err != nil { + return nil, err + } + copiedRt := rt + b.PublicKeys = []PublicKey{aggPub} + b.Signatures = [][]byte{aggSig.Marshal()} + b.Messages = [][32]byte{copiedRt} + b.Descriptions = []string{AggregatedSignature} + } + newObj := *b + newSt = newSt.Join(&newObj) + } + return newSt, nil +} diff --git a/crypto/bls/signature_batch_test.go b/crypto/bls/signature_batch_test.go new file mode 100644 index 0000000000..d073e1fa78 --- /dev/null +++ b/crypto/bls/signature_batch_test.go @@ -0,0 +1,744 @@ +package bls + +import ( + "bytes" + "fmt" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "reflect" + "sort" + "testing" + + "github.com/ethereum/go-ethereum/crypto/bls/common" +) + +const TestSignature = "test signature" + +func TestCopySignatureSet(t *testing.T) { + t.Run("blst", func(t *testing.T) { + key, err := RandKey() + assert.NoError(t, err) + key2, err := RandKey() + assert.NoError(t, err) + key3, err := RandKey() + assert.NoError(t, err) + + message := [32]byte{'C', 'D'} + message2 := [32]byte{'E', 'F'} + message3 := [32]byte{'H', 'I'} + + sig := key.Sign(message[:]) + sig2 := key2.Sign(message2[:]) + sig3 := key3.Sign(message3[:]) + + set := &SignatureBatch{ + Signatures: [][]byte{sig.Marshal()}, + PublicKeys: []PublicKey{key.PublicKey()}, + Messages: [][32]byte{message}, + Descriptions: createDescriptions(1), + } + set2 := &SignatureBatch{ + Signatures: [][]byte{sig2.Marshal()}, + PublicKeys: []PublicKey{key.PublicKey()}, + Messages: [][32]byte{message}, + Descriptions: createDescriptions(1), + } + set3 := &SignatureBatch{ + Signatures: [][]byte{sig3.Marshal()}, + PublicKeys: []PublicKey{key.PublicKey()}, + Messages: [][32]byte{message}, + Descriptions: createDescriptions(1), + } + aggSet := set.Join(set2).Join(set3) + aggSet2 := aggSet.Copy() + + assert.Equal(t, aggSet, aggSet2) + }) +} + +func TestVerifyVerbosely_AllSignaturesValid(t *testing.T) { + set := NewValidSignatureSet(t, "good", 3) + valid, err := set.VerifyVerbosely() + assert.NoError(t, err) + assert.Equal(t, true, valid, "SignatureSet is expected to be valid") +} + +func TestVerifyVerbosely_SomeSignaturesInvalid(t *testing.T) { + goodSet := NewValidSignatureSet(t, "good", 3) + badSet := NewInvalidSignatureSet(t, "bad", 3, false) + set := NewSet().Join(goodSet).Join(badSet) + valid, err := set.VerifyVerbosely() + assert.Equal(t, false, valid, "SignatureSet is expected to be invalid") + assert.Contains(t, err.Error(), "signature 'signature of bad0' is invalid") + assert.Contains(t, err.Error(), "signature 'signature of bad1' is invalid") + assert.Contains(t, err.Error(), "signature 'signature of bad2' is invalid") + assert.NotContains(t, err.Error(), "signature 'signature of good0' is invalid") + assert.NotContains(t, err.Error(), "signature 'signature of good1' is invalid") + assert.NotContains(t, err.Error(), "signature 'signature of good2' is invalid") +} + +func TestVerifyVerbosely_VerificationThrowsError(t *testing.T) { + goodSet := NewValidSignatureSet(t, "good", 1) + badSet := NewInvalidSignatureSet(t, "bad", 1, true) + set := NewSet().Join(goodSet).Join(badSet) + valid, err := set.VerifyVerbosely() + assert.Equal(t, false, valid, "SignatureSet is expected to be invalid") + assert.Contains(t, err.Error(), "signature 'signature of bad0' is invalid") + assert.Contains(t, err.Error(), "error: could not unmarshal bytes into signature") + assert.NotContains(t, err.Error(), "signature 'signature of good0' is invalid") +} + +func TestSignatureBatch_RemoveDuplicates(t *testing.T) { + var keys []SecretKey + for i := 0; i < 100; i++ { + key, err := RandKey() + assert.NoError(t, err) + keys = append(keys, key) + } + tests := []struct { + name string + batchCreator func() (input *SignatureBatch, output *SignatureBatch) + want int + }{ + { + name: "empty batch", + batchCreator: func() (*SignatureBatch, *SignatureBatch) { + return &SignatureBatch{}, &SignatureBatch{} + }, + want: 0, + }, + { + name: "valid duplicates in batch", + batchCreator: func() (*SignatureBatch, *SignatureBatch) { + chosenKeys := keys[:20] + + msg := [32]byte{'r', 'a', 'n', 'd', 'o', 'm'} + var signatures [][]byte + var messages [][32]byte + var pubs []PublicKey + for _, k := range chosenKeys { + s := k.Sign(msg[:]) + signatures = append(signatures, s.Marshal()) + messages = append(messages, msg) + pubs = append(pubs, k.PublicKey()) + } + allSigs := append(signatures, signatures...) + allPubs := append(pubs, pubs...) + allMsgs := append(messages, messages...) + return &SignatureBatch{ + Signatures: allSigs, + PublicKeys: allPubs, + Messages: allMsgs, + Descriptions: createDescriptions(len(allMsgs)), + }, &SignatureBatch{ + Signatures: signatures, + PublicKeys: pubs, + Messages: messages, + Descriptions: createDescriptions(len(allMsgs)), + } + }, + want: 20, + }, + { + name: "valid duplicates in batch with multiple messages", + batchCreator: func() (*SignatureBatch, *SignatureBatch) { + chosenKeys := keys[:30] + + msg := [32]byte{'r', 'a', 'n', 'd', 'o', 'm'} + msg1 := [32]byte{'r', 'a', 'n', 'd', 'o', 'm', '1'} + msg2 := [32]byte{'r', 'a', 'n', 'd', 'o', 'm', '2'} + var signatures [][]byte + var messages [][32]byte + var pubs []PublicKey + for _, k := range chosenKeys[:10] { + s := k.Sign(msg[:]) + signatures = append(signatures, s.Marshal()) + messages = append(messages, msg) + pubs = append(pubs, k.PublicKey()) + } + for _, k := range chosenKeys[10:20] { + s := k.Sign(msg1[:]) + signatures = append(signatures, s.Marshal()) + messages = append(messages, msg1) + pubs = append(pubs, k.PublicKey()) + } + for _, k := range chosenKeys[20:30] { + s := k.Sign(msg2[:]) + signatures = append(signatures, s.Marshal()) + messages = append(messages, msg2) + pubs = append(pubs, k.PublicKey()) + } + allSigs := append(signatures, signatures...) + allPubs := append(pubs, pubs...) + allMsgs := append(messages, messages...) + return &SignatureBatch{ + Signatures: allSigs, + PublicKeys: allPubs, + Messages: allMsgs, + Descriptions: createDescriptions(len(allMsgs)), + }, &SignatureBatch{ + Signatures: signatures, + PublicKeys: pubs, + Messages: messages, + Descriptions: createDescriptions(len(allMsgs)), + } + }, + want: 30, + }, + { + name: "no duplicates in batch with multiple messages", + batchCreator: func() (*SignatureBatch, *SignatureBatch) { + chosenKeys := keys[:30] + + msg := [32]byte{'r', 'a', 'n', 'd', 'o', 'm'} + msg1 := [32]byte{'r', 'a', 'n', 'd', 'o', 'm', '1'} + msg2 := [32]byte{'r', 'a', 'n', 'd', 'o', 'm', '2'} + var signatures [][]byte + var messages [][32]byte + var pubs []PublicKey + for _, k := range chosenKeys[:10] { + s := k.Sign(msg[:]) + signatures = append(signatures, s.Marshal()) + messages = append(messages, msg) + pubs = append(pubs, k.PublicKey()) + } + for _, k := range chosenKeys[10:20] { + s := k.Sign(msg1[:]) + signatures = append(signatures, s.Marshal()) + messages = append(messages, msg1) + pubs = append(pubs, k.PublicKey()) + } + for _, k := range chosenKeys[20:30] { + s := k.Sign(msg2[:]) + signatures = append(signatures, s.Marshal()) + messages = append(messages, msg2) + pubs = append(pubs, k.PublicKey()) + } + return &SignatureBatch{ + Signatures: signatures, + PublicKeys: pubs, + Messages: messages, + Descriptions: createDescriptions(len(messages)), + }, &SignatureBatch{ + Signatures: signatures, + PublicKeys: pubs, + Messages: messages, + Descriptions: createDescriptions(len(messages)), + } + }, + want: 0, + }, + { + name: "valid duplicates and invalid duplicates in batch with multiple messages", + batchCreator: func() (*SignatureBatch, *SignatureBatch) { + chosenKeys := keys[:30] + + msg := [32]byte{'r', 'a', 'n', 'd', 'o', 'm'} + msg1 := [32]byte{'r', 'a', 'n', 'd', 'o', 'm', '1'} + msg2 := [32]byte{'r', 'a', 'n', 'd', 'o', 'm', '2'} + var signatures [][]byte + var messages [][32]byte + var pubs []PublicKey + for _, k := range chosenKeys[:10] { + s := k.Sign(msg[:]) + signatures = append(signatures, s.Marshal()) + messages = append(messages, msg) + pubs = append(pubs, k.PublicKey()) + } + for _, k := range chosenKeys[10:20] { + s := k.Sign(msg1[:]) + signatures = append(signatures, s.Marshal()) + messages = append(messages, msg1) + pubs = append(pubs, k.PublicKey()) + } + for _, k := range chosenKeys[20:30] { + s := k.Sign(msg2[:]) + signatures = append(signatures, s.Marshal()) + messages = append(messages, msg2) + pubs = append(pubs, k.PublicKey()) + } + allSigs := append(signatures, signatures...) + // Make it a non-unique entry + allSigs[10] = make([]byte, 96) + allPubs := append(pubs, pubs...) + allMsgs := append(messages, messages...) + // Insert it back at the end + signatures = append(signatures, signatures[10]) + pubs = append(pubs, pubs[10]) + messages = append(messages, messages[10]) + // Zero out to expected result + signatures[10] = make([]byte, 96) + return &SignatureBatch{ + Signatures: allSigs, + PublicKeys: allPubs, + Messages: allMsgs, + Descriptions: createDescriptions(len(allMsgs)), + }, &SignatureBatch{ + Signatures: signatures, + PublicKeys: pubs, + Messages: messages, + Descriptions: createDescriptions(len(allMsgs)), + } + }, + want: 29, + }, + { + name: "valid duplicates and invalid duplicates with signature,pubkey,message in batch with multiple messages", + batchCreator: func() (*SignatureBatch, *SignatureBatch) { + chosenKeys := keys[:30] + + msg := [32]byte{'r', 'a', 'n', 'd', 'o', 'm'} + msg1 := [32]byte{'r', 'a', 'n', 'd', 'o', 'm', '1'} + msg2 := [32]byte{'r', 'a', 'n', 'd', 'o', 'm', '2'} + var signatures [][]byte + var messages [][32]byte + var pubs []PublicKey + for _, k := range chosenKeys[:10] { + s := k.Sign(msg[:]) + signatures = append(signatures, s.Marshal()) + messages = append(messages, msg) + pubs = append(pubs, k.PublicKey()) + } + for _, k := range chosenKeys[10:20] { + s := k.Sign(msg1[:]) + signatures = append(signatures, s.Marshal()) + messages = append(messages, msg1) + pubs = append(pubs, k.PublicKey()) + } + for _, k := range chosenKeys[20:30] { + s := k.Sign(msg2[:]) + signatures = append(signatures, s.Marshal()) + messages = append(messages, msg2) + pubs = append(pubs, k.PublicKey()) + } + allSigs := append(signatures, signatures...) + // Make it a non-unique entry + allSigs[10] = make([]byte, 96) + + allPubs := append(pubs, pubs...) + allPubs[20] = keys[len(keys)-1].PublicKey() + + allMsgs := append(messages, messages...) + allMsgs[29] = [32]byte{'j', 'u', 'n', 'k'} + + // Insert it back at the end + signatures = append(signatures, signatures[10]) + pubs = append(pubs, pubs[10]) + messages = append(messages, messages[10]) + // Zero out to expected result + signatures[10] = make([]byte, 96) + + // Insert it back at the end + signatures = append(signatures, signatures[20]) + pubs = append(pubs, pubs[20]) + messages = append(messages, messages[20]) + // Zero out to expected result + pubs[20] = keys[len(keys)-1].PublicKey() + + // Insert it back at the end + signatures = append(signatures, signatures[29]) + pubs = append(pubs, pubs[29]) + messages = append(messages, messages[29]) + messages[29] = [32]byte{'j', 'u', 'n', 'k'} + + return &SignatureBatch{ + Signatures: allSigs, + PublicKeys: allPubs, + Messages: allMsgs, + Descriptions: createDescriptions(len(allMsgs)), + }, &SignatureBatch{ + Signatures: signatures, + PublicKeys: pubs, + Messages: messages, + Descriptions: createDescriptions(len(messages)), + } + }, + want: 27, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + input, output := tt.batchCreator() + num, res, err := input.RemoveDuplicates() + assert.NoError(t, err) + if num != tt.want { + t.Errorf("RemoveDuplicates() got = %v, want %v", num, tt.want) + } + if !reflect.DeepEqual(res.Signatures, output.Signatures) { + t.Errorf("RemoveDuplicates() Signatures output = %v, want %v", res.Signatures, output.Signatures) + } + if !reflect.DeepEqual(res.PublicKeys, output.PublicKeys) { + t.Errorf("RemoveDuplicates() Publickeys output = %v, want %v", res.PublicKeys, output.PublicKeys) + } + if !reflect.DeepEqual(res.Messages, output.Messages) { + t.Errorf("RemoveDuplicates() Messages output = %v, want %v", res.Messages, output.Messages) + } + }) + } +} + +func TestSignatureBatch_AggregateBatch(t *testing.T) { + var keys []SecretKey + for i := 0; i < 100; i++ { + key, err := RandKey() + assert.NoError(t, err) + keys = append(keys, key) + } + tests := []struct { + name string + batchCreator func(t *testing.T) (input *SignatureBatch, output *SignatureBatch) + wantErr bool + }{ + { + name: "empty batch", + batchCreator: func(t *testing.T) (*SignatureBatch, *SignatureBatch) { + return &SignatureBatch{Signatures: nil, Messages: nil, PublicKeys: nil, Descriptions: nil}, + &SignatureBatch{Signatures: nil, Messages: nil, PublicKeys: nil, Descriptions: nil} + }, + wantErr: false, + }, + { + name: "mismatch number of signatures and messages in batch", + batchCreator: func(t *testing.T) (*SignatureBatch, *SignatureBatch) { + key1 := keys[0] + key2 := keys[1] + msg := [32]byte{'r', 'a', 'n', 'd', 'o', 'm'} + sig1 := key1.Sign(msg[:]) + sig2 := key2.Sign(msg[:]) + signatures := [][]byte{sig1.Marshal(), sig2.Marshal()} + pubs := []common.PublicKey{key1.PublicKey(), key2.PublicKey()} + messages := [][32]byte{msg} + descs := createDescriptions(2) + return &SignatureBatch{ + Signatures: signatures, + PublicKeys: pubs, + Messages: messages, + Descriptions: descs, + }, &SignatureBatch{ + Signatures: signatures, + PublicKeys: pubs, + Messages: messages, + Descriptions: descs, + } + }, + wantErr: true, + }, + { + name: "valid signatures in batch", + batchCreator: func(t *testing.T) (*SignatureBatch, *SignatureBatch) { + chosenKeys := keys[:20] + + msg := [32]byte{'r', 'a', 'n', 'd', 'o', 'm'} + var signatures [][]byte + var messages [][32]byte + var pubs []PublicKey + for _, k := range chosenKeys { + s := k.Sign(msg[:]) + signatures = append(signatures, s.Marshal()) + messages = append(messages, msg) + pubs = append(pubs, k.PublicKey()) + } + aggSig, err := AggregateCompressedSignatures(signatures) + assert.NoError(t, err) + aggPub := AggregateMultiplePubkeys(pubs) + return &SignatureBatch{ + Signatures: signatures, + PublicKeys: pubs, + Messages: messages, + Descriptions: createDescriptions(len(messages)), + }, &SignatureBatch{ + Signatures: [][]byte{aggSig.Marshal()}, + PublicKeys: []PublicKey{aggPub}, + Messages: [][32]byte{msg}, + Descriptions: createDescriptions(1, AggregatedSignature), + } + }, + wantErr: false, + }, + { + name: "invalid signatures in batch", + batchCreator: func(t *testing.T) (*SignatureBatch, *SignatureBatch) { + chosenKeys := keys[:20] + + msg := [32]byte{'r', 'a', 'n', 'd', 'o', 'm'} + var signatures [][]byte + var messages [][32]byte + var pubs []PublicKey + for _, k := range chosenKeys { + s := k.Sign(msg[:]) + signatures = append(signatures, s.Marshal()) + messages = append(messages, msg) + pubs = append(pubs, k.PublicKey()) + } + signatures[10] = make([]byte, 96) + return &SignatureBatch{ + Signatures: signatures, + PublicKeys: pubs, + Messages: messages, + Descriptions: createDescriptions(len(messages)), + }, nil + }, + wantErr: true, + }, + { + name: "valid aggregates in batch with multiple messages", + batchCreator: func(t *testing.T) (*SignatureBatch, *SignatureBatch) { + chosenKeys := keys[:30] + + msg := [32]byte{'r', 'a', 'n', 'd', 'o', 'm'} + msg1 := [32]byte{'r', 'a', 'n', 'd', 'o', 'm', '1'} + msg2 := [32]byte{'r', 'a', 'n', 'd', 'o', 'm', '2'} + var signatures [][]byte + var messages [][32]byte + var pubs []PublicKey + for _, k := range chosenKeys[:10] { + s := k.Sign(msg[:]) + signatures = append(signatures, s.Marshal()) + messages = append(messages, msg) + pubs = append(pubs, k.PublicKey()) + } + for _, k := range chosenKeys[10:20] { + s := k.Sign(msg1[:]) + signatures = append(signatures, s.Marshal()) + messages = append(messages, msg1) + pubs = append(pubs, k.PublicKey()) + } + for _, k := range chosenKeys[20:30] { + s := k.Sign(msg2[:]) + signatures = append(signatures, s.Marshal()) + messages = append(messages, msg2) + pubs = append(pubs, k.PublicKey()) + } + aggSig1, err := AggregateCompressedSignatures(signatures[:10]) + assert.NoError(t, err) + aggSig2, err := AggregateCompressedSignatures(signatures[10:20]) + assert.NoError(t, err) + aggSig3, err := AggregateCompressedSignatures(signatures[20:30]) + assert.NoError(t, err) + aggPub1 := AggregateMultiplePubkeys(pubs[:10]) + aggPub2 := AggregateMultiplePubkeys(pubs[10:20]) + aggPub3 := AggregateMultiplePubkeys(pubs[20:30]) + return &SignatureBatch{ + Signatures: signatures, + PublicKeys: pubs, + Messages: messages, + Descriptions: createDescriptions(len(messages)), + }, &SignatureBatch{ + Signatures: [][]byte{aggSig1.Marshal(), aggSig2.Marshal(), aggSig3.Marshal()}, + PublicKeys: []PublicKey{aggPub1, aggPub2, aggPub3}, + Messages: [][32]byte{msg, msg1, msg2}, + Descriptions: createDescriptions(3, AggregatedSignature), + } + }, + wantErr: false, + }, + { + name: "common and uncommon messages in batch with multiple messages", + batchCreator: func(t *testing.T) (*SignatureBatch, *SignatureBatch) { + chosenKeys := keys[:30] + + msg := [32]byte{'r', 'a', 'n', 'd', 'o', 'm'} + msg1 := [32]byte{'r', 'a', 'n', 'd', 'o', 'm', '1'} + msg2 := [32]byte{'r', 'a', 'n', 'd', 'o', 'm', '2'} + var signatures [][]byte + var messages [][32]byte + var pubs []PublicKey + for _, k := range chosenKeys[:10] { + s := k.Sign(msg[:]) + signatures = append(signatures, s.Marshal()) + messages = append(messages, msg) + pubs = append(pubs, k.PublicKey()) + } + for _, k := range chosenKeys[10:20] { + s := k.Sign(msg1[:]) + signatures = append(signatures, s.Marshal()) + messages = append(messages, msg1) + pubs = append(pubs, k.PublicKey()) + } + for _, k := range chosenKeys[20:30] { + s := k.Sign(msg2[:]) + signatures = append(signatures, s.Marshal()) + messages = append(messages, msg2) + pubs = append(pubs, k.PublicKey()) + } + // Set a custom message + messages[5][31] ^= byte(100) + messages[15][31] ^= byte(100) + messages[25][31] ^= byte(100) + + var newSigs [][]byte + newSigs = append(newSigs, signatures[:5]...) + newSigs = append(newSigs, signatures[6:10]...) + + aggSig1, err := AggregateCompressedSignatures(newSigs) + assert.NoError(t, err) + + newSigs = [][]byte{} + newSigs = append(newSigs, signatures[10:15]...) + newSigs = append(newSigs, signatures[16:20]...) + aggSig2, err := AggregateCompressedSignatures(newSigs) + assert.NoError(t, err) + + newSigs = [][]byte{} + newSigs = append(newSigs, signatures[20:25]...) + newSigs = append(newSigs, signatures[26:30]...) + aggSig3, err := AggregateCompressedSignatures(newSigs) + assert.NoError(t, err) + + var newPubs []PublicKey + newPubs = append(newPubs, pubs[:5]...) + newPubs = append(newPubs, pubs[6:10]...) + + aggPub1 := AggregateMultiplePubkeys(newPubs) + + newPubs = []PublicKey{} + newPubs = append(newPubs, pubs[10:15]...) + newPubs = append(newPubs, pubs[16:20]...) + aggPub2 := AggregateMultiplePubkeys(newPubs) + + newPubs = []PublicKey{} + newPubs = append(newPubs, pubs[20:25]...) + newPubs = append(newPubs, pubs[26:30]...) + aggPub3 := AggregateMultiplePubkeys(newPubs) + + return &SignatureBatch{ + Signatures: signatures, + PublicKeys: pubs, + Messages: messages, + Descriptions: createDescriptions(len(messages)), + }, &SignatureBatch{ + Signatures: [][]byte{aggSig1.Marshal(), signatures[5], aggSig2.Marshal(), signatures[15], aggSig3.Marshal(), signatures[25]}, + PublicKeys: []PublicKey{aggPub1, pubs[5], aggPub2, pubs[15], aggPub3, pubs[25]}, + Messages: [][32]byte{msg, messages[5], msg1, messages[15], msg2, messages[25]}, + Descriptions: []string{AggregatedSignature, TestSignature, AggregatedSignature, TestSignature, AggregatedSignature, TestSignature}, + } + }, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + input, output := tt.batchCreator(t) + got, err := input.AggregateBatch() + if (err != nil) != tt.wantErr { + t.Errorf("AggregateBatch() error = %v, wantErr %v", err, tt.wantErr) + return + } + if tt.wantErr { + return + } + got = sortSet(got) + output = sortSet(output) + + if !reflect.DeepEqual(got.Signatures, output.Signatures) { + t.Errorf("AggregateBatch() Signatures got = %v, want %v", got.Signatures, output.Signatures) + } + if !reflect.DeepEqual(got.PublicKeys, output.PublicKeys) { + t.Errorf("AggregateBatch() PublicKeys got = %v, want %v", got.PublicKeys, output.PublicKeys) + } + if !reflect.DeepEqual(got.Messages, output.Messages) { + t.Errorf("AggregateBatch() Messages got = %v, want %v", got.Messages, output.Messages) + } + if !reflect.DeepEqual(got.Descriptions, output.Descriptions) { + t.Errorf("AggregateBatch() Descriptions got = %v, want %v", got.Descriptions, output.Descriptions) + } + }) + } +} + +func NewValidSignatureSet(t *testing.T, msgBody string, num int) *SignatureBatch { + set := &SignatureBatch{ + Signatures: make([][]byte, num), + PublicKeys: make([]common.PublicKey, num), + Messages: make([][32]byte, num), + Descriptions: make([]string, num), + } + + for i := 0; i < num; i++ { + priv, err := RandKey() + require.NoError(t, err) + pubkey := priv.PublicKey() + msg := messageBytes(fmt.Sprintf("%s%d", msgBody, i)) + sig := priv.Sign(msg[:]).Marshal() + desc := fmt.Sprintf("signature of %s%d", msgBody, i) + + set.Signatures[i] = sig + set.PublicKeys[i] = pubkey + set.Messages[i] = msg + set.Descriptions[i] = desc + } + + return set +} + +func NewInvalidSignatureSet(t *testing.T, msgBody string, num int, throwErr bool) *SignatureBatch { + set := &SignatureBatch{ + Signatures: make([][]byte, num), + PublicKeys: make([]common.PublicKey, num), + Messages: make([][32]byte, num), + Descriptions: make([]string, num), + } + + for i := 0; i < num; i++ { + priv, err := RandKey() + require.NoError(t, err) + pubkey := priv.PublicKey() + msg := messageBytes(fmt.Sprintf("%s%d", msgBody, i)) + var sig []byte + if throwErr { + sig = make([]byte, 96) + } else { + badMsg := messageBytes("badmsg") + sig = priv.Sign(badMsg[:]).Marshal() + } + desc := fmt.Sprintf("signature of %s%d", msgBody, i) + + set.Signatures[i] = sig + set.PublicKeys[i] = pubkey + set.Messages[i] = msg + set.Descriptions[i] = desc + } + + return set +} + +func messageBytes(message string) [32]byte { + var bytes [32]byte + copy(bytes[:], []byte(message)) + return bytes +} + +func createDescriptions(length int, text ...string) []string { + desc := make([]string, length) + for i := range desc { + if len(text) > 0 { + desc[i] = text[0] + } else { + desc[i] = TestSignature + } + } + return desc +} + +func sortSet(s *SignatureBatch) *SignatureBatch { + sort.Sort(sorter{set: s}) + return s +} + +type sorter struct { + set *SignatureBatch +} + +func (s sorter) Len() int { + return len(s.set.Messages) +} + +func (s sorter) Swap(i, j int) { + s.set.Signatures[i], s.set.Signatures[j] = s.set.Signatures[j], s.set.Signatures[i] + s.set.PublicKeys[i], s.set.PublicKeys[j] = s.set.PublicKeys[j], s.set.PublicKeys[i] + s.set.Messages[i], s.set.Messages[j] = s.set.Messages[j], s.set.Messages[i] +} + +func (s sorter) Less(i, j int) bool { + return bytes.Compare(s.set.Messages[i][:], s.set.Messages[j][:]) == -1 +} diff --git a/crypto/rand/rand.go b/crypto/rand/rand.go new file mode 100644 index 0000000000..10360559b0 --- /dev/null +++ b/crypto/rand/rand.go @@ -0,0 +1,86 @@ +/* +Package rand defines methods of obtaining random number generators. + +One is expected to use randomness from this package only, without introducing any other packages. +This limits the scope of code that needs to be hardened. + +There are two modes, one for deterministic and another non-deterministic randomness: +1. If deterministic pseudo-random generator is enough, use: + + import "github.com/ethereum/go-ethereum/crypto/rand" + randGen := rand.NewDeterministicGenerator() + randGen.Intn(32) // or any other func defined in math.rand API + + In this mode, only seed is generated using cryptographically secure source (crypto/rand). So, + once seed is obtained, and generator is seeded, the next generations are deterministic, thus fast. + However given that we only seed this 63 bits from crypto/rand and use math/rand to generate the outputs, + this method is not cryptographically secure. This is directly stated in the math/rand package, + https://github.com/golang/go/blob/release-branch.go1.17/src/math/rand/rand.go#L15. For any security + sensitive work this particular generator is NOT to be used. + +2. For cryptographically secure non-deterministic mode (CSPRNG), use: + + import "github.com/ethereum/go-ethereum/crypto/rand" + randGen := rand.NewGenerator() + randGen.Intn(32) // or any other func defined in math.rand API + + Again, any of the functions from `math/rand` can be used, however, they all use custom source + of randomness (crypto/rand), on every step. This makes randomness non-deterministic. However, + you take a performance hit -- as it is an order of magnitude slower. +*/ +package rand + +import ( + "crypto/rand" + "encoding/binary" + mrand "math/rand" + "sync" +) + +type source struct{} + +var lock sync.RWMutex +var _ mrand.Source64 = (*source)(nil) // #nosec G404 -- This ensures we meet the interface + +// Seed does nothing when crypto/rand is used as source. +func (_ *source) Seed(_ int64) {} + +// Int63 returns uniformly-distributed random (as in CSPRNG) int64 value within [0, 1<<63) range. +// Panics if random generator reader cannot return data. +func (s *source) Int63() int64 { + return int64(s.Uint64() & ^uint64(1<<63)) +} + +// Uint64 returns uniformly-distributed random (as in CSPRNG) uint64 value within [0, 1<<64) range. +// Panics if random generator reader cannot return data. +func (_ *source) Uint64() (val uint64) { + lock.RLock() + defer lock.RUnlock() + if err := binary.Read(rand.Reader, binary.BigEndian, &val); err != nil { + panic(err) + } + return +} + +// Rand is alias for underlying random generator. +type Rand = mrand.Rand // #nosec G404 + +// NewGenerator returns a new generator that uses random values from crypto/rand as a source +// (cryptographically secure random number generator). +// Panics if crypto/rand input cannot be read. +// Use it for everything where crypto secure non-deterministic randomness is required. Performance +// takes a hit, so use sparingly. +func NewGenerator() *Rand { + return mrand.New(&source{}) // #nosec G404 -- excluded +} + +// NewDeterministicGenerator returns a random generator which is only seeded with crypto/rand, +// but is deterministic otherwise (given seed, produces given results, deterministically). +// Panics if crypto/rand input cannot be read. +// Use this method for performance, where deterministic pseudo-random behaviour is enough. +// Otherwise, rely on NewGenerator(). This method is not cryptographically secure as outputs +// can be potentially predicted even without knowledge of the underlying seed. +func NewDeterministicGenerator() *Rand { + randGen := NewGenerator() + return mrand.New(mrand.NewSource(randGen.Int63())) // #nosec G404 -- excluded +} diff --git a/crypto/rand/rand_test.go b/crypto/rand/rand_test.go new file mode 100644 index 0000000000..599006def2 --- /dev/null +++ b/crypto/rand/rand_test.go @@ -0,0 +1,24 @@ +package rand + +import ( + "math/rand" + "testing" +) + +func TestNewGenerator(_ *testing.T) { + // Make sure that generation works, no panics. + randGen := NewGenerator() + _ = randGen.Int63() + _ = randGen.Uint64() + _ = randGen.Intn(32) + var _ = rand.Source64(randGen) +} + +func TestNewDeterministicGenerator(_ *testing.T) { + // Make sure that generation works, no panics. + randGen := NewDeterministicGenerator() + _ = randGen.Int63() + _ = randGen.Uint64() + _ = randGen.Intn(32) + var _ = rand.Source64(randGen) +} diff --git a/go.mod b/go.mod index 1327edb6a7..8cade89c2c 100644 --- a/go.mod +++ b/go.mod @@ -6,65 +6,64 @@ require ( github.com/Azure/azure-pipeline-go v0.2.2 // indirect github.com/Azure/azure-storage-blob-go v0.7.0 github.com/Azure/go-autorest/autorest/adal v0.8.0 // indirect - github.com/StackExchange/wmi v1.2.1 // indirect - github.com/VictoriaMetrics/fastcache v1.6.0 + github.com/VictoriaMetrics/fastcache v1.12.0 github.com/aws/aws-sdk-go-v2 v1.2.0 github.com/aws/aws-sdk-go-v2/config v1.1.1 github.com/aws/aws-sdk-go-v2/credentials v1.1.1 github.com/aws/aws-sdk-go-v2/service/route53 v1.1.1 github.com/btcsuite/btcd v0.20.1-beta - github.com/cespare/cp v0.1.0 + github.com/cespare/cp v1.1.1 github.com/cloudflare/cloudflare-go v0.14.0 github.com/consensys/gnark-crypto v0.4.1-0.20210426202927-39ac3d4b3f1f github.com/davecgh/go-spew v1.1.1 github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 - github.com/edsrzf/mmap-go v1.0.0 - github.com/fatih/color v1.7.0 + github.com/edsrzf/mmap-go v1.1.0 + github.com/fatih/color v1.9.0 github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 - github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff - github.com/go-stack/stack v1.8.0 - github.com/golang/protobuf v1.5.2 + github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 + github.com/go-stack/stack v1.8.1 + github.com/golang/protobuf v1.5.3 github.com/golang/snappy v0.0.4 - github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa - github.com/google/uuid v1.2.0 - github.com/gorilla/websocket v1.4.2 + github.com/google/gofuzz v1.2.0 + github.com/google/uuid v1.3.0 + github.com/gorilla/websocket v1.5.0 github.com/graph-gophers/graphql-go v1.3.0 github.com/hashicorp/go-bexpr v0.1.10 github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d github.com/holiman/bloomfilter/v2 v2.0.3 - github.com/holiman/uint256 v1.2.0 - github.com/huin/goupnp v1.0.2 + github.com/holiman/uint256 v1.2.1 + github.com/huin/goupnp v1.1.0 github.com/influxdata/influxdb v1.8.3 github.com/influxdata/influxdb-client-go/v2 v2.8.0 github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097 // indirect - github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458 + github.com/jackpal/go-nat-pmp v1.0.2 github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e github.com/julienschmidt/httprouter v1.3.0 - github.com/karalabe/usb v0.0.0-20211005121534-4c5740d64559 + github.com/karalabe/usb v0.0.2 github.com/kylelemons/godebug v1.1.0 // indirect - github.com/mattn/go-colorable v0.1.11 - github.com/mattn/go-isatty v0.0.14 + github.com/mattn/go-colorable v0.1.13 + github.com/mattn/go-isatty v0.0.18 github.com/naoina/go-stringutil v0.1.0 // indirect github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416 github.com/olekukonko/tablewriter v0.0.5 - github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 + github.com/peterh/liner v1.2.0 github.com/prometheus/tsdb v0.7.1 github.com/rjeczalik/notify v0.9.1 github.com/rs/cors v1.7.0 - github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible - github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4 - github.com/stretchr/testify v1.7.0 - github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 - github.com/tklauser/go-sysconf v0.3.5 // indirect - github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef - golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 - golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 - golang.org/x/sys v0.5.0 - golang.org/x/text v0.7.0 - golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba - google.golang.org/protobuf v1.27.1 // indirect + github.com/shirou/gopsutil v3.21.11+incompatible + github.com/status-im/keycard-go v0.2.0 + github.com/stretchr/testify v1.8.2 + github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d + github.com/tklauser/go-sysconf v0.3.11 // indirect + github.com/tyler-smith/go-bip39 v1.1.0 + golang.org/x/crypto v0.7.0 + golang.org/x/sync v0.1.0 + golang.org/x/sys v0.7.0 + golang.org/x/text v0.9.0 + golang.org/x/time v0.0.0-20220922220347-f3bd1da661af + google.golang.org/protobuf v1.30.0 // indirect gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce gopkg.in/urfave/cli.v1 v1.20.0 gotest.tools v2.2.0+incompatible // indirect @@ -72,8 +71,12 @@ require ( require ( github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be - github.com/klauspost/compress v1.15.1 + github.com/golang/mock v1.6.0 + github.com/herumi/bls-eth-go-binary v1.31.0 + github.com/klauspost/compress v1.16.4 + github.com/pkg/errors v0.9.1 github.com/pyroscope-io/client v0.7.2 + github.com/supranational/blst v0.3.10 ) require ( @@ -82,27 +85,25 @@ require ( github.com/aws/aws-sdk-go-v2/service/sso v1.1.1 // indirect github.com/aws/aws-sdk-go-v2/service/sts v1.1.1 // indirect github.com/aws/smithy-go v1.1.0 // indirect - github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/deepmap/oapi-codegen v1.8.2 // indirect github.com/dlclark/regexp2 v1.7.0 // indirect github.com/go-kit/kit v0.10.0 // indirect - github.com/go-ole/go-ole v1.2.5 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect - github.com/google/go-cmp v0.5.6 // indirect - github.com/google/pprof v0.0.0-20230207041349-798e818bf904 // indirect + github.com/google/pprof v0.0.0-20230405160723-4a4c7d95572b // indirect github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d // indirect - github.com/mattn/go-runewidth v0.0.9 // indirect + github.com/mattn/go-runewidth v0.0.14 // indirect github.com/mitchellh/mapstructure v1.4.1 // indirect github.com/mitchellh/pointerstructure v1.2.0 // indirect - github.com/onsi/ginkgo v1.16.5 // indirect - github.com/onsi/gomega v1.18.1 // indirect - github.com/opentracing/opentracing-go v1.1.0 // indirect - github.com/pkg/errors v0.9.1 // indirect + github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pyroscope-io/godeltaprof v0.1.2 // indirect - github.com/tklauser/numcpus v0.2.2 // indirect - golang.org/x/net v0.7.0 // indirect - golang.org/x/term v0.5.0 // indirect + github.com/rivo/uniseg v0.4.3 // indirect + github.com/tklauser/numcpus v0.6.0 // indirect + github.com/yusufpapurcu/wmi v1.2.2 // indirect + golang.org/x/net v0.9.0 // indirect + golang.org/x/term v0.7.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect - gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 9302e938ea..3d7a24fa5f 100644 --- a/go.sum +++ b/go.sum @@ -45,10 +45,8 @@ github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= -github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA= -github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= -github.com/VictoriaMetrics/fastcache v1.6.0 h1:C/3Oi3EiBCqufydp1neRZkqcwmEiuRT9c3fqvvgKm5o= -github.com/VictoriaMetrics/fastcache v1.6.0/go.mod h1:0qHz5QP0GMX4pfmMA/zt5RgfNuXJrTP0zS7DqpHGGTw= +github.com/VictoriaMetrics/fastcache v1.12.0 h1:vnVi/y9yKDcD9akmc4NqAoqgQhJrOwUF+j9LTgn4QDE= +github.com/VictoriaMetrics/fastcache v1.12.0/go.mod h1:tjiYeEfYXCqacuvYw/7UoDIeJaNxq6132xHICNP77w8= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= @@ -107,12 +105,13 @@ github.com/c-bata/go-prompt v0.2.2/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOC github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= -github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= +github.com/cespare/cp v1.1.1 h1:nCb6ZLdB7NRaqsm91JtQTAme2SKJzXVsdPIPkyJr1MU= +github.com/cespare/cp v1.1.1/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= @@ -165,23 +164,26 @@ github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5m github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= github.com/eclipse/paho.mqtt.golang v1.2.0/go.mod h1:H9keYFcgq3Qr5OUJm/JZI/i6U7joQ8SYLhZwfeOo6Ts= -github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/edsrzf/mmap-go v1.1.0 h1:6EUwBLQ/Mcr1EYLE4Tn1VdW1A4ckqCQWZBw8Hr0kjpQ= +github.com/edsrzf/mmap-go v1.1.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8EIth78Q= github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s= +github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI= -github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= +github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= +github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/getkin/kin-openapi v0.61.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/glycerine/go-unsnap-stream v0.0.0-20180323001048-9f0cb55181dd/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE= @@ -197,16 +199,17 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-ole/go-ole v1.2.5 h1:t4MGB5xEDZvXI+0rMjjsfBsD7yAgp/s9ZDkL1JndXwY= -github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU= github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= -github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= +github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= @@ -223,6 +226,8 @@ github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4er github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -233,10 +238,10 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y= @@ -249,23 +254,23 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa h1:Q75Upo5UN4JbPFURXZ8nLKYUvF85dyFRop/vQ0Rv+64= -github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20230207041349-798e818bf904 h1:4/hN5RUoecvl+RmJRE2YxKWtnnQls6rQjjW5oV7qg2U= github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg= +github.com/google/pprof v0.0.0-20230405160723-4a4c7d95572b h1:Qcx5LM0fSiks9uCyFZwDBUasd3lxd1RM0GYpL+Li5o4= +github.com/google/pprof v0.0.0-20230405160723-4a4c7d95572b/go.mod h1:79YE0hCXdHag9sBkw2o+N/YnZtTkXi0UT9Nnixa5eYk= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs= -github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= @@ -274,8 +279,8 @@ github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2z github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/graph-gophers/graphql-go v1.3.0 h1:Eb9x/q6MFpCLz7jBCiP/WTxjSDrYLR1QY41SORZyNJ0= github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= @@ -305,15 +310,16 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/herumi/bls-eth-go-binary v1.31.0 h1:9eeW3EA4epCb7FIHt2luENpAW69MvKGL5jieHlBiP+w= +github.com/herumi/bls-eth-go-binary v1.31.0/go.mod h1:luAnRm3OsMQeokhGzpYmc0ZKwawY7o87PUEP11Z7r7U= github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= -github.com/holiman/uint256 v1.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM= -github.com/holiman/uint256 v1.2.0/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw= +github.com/holiman/uint256 v1.2.1 h1:XRtyuda/zw2l+Bq/38n5XUoEF72aSOu/77Thd9pPp2o= +github.com/holiman/uint256 v1.2.1/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= -github.com/huin/goupnp v1.0.2 h1:RfGLP+h3mvisuWEyybxNq5Eft3NWhHLPeUN72kpKZoI= -github.com/huin/goupnp v1.0.2/go.mod h1:0dxJBVBHqTMjIUMkESDTNgOOx/Mw5wYIfyFmdzSamkM= -github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= +github.com/huin/goupnp v1.1.0 h1:gEe0Dp/lZmPZiDFzJJaOfUpOvv2MKUkoBX8lDrn9vKU= +github.com/huin/goupnp v1.1.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= @@ -332,8 +338,8 @@ github.com/influxdata/promql/v2 v2.12.0/go.mod h1:fxOPu+DY0bqCTCECchSRtWfc+0X19y github.com/influxdata/roaring v0.4.13-0.20180809181101-fc520f41fab6/go.mod h1:bSgUQ7q5ZLSO+bKBGqJiCBGAl+9DxyW63zLTujjUlOE= github.com/influxdata/tdigest v0.0.0-20181121200506-bf2b5ad3c0a9/go.mod h1:Js0mqiSBE6Ffsg94weZZ2c+v/ciT8QRHFOap7EKDrR0= github.com/influxdata/usage-client v0.0.0-20160829180054-6d3895376368/go.mod h1:Wbbw6tYNvwa5dlB6304Sd+82Z3f7PmVZHVKU637d4po= -github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458 h1:6OvNmYgJyexcZ3pYbTI9jWx5tHo1Dee/tWbLMfPe2TA= -github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= +github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= +github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e h1:UvSe12bq+Uj2hWd8aOlwPmoZ+CITRFrdit+sDGfAg8U= github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e/go.mod h1:G1CVv03EnqU1wYL2dFwXxW2An0az9JTl/ZsqXQeBlkU= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= @@ -354,15 +360,15 @@ github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4d github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= github.com/jwilder/encoding v0.0.0-20170811194829-b4e1701a28ef/go.mod h1:Ct9fl0F6iIOGgxJ5npU/IUOhOhqlVrGjyIZc8/MagT0= -github.com/karalabe/usb v0.0.0-20211005121534-4c5740d64559 h1:0VWDXPNE0brOek1Q8bLfzKkvOzwbQE/snjGojlCr8CY= -github.com/karalabe/usb v0.0.0-20211005121534-4c5740d64559/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= +github.com/karalabe/usb v0.0.2 h1:M6QQBNxF+CQ8OFvxrT90BA0qBOXymndZnk5q235mFc4= +github.com/karalabe/usb v0.0.2/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/compress v1.15.1 h1:y9FcTHGyrebwfP0ZZqFiaxTaiDnUrGkJkI+f583BL1A= -github.com/klauspost/compress v1.15.1/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/klauspost/compress v1.16.4 h1:91KN02FnsOYhuunwU4ssRe8lc2JosWmizWa91B5v1PU= +github.com/klauspost/compress v1.16.4/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/crc32 v0.0.0-20161016154125-cb6bfca970f6/go.mod h1:+ZoRqAPRLkC4NPOvfYeR5KNOrY6TD+/sAC3HXPZgDYg= github.com/klauspost/pgzip v1.0.2-0.20170402124221-0bf5dcad4ada/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= @@ -391,10 +397,11 @@ github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.11 h1:nQ+aFkoE2TMGc0b68U2OKSexC+eq46+XwZzWXHRmPYs= -github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d h1:oNAwILwmgWKFpuU+dXvI6dl9jG2mAWAZLX3r9s0PPiw= github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= @@ -402,13 +409,16 @@ github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNx github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= +github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98= +github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= +github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-tty v0.0.0-20180907095812-13ff1204f104/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= @@ -453,24 +463,24 @@ github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6 github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= -github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= +github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= -github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE= -github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= +github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw= +github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.0.3-0.20180606204148-bd9c31933947/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= +github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= @@ -481,8 +491,8 @@ github.com/paulbellamy/ratecounter v0.2.0/go.mod h1:Hfx1hDpSGoqxkVVpBi/IlYD7kChl github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= github.com/peterh/liner v1.0.1-0.20180619022028-8c1271fcf47f/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc= -github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 h1:oYW+YCJ1pachXTQmzR3rNLYGGz4g/UgFcjb28p/viDM= -github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= +github.com/peterh/liner v1.2.0 h1:w/UPXyl5GfahFxcTOz2j9wCIHNI+pUPr2laqpojKNCg= +github.com/peterh/liner v1.2.0/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= @@ -521,6 +531,9 @@ github.com/pyroscope-io/godeltaprof v0.1.2 h1:MdlEmYELd5w+lvIzmZvXGNMVzW2Qc9jDMu github.com/pyroscope-io/godeltaprof v0.1.2/go.mod h1:psMITXp90+8pFenXkKIpNhrfmI9saQnPbba27VIaiQE= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.4.3 h1:utMvzDsuh3suAEnhH0RdHmoPbU648o6CvXxTx4SBMOw= +github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rjeczalik/notify v0.9.1 h1:CLCKso/QK1snAlnhNR/CNvNiFU2saUtjV0bx3EwNeCE= github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= @@ -536,8 +549,8 @@ github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg github.com/segmentio/kafka-go v0.1.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo= github.com/segmentio/kafka-go v0.2.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= -github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= -github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= +github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= @@ -550,30 +563,38 @@ github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4 h1:Gb2Tyox57NRNuZ2d3rmvB3pcmbu7O1RS3m8WRx7ilrg= -github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= +github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= +github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= -github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/supranational/blst v0.3.10 h1:CMciDZ/h4pXDDXQASe8ZGTNKUiVNxVVA5hpci2Uuhuk= +github.com/supranational/blst v0.3.10/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= +github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDdvS342BElfbETmL1Aiz3i2t0zfRj16Hs= +github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= github.com/tinylib/msgp v1.0.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= -github.com/tklauser/go-sysconf v0.3.5 h1:uu3Xl4nkLzQfXNsWn15rPc/HQCJKObbt1dKJeWp3vU4= -github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI= -github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA= -github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= +github.com/tklauser/go-sysconf v0.3.11 h1:89WgdJhk5SNwJfu+GKyYveZ4IaJ7xAkecBo+KdJV0CM= +github.com/tklauser/go-sysconf v0.3.11/go.mod h1:GqXfhXY3kiPa0nAXPDIQIWzJbMCB7AmcWpGR8lSZfqI= +github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYms= +github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ5UVIcaL4= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef h1:wHSqTBrZW24CsNJDfeh9Ex6Pm0Rcpc7qrgKBiL44vF4= -github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= +github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= @@ -584,7 +605,10 @@ github.com/willf/bitset v1.1.3/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPyS github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= +github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= @@ -614,8 +638,8 @@ golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 h1:0es+/5331RGQPcXlMfP+WrnIIS6dNnNRe0WB02W0F4M= -golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -666,16 +690,18 @@ golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210220033124-5f55cee0dc0d/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= -golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM= +golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -687,10 +713,11 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -723,32 +750,33 @@ golang.org/x/sys v0.0.0-20200107162124-548cf772de50/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210420205809-ac73e9fd8988/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220405052023-b1e9470b6e64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= +golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.7.0 h1:BEvjmm5fURWqcfbSKTdpkDXYBrUS1c0m8agp14W48vQ= +golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= @@ -758,15 +786,16 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20220922220347-f3bd1da661af h1:Yx9k8YCG3dvF87UAn2tu2HQLf2dt/eR1bXxpLMWeH+Y= +golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -800,12 +829,14 @@ golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200108203644-89082a384178/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df h1:5Pf6pFKu98ODmgnpvkJ3kFUOQGGLIzLIkbzUHp47618= +golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= gonum.org/v1/gonum v0.0.0-20181121035319-3f7ecaa7e8ca/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= gonum.org/v1/gonum v0.6.0/go.mod h1:9mxDZsDKxgMAuccQkewq682L+0eCu4dCN2yonUJTCLU= @@ -859,8 +890,8 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= -google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= +google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -887,8 +918,9 @@ gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/params/config.go b/params/config.go index 5ac24c2914..e6252f2011 100644 --- a/params/config.go +++ b/params/config.go @@ -26,6 +26,12 @@ import ( "golang.org/x/crypto/sha3" ) +const ( + BLSSignatureLength = 96 // BLSSignatureLength defines the byte length of a BLSSignature. + BLSSecretKeyLength = 32 + BLSPubkeyLength = 48 // BLSPubkeyLength defines the byte length of a BLSSignature. +) + // Genesis hashes to enforce below configs on. var ( MainnetGenesisHash = common.HexToHash("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3")