github.com/okex/exchain@v1.8.0/libs/tendermint/crypto/encoding/amino/amino.go (about) 1 package cryptoamino 2 3 import ( 4 "bytes" 5 "errors" 6 "reflect" 7 8 "github.com/okex/exchain/libs/tendermint/crypto" 9 "github.com/okex/exchain/libs/tendermint/crypto/ed25519" 10 "github.com/okex/exchain/libs/tendermint/crypto/multisig" 11 "github.com/okex/exchain/libs/tendermint/crypto/secp256k1" 12 "github.com/okex/exchain/libs/tendermint/crypto/sr25519" 13 "github.com/tendermint/go-amino" 14 ) 15 16 var cdc = amino.NewCodec() 17 18 // nameTable is used to map public key concrete types back 19 // to their registered amino names. This should eventually be handled 20 // by amino. Example usage: 21 // nameTable[reflect.TypeOf(ed25519.PubKeyEd25519{})] = ed25519.PubKeyAminoName 22 var nameTable = make(map[reflect.Type]string, 3) 23 24 func init() { 25 // NOTE: It's important that there be no conflicts here, 26 // as that would change the canonical representations, 27 // and therefore change the address. 28 // TODO: Remove above note when 29 // https://github.com/tendermint/go-amino/issues/9 30 // is resolved 31 RegisterAmino(cdc) 32 33 // TODO: Have amino provide a way to go from concrete struct to route directly. 34 // Its currently a private API 35 nameTable[reflect.TypeOf(ed25519.PubKeyEd25519{})] = ed25519.PubKeyAminoName 36 nameTable[reflect.TypeOf(sr25519.PubKeySr25519{})] = sr25519.PubKeyAminoName 37 nameTable[reflect.TypeOf(secp256k1.PubKeySecp256k1{})] = secp256k1.PubKeyAminoName 38 nameTable[reflect.TypeOf(multisig.PubKeyMultisigThreshold{})] = multisig.PubKeyMultisigThresholdAminoRoute 39 } 40 41 // PubkeyAminoName returns the amino route of a pubkey 42 // cdc is currently passed in, as eventually this will not be using 43 // a package level codec. 44 func PubkeyAminoName(cdc *amino.Codec, key crypto.PubKey) (string, bool) { 45 route, found := nameTable[reflect.TypeOf(key)] 46 return route, found 47 } 48 49 // RegisterAmino registers all crypto related types in the given (amino) codec. 50 func RegisterAmino(cdc *amino.Codec) { 51 // These are all written here instead of 52 cdc.RegisterInterface((*crypto.PubKey)(nil), nil) 53 cdc.RegisterConcrete(ed25519.PubKeyEd25519{}, 54 ed25519.PubKeyAminoName, nil) 55 cdc.RegisterConcrete(sr25519.PubKeySr25519{}, 56 sr25519.PubKeyAminoName, nil) 57 cdc.RegisterConcrete(secp256k1.PubKeySecp256k1{}, 58 secp256k1.PubKeyAminoName, nil) 59 cdc.RegisterConcrete(multisig.PubKeyMultisigThreshold{}, 60 multisig.PubKeyMultisigThresholdAminoRoute, nil) 61 62 cdc.RegisterInterface((*crypto.PrivKey)(nil), nil) 63 cdc.RegisterConcrete(ed25519.PrivKeyEd25519{}, 64 ed25519.PrivKeyAminoName, nil) 65 cdc.RegisterConcrete(sr25519.PrivKeySr25519{}, 66 sr25519.PrivKeyAminoName, nil) 67 cdc.RegisterConcrete(secp256k1.PrivKeySecp256k1{}, 68 secp256k1.PrivKeyAminoName, nil) 69 } 70 71 // RegisterKeyType registers an external key type to allow decoding it from bytes 72 func RegisterKeyType(o interface{}, name string) { 73 cdc.RegisterConcrete(o, name, nil) 74 nameTable[reflect.TypeOf(o)] = name 75 } 76 77 // PrivKeyFromBytes unmarshals private key bytes and returns a PrivKey 78 func PrivKeyFromBytes(privKeyBytes []byte) (privKey crypto.PrivKey, err error) { 79 err = cdc.UnmarshalBinaryBare(privKeyBytes, &privKey) 80 return 81 } 82 83 // PubKeyFromBytes unmarshals public key bytes and returns a PubKey 84 func PubKeyFromBytes(pubKeyBytes []byte) (pubKey crypto.PubKey, err error) { 85 err = cdc.UnmarshalBinaryBare(pubKeyBytes, &pubKey) 86 return 87 } 88 89 // hard code here for performance 90 var typePubKeySecp256k1Prefix = []byte{0xeb, 0x5a, 0xe9, 0x87} 91 var typePubKeyEd25519Prefix = []byte{0x16, 0x24, 0xde, 0x64} 92 var typePubKeySr25519Prefix = []byte{0x0d, 0xfb, 0x10, 0x05} 93 94 const typePrefixAndSizeLen = 4 + 1 95 const aminoTypePrefix = 4 96 97 // unmarshalPubKeyFromAminoFast does a fast path for amino decodes. 98 func unmarshalPubKeyFromAminoFast(data []byte) (crypto.PubKey, error) { 99 if len(data) < aminoTypePrefix { 100 return nil, errors.New("pubkey raw data size error") 101 } 102 if data[0] == 0x00 { 103 return nil, errors.New("unmarshal pubkey with disamb do not implement") 104 } 105 106 prefix := data[0:aminoTypePrefix] 107 data = data[aminoTypePrefix:] 108 109 if bytes.Compare(typePubKeySecp256k1Prefix, prefix) == 0 { 110 sub, err := amino.DecodeByteSliceWithoutCopy(&data) 111 if err != nil { 112 return nil, err 113 } 114 if len(sub) != secp256k1.PubKeySecp256k1Size && len(data) != 0 { 115 return nil, errors.New("pubkey secp256k1 size error") 116 } 117 pubKey := secp256k1.PubKeySecp256k1{} 118 copy(pubKey[:], sub) 119 return pubKey, nil 120 } else if bytes.Compare(typePubKeyEd25519Prefix, prefix) == 0 { 121 sub, err := amino.DecodeByteSliceWithoutCopy(&data) 122 if err != nil { 123 return nil, err 124 } 125 if len(sub) != ed25519.PubKeyEd25519Size && len(data) != 0 { 126 return nil, errors.New("pubkey ed25519 size error") 127 } 128 pubKey := ed25519.PubKeyEd25519{} 129 copy(pubKey[:], sub) 130 return pubKey, nil 131 } else if bytes.Compare(typePubKeySr25519Prefix, prefix) == 0 { 132 sub, err := amino.DecodeByteSliceWithoutCopy(&data) 133 if err != nil { 134 return nil, err 135 } 136 if len(sub) != sr25519.PubKeySr25519Size && len(data) != 0 { 137 return nil, errors.New("pubkey sr25519 size error") 138 } 139 pubKey := sr25519.PubKeySr25519{} 140 copy(pubKey[:], sub) 141 return pubKey, nil 142 } else { 143 return nil, errors.New("unmarshal pubkey with unknown type") 144 } 145 } 146 147 // UnmarshalPubKeyFromAmino decode pubkey from amino bytes, 148 // bytes should start with type prefix 149 func UnmarshalPubKeyFromAmino(cdc *amino.Codec, data []byte) (crypto.PubKey, error) { 150 var pubkey crypto.PubKey 151 var err error 152 pubkey, err = unmarshalPubKeyFromAminoFast(data) 153 if err != nil { 154 var pubkeyTmp crypto.PubKey 155 err = cdc.UnmarshalBinaryBare(data, &pubkeyTmp) 156 pubkey = pubkeyTmp 157 } 158 return pubkey, err 159 } 160 161 func MarshalPubKeyToAmino(cdc *amino.Codec, key crypto.PubKey) (data []byte, err error) { 162 switch key.(type) { 163 case secp256k1.PubKeySecp256k1: 164 data = make([]byte, 0, secp256k1.PubKeySecp256k1Size+typePrefixAndSizeLen) 165 data = append(data, typePubKeySecp256k1Prefix...) 166 data = append(data, byte(secp256k1.PubKeySecp256k1Size)) 167 keyData := key.(secp256k1.PubKeySecp256k1) 168 data = append(data, keyData[:]...) 169 return data, nil 170 case ed25519.PubKeyEd25519: 171 data = make([]byte, 0, ed25519.PubKeyEd25519Size+typePrefixAndSizeLen) 172 data = append(data, typePubKeyEd25519Prefix...) 173 data = append(data, byte(ed25519.PubKeyEd25519Size)) 174 keyData := key.(ed25519.PubKeyEd25519) 175 data = append(data, keyData[:]...) 176 return data, nil 177 case sr25519.PubKeySr25519: 178 data = make([]byte, 0, sr25519.PubKeySr25519Size+typePrefixAndSizeLen) 179 data = append(data, typePubKeySr25519Prefix...) 180 data = append(data, byte(sr25519.PubKeySr25519Size)) 181 keyData := key.(sr25519.PubKeySr25519) 182 data = append(data, keyData[:]...) 183 return data, nil 184 } 185 data, err = cdc.MarshalBinaryBare(key) 186 if err != nil { 187 return nil, err 188 } 189 return data, nil 190 } 191 192 func MarshalPubKeyAminoTo(cdc *amino.Codec, key crypto.PubKey, buf *bytes.Buffer) error { 193 switch keyData := key.(type) { 194 case secp256k1.PubKeySecp256k1: 195 buf.Write(typePubKeySecp256k1Prefix) 196 buf.WriteByte(byte(secp256k1.PubKeySecp256k1Size)) 197 buf.Write(keyData[:]) 198 return nil 199 case ed25519.PubKeyEd25519: 200 buf.Write(typePubKeyEd25519Prefix) 201 buf.WriteByte(byte(ed25519.PubKeyEd25519Size)) 202 buf.Write(keyData[:]) 203 return nil 204 case sr25519.PubKeySr25519: 205 buf.Write(typePubKeySr25519Prefix) 206 buf.WriteByte(byte(sr25519.PubKeySr25519Size)) 207 buf.Write(keyData[:]) 208 return nil 209 } 210 data, err := cdc.MarshalBinaryBare(key) 211 if err != nil { 212 return err 213 } 214 buf.Write(data) 215 return nil 216 } 217 218 func PubKeyAminoSize(pubKey crypto.PubKey, cdc *amino.Codec) int { 219 switch k := pubKey.(type) { 220 case secp256k1.PubKeySecp256k1: 221 return amino.PrefixBytesLen + k.AminoSize(cdc) 222 case ed25519.PubKeyEd25519: 223 return amino.PrefixBytesLen + k.AminoSize(cdc) 224 case sr25519.PubKeySr25519: 225 return amino.PrefixBytesLen + k.AminoSize(cdc) 226 } 227 228 if sizer, ok := pubKey.(amino.Sizer); ok { 229 var typePrefix [8]byte 230 tpl, err := cdc.GetTypePrefix(pubKey, typePrefix[:]) 231 if err != nil { 232 return 0 233 } 234 return tpl + sizer.AminoSize(cdc) 235 } else { 236 encodedPubKey, err := cdc.MarshalBinaryBare(pubKey) 237 if err != nil { 238 return 0 239 } 240 return len(encodedPubKey) 241 } 242 }