PubKey proto types (#7147)

* WIP on protobuf keys

* Use Type() and Bytes() in sr25519 pub key Equals

* Add tests

* Add few more tests

* Update other pub/priv key types Equals

* Fix PrivKey's Sign method

* Rename variables in tests

* Fix infinite recursive calls

* Use tm ed25519 keys

* Add Sign and VerifySignature tests

* Remove ed25519 and sr25519 references

* proto linting

* Add proto crypto file

* Implement some of the new multisig proto type methods

* Add tests for MultisigThresholdPubKey

* Add tests for pubkey pb/amino conversion functions

* Move crypto types.go and register new proto pubkeys

* Add missing pointer ref

* Address review comments

* panic in MultisigThresholdPubKey VerifySignature

* Use internal crypto.PubKey in multisig

* Add tests for MultisigThresholdPubKey VerifyMultisignature

* Only keep LegacyAminoMultisigThresholdPubKey and move to proto keys to v1

* Remove conversion functions and introduce internal PubKey type

* Remove old secp256k1 PubKey and PrivKey

* Uncomment test case

* Fix linting issues

* More linting

* Revert tests keys values

* Add Amino overrides to proto keys

* Add pubkey test

* Fix tests

* Use threshold isntead of K

* Standardize Type

* Revert standardize types commit

* Add comment

* Simplify proto names

* Add comment about multisig codec

Co-authored-by: Aaron Craelius <aaronc@users.noreply.github.com>
Co-authored-by: Amaury Martiny <amaury.martiny@protonmail.com>
Co-authored-by: Alexander Bezobchuk <alexanderbez@users.noreply.github.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
This commit is contained in:
Marie
2020-09-16 11:08:55 +00:00
committed by GitHub
co-authored by Aaron Craelius Amaury Martiny Alexander Bezobchuk mergify[bot]
parent d4266dcde8
commit 320a852ee2
26 changed files with 2205 additions and 677 deletions
+9
View File
@@ -54,4 +54,13 @@ type (
Size() int
Unmarshal(data []byte) error
}
// AminoMarshaler defines an interface where Amino marshalling can be
// overridden by custom marshalling.
AminoMarshaler interface {
MarshalAmino() ([]byte, error)
UnmarshalAmino([]byte) error
MarshalAminoJSON() ([]byte, error)
UnmarshalAminoJSON([]byte) error
}
)
+8 -2
View File
@@ -6,6 +6,7 @@ import (
"github.com/tendermint/tendermint/crypto/sr25519"
"github.com/cosmos/cosmos-sdk/codec"
kmultisig "github.com/cosmos/cosmos-sdk/crypto/keys/multisig"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
"github.com/cosmos/cosmos-sdk/crypto/types/multisig"
)
@@ -25,17 +26,22 @@ func RegisterCrypto(cdc *codec.LegacyAmino) {
ed25519.PubKeyName, nil)
cdc.RegisterConcrete(sr25519.PubKey{},
sr25519.PubKeyName, nil)
cdc.RegisterConcrete(secp256k1.PubKey{},
cdc.RegisterConcrete(&secp256k1.PubKey{},
secp256k1.PubKeyName, nil)
// TODO Follow-up in https://github.com/cosmos/cosmos-sdk/pull/7284
// Remove `multisig.PubKeyMultisigThreshold{}`, and register instead
// kmultisig.LegacyAminoPubKey{} on `PubKeyAminoRoute`.
cdc.RegisterConcrete(multisig.PubKeyMultisigThreshold{},
multisig.PubKeyAminoRoute, nil)
cdc.RegisterConcrete(&kmultisig.LegacyAminoPubKey{},
"cosmos-sdk/LegacyAminoPubKey", nil)
cdc.RegisterInterface((*crypto.PrivKey)(nil), nil)
cdc.RegisterConcrete(ed25519.PrivKey{},
ed25519.PrivKeyName, nil)
cdc.RegisterConcrete(sr25519.PrivKey{},
sr25519.PrivKeyName, nil)
cdc.RegisterConcrete(secp256k1.PrivKey{},
cdc.RegisterConcrete(&secp256k1.PrivKey{},
secp256k1.PrivKeyName, nil)
}
+1 -1
View File
@@ -66,6 +66,6 @@ func (s secp256k1Algo) Generate() GenerateFn {
var bzArr = make([]byte, secp256k1.PrivKeySize)
copy(bzArr, bz)
return secp256k1.PrivKey(bzArr)
return &secp256k1.PrivKey{Key: bzArr}
}
}
+3 -2
View File
@@ -65,7 +65,8 @@ func TestFundraiserCompatibility(t *testing.T) {
master, ch := hd.ComputeMastersFromSeed(seed)
priv, err := hd.DerivePrivateKeyForPath(master, ch, "44'/118'/0'/0/0")
require.NoError(t, err)
pub := secp256k1.PrivKey(priv).PubKey()
privKey := &secp256k1.PrivKey{Key: priv}
pub := privKey.PubKey()
t.Log("\tNODEJS GOLANG\n")
t.Logf("SEED \t%X %X\n", seedB, seed)
@@ -78,7 +79,7 @@ func TestFundraiserCompatibility(t *testing.T) {
require.Equal(t, priv[:], privB, "Expected priv keys to match")
pubBFixed := make([]byte, secp256k1.PubKeySize)
copy(pubBFixed, pubB)
require.Equal(t, pub, secp256k1.PubKey(pubBFixed), fmt.Sprintf("Expected pub keys to match for %d", i))
require.Equal(t, pub, &secp256k1.PubKey{Key: pubBFixed}, fmt.Sprintf("Expected pub keys to match for %d", i))
addr := pub.Address()
t.Logf("ADDR \t%X %X\n", addrB, addr)
+2 -2
View File
@@ -12,11 +12,11 @@ import (
)
func Test_writeReadLedgerInfo(t *testing.T) {
tmpKey := make(secp256k1.PubKey, secp256k1.PubKeySize)
tmpKey := make([]byte, secp256k1.PubKeySize)
bz, _ := hex.DecodeString("035AD6810A47F073553FF30D2FCC7E0D3B1C0B74B61A1AAA2582344037151E143A")
copy(tmpKey[:], bz)
lInfo := newLedgerInfo("some_name", tmpKey, *hd.NewFundraiserParams(5, sdk.CoinType, 1), hd.Secp256k1Type)
lInfo := newLedgerInfo("some_name", &secp256k1.PubKey{Key: tmpKey}, *hd.NewFundraiserParams(5, sdk.CoinType, 1), hd.Secp256k1Type)
assert.Equal(t, TypeLedger, lInfo.GetType())
path, err := lInfo.GetPath()
+362
View File
@@ -0,0 +1,362 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: cosmos/crypto/multisig/keys.proto
package multisig
import (
fmt "fmt"
types "github.com/cosmos/cosmos-sdk/codec/types"
_ "github.com/gogo/protobuf/gogoproto"
proto "github.com/gogo/protobuf/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
// LegacyAminoPubKey specifies a public key type
// which nests multiple public keys and a threshold,
// it uses legacy amino address rules.
type LegacyAminoPubKey struct {
Threshold uint32 `protobuf:"varint,1,opt,name=threshold,proto3" json:"threshold,omitempty" yaml:"threshold"`
PubKeys []*types.Any `protobuf:"bytes,2,rep,name=public_keys,json=publicKeys,proto3" json:"public_keys,omitempty" yaml:"pubkeys"`
}
func (m *LegacyAminoPubKey) Reset() { *m = LegacyAminoPubKey{} }
func (m *LegacyAminoPubKey) String() string { return proto.CompactTextString(m) }
func (*LegacyAminoPubKey) ProtoMessage() {}
func (*LegacyAminoPubKey) Descriptor() ([]byte, []int) {
return fileDescriptor_46b57537e097d47d, []int{0}
}
func (m *LegacyAminoPubKey) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *LegacyAminoPubKey) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_LegacyAminoPubKey.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 *LegacyAminoPubKey) XXX_Merge(src proto.Message) {
xxx_messageInfo_LegacyAminoPubKey.Merge(m, src)
}
func (m *LegacyAminoPubKey) XXX_Size() int {
return m.Size()
}
func (m *LegacyAminoPubKey) XXX_DiscardUnknown() {
xxx_messageInfo_LegacyAminoPubKey.DiscardUnknown(m)
}
var xxx_messageInfo_LegacyAminoPubKey proto.InternalMessageInfo
func init() {
proto.RegisterType((*LegacyAminoPubKey)(nil), "cosmos.crypto.multisig.LegacyAminoPubKey")
}
func init() { proto.RegisterFile("cosmos/crypto/multisig/keys.proto", fileDescriptor_46b57537e097d47d) }
var fileDescriptor_46b57537e097d47d = []byte{
// 287 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x4c, 0xce, 0x2f, 0xce,
0xcd, 0x2f, 0xd6, 0x4f, 0x2e, 0xaa, 0x2c, 0x28, 0xc9, 0xd7, 0xcf, 0x2d, 0xcd, 0x29, 0xc9, 0x2c,
0xce, 0x4c, 0xd7, 0xcf, 0x4e, 0xad, 0x2c, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x83,
0x28, 0xd1, 0x83, 0x28, 0xd1, 0x83, 0x29, 0x91, 0x12, 0x49, 0xcf, 0x4f, 0xcf, 0x07, 0x2b, 0xd1,
0x07, 0xb1, 0x20, 0xaa, 0xa5, 0x24, 0xd3, 0xf3, 0xf3, 0xd3, 0x73, 0x52, 0xf5, 0xc1, 0xbc, 0xa4,
0xd2, 0x34, 0xfd, 0xc4, 0xbc, 0x4a, 0x88, 0x94, 0xd2, 0x62, 0x46, 0x2e, 0x41, 0x9f, 0xd4, 0xf4,
0xc4, 0xe4, 0x4a, 0xc7, 0xdc, 0xcc, 0xbc, 0xfc, 0x80, 0xd2, 0x24, 0xef, 0xd4, 0x4a, 0x21, 0x23,
0x2e, 0xce, 0x92, 0x8c, 0xa2, 0xd4, 0xe2, 0x8c, 0xfc, 0x9c, 0x14, 0x09, 0x46, 0x05, 0x46, 0x0d,
0x5e, 0x27, 0x91, 0x4f, 0xf7, 0xe4, 0x05, 0x2a, 0x13, 0x73, 0x73, 0xac, 0x94, 0xe0, 0x52, 0x4a,
0x41, 0x08, 0x65, 0x42, 0x21, 0x5c, 0xdc, 0x05, 0xa5, 0x49, 0x39, 0x99, 0xc9, 0xf1, 0x20, 0x77,
0x4a, 0x30, 0x29, 0x30, 0x6b, 0x70, 0x1b, 0x89, 0xe8, 0x41, 0xac, 0xd6, 0x83, 0x59, 0xad, 0xe7,
0x98, 0x57, 0xe9, 0x24, 0xfb, 0xe8, 0x9e, 0x3c, 0x3b, 0xc4, 0xaa, 0xe2, 0x4f, 0xf7, 0xe4, 0xf9,
0x20, 0xc6, 0x16, 0x94, 0x26, 0x81, 0x74, 0x2a, 0x05, 0x71, 0x41, 0xcc, 0x01, 0xc9, 0x5a, 0xb1,
0x74, 0x2c, 0x90, 0x67, 0x70, 0xf2, 0x3e, 0xf1, 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39, 0xc6, 0x07,
0x8f, 0xe4, 0x18, 0x27, 0x3c, 0x96, 0x63, 0xb8, 0xf0, 0x58, 0x8e, 0xe1, 0xc6, 0x63, 0x39, 0x86,
0x28, 0xc3, 0xf4, 0xcc, 0x92, 0x8c, 0xd2, 0x24, 0xbd, 0xe4, 0xfc, 0x5c, 0x7d, 0x58, 0xb0, 0x81,
0x29, 0xdd, 0xe2, 0x94, 0x6c, 0x58, 0x08, 0x82, 0x8c, 0x85, 0x07, 0x63, 0x12, 0x1b, 0xd8, 0x2d,
0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0x76, 0x6e, 0xbf, 0x3c, 0x67, 0x01, 0x00, 0x00,
}
func (m *LegacyAminoPubKey) 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 *LegacyAminoPubKey) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *LegacyAminoPubKey) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if len(m.PubKeys) > 0 {
for iNdEx := len(m.PubKeys) - 1; iNdEx >= 0; iNdEx-- {
{
size, err := m.PubKeys[iNdEx].MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarintKeys(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0x12
}
}
if m.Threshold != 0 {
i = encodeVarintKeys(dAtA, i, uint64(m.Threshold))
i--
dAtA[i] = 0x8
}
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 *LegacyAminoPubKey) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
if m.Threshold != 0 {
n += 1 + sovKeys(uint64(m.Threshold))
}
if len(m.PubKeys) > 0 {
for _, e := range m.PubKeys {
l = e.Size()
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 *LegacyAminoPubKey) 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: LegacyAminoPubKey: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: LegacyAminoPubKey: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Threshold", wireType)
}
m.Threshold = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowKeys
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.Threshold |= uint32(b&0x7F) << shift
if b < 0x80 {
break
}
}
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field PubKeys", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowKeys
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthKeys
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthKeys
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.PubKeys = append(m.PubKeys, &types.Any{})
if err := m.PubKeys[len(m.PubKeys)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipKeys(dAtA[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthKeys
}
if (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")
)
+130
View File
@@ -0,0 +1,130 @@
package multisig
import (
fmt "fmt"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/codec/types"
crypto "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/cosmos-sdk/types/tx/signing"
tmcrypto "github.com/tendermint/tendermint/crypto"
"github.com/cosmos/cosmos-sdk/crypto/types/multisig"
)
// In the refactor in https://github.com/cosmos/cosmos-sdk/pull/7284, make sure
// to use AminoCdc here.
var cdc = codec.NewProtoCodec(types.NewInterfaceRegistry())
var _ multisig.PubKey = &LegacyAminoPubKey{}
// Address implements crypto.PubKey Address method
func (m *LegacyAminoPubKey) Address() crypto.Address {
return tmcrypto.AddressHash(m.Bytes())
}
// Bytes returns the proto encoded version of the LegacyAminoPubKey
func (m *LegacyAminoPubKey) Bytes() []byte {
return cdc.MustMarshalBinaryBare(m)
}
// VerifyMultisignature implements the multisig.PubKey VerifyMultisignature method
func (m *LegacyAminoPubKey) VerifyMultisignature(getSignBytes multisig.GetSignBytesFunc, sig *signing.MultiSignatureData) error {
bitarray := sig.BitArray
sigs := sig.Signatures
size := bitarray.Count()
pubKeys := m.GetPubKeys()
// ensure bit array is the correct size
if len(pubKeys) != size {
return fmt.Errorf("bit array size is incorrect %d", len(pubKeys))
}
// ensure size of signature list
if len(sigs) < int(m.Threshold) || len(sigs) > size {
return fmt.Errorf("signature size is incorrect %d", len(sigs))
}
// ensure at least k signatures are set
if bitarray.NumTrueBitsBefore(size) < int(m.Threshold) {
return fmt.Errorf("minimum number of signatures not set, have %d, expected %d", bitarray.NumTrueBitsBefore(size), int(m.Threshold))
}
// index in the list of signatures which we are concerned with.
sigIndex := 0
for i := 0; i < size; i++ {
if bitarray.GetIndex(i) {
si := sig.Signatures[sigIndex]
switch si := si.(type) {
case *signing.SingleSignatureData:
msg, err := getSignBytes(si.SignMode)
if err != nil {
return err
}
if !pubKeys[i].VerifySignature(msg, si.Signature) {
return err
}
case *signing.MultiSignatureData:
nestedMultisigPk, ok := pubKeys[i].(multisig.PubKey)
if !ok {
return fmt.Errorf("unable to parse pubkey of index %d", i)
}
if err := nestedMultisigPk.VerifyMultisignature(getSignBytes, si); err != nil {
return err
}
default:
return fmt.Errorf("improper signature data type for index %d", sigIndex)
}
sigIndex++
}
}
return nil
}
// VerifySignature implements crypto.PubKey VerifySignature method,
// it panics because it can't handle MultiSignatureData
// cf. https://github.com/cosmos/cosmos-sdk/issues/7109#issuecomment-686329936
func (m *LegacyAminoPubKey) VerifySignature(msg []byte, sig []byte) bool {
panic("not implemented")
}
// GetPubKeys implements the PubKey.GetPubKeys method
func (m *LegacyAminoPubKey) GetPubKeys() []tmcrypto.PubKey {
if m != nil {
pubKeys := make([]tmcrypto.PubKey, len(m.PubKeys))
for i := 0; i < len(m.PubKeys); i++ {
pubKeys[i] = m.PubKeys[i].GetCachedValue().(tmcrypto.PubKey)
}
return pubKeys
}
return nil
}
// Equals returns true if m and other both have the same number of keys, and
// all constituent keys are the same, and in the same order.
func (m *LegacyAminoPubKey) Equals(key tmcrypto.PubKey) bool {
otherKey, ok := key.(multisig.PubKey)
if !ok {
return false
}
pubKeys := m.GetPubKeys()
otherPubKeys := otherKey.GetPubKeys()
if m.GetThreshold() != otherKey.GetThreshold() || len(pubKeys) != len(otherPubKeys) {
return false
}
for i := 0; i < len(pubKeys); i++ {
if !pubKeys[i].Equals(otherPubKeys[i]) {
return false
}
}
return true
}
// GetThreshold implements the PubKey.GetThreshold method
func (m *LegacyAminoPubKey) GetThreshold() uint {
return uint(m.Threshold)
}
// Type returns multisig type
func (m *LegacyAminoPubKey) Type() string {
return "PubKeyMultisigThreshold"
}
+230
View File
@@ -0,0 +1,230 @@
package multisig
import (
"testing"
"github.com/cosmos/cosmos-sdk/codec/types"
crypto "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/cosmos-sdk/crypto/types/multisig"
proto "github.com/gogo/protobuf/proto"
tmcrypto "github.com/tendermint/tendermint/crypto"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
"github.com/cosmos/cosmos-sdk/types/tx/signing"
"github.com/stretchr/testify/require"
)
func TestAddress(t *testing.T) {
msg := []byte{1, 2, 3, 4}
pubKeys, _ := generatePubKeysAndSignatures(5, msg)
anyPubKeys, err := packPubKeys(pubKeys)
require.NoError(t, err)
multisigKey := &LegacyAminoPubKey{Threshold: 2, PubKeys: anyPubKeys}
require.Len(t, multisigKey.Address().Bytes(), 20)
}
func TestEquals(t *testing.T) {
pubKey1 := secp256k1.GenPrivKey().PubKey()
pubKey2 := secp256k1.GenPrivKey().PubKey()
anyPubKeys, err := packPubKeys([]tmcrypto.PubKey{pubKey1, pubKey2})
require.NoError(t, err)
multisigKey := &LegacyAminoPubKey{Threshold: 1, PubKeys: anyPubKeys}
otherPubKeys, err := packPubKeys([]tmcrypto.PubKey{pubKey1, multisigKey})
require.NoError(t, err)
otherMultisigKey := LegacyAminoPubKey{Threshold: 1, PubKeys: otherPubKeys}
testCases := []struct {
msg string
other tmcrypto.PubKey
expectEq bool
}{
{
"equals with proto pub key",
&LegacyAminoPubKey{Threshold: 1, PubKeys: anyPubKeys},
true,
},
{
"different threshold",
&LegacyAminoPubKey{Threshold: 2, PubKeys: anyPubKeys},
false,
},
{
"different pub keys length",
&LegacyAminoPubKey{Threshold: 1, PubKeys: []*types.Any{anyPubKeys[0]}},
false,
},
{
"different pub keys",
&otherMultisigKey,
false,
},
{
"different types",
secp256k1.GenPrivKey().PubKey(),
false,
},
}
for _, tc := range testCases {
t.Run(tc.msg, func(t *testing.T) {
eq := multisigKey.Equals(tc.other)
require.Equal(t, eq, tc.expectEq)
})
}
}
func TestVerifyMultisignature(t *testing.T) {
var (
pk multisig.PubKey
sig *signing.MultiSignatureData
)
msg := []byte{1, 2, 3, 4}
signBytesFn := func(mode signing.SignMode) ([]byte, error) { return msg, nil }
testCases := []struct {
msg string
malleate func()
expectPass bool
}{
{
"nested multisignature",
func() {
genPk, genSig, err := generateNestedMultiSignature(3, msg)
require.NoError(t, err)
sig = genSig
pk = genPk
},
true,
},
{
"wrong size for sig bit array",
func() {
pubKeys, _ := generatePubKeysAndSignatures(3, msg)
anyPubKeys, err := packPubKeys(pubKeys)
require.NoError(t, err)
pk = &LegacyAminoPubKey{Threshold: 3, PubKeys: anyPubKeys}
sig = multisig.NewMultisig(1)
},
false,
},
{
"single signature data",
func() {
k := 2
signingIndices := []int{0, 3, 1}
pubKeys, sigs := generatePubKeysAndSignatures(5, msg)
anyPubKeys, err := packPubKeys(pubKeys)
require.NoError(t, err)
pk = &LegacyAminoPubKey{Threshold: uint32(k), PubKeys: anyPubKeys}
sig = multisig.NewMultisig(len(pubKeys))
signBytesFn := func(mode signing.SignMode) ([]byte, error) { return msg, nil }
for i := 0; i < k-1; i++ {
signingIndex := signingIndices[i]
require.NoError(
t,
multisig.AddSignatureFromPubKey(sig, sigs[signingIndex], pubKeys[signingIndex], pubKeys),
)
require.Error(
t,
pk.VerifyMultisignature(signBytesFn, sig),
"multisig passed when i < k, i %d", i,
)
require.NoError(
t,
multisig.AddSignatureFromPubKey(sig, sigs[signingIndex], pubKeys[signingIndex], pubKeys),
)
}
require.Error(
t,
pk.VerifyMultisignature(signBytesFn, sig),
"multisig passed with k - 1 sigs",
)
require.NoError(
t,
multisig.AddSignatureFromPubKey(
sig,
sigs[signingIndices[k]],
pubKeys[signingIndices[k]],
pubKeys,
),
)
},
true,
},
}
for _, tc := range testCases {
t.Run(tc.msg, func(t *testing.T) {
tc.malleate()
err := pk.VerifyMultisignature(signBytesFn, sig)
if tc.expectPass {
require.NoError(t, err)
} else {
require.Error(t, err)
}
})
}
}
func generatePubKeysAndSignatures(n int, msg []byte) (pubKeys []tmcrypto.PubKey, signatures []signing.SignatureData) {
pubKeys = make([]tmcrypto.PubKey, n)
signatures = make([]signing.SignatureData, n)
for i := 0; i < n; i++ {
privkey := secp256k1.GenPrivKey()
pubKeys[i] = privkey.PubKey()
sig, _ := privkey.Sign(msg)
signatures[i] = &signing.SingleSignatureData{Signature: sig}
}
return
}
func generateNestedMultiSignature(n int, msg []byte) (multisig.PubKey, *signing.MultiSignatureData, error) {
pubKeys := make([]tmcrypto.PubKey, n)
signatures := make([]signing.SignatureData, n)
bitArray := crypto.NewCompactBitArray(n)
for i := 0; i < n; i++ {
nestedPks, nestedSigs := generatePubKeysAndSignatures(5, msg)
nestedBitArray := crypto.NewCompactBitArray(5)
for j := 0; j < 5; j++ {
nestedBitArray.SetIndex(j, true)
}
nestedSig := &signing.MultiSignatureData{
BitArray: nestedBitArray,
Signatures: nestedSigs,
}
signatures[i] = nestedSig
anyNestedPks, err := packPubKeys(nestedPks)
if err != nil {
return nil, nil, err
}
pubKeys[i] = &LegacyAminoPubKey{Threshold: 5, PubKeys: anyNestedPks}
bitArray.SetIndex(i, true)
}
anyPubKeys, err := packPubKeys(pubKeys)
if err != nil {
return nil, nil, err
}
return &LegacyAminoPubKey{Threshold: uint32(n), PubKeys: anyPubKeys}, &signing.MultiSignatureData{
BitArray: bitArray,
Signatures: signatures,
}, nil
}
func packPubKeys(pubKeys []tmcrypto.PubKey) ([]*types.Any, error) {
anyPubKeys := make([]*types.Any, len(pubKeys))
for i := 0; i < len(pubKeys); i++ {
any, err := types.NewAnyWithValue(pubKeys[i].(proto.Message))
if err != nil {
return nil, err
}
anyPubKeys[i] = any
}
return anyPubKeys, nil
}
+2 -1
View File
@@ -11,7 +11,8 @@ import (
func BenchmarkKeyGeneration(b *testing.B) {
benchmarkKeygenWrapper := func(reader io.Reader) crypto.PrivKey {
return genPrivKey(reader)
priv := genPrivKey(reader)
return &PrivKey{Key: priv}
}
benchmarking.BenchmarkKeyGeneration(b, benchmarkKeygenWrapper)
}
+504
View File
@@ -0,0 +1,504 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: cosmos/crypto/secp256k1/keys.proto
package secp256k1
import (
fmt "fmt"
_ "github.com/gogo/protobuf/gogoproto"
proto "github.com/gogo/protobuf/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
// PubKey defines a secp256k1 public key
// Key is the compressed form of the pubkey. The first byte depends is a 0x02 byte
// if the y-coordinate is the lexicographically largest of the two associated with
// the x-coordinate. Otherwise the first byte is a 0x03.
// This prefix is followed with the x-coordinate.
type PubKey struct {
Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
}
func (m *PubKey) Reset() { *m = PubKey{} }
func (*PubKey) ProtoMessage() {}
func (*PubKey) Descriptor() ([]byte, []int) {
return fileDescriptor_e0835e68ebdcb224, []int{0}
}
func (m *PubKey) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *PubKey) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_PubKey.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 *PubKey) XXX_Merge(src proto.Message) {
xxx_messageInfo_PubKey.Merge(m, src)
}
func (m *PubKey) XXX_Size() int {
return m.Size()
}
func (m *PubKey) XXX_DiscardUnknown() {
xxx_messageInfo_PubKey.DiscardUnknown(m)
}
var xxx_messageInfo_PubKey proto.InternalMessageInfo
func (m *PubKey) GetKey() []byte {
if m != nil {
return m.Key
}
return nil
}
// PrivKey defines a secp256k1 private key.
type PrivKey struct {
Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
}
func (m *PrivKey) Reset() { *m = PrivKey{} }
func (m *PrivKey) String() string { return proto.CompactTextString(m) }
func (*PrivKey) ProtoMessage() {}
func (*PrivKey) Descriptor() ([]byte, []int) {
return fileDescriptor_e0835e68ebdcb224, []int{1}
}
func (m *PrivKey) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *PrivKey) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_PrivKey.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 *PrivKey) XXX_Merge(src proto.Message) {
xxx_messageInfo_PrivKey.Merge(m, src)
}
func (m *PrivKey) XXX_Size() int {
return m.Size()
}
func (m *PrivKey) XXX_DiscardUnknown() {
xxx_messageInfo_PrivKey.DiscardUnknown(m)
}
var xxx_messageInfo_PrivKey proto.InternalMessageInfo
func (m *PrivKey) GetKey() []byte {
if m != nil {
return m.Key
}
return nil
}
func init() {
proto.RegisterType((*PubKey)(nil), "cosmos.crypto.secp256k1.PubKey")
proto.RegisterType((*PrivKey)(nil), "cosmos.crypto.secp256k1.PrivKey")
}
func init() {
proto.RegisterFile("cosmos/crypto/secp256k1/keys.proto", fileDescriptor_e0835e68ebdcb224)
}
var fileDescriptor_e0835e68ebdcb224 = []byte{
// 185 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x4a, 0xce, 0x2f, 0xce,
0xcd, 0x2f, 0xd6, 0x4f, 0x2e, 0xaa, 0x2c, 0x28, 0xc9, 0xd7, 0x2f, 0x4e, 0x4d, 0x2e, 0x30, 0x32,
0x35, 0xcb, 0x36, 0xd4, 0xcf, 0x4e, 0xad, 0x2c, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12,
0x87, 0xa8, 0xd1, 0x83, 0xa8, 0xd1, 0x83, 0xab, 0x91, 0x12, 0x49, 0xcf, 0x4f, 0xcf, 0x07, 0xab,
0xd1, 0x07, 0xb1, 0x20, 0xca, 0x95, 0x14, 0xb8, 0xd8, 0x02, 0x4a, 0x93, 0xbc, 0x53, 0x2b, 0x85,
0x04, 0xb8, 0x98, 0xb3, 0x53, 0x2b, 0x25, 0x18, 0x15, 0x18, 0x35, 0x78, 0x82, 0x40, 0x4c, 0x2b,
0x96, 0x19, 0x0b, 0xe4, 0x19, 0x94, 0xa4, 0xb9, 0xd8, 0x03, 0x8a, 0x32, 0xcb, 0xb0, 0x2a, 0x71,
0xf2, 0x39, 0xf1, 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39, 0xc6, 0x07, 0x8f, 0xe4, 0x18, 0x27, 0x3c,
0x96, 0x63, 0xb8, 0xf0, 0x58, 0x8e, 0xe1, 0xc6, 0x63, 0x39, 0x86, 0x28, 0xa3, 0xf4, 0xcc, 0x92,
0x8c, 0xd2, 0x24, 0xbd, 0xe4, 0xfc, 0x5c, 0x7d, 0x98, 0xb3, 0xc1, 0x94, 0x6e, 0x71, 0x4a, 0x36,
0xcc, 0x07, 0x20, 0x77, 0x23, 0xbc, 0x91, 0xc4, 0x06, 0x76, 0x93, 0x31, 0x20, 0x00, 0x00, 0xff,
0xff, 0x63, 0x00, 0x68, 0x16, 0xe8, 0x00, 0x00, 0x00,
}
func (m *PubKey) 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 *PubKey) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *PubKey) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if len(m.Key) > 0 {
i -= len(m.Key)
copy(dAtA[i:], m.Key)
i = encodeVarintKeys(dAtA, i, uint64(len(m.Key)))
i--
dAtA[i] = 0xa
}
return len(dAtA) - i, nil
}
func (m *PrivKey) 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 *PrivKey) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *PrivKey) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if len(m.Key) > 0 {
i -= len(m.Key)
copy(dAtA[i:], m.Key)
i = encodeVarintKeys(dAtA, i, uint64(len(m.Key)))
i--
dAtA[i] = 0xa
}
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 *PubKey) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
l = len(m.Key)
if l > 0 {
n += 1 + l + sovKeys(uint64(l))
}
return n
}
func (m *PrivKey) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
l = len(m.Key)
if l > 0 {
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 *PubKey) 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: PubKey: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: PubKey: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Key", 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
}
m.Key = append(m.Key[:0], dAtA[iNdEx:postIndex]...)
if m.Key == nil {
m.Key = []byte{}
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipKeys(dAtA[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthKeys
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthKeys
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *PrivKey) 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: PrivKey: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: PrivKey: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Key", 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
}
m.Key = append(m.Key[:0], dAtA[iNdEx:postIndex]...)
if m.Key == nil {
m.Key = []byte{}
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipKeys(dAtA[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthKeys
}
if (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")
)
+83 -42
View File
@@ -9,12 +9,15 @@ import (
"math/big"
secp256k1 "github.com/btcsuite/btcd/btcec"
"github.com/cosmos/cosmos-sdk/codec"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"golang.org/x/crypto/ripemd160" // nolint: staticcheck // necessary for Bitcoin address format
"github.com/tendermint/tendermint/crypto"
)
var _ crypto.PrivKey = PrivKey{}
var _ cryptotypes.PrivKey = &PrivKey{}
var _ codec.AminoMarshaler = &PrivKey{}
const (
PrivKeySize = 32
@@ -23,42 +26,63 @@ const (
PubKeyName = "tendermint/PubKeySecp256k1"
)
// PrivKey implements PrivKey.
type PrivKey []byte
// Bytes returns the byte representation of the Private Key.
func (privKey PrivKey) Bytes() []byte {
return []byte(privKey)
func (privKey *PrivKey) Bytes() []byte {
return privKey.Key
}
// PubKey performs the point-scalar multiplication from the privKey on the
// generator point to get the pubkey.
func (privKey PrivKey) PubKey() crypto.PubKey {
_, pubkeyObject := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKey)
return PubKey(pubkeyObject.SerializeCompressed())
func (privKey *PrivKey) PubKey() crypto.PubKey {
_, pubkeyObject := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKey.Key)
pk := pubkeyObject.SerializeCompressed()
return &PubKey{Key: pk}
}
// 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 otherSecp, ok := other.(PrivKey); ok {
return subtle.ConstantTimeCompare(privKey[:], otherSecp[:]) == 1
}
return false
// Runs in constant time based on length of the
func (privKey *PrivKey) Equals(other crypto.PrivKey) bool {
return privKey.Type() == other.Type() && subtle.ConstantTimeCompare(privKey.Bytes(), other.Bytes()) == 1
}
func (privKey PrivKey) Type() string {
func (privKey *PrivKey) Type() string {
return keyType
}
// MarshalAmino overrides Amino binary marshalling.
func (privKey PrivKey) MarshalAmino() ([]byte, error) {
return privKey.Key, nil
}
// UnmarshalAmino overrides Amino binary marshalling.
func (privKey *PrivKey) UnmarshalAmino(bz []byte) error {
*privKey = PrivKey{
Key: bz,
}
return nil
}
// MarshalAminoJSON overrides Amino JSON marshalling.
func (privKey PrivKey) MarshalAminoJSON() ([]byte, error) {
// When we marshal to Amino JSON, we don't marshal the "key" field itself,
// just its contents (i.e. the key bytes).
return privKey.MarshalAmino()
}
// UnmarshalAminoJSON overrides Amino JSON marshalling.
func (privKey *PrivKey) UnmarshalAminoJSON(bz []byte) error {
return privKey.UnmarshalAmino(bz)
}
// GenPrivKey generates a new ECDSA private key on curve secp256k1 private key.
// It uses OS randomness to generate the private key.
func GenPrivKey() PrivKey {
return genPrivKey(crypto.CReader())
func GenPrivKey() *PrivKey {
return &PrivKey{Key: genPrivKey(crypto.CReader())}
}
// genPrivKey generates a new secp256k1 private key using the provided reader.
func genPrivKey(rand io.Reader) PrivKey {
func genPrivKey(rand io.Reader) []byte {
var privKeyBytes [PrivKeySize]byte
d := new(big.Int)
for {
@@ -76,7 +100,7 @@ func genPrivKey(rand io.Reader) PrivKey {
}
}
return PrivKey(privKeyBytes[:])
return privKeyBytes[:]
}
var one = new(big.Int).SetInt64(1)
@@ -91,7 +115,7 @@ var one = new(big.Int).SetInt64(1)
//
// NOTE: secret should be the output of a KDF like bcrypt,
// if it's derived from user input.
func GenPrivKeyFromSecret(secret []byte) PrivKey {
func GenPrivKeyFromSecret(secret []byte) *PrivKey {
secHash := sha256.Sum256(secret)
// to guarantee that we have a valid field element, we use the approach of:
// "Suite B Implementers Guide to FIPS 186-3", A.2.1
@@ -107,32 +131,26 @@ func GenPrivKeyFromSecret(secret []byte) PrivKey {
// copy feB over to fixed 32 byte privKey32 and pad (if necessary)
copy(privKey32[32-len(feB):32], feB)
return PrivKey(privKey32)
return &PrivKey{Key: privKey32}
}
//-------------------------------------
var _ crypto.PubKey = PubKey{}
var _ cryptotypes.PubKey = &PubKey{}
var _ codec.AminoMarshaler = &PubKey{}
// PubKeySize is comprised of 32 bytes for one field element
// (the x-coordinate), plus one byte for the parity of the y-coordinate.
const PubKeySize = 33
// PubKey implements crypto.PubKey.
// It is the compressed form of the pubkey. The first byte depends is a 0x02 byte
// if the y-coordinate is the lexicographically largest of the two associated with
// the x-coordinate. Otherwise the first byte is a 0x03.
// This prefix is followed with the x-coordinate.
type PubKey []byte
// Address returns a Bitcoin style addresses: RIPEMD160(SHA256(pubkey))
func (pubKey PubKey) Address() crypto.Address {
if len(pubKey) != PubKeySize {
func (pubKey *PubKey) Address() crypto.Address {
if len(pubKey.Key) != PubKeySize {
panic("length of pubkey is incorrect")
}
hasherSHA256 := sha256.New()
hasherSHA256.Write(pubKey) // does not error
hasherSHA256.Write(pubKey.Key) // does not error
sha := hasherSHA256.Sum(nil)
hasherRIPEMD160 := ripemd160.New()
@@ -141,21 +159,44 @@ func (pubKey PubKey) Address() crypto.Address {
}
// Bytes returns the pubkey byte format.
func (pubKey PubKey) Bytes() []byte {
return []byte(pubKey)
func (pubKey *PubKey) Bytes() []byte {
return pubKey.Key
}
func (pubKey PubKey) String() string {
return fmt.Sprintf("PubKeySecp256k1{%X}", []byte(pubKey))
func (pubKey *PubKey) String() string {
return fmt.Sprintf("PubKeySecp256k1{%X}", pubKey.Key)
}
func (pubKey PubKey) Type() string {
func (pubKey *PubKey) Type() string {
return keyType
}
func (pubKey PubKey) Equals(other crypto.PubKey) bool {
if otherSecp, ok := other.(PubKey); ok {
return bytes.Equal(pubKey[:], otherSecp[:])
func (pubKey *PubKey) Equals(other crypto.PubKey) bool {
return pubKey.Type() == other.Type() && bytes.Equal(pubKey.Bytes(), other.Bytes())
}
// MarshalAmino overrides Amino binary marshalling.
func (pubKey PubKey) MarshalAmino() ([]byte, error) {
return pubKey.Key, nil
}
// UnmarshalAmino overrides Amino binary marshalling.
func (pubKey *PubKey) UnmarshalAmino(bz []byte) error {
*pubKey = PubKey{
Key: bz,
}
return false
return nil
}
// MarshalAminoJSON overrides Amino JSON marshalling.
func (pubKey PubKey) MarshalAminoJSON() ([]byte, error) {
// When we marshal to Amino JSON, we don't marshal the "key" field itself,
// just its contents (i.e. the key bytes).
return pubKey.MarshalAmino()
}
// UnmarshalAminoJSON overrides Amino JSON marshalling.
func (pubKey *PubKey) UnmarshalAminoJSON(bz []byte) error {
return pubKey.UnmarshalAmino(bz)
}
+4 -4
View File
@@ -9,8 +9,8 @@ import (
)
// Sign creates an ECDSA signature on curve Secp256k1, using SHA256 on the msg.
func (privKey PrivKey) Sign(msg []byte) ([]byte, error) {
rsv, err := secp256k1.Sign(crypto.Sha256(msg), privKey[:])
func (privKey *PrivKey) Sign(msg []byte) ([]byte, error) {
rsv, err := secp256k1.Sign(crypto.Sha256(msg), privKey.Key)
if err != nil {
return nil, err
}
@@ -19,6 +19,6 @@ func (privKey PrivKey) Sign(msg []byte) ([]byte, error) {
return rs, nil
}
func (pubKey PubKey) VerifySignature(msg []byte, sig []byte) bool {
return secp256k1.VerifySignature(pubKey[:], crypto.Sha256(msg), sig)
func (pubKey *PrivKey) VerifySignature(msg []byte, sig []byte) bool {
return secp256k1.VerifySignature(pubKey.Key, crypto.Sha256(msg), sig)
}
+2 -2
View File
@@ -15,12 +15,12 @@ func TestPrivKeySecp256k1SignVerify(t *testing.T) {
priv := GenPrivKey()
tests := []struct {
name string
privKey PrivKey
privKey *PrivKey
wantSignErr bool
wantVerifyPasses bool
}{
{name: "valid sign-verify round", privKey: priv, wantSignErr: false, wantVerifyPasses: true},
{name: "invalid private key", privKey: [32]byte{}, wantSignErr: true, wantVerifyPasses: false},
{name: "invalid private key", privKey: &*PrivKey{Key: [32]byte{}}, wantSignErr: true, wantVerifyPasses: false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
+4 -4
View File
@@ -18,8 +18,8 @@ var secp256k1halfN = new(big.Int).Rsh(secp256k1.S256().N, 1)
// Sign creates an ECDSA signature on curve Secp256k1, using SHA256 on the msg.
// The returned signature will be of the form R || S (in lower-S form).
func (privKey PrivKey) Sign(msg []byte) ([]byte, error) {
priv, _ := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKey[:])
func (privKey *PrivKey) Sign(msg []byte) ([]byte, error) {
priv, _ := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKey.Key)
sig, err := priv.Sign(crypto.Sha256(msg))
if err != nil {
return nil, err
@@ -30,11 +30,11 @@ func (privKey PrivKey) Sign(msg []byte) ([]byte, error) {
// VerifyBytes verifies a signature of the form R || S.
// It rejects signatures which are not in lower-S form.
func (pubKey PubKey) VerifySignature(msg []byte, sigStr []byte) bool {
func (pubKey *PubKey) VerifySignature(msg []byte, sigStr []byte) bool {
if len(sigStr) != 64 {
return false
}
pub, err := secp256k1.ParsePubKey(pubKey[:], secp256k1.S256())
pub, err := secp256k1.ParsePubKey(pubKey.Key, secp256k1.S256())
if err != nil {
return false
}
+139 -4
View File
@@ -1,6 +1,7 @@
package secp256k1_test
import (
"encoding/base64"
"encoding/hex"
"math/big"
"testing"
@@ -10,10 +11,13 @@ import (
"github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/crypto/sr25519"
underlyingSecp256k1 "github.com/btcsuite/btcd/btcec"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
)
type keyData struct {
@@ -37,13 +41,13 @@ func TestPubKeySecp256k1Address(t *testing.T) {
addrBbz, _, _ := base58.CheckDecode(d.addr)
addrB := crypto.Address(addrBbz)
var priv secp256k1.PrivKey = privB
var priv secp256k1.PrivKey = secp256k1.PrivKey{Key: privB}
pubKey := priv.PubKey()
pubT, _ := pubKey.(secp256k1.PubKey)
pubT, _ := pubKey.(*secp256k1.PubKey)
addr := pubKey.Address()
assert.Equal(t, pubT, secp256k1.PubKey(pubB), "Expected pub keys to match")
assert.Equal(t, pubT, &secp256k1.PubKey{Key: pubB}, "Expected pub keys to match")
assert.Equal(t, addr, addrB, "Expected addresses to match")
}
}
@@ -108,9 +112,140 @@ func TestGenPrivKeyFromSecret(t *testing.T) {
gotPrivKey := secp256k1.GenPrivKeyFromSecret(tt.secret)
require.NotNil(t, gotPrivKey)
// interpret as a big.Int and make sure it is a valid field element:
fe := new(big.Int).SetBytes(gotPrivKey[:])
fe := new(big.Int).SetBytes(gotPrivKey.Key[:])
require.True(t, fe.Cmp(N) < 0)
require.True(t, fe.Sign() > 0)
})
}
}
func TestPubKeyEquals(t *testing.T) {
secp256K1PubKey := secp256k1.GenPrivKey().PubKey().(*secp256k1.PubKey)
testCases := []struct {
msg string
pubKey cryptotypes.PubKey
other crypto.PubKey
expectEq bool
}{
{
"different bytes",
secp256K1PubKey,
secp256k1.GenPrivKey().PubKey(),
false,
},
{
"equals",
secp256K1PubKey,
&secp256k1.PubKey{
Key: secp256K1PubKey.Key,
},
true,
},
{
"different types",
secp256K1PubKey,
sr25519.GenPrivKey().PubKey(),
false,
},
}
for _, tc := range testCases {
t.Run(tc.msg, func(t *testing.T) {
eq := tc.pubKey.Equals(tc.other)
require.Equal(t, eq, tc.expectEq)
})
}
}
func TestPrivKeyEquals(t *testing.T) {
secp256K1PrivKey := secp256k1.GenPrivKey()
testCases := []struct {
msg string
privKey cryptotypes.PrivKey
other crypto.PrivKey
expectEq bool
}{
{
"different bytes",
secp256K1PrivKey,
secp256k1.GenPrivKey(),
false,
},
{
"equals",
secp256K1PrivKey,
&secp256k1.PrivKey{
Key: secp256K1PrivKey.Key,
},
true,
},
{
"different types",
secp256K1PrivKey,
sr25519.GenPrivKey(),
false,
},
}
for _, tc := range testCases {
t.Run(tc.msg, func(t *testing.T) {
eq := tc.privKey.Equals(tc.other)
require.Equal(t, eq, tc.expectEq)
})
}
}
func TestMarshalAmino(t *testing.T) {
aminoCdc := codec.NewLegacyAmino()
privKey := secp256k1.GenPrivKey()
pubKey := privKey.PubKey().(*secp256k1.PubKey)
testCases := []struct {
desc string
msg codec.AminoMarshaler
typ interface{}
expBinary []byte
expJSON string
}{
{
"secp256k1 private key",
privKey,
&secp256k1.PrivKey{},
append([]byte{32}, privKey.Bytes()...), // Length-prefixed.
"\"" + base64.StdEncoding.EncodeToString(privKey.Bytes()) + "\"",
},
{
"secp256k1 public key",
pubKey,
&secp256k1.PubKey{},
append([]byte{33}, pubKey.Bytes()...), // Length-prefixed.
"\"" + base64.StdEncoding.EncodeToString(pubKey.Bytes()) + "\"",
},
}
for _, tc := range testCases {
t.Run(tc.desc, func(t *testing.T) {
// Do a round trip of encoding/decoding binary.
bz, err := aminoCdc.MarshalBinaryBare(tc.msg)
require.NoError(t, err)
require.Equal(t, tc.expBinary, bz)
err = aminoCdc.UnmarshalBinaryBare(bz, tc.typ)
require.NoError(t, err)
require.Equal(t, tc.msg, tc.typ)
// Do a round trip of encoding/decoding JSON.
bz, err = aminoCdc.MarshalJSON(tc.msg)
require.NoError(t, err)
require.Equal(t, tc.expJSON, string(bz))
err = aminoCdc.UnmarshalJSON(bz, tc.typ)
require.NoError(t, err)
require.Equal(t, tc.msg, tc.typ)
})
}
}
+3 -2
View File
@@ -77,11 +77,12 @@ func (mock LedgerSECP256K1Mock) GetAddressPubKeySECP256K1(derivationPath []uint3
return nil, "", fmt.Errorf("error parsing public key: %v", err)
}
compressedPublicKey := make(csecp256k1.PubKey, csecp256k1.PubKeySize)
compressedPublicKey := make([]byte, csecp256k1.PubKeySize)
copy(compressedPublicKey, cmp.SerializeCompressed())
// Generate the bech32 addr using existing tmcrypto/etc.
addr := sdk.AccAddress(compressedPublicKey.Address()).String()
pub := &csecp256k1.PubKey{Key: compressedPublicKey}
addr := sdk.AccAddress(pub.Address()).String()
return pk, addr, err
}
+4 -4
View File
@@ -246,10 +246,10 @@ func getPubKeyUnsafe(device SECP256K1, path hd.BIP44Params) (tmcrypto.PubKey, er
return nil, fmt.Errorf("error parsing public key: %v", err)
}
compressedPublicKey := make(secp256k1.PubKey, secp256k1.PubKeySize)
compressedPublicKey := make([]byte, secp256k1.PubKeySize)
copy(compressedPublicKey, cmp.SerializeCompressed())
return compressedPublicKey, nil
return &secp256k1.PubKey{Key: compressedPublicKey}, nil
}
// getPubKeyAddr reads the pubkey and the address from a ledger device.
@@ -270,8 +270,8 @@ func getPubKeyAddrSafe(device SECP256K1, path hd.BIP44Params, hrp string) (tmcry
return nil, "", fmt.Errorf("error parsing public key: %v", err)
}
compressedPublicKey := make(secp256k1.PubKey, secp256k1.PubKeySize)
compressedPublicKey := make([]byte, secp256k1.PubKeySize)
copy(compressedPublicKey, cmp.SerializeCompressed())
return compressedPublicKey, addr, nil
return &secp256k1.PubKey{Key: compressedPublicKey}, addr, nil
}
+1 -1
View File
@@ -25,6 +25,6 @@ func init() {
ed25519.PubKeyName, nil)
Cdc.RegisterConcrete(sr25519.PubKey{},
sr25519.PubKeyName, nil)
Cdc.RegisterConcrete(secp256k1.PubKey{},
Cdc.RegisterConcrete(&secp256k1.PubKey{},
secp256k1.PubKeyName, nil)
}
+6 -5
View File
@@ -33,14 +33,14 @@ func NewPubKeyMultisigThreshold(k int, pubkeys []crypto.PubKey) PubKey {
return PubKeyMultisigThreshold{uint(k), pubkeys}
}
// VerifyBytes expects sig to be an amino encoded version of a MultiSignature.
// VerifySignature expects sig to be an amino encoded version of a MultiSignature.
// Returns true iff the multisignature contains k or more signatures
// for the correct corresponding keys,
// and all signatures are valid. (Not just k of the signatures)
// The multisig uses a bitarray, so multiple signatures for the same key is not
// a concern.
//
// NOTE: VerifyMultisignature should preferred to VerifyBytes which only works
// NOTE: VerifyMultisignature should preferred to VerifySignature which only works
// with amino multisignatures.
func (pk PubKeyMultisigThreshold) VerifySignature(msg []byte, marshalledSig []byte) bool {
var sig AminoMultisignature
@@ -140,15 +140,16 @@ func (pk PubKeyMultisigThreshold) Address() crypto.Address {
// Equals returns true iff pk and other both have the same number of keys, and
// all constituent keys are the same, and in the same order.
func (pk PubKeyMultisigThreshold) Equals(other crypto.PubKey) bool {
otherKey, sameType := other.(PubKeyMultisigThreshold)
otherKey, sameType := other.(PubKey)
if !sameType {
return false
}
if pk.K != otherKey.K || len(pk.PubKeys) != len(otherKey.PubKeys) {
otherPubKeys := otherKey.GetPubKeys()
if pk.GetThreshold() != otherKey.GetThreshold() || len(pk.PubKeys) != len(otherPubKeys) {
return false
}
for i := 0; i < len(pk.PubKeys); i++ {
if !pk.PubKeys[i].Equals(otherKey.PubKeys[i]) {
if !pk.PubKeys[i].Equals(otherPubKeys[i]) {
return false
}
}
+56 -13
View File
@@ -4,12 +4,16 @@ import (
"math/rand"
"testing"
proto "github.com/gogo/protobuf/proto"
"github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/crypto/ed25519"
"github.com/tendermint/tendermint/crypto/sr25519"
"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
kmultisig "github.com/cosmos/cosmos-sdk/crypto/keys/multisig"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
"github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/cosmos-sdk/crypto/types/multisig"
@@ -130,22 +134,61 @@ func TestThresholdMultisigDuplicateSignatures(t *testing.T) {
require.Error(t, multisigKey.VerifyMultisignature(signBytesFn, multisignature))
}
// TODO: Fully replace this test with table driven tests
func TestMultiSigPubKeyEquality(t *testing.T) {
msg := []byte{1, 2, 3, 4}
pubkeys, _ := generatePubKeysAndSignatures(5, msg)
pubKey1 := secp256k1.GenPrivKey().PubKey()
pubKey2 := secp256k1.GenPrivKey().PubKey()
pubkeys := []crypto.PubKey{pubKey1, pubKey2}
multisigKey := multisig.NewPubKeyMultisigThreshold(2, pubkeys)
var unmarshalledMultisig multisig.PubKeyMultisigThreshold
multisig.Cdc.MustUnmarshalBinaryBare(multisigKey.Bytes(), &unmarshalledMultisig)
require.True(t, multisigKey.Equals(unmarshalledMultisig))
var other multisig.PubKey
// Ensure that reordering pubkeys is treated as a different pubkey
pubkeysCpy := make([]crypto.PubKey, 5)
copy(pubkeysCpy, pubkeys)
pubkeysCpy[4] = pubkeys[3]
pubkeysCpy[3] = pubkeys[4]
multisigKey2 := multisig.NewPubKeyMultisigThreshold(2, pubkeysCpy)
require.False(t, multisigKey.Equals(multisigKey2))
testCases := []struct {
msg string
malleate func()
expectEq bool
}{
{
"equals",
func() {
var otherPubKey multisig.PubKeyMultisigThreshold
multisig.Cdc.MustUnmarshalBinaryBare(multisigKey.Bytes(), &otherPubKey)
other = otherPubKey
},
true,
},
{
"ensure that reordering pubkeys is treated as a different pubkey",
func() {
pubkeysCpy := make([]crypto.PubKey, 2)
copy(pubkeysCpy, pubkeys)
pubkeysCpy[0] = pubkeys[1]
pubkeysCpy[1] = pubkeys[0]
other = multisig.NewPubKeyMultisigThreshold(2, pubkeysCpy)
},
false,
},
{
"equals with proto pub key",
func() {
anyPubKeys := make([]*codectypes.Any, len(pubkeys))
for i := 0; i < len(pubkeys); i++ {
any, err := codectypes.NewAnyWithValue(pubkeys[i].(proto.Message))
require.NoError(t, err)
anyPubKeys[i] = any
}
other = &kmultisig.LegacyAminoPubKey{Threshold: 2, PubKeys: anyPubKeys}
},
true,
},
}
for _, tc := range testCases {
t.Run(tc.msg, func(t *testing.T) {
tc.malleate()
eq := multisigKey.Equals(other)
require.Equal(t, eq, tc.expectEq)
})
}
}
func TestAddress(t *testing.T) {
+24
View File
@@ -0,0 +1,24 @@
package types
import (
proto "github.com/gogo/protobuf/proto"
tmcrypto "github.com/tendermint/tendermint/crypto"
)
// PubKey interface extends proto.Message
// and tendermint crypto.PubKey
type PubKey interface {
proto.Message
tmcrypto.PubKey
}
// PrivKey interface extends proto.Message
// and tendermint crypto.PrivKey
type PrivKey interface {
proto.Message
tmcrypto.PrivKey
}
type (
Address = tmcrypto.Address
)
+17
View File
@@ -0,0 +1,17 @@
syntax = "proto3";
package cosmos.crypto.multisig;
import "gogoproto/gogo.proto";
import "google/protobuf/any.proto";
option go_package = "github.com/cosmos/cosmos-sdk/crypto/keys/multisig";
// LegacyAminoPubKey specifies a public key type
// which nests multiple public keys and a threshold,
// it uses legacy amino address rules.
message LegacyAminoPubKey {
option (gogoproto.goproto_getters) = false;
uint32 threshold = 1 [(gogoproto.moretags) = "yaml:\"threshold\""];
repeated google.protobuf.Any public_keys = 2 [(gogoproto.customname) = "PubKeys", (gogoproto.moretags) = "yaml:\"pubkeys\""];
}
+22
View File
@@ -0,0 +1,22 @@
syntax = "proto3";
package cosmos.crypto.secp256k1;
import "gogoproto/gogo.proto";
option go_package = "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1";
// PubKey defines a secp256k1 public key
// Key is the compressed form of the pubkey. The first byte depends is a 0x02 byte
// if the y-coordinate is the lexicographically largest of the two associated with
// the x-coordinate. Otherwise the first byte is a 0x03.
// This prefix is followed with the x-coordinate.
message PubKey {
option (gogoproto.goproto_stringer) = false;
bytes key = 1;
}
// PrivKey defines a secp256k1 private key.
message PrivKey {
bytes key = 1;
}
+4 -4
View File
@@ -34,9 +34,9 @@ func (cdc DefaultPublicKeyCodec) Decode(key *types.PublicKey) (crypto.PubKey, er
return nil, fmt.Errorf("wrong length %d for secp256k1 public key", n)
}
res := make(secp256k1.PubKey, secp256k1.PubKeySize)
res := make([]byte, secp256k1.PubKeySize)
copy(res, key.Secp256K1)
return res, nil
return &secp256k1.PubKey{Key: res}, nil
case *types.PublicKey_Ed25519:
n := len(key.Ed25519)
if n != ed25519.PubKeySize {
@@ -79,8 +79,8 @@ func (cdc DefaultPublicKeyCodec) Encode(key crypto.PubKey) (*types.PublicKey, er
return &types.PublicKey{}, nil
}
switch key := key.(type) {
case secp256k1.PubKey:
return &types.PublicKey{Sum: &types.PublicKey_Secp256K1{Secp256K1: key}}, nil
case *secp256k1.PubKey:
return &types.PublicKey{Sum: &types.PublicKey_Secp256K1{Secp256K1: key.Key}}, nil
case ed25519.PubKey:
return &types.PublicKey{Sum: &types.PublicKey_Ed25519{Ed25519: key}}, nil
case sr25519.PubKey:
+5 -3
View File
@@ -18,7 +18,8 @@ import (
var (
// simulation signature values used to estimate gas consumption
simSecp256k1Pubkey = make(secp256k1.PubKey, secp256k1.PubKeySize)
key = make([]byte, secp256k1.PubKeySize)
simSecp256k1Pubkey = &secp256k1.PubKey{Key: key}
simSecp256k1Sig [64]byte
_ authsigning.SigVerifiableTx = (*types.StdTx)(nil) // assert StdTx implements SigVerifiableTx
@@ -27,7 +28,8 @@ var (
func init() {
// This decodes a valid hex string into a sepc256k1Pubkey for use in transaction simulation
bz, _ := hex.DecodeString("035AD6810A47F073553FF30D2FCC7E0D3B1C0B74B61A1AAA2582344037151E143A")
copy(simSecp256k1Pubkey, bz)
copy(key, bz)
simSecp256k1Pubkey.Key = key
}
// SignatureVerificationGasConsumer is the type of function that is used to both
@@ -337,7 +339,7 @@ func DefaultSigVerificationGasConsumer(
meter.ConsumeGas(params.SigVerifyCostED25519, "ante verify: ed25519")
return sdkerrors.Wrap(sdkerrors.ErrInvalidPubKey, "ED25519 public keys are unsupported")
case secp256k1.PubKey:
case *secp256k1.PubKey:
meter.ConsumeGas(params.SigVerifyCostSecp256k1, "ante verify: secp256k1")
return nil
File diff suppressed because it is too large Load Diff