From 0fd5d91fc51c3da0961cd780b5360e51b73bf804 Mon Sep 17 00:00:00 2001 From: Andrew Gouin Date: Sun, 17 Dec 2023 18:40:13 -0700 Subject: [PATCH] Marshal bn254 pubkeys --- cmd/horcrux/cmd/migrate.go | 8 +- proto/buf.lock | 5 + proto/buf.yaml | 2 + proto/tendermint/crypto/keys.proto | 18 + signer/bn254/bn254.go | 174 ++++++ signer/cosigner_key.go | 37 +- signer/encoding/codec.go | 76 +++ signer/local_cosigner_test.go | 2 +- signer/proto/keys.pb.go | 791 ++++++++++++++++++++++++ signer/single_signer_validator.go | 3 + signer/threshold_signer_soft_bn254.go | 2 +- signer/threshold_signer_soft_ed25519.go | 2 +- signer/threshold_validator_test.go | 4 +- 13 files changed, 1101 insertions(+), 23 deletions(-) create mode 100644 proto/tendermint/crypto/keys.proto create mode 100644 signer/bn254/bn254.go create mode 100644 signer/encoding/codec.go create mode 100644 signer/proto/keys.pb.go diff --git a/cmd/horcrux/cmd/migrate.go b/cmd/horcrux/cmd/migrate.go index 4f3d688b..a0efff08 100644 --- a/cmd/horcrux/cmd/migrate.go +++ b/cmd/horcrux/cmd/migrate.go @@ -10,10 +10,10 @@ import ( cometcrypto "github.com/cometbft/cometbft/crypto" cometcryptoed25519 "github.com/cometbft/cometbft/crypto/ed25519" - cometcryptoencoding "github.com/cometbft/cometbft/crypto/encoding" - cometprotocrypto "github.com/cometbft/cometbft/proto/tendermint/crypto" "github.com/spf13/cobra" "github.com/strangelove-ventures/horcrux/signer" + "github.com/strangelove-ventures/horcrux/signer/encoding" + "github.com/strangelove-ventures/horcrux/signer/proto" amino "github.com/tendermint/go-amino" "gopkg.in/yaml.v2" ) @@ -98,7 +98,7 @@ func (key *v2CosignerKey) UnmarshalJSON(data []byte) error { } var pubkey cometcrypto.PubKey - var protoPubkey cometprotocrypto.PublicKey + var protoPubkey proto.PublicKey err = protoPubkey.Unmarshal(aux.PubkeyBytes) // Prior to the tendermint protobuf migration, the public key bytes in key files @@ -118,7 +118,7 @@ func (key *v2CosignerKey) UnmarshalJSON(data []byte) error { } pubkey = pub } else { - pubkey, err = cometcryptoencoding.PubKeyFromProto(protoPubkey) + pubkey, err = encoding.PubKeyFromProto(protoPubkey) if err != nil { return err } diff --git a/proto/buf.lock b/proto/buf.lock index c91b5810..4850ea9b 100755 --- a/proto/buf.lock +++ b/proto/buf.lock @@ -1,2 +1,7 @@ # Generated by buf. DO NOT EDIT. version: v1 +deps: + - remote: buf.build + owner: cosmos + repository: gogo-proto + commit: 5e5b9fdd01804356895f8f79a6f1ddc1 diff --git a/proto/buf.yaml b/proto/buf.yaml index c126332f..8477697c 100644 --- a/proto/buf.yaml +++ b/proto/buf.yaml @@ -1 +1,3 @@ version: v1 +deps: + - buf.build/cosmos/gogo-proto \ No newline at end of file diff --git a/proto/tendermint/crypto/keys.proto b/proto/tendermint/crypto/keys.proto new file mode 100644 index 00000000..75efddbc --- /dev/null +++ b/proto/tendermint/crypto/keys.proto @@ -0,0 +1,18 @@ +syntax = "proto3"; +package tendermint.crypto; + +option go_package = "github.com/strangelove-ventures/horcrux/signer/proto"; + +import "gogoproto/gogo.proto"; + +// PublicKey defines the keys available for use with Validators +message PublicKey { + option (gogoproto.compare) = true; + option (gogoproto.equal) = true; + + oneof sum { + bytes ed25519 = 1; + bytes secp256k1 = 2; + bytes bn254 = 3; + } +} diff --git a/signer/bn254/bn254.go b/signer/bn254/bn254.go new file mode 100644 index 00000000..7a8e5220 --- /dev/null +++ b/signer/bn254/bn254.go @@ -0,0 +1,174 @@ +package bn254 + +import ( + "bytes" + "crypto/sha256" + "crypto/subtle" + "fmt" + "io" + + "github.com/cometbft/cometbft/crypto" + "github.com/cometbft/cometbft/crypto/tmhash" + cometjson "github.com/cometbft/cometbft/libs/json" + ecdsa_bn254 "github.com/consensys/gnark-crypto/ecc/bn254/ecdsa" +) + +//------------------------------------- + +var ( + _ crypto.PrivKey = PrivKey{} +) + +const ( + PrivKeyName = "tendermint/PrivKeyBn254" + PubKeyName = "tendermint/PubKeyBn254" + // PubKeySize is is the size, in bytes, of public keys as used in this package. + PubKeySize = 32 + // PrivateKeySize is the size, in bytes, of private keys as used in this package. + PrivateKeySize = 64 + // Size of an Bn254 signature. Namely the size of a compressed + // Bn254 point, and a field element. Both of which are 32 bytes. + SignatureSize = 64 + // SeedSize is the size, in bytes, of private key seeds. These are the + // private key representations used by RFC 8032. + SeedSize = 32 + + KeyType = "bn254" +) + +func init() { + cometjson.RegisterType(PubKey{}, PubKeyName) + cometjson.RegisterType(PrivKey{}, PrivKeyName) +} + +// PrivKey implements crypto.PrivKey. +type PrivKey []byte + +// Bytes returns the privkey byte format. +func (privKey PrivKey) Bytes() []byte { + return []byte(privKey) +} + +// Sign produces a signature on the provided message. +// This assumes the privkey is wellformed in the golang format. +// The first 32 bytes should be random, +// corresponding to the normal bn254 private key. +// The latter 32 bytes should be the compressed public key. +// If these conditions aren't met, Sign will panic or produce an +// incorrect signature. +func (privKey PrivKey) Sign(msg []byte) ([]byte, error) { + priv := new(ecdsa_bn254.PrivateKey) + _, err := priv.SetBytes(privKey[:]) + if err != nil { + return nil, err + } + + hFunc := sha256.New() + + return priv.Sign(msg, hFunc) +} + +// PubKey gets the corresponding public key from the private key. +// +// Panics if the private key is not initialized. +func (privKey PrivKey) PubKey() crypto.PubKey { + // If the latter 32 bytes of the privkey are all zero, privkey is not + // initialized. + initialized := false + for _, v := range privKey[32:] { + if v != 0 { + initialized = true + break + } + } + + if !initialized { + panic("Expected bn254 PrivKey to include concatenated pubkey bytes") + } + + pubkeyBytes := make([]byte, PubKeySize) + copy(pubkeyBytes, privKey[32:]) + return PubKey(pubkeyBytes) +} + +// Equals - you probably don't need to use this. +// Runs in constant time based on length of the keys. +func (privKey PrivKey) Equals(other crypto.PrivKey) bool { + if otherEd, ok := other.(PrivKey); ok { + return subtle.ConstantTimeCompare(privKey[:], otherEd[:]) == 1 + } + + return false +} + +func (privKey PrivKey) Type() string { + return KeyType +} + +// GenPrivKey generates a new bn254 private key. +// It uses OS randomness in conjunction with the current global random seed +// in cometbft/libs/rand to generate the private key. +func GenPrivKey() PrivKey { + return genPrivKey(crypto.CReader()) +} + +// genPrivKey generates a new bn254 private key using the provided reader. +func genPrivKey(rand io.Reader) PrivKey { + priv, err := ecdsa_bn254.GenerateKey(rand) + if err != nil { + panic(err) + } + + return PrivKey(priv.Bytes()) +} + +//------------------------------------- + +var _ crypto.PubKey = PubKey{} + +// PubKey implements crypto.PubKey for the Bn254 signature scheme. +type PubKey []byte + +// Address is the SHA256-20 of the raw pubkey bytes. +func (pubKey PubKey) Address() crypto.Address { + if len(pubKey) != PubKeySize { + panic("pubkey is incorrect size") + } + return crypto.Address(tmhash.SumTruncated(pubKey)) +} + +// Bytes returns the PubKey byte format. +func (pubKey PubKey) Bytes() []byte { + return []byte(pubKey) +} + +func (pubKey PubKey) VerifySignature(msg []byte, sig []byte) bool { + // make sure we use the same algorithm to sign + if len(sig) != SignatureSize { + return false + } + + pub := new(ecdsa_bn254.PublicKey) + if _, err := pub.SetBytes(pubKey[:]); err != nil { + return false + } + + valid, _ := pub.Verify(msg, sig, sha256.New()) + return valid +} + +func (pubKey PubKey) String() string { + return fmt.Sprintf("PubKeyBn254{%X}", []byte(pubKey)) +} + +func (pubKey PubKey) Type() string { + return KeyType +} + +func (pubKey PubKey) Equals(other crypto.PubKey) bool { + if otherEd, ok := other.(PubKey); ok { + return bytes.Equal(pubKey[:], otherEd[:]) + } + + return false +} diff --git a/signer/cosigner_key.go b/signer/cosigner_key.go index 330e060f..0424e843 100644 --- a/signer/cosigner_key.go +++ b/signer/cosigner_key.go @@ -2,12 +2,15 @@ package signer import ( "encoding/json" + "errors" + "fmt" "os" cometcrypto "github.com/cometbft/cometbft/crypto" cometcryptoed25519 "github.com/cometbft/cometbft/crypto/ed25519" - cometcryptoencoding "github.com/cometbft/cometbft/crypto/encoding" - cometprotocrypto "github.com/cometbft/cometbft/proto/tendermint/crypto" + "github.com/strangelove-ventures/horcrux/signer/bn254" + "github.com/strangelove-ventures/horcrux/signer/encoding" + "github.com/strangelove-ventures/horcrux/signer/proto" "github.com/tendermint/go-amino" ) @@ -22,7 +25,17 @@ type CosignerKey struct { func (key *CosignerKey) MarshalJSON() ([]byte, error) { type Alias CosignerKey - protoPubkey, err := cometcryptoencoding.PubKeyToProto(cometcryptoed25519.PubKey(key.PubKey)) + var pub cometcrypto.PubKey + switch key.KeyType { + case CosignerKeyTypeBn254: + pub = bn254.PubKey(key.PubKey) + case CosignerKeyTypeEd25519: + fallthrough + default: + pub = cometcryptoed25519.PubKey(key.PubKey) + } + + protoPubkey, err := encoding.PubKeyToProto(pub) if err != nil { return nil, err } @@ -55,7 +68,7 @@ func (key *CosignerKey) UnmarshalJSON(data []byte) error { } var pubkey cometcrypto.PubKey - var protoPubkey cometprotocrypto.PublicKey + var protoPubkey proto.PublicKey err := protoPubkey.Unmarshal(aux.PubkeyBytes) // Prior to the tendermint protobuf migration, the public key bytes in key files @@ -65,19 +78,17 @@ func (key *CosignerKey) UnmarshalJSON(data []byte) error { // To support reading the public key bytes from these key files, we fallback to // amino unmarshalling if the protobuf unmarshalling fails if err != nil { - var pub cometcryptoed25519.PubKey codec := amino.NewCodec() codec.RegisterInterface((*cometcrypto.PubKey)(nil), nil) codec.RegisterConcrete(cometcryptoed25519.PubKey{}, "tendermint/PubKeyEd25519", nil) - codec.RegisterConcrete(cometcryptoed25519.PubKey{}, "tendermint/PubKeyBn254", nil) - errInner := codec.UnmarshalBinaryBare(aux.PubkeyBytes, &pub) - if errInner != nil { - return err + var pub cometcryptoed25519.PubKey + if errInner := codec.UnmarshalBinaryBare(aux.PubkeyBytes, &pub); errInner != nil { + return fmt.Errorf("error in unmarshal ed25519: %w", errors.Join(err, errInner)) } pubkey = pub } else { - pubkey, err = cometcryptoencoding.PubKeyFromProto(protoPubkey) + pubkey, err = encoding.PubKeyFromProto(protoPubkey) if err != nil { return err } @@ -88,8 +99,8 @@ func (key *CosignerKey) UnmarshalJSON(data []byte) error { } // LoadCosignerKey loads a CosignerKey from file. -func LoadCosignerKey(file string) (CosignerKey, error) { - pvKey := CosignerKey{} +func LoadCosignerKey(file string) (*CosignerKey, error) { + pvKey := new(CosignerKey) keyJSONBytes, err := os.ReadFile(file) if err != nil { return pvKey, err @@ -97,7 +108,7 @@ func LoadCosignerKey(file string) (CosignerKey, error) { err = json.Unmarshal(keyJSONBytes, &pvKey) if err != nil { - return pvKey, err + return pvKey, fmt.Errorf("error in unmarshal: %w", err) } return pvKey, nil diff --git a/signer/encoding/codec.go b/signer/encoding/codec.go new file mode 100644 index 00000000..ee58cd20 --- /dev/null +++ b/signer/encoding/codec.go @@ -0,0 +1,76 @@ +package encoding + +import ( + "fmt" + + "github.com/cometbft/cometbft/crypto" + "github.com/cometbft/cometbft/crypto/ed25519" + "github.com/cometbft/cometbft/crypto/secp256k1" + "github.com/cometbft/cometbft/libs/json" + "github.com/strangelove-ventures/horcrux/signer/bn254" + "github.com/strangelove-ventures/horcrux/signer/proto" +) + +func init() { + json.RegisterType((*proto.PublicKey_Bn254)(nil), "tendermint.crypto.PublicKey_Bn254") +} + +// PubKeyToProto takes crypto.PubKey and transforms it to a protobuf Pubkey +func PubKeyToProto(k crypto.PubKey) (proto.PublicKey, error) { + var kp proto.PublicKey + switch k := k.(type) { + case ed25519.PubKey: + kp = proto.PublicKey{ + Sum: &proto.PublicKey_Ed25519{ + Ed25519: k, + }, + } + case secp256k1.PubKey: + kp = proto.PublicKey{ + Sum: &proto.PublicKey_Secp256K1{ + Secp256K1: k, + }, + } + case bn254.PubKey: + kp = proto.PublicKey{ + Sum: &proto.PublicKey_Bn254{ + Bn254: k, + }, + } + default: + return kp, fmt.Errorf("toproto: key type %v is not supported", k) + } + return kp, nil +} + +// PubKeyFromProto takes a protobuf Pubkey and transforms it to a crypto.Pubkey +func PubKeyFromProto(k proto.PublicKey) (crypto.PubKey, error) { + switch k := k.Sum.(type) { + case *proto.PublicKey_Ed25519: + if len(k.Ed25519) != ed25519.PubKeySize { + return nil, fmt.Errorf("invalid size for PubKeyEd25519. Got %d, expected %d", + len(k.Ed25519), ed25519.PubKeySize) + } + pk := make(ed25519.PubKey, ed25519.PubKeySize) + copy(pk, k.Ed25519) + return pk, nil + case *proto.PublicKey_Secp256K1: + if len(k.Secp256K1) != secp256k1.PubKeySize { + return nil, fmt.Errorf("invalid size for PubKeySecp256k1. Got %d, expected %d", + len(k.Secp256K1), secp256k1.PubKeySize) + } + pk := make(secp256k1.PubKey, secp256k1.PubKeySize) + copy(pk, k.Secp256K1) + return pk, nil + case *proto.PublicKey_Bn254: + if len(k.Bn254) != bn254.PubKeySize { + return nil, fmt.Errorf("invalid size for PubKeyBn254. Got %d, expected %d", + len(k.Bn254), bn254.PubKeySize) + } + pk := make(bn254.PubKey, bn254.PubKeySize) + copy(pk, k.Bn254) + return pk, nil + default: + return nil, fmt.Errorf("fromproto: key type %v is not supported", k) + } +} diff --git a/signer/local_cosigner_test.go b/signer/local_cosigner_test.go index 7754c772..46c09659 100644 --- a/signer/local_cosigner_test.go +++ b/signer/local_cosigner_test.go @@ -137,7 +137,7 @@ func testLocalCosignerSign(t *testing.T, threshold, total uint8, security []Cosi for i := 0; i < int(total); i++ { id := i + 1 - key := CosignerKey{ + key := &CosignerKey{ PubKey: pubKey.Bytes(), PrivateShard: privShards[i], ID: id, diff --git a/signer/proto/keys.pb.go b/signer/proto/keys.pb.go new file mode 100644 index 00000000..23114779 --- /dev/null +++ b/signer/proto/keys.pb.go @@ -0,0 +1,791 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: tendermint/crypto/keys.proto + +package proto + +import ( + bytes "bytes" + fmt "fmt" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// PublicKey defines the keys available for use with Validators +type PublicKey struct { + // Types that are valid to be assigned to Sum: + // + // *PublicKey_Ed25519 + // *PublicKey_Secp256K1 + // *PublicKey_Bn254 + Sum isPublicKey_Sum `protobuf_oneof:"sum"` +} + +func (m *PublicKey) Reset() { *m = PublicKey{} } +func (m *PublicKey) String() string { return proto.CompactTextString(m) } +func (*PublicKey) ProtoMessage() {} +func (*PublicKey) Descriptor() ([]byte, []int) { + return fileDescriptor_cb048658b234868c, []int{0} +} +func (m *PublicKey) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *PublicKey) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_PublicKey.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *PublicKey) XXX_Merge(src proto.Message) { + xxx_messageInfo_PublicKey.Merge(m, src) +} +func (m *PublicKey) XXX_Size() int { + return m.Size() +} +func (m *PublicKey) XXX_DiscardUnknown() { + xxx_messageInfo_PublicKey.DiscardUnknown(m) +} + +var xxx_messageInfo_PublicKey proto.InternalMessageInfo + +type isPublicKey_Sum interface { + isPublicKey_Sum() + Equal(interface{}) bool + MarshalTo([]byte) (int, error) + Size() int + Compare(interface{}) int +} + +type PublicKey_Ed25519 struct { + Ed25519 []byte `protobuf:"bytes,1,opt,name=ed25519,proto3,oneof" json:"ed25519,omitempty"` +} +type PublicKey_Secp256K1 struct { + Secp256K1 []byte `protobuf:"bytes,2,opt,name=secp256k1,proto3,oneof" json:"secp256k1,omitempty"` +} +type PublicKey_Bn254 struct { + Bn254 []byte `protobuf:"bytes,3,opt,name=bn254,proto3,oneof" json:"bn254,omitempty"` +} + +func (*PublicKey_Ed25519) isPublicKey_Sum() {} +func (*PublicKey_Secp256K1) isPublicKey_Sum() {} +func (*PublicKey_Bn254) isPublicKey_Sum() {} + +func (m *PublicKey) GetSum() isPublicKey_Sum { + if m != nil { + return m.Sum + } + return nil +} + +func (m *PublicKey) GetEd25519() []byte { + if x, ok := m.GetSum().(*PublicKey_Ed25519); ok { + return x.Ed25519 + } + return nil +} + +func (m *PublicKey) GetSecp256K1() []byte { + if x, ok := m.GetSum().(*PublicKey_Secp256K1); ok { + return x.Secp256K1 + } + return nil +} + +func (m *PublicKey) GetBn254() []byte { + if x, ok := m.GetSum().(*PublicKey_Bn254); ok { + return x.Bn254 + } + return nil +} + +// XXX_OneofWrappers is for the internal use of the proto package. +func (*PublicKey) XXX_OneofWrappers() []interface{} { + return []interface{}{ + (*PublicKey_Ed25519)(nil), + (*PublicKey_Secp256K1)(nil), + (*PublicKey_Bn254)(nil), + } +} + +func init() { + proto.RegisterType((*PublicKey)(nil), "tendermint.crypto.PublicKey") +} + +func init() { proto.RegisterFile("tendermint/crypto/keys.proto", fileDescriptor_cb048658b234868c) } + +var fileDescriptor_cb048658b234868c = []byte{ + // 243 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x29, 0x49, 0xcd, 0x4b, + 0x49, 0x2d, 0xca, 0xcd, 0xcc, 0x2b, 0xd1, 0x4f, 0x2e, 0xaa, 0x2c, 0x28, 0xc9, 0xd7, 0xcf, 0x4e, + 0xad, 0x2c, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x44, 0xc8, 0xea, 0x41, 0x64, 0xa5, + 0x44, 0xd2, 0xf3, 0xd3, 0xf3, 0xc1, 0xb2, 0xfa, 0x20, 0x16, 0x44, 0xa1, 0x52, 0x01, 0x17, 0x67, + 0x40, 0x69, 0x52, 0x4e, 0x66, 0xb2, 0x77, 0x6a, 0xa5, 0x90, 0x14, 0x17, 0x7b, 0x6a, 0x8a, 0x91, + 0xa9, 0xa9, 0xa1, 0xa5, 0x04, 0xa3, 0x02, 0xa3, 0x06, 0x8f, 0x07, 0x43, 0x10, 0x4c, 0x40, 0x48, + 0x8e, 0x8b, 0xb3, 0x38, 0x35, 0xb9, 0xc0, 0xc8, 0xd4, 0x2c, 0xdb, 0x50, 0x82, 0x09, 0x2a, 0x8b, + 0x10, 0x12, 0x12, 0xe3, 0x62, 0x4d, 0xca, 0x33, 0x32, 0x35, 0x91, 0x60, 0x86, 0xca, 0x41, 0xb8, + 0x56, 0x1c, 0x2f, 0x16, 0xc8, 0x33, 0xbe, 0x58, 0x28, 0xcf, 0xe8, 0xc4, 0xca, 0xc5, 0x5c, 0x5c, + 0x9a, 0xeb, 0xe4, 0x77, 0xe2, 0x91, 0x1c, 0xe3, 0x85, 0x47, 0x72, 0x8c, 0x0f, 0x1e, 0xc9, 0x31, + 0x4e, 0x78, 0x2c, 0xc7, 0x70, 0xe1, 0xb1, 0x1c, 0xc3, 0x8d, 0xc7, 0x72, 0x0c, 0x51, 0x26, 0xe9, + 0x99, 0x25, 0x19, 0xa5, 0x49, 0x7a, 0xc9, 0xf9, 0xb9, 0xfa, 0xc5, 0x25, 0x45, 0x89, 0x79, 0xe9, + 0xa9, 0x39, 0xf9, 0x65, 0xa9, 0xba, 0x65, 0xa9, 0x79, 0x25, 0xa5, 0x45, 0xa9, 0xc5, 0xfa, 0x19, + 0xf9, 0x45, 0xc9, 0x45, 0xa5, 0x15, 0xfa, 0xc5, 0x99, 0xe9, 0x79, 0xa9, 0x45, 0xfa, 0x60, 0x1f, + 0x24, 0xb1, 0x81, 0x29, 0x63, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0x82, 0xe1, 0xf2, 0x9e, 0x11, + 0x01, 0x00, 0x00, +} + +func (this *PublicKey) Compare(that interface{}) int { + if that == nil { + if this == nil { + return 0 + } + return 1 + } + + that1, ok := that.(*PublicKey) + if !ok { + that2, ok := that.(PublicKey) + if ok { + that1 = &that2 + } else { + return 1 + } + } + if that1 == nil { + if this == nil { + return 0 + } + return 1 + } else if this == nil { + return -1 + } + if that1.Sum == nil { + if this.Sum != nil { + return 1 + } + } else if this.Sum == nil { + return -1 + } else { + thisType := -1 + switch this.Sum.(type) { + case *PublicKey_Ed25519: + thisType = 0 + case *PublicKey_Secp256K1: + thisType = 1 + case *PublicKey_Bn254: + thisType = 2 + default: + panic(fmt.Sprintf("compare: unexpected type %T in oneof", this.Sum)) + } + that1Type := -1 + switch that1.Sum.(type) { + case *PublicKey_Ed25519: + that1Type = 0 + case *PublicKey_Secp256K1: + that1Type = 1 + case *PublicKey_Bn254: + that1Type = 2 + default: + panic(fmt.Sprintf("compare: unexpected type %T in oneof", that1.Sum)) + } + if thisType == that1Type { + if c := this.Sum.Compare(that1.Sum); c != 0 { + return c + } + } else if thisType < that1Type { + return -1 + } else if thisType > that1Type { + return 1 + } + } + return 0 +} +func (this *PublicKey_Ed25519) Compare(that interface{}) int { + if that == nil { + if this == nil { + return 0 + } + return 1 + } + + that1, ok := that.(*PublicKey_Ed25519) + if !ok { + that2, ok := that.(PublicKey_Ed25519) + if ok { + that1 = &that2 + } else { + return 1 + } + } + if that1 == nil { + if this == nil { + return 0 + } + return 1 + } else if this == nil { + return -1 + } + if c := bytes.Compare(this.Ed25519, that1.Ed25519); c != 0 { + return c + } + return 0 +} +func (this *PublicKey_Secp256K1) Compare(that interface{}) int { + if that == nil { + if this == nil { + return 0 + } + return 1 + } + + that1, ok := that.(*PublicKey_Secp256K1) + if !ok { + that2, ok := that.(PublicKey_Secp256K1) + if ok { + that1 = &that2 + } else { + return 1 + } + } + if that1 == nil { + if this == nil { + return 0 + } + return 1 + } else if this == nil { + return -1 + } + if c := bytes.Compare(this.Secp256K1, that1.Secp256K1); c != 0 { + return c + } + return 0 +} +func (this *PublicKey_Bn254) Compare(that interface{}) int { + if that == nil { + if this == nil { + return 0 + } + return 1 + } + + that1, ok := that.(*PublicKey_Bn254) + if !ok { + that2, ok := that.(PublicKey_Bn254) + if ok { + that1 = &that2 + } else { + return 1 + } + } + if that1 == nil { + if this == nil { + return 0 + } + return 1 + } else if this == nil { + return -1 + } + if c := bytes.Compare(this.Bn254, that1.Bn254); c != 0 { + return c + } + return 0 +} +func (this *PublicKey) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*PublicKey) + if !ok { + that2, ok := that.(PublicKey) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if that1.Sum == nil { + if this.Sum != nil { + return false + } + } else if this.Sum == nil { + return false + } else if !this.Sum.Equal(that1.Sum) { + return false + } + return true +} +func (this *PublicKey_Ed25519) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*PublicKey_Ed25519) + if !ok { + that2, ok := that.(PublicKey_Ed25519) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !bytes.Equal(this.Ed25519, that1.Ed25519) { + return false + } + return true +} +func (this *PublicKey_Secp256K1) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*PublicKey_Secp256K1) + if !ok { + that2, ok := that.(PublicKey_Secp256K1) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !bytes.Equal(this.Secp256K1, that1.Secp256K1) { + return false + } + return true +} +func (this *PublicKey_Bn254) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*PublicKey_Bn254) + if !ok { + that2, ok := that.(PublicKey_Bn254) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !bytes.Equal(this.Bn254, that1.Bn254) { + return false + } + return true +} +func (m *PublicKey) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *PublicKey) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PublicKey) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Sum != nil { + { + size := m.Sum.Size() + i -= size + if _, err := m.Sum.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + } + } + return len(dAtA) - i, nil +} + +func (m *PublicKey_Ed25519) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PublicKey_Ed25519) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Ed25519 != nil { + i -= len(m.Ed25519) + copy(dAtA[i:], m.Ed25519) + i = encodeVarintKeys(dAtA, i, uint64(len(m.Ed25519))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} +func (m *PublicKey_Secp256K1) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PublicKey_Secp256K1) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Secp256K1 != nil { + i -= len(m.Secp256K1) + copy(dAtA[i:], m.Secp256K1) + i = encodeVarintKeys(dAtA, i, uint64(len(m.Secp256K1))) + i-- + dAtA[i] = 0x12 + } + return len(dAtA) - i, nil +} +func (m *PublicKey_Bn254) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PublicKey_Bn254) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Bn254 != nil { + i -= len(m.Bn254) + copy(dAtA[i:], m.Bn254) + i = encodeVarintKeys(dAtA, i, uint64(len(m.Bn254))) + i-- + dAtA[i] = 0x1a + } + return len(dAtA) - i, nil +} +func encodeVarintKeys(dAtA []byte, offset int, v uint64) int { + offset -= sovKeys(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *PublicKey) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Sum != nil { + n += m.Sum.Size() + } + return n +} + +func (m *PublicKey_Ed25519) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Ed25519 != nil { + l = len(m.Ed25519) + n += 1 + l + sovKeys(uint64(l)) + } + return n +} +func (m *PublicKey_Secp256K1) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Secp256K1 != nil { + l = len(m.Secp256K1) + n += 1 + l + sovKeys(uint64(l)) + } + return n +} +func (m *PublicKey_Bn254) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Bn254 != nil { + l = len(m.Bn254) + n += 1 + l + sovKeys(uint64(l)) + } + return n +} + +func sovKeys(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozKeys(x uint64) (n int) { + return sovKeys(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *PublicKey) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowKeys + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: PublicKey: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PublicKey: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Ed25519", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowKeys + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthKeys + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthKeys + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := make([]byte, postIndex-iNdEx) + copy(v, dAtA[iNdEx:postIndex]) + m.Sum = &PublicKey_Ed25519{v} + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Secp256K1", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowKeys + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthKeys + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthKeys + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := make([]byte, postIndex-iNdEx) + copy(v, dAtA[iNdEx:postIndex]) + m.Sum = &PublicKey_Secp256K1{v} + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Bn254", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowKeys + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthKeys + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthKeys + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := make([]byte, postIndex-iNdEx) + copy(v, dAtA[iNdEx:postIndex]) + m.Sum = &PublicKey_Bn254{v} + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipKeys(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthKeys + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipKeys(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowKeys + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowKeys + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowKeys + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthKeys + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupKeys + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthKeys + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthKeys = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowKeys = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupKeys = fmt.Errorf("proto: unexpected end of group") +) diff --git a/signer/single_signer_validator.go b/signer/single_signer_validator.go index ee0d40ff..d5d7703e 100644 --- a/signer/single_signer_validator.go +++ b/signer/single_signer_validator.go @@ -6,6 +6,9 @@ import ( "os" "sync" "time" + + // required to register bn254 types for signing + _ "github.com/strangelove-ventures/horcrux/signer/bn254" ) var _ PrivValidator = &SingleSignerValidator{} diff --git a/signer/threshold_signer_soft_bn254.go b/signer/threshold_signer_soft_bn254.go index c4567096..fd99bee3 100644 --- a/signer/threshold_signer_soft_bn254.go +++ b/signer/threshold_signer_soft_bn254.go @@ -20,7 +20,7 @@ type ThresholdSignerSoftBn254 struct { suite *bn256.Suite } -func NewThresholdSignerSoftBn254(key CosignerKey, threshold, total uint8) (*ThresholdSignerSoftBn254, error) { +func NewThresholdSignerSoftBn254(key *CosignerKey, threshold, total uint8) (*ThresholdSignerSoftBn254, error) { suite := bn256.NewSuite() privateKey := suite.G2().Scalar().SetBytes(key.PrivateShard) pubKey := suite.G2().Point() diff --git a/signer/threshold_signer_soft_ed25519.go b/signer/threshold_signer_soft_ed25519.go index 8191c1dd..b185063d 100644 --- a/signer/threshold_signer_soft_ed25519.go +++ b/signer/threshold_signer_soft_ed25519.go @@ -20,7 +20,7 @@ type ThresholdSignerSoftEd25519 struct { total uint8 } -func NewThresholdSignerSoftEd25519(key CosignerKey, threshold, total uint8) *ThresholdSignerSoftEd25519 { +func NewThresholdSignerSoftEd25519(key *CosignerKey, threshold, total uint8) *ThresholdSignerSoftEd25519 { return &ThresholdSignerSoftEd25519{ privateKeyShard: key.PrivateShard, pubKey: key.PubKey, diff --git a/signer/threshold_validator_test.go b/signer/threshold_validator_test.go index 3371422d..411aa509 100644 --- a/signer/threshold_validator_test.go +++ b/signer/threshold_validator_test.go @@ -68,7 +68,7 @@ func loadKeyForLocalCosigner( chainID string, privateShard []byte, ) error { - key := CosignerKey{ + key := &CosignerKey{ KeyType: keyType, PubKey: pubKey, PrivateShard: privateShard, @@ -351,12 +351,10 @@ func getTestLocalCosigners(t *testing.T, keyType string, threshold, total uint8) pk := pubPoly.Commit() pubKey, err = pk.MarshalBinary() require.NoError(t, err) - fmt.Printf("pubKey: %+v\n", pk) for i, x := range priPoly.Shares(int(total)) { privShards[i], err = x.V.MarshalBinary() require.NoError(t, err) - fmt.Printf("share i: %d, %x\n", x.I, privShards[i]) } }