infra/op-txproxy/conditional_txs_test.go
Hamdi Allam dff24e9fca
op-txproxy: external validating proxy for conditional transactions (#42)
* txpool svc

* change mod github path

* tag-tool

* codeowners
2024-09-30 13:43:34 -07:00

136 lines
4.3 KiB
Go

package op_txproxy
import (
"context"
"math/big"
"net/http/httptest"
"testing"
"github.com/ethereum-optimism/optimism/op-service/metrics"
"github.com/ethereum-optimism/optimism/op-service/predeploys"
"github.com/ethereum-optimism/optimism/op-service/testlog"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc"
"github.com/stretchr/testify/require"
)
type testBackend struct{}
func (b *testBackend) SendRawTransactionConditional(ctx context.Context, txBytes hexutil.Bytes, cond types.TransactionConditional) (common.Hash, error) {
return common.Hash{}, nil
}
func setupSvc(t *testing.T) *ConditionalTxService {
// setup no-op backend
srv := rpc.NewServer()
t.Cleanup(func() { srv.Stop() })
require.NoError(t, srv.RegisterName("eth", new(testBackend)))
httpSrv := httptest.NewServer(srv)
t.Cleanup(func() { httpSrv.Close() })
log := testlog.Logger(t, log.LevelInfo)
cfg := &CLIConfig{
SendRawTransactionConditionalEnabled: true,
SendRawTransactionConditionalBackend: httpSrv.URL,
SendRawTransactionConditionalRateLimit: 10_000,
}
svc, err := NewConditionalTxService(context.Background(), log, metrics.With(metrics.NewRegistry()), cfg)
require.NoError(t, err)
return svc
}
func TestSendRawTransactionConditionalDisabled(t *testing.T) {
svc := setupSvc(t)
svc.cfg.SendRawTransactionConditionalEnabled = false
hash, err := svc.SendRawTransactionConditional(context.Background(), nil, types.TransactionConditional{})
require.Zero(t, hash)
require.Equal(t, endpointDisabledErr, err)
}
func TestSendRawTransactionConditionalMissingAuth(t *testing.T) {
svc := setupSvc(t)
hash, err := svc.SendRawTransactionConditional(context.Background(), nil, types.TransactionConditional{})
require.Zero(t, hash)
require.Equal(t, missingAuthenticationErr, err)
}
func TestSendRawTransactionConditionalInvalidTxTarget(t *testing.T) {
svc := setupSvc(t)
txBytes, err := rlp.EncodeToBytes(types.NewTransaction(0, common.Address{19: 1}, big.NewInt(0), 0, big.NewInt(0), nil))
require.NoError(t, err)
// setup auth
ctx := context.WithValue(context.Background(), authContextKey{}, &AuthContext{Caller: common.HexToAddress("0xa")})
hash, err := svc.SendRawTransactionConditional(ctx, txBytes, types.TransactionConditional{})
require.Zero(t, hash)
require.Equal(t, entrypointSupportErr, err)
}
func TestSendRawTransactionConditionals(t *testing.T) {
costExcessiveCond := types.TransactionConditional{KnownAccounts: make(types.KnownAccounts)}
for i := 0; i < (params.TransactionConditionalMaxCost + 1); i++ {
iBig := big.NewInt(int64(i))
root := common.BigToHash(iBig)
costExcessiveCond.KnownAccounts[common.BigToAddress(iBig)] = types.KnownAccount{StorageRoot: &root}
}
uint64Ptr := func(num uint64) *uint64 { return &num }
tests := []struct {
name string
cond types.TransactionConditional
mustFail bool
}{
{
name: "passes",
cond: types.TransactionConditional{BlockNumberMin: big.NewInt(1), BlockNumberMax: big.NewInt(2), TimestampMin: uint64Ptr(1), TimestampMax: uint64Ptr(2)},
mustFail: false,
},
{
name: "validation. block min greater than max",
cond: types.TransactionConditional{BlockNumberMin: big.NewInt(2), BlockNumberMax: big.NewInt(1)},
mustFail: true,
},
{
name: "validation. timestamp min greater than max",
cond: types.TransactionConditional{TimestampMin: uint64Ptr(2), TimestampMax: uint64Ptr(1)},
mustFail: true,
},
{
name: "excessive cost",
cond: costExcessiveCond,
mustFail: true,
},
}
svc := setupSvc(t)
txBytes, err := rlp.EncodeToBytes(types.NewTransaction(0, predeploys.EntryPoint_v060Addr, big.NewInt(0), 0, big.NewInt(0), nil))
require.NoError(t, err)
for _, test := range tests {
ctx := context.Background()
if !test.mustFail {
ctx = context.WithValue(ctx, authContextKey{}, &AuthContext{Caller: common.HexToAddress("0xa")})
}
_, err := svc.SendRawTransactionConditional(ctx, txBytes, test.cond)
if test.mustFail && err == nil {
t.Errorf("Test %s should fail", test.name)
}
if !test.mustFail && err != nil {
t.Errorf("Test %s should pass but got err: %v", test.name, err)
}
}
}