Skip to content

Commit

Permalink
Align RPC with geth (#1841)
Browse files Browse the repository at this point in the history
* - return nil instead of custom error
- align some methods with the geth rpc types

* fix

* fix

* lint

* fix

* fix

* fix
  • Loading branch information
tudor-malene authored Mar 20, 2024
1 parent 172fae2 commit fdde1b7
Show file tree
Hide file tree
Showing 21 changed files with 267 additions and 163 deletions.
60 changes: 47 additions & 13 deletions go/common/gethencoding/geth_encoding.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import (
"github.com/ten-protocol/go-ten/go/enclave/crypto"

"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ten-protocol/go-ten/go/common/errutil"
"github.com/ten-protocol/go-ten/go/common/gethapi"

gethcommon "github.com/ethereum/go-ethereum/common"
Expand Down Expand Up @@ -145,33 +144,68 @@ func ExtractAddress(param interface{}) (*gethcommon.Address, error) {
}

// ExtractOptionalBlockNumber defaults nil or empty block number params to latest block number
func ExtractOptionalBlockNumber(params []interface{}, idx int) (*gethrpc.BlockNumber, error) {
func ExtractOptionalBlockNumber(params []interface{}, idx int) (*gethrpc.BlockNumberOrHash, error) {
latest := gethrpc.BlockNumberOrHashWithNumber(gethrpc.LatestBlockNumber)
if len(params) <= idx {
return ExtractBlockNumber("latest")
return &latest, nil
}
if params[idx] == nil {
return ExtractBlockNumber("latest")
return &latest, nil
}
if emptyStr, ok := params[idx].(string); ok && len(strings.TrimSpace(emptyStr)) == 0 {
return ExtractBlockNumber("latest")
return &latest, nil
}

return ExtractBlockNumber(params[idx])
}

// ExtractBlockNumber returns a gethrpc.BlockNumber given an interface{}, errors if unexpected values are used
func ExtractBlockNumber(param interface{}) (*gethrpc.BlockNumber, error) {
func ExtractBlockNumber(param interface{}) (*gethrpc.BlockNumberOrHash, error) {
if param == nil {
return nil, errutil.ErrNotFound
latest := gethrpc.BlockNumberOrHashWithNumber(gethrpc.LatestBlockNumber)
return &latest, nil
}

blockNumber := gethrpc.BlockNumber(0)
err := blockNumber.UnmarshalJSON([]byte(param.(string)))
if err != nil {
return nil, fmt.Errorf("could not parse requested rollup number %s - %w", param.(string), err)
// when the param is a single string we try to convert it to a block number
blockString, ok := param.(string)
if ok {
blockNumber := gethrpc.BlockNumber(0)
err := blockNumber.UnmarshalJSON([]byte(blockString))
if err != nil {
return nil, fmt.Errorf("invalid block number %s - %w", blockString, err)
}
return &gethrpc.BlockNumberOrHash{BlockNumber: &blockNumber}, nil
}

var blockNo *gethrpc.BlockNumber
var blockHa *gethcommon.Hash
var reqCanon bool

blockAndHash, ok := param.(map[string]any)
if !ok {
return nil, fmt.Errorf("invalid block or hash parameter %s", param.(string))
}
if blockAndHash["blockNumber"] != nil {
b := blockAndHash["blockNumber"].(string)
blockNumber := gethrpc.BlockNumber(0)
err := blockNumber.UnmarshalJSON([]byte(b))
if err != nil {
return nil, fmt.Errorf("invalid block number %s - %w", b, err)
}
blockNo = &blockNumber
}
if blockAndHash["blockHash"] != nil {
bh := blockAndHash["blockHash"].(gethcommon.Hash)
blockHa = &bh
}
if blockAndHash["RequireCanonical"] != nil {
reqCanon = blockAndHash["RequireCanonical"].(bool)
}

return &blockNumber, err
return &gethrpc.BlockNumberOrHash{
BlockNumber: blockNo,
BlockHash: blockHa,
RequireCanonical: reqCanon,
}, nil
}

// ExtractEthCall extracts the eth_call gethapi.TransactionArgs from an interface{}
Expand Down
1 change: 1 addition & 0 deletions go/enclave/l2chain/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ type ObscuroChain interface {
// For EOA - the actual address.
// For Contracts - the address of the deployer.
// Note - this might be subject to change if we implement a more flexible mechanism
// todo - support BlockNumberOrHash
AccountOwner(address gethcommon.Address, blockNumber *gethrpc.BlockNumber) (*gethcommon.Address, error)

// GetBalanceAtBlock - will return the balance of a specific address at the specific given block number (batch number).
Expand Down
7 changes: 2 additions & 5 deletions go/enclave/l2chain/l1_blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,8 @@ import (
)

const (
gethDir = "geth"
chainDataDir = "chaindata"
chainDataAncientDir = "chaindata/ancient"
trieCacheDir = "triecache"
ethashDir = "ethash"
gethDir = "geth"
chainDataDir = "chaindata"
// todo (#1471) - use a constant that makes sense outside of the simulation.
dataDirRoot = "../.build/simulations/gethDataDir"
)
Expand Down
3 changes: 2 additions & 1 deletion go/enclave/rpc/EstimateGas.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ func EstimateGasValidate(reqParams []any, builder *CallBuilder[CallParamsWithBlo
}

builder.From = callMsg.From
builder.Param = &CallParamsWithBlock{callMsg, blockNumber}
// todo
builder.Param = &CallParamsWithBlock{callMsg, blockNumber.BlockNumber}
return nil
}

Expand Down
6 changes: 3 additions & 3 deletions go/enclave/rpc/GetBalance.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (

type BalanceReq struct {
Addr *common.Address
Block *rpc.BlockNumber
Block *rpc.BlockNumberOrHash
}

func GetBalanceValidate(reqParams []any, builder *CallBuilder[BalanceReq, hexutil.Big], _ *EncryptionManager) error {
Expand Down Expand Up @@ -41,7 +41,7 @@ func GetBalanceValidate(reqParams []any, builder *CallBuilder[BalanceReq, hexuti
}

func GetBalanceExecute(builder *CallBuilder[BalanceReq, hexutil.Big], rpc *EncryptionManager) error {
acctOwner, err := rpc.chain.AccountOwner(*builder.Param.Addr, builder.Param.Block)
acctOwner, err := rpc.chain.AccountOwner(*builder.Param.Addr, builder.Param.Block.BlockNumber)
if err != nil {
return err
}
Expand All @@ -53,7 +53,7 @@ func GetBalanceExecute(builder *CallBuilder[BalanceReq, hexutil.Big], rpc *Encry
return nil
}

balance, err := rpc.chain.GetBalanceAtBlock(*builder.Param.Addr, builder.Param.Block)
balance, err := rpc.chain.GetBalanceAtBlock(*builder.Param.Addr, builder.Param.Block.BlockNumber)
if err != nil {
return fmt.Errorf("unable to get balance - %w", err)
}
Expand Down
2 changes: 1 addition & 1 deletion go/enclave/rpc/GetTransaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ func GetTransactionExecute(builder *CallBuilder[gethcommon.Hash, RpcTransaction]
// Unlike in the Geth impl, we hardcode the use of a London signer.
// todo (#1553) - once the enclave's genesis.json is set, retrieve the signer type using `types.MakeSigner`
signer := types.NewLondonSigner(tx.ChainId())
rpcTx := newRPCTransaction(tx, blockHash, blockNumber, index, gethcommon.Big0, signer)
rpcTx := newRPCTransaction(tx, blockHash, blockNumber, index, rpc.config.BaseFee, signer)
builder.ReturnValue = rpcTx
return nil
}
Expand Down
3 changes: 2 additions & 1 deletion go/enclave/rpc/GetTransactionCount.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ func GetTransactionCountValidate(reqParams []any, builder *CallBuilder[uint64, s
return nil
}

b, err := rpc.registry.GetBatchAtHeight(*tag)
// todo - support BlockNumberOrHash
b, err := rpc.registry.GetBatchAtHeight(*tag.BlockNumber)
if err != nil {
builder.Err = fmt.Errorf("cant retrieve batch for tag. Cause: %w", err)
return nil
Expand Down
57 changes: 53 additions & 4 deletions go/enclave/rpc/GetTransactionReceipt.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ package rpc
import (
"errors"
"fmt"
"math/big"

"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ten-protocol/go-ten/go/enclave/evm/ethchainadapter"

"github.com/ten-protocol/go-ten/go/enclave/core"

Expand All @@ -13,7 +17,7 @@ import (
"github.com/ten-protocol/go-ten/go/enclave/events"
)

func GetTransactionReceiptValidate(reqParams []any, builder *CallBuilder[gethcommon.Hash, types.Receipt], _ *EncryptionManager) error {
func GetTransactionReceiptValidate(reqParams []any, builder *CallBuilder[gethcommon.Hash, map[string]interface{}], _ *EncryptionManager) error {
// Parameters are [Hash]
if len(reqParams) < 1 {
builder.Err = fmt.Errorf("unexpected number of parameters")
Expand All @@ -30,12 +34,12 @@ func GetTransactionReceiptValidate(reqParams []any, builder *CallBuilder[gethcom
return nil
}

func GetTransactionReceiptExecute(builder *CallBuilder[gethcommon.Hash, types.Receipt], rpc *EncryptionManager) error {
func GetTransactionReceiptExecute(builder *CallBuilder[gethcommon.Hash, map[string]interface{}], rpc *EncryptionManager) error {
txHash := *builder.Param
// todo - optimise these calls. This can be done with a single sql
rpc.logger.Trace("Get receipt for ", log.TxKey, txHash)
// We retrieve the transaction.
tx, _, _, _, err := rpc.storage.GetTransaction(txHash) //nolint:dogsled
tx, blockHash, number, txIndex, err := rpc.storage.GetTransaction(txHash) //nolint:dogsled
if err != nil {
rpc.logger.Trace("error getting tx ", log.TxKey, txHash, log.ErrKey, err)
if errors.Is(err, errutil.ErrNotFound) {
Expand Down Expand Up @@ -78,6 +82,51 @@ func GetTransactionReceiptExecute(builder *CallBuilder[gethcommon.Hash, types.Re
}

rpc.logger.Trace("Successfully retrieved receipt for ", log.TxKey, txHash, "rec", txReceipt)
builder.ReturnValue = txReceipt
signer := types.MakeSigner(ethchainadapter.ChainParams(big.NewInt(rpc.config.ObscuroChainID)), big.NewInt(int64(number)), 0)
r := marshalReceipt(txReceipt, blockHash, number, signer, tx, int(txIndex))
builder.ReturnValue = &r
return nil
}

// marshalReceipt marshals a transaction receipt into a JSON object.
// taken from geth
func marshalReceipt(receipt *types.Receipt, blockHash gethcommon.Hash, blockNumber uint64, signer types.Signer, tx *types.Transaction, txIndex int) map[string]interface{} {
from, _ := types.Sender(signer, tx)

fields := map[string]interface{}{
"blockHash": blockHash,
"blockNumber": hexutil.Uint64(blockNumber),
"transactionHash": tx.Hash(),
"transactionIndex": hexutil.Uint64(txIndex),
"from": from,
"to": tx.To(),
"gasUsed": hexutil.Uint64(receipt.GasUsed),
"cumulativeGasUsed": hexutil.Uint64(receipt.CumulativeGasUsed),
"contractAddress": nil,
"logs": receipt.Logs,
"logsBloom": receipt.Bloom,
"type": hexutil.Uint(tx.Type()),
"effectiveGasPrice": (*hexutil.Big)(receipt.EffectiveGasPrice),
}

// Assign receipt status or post state.
if len(receipt.PostState) > 0 {
fields["root"] = hexutil.Bytes(receipt.PostState)
} else {
fields["status"] = hexutil.Uint(receipt.Status)
}
if receipt.Logs == nil {
fields["logs"] = []*types.Log{}
}

if tx.Type() == types.BlobTxType {
fields["blobGasUsed"] = hexutil.Uint64(receipt.BlobGasUsed)
fields["blobGasPrice"] = (*hexutil.Big)(receipt.BlobGasPrice)
}

// If the ContractAddress is 20 0x0 bytes, assume it is not a contract creation
if receipt.ContractAddress != (gethcommon.Address{}) {
fields["contractAddress"] = receipt.ContractAddress
}
return fields
}
11 changes: 7 additions & 4 deletions go/enclave/rpc/TenEthCall.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import (
)

func TenCallValidate(reqParams []any, builder *CallBuilder[CallParamsWithBlock, string], _ *EncryptionManager) error {
// Parameters are [TransactionArgs, BlockNumber]
if len(reqParams) != 2 {
// Parameters are [TransactionArgs, BlockNumber, 2 more which we don't support yet]
if len(reqParams) < 2 && len(reqParams) > 4 {
builder.Err = fmt.Errorf("unexpected number of parameters")
return nil
}
Expand All @@ -36,7 +36,8 @@ func TenCallValidate(reqParams []any, builder *CallBuilder[CallParamsWithBlock,
}

builder.From = apiArgs.From
builder.Param = &CallParamsWithBlock{apiArgs, blkNumber}
// todo - support BlockNumberOrHash
builder.Param = &CallParamsWithBlock{apiArgs, blkNumber.BlockNumber}

return nil
}
Expand Down Expand Up @@ -71,8 +72,10 @@ func TenCallExecute(builder *CallBuilder[CallParamsWithBlock, string], rpc *Encr
var encodedResult string
if len(execResult.ReturnData) != 0 {
encodedResult = hexutil.Encode(execResult.ReturnData)
builder.ReturnValue = &encodedResult
} else {
builder.ReturnValue = nil
}
builder.ReturnValue = &encodedResult
return nil
}

Expand Down
3 changes: 2 additions & 1 deletion go/enclave/storage/enclavedb/batch.go
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,8 @@ func ReadReceipt(db *sql.DB, hash common.L2TxHash, config *params.ChainConfig) (

batchhash := common.L2BatchHash{}
batchhash.SetBytes(batchHash)
if err = receipts.DeriveFields(config, batchhash, height, 0, big.NewInt(0), big.NewInt(0), transactions); err != nil {
// todo base fee
if err = receipts.DeriveFields(config, batchhash, height, 0, big.NewInt(1), big.NewInt(0), transactions); err != nil {
return nil, fmt.Errorf("failed to derive block receipts fields. hash = %s; number = %d; err = %w", hash, height, err)
}
return receipts[0], nil
Expand Down
Loading

0 comments on commit fdde1b7

Please sign in to comment.