Skip to content

Commit

Permalink
add support to jrpc to accept short hashes and addresses strings like…
Browse files Browse the repository at this point in the history
  • Loading branch information
tclemos authored Mar 14, 2023
1 parent 5e7794c commit 77072a2
Show file tree
Hide file tree
Showing 7 changed files with 126 additions and 37 deletions.
6 changes: 1 addition & 5 deletions encoding/encoding.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,6 @@ import (
const (
// Base10 decimal base
Base10 = 10
// Base16 hexadecimal base
Base16 = 16
// BitSize64 64 bits
BitSize64 = 64
// TenToThePowerOf18 represents 1000000000000000000
TenToThePowerOf18 = 1000000000000000000
// Gwei represents 1000000000 wei
Expand All @@ -37,7 +33,7 @@ func DecodeUint64orHex(val *string) (uint64, error) {
str = str[2:]
base = 16
}
return strconv.ParseUint(str, base, BitSize64)
return strconv.ParseUint(str, base, hex.BitSize64)
}

// DecodeUint256orHex decodes a string uint256 or hex string into a bit.Int
Expand Down
22 changes: 13 additions & 9 deletions hex/hex.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,9 @@ import (
const (
// Base represents the hexadecimal base, which is 16
Base = 16
)

// TODO Remove
var (
ErrSyntax = &DecError{"invalid hex string"}
ErrMissingPrefix = &DecError{"hex string without 0x prefix"}
ErrEmptyNumber = &DecError{"hex string \"0x\""}
ErrLeadingZero = &DecError{"hex number with leading zero digits"}
ErrUint64Range = &DecError{"hex number > 64 bits"}
ErrBig256Range = &DecError{"hex number > 256 bits"}
// BitSize64 64 bits
BitSize64 = 64
)

// DecError represents an error when decoding a hex value
Expand Down Expand Up @@ -103,3 +96,14 @@ func DecodeBig(hexNum string) *big.Int {

return createdNum
}

// IsValid checks if the provided string is a valid hexadecimal value
func IsValid(s string) bool {
str := strings.TrimPrefix(s, "0x")
for _, b := range []byte(str) {
if !(b >= '0' && b <= '9' || b >= 'a' && b <= 'f' || b >= 'A' && b <= 'F') {
return false
}
}
return true
}
10 changes: 8 additions & 2 deletions jsonrpc/endpoints_eth.go
Original file line number Diff line number Diff line change
Expand Up @@ -354,15 +354,21 @@ func (e *EthEndpoints) internalGetLogs(ctx context.Context, dbTx pgx.Tx, filter
}

// GetStorageAt gets the value stored for an specific address and position
func (e *EthEndpoints) GetStorageAt(address argAddress, position argHash, number *BlockNumber) (interface{}, rpcError) {
func (e *EthEndpoints) GetStorageAt(address argAddress, storageKeyStr string, number *BlockNumber) (interface{}, rpcError) {
storageKey := argHash{}
err := storageKey.UnmarshalText([]byte(storageKeyStr))
if err != nil {
return rpcErrorResponse(defaultErrorCode, "unable to decode storage key: hex string invalid", nil)
}

return e.txMan.NewDbTxScope(e.state, func(ctx context.Context, dbTx pgx.Tx) (interface{}, rpcError) {
var err error
blockNumber, rpcErr := number.getNumericBlockNumber(ctx, e.state, dbTx)
if rpcErr != nil {
return nil, rpcErr
}

value, err := e.state.GetStorageAt(ctx, address.Address(), position.Hash().Big(), blockNumber, dbTx)
value, err := e.state.GetStorageAt(ctx, address.Address(), storageKey.Hash().Big(), blockNumber, dbTx)
if errors.Is(err, state.ErrNotFound) {
return argBytesPtr(common.Hash{}.Bytes()), nil
} else if err != nil {
Expand Down
13 changes: 7 additions & 6 deletions jsonrpc/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"strconv"
"strings"

"github.com/0xPolygonHermez/zkevm-node/encoding"
"github.com/0xPolygonHermez/zkevm-node/hex"
"github.com/0xPolygonHermez/zkevm-node/state"
"github.com/ethereum/go-ethereum/common"
Expand All @@ -28,7 +27,7 @@ func (b argUint64) MarshalText() ([]byte, error) {
// UnmarshalText unmarshals from text
func (b *argUint64) UnmarshalText(input []byte) error {
str := strings.TrimPrefix(string(input), "0x")
num, err := strconv.ParseUint(str, hex.Base, encoding.BitSize64)
num, err := strconv.ParseUint(str, hex.Base, hex.BitSize64)
if err != nil {
return err
}
Expand Down Expand Up @@ -123,9 +122,10 @@ type argHash common.Hash

// UnmarshalText unmarshals from text
func (arg *argHash) UnmarshalText(input []byte) error {
if !strings.HasPrefix(string(input), "0x") {
return fmt.Errorf("invalid address, it needs to be a hexadecimal value starting with 0x")
if !hex.IsValid(string(input)) {
return fmt.Errorf("invalid hash, it needs to be a hexadecimal value")
}

str := strings.TrimPrefix(string(input), "0x")
*arg = argHash(common.HexToHash(str))
return nil
Expand All @@ -146,9 +146,10 @@ type argAddress common.Address

// UnmarshalText unmarshals from text
func (b *argAddress) UnmarshalText(input []byte) error {
if !strings.HasPrefix(string(input), "0x") {
return fmt.Errorf("invalid address, it needs to be a hexadecimal value starting with 0x")
if !hex.IsValid(string(input)) {
return fmt.Errorf("invalid address, it needs to be a hexadecimal value")
}

str := strings.TrimPrefix(string(input), "0x")
*b = argAddress(common.HexToAddress(str))
return nil
Expand Down
103 changes: 93 additions & 10 deletions jsonrpc/types_test.go
Original file line number Diff line number Diff line change
@@ -1,26 +1,109 @@
package jsonrpc

import (
"fmt"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestArgHashUnmarshalFromShortString(t *testing.T) {
str := "0x01"
arg := argHash{}
err := arg.UnmarshalText([]byte(str))
require.NoError(t, err)
type testCase struct {
name string
input string
expectedResult string
expectedError error
}
testCases := []testCase{
{
name: "valid hex value starting with 0x",
input: "0x1",
expectedResult: "0x0000000000000000000000000000000000000000000000000000000000000001",
expectedError: nil,
},
{
name: "valid hex value starting without 0x",
input: "1",
expectedResult: "0x0000000000000000000000000000000000000000000000000000000000000001",
expectedError: nil,
},
{
name: "valid full hash value",
input: "0x05b21ee5f65c28a0af8e71290fc33625a1279a8b3d6357ce3ca60f22dbf59e63",
expectedResult: "0x05b21ee5f65c28a0af8e71290fc33625a1279a8b3d6357ce3ca60f22dbf59e63",
expectedError: nil,
},
{
name: "invalid hex value starting with 0x",
input: "0xG",
expectedResult: "0x0000000000000000000000000000000000000000000000000000000000000000",
expectedError: fmt.Errorf("invalid hash, it needs to be a hexadecimal value"),
},
{
name: "invalid hex value starting without 0x",
input: "G",
expectedResult: "0x0000000000000000000000000000000000000000000000000000000000000000",
expectedError: fmt.Errorf("invalid hash, it needs to be a hexadecimal value"),
},
}

assert.Equal(t, "0x0000000000000000000000000000000000000000000000000000000000000001", arg.Hash().String())
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
arg := argHash{}
err := arg.UnmarshalText([]byte(testCase.input))
require.Equal(t, testCase.expectedError, err)
assert.Equal(t, testCase.expectedResult, arg.Hash().String())
})
}
}

func TestArgAddressUnmarshalFromShortString(t *testing.T) {
str := "0x01"
arg := argAddress{}
err := arg.UnmarshalText([]byte(str))
require.NoError(t, err)
type testCase struct {
name string
input string
expectedResult string
expectedError error
}
testCases := []testCase{
{
name: "valid hex value starting with 0x",
input: "0x1",
expectedResult: "0x0000000000000000000000000000000000000001",
expectedError: nil,
},
{
name: "valid hex value starting without 0x",
input: "1",
expectedResult: "0x0000000000000000000000000000000000000001",
expectedError: nil,
},
{
name: "valid full address value",
input: "0x748964F22eFd023eB78A246A7AC2506e84CC4545",
expectedResult: "0x748964F22eFd023eB78A246A7AC2506e84CC4545",
expectedError: nil,
},
{
name: "invalid hex value starting with 0x",
input: "0xG",
expectedResult: "0x0000000000000000000000000000000000000000",
expectedError: fmt.Errorf("invalid address, it needs to be a hexadecimal value"),
},
{
name: "invalid hex value starting without 0x",
input: "G",
expectedResult: "0x0000000000000000000000000000000000000000",
expectedError: fmt.Errorf("invalid address, it needs to be a hexadecimal value"),
},
}

assert.Equal(t, "0x0000000000000000000000000000000000000001", arg.Address().String())
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
arg := argAddress{}
err := arg.UnmarshalText([]byte(testCase.input))
require.Equal(t, testCase.expectedError, err)
assert.Equal(t, testCase.expectedResult, arg.Address().String())
})
}
}
5 changes: 2 additions & 3 deletions state/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"math/big"
"strconv"

"github.com/0xPolygonHermez/zkevm-node/encoding"
"github.com/0xPolygonHermez/zkevm-node/hex"
"github.com/0xPolygonHermez/zkevm-node/log"
"github.com/ethereum/go-ethereum/core/types"
Expand Down Expand Up @@ -160,7 +159,7 @@ func DecodeTxs(txsData []byte) ([]types.Transaction, []byte, error) {
return txs, txsData, nil
}
for pos < int64(txDataLength) {
num, err := strconv.ParseInt(hex.EncodeToString(txsData[pos:pos+1]), hex.Base, encoding.BitSize64)
num, err := strconv.ParseInt(hex.EncodeToString(txsData[pos:pos+1]), hex.Base, hex.BitSize64)
if err != nil {
log.Debug("error parsing header length: ", err)
return []types.Transaction{}, txsData, err
Expand All @@ -173,7 +172,7 @@ func DecodeTxs(txsData []byte) ([]types.Transaction, []byte, error) {
log.Debug("error parsing length: ", err)
return []types.Transaction{}, txsData, err
}
n, err := strconv.ParseInt(hex.EncodeToString(txsData[pos+1:pos+1+num-f7]), hex.Base, encoding.BitSize64) // +1 is the header. For example 0xf7
n, err := strconv.ParseInt(hex.EncodeToString(txsData[pos+1:pos+1+num-f7]), hex.Base, hex.BitSize64) // +1 is the header. For example 0xf7
if err != nil {
log.Debug("error parsing length: ", err)
return []types.Transaction{}, txsData, err
Expand Down
4 changes: 2 additions & 2 deletions tools/zkevmprovermock/server/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ package server

import (
"context"
"encoding/hex"
"fmt"
"math/big"
"net"
"strconv"
"strings"

"github.com/0xPolygonHermez/zkevm-node/encoding"
"github.com/0xPolygonHermez/zkevm-node/hex"
"github.com/0xPolygonHermez/zkevm-node/log"
"github.com/0xPolygonHermez/zkevm-node/state/runtime/executor/pb"
"github.com/0xPolygonHermez/zkevm-node/tools/zkevmprovermock/testvector"
Expand Down Expand Up @@ -333,7 +333,7 @@ func translateTransactionSteps(inputSteps []*testvector.TransactionStep) ([]*pb.
if strings.HasPrefix(inputStep.Op, "0x") { // nolint
inputStep.Op = inputStep.Op[2:]
}
opBI, ok := new(big.Int).SetString(inputStep.Op, encoding.Base16)
opBI, ok := new(big.Int).SetString(inputStep.Op, hex.Base)
if !ok {
return nil, fmt.Errorf("Could not convert base16 %q to big int", inputStep.Op)
}
Expand Down

0 comments on commit 77072a2

Please sign in to comment.