Skip to content
This repository has been archived by the owner on Sep 23, 2024. It is now read-only.

Use context with timeout for external RPC API calls #27

Merged
Show file tree
Hide file tree
Changes from all commits
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
3 changes: 2 additions & 1 deletion client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@ import (
"fmt"
"time"

"github.com/0xPolygon/beethoven/tx"
"github.com/0xPolygon/cdk-validium-node/ethtxmanager"
"github.com/0xPolygon/cdk-validium-node/jsonrpc/client"
"github.com/0xPolygon/cdk-validium-node/jsonrpc/types"
"github.com/ethereum/go-ethereum/common"

"github.com/0xPolygon/beethoven/tx"
)

// ClientFactoryInterface interface for the client factory
Expand Down
5 changes: 3 additions & 2 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,9 @@ func start(cliCtx *cli.Context) error {
&dummyinterfaces.DummyStorage{},
[]jsonrpc.Service{
{
Name: rpc.INTEROP,
Service: rpc.NewInteropEndpoints(addr, storage, &ethMan, c.FullNodeRPCs, etm),
Name: rpc.INTEROP,
Service: rpc.NewInteropEndpoints(addr, storage, &ethMan,
c.FullNodeRPCs, c.RPC.ReadTimeout.Duration, etm),
},
},
)
Expand Down
3 changes: 2 additions & 1 deletion config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"path/filepath"
"strings"

"github.com/0xPolygon/beethoven/rpc"
"github.com/0xPolygon/cdk-validium-node/config/types"
"github.com/0xPolygon/cdk-validium-node/db"
"github.com/0xPolygon/cdk-validium-node/ethtxmanager"
Expand All @@ -16,6 +15,8 @@ import (
"github.com/mitchellh/mapstructure"
"github.com/spf13/viper"
"github.com/urfave/cli/v2"

"github.com/0xPolygon/beethoven/rpc"
)

const (
Expand Down
14 changes: 10 additions & 4 deletions etherman/etherman.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,9 @@ package etherman
import (
"context"
"errors"
"github.com/jackc/pgx/v4"
"math/big"
"time"

"github.com/0xPolygon/beethoven/tx"
"github.com/0xPolygon/cdk-validium-node/etherman/smartcontracts/cdkvalidium"
"github.com/0xPolygon/cdk-validium-node/log"
"github.com/0xPolygon/cdk-validium-node/state"
Expand All @@ -16,6 +14,14 @@ import (
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/jackc/pgx/v4"

"github.com/0xPolygon/beethoven/tx"
)

const (
HashLength = 32
ProofLength = 24
)

type Etherman struct {
Expand All @@ -40,9 +46,9 @@ func (e *Etherman) GetSequencerAddr(l1Contract common.Address) (common.Address,
}

func (e *Etherman) BuildTrustedVerifyBatchesTxData(lastVerifiedBatch, newVerifiedBatch uint64, proof tx.ZKP) (data []byte, err error) {
var newLocalExitRoot [32]byte
var newLocalExitRoot [HashLength]byte
copy(newLocalExitRoot[:], proof.NewLocalExitRoot.Bytes())
var newStateRoot [32]byte
var newStateRoot [HashLength]byte
copy(newStateRoot[:], proof.NewStateRoot.Bytes())
finalProof, err := ConvertProof(proof.Proof.Hex())
if err != nil {
Expand Down
37 changes: 37 additions & 0 deletions etherman/helpers_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package etherman

import (
"bytes"
"crypto/rand"
"encoding/hex"
"testing"

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

func generateProof(t *testing.T) string {
t.Helper()

var buf bytes.Buffer
buf.WriteString("0x")

for i := 0; i < 2*ProofLength; i++ {
hash := generateRandomHexString(t, HashLength)
_, err := buf.WriteString(hash)
require.NoError(t, err)
}

return buf.String()
}

func generateRandomHexString(t *testing.T, length int) string {
t.Helper()

numBytes := length / 2
randomBytes := make([]byte, numBytes)

_, err := rand.Read(randomBytes)
require.NoError(t, err)

return hex.EncodeToString(randomBytes)
}
40 changes: 35 additions & 5 deletions etherman/proof.go
Original file line number Diff line number Diff line change
@@ -1,28 +1,58 @@
package etherman

import (
"bytes"
"fmt"
"strings"

"github.com/0xPolygon/cdk-validium-node/encoding"
)

type Proof [24][32]byte
type Proof [ProofLength][HashLength]byte

func (p Proof) Equals(other Proof) bool {
for i := 0; i < len(p); i++ {
if !bytes.Equal(p[i][:], other[i][:]) {
return false
}
}
return true
}

func BytesToProof(data []byte) (Proof, error) {
// Check if the length of the input data is compatible with the Proof type
expectedLength := ProofLength * HashLength
if len(data) != expectedLength {
return Proof{}, fmt.Errorf("invalid byte slice length. Expected length: %d, Actual length: %d", expectedLength, len(data))
}

// Create a Proof type and copy the data into it
var proof Proof
for i := 0; i < ProofLength; i++ {
copy(proof[i][:], data[i*HashLength:(i+1)*HashLength])
}

return proof, nil
}

func ConvertProof(p string) (Proof, error) {
const expectedLength = 24*32*2 + 2
const (
expectedLength = ProofLength*HashLength*2 + 2
rawHashLength = 2 * HashLength // 1 byte gets substituted with 2 hex digits (1 hex digit = nibble = 4 bits)
)

if len(p) != expectedLength {
return Proof{}, fmt.Errorf("invalid proof length. Expected length: %d, Actual length %d", expectedLength, len(p))
}
p = strings.TrimPrefix(p, "0x")
proof := Proof{}
for i := 0; i < 24; i++ {
data := p[i*64 : (i+1)*64]
for i := 0; i < ProofLength; i++ {
data := p[i*rawHashLength : (i+1)*rawHashLength]
p, err := encoding.DecodeBytes(&data)
if err != nil {
return Proof{}, fmt.Errorf("failed to decode proof, err: %w", err)
}
var aux [32]byte
var aux [HashLength]byte
copy(aux[:], p)
proof[i] = aux
}
Expand Down
51 changes: 51 additions & 0 deletions etherman/proof_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package etherman

import (
"fmt"
"testing"

"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/stretchr/testify/require"
)

func TestConvertProof(t *testing.T) {
validInputProof := generateProof(t)

validRawProof, err := hexutil.Decode(validInputProof)
require.NoError(t, err)

validProof, err := BytesToProof(validRawProof)
require.NoError(t, err)

tests := []struct {
name string
input string
expected Proof
expectedErr string
}{
{
name: "valid proof",
input: validInputProof,
expected: validProof,
expectedErr: "",
},
{
name: "invalid proof length",
input: "0x1234",
expectedErr: fmt.Sprintf("invalid proof length. Expected length: %d, Actual length %d", ProofLength*HashLength*2+2, 6),
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := ConvertProof(tt.input)

if tt.expectedErr != "" {
require.ErrorContains(t, err, tt.expectedErr)
} else {
require.NoError(t, err)
require.True(t, result.Equals(tt.expected), "expected: %v, actual: %v", tt.expected, result)
}
})
}
}
16 changes: 12 additions & 4 deletions rpc/rpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ import (
"context"
"fmt"
"math/big"
"time"

"github.com/0xPolygon/beethoven/tx"
"github.com/0xPolygon/cdk-validium-node/jsonrpc/client"
"github.com/0xPolygon/cdk-validium-node/jsonrpc/types"
"github.com/0xPolygon/cdk-validium-node/log"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common"

"github.com/0xPolygon/beethoven/tx"
)

// INTEROP is the namespace of the interop service
Expand All @@ -35,6 +37,7 @@ type InteropEndpoints struct {
etherman EthermanInterface
interopAdminAddr common.Address
fullNodeRPCs FullNodeRPCs
rpcTimeout time.Duration
ethTxManager EthTxManager
zkEVMClientCreator ZkEVMClientClientCreator
}
Expand All @@ -45,20 +48,23 @@ func NewInteropEndpoints(
db DBInterface,
etherman EthermanInterface,
fullNodeRPCs FullNodeRPCs,
rpcTimeout time.Duration,
ethTxManager EthTxManager,
) *InteropEndpoints {
return &InteropEndpoints{
db: db,
interopAdminAddr: interopAdminAddr,
etherman: etherman,
fullNodeRPCs: fullNodeRPCs,
rpcTimeout: rpcTimeout,
ethTxManager: ethTxManager,
zkEVMClientCreator: &zkEVMClientCreator{},
}
}

func (i *InteropEndpoints) SendTx(signedTx tx.SignedTx) (interface{}, types.Error) {
ctx := context.TODO()
ctx, cancel := context.WithTimeout(context.Background(), i.rpcTimeout)
defer cancel()

// Check if the RPC is actually registered, if not it won't be possible to assert soundness (in the future once we are stateless won't be needed)
if _, ok := i.fullNodeRPCs[signedTx.Tx.L1Contract]; !ok {
Expand Down Expand Up @@ -141,7 +147,9 @@ func (i *InteropEndpoints) SendTx(signedTx tx.SignedTx) (interface{}, types.Erro
}

func (i *InteropEndpoints) GetTxStatus(hash common.Hash) (result interface{}, err types.Error) {
ctx := context.TODO()
ctx, cancel := context.WithTimeout(context.Background(), i.rpcTimeout)
defer cancel()

dbTx, innerErr := i.db.BeginStateTransaction(ctx)
if innerErr != nil {
result = "0x0"
Expand All @@ -167,5 +175,5 @@ func (i *InteropEndpoints) GetTxStatus(hash common.Hash) (result interface{}, er

result = res.Status.String()

return result, err
return
}
11 changes: 9 additions & 2 deletions rpc/rpc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import (
"github.com/0xPolygon/beethoven/mocks"
"math/big"
"testing"
"time"

"github.com/0xPolygon/beethoven/tx"
"github.com/0xPolygon/cdk-validium-node/ethtxmanager"
validiumTypes "github.com/0xPolygon/cdk-validium-node/jsonrpc/types"
"github.com/ethereum/go-ethereum"
Expand All @@ -17,8 +17,12 @@ import (
"github.com/jackc/pgx/v4"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"

"github.com/0xPolygon/beethoven/tx"
)

const rpcRequestTimeout = 10 * time.Second

var _ EthermanInterface = (*ethermanMock)(nil)

type ethermanMock struct {
Expand Down Expand Up @@ -137,6 +141,7 @@ func TestInteropEndpointsGetTxStatus(t *testing.T) {
dbMock,
new(ethermanMock),
nil,
rpcRequestTimeout,
new(ethTxManagerMock),
)

Expand Down Expand Up @@ -168,6 +173,7 @@ func TestInteropEndpointsGetTxStatus(t *testing.T) {
dbMock,
new(ethermanMock),
nil,
rpcRequestTimeout,
txManagerMock,
)

Expand Down Expand Up @@ -211,6 +217,7 @@ func TestInteropEndpointsGetTxStatus(t *testing.T) {
dbMock,
new(ethermanMock),
nil,
rpcRequestTimeout,
txManagerMock,
)

Expand Down Expand Up @@ -266,7 +273,7 @@ func TestInteropEndpointsSendTx(t *testing.T) {
ethTxManagerMock := new(ethTxManagerMock)

executeTestFn := func() {
i := NewInteropEndpoints(common.HexToAddress("0xadmin"), dbMock, ethermanMock, fullNodeRPCs, ethTxManagerMock)
i := NewInteropEndpoints(common.HexToAddress("0xadmin"), dbMock, ethermanMock, fullNodeRPCs, rpcRequestTimeout, ethTxManagerMock)
i.zkEVMClientCreator = zkEVMClientCreatorMock

result, err := i.SendTx(*signedTx)
Expand Down
Loading