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["index"].(float64)), block.Index)
assert.Equal(t, uint32(data["version"].(float64)), block.Version) assert.Equal(t, uint32(data["version"].(float64)), block.Version)
assert.Equal(t, data["hash"].(string), block.Hash().String()) assert.Equal(t, data["hash"].(string), block.Hash().ReverseString())
assert.Equal(t, data["previousblockhash"].(string), block.PrevHash.String()) assert.Equal(t, data["previousblockhash"].(string), block.PrevHash.ReverseString())
assert.Equal(t, data["merkleroot"].(string), block.MerkleRoot.String()) assert.Equal(t, data["merkleroot"].(string), block.MerkleRoot.ReverseString())
assert.Equal(t, data["nextconsensus"].(string), crypto.AddressFromUint160(block.NextConsensus)) assert.Equal(t, data["nextconsensus"].(string), crypto.AddressFromUint160(block.NextConsensus))
script := data["script"].(map[string]interface{}) 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 { func getTestTransaction(txID string, t *testing.T) *transaction.Transaction {
chain := getTestBlockchain(t) 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) require.NoErrorf(t, err, "could not decode string %s to Uint256", txID)
tx, _, err := chain.GetTransaction(txHash) tx, _, err := chain.GetTransaction(txHash)

View file

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

View file

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

View file

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

View file

@ -20,7 +20,7 @@ func TestGenesisBlockMainNet(t *testing.T) {
} }
expect := "d42561e3d30e15be6400b6df2f328e02d2bf6354c41dce433bc57687c82144bf" expect := "d42561e3d30e15be6400b6df2f328e02d2bf6354c41dce433bc57687c82144bf"
assert.Equal(t, expect, block.Hash().String()) assert.Equal(t, expect, block.Hash().ReverseString())
} }
func TestGetConsensusAddressMainNet(t *testing.T) { func TestGetConsensusAddressMainNet(t *testing.T) {
@ -51,11 +51,11 @@ func TestGetConsensusAddressMainNet(t *testing.T) {
func TestUtilityTokenTX(t *testing.T) { func TestUtilityTokenTX(t *testing.T) {
expect := "602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7" expect := "602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7"
tx := utilityTokenTX() tx := utilityTokenTX()
assert.Equal(t, expect, tx.Hash().String()) assert.Equal(t, expect, tx.Hash().ReverseString())
} }
func TestGoverningTokenTX(t *testing.T) { func TestGoverningTokenTX(t *testing.T) {
expect := "c56f33fc6ecfcd0c225c4ab356fee59390af8560be0e930faebe74a6daff7c9b" expect := "c56f33fc6ecfcd0c225c4ab356fee59390af8560be0e930faebe74a6daff7c9b"
tx := governingTokenTX() 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)) hashes := make([]util.Uint256, len(rawHashes))
for i, str := range rawHashes { for i, str := range rawHashes {
hash, _ := util.Uint256DecodeString(str) hash, _ := util.Uint256DecodeReverseString(str)
hashes[i] = hash hashes[i] = hash
} }
@ -25,5 +25,5 @@ func TestComputeMerkleTree(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) 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) selected = util.Fixed8(0)
us []*Unspent us []*Unspent
assetUnspent Unspent assetUnspent Unspent
assetId = GlobalAssets[assetIdUint.String()] assetId = GlobalAssets[assetIdUint.ReverseString()]
) )
if us, err = s.GetBalance(address); err != nil { if us, err = s.GetBalance(address); err != nil {
return nil, util.Fixed8(0), errs.Wrapf(err, "Cannot get balance for address %v", address) 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.ID = resp.ID
response.JSONRPC = resp.JSONRPC response.JSONRPC = resp.JSONRPC
response.Result = &TxResponse{ response.Result = &TxResponse{
TxID: rawTx.Hash().String(), TxID: rawTx.Hash().ReverseString(),
} }
return response, nil return response, nil
} }

View file

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

View file

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

View file

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

View file

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

View file

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