You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

224 lines
6.3 KiB

  1. package cryptoamino
  2. import (
  3. "reflect"
  4. "testing"
  5. "github.com/stretchr/testify/assert"
  6. "github.com/stretchr/testify/require"
  7. amino "github.com/tendermint/go-amino"
  8. "github.com/tendermint/tendermint/crypto"
  9. "github.com/tendermint/tendermint/crypto/ed25519"
  10. "github.com/tendermint/tendermint/crypto/secp256k1"
  11. "github.com/tendermint/tendermint/crypto/sr25519"
  12. tmjson "github.com/tendermint/tendermint/libs/json"
  13. )
  14. type AminoMarshal interface {
  15. AminoMarshal() ([]byte, error)
  16. AminoUnmarshal([]byte) error
  17. }
  18. func checkAminoBinary(t *testing.T, src, dst interface{}, size int) {
  19. // Marshal to binary bytes.
  20. bz, err := cdc.MarshalBinaryBare(src)
  21. require.Nil(t, err, "%+v", err)
  22. if byterSrc, ok := src.(AminoMarshal); ok {
  23. // Make sure this is compatible with current (Bytes()) encoding.
  24. bza, err := byterSrc.AminoMarshal()
  25. assert.NoError(t, err)
  26. assert.Equal(t, bza, bz, "Amino binary vs Bytes() mismatch")
  27. }
  28. // Make sure we have the expected length.
  29. assert.Equal(t, size, len(bz), "Amino binary size mismatch")
  30. // Unmarshal.
  31. err = cdc.UnmarshalBinaryBare(bz, dst)
  32. require.Nil(t, err, "%+v", err)
  33. }
  34. func checkJSON(t *testing.T, src interface{}, dst interface{}, isNil bool) {
  35. // Marshal to JSON bytes.
  36. js, err := tmjson.Marshal(src)
  37. require.Nil(t, err, "%+v", err)
  38. if isNil {
  39. assert.Equal(t, string(js), `null`)
  40. } else {
  41. assert.Contains(t, string(js), `"type":`)
  42. assert.Contains(t, string(js), `"value":`)
  43. }
  44. // Unmarshal.
  45. err = tmjson.Unmarshal(js, dst)
  46. require.Nil(t, err, "%+v", err)
  47. }
  48. func TestKeyEncodings(t *testing.T) {
  49. cases := []struct {
  50. privKey crypto.PrivKey
  51. privSize, pubSize, sigSize int // binary sizes
  52. }{
  53. {
  54. privKey: ed25519.GenPrivKey(),
  55. privSize: 69,
  56. pubSize: 37,
  57. sigSize: 65,
  58. },
  59. {
  60. privKey: sr25519.GenPrivKey(),
  61. privSize: 37,
  62. pubSize: 37,
  63. sigSize: 65,
  64. },
  65. {
  66. privKey: secp256k1.GenPrivKey(),
  67. privSize: 37,
  68. pubSize: 38,
  69. sigSize: 65,
  70. },
  71. }
  72. for tcIndex, tc := range cases {
  73. // Check (de/en)codings of PrivKeys.
  74. var priv2, priv3 crypto.PrivKey
  75. checkAminoBinary(t, tc.privKey, &priv2, tc.privSize)
  76. assert.EqualValues(t, tc.privKey, priv2, "tc #%d", tcIndex)
  77. checkJSON(t, tc.privKey, &priv3, false) // TODO also check Prefix bytes.
  78. assert.EqualValues(t, tc.privKey, priv3, "tc #%d", tcIndex)
  79. // Check (de/en)codings of Signatures.
  80. var sig1, sig2 []byte
  81. sig1, err := tc.privKey.Sign([]byte("something"))
  82. assert.NoError(t, err, "tc #%d", tcIndex)
  83. checkAminoBinary(t, sig1, &sig2, tc.sigSize)
  84. assert.EqualValues(t, sig1, sig2, "tc #%d", tcIndex)
  85. // Check (de/en)codings of PubKeys.
  86. pubKey := tc.privKey.PubKey()
  87. var pub2, pub3 crypto.PubKey
  88. checkAminoBinary(t, pubKey, &pub2, tc.pubSize)
  89. assert.EqualValues(t, pubKey, pub2, "tc #%d", tcIndex)
  90. checkJSON(t, pubKey, &pub3, false) // TODO also check Prefix bytes.
  91. assert.EqualValues(t, pubKey, pub3, "tc #%d", tcIndex)
  92. }
  93. }
  94. func TestNilEncodings(t *testing.T) {
  95. // Check nil Signature.
  96. var a, b []byte
  97. checkJSON(t, &a, &b, true)
  98. assert.EqualValues(t, a, b)
  99. // Check nil PubKey.
  100. var c, d crypto.PubKey
  101. checkJSON(t, &c, &d, true)
  102. assert.EqualValues(t, c, d)
  103. // Check nil PrivKey.
  104. var e, f crypto.PrivKey
  105. checkJSON(t, &e, &f, true)
  106. assert.EqualValues(t, e, f)
  107. }
  108. func TestPubKeyInvalidDataProperReturnsEmpty(t *testing.T) {
  109. pk, err := PubKeyFromBytes([]byte("foo"))
  110. require.NotNil(t, err)
  111. require.Nil(t, pk)
  112. }
  113. func TestPubkeyAminoName(t *testing.T) {
  114. tests := []struct {
  115. key crypto.PubKey
  116. want string
  117. found bool
  118. }{
  119. {ed25519.PubKey{}, ed25519.PubKeyAminoName, true},
  120. {sr25519.PubKey{}, sr25519.PubKeyAminoName, true},
  121. {secp256k1.PubKey{}, secp256k1.PubKeyAminoName, true},
  122. }
  123. for i, tc := range tests {
  124. got, found := PubkeyAminoName(cdc, tc.key)
  125. require.Equal(t, tc.found, found, "not equal on tc %d", i)
  126. if tc.found {
  127. require.Equal(t, tc.want, got, "not equal on tc %d", i)
  128. }
  129. }
  130. }
  131. var _ crypto.PrivKey = testPriv{}
  132. var _ crypto.PubKey = testPub{}
  133. var testCdc = amino.NewCodec()
  134. type testPriv []byte
  135. func (privkey testPriv) PubKey() crypto.PubKey { return testPub{} }
  136. func (privkey testPriv) Bytes() []byte {
  137. return testCdc.MustMarshalBinaryBare(privkey)
  138. }
  139. func (privkey testPriv) Sign(msg []byte) ([]byte, error) { return []byte{}, nil }
  140. func (privkey testPriv) Equals(other crypto.PrivKey) bool { return true }
  141. func (privkey testPriv) Type() string { return "testPriv" }
  142. type testPub []byte
  143. func (key testPub) Address() crypto.Address { return crypto.Address{} }
  144. func (key testPub) Bytes() []byte {
  145. return testCdc.MustMarshalBinaryBare(key)
  146. }
  147. func (key testPub) VerifyBytes(msg []byte, sig []byte) bool { return true }
  148. func (key testPub) Equals(other crypto.PubKey) bool { return true }
  149. func (key testPub) String() string { return "" }
  150. func (key testPub) Type() string { return "testPub" }
  151. var (
  152. privAminoName = "registerTest/Priv"
  153. pubAminoName = "registerTest/Pub"
  154. )
  155. func TestRegisterKeyType(t *testing.T) {
  156. RegisterAmino(testCdc)
  157. testCdc.RegisterConcrete(testPriv{}, privAminoName, nil)
  158. testCdc.RegisterConcrete(testPub{}, pubAminoName, nil)
  159. pub := testPub{0x1}
  160. priv := testPriv{0x2}
  161. // Check to make sure key cannot be decoded before registering
  162. _, err := PrivKeyFromBytes(priv.Bytes())
  163. require.Error(t, err)
  164. _, err = PubKeyFromBytes(pub.Bytes())
  165. require.Error(t, err)
  166. // Check that name is not registered
  167. _, found := PubkeyAminoName(testCdc, pub)
  168. require.False(t, found)
  169. // Register key types
  170. RegisterKeyType(testPriv{}, privAminoName)
  171. RegisterKeyType(testPub{}, pubAminoName)
  172. // Name should exist after registering
  173. name, found := PubkeyAminoName(testCdc, pub)
  174. require.True(t, found)
  175. require.Equal(t, name, pubAminoName)
  176. // Decode keys using the encoded bytes from encoding with the other codec
  177. decodedPriv, err := PrivKeyFromBytes(priv.Bytes())
  178. require.NoError(t, err)
  179. require.Equal(t, priv, decodedPriv)
  180. decodedPub, err := PubKeyFromBytes(pub.Bytes())
  181. require.NoError(t, err)
  182. require.Equal(t, pub, decodedPub)
  183. // Reset module codec after testing
  184. cdc = amino.NewCodec()
  185. nameTable = make(map[reflect.Type]string, 3)
  186. RegisterAmino(cdc)
  187. nameTable[reflect.TypeOf(ed25519.PubKey{})] = ed25519.PubKeyAminoName
  188. nameTable[reflect.TypeOf(sr25519.PubKey{})] = sr25519.PubKeyAminoName
  189. nameTable[reflect.TypeOf(secp256k1.PubKey{})] = secp256k1.PubKeyAminoName
  190. }