Merge pull request #2125 from nspcc-dev/cli-convert-public

vm/cli: add public key -> address conversion, fix #2121
This commit is contained in:
Roman Khimov 2021-08-13 11:49:49 +03:00 committed by GitHub
commit 4a714425bf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 36 additions and 3 deletions

View file

@ -622,7 +622,7 @@ distribution.
## Conversion utility ## Conversion utility
NeoGo provides conversion utility command to reverse data, convert script NeoGo provides conversion utility command to reverse data, convert script
hashes to/from address, convert data to/from hexadecimal or base64 hashes to/from address, convert public keys to hashes/addresses, convert data to/from hexadecimal or base64
representation. All of this is done by a single `util convert` command like representation. All of this is done by a single `util convert` command like
this: this:
``` ```

View file

@ -8,6 +8,7 @@ import (
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
gio "io"
"math/big" "math/big"
"github.com/btcsuite/btcd/btcec" "github.com/btcsuite/btcd/btcec"
@ -234,9 +235,17 @@ func decodeCompressedY(x *big.Int, ylsb uint, curve elliptic.Curve) (*big.Int, e
func (p *PublicKey) DecodeBytes(data []byte) error { func (p *PublicKey) DecodeBytes(data []byte) error {
b := io.NewBinReaderFromBuf(data) b := io.NewBinReaderFromBuf(data)
p.DecodeBinary(b) p.DecodeBinary(b)
if b.Err != nil {
return b.Err return b.Err
} }
b.ReadB()
if b.Err != gio.EOF {
return errors.New("extra data")
}
return nil
}
// DecodeBinary decodes a PublicKey from the given BinReader using information // DecodeBinary decodes a PublicKey from the given BinReader using information
// about the EC curve to decompress Y point. Secp256r1 is a default value for EC curve. // about the EC curve to decompress Y point. Secp256r1 is a default value for EC curve.
func (p *PublicKey) DecodeBinary(r *io.BinReader) { func (p *PublicKey) DecodeBinary(r *io.BinReader) {
@ -375,7 +384,7 @@ func (p *PublicKey) UnmarshalJSON(data []byte) error {
return errors.New("wrong format") return errors.New("wrong format")
} }
bytes := make([]byte, l-2) bytes := make([]byte, hex.DecodedLen(l-2))
_, err := hex.Decode(bytes, data[1:l-1]) _, err := hex.Decode(bytes, data[1:l-1])
if err != nil { if err != nil {
return err return err

View file

@ -67,6 +67,9 @@ func TestNewPublicKeyFromBytes(t *testing.T) {
pub2, err := NewPublicKeyFromBytes(b, elliptic.P256()) pub2, err := NewPublicKeyFromBytes(b, elliptic.P256())
require.NoError(t, err) require.NoError(t, err)
require.Same(t, pub, pub2) require.Same(t, pub, pub2)
_, err = NewPublicKeyFromBytes([]byte{0x00, 0x01}, elliptic.P256())
require.Error(t, err)
} }
func TestDecodeFromString(t *testing.T) { func TestDecodeFromString(t *testing.T) {

View file

@ -2,6 +2,7 @@ package cli
import ( import (
"bytes" "bytes"
"crypto/elliptic"
"encoding/base64" "encoding/base64"
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
@ -17,6 +18,7 @@ import (
"github.com/abiosoft/ishell/v2" "github.com/abiosoft/ishell/v2"
"github.com/abiosoft/readline" "github.com/abiosoft/readline"
"github.com/nspcc-dev/neo-go/pkg/compiler" "github.com/nspcc-dev/neo-go/pkg/compiler"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/encoding/address"
"github.com/nspcc-dev/neo-go/pkg/encoding/bigint" "github.com/nspcc-dev/neo-go/pkg/encoding/bigint"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
@ -564,6 +566,12 @@ func Parse(args []string) (string, error) {
buf.WriteString(fmt.Sprintf("BE ScriptHash to Address\t%s\n", address.Uint160ToString(val))) buf.WriteString(fmt.Sprintf("BE ScriptHash to Address\t%s\n", address.Uint160ToString(val)))
buf.WriteString(fmt.Sprintf("LE ScriptHash to Address\t%s\n", address.Uint160ToString(val.Reverse()))) buf.WriteString(fmt.Sprintf("LE ScriptHash to Address\t%s\n", address.Uint160ToString(val.Reverse())))
} }
if pub, err := keys.NewPublicKeyFromBytes(rawStr, elliptic.P256()); err == nil {
sh := pub.GetScriptHash()
buf.WriteString(fmt.Sprintf("Public key to BE ScriptHash\t%s\n", sh))
buf.WriteString(fmt.Sprintf("Public key to LE ScriptHash\t%s\n", sh.Reverse()))
buf.WriteString(fmt.Sprintf("Public key to Address\t%s\n", address.Uint160ToString(sh)))
}
buf.WriteString(fmt.Sprintf("Hex to String\t%s\n", fmt.Sprintf("%q", string(rawStr)))) buf.WriteString(fmt.Sprintf("Hex to String\t%s\n", fmt.Sprintf("%q", string(rawStr))))
buf.WriteString(fmt.Sprintf("Hex to Integer\t%s\n", bigint.FromBytes(rawStr))) buf.WriteString(fmt.Sprintf("Hex to Integer\t%s\n", bigint.FromBytes(rawStr)))
buf.WriteString(fmt.Sprintf("Swap Endianness\t%s\n", hex.EncodeToString(slice.CopyReverse(rawStr)))) buf.WriteString(fmt.Sprintf("Swap Endianness\t%s\n", hex.EncodeToString(slice.CopyReverse(rawStr))))

View file

@ -500,6 +500,19 @@ func TestParse(t *testing.T) {
e.checkNextLine(t, "String to Hex.*30303030303030303030303030303030303030303030303030303030303030303030343434333432") e.checkNextLine(t, "String to Hex.*30303030303030303030303030303030303030303030303030303030303030303030343434333432")
e.checkNextLine(t, "String to Base64.*MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDQ0NDM0Mg==") e.checkNextLine(t, "String to Base64.*MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDQ0NDM0Mg==")
}) })
t.Run("public key", func(t *testing.T) {
pub := "02b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc2"
e := newTestVMCLI(t)
e.runProg(t, "parse "+pub)
e.checkNextLine(t, "Public key to BE ScriptHash.*ee9ea22c27e34bd0148fc4108e08f74e8f5048b2")
e.checkNextLine(t, "Public key to LE ScriptHash.*b248508f4ef7088e10c48f14d04be3272ca29eee")
e.checkNextLine(t, "Public key to Address.*Nhfg3TbpwogLvDGVvAvqyThbsHgoSUKwtn")
e.checkNextLine(t, "Hex to String")
e.checkNextLine(t, "Hex to Integer.*-7115107707948693452214836319400158580475150561081357074343221218306172781415678")
e.checkNextLine(t, "Swap Endianness.*c28d7fbfc4bb74d7a76f0496b87d6b203f754c5fed8ac517e3df7b01f42b62b302")
e.checkNextLine(t, "String to Hex.*303262333632326266343031376264666533313763353861656435663463373533663230366237646238393630343666613764373734626263346266376638646332")
e.checkNextLine(t, "String to Base64.*MDJiMzYyMmJmNDAxN2JkZmUzMTdjNThhZWQ1ZjRjNzUzZjIwNmI3ZGI4OTYwNDZmYTdkNzc0YmJjNGJmN2Y4ZGMy")
})
} }
func TestPrintLogo(t *testing.T) { func TestPrintLogo(t *testing.T) {