Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RPC wrapper for simple arrays #2792

Merged
merged 2 commits into from
Nov 15, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 79 additions & 0 deletions pkg/rpcclient/unwrap/unwrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,42 @@ func Array(r *result.Invoke, err error) ([]stackitem.Item, error) {
return arr, nil
}

// ArrayOfBools checks the result for correct state (HALT) and then extracts a
// slice of boolean values from the returned stack item.
func ArrayOfBools(r *result.Invoke, err error) ([]bool, error) {
a, err := Array(r, err)
if err != nil {
return nil, err
}
res := make([]bool, len(a))
for i := range a {
b, err := a[i].TryBool()
if err != nil {
return nil, fmt.Errorf("element %d is not a boolean: %w", i, err)
}
res[i] = b
}
return res, nil
}

// ArrayOfBigInts checks the result for correct state (HALT) and then extracts a
// slice of (big) integer values from the returned stack item.
func ArrayOfBigInts(r *result.Invoke, err error) ([]*big.Int, error) {
a, err := Array(r, err)
if err != nil {
return nil, err
}
res := make([]*big.Int, len(a))
for i := range a {
v, err := a[i].TryInteger()
if err != nil {
return nil, fmt.Errorf("element %d is not an integer: %w", i, err)
}
res[i] = v
}
return res, nil
}

// ArrayOfBytes checks the result for correct state (HALT) and then extracts a
// slice of byte slices from the returned stack item.
func ArrayOfBytes(r *result.Invoke, err error) ([][]byte, error) {
Expand All @@ -214,6 +250,27 @@ func ArrayOfBytes(r *result.Invoke, err error) ([][]byte, error) {
return res, nil
}

// ArrayOfUTB8Strings checks the result for correct state (HALT) and then extracts a
// slice of UTF-8 strings from the returned stack item.
func ArrayOfUTF8Strings(r *result.Invoke, err error) ([]string, error) {
a, err := Array(r, err)
if err != nil {
return nil, err
}
res := make([]string, len(a))
for i := range a {
b, err := a[i].TryBytes()
if err != nil {
return nil, fmt.Errorf("element %d is not a byte string: %w", i, err)
}
if !utf8.Valid(b) {
return nil, fmt.Errorf("element %d is not a UTF-8 string", i)
}
res[i] = string(b)
}
return res, nil
}

// ArrayOfUint160 checks the result for correct state (HALT) and then extracts a
// slice of util.Uint160 from the returned stack item.
func ArrayOfUint160(r *result.Invoke, err error) ([]util.Uint160, error) {
Expand All @@ -236,6 +293,28 @@ func ArrayOfUint160(r *result.Invoke, err error) ([]util.Uint160, error) {
return res, nil
}

// ArrayOfUint256 checks the result for correct state (HALT) and then extracts a
// slice of util.Uint256 from the returned stack item.
func ArrayOfUint256(r *result.Invoke, err error) ([]util.Uint256, error) {
AnnaShaleva marked this conversation as resolved.
Show resolved Hide resolved
a, err := Array(r, err)
if err != nil {
return nil, err
}
res := make([]util.Uint256, len(a))
for i := range a {
b, err := a[i].TryBytes()
if err != nil {
return nil, fmt.Errorf("element %d is not a byte string: %w", i, err)
}
u, err := util.Uint256DecodeBytesBE(b)
if err != nil {
return nil, fmt.Errorf("element %d is not a uint256: %w", i, err)
}
res[i] = u
}
return res, nil
}

// ArrayOfPublicKeys checks the result for correct state (HALT) and then
// extracts a slice of public keys from the returned stack item.
func ArrayOfPublicKeys(r *result.Invoke, err error) (keys.PublicKeys, error) {
Expand Down
74 changes: 74 additions & 0 deletions pkg/rpcclient/unwrap/unwrap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,24 @@ func TestStdErrors(t *testing.T) {
func(r *result.Invoke, err error) (interface{}, error) {
return Array(r, err)
},
func(r *result.Invoke, err error) (interface{}, error) {
return ArrayOfBools(r, err)
},
func(r *result.Invoke, err error) (interface{}, error) {
return ArrayOfBigInts(r, err)
},
func(r *result.Invoke, err error) (interface{}, error) {
return ArrayOfBytes(r, err)
},
func(r *result.Invoke, err error) (interface{}, error) {
return ArrayOfUTF8Strings(r, err)
},
func(r *result.Invoke, err error) (interface{}, error) {
return ArrayOfUint160(r, err)
},
func(r *result.Invoke, err error) (interface{}, error) {
return ArrayOfUint256(r, err)
},
func(r *result.Invoke, err error) (interface{}, error) {
return ArrayOfPublicKeys(r, err)
},
Expand Down Expand Up @@ -233,6 +248,32 @@ func TestArray(t *testing.T) {
require.Equal(t, stackitem.Make(42), a[0])
}

func TestArrayOfBools(t *testing.T) {
_, err := ArrayOfBools(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make(42)}}, nil)
require.Error(t, err)

_, err = ArrayOfBools(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make([]stackitem.Item{stackitem.Make("reallybigstringthatcantbeanumberandthuscantbeconvertedtobool")})}}, nil)
require.Error(t, err)

a, err := ArrayOfBools(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make([]stackitem.Item{stackitem.Make(true)})}}, nil)
require.NoError(t, err)
require.Equal(t, 1, len(a))
require.Equal(t, true, a[0])
}

func TestArrayOfBigInts(t *testing.T) {
_, err := ArrayOfBigInts(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make(42)}}, nil)
require.Error(t, err)

_, err = ArrayOfBigInts(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make([]stackitem.Item{stackitem.Make([]stackitem.Item{})})}}, nil)
require.Error(t, err)

a, err := ArrayOfBigInts(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make([]stackitem.Item{stackitem.Make(42)})}}, nil)
require.NoError(t, err)
require.Equal(t, 1, len(a))
require.Equal(t, big.NewInt(42), a[0])
}

func TestArrayOfBytes(t *testing.T) {
_, err := ArrayOfBytes(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make(42)}}, nil)
require.Error(t, err)
Expand All @@ -246,6 +287,22 @@ func TestArrayOfBytes(t *testing.T) {
require.Equal(t, []byte("some"), a[0])
}

func TestArrayOfUTF8Strings(t *testing.T) {
_, err := ArrayOfUTF8Strings(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make(42)}}, nil)
require.Error(t, err)

_, err = ArrayOfUTF8Strings(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make([]stackitem.Item{stackitem.Make([]stackitem.Item{})})}}, nil)
require.Error(t, err)

_, err = ArrayOfUTF8Strings(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make([]stackitem.Item{stackitem.Make([]byte{0, 0xff})})}}, nil)
require.Error(t, err)

a, err := ArrayOfUTF8Strings(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make([]stackitem.Item{stackitem.Make("some")})}}, nil)
require.NoError(t, err)
require.Equal(t, 1, len(a))
require.Equal(t, "some", a[0])
}

func TestArrayOfUint160(t *testing.T) {
_, err := ArrayOfUint160(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make(42)}}, nil)
require.Error(t, err)
Expand All @@ -263,6 +320,23 @@ func TestArrayOfUint160(t *testing.T) {
require.Equal(t, u160, uints[0])
}

func TestArrayOfUint256(t *testing.T) {
_, err := ArrayOfUint256(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make(42)}}, nil)
require.Error(t, err)

_, err = ArrayOfUint256(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make([]stackitem.Item{stackitem.Make([]stackitem.Item{})})}}, nil)
require.Error(t, err)

_, err = ArrayOfUint256(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make([]stackitem.Item{stackitem.Make([]byte("some"))})}}, nil)
require.Error(t, err)

u256 := util.Uint256{1, 2, 3}
uints, err := ArrayOfUint256(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make([]stackitem.Item{stackitem.Make(u256.BytesBE())})}}, nil)
require.NoError(t, err)
require.Equal(t, 1, len(uints))
require.Equal(t, u256, uints[0])
}

func TestArrayOfPublicKeys(t *testing.T) {
_, err := ArrayOfPublicKeys(&result.Invoke{State: "HALT", Stack: []stackitem.Item{stackitem.Make(42)}}, nil)
require.Error(t, err)
Expand Down