uint256: add Reverse(), change String() to be BE

This one makes a little more obvious that we're operating with LE
representations mostly. Refs. #307. See #314 also.
This commit is contained in:
Roman Khimov 2019-08-22 20:33:58 +03:00
parent c1b1b6fca4
commit d5d570f793
16 changed files with 48 additions and 164 deletions

View file

@ -1,77 +0,0 @@
package util
import (
"encoding/hex"
"encoding/json"
"fmt"
"github.com/CityOfZion/neo-go/pkg/wire/util/slice"
)
const uint256Size = 32
// Uint256 is a 32 byte long unsigned integer.
type Uint256 [uint256Size]uint8
// Uint256DecodeString attempts to decode the given string into an Uint256.
func Uint256DecodeString(s string) (u Uint256, err error) {
if len(s) != uint256Size*2 {
return u, fmt.Errorf("expected string size of %d got %d", uint256Size*2, len(s))
}
b, err := hex.DecodeString(s)
if err != nil {
return u, err
}
return Uint256DecodeBytes(b)
}
// Uint256DecodeBytes attempts to decode the given string into an Uint256.
func Uint256DecodeBytes(b []byte) (u Uint256, err error) {
if len(b) != uint256Size {
return u, fmt.Errorf("expected []byte of size %d got %d", uint256Size, len(b))
}
for i := 0; i < uint256Size; i++ {
u[i] = b[i]
}
return u, nil
}
// Bytes returns a byte slice representation of u.
func (u Uint256) Bytes() []byte {
b := make([]byte, uint256Size)
for i := 0; i < uint256Size; i++ {
b[i] = byte(u[i])
}
return b
}
// Reverse reverses the Uint256 object
func (u Uint256) Reverse() Uint256 {
res, _ := Uint256DecodeBytes(u.BytesReverse())
return res
}
// BytesReverse return a reversed byte representation of u.
func (u Uint256) BytesReverse() []byte {
return slice.Reverse(u.Bytes())
}
// Equals returns true if both Uint256 values are the same.
func (u Uint256) Equals(other Uint256) bool {
return u.String() == other.String()
}
// String implements the stringer interface.
func (u Uint256) String() string {
return hex.EncodeToString(u.Bytes())
}
// ReverseString displays a reverse string representation of Uint256.
func (u Uint256) ReverseString() string {
return hex.EncodeToString(slice.Reverse(u.Bytes()))
}
// MarshalJSON implements the json marshaller interface.
func (u Uint256) MarshalJSON() ([]byte, error) {
return json.Marshal(fmt.Sprintf("0x%s", u.String()))
}

View file

@ -1,50 +0,0 @@
package util
import (
"encoding/hex"
"testing"
"github.com/stretchr/testify/assert"
)
func TestUint256DecodeString(t *testing.T) {
hexStr := "f037308fa0ab18155bccfc08485468c112409ea5064595699e98c545f245f32d"
val, err := Uint256DecodeString(hexStr)
if err != nil {
t.Fatal(err)
}
assert.Equal(t, hexStr, val.String())
}
func TestUint256DecodeBytes(t *testing.T) {
hexStr := "f037308fa0ab18155bccfc08485468c112409ea5064595699e98c545f245f32d"
b, err := hex.DecodeString(hexStr)
if err != nil {
t.Fatal(err)
}
val, err := Uint256DecodeBytes(b)
if err != nil {
t.Fatal(err)
}
assert.Equal(t, hexStr, val.String())
}
func TestUInt256Equals(t *testing.T) {
a := "f037308fa0ab18155bccfc08485468c112409ea5064595699e98c545f245f32d"
b := "e287c5b29a1b66092be6803c59c765308ac20287e1b4977fd399da5fc8f66ab5"
ua, err := Uint256DecodeString(a)
if err != nil {
t.Fatal(err)
}
ub, err := Uint256DecodeString(b)
if err != nil {
t.Fatal(err)
}
if ua.Equals(ub) {
t.Fatalf("%s and %s cannot be equal", ua, ub)
}
if !ua.Equals(ua) {
t.Fatalf("%s and %s must be equal", ua, ua)
}
}

View file

@ -30,9 +30,9 @@ func TestDecodeBlock1(t *testing.T) {
assert.Equal(t, uint32(data["index"].(float64)), block.Index)
assert.Equal(t, uint32(data["version"].(float64)), block.Version)
assert.Equal(t, data["hash"].(string), block.Hash().String())
assert.Equal(t, data["previousblockhash"].(string), block.PrevHash.String())
assert.Equal(t, data["merkleroot"].(string), block.MerkleRoot.String())
assert.Equal(t, data["hash"].(string), block.Hash().ReverseString())
assert.Equal(t, data["previousblockhash"].(string), block.PrevHash.ReverseString())
assert.Equal(t, data["merkleroot"].(string), block.MerkleRoot.ReverseString())
assert.Equal(t, data["nextconsensus"].(string), crypto.AddressFromUint160(block.NextConsensus))
script := data["script"].(map[string]interface{})

View file

@ -185,7 +185,7 @@ func getTestBlockchain(t *testing.T) *Blockchain {
func getTestTransaction(txID string, t *testing.T) *transaction.Transaction {
chain := getTestBlockchain(t)
txHash, err := util.Uint256DecodeString(txID)
txHash, err := util.Uint256DecodeReverseString(txID)
require.NoErrorf(t, err, "could not decode string %s to Uint256", txID)
tx, _, err := chain.GetTransaction(txHash)

View file

@ -38,7 +38,7 @@ func CurrentHeaderHeight(s Store) (i uint32, h util.Uint256, err error) {
return
}
i = binary.LittleEndian.Uint32(b[32:36])
h, err = util.Uint256DecodeBytes(b[:32])
h, err = util.Uint256DecodeReverseBytes(b[:32])
return
}

View file

@ -52,7 +52,7 @@ func TestDecodeRegisterTXFromRawString(t *testing.T) {
assert.Equal(t, uint8(0), txData.Precision)
assert.Equal(t, &crypto.PublicKey{}, txData.Owner)
assert.Equal(t, "Abf2qMs1pzQb8kYk9RuxtUb9jtRKJVuBJt", crypto.AddressFromUint160(txData.Admin))
assert.Equal(t, "c56f33fc6ecfcd0c225c4ab356fee59390af8560be0e930faebe74a6daff7c9b", tx.Hash().String())
assert.Equal(t, "c56f33fc6ecfcd0c225c4ab356fee59390af8560be0e930faebe74a6daff7c9b", tx.Hash().ReverseString())
buf := new(bytes.Buffer)
assert.Nil(t, tx.EncodeBinary(buf))

View file

@ -59,7 +59,7 @@ func TestDecodeEncodeClaimTX(t *testing.T) {
assert.Equal(t, 1, len(tx.Outputs))
address := crypto.AddressFromUint160(tx.Outputs[0].ScriptHash)
assert.Equal(t, "AQJseD8iBmCD4sgfHRhMahmoi9zvopG6yz", address)
assert.Equal(t, "602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7", tx.Outputs[0].AssetID.String())
assert.Equal(t, "602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7", tx.Outputs[0].AssetID.ReverseString())
assert.Equal(t, tx.Outputs[0].Amount.String(), "0.06247739")
invoc := "40456349cec43053009accdb7781b0799c6b591c812768804ab0a0b56b5eae7a97694227fcd33e70899c075848b2cee8fae733faac6865b484d3f7df8949e2aadb"
verif := "2103945fae1ed3c31d778f149192b76734fcc951b400ba3598faa81ff92ebe477eacac"
@ -74,7 +74,7 @@ func TestDecodeEncodeClaimTX(t *testing.T) {
assert.Equal(t, rawClaimTX, hex.EncodeToString(buf.Bytes()))
hash := "2c6a45547b3898318e400e541628990a07acb00f3b9a15a8e966ae49525304da"
assert.Equal(t, hash, tx.hash.String())
assert.Equal(t, hash, tx.hash.ReverseString())
}
func TestDecodeEncodeInvocationTX(t *testing.T) {

View file

@ -20,7 +20,7 @@ func TestGenesisBlockMainNet(t *testing.T) {
}
expect := "d42561e3d30e15be6400b6df2f328e02d2bf6354c41dce433bc57687c82144bf"
assert.Equal(t, expect, block.Hash().String())
assert.Equal(t, expect, block.Hash().ReverseString())
}
func TestGetConsensusAddressMainNet(t *testing.T) {
@ -51,11 +51,11 @@ func TestGetConsensusAddressMainNet(t *testing.T) {
func TestUtilityTokenTX(t *testing.T) {
expect := "602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7"
tx := utilityTokenTX()
assert.Equal(t, expect, tx.Hash().String())
assert.Equal(t, expect, tx.Hash().ReverseString())
}
func TestGoverningTokenTX(t *testing.T) {
expect := "c56f33fc6ecfcd0c225c4ab356fee59390af8560be0e930faebe74a6daff7c9b"
tx := governingTokenTX()
assert.Equal(t, expect, tx.Hash().String())
assert.Equal(t, expect, tx.Hash().ReverseString())
}

View file

@ -17,7 +17,7 @@ func TestComputeMerkleTree(t *testing.T) {
hashes := make([]util.Uint256, len(rawHashes))
for i, str := range rawHashes {
hash, _ := util.Uint256DecodeString(str)
hash, _ := util.Uint256DecodeReverseString(str)
hashes[i] = hash
}
@ -25,5 +25,5 @@ func TestComputeMerkleTree(t *testing.T) {
if err != nil {
t.Fatal(err)
}
assert.Equal(t, "803ff4abe3ea6533bcc0be574efa02f83ae8fdc651c879056b0d9be336c01bf4", merkle.Root().String())
assert.Equal(t, "803ff4abe3ea6533bcc0be574efa02f83ae8fdc651c879056b0d9be336c01bf4", merkle.Root().ReverseString())
}

View file

@ -57,7 +57,7 @@ func (s NeoScanServer) CalculateInputs(address string, assetIdUint util.Uint256,
selected = util.Fixed8(0)
us []*Unspent
assetUnspent Unspent
assetId = GlobalAssets[assetIdUint.String()]
assetId = GlobalAssets[assetIdUint.ReverseString()]
)
if us, err = s.GetBalance(address); err != nil {
return nil, util.Fixed8(0), errs.Wrapf(err, "Cannot get balance for address %v", address)

View file

@ -139,7 +139,7 @@ func (c *Client) SendToAddress(asset util.Uint256, address string, amount util.F
response.ID = resp.ID
response.JSONRPC = resp.JSONRPC
response.Result = &TxResponse{
TxID: rawTx.Hash().String(),
TxID: rawTx.Hash().ReverseString(),
}
return response, nil
}

View file

@ -107,7 +107,7 @@ func (s *Server) methodHandler(w http.ResponseWriter, req *Request, reqParams Pa
Methods:
switch req.Method {
case "getbestblockhash":
results = s.chain.CurrentBlockHash().String()
results = s.chain.CurrentBlockHash().ReverseString()
case "getblock":
var hash util.Uint256
@ -120,7 +120,7 @@ Methods:
switch param.Type {
case "string":
hash, err = util.Uint256DecodeString(param.StringVal)
hash, err = util.Uint256DecodeReverseString(param.StringVal)
if err != nil {
resultsErr = errInvalidParams
break Methods
@ -204,7 +204,7 @@ Methods:
break Methods
}
paramAssetID, err := util.Uint256DecodeString(param.StringVal)
paramAssetID, err := util.Uint256DecodeReverseString(param.StringVal)
if err != nil {
resultsErr = errInvalidParams
break
@ -253,7 +253,7 @@ func (s *Server) getrawtransaction(reqParams Params) (interface{}, error) {
param0, err := reqParams.ValueWithType(0, "string")
if err != nil {
resultsErr = err
} else if txHash, err := util.Uint256DecodeString(param0.StringVal); err != nil {
} else if txHash, err := util.Uint256DecodeReverseString(param0.StringVal); err != nil {
resultsErr = errInvalidParams
} else if tx, height, err := s.chain.GetTransaction(txHash); err != nil {
err = errors.Wrapf(err, "Invalid transaction hash: %s", txHash)

View file

@ -214,7 +214,7 @@ func (p StackParam) TryParse(dest interface{}) error {
*dest = data
return nil
case *util.Uint256:
if *dest, err = util.Uint256DecodeBytes(data); err != nil {
if *dest, err = util.Uint256DecodeReverseBytes(data); err != nil {
return err
}
return nil

View file

@ -90,7 +90,7 @@ func TestStackParam_UnmarshalJSON(t *testing.T) {
if err != nil {
t.Errorf("error while unmarhsalling: %v", err)
}
h256, err := util.Uint256DecodeString("f037308fa0ab18155bccfc08485468c112409ea5064595699e98c545f245f32d")
h256, err := util.Uint256DecodeReverseString("f037308fa0ab18155bccfc08485468c112409ea5064595699e98c545f245f32d")
if err != nil {
t.Errorf("unmarshal error: %v", err)
}
@ -149,7 +149,7 @@ func TestStackParam_TryParse(t *testing.T) {
Value: data,
}
)
expectedUint256, err = util.Uint256DecodeString(hash256)
expectedUint256, err = util.Uint256DecodeReverseString(hash256)
if err != nil {
t.Fatal(err)
}

View file

@ -13,8 +13,8 @@ const uint256Size = 32
// Uint256 is a 32 byte long unsigned integer.
type Uint256 [uint256Size]uint8
// Uint256DecodeString attempts to decode the given string into an Uint256.
func Uint256DecodeString(s string) (u Uint256, err error) {
// Uint256DecodeReverseString attempts to decode the given string (in LE representation) into an Uint256.
func Uint256DecodeReverseString(s string) (u Uint256, err error) {
if len(s) != uint256Size*2 {
return u, fmt.Errorf("expected string size of %d got %d", uint256Size*2, len(s))
}
@ -22,11 +22,11 @@ func Uint256DecodeString(s string) (u Uint256, err error) {
if err != nil {
return u, err
}
return Uint256DecodeBytes(b)
return Uint256DecodeReverseBytes(b)
}
// Uint256DecodeBytes attempts to decode the given string into an Uint256.
func Uint256DecodeBytes(b []byte) (u Uint256, err error) {
// Uint256DecodeReverseBytes attempts to decode the given string (in LE representation) into an Uint256.
func Uint256DecodeReverseBytes(b []byte) (u Uint256, err error) {
b = ArrayReverse(b)
if len(b) != uint256Size {
return u, fmt.Errorf("expected []byte of size %d got %d", uint256Size, len(b))
@ -40,6 +40,12 @@ func (u Uint256) Bytes() []byte {
return u[:]
}
// Reverse reverses the Uint256 object
func (u Uint256) Reverse() Uint256 {
res, _ := Uint256DecodeReverseBytes(u.Bytes())
return res
}
// BytesReverse return a reversed byte representation of u.
func (u Uint256) BytesReverse() []byte {
return ArrayReverse(u.Bytes())
@ -52,7 +58,12 @@ func (u Uint256) Equals(other Uint256) bool {
// String implements the stringer interface.
func (u Uint256) String() string {
return hex.EncodeToString(ArrayReverse(u.Bytes()))
return hex.EncodeToString(u.Bytes())
}
// ReverseString produces string representation of Uint256 with LE byte order.
func (u Uint256) ReverseString() string {
return hex.EncodeToString(u.BytesReverse())
}
// UnmarshalJSON implements the json unmarshaller interface.
@ -62,7 +73,7 @@ func (u *Uint256) UnmarshalJSON(data []byte) (err error) {
return err
}
js = strings.TrimPrefix(js, "0x")
*u, err = Uint256DecodeString(js)
*u, err = Uint256DecodeReverseString(js)
return err
}
@ -73,7 +84,7 @@ func (u Uint256) Size() int {
// MarshalJSON implements the json marshaller interface.
func (u Uint256) MarshalJSON() ([]byte, error) {
return []byte(`"0x` + u.String() + `"`), nil
return []byte(`"0x` + u.ReverseString() + `"`), nil
}
// CompareTo compares two Uint256 with each other. Possible output: 1, -1, 0

View file

@ -9,7 +9,7 @@ import (
func TestUint256UnmarshalJSON(t *testing.T) {
str := "f037308fa0ab18155bccfc08485468c112409ea5064595699e98c545f245f32d"
expected, err := Uint256DecodeString(str)
expected, err := Uint256DecodeReverseString(str)
if err != nil {
t.Fatal(err)
}
@ -36,11 +36,11 @@ func TestUint256UnmarshalJSON(t *testing.T) {
func TestUint256DecodeString(t *testing.T) {
hexStr := "f037308fa0ab18155bccfc08485468c112409ea5064595699e98c545f245f32d"
val, err := Uint256DecodeString(hexStr)
val, err := Uint256DecodeReverseString(hexStr)
if err != nil {
t.Fatal(err)
}
assert.Equal(t, hexStr, val.String())
assert.Equal(t, hexStr, val.ReverseString())
}
func TestUint256DecodeBytes(t *testing.T) {
@ -49,22 +49,22 @@ func TestUint256DecodeBytes(t *testing.T) {
if err != nil {
t.Fatal(err)
}
val, err := Uint256DecodeBytes(b)
val, err := Uint256DecodeReverseBytes(b)
if err != nil {
t.Fatal(err)
}
assert.Equal(t, hexStr, val.String())
assert.Equal(t, hexStr, val.ReverseString())
}
func TestUInt256Equals(t *testing.T) {
a := "f037308fa0ab18155bccfc08485468c112409ea5064595699e98c545f245f32d"
b := "e287c5b29a1b66092be6803c59c765308ac20287e1b4977fd399da5fc8f66ab5"
ua, err := Uint256DecodeString(a)
ua, err := Uint256DecodeReverseString(a)
if err != nil {
t.Fatal(err)
}
ub, err := Uint256DecodeString(b)
ub, err := Uint256DecodeReverseString(b)
if err != nil {
t.Fatal(err)
}