From db5555bb15096cd399cef29566bf433f31ee5d88 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Wed, 25 Dec 2019 11:25:05 +0300 Subject: [PATCH 01/17] crypto: internalize aes functions into the keys package This is the only user of it and no one outside should care about these details. --- pkg/crypto/{ => keys}/aes256.go | 10 +++++----- pkg/crypto/keys/nep2.go | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) rename pkg/crypto/{ => keys}/aes256.go (87%) diff --git a/pkg/crypto/aes256.go b/pkg/crypto/keys/aes256.go similarity index 87% rename from pkg/crypto/aes256.go rename to pkg/crypto/keys/aes256.go index bb0c97e96..2aa3cd1a3 100644 --- a/pkg/crypto/aes256.go +++ b/pkg/crypto/keys/aes256.go @@ -1,12 +1,12 @@ -package crypto +package keys import ( "crypto/aes" "crypto/cipher" ) -// AESEncrypt encrypts the key with the given source. -func AESEncrypt(src, key []byte) ([]byte, error) { +// aesEncrypt encrypts the key with the given source. +func aesEncrypt(src, key []byte) ([]byte, error) { block, err := aes.NewCipher(key) if err != nil { return nil, err @@ -19,8 +19,8 @@ func AESEncrypt(src, key []byte) ([]byte, error) { return out, nil } -// AESDecrypt decrypts the encrypted source with the given key. -func AESDecrypt(crypted, key []byte) ([]byte, error) { +// aesDecrypt decrypts the encrypted source with the given key. +func aesDecrypt(crypted, key []byte) ([]byte, error) { block, err := aes.NewCipher(key) if err != nil { return nil, err diff --git a/pkg/crypto/keys/nep2.go b/pkg/crypto/keys/nep2.go index 29f1c5661..5d8144439 100644 --- a/pkg/crypto/keys/nep2.go +++ b/pkg/crypto/keys/nep2.go @@ -57,7 +57,7 @@ func NEP2Encrypt(priv *PrivateKey, passphrase string) (s string, err error) { derivedKey2 := derivedKey[32:] xr := xor(priv.Bytes(), derivedKey1) - encrypted, err := crypto.AESEncrypt(xr, derivedKey2) + encrypted, err := aesEncrypt(xr, derivedKey2) if err != nil { return s, err } @@ -98,7 +98,7 @@ func NEP2Decrypt(key, passphrase string) (s string, err error) { derivedKey2 := derivedKey[32:] encryptedBytes := b[7:] - decrypted, err := crypto.AESDecrypt(encryptedBytes, derivedKey2) + decrypted, err := aesDecrypt(encryptedBytes, derivedKey2) if err != nil { return s, err } From ee28fb08f63d76c2a63a5cd10d9ed18aef47862c Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Wed, 25 Dec 2019 11:28:59 +0300 Subject: [PATCH 02/17] crypto: move merkle tree into the hash package It's all about hashes, so it makes sense putting it there. --- pkg/core/block.go | 6 +++--- pkg/crypto/{ => hash}/merkle_tree.go | 5 ++--- pkg/crypto/{ => hash}/merkle_tree_test.go | 2 +- 3 files changed, 6 insertions(+), 7 deletions(-) rename pkg/crypto/{ => hash}/merkle_tree.go (94%) rename pkg/crypto/{ => hash}/merkle_tree_test.go (98%) diff --git a/pkg/core/block.go b/pkg/core/block.go index 1561a3fa5..a7e2b4791 100644 --- a/pkg/core/block.go +++ b/pkg/core/block.go @@ -5,7 +5,7 @@ import ( "fmt" "github.com/CityOfZion/neo-go/pkg/core/transaction" - "github.com/CityOfZion/neo-go/pkg/crypto" + "github.com/CityOfZion/neo-go/pkg/crypto/hash" "github.com/CityOfZion/neo-go/pkg/io" "github.com/CityOfZion/neo-go/pkg/util" "github.com/Workiva/go-datastructures/queue" @@ -30,13 +30,13 @@ func (b *Block) Header() *Header { } } -func merkleTreeFromTransactions(txes []*transaction.Transaction) (*crypto.MerkleTree, error) { +func merkleTreeFromTransactions(txes []*transaction.Transaction) (*hash.MerkleTree, error) { hashes := make([]util.Uint256, len(txes)) for i, tx := range txes { hashes[i] = tx.Hash() } - return crypto.NewMerkleTree(hashes) + return hash.NewMerkleTree(hashes) } // rebuildMerkleRoot rebuilds the merkleroot of the block. diff --git a/pkg/crypto/merkle_tree.go b/pkg/crypto/hash/merkle_tree.go similarity index 94% rename from pkg/crypto/merkle_tree.go rename to pkg/crypto/hash/merkle_tree.go index b1d289806..6e980d0b1 100644 --- a/pkg/crypto/merkle_tree.go +++ b/pkg/crypto/hash/merkle_tree.go @@ -1,9 +1,8 @@ -package crypto +package hash import ( "errors" - "github.com/CityOfZion/neo-go/pkg/crypto/hash" "github.com/CityOfZion/neo-go/pkg/util" ) @@ -66,7 +65,7 @@ func buildMerkleTree(leaves []*MerkleTreeNode) (*MerkleTreeNode, error) { b1 := parents[i].leftChild.hash.BytesBE() b2 := parents[i].rightChild.hash.BytesBE() b1 = append(b1, b2...) - parents[i].hash = hash.DoubleSha256(b1) + parents[i].hash = DoubleSha256(b1) } return buildMerkleTree(parents) diff --git a/pkg/crypto/merkle_tree_test.go b/pkg/crypto/hash/merkle_tree_test.go similarity index 98% rename from pkg/crypto/merkle_tree_test.go rename to pkg/crypto/hash/merkle_tree_test.go index dbd65c03a..89bb573fc 100644 --- a/pkg/crypto/merkle_tree_test.go +++ b/pkg/crypto/hash/merkle_tree_test.go @@ -1,4 +1,4 @@ -package crypto +package hash import ( "testing" From ddad9ac9a3bf1db3710aeb3fdb187ffd7123e23a Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Wed, 25 Dec 2019 14:38:48 +0300 Subject: [PATCH 03/17] hash: simplify merkle tree error handling buildMerkleTree() is internal to the hash package and if anyone calls it with `len(leaves) == 0` he deserves a panic. As it's the only error case in it, we can remove error value return from this function and simplify NewMerkleTree(). --- pkg/crypto/hash/merkle_tree.go | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/pkg/crypto/hash/merkle_tree.go b/pkg/crypto/hash/merkle_tree.go index 6e980d0b1..9d6642efa 100644 --- a/pkg/crypto/hash/merkle_tree.go +++ b/pkg/crypto/hash/merkle_tree.go @@ -25,13 +25,8 @@ func NewMerkleTree(hashes []util.Uint256) (*MerkleTree, error) { } } - root, err := buildMerkleTree(nodes) - if err != nil { - return nil, err - } - return &MerkleTree{ - root: root, + root: buildMerkleTree(nodes), depth: 1, }, nil } @@ -41,12 +36,12 @@ func (t *MerkleTree) Root() util.Uint256 { return t.root.hash } -func buildMerkleTree(leaves []*MerkleTreeNode) (*MerkleTreeNode, error) { +func buildMerkleTree(leaves []*MerkleTreeNode) *MerkleTreeNode { if len(leaves) == 0 { - return nil, errors.New("length of the leaves cannot be zero") + panic("length of leaves cannot be zero") } if len(leaves) == 1 { - return leaves[0], nil + return leaves[0] } parents := make([]*MerkleTreeNode, (len(leaves)+1)/2) From 5dd8d29534229e39cd9a648b0a42795417fb6473 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Wed, 25 Dec 2019 14:43:50 +0300 Subject: [PATCH 04/17] hash: improve merkle tree testing Make it 100% covered. --- pkg/crypto/hash/merkle_tree_test.go | 98 +++++++++++++++++++++++++---- 1 file changed, 86 insertions(+), 12 deletions(-) diff --git a/pkg/crypto/hash/merkle_tree_test.go b/pkg/crypto/hash/merkle_tree_test.go index 89bb573fc..9afd15b1c 100644 --- a/pkg/crypto/hash/merkle_tree_test.go +++ b/pkg/crypto/hash/merkle_tree_test.go @@ -5,19 +5,14 @@ import ( "github.com/CityOfZion/neo-go/pkg/util" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) -func TestComputeMerkleTree(t *testing.T) { - rawHashes := []string{ - "fb5bd72b2d6792d75dc2f1084ffa9e9f70ca85543c717a6b13d9959b452a57d6", - "c56f33fc6ecfcd0c225c4ab356fee59390af8560be0e930faebe74a6daff7c9b", - "602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7", - "3631f66024ca6f5b033d7e0809eb993443374830025af904fb51b0334f127cda", - } - - hashes := make([]util.Uint256, len(rawHashes)) - for i, str := range rawHashes { - hash, _ := util.Uint256DecodeStringLE(str) +func testComputeMerkleTree(t *testing.T, hexHashes []string, result string) { + hashes := make([]util.Uint256, len(hexHashes)) + for i, str := range hexHashes { + hash, err := util.Uint256DecodeStringLE(str) + require.NoError(t, err) hashes[i] = hash } @@ -25,5 +20,84 @@ func TestComputeMerkleTree(t *testing.T) { if err != nil { t.Fatal(err) } - assert.Equal(t, "803ff4abe3ea6533bcc0be574efa02f83ae8fdc651c879056b0d9be336c01bf4", merkle.Root().StringLE()) + assert.Equal(t, result, merkle.Root().StringLE()) + assert.Equal(t, true, merkle.root.IsRoot()) + assert.Equal(t, false, merkle.root.IsLeaf()) + leaf := merkle.root + for leaf.leftChild != nil || leaf.rightChild != nil { + if leaf.leftChild != nil { + leaf = leaf.leftChild + continue + } + leaf = leaf.rightChild + } + assert.Equal(t, true, leaf.IsLeaf()) + assert.Equal(t, false, leaf.IsRoot()) +} + +func TestComputeMerkleTree1(t *testing.T) { + // Mainnet block #0 + rawHashes := []string{ + "fb5bd72b2d6792d75dc2f1084ffa9e9f70ca85543c717a6b13d9959b452a57d6", + "c56f33fc6ecfcd0c225c4ab356fee59390af8560be0e930faebe74a6daff7c9b", + "602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7", + "3631f66024ca6f5b033d7e0809eb993443374830025af904fb51b0334f127cda", + } + res := "803ff4abe3ea6533bcc0be574efa02f83ae8fdc651c879056b0d9be336c01bf4" + testComputeMerkleTree(t, rawHashes, res) +} + +func TestComputeMerkleTree2(t *testing.T) { + // Mainnet block #4635525 + rawHashes := []string{ + "c832ef573136eae2c57a35989d3fb9b3a135d08ffa0faa49d8766f7c1a92ca0f", + "b8606dfeb126a5963d6674f8dbfb786db7f6c27800167c3eef56ff7110ff0ffc", + "498a5d58179002dd9db7b23df657ecf7e1b2e8218bd48dda035e5accc664830a", + "5c350282b448c139adb1f5e3fba0e9326476a38c01ea88876ebc4a882c472d42", + "cea31cc85e7310183561d4f420026984ba48354516f9274c44b52c7f9a5c6107", + "744f985dd5ad6f4ad6376376b48552abf7755b2ebc5c6271950714f848d1cc3a", + "02c5fc225b6ead91f73a7b3ebb19bb30a113baea60f439b654c2811d630a2c48", + "2b3478e0fa91db3a309caeb4d9739f38233c1c189d6fa7e159e24afce9fae082", + "4d50693cee3ac2c976c092620834d4da264583cf15a1d11dd65d0e94861d49e0", + "5f179efae999f8f8086269cedd1fbfaf6e90aadf5369a12737db0fff5905b12e", + "6ef2237b6c8683f626269027050c45cc4be89042ee99e4e89bfd9d9fbd24da19", + "6fd5154af55b4a1e4a1a5272e33238b2a2da12a30fa06af4f740d207e54ed495", + } + res := "42489ad8043a834149cd8e406c90c61411a05a0ca9f8e921b456a00b5d5988d7" + testComputeMerkleTree(t, rawHashes, res) +} + +func TestComputeMerkleTree3(t *testing.T) { + // Mainnet block #2097152 + rawHashes := []string{ + "a7ff2c6aa08d4b979d5f7605aec5a1783c9207c738b5852ed5ff17b37ada649d", + "34fd42c1f47aa306ad2fd0fc04437fd5c828a25b3de59e73b18157253094a8da", + "36458dffd678d9f75ed9f2a28beb58bf1ad739f8899469b8641b0ddea22fcf5d", + "3e8144abe2edda263593f24defd4557d403efa1b4fa839409ac217d6f8a87d3a", + "a1d2cf73841fefcd21ca9986c664518d2af61edcfe3a97b30b3cc58fab4e61f6", + "c1e868aef0e8fd76b95a18e155b1fa65f30d0a4887bc953411553728664725bc", + "52d2fda0fe0fd586063d801c5ba77ca123a790d7e4dae34c53398feab36da721", + "fdf8d4610cb2de35ab4c18d38357b86c52966d149c8975906170dc513cc26345", + "35a26a11ef65d8f7a2424f7ce5915aa1d8bf3449018516003799767c2696197e", + "c9d251abfc20a0d6eeac2d5a93b77a6a0632a679a07decea2c809aead89bb503", + "d92c72873f2929c621ec06433da3053db25ee396b70c83d53abd40801823f66c", + } + res := "09c2dbc88810c350a2e7ace56bb1b371b2a2b5c4744e7a303adace9a2c2bbf6d" + testComputeMerkleTree(t, rawHashes, res) +} + +func TestNewMerkleTreeFailWithoutHashes(t *testing.T) { + var hashes []util.Uint256 + _, err := NewMerkleTree(hashes) + require.Error(t, err) + hashes = make([]util.Uint256, 0) + _, err = NewMerkleTree(hashes) + require.Error(t, err) +} + +func TestBuildMerkleTreeWithoutNodes(t *testing.T) { + var leaves []*MerkleTreeNode + require.Panics(t, func() { buildMerkleTree(leaves) }) + leaves = make([]*MerkleTreeNode, 0) + require.Panics(t, func() { buildMerkleTree(leaves) }) } From 369ac01a27e17d46cbd384c3b994fa78b108d641 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Wed, 25 Dec 2019 15:05:54 +0300 Subject: [PATCH 05/17] base58: move into its own package It doesn't belong to crypto in any way other than it uses hash function internally. --- pkg/crypto/address.go | 5 +++-- pkg/crypto/keys/nep2.go | 6 +++--- pkg/crypto/keys/publickey.go | 4 ++-- pkg/crypto/keys/wif.go | 6 +++--- pkg/{crypto => encoding/base58}/base58.go | 12 +++++++----- pkg/{crypto => encoding/base58}/base58_test.go | 16 ++++++++-------- pkg/encoding/base58/doc.go | 4 ++++ 7 files changed, 30 insertions(+), 23 deletions(-) rename pkg/{crypto => encoding/base58}/base58.go (68%) rename pkg/{crypto => encoding/base58}/base58_test.go (64%) create mode 100644 pkg/encoding/base58/doc.go diff --git a/pkg/crypto/address.go b/pkg/crypto/address.go index 3fb69017d..a289f7275 100644 --- a/pkg/crypto/address.go +++ b/pkg/crypto/address.go @@ -1,6 +1,7 @@ package crypto import ( + "github.com/CityOfZion/neo-go/pkg/encoding/base58" "github.com/CityOfZion/neo-go/pkg/util" ) @@ -9,13 +10,13 @@ import ( func AddressFromUint160(u util.Uint160) string { // Dont forget to prepend the Address version 0x17 (23) A b := append([]byte{0x17}, u.BytesBE()...) - return Base58CheckEncode(b) + return base58.CheckEncode(b) } // Uint160DecodeAddress attempts to decode the given NEO address string // into an Uint160. func Uint160DecodeAddress(s string) (u util.Uint160, err error) { - b, err := Base58CheckDecode(s) + b, err := base58.CheckDecode(s) if err != nil { return u, err } diff --git a/pkg/crypto/keys/nep2.go b/pkg/crypto/keys/nep2.go index 5d8144439..abe478490 100644 --- a/pkg/crypto/keys/nep2.go +++ b/pkg/crypto/keys/nep2.go @@ -5,8 +5,8 @@ import ( "errors" "fmt" - "github.com/CityOfZion/neo-go/pkg/crypto" "github.com/CityOfZion/neo-go/pkg/crypto/hash" + "github.com/CityOfZion/neo-go/pkg/encoding/base58" "golang.org/x/crypto/scrypt" "golang.org/x/text/unicode/norm" ) @@ -72,13 +72,13 @@ func NEP2Encrypt(priv *PrivateKey, passphrase string) (s string, err error) { return s, fmt.Errorf("invalid buffer length: expecting 39 bytes got %d", buf.Len()) } - return crypto.Base58CheckEncode(buf.Bytes()), nil + return base58.CheckEncode(buf.Bytes()), nil } // NEP2Decrypt decrypts an encrypted key using a given passphrase // under the NEP-2 standard. func NEP2Decrypt(key, passphrase string) (s string, err error) { - b, err := crypto.Base58CheckDecode(key) + b, err := base58.CheckDecode(key) if err != nil { return s, nil } diff --git a/pkg/crypto/keys/publickey.go b/pkg/crypto/keys/publickey.go index e166d8031..64cbb3f54 100644 --- a/pkg/crypto/keys/publickey.go +++ b/pkg/crypto/keys/publickey.go @@ -9,8 +9,8 @@ import ( "fmt" "math/big" - "github.com/CityOfZion/neo-go/pkg/crypto" "github.com/CityOfZion/neo-go/pkg/crypto/hash" + "github.com/CityOfZion/neo-go/pkg/encoding/base58" "github.com/CityOfZion/neo-go/pkg/io" "github.com/CityOfZion/neo-go/pkg/vm/opcode" "github.com/pkg/errors" @@ -246,7 +246,7 @@ func (p *PublicKey) Address() string { b = append([]byte{0x17}, b...) - return crypto.Base58CheckEncode(b) + return base58.CheckEncode(b) } // Verify returns true if the signature is valid and corresponds diff --git a/pkg/crypto/keys/wif.go b/pkg/crypto/keys/wif.go index 3e30fc47a..e23fbbd3c 100644 --- a/pkg/crypto/keys/wif.go +++ b/pkg/crypto/keys/wif.go @@ -4,7 +4,7 @@ import ( "bytes" "fmt" - "github.com/CityOfZion/neo-go/pkg/crypto" + "github.com/CityOfZion/neo-go/pkg/encoding/base58" ) const ( @@ -43,13 +43,13 @@ func WIFEncode(key []byte, version byte, compressed bool) (s string, err error) buf.WriteByte(0x01) } - s = crypto.Base58CheckEncode(buf.Bytes()) + s = base58.CheckEncode(buf.Bytes()) return } // WIFDecode decodes the given WIF string into a WIF struct. func WIFDecode(wif string, version byte) (*WIF, error) { - b, err := crypto.Base58CheckDecode(wif) + b, err := base58.CheckDecode(wif) if err != nil { return nil, err } diff --git a/pkg/crypto/base58.go b/pkg/encoding/base58/base58.go similarity index 68% rename from pkg/crypto/base58.go rename to pkg/encoding/base58/base58.go index 9db748022..ccac93aca 100644 --- a/pkg/crypto/base58.go +++ b/pkg/encoding/base58/base58.go @@ -1,4 +1,4 @@ -package crypto +package base58 import ( "bytes" @@ -8,8 +8,9 @@ import ( "github.com/pkg/errors" ) -// Base58CheckDecode decodes the given string. -func Base58CheckDecode(s string) (b []byte, err error) { +// CheckDecode implements a base58-encoded string decoding with hash-based +// checksum check. +func CheckDecode(s string) (b []byte, err error) { b, err = base58.Decode(s) if err != nil { return nil, err @@ -36,8 +37,9 @@ func Base58CheckDecode(s string) (b []byte, err error) { return b, nil } -// Base58CheckEncode encodes b into a base-58 check encoded string. -func Base58CheckEncode(b []byte) string { +// CheckEncode encodes given byte slice into a base58 string with hash-based +// checksum appended to it. +func CheckEncode(b []byte) string { b = append(b, hash.Checksum(b)...) return base58.Encode(b) diff --git a/pkg/crypto/base58_test.go b/pkg/encoding/base58/base58_test.go similarity index 64% rename from pkg/crypto/base58_test.go rename to pkg/encoding/base58/base58_test.go index 5c1388754..e525265ae 100644 --- a/pkg/crypto/base58_test.go +++ b/pkg/encoding/base58/base58_test.go @@ -1,4 +1,4 @@ -package crypto +package base58 import ( "encoding/hex" @@ -7,26 +7,26 @@ import ( "github.com/stretchr/testify/assert" ) -func TestBase58CheckEncodeDecode(t *testing.T) { +func TestCheckEncodeDecode(t *testing.T) { var b58CsumEncoded = "KxhEDBQyyEFymvfJD96q8stMbJMbZUb6D1PmXqBWZDU2WvbvVs9o" var b58CsumDecodedHex = "802bfe58ab6d9fd575bdc3a624e4825dd2b375d64ac033fbc46ea79dbab4f69a3e01" b58CsumDecoded, _ := hex.DecodeString(b58CsumDecodedHex) - encoded := Base58CheckEncode(b58CsumDecoded) - decoded, err := Base58CheckDecode(b58CsumEncoded) + encoded := CheckEncode(b58CsumDecoded) + decoded, err := CheckDecode(b58CsumEncoded) assert.Nil(t, err) assert.Equal(t, encoded, b58CsumEncoded) assert.Equal(t, decoded, b58CsumDecoded) } -func TestBase58CheckDecodeFailures(t *testing.T) { +func TestCheckDecodeFailures(t *testing.T) { badbase58 := "BASE%*" - _, err := Base58CheckDecode(badbase58) + _, err := CheckDecode(badbase58) assert.NotNil(t, err) shortbase58 := "THqY" - _, err = Base58CheckDecode(shortbase58) + _, err = CheckDecode(shortbase58) assert.NotNil(t, err) badcsum := "KxhEDBQyyEFymvfJD96q8stMbJMbZUb6D1PmXqBWZDU2WvbvVs9A" - _, err = Base58CheckDecode(badcsum) + _, err = CheckDecode(badcsum) assert.NotNil(t, err) } diff --git a/pkg/encoding/base58/doc.go b/pkg/encoding/base58/doc.go new file mode 100644 index 000000000..fcac3bba2 --- /dev/null +++ b/pkg/encoding/base58/doc.go @@ -0,0 +1,4 @@ +/* +Package base58 wraps generic base58 encoder with NEO-specific checksumming. +*/ +package base58 From a025b9c42deaca048620636e73b1a2da29274fb3 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Wed, 25 Dec 2019 15:07:11 +0300 Subject: [PATCH 06/17] base58: remove bogus code from CheckDecode No other implementation does that and it looks weird, I see nothing meaninful here. --- pkg/encoding/base58/base58.go | 7 ------- 1 file changed, 7 deletions(-) diff --git a/pkg/encoding/base58/base58.go b/pkg/encoding/base58/base58.go index ccac93aca..9c7398500 100644 --- a/pkg/encoding/base58/base58.go +++ b/pkg/encoding/base58/base58.go @@ -16,13 +16,6 @@ func CheckDecode(s string) (b []byte, err error) { return nil, err } - for i := 0; i < len(s); i++ { - if s[i] != '1' { - break - } - b = append([]byte{0x00}, b...) - } - if len(b) < 5 { return nil, errors.New("invalid base-58 check string: missing checksum") } From e685e9bf9a76629f14d5c27c91f6e8cb50dcc0aa Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Wed, 25 Dec 2019 15:22:02 +0300 Subject: [PATCH 07/17] address: move into its own package Doesn't really belong to the crypto. --- integration/performance_test.go | 4 ++-- pkg/compiler/codegen.go | 4 ++-- pkg/core/block_test.go | 6 +++--- pkg/core/transaction/output.go | 4 ++-- pkg/core/transaction/register_test.go | 4 ++-- pkg/core/transaction/transaction_test.go | 5 ++--- pkg/core/util_test.go | 4 ++-- pkg/{crypto => encoding/address}/address.go | 11 +++++------ .../address}/address_test.go | 8 ++++---- pkg/rpc/param.go | 4 ++-- pkg/rpc/param_test.go | 4 ++-- pkg/rpc/txBuilder.go | 18 +++++++++--------- pkg/rpc/wrappers/asset_state.go | 6 +++--- pkg/rpc/wrappers/validate_address.go | 10 +++++----- pkg/smartcontract/param_context.go | 6 +++--- 15 files changed, 48 insertions(+), 50 deletions(-) rename pkg/{crypto => encoding/address}/address.go (57%) rename pkg/{crypto => encoding/address}/address_test.go (80%) diff --git a/integration/performance_test.go b/integration/performance_test.go index 19e8b5c9b..e4dce2490 100644 --- a/integration/performance_test.go +++ b/integration/performance_test.go @@ -8,8 +8,8 @@ import ( "github.com/CityOfZion/neo-go/pkg/core" "github.com/CityOfZion/neo-go/pkg/core/storage" "github.com/CityOfZion/neo-go/pkg/core/transaction" - "github.com/CityOfZion/neo-go/pkg/crypto" "github.com/CityOfZion/neo-go/pkg/crypto/keys" + "github.com/CityOfZion/neo-go/pkg/encoding/address" "github.com/CityOfZion/neo-go/pkg/network" "github.com/CityOfZion/neo-go/pkg/rpc" "github.com/stretchr/testify/require" @@ -72,7 +72,7 @@ func getWif(t *testing.B) *keys.WIF { // getTX returns Invocation transaction with some random attributes in order to have different hashes. func getTX(t *testing.B, wif *keys.WIF) *transaction.Transaction { fromAddress := wif.PrivateKey.Address() - fromAddressHash, err := crypto.Uint160DecodeAddress(fromAddress) + fromAddressHash, err := address.DecodeUint160(fromAddress) require.NoError(t, err) tx := &transaction.Transaction{ diff --git a/pkg/compiler/codegen.go b/pkg/compiler/codegen.go index 04e47430a..3cd354fd8 100644 --- a/pkg/compiler/codegen.go +++ b/pkg/compiler/codegen.go @@ -11,7 +11,7 @@ import ( "strconv" "strings" - "github.com/CityOfZion/neo-go/pkg/crypto" + "github.com/CityOfZion/neo-go/pkg/encoding/address" "github.com/CityOfZion/neo-go/pkg/io" "github.com/CityOfZion/neo-go/pkg/vm/opcode" ) @@ -673,7 +673,7 @@ func (c *codegen) convertBuiltin(expr *ast.CallExpr) { // contain double quotes that need to be stripped. addressStr := expr.Args[0].(*ast.BasicLit).Value addressStr = strings.Replace(addressStr, "\"", "", 2) - uint160, err := crypto.Uint160DecodeAddress(addressStr) + uint160, err := address.DecodeUint160(addressStr) if err != nil { c.prog.Err = err return diff --git a/pkg/core/block_test.go b/pkg/core/block_test.go index 594041158..48b4d75a8 100644 --- a/pkg/core/block_test.go +++ b/pkg/core/block_test.go @@ -5,8 +5,8 @@ import ( "testing" "github.com/CityOfZion/neo-go/pkg/core/transaction" - "github.com/CityOfZion/neo-go/pkg/crypto" "github.com/CityOfZion/neo-go/pkg/crypto/hash" + "github.com/CityOfZion/neo-go/pkg/encoding/address" "github.com/CityOfZion/neo-go/pkg/io" "github.com/stretchr/testify/assert" ) @@ -34,7 +34,7 @@ func TestDecodeBlock1(t *testing.T) { assert.Equal(t, data["hash"].(string), block.Hash().StringLE()) assert.Equal(t, data["previousblockhash"].(string), block.PrevHash.StringLE()) assert.Equal(t, data["merkleroot"].(string), block.MerkleRoot.StringLE()) - assert.Equal(t, data["nextconsensus"].(string), crypto.AddressFromUint160(block.NextConsensus)) + assert.Equal(t, data["nextconsensus"].(string), address.EncodeUint160(block.NextConsensus)) script := data["script"].(map[string]interface{}) assert.Equal(t, script["invocation"].(string), hex.EncodeToString(block.Script.InvocationScript)) @@ -273,7 +273,7 @@ func TestBlockSizeCalculation(t *testing.T) { assert.Equal(t, 1527894405, int(b.Timestamp)) assert.Equal(t, 2340363, int(b.Index)) - nextConsensus := crypto.AddressFromUint160(b.NextConsensus) + nextConsensus := address.EncodeUint160(b.NextConsensus) assert.Equal(t, "APyEx5f4Zm4oCHwFWiSTaph1fPBxZacYVR", nextConsensus) assert.Equal(t, "4012afae6df64195041e4764b57caa9e27fc2cfc596833163904136ec95816d104b44b3737d0e9f6b1b4445cd3b6a5cc80f6b0935675bc44dba44415eb309832b3404dc95bcf85e4635556a1d618e4ce947b26972992ed74788df5f9501b850ac0b40b7112d1ff30e4ade00369e16f0d13932d1ba76725e7682db072f8e2cd7752b840d12bb7dd45dd3b0e2098db5c67b6de55b7c40164937491fcaca1239b25860251224ead23ab232add78ccccd347239eae50ffc98f50b2a84c60ec5c3d284647a7406fabf6ca241b759af6b71080c0dfad7395632e989226a7e52f8cd2c133aeb2226e6e1aea47666fd81f578405a9f9bbd9d0bc523c3a44d7a5099ddc649feabe5f406188b8ee478731a89beeb76fdbd108eb0071b8f2b8678f40c5a1f387a491314336783255dee8cc5af4bf914dfeaacecc318fc13e02262658e39e8ce0631941b1", hex.EncodeToString(b.Script.InvocationScript)) diff --git a/pkg/core/transaction/output.go b/pkg/core/transaction/output.go index 72dd74f2d..06058d674 100644 --- a/pkg/core/transaction/output.go +++ b/pkg/core/transaction/output.go @@ -3,7 +3,7 @@ package transaction import ( "encoding/json" - "github.com/CityOfZion/neo-go/pkg/crypto" + "github.com/CityOfZion/neo-go/pkg/encoding/address" "github.com/CityOfZion/neo-go/pkg/io" "github.com/CityOfZion/neo-go/pkg/util" ) @@ -52,7 +52,7 @@ func (out *Output) MarshalJSON() ([]byte, error) { return json.Marshal(map[string]interface{}{ "asset": out.AssetID, "value": out.Amount, - "address": crypto.AddressFromUint160(out.ScriptHash), + "address": address.EncodeUint160(out.ScriptHash), "n": out.Position, }) } diff --git a/pkg/core/transaction/register_test.go b/pkg/core/transaction/register_test.go index 7d635802d..37662381b 100644 --- a/pkg/core/transaction/register_test.go +++ b/pkg/core/transaction/register_test.go @@ -4,8 +4,8 @@ import ( "encoding/hex" "testing" - "github.com/CityOfZion/neo-go/pkg/crypto" "github.com/CityOfZion/neo-go/pkg/crypto/keys" + "github.com/CityOfZion/neo-go/pkg/encoding/address" "github.com/CityOfZion/neo-go/pkg/io" "github.com/CityOfZion/neo-go/pkg/util" "github.com/stretchr/testify/assert" @@ -58,7 +58,7 @@ func TestDecodeRegisterTXFromRawString(t *testing.T) { assert.Equal(t, util.Fixed8FromInt64(100000000), txData.Amount) assert.Equal(t, uint8(0), txData.Precision) assert.Equal(t, keys.PublicKey{}, txData.Owner) - assert.Equal(t, "Abf2qMs1pzQb8kYk9RuxtUb9jtRKJVuBJt", crypto.AddressFromUint160(txData.Admin)) + assert.Equal(t, "Abf2qMs1pzQb8kYk9RuxtUb9jtRKJVuBJt", address.EncodeUint160(txData.Admin)) assert.Equal(t, "c56f33fc6ecfcd0c225c4ab356fee59390af8560be0e930faebe74a6daff7c9b", tx.Hash().StringLE()) buf := io.NewBufBinWriter() diff --git a/pkg/core/transaction/transaction_test.go b/pkg/core/transaction/transaction_test.go index 2decc6f7d..5f8ea7e49 100644 --- a/pkg/core/transaction/transaction_test.go +++ b/pkg/core/transaction/transaction_test.go @@ -4,7 +4,7 @@ import ( "encoding/hex" "testing" - "github.com/CityOfZion/neo-go/pkg/crypto" + "github.com/CityOfZion/neo-go/pkg/encoding/address" "github.com/CityOfZion/neo-go/pkg/io" "github.com/CityOfZion/neo-go/pkg/smartcontract" "github.com/CityOfZion/neo-go/pkg/util" @@ -51,8 +51,7 @@ func TestDecodeEncodeClaimTX(t *testing.T) { assert.Equal(t, 0, len(tx.Attributes)) assert.Equal(t, 0, len(tx.Inputs)) assert.Equal(t, 1, len(tx.Outputs)) - address := crypto.AddressFromUint160(tx.Outputs[0].ScriptHash) - assert.Equal(t, "AQJseD8iBmCD4sgfHRhMahmoi9zvopG6yz", address) + assert.Equal(t, "AQJseD8iBmCD4sgfHRhMahmoi9zvopG6yz", address.EncodeUint160(tx.Outputs[0].ScriptHash)) assert.Equal(t, "602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7", tx.Outputs[0].AssetID.StringLE()) assert.Equal(t, tx.Outputs[0].Amount.String(), "0.06247739") invoc := "40456349cec43053009accdb7781b0799c6b591c812768804ab0a0b56b5eae7a97694227fcd33e70899c075848b2cee8fae733faac6865b484d3f7df8949e2aadb" diff --git a/pkg/core/util_test.go b/pkg/core/util_test.go index 42b326286..968a06fc7 100644 --- a/pkg/core/util_test.go +++ b/pkg/core/util_test.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/CityOfZion/neo-go/config" - "github.com/CityOfZion/neo-go/pkg/crypto" + "github.com/CityOfZion/neo-go/pkg/encoding/address" "github.com/stretchr/testify/assert" ) @@ -45,7 +45,7 @@ func TestGetConsensusAddressMainNet(t *testing.T) { } assert.Equal(t, consensusScript, script.String()) - assert.Equal(t, consensusAddr, crypto.AddressFromUint160(script)) + assert.Equal(t, consensusAddr, address.EncodeUint160(script)) } func TestUtilityTokenTX(t *testing.T) { diff --git a/pkg/crypto/address.go b/pkg/encoding/address/address.go similarity index 57% rename from pkg/crypto/address.go rename to pkg/encoding/address/address.go index a289f7275..34638494d 100644 --- a/pkg/crypto/address.go +++ b/pkg/encoding/address/address.go @@ -1,21 +1,20 @@ -package crypto +package address import ( "github.com/CityOfZion/neo-go/pkg/encoding/base58" "github.com/CityOfZion/neo-go/pkg/util" ) -// AddressFromUint160 returns the "NEO address" from the given -// Uint160. -func AddressFromUint160(u util.Uint160) string { +// EncodeUint160 returns the "NEO address" from the given Uint160. +func EncodeUint160(u util.Uint160) string { // Dont forget to prepend the Address version 0x17 (23) A b := append([]byte{0x17}, u.BytesBE()...) return base58.CheckEncode(b) } -// Uint160DecodeAddress attempts to decode the given NEO address string +// DecodeUint160 attempts to decode the given NEO address string // into an Uint160. -func Uint160DecodeAddress(s string) (u util.Uint160, err error) { +func DecodeUint160(s string) (u util.Uint160, err error) { b, err := base58.CheckDecode(s) if err != nil { return u, err diff --git a/pkg/crypto/address_test.go b/pkg/encoding/address/address_test.go similarity index 80% rename from pkg/crypto/address_test.go rename to pkg/encoding/address/address_test.go index 62315eec0..d5b25f50c 100644 --- a/pkg/crypto/address_test.go +++ b/pkg/encoding/address/address_test.go @@ -1,4 +1,4 @@ -package crypto +package address import ( "testing" @@ -13,18 +13,18 @@ func TestUint160DecodeEncodeAddress(t *testing.T) { "AMxkaxFVG8Q1BhnB4fjTA5ZmUTEnnTMJMa", } for _, addr := range addrs { - val, err := Uint160DecodeAddress(addr) + val, err := DecodeUint160(addr) if err != nil { t.Fatal(err) } - assert.Equal(t, addr, AddressFromUint160(val)) + assert.Equal(t, addr, EncodeUint160(val)) } } func TestUint160DecodeKnownAddress(t *testing.T) { address := "AJeAEsmeD6t279Dx4n2HWdUvUmmXQ4iJvP" - val, err := Uint160DecodeAddress(address) + val, err := DecodeUint160(address) if err != nil { t.Fatal(err) } diff --git a/pkg/rpc/param.go b/pkg/rpc/param.go index 7e9f09e66..af612e4a0 100644 --- a/pkg/rpc/param.go +++ b/pkg/rpc/param.go @@ -6,7 +6,7 @@ import ( "encoding/json" "fmt" - "github.com/CityOfZion/neo-go/pkg/crypto" + "github.com/CityOfZion/neo-go/pkg/encoding/address" "github.com/CityOfZion/neo-go/pkg/util" "github.com/pkg/errors" ) @@ -96,7 +96,7 @@ func (p Param) GetUint160FromAddress() (util.Uint160, error) { return util.Uint160{}, err } - return crypto.Uint160DecodeAddress(s) + return address.DecodeUint160(s) } // GetFuncParam returns current parameter as a function call parameter. diff --git a/pkg/rpc/param_test.go b/pkg/rpc/param_test.go index 3023f2d48..fcd0450b8 100644 --- a/pkg/rpc/param_test.go +++ b/pkg/rpc/param_test.go @@ -5,7 +5,7 @@ import ( "encoding/json" "testing" - "github.com/CityOfZion/neo-go/pkg/crypto" + "github.com/CityOfZion/neo-go/pkg/encoding/address" "github.com/CityOfZion/neo-go/pkg/util" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -129,7 +129,7 @@ func TestParamGetUint160FromHex(t *testing.T) { func TestParamGetUint160FromAddress(t *testing.T) { in := "AK2nJJpJr6o664CWJKi1QRXjqeic2zRp8y" - u160, _ := crypto.Uint160DecodeAddress(in) + u160, _ := address.DecodeUint160(in) p := Param{stringT, in} u, err := p.GetUint160FromAddress() assert.Equal(t, u160, u) diff --git a/pkg/rpc/txBuilder.go b/pkg/rpc/txBuilder.go index 4ce978b58..111321a1d 100644 --- a/pkg/rpc/txBuilder.go +++ b/pkg/rpc/txBuilder.go @@ -7,8 +7,8 @@ import ( "strconv" "github.com/CityOfZion/neo-go/pkg/core/transaction" - "github.com/CityOfZion/neo-go/pkg/crypto" "github.com/CityOfZion/neo-go/pkg/crypto/keys" + "github.com/CityOfZion/neo-go/pkg/encoding/address" "github.com/CityOfZion/neo-go/pkg/io" "github.com/CityOfZion/neo-go/pkg/smartcontract" "github.com/CityOfZion/neo-go/pkg/util" @@ -26,17 +26,17 @@ func CreateRawContractTransaction(params ContractTxParams) (*transaction.Transac fromAddress string receiverOutput *transaction.Output - wif, assetID, address, amount, balancer = params.wif, params.assetID, params.address, params.value, params.balancer + wif, assetID, toAddress, amount, balancer = params.wif, params.assetID, params.address, params.value, params.balancer ) fromAddress = wif.PrivateKey.Address() - if fromAddressHash, err = crypto.Uint160DecodeAddress(fromAddress); err != nil { + if fromAddressHash, err = address.DecodeUint160(fromAddress); err != nil { return nil, errs.Wrapf(err, "Failed to take script hash from address: %v", fromAddress) } - if toAddressHash, err = crypto.Uint160DecodeAddress(address); err != nil { - return nil, errs.Wrapf(err, "Failed to take script hash from address: %v", address) + if toAddressHash, err = address.DecodeUint160(toAddress); err != nil { + return nil, errs.Wrapf(err, "Failed to take script hash from address: %v", toAddress) } tx.Attributes = append(tx.Attributes, transaction.Attribute{ @@ -58,12 +58,12 @@ func CreateRawContractTransaction(params ContractTxParams) (*transaction.Transac // AddInputsAndUnspentsToTx adds inputs needed to transaction and one output // with change. -func AddInputsAndUnspentsToTx(tx *transaction.Transaction, address string, assetID util.Uint256, amount util.Fixed8, balancer BalanceGetter) error { - scriptHash, err := crypto.Uint160DecodeAddress(address) +func AddInputsAndUnspentsToTx(tx *transaction.Transaction, addr string, assetID util.Uint256, amount util.Fixed8, balancer BalanceGetter) error { + scriptHash, err := address.DecodeUint160(addr) if err != nil { - return errs.Wrapf(err, "failed to take script hash from address: %v", address) + return errs.Wrapf(err, "failed to take script hash from address: %v", addr) } - inputs, spent, err := balancer.CalculateInputs(address, assetID, amount) + inputs, spent, err := balancer.CalculateInputs(addr, assetID, amount) if err != nil { return errs.Wrap(err, "failed to get inputs") } diff --git a/pkg/rpc/wrappers/asset_state.go b/pkg/rpc/wrappers/asset_state.go index b9b08c3ce..a50d75045 100644 --- a/pkg/rpc/wrappers/asset_state.go +++ b/pkg/rpc/wrappers/asset_state.go @@ -3,7 +3,7 @@ package wrappers import ( "github.com/CityOfZion/neo-go/pkg/core/state" "github.com/CityOfZion/neo-go/pkg/core/transaction" - "github.com/CityOfZion/neo-go/pkg/crypto" + "github.com/CityOfZion/neo-go/pkg/encoding/address" "github.com/CityOfZion/neo-go/pkg/util" ) @@ -37,8 +37,8 @@ func NewAssetState(a *state.Asset) AssetState { FeeMode: a.FeeMode, FeeAddress: a.FeeAddress, Owner: a.Owner.String(), - Admin: crypto.AddressFromUint160(a.Admin), - Issuer: crypto.AddressFromUint160(a.Issuer), + Admin: address.EncodeUint160(a.Admin), + Issuer: address.EncodeUint160(a.Issuer), Expiration: a.Expiration, IsFrozen: a.IsFrozen, } diff --git a/pkg/rpc/wrappers/validate_address.go b/pkg/rpc/wrappers/validate_address.go index cea0ab64a..5580719fe 100644 --- a/pkg/rpc/wrappers/validate_address.go +++ b/pkg/rpc/wrappers/validate_address.go @@ -1,7 +1,7 @@ package wrappers import ( - "github.com/CityOfZion/neo-go/pkg/crypto" + "github.com/CityOfZion/neo-go/pkg/encoding/address" ) // ValidateAddressResponse represents response to validate address call. @@ -12,10 +12,10 @@ type ValidateAddressResponse struct { // ValidateAddress verifies that the address is a correct NEO address // see https://docs.neo.org/en-us/node/cli/2.9.4/api/validateaddress.html -func ValidateAddress(address interface{}) ValidateAddressResponse { - resp := ValidateAddressResponse{Address: address} - if address, ok := address.(string); ok { - _, err := crypto.Uint160DecodeAddress(address) +func ValidateAddress(addr interface{}) ValidateAddressResponse { + resp := ValidateAddressResponse{Address: addr} + if addr, ok := addr.(string); ok { + _, err := address.DecodeUint160(addr) resp.IsValid = err == nil } return resp diff --git a/pkg/smartcontract/param_context.go b/pkg/smartcontract/param_context.go index 48fc79cb5..d2bff6843 100644 --- a/pkg/smartcontract/param_context.go +++ b/pkg/smartcontract/param_context.go @@ -7,8 +7,8 @@ import ( "strings" "unicode/utf8" - "github.com/CityOfZion/neo-go/pkg/crypto" "github.com/CityOfZion/neo-go/pkg/crypto/keys" + "github.com/CityOfZion/neo-go/pkg/encoding/address" "github.com/CityOfZion/neo-go/pkg/io" "github.com/CityOfZion/neo-go/pkg/util" ) @@ -156,7 +156,7 @@ func adjustValToType(typ ParamType, val string) (interface{}, error) { case IntegerType: return strconv.Atoi(val) case Hash160Type: - u, err := crypto.Uint160DecodeAddress(val) + u, err := address.DecodeUint160(val) if err == nil { return hex.EncodeToString(u.BytesBE()), nil } @@ -215,7 +215,7 @@ func inferParamType(val string) ParamType { return BoolType } - _, err = crypto.Uint160DecodeAddress(val) + _, err = address.DecodeUint160(val) if err == nil { return Hash160Type } From 89b6cbf795d4a02df5f8e9e4327e488da5c3a0bb Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Wed, 25 Dec 2019 15:42:18 +0300 Subject: [PATCH 08/17] address: make Prefix overridable As it should be, it's specified in the configuration file (and it should be treated as byte in the config) --- cli/server/server.go | 4 ++++ config/config.go | 2 +- pkg/encoding/address/address.go | 6 +++++- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/cli/server/server.go b/cli/server/server.go index d742e0d1c..965e3fb2a 100644 --- a/cli/server/server.go +++ b/cli/server/server.go @@ -9,6 +9,7 @@ import ( "github.com/CityOfZion/neo-go/config" "github.com/CityOfZion/neo-go/pkg/core" "github.com/CityOfZion/neo-go/pkg/core/storage" + "github.com/CityOfZion/neo-go/pkg/encoding/address" "github.com/CityOfZion/neo-go/pkg/io" "github.com/CityOfZion/neo-go/pkg/network" "github.com/CityOfZion/neo-go/pkg/network/metrics" @@ -361,6 +362,9 @@ func initBlockChain(cfg config.Config) (*core.Blockchain, error) { if err != nil { return nil, cli.NewExitError(fmt.Errorf("could not initialize blockchain: %s", err), 1) } + if cfg.ProtocolConfiguration.AddressVersion != 0 { + address.Prefix = cfg.ProtocolConfiguration.AddressVersion + } return chain, nil } diff --git a/config/config.go b/config/config.go index cf86d9e32..f962ec41c 100644 --- a/config/config.go +++ b/config/config.go @@ -43,7 +43,7 @@ type ( // ProtocolConfiguration represents the protocol config. ProtocolConfiguration struct { Magic NetMode `yaml:"Magic"` - AddressVersion int64 `yaml:"AddressVersion"` + AddressVersion byte `yaml:"AddressVersion"` SecondsPerBlock int `yaml:"SecondsPerBlock"` LowPriorityThreshold float64 `yaml:"LowPriorityThreshold"` MaxTransactionsPerBlock int64 `yaml:"MaxTransactionsPerBlock"` diff --git a/pkg/encoding/address/address.go b/pkg/encoding/address/address.go index 34638494d..62e9404bc 100644 --- a/pkg/encoding/address/address.go +++ b/pkg/encoding/address/address.go @@ -5,10 +5,14 @@ import ( "github.com/CityOfZion/neo-go/pkg/util" ) +// Prefix is the byte used to prepend to addresses when encoding them, it can +// be changed and defaults to 23 (0x17), the standard NEO prefix. +var Prefix = byte(0x17) + // EncodeUint160 returns the "NEO address" from the given Uint160. func EncodeUint160(u util.Uint160) string { // Dont forget to prepend the Address version 0x17 (23) A - b := append([]byte{0x17}, u.BytesBE()...) + b := append([]byte{Prefix}, u.BytesBE()...) return base58.CheckEncode(b) } From c5ceb9128a6b3aa12c6d59a1d936af74e4e665bc Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Wed, 25 Dec 2019 15:50:52 +0300 Subject: [PATCH 09/17] address: check for prefix when decoding --- pkg/encoding/address/address.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pkg/encoding/address/address.go b/pkg/encoding/address/address.go index 62e9404bc..02548d100 100644 --- a/pkg/encoding/address/address.go +++ b/pkg/encoding/address/address.go @@ -1,6 +1,8 @@ package address import ( + "errors" + "github.com/CityOfZion/neo-go/pkg/encoding/base58" "github.com/CityOfZion/neo-go/pkg/util" ) @@ -23,5 +25,8 @@ func DecodeUint160(s string) (u util.Uint160, err error) { if err != nil { return u, err } + if b[0] != Prefix { + return u, errors.New("wrong address prefix") + } return util.Uint160DecodeBytesBE(b[1:21]) } From b7702f3a2e24c3a59cb892812a195efa7db76ef4 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Wed, 25 Dec 2019 15:55:39 +0300 Subject: [PATCH 10/17] address: improve testing, make it 100% covered --- pkg/encoding/address/address_test.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/pkg/encoding/address/address_test.go b/pkg/encoding/address/address_test.go index d5b25f50c..b9bf1f488 100644 --- a/pkg/encoding/address/address_test.go +++ b/pkg/encoding/address/address_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestUint160DecodeEncodeAddress(t *testing.T) { @@ -32,3 +33,18 @@ func TestUint160DecodeKnownAddress(t *testing.T) { assert.Equal(t, "b28427088a3729b2536d10122960394e8be6721f", val.StringLE()) assert.Equal(t, "1f72e68b4e39602912106d53b229378a082784b2", val.String()) } + +func TestUint160DecodeBadBase58(t *testing.T) { + address := "AJeAEsmeD6t279Dx4n2HWdUvUmmXQ4iJv@" + + _, err := DecodeUint160(address) + require.Error(t, err) +} + +func TestUint160DecodeBadPrefix(t *testing.T) { + // The same AJeAEsmeD6t279Dx4n2HWdUvUmmXQ4iJvP key encoded with 0x18 prefix. + address := "AhymDz4vvHLtvaN36CMbzkki7H2U8ENb8F" + + _, err := DecodeUint160(address) + require.Error(t, err) +} From e25133a3859aa05cd0eebf3c4fbf08620e7dec75 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Wed, 25 Dec 2019 16:03:39 +0300 Subject: [PATCH 11/17] keys: reuse address package for address generation Deduplicates code and makes prefix overridable. --- pkg/crypto/keys/publickey.go | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/pkg/crypto/keys/publickey.go b/pkg/crypto/keys/publickey.go index 64cbb3f54..13aba0106 100644 --- a/pkg/crypto/keys/publickey.go +++ b/pkg/crypto/keys/publickey.go @@ -10,7 +10,7 @@ import ( "math/big" "github.com/CityOfZion/neo-go/pkg/crypto/hash" - "github.com/CityOfZion/neo-go/pkg/encoding/base58" + "github.com/CityOfZion/neo-go/pkg/encoding/address" "github.com/CityOfZion/neo-go/pkg/io" "github.com/CityOfZion/neo-go/pkg/vm/opcode" "github.com/pkg/errors" @@ -242,11 +242,9 @@ func (p *PublicKey) Signature() []byte { // Address returns a base58-encoded NEO-specific address based on the key hash. func (p *PublicKey) Address() string { - var b = p.Signature() + sig := hash.Hash160(p.GetVerificationScript()) - b = append([]byte{0x17}, b...) - - return base58.CheckEncode(b) + return address.EncodeUint160(sig) } // Verify returns true if the signature is valid and corresponds From 53e6fbbbf92579ec3f6b71b15539a96c6fc3b131 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Wed, 25 Dec 2019 17:06:38 +0300 Subject: [PATCH 12/17] base58: add a test for a025b9c42deaca048620636e73b1a2da29274fb3 As noted by @fyrchik in #579 comments. --- pkg/encoding/base58/base58_test.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/pkg/encoding/base58/base58_test.go b/pkg/encoding/base58/base58_test.go index e525265ae..de4d90f78 100644 --- a/pkg/encoding/base58/base58_test.go +++ b/pkg/encoding/base58/base58_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestCheckEncodeDecode(t *testing.T) { @@ -30,3 +31,11 @@ func TestCheckDecodeFailures(t *testing.T) { _, err = CheckDecode(badcsum) assert.NotNil(t, err) } + +func TestBase58LeadingZeroes(t *testing.T) { + buf := []byte{0, 0, 0, 1} + b58 := CheckEncode(buf) + dec, err := CheckDecode(b58) + require.NoError(t, err) + require.Equal(t, buf, dec) +} From b246653f6260d9a6c587d23dd340a3a996f8ef97 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Wed, 25 Dec 2019 17:34:18 +0300 Subject: [PATCH 13/17] address: rename functions as per #579 comments Make them more clear to understand. --- integration/performance_test.go | 2 +- pkg/compiler/codegen.go | 2 +- pkg/core/block_test.go | 4 ++-- pkg/core/transaction/output.go | 2 +- pkg/core/transaction/register_test.go | 2 +- pkg/core/transaction/transaction_test.go | 2 +- pkg/core/util_test.go | 2 +- pkg/crypto/keys/publickey.go | 2 +- pkg/encoding/address/address.go | 8 ++++---- pkg/encoding/address/address_test.go | 10 +++++----- pkg/rpc/param.go | 2 +- pkg/rpc/param_test.go | 2 +- pkg/rpc/txBuilder.go | 6 +++--- pkg/rpc/wrappers/asset_state.go | 4 ++-- pkg/rpc/wrappers/validate_address.go | 2 +- pkg/smartcontract/param_context.go | 4 ++-- 16 files changed, 28 insertions(+), 28 deletions(-) diff --git a/integration/performance_test.go b/integration/performance_test.go index e4dce2490..d81c42e58 100644 --- a/integration/performance_test.go +++ b/integration/performance_test.go @@ -72,7 +72,7 @@ func getWif(t *testing.B) *keys.WIF { // getTX returns Invocation transaction with some random attributes in order to have different hashes. func getTX(t *testing.B, wif *keys.WIF) *transaction.Transaction { fromAddress := wif.PrivateKey.Address() - fromAddressHash, err := address.DecodeUint160(fromAddress) + fromAddressHash, err := address.StringToUint160(fromAddress) require.NoError(t, err) tx := &transaction.Transaction{ diff --git a/pkg/compiler/codegen.go b/pkg/compiler/codegen.go index 3cd354fd8..3544a38bc 100644 --- a/pkg/compiler/codegen.go +++ b/pkg/compiler/codegen.go @@ -673,7 +673,7 @@ func (c *codegen) convertBuiltin(expr *ast.CallExpr) { // contain double quotes that need to be stripped. addressStr := expr.Args[0].(*ast.BasicLit).Value addressStr = strings.Replace(addressStr, "\"", "", 2) - uint160, err := address.DecodeUint160(addressStr) + uint160, err := address.StringToUint160(addressStr) if err != nil { c.prog.Err = err return diff --git a/pkg/core/block_test.go b/pkg/core/block_test.go index 48b4d75a8..82118b6ea 100644 --- a/pkg/core/block_test.go +++ b/pkg/core/block_test.go @@ -34,7 +34,7 @@ func TestDecodeBlock1(t *testing.T) { assert.Equal(t, data["hash"].(string), block.Hash().StringLE()) assert.Equal(t, data["previousblockhash"].(string), block.PrevHash.StringLE()) assert.Equal(t, data["merkleroot"].(string), block.MerkleRoot.StringLE()) - assert.Equal(t, data["nextconsensus"].(string), address.EncodeUint160(block.NextConsensus)) + assert.Equal(t, data["nextconsensus"].(string), address.Uint160ToString(block.NextConsensus)) script := data["script"].(map[string]interface{}) assert.Equal(t, script["invocation"].(string), hex.EncodeToString(block.Script.InvocationScript)) @@ -273,7 +273,7 @@ func TestBlockSizeCalculation(t *testing.T) { assert.Equal(t, 1527894405, int(b.Timestamp)) assert.Equal(t, 2340363, int(b.Index)) - nextConsensus := address.EncodeUint160(b.NextConsensus) + nextConsensus := address.Uint160ToString(b.NextConsensus) assert.Equal(t, "APyEx5f4Zm4oCHwFWiSTaph1fPBxZacYVR", nextConsensus) assert.Equal(t, "4012afae6df64195041e4764b57caa9e27fc2cfc596833163904136ec95816d104b44b3737d0e9f6b1b4445cd3b6a5cc80f6b0935675bc44dba44415eb309832b3404dc95bcf85e4635556a1d618e4ce947b26972992ed74788df5f9501b850ac0b40b7112d1ff30e4ade00369e16f0d13932d1ba76725e7682db072f8e2cd7752b840d12bb7dd45dd3b0e2098db5c67b6de55b7c40164937491fcaca1239b25860251224ead23ab232add78ccccd347239eae50ffc98f50b2a84c60ec5c3d284647a7406fabf6ca241b759af6b71080c0dfad7395632e989226a7e52f8cd2c133aeb2226e6e1aea47666fd81f578405a9f9bbd9d0bc523c3a44d7a5099ddc649feabe5f406188b8ee478731a89beeb76fdbd108eb0071b8f2b8678f40c5a1f387a491314336783255dee8cc5af4bf914dfeaacecc318fc13e02262658e39e8ce0631941b1", hex.EncodeToString(b.Script.InvocationScript)) diff --git a/pkg/core/transaction/output.go b/pkg/core/transaction/output.go index 06058d674..e8cf91ea2 100644 --- a/pkg/core/transaction/output.go +++ b/pkg/core/transaction/output.go @@ -52,7 +52,7 @@ func (out *Output) MarshalJSON() ([]byte, error) { return json.Marshal(map[string]interface{}{ "asset": out.AssetID, "value": out.Amount, - "address": address.EncodeUint160(out.ScriptHash), + "address": address.Uint160ToString(out.ScriptHash), "n": out.Position, }) } diff --git a/pkg/core/transaction/register_test.go b/pkg/core/transaction/register_test.go index 37662381b..ba073bbf5 100644 --- a/pkg/core/transaction/register_test.go +++ b/pkg/core/transaction/register_test.go @@ -58,7 +58,7 @@ func TestDecodeRegisterTXFromRawString(t *testing.T) { assert.Equal(t, util.Fixed8FromInt64(100000000), txData.Amount) assert.Equal(t, uint8(0), txData.Precision) assert.Equal(t, keys.PublicKey{}, txData.Owner) - assert.Equal(t, "Abf2qMs1pzQb8kYk9RuxtUb9jtRKJVuBJt", address.EncodeUint160(txData.Admin)) + assert.Equal(t, "Abf2qMs1pzQb8kYk9RuxtUb9jtRKJVuBJt", address.Uint160ToString(txData.Admin)) assert.Equal(t, "c56f33fc6ecfcd0c225c4ab356fee59390af8560be0e930faebe74a6daff7c9b", tx.Hash().StringLE()) buf := io.NewBufBinWriter() diff --git a/pkg/core/transaction/transaction_test.go b/pkg/core/transaction/transaction_test.go index 5f8ea7e49..3403a0c6b 100644 --- a/pkg/core/transaction/transaction_test.go +++ b/pkg/core/transaction/transaction_test.go @@ -51,7 +51,7 @@ func TestDecodeEncodeClaimTX(t *testing.T) { assert.Equal(t, 0, len(tx.Attributes)) assert.Equal(t, 0, len(tx.Inputs)) assert.Equal(t, 1, len(tx.Outputs)) - assert.Equal(t, "AQJseD8iBmCD4sgfHRhMahmoi9zvopG6yz", address.EncodeUint160(tx.Outputs[0].ScriptHash)) + assert.Equal(t, "AQJseD8iBmCD4sgfHRhMahmoi9zvopG6yz", address.Uint160ToString(tx.Outputs[0].ScriptHash)) assert.Equal(t, "602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7", tx.Outputs[0].AssetID.StringLE()) assert.Equal(t, tx.Outputs[0].Amount.String(), "0.06247739") invoc := "40456349cec43053009accdb7781b0799c6b591c812768804ab0a0b56b5eae7a97694227fcd33e70899c075848b2cee8fae733faac6865b484d3f7df8949e2aadb" diff --git a/pkg/core/util_test.go b/pkg/core/util_test.go index 968a06fc7..b2222a56a 100644 --- a/pkg/core/util_test.go +++ b/pkg/core/util_test.go @@ -45,7 +45,7 @@ func TestGetConsensusAddressMainNet(t *testing.T) { } assert.Equal(t, consensusScript, script.String()) - assert.Equal(t, consensusAddr, address.EncodeUint160(script)) + assert.Equal(t, consensusAddr, address.Uint160ToString(script)) } func TestUtilityTokenTX(t *testing.T) { diff --git a/pkg/crypto/keys/publickey.go b/pkg/crypto/keys/publickey.go index 13aba0106..edf033998 100644 --- a/pkg/crypto/keys/publickey.go +++ b/pkg/crypto/keys/publickey.go @@ -244,7 +244,7 @@ func (p *PublicKey) Signature() []byte { func (p *PublicKey) Address() string { sig := hash.Hash160(p.GetVerificationScript()) - return address.EncodeUint160(sig) + return address.Uint160ToString(sig) } // Verify returns true if the signature is valid and corresponds diff --git a/pkg/encoding/address/address.go b/pkg/encoding/address/address.go index 02548d100..e02cca4ce 100644 --- a/pkg/encoding/address/address.go +++ b/pkg/encoding/address/address.go @@ -11,16 +11,16 @@ import ( // be changed and defaults to 23 (0x17), the standard NEO prefix. var Prefix = byte(0x17) -// EncodeUint160 returns the "NEO address" from the given Uint160. -func EncodeUint160(u util.Uint160) string { +// Uint160ToString returns the "NEO address" from the given Uint160. +func Uint160ToString(u util.Uint160) string { // Dont forget to prepend the Address version 0x17 (23) A b := append([]byte{Prefix}, u.BytesBE()...) return base58.CheckEncode(b) } -// DecodeUint160 attempts to decode the given NEO address string +// StringToUint160 attempts to decode the given NEO address string // into an Uint160. -func DecodeUint160(s string) (u util.Uint160, err error) { +func StringToUint160(s string) (u util.Uint160, err error) { b, err := base58.CheckDecode(s) if err != nil { return u, err diff --git a/pkg/encoding/address/address_test.go b/pkg/encoding/address/address_test.go index b9bf1f488..db7d24c03 100644 --- a/pkg/encoding/address/address_test.go +++ b/pkg/encoding/address/address_test.go @@ -14,18 +14,18 @@ func TestUint160DecodeEncodeAddress(t *testing.T) { "AMxkaxFVG8Q1BhnB4fjTA5ZmUTEnnTMJMa", } for _, addr := range addrs { - val, err := DecodeUint160(addr) + val, err := StringToUint160(addr) if err != nil { t.Fatal(err) } - assert.Equal(t, addr, EncodeUint160(val)) + assert.Equal(t, addr, Uint160ToString(val)) } } func TestUint160DecodeKnownAddress(t *testing.T) { address := "AJeAEsmeD6t279Dx4n2HWdUvUmmXQ4iJvP" - val, err := DecodeUint160(address) + val, err := StringToUint160(address) if err != nil { t.Fatal(err) } @@ -37,7 +37,7 @@ func TestUint160DecodeKnownAddress(t *testing.T) { func TestUint160DecodeBadBase58(t *testing.T) { address := "AJeAEsmeD6t279Dx4n2HWdUvUmmXQ4iJv@" - _, err := DecodeUint160(address) + _, err := StringToUint160(address) require.Error(t, err) } @@ -45,6 +45,6 @@ func TestUint160DecodeBadPrefix(t *testing.T) { // The same AJeAEsmeD6t279Dx4n2HWdUvUmmXQ4iJvP key encoded with 0x18 prefix. address := "AhymDz4vvHLtvaN36CMbzkki7H2U8ENb8F" - _, err := DecodeUint160(address) + _, err := StringToUint160(address) require.Error(t, err) } diff --git a/pkg/rpc/param.go b/pkg/rpc/param.go index af612e4a0..1dc57eb07 100644 --- a/pkg/rpc/param.go +++ b/pkg/rpc/param.go @@ -96,7 +96,7 @@ func (p Param) GetUint160FromAddress() (util.Uint160, error) { return util.Uint160{}, err } - return address.DecodeUint160(s) + return address.StringToUint160(s) } // GetFuncParam returns current parameter as a function call parameter. diff --git a/pkg/rpc/param_test.go b/pkg/rpc/param_test.go index fcd0450b8..58cc9b879 100644 --- a/pkg/rpc/param_test.go +++ b/pkg/rpc/param_test.go @@ -129,7 +129,7 @@ func TestParamGetUint160FromHex(t *testing.T) { func TestParamGetUint160FromAddress(t *testing.T) { in := "AK2nJJpJr6o664CWJKi1QRXjqeic2zRp8y" - u160, _ := address.DecodeUint160(in) + u160, _ := address.StringToUint160(in) p := Param{stringT, in} u, err := p.GetUint160FromAddress() assert.Equal(t, u160, u) diff --git a/pkg/rpc/txBuilder.go b/pkg/rpc/txBuilder.go index 111321a1d..6a31f29ec 100644 --- a/pkg/rpc/txBuilder.go +++ b/pkg/rpc/txBuilder.go @@ -31,11 +31,11 @@ func CreateRawContractTransaction(params ContractTxParams) (*transaction.Transac fromAddress = wif.PrivateKey.Address() - if fromAddressHash, err = address.DecodeUint160(fromAddress); err != nil { + if fromAddressHash, err = address.StringToUint160(fromAddress); err != nil { return nil, errs.Wrapf(err, "Failed to take script hash from address: %v", fromAddress) } - if toAddressHash, err = address.DecodeUint160(toAddress); err != nil { + if toAddressHash, err = address.StringToUint160(toAddress); err != nil { return nil, errs.Wrapf(err, "Failed to take script hash from address: %v", toAddress) } tx.Attributes = append(tx.Attributes, @@ -59,7 +59,7 @@ func CreateRawContractTransaction(params ContractTxParams) (*transaction.Transac // AddInputsAndUnspentsToTx adds inputs needed to transaction and one output // with change. func AddInputsAndUnspentsToTx(tx *transaction.Transaction, addr string, assetID util.Uint256, amount util.Fixed8, balancer BalanceGetter) error { - scriptHash, err := address.DecodeUint160(addr) + scriptHash, err := address.StringToUint160(addr) if err != nil { return errs.Wrapf(err, "failed to take script hash from address: %v", addr) } diff --git a/pkg/rpc/wrappers/asset_state.go b/pkg/rpc/wrappers/asset_state.go index a50d75045..5ee365a97 100644 --- a/pkg/rpc/wrappers/asset_state.go +++ b/pkg/rpc/wrappers/asset_state.go @@ -37,8 +37,8 @@ func NewAssetState(a *state.Asset) AssetState { FeeMode: a.FeeMode, FeeAddress: a.FeeAddress, Owner: a.Owner.String(), - Admin: address.EncodeUint160(a.Admin), - Issuer: address.EncodeUint160(a.Issuer), + Admin: address.Uint160ToString(a.Admin), + Issuer: address.Uint160ToString(a.Issuer), Expiration: a.Expiration, IsFrozen: a.IsFrozen, } diff --git a/pkg/rpc/wrappers/validate_address.go b/pkg/rpc/wrappers/validate_address.go index 5580719fe..dfde7b833 100644 --- a/pkg/rpc/wrappers/validate_address.go +++ b/pkg/rpc/wrappers/validate_address.go @@ -15,7 +15,7 @@ type ValidateAddressResponse struct { func ValidateAddress(addr interface{}) ValidateAddressResponse { resp := ValidateAddressResponse{Address: addr} if addr, ok := addr.(string); ok { - _, err := address.DecodeUint160(addr) + _, err := address.StringToUint160(addr) resp.IsValid = err == nil } return resp diff --git a/pkg/smartcontract/param_context.go b/pkg/smartcontract/param_context.go index d2bff6843..b53b0cadd 100644 --- a/pkg/smartcontract/param_context.go +++ b/pkg/smartcontract/param_context.go @@ -156,7 +156,7 @@ func adjustValToType(typ ParamType, val string) (interface{}, error) { case IntegerType: return strconv.Atoi(val) case Hash160Type: - u, err := address.DecodeUint160(val) + u, err := address.StringToUint160(val) if err == nil { return hex.EncodeToString(u.BytesBE()), nil } @@ -215,7 +215,7 @@ func inferParamType(val string) ParamType { return BoolType } - _, err = address.DecodeUint160(val) + _, err = address.StringToUint160(val) if err == nil { return Hash160Type } From 5ac8cae22150dabb05caeb3bbb2d9e782b09fa04 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Wed, 25 Dec 2019 17:44:30 +0300 Subject: [PATCH 14/17] keys: fix bad compressed public key decoding, add a test The error was not propagated properly here. --- pkg/crypto/keys/publickey.go | 1 + pkg/crypto/keys/publickey_test.go | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/pkg/crypto/keys/publickey.go b/pkg/crypto/keys/publickey.go index edf033998..38f4a22a7 100644 --- a/pkg/crypto/keys/publickey.go +++ b/pkg/crypto/keys/publickey.go @@ -189,6 +189,7 @@ func (p *PublicKey) DecodeBinary(r *io.BinReader) { ylsb := uint(prefix & 0x1) y, err = decodeCompressedY(x, ylsb) if err != nil { + r.Err = err return } case 0x04: diff --git a/pkg/crypto/keys/publickey_test.go b/pkg/crypto/keys/publickey_test.go index c7a8f7665..38f80adc1 100644 --- a/pkg/crypto/keys/publickey_test.go +++ b/pkg/crypto/keys/publickey_test.go @@ -63,6 +63,12 @@ func TestDecodeFromString(t *testing.T) { require.Error(t, err) } +func TestDecodeFromStringBadCompressed(t *testing.T) { + str := "02ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + _, err := NewPublicKeyFromString(str) + require.Error(t, err) +} + func TestPubkeyToAddress(t *testing.T) { pubKey, err := NewPublicKeyFromString("031ee4e73a17d8f76dc02532e2620bcb12425b33c0c9f9694cc2caa8226b68cad4") require.NoError(t, err) From 6c471ecd98f88b6538fe907ba12aa80e05210fb5 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Wed, 25 Dec 2019 18:00:25 +0300 Subject: [PATCH 15/17] keys: move IsOnCurve decoding check, add a test for it This check only makes sense for 04-encoded points, because 02 and 03 derive Y from X and they're on the curve by definition. --- pkg/crypto/keys/publickey.go | 14 +++++++------- pkg/crypto/keys/publickey_test.go | 6 ++++++ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/pkg/crypto/keys/publickey.go b/pkg/crypto/keys/publickey.go index 38f4a22a7..422efadca 100644 --- a/pkg/crypto/keys/publickey.go +++ b/pkg/crypto/keys/publickey.go @@ -173,6 +173,8 @@ func (p *PublicKey) DecodeBinary(r *io.BinReader) { return } + p256 := elliptic.P256() + p256Params := p256.Params() // Infinity switch prefix { case 0x00: @@ -202,17 +204,15 @@ func (p *PublicKey) DecodeBinary(r *io.BinReader) { } x = new(big.Int).SetBytes(xbytes) y = new(big.Int).SetBytes(ybytes) + if !p256.IsOnCurve(x, y) { + r.Err = errors.New("encoded point is not on the P256 curve") + return + } default: r.Err = errors.Errorf("invalid prefix %d", prefix) return } - c := elliptic.P256() - cp := c.Params() - if !c.IsOnCurve(x, y) { - r.Err = errors.New("enccoded point is not on the P256 curve") - return - } - if x.Cmp(cp.P) >= 0 || y.Cmp(cp.P) >= 0 { + if x.Cmp(p256Params.P) >= 0 || y.Cmp(p256Params.P) >= 0 { r.Err = errors.New("enccoded point is not correct (X or Y is bigger than P") return } diff --git a/pkg/crypto/keys/publickey_test.go b/pkg/crypto/keys/publickey_test.go index 38f80adc1..98a73a40f 100644 --- a/pkg/crypto/keys/publickey_test.go +++ b/pkg/crypto/keys/publickey_test.go @@ -69,6 +69,12 @@ func TestDecodeFromStringBadCompressed(t *testing.T) { require.Error(t, err) } +func TestDecodeFromStringNotOnCurve(t *testing.T) { + str := "04ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + _, err := NewPublicKeyFromString(str) + require.Error(t, err) +} + func TestPubkeyToAddress(t *testing.T) { pubKey, err := NewPublicKeyFromString("031ee4e73a17d8f76dc02532e2620bcb12425b33c0c9f9694cc2caa8226b68cad4") require.NoError(t, err) From fa0537758fd715d33594ab6a27c9a0e9143949cc Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Wed, 25 Dec 2019 18:01:54 +0300 Subject: [PATCH 16/17] keys: add a test for X/Y > P decoding case --- pkg/crypto/keys/publickey_test.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pkg/crypto/keys/publickey_test.go b/pkg/crypto/keys/publickey_test.go index 98a73a40f..d3f316b28 100644 --- a/pkg/crypto/keys/publickey_test.go +++ b/pkg/crypto/keys/publickey_test.go @@ -69,6 +69,12 @@ func TestDecodeFromStringBadCompressed(t *testing.T) { require.Error(t, err) } +func TestDecodeFromStringBadXMoreThanP(t *testing.T) { + str := "02ffffffff00000001000000000000000000000001ffffffffffffffffffffffff" + _, err := NewPublicKeyFromString(str) + require.Error(t, err) +} + func TestDecodeFromStringNotOnCurve(t *testing.T) { str := "04ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" _, err := NewPublicKeyFromString(str) From 604b2c82407d527875eadcf5d9beba849b564eb6 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Wed, 25 Dec 2019 18:06:25 +0300 Subject: [PATCH 17/17] keys: add a successful test for 04-encoded public key --- pkg/crypto/keys/publickey_test.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pkg/crypto/keys/publickey_test.go b/pkg/crypto/keys/publickey_test.go index d3f316b28..f4aeb28aa 100644 --- a/pkg/crypto/keys/publickey_test.go +++ b/pkg/crypto/keys/publickey_test.go @@ -81,6 +81,12 @@ func TestDecodeFromStringNotOnCurve(t *testing.T) { require.Error(t, err) } +func TestDecodeFromStringUncompressed(t *testing.T) { + str := "046b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5" + _, err := NewPublicKeyFromString(str) + require.NoError(t, err) +} + func TestPubkeyToAddress(t *testing.T) { pubKey, err := NewPublicKeyFromString("031ee4e73a17d8f76dc02532e2620bcb12425b33c0c9f9694cc2caa8226b68cad4") require.NoError(t, err)