From 94d13b8e653d1364214ab44d33ffa77aa6662baa Mon Sep 17 00:00:00 2001 From: Francisco Moura Date: Tue, 6 Aug 2024 17:22:52 -0300 Subject: [PATCH] chore(evm-reader): Make code more go-like --- internal/evmreader/evmreader.go | 68 ++++++--------- internal/evmreader/evmreader_test.go | 87 ++++++++++--------- internal/evmreader/inputsource_adapter.go | 15 ++-- .../retrypolicy_ethclient_delegator.go | 23 ++--- .../retrypolicy_ethwsclient_delegator.go | 8 +- .../retrypolicy_inputsource_delegator.go | 20 ++--- 6 files changed, 94 insertions(+), 127 deletions(-) diff --git a/internal/evmreader/evmreader.go b/internal/evmreader/evmreader.go index 41ca2ab3b..f4eb76334 100644 --- a/internal/evmreader/evmreader.go +++ b/internal/evmreader/evmreader.go @@ -9,7 +9,7 @@ import ( "log/slog" "math/big" - "github.com/cartesi/rollups-node/internal/node/model" + . "github.com/cartesi/rollups-node/internal/node/model" "github.com/cartesi/rollups-node/pkg/contracts/inputbox" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -18,52 +18,38 @@ import ( "github.com/ethereum/go-ethereum/rpc" ) -type ( - Address = common.Address - Application = model.Application - Input = model.Input - DefaultBlock = model.DefaultBlock - NodePersistentConfig = model.NodePersistentConfig - InputBoxInputAdded = inputbox.InputBoxInputAdded - FilterOpts = bind.FilterOpts - Context = context.Context - Header = types.Header - Subscription = ethereum.Subscription - Epoch = model.Epoch -) - // Interface for Input reading type InputSource interface { // Wrapper for FilterInputAdded(), which is automatically generated // by go-ethereum and cannot be used for testing RetrieveInputs( - opts *FilterOpts, - appContract []Address, + opts *bind.FilterOpts, + appContract []common.Address, index []*big.Int, - ) ([]InputBoxInputAdded, error) + ) ([]inputbox.InputBoxInputAdded, error) } // Interface for the node repository type EvmReaderRepository interface { InsertInputsAndUpdateLastProcessedBlock( - ctx Context, + ctx context.Context, inputs []Input, blockNumber uint64, - appAddress Address, + appAddress common.Address, ) error GetAllRunningApplications( - ctx Context, + ctx context.Context, ) ([]Application, error) GetNodeConfig( - ctx Context, + ctx context.Context, ) (*NodePersistentConfig, error) GetEpoch( - ctx Context, + ctx context.Context, indexKey uint64, - appAddressKey Address, + appAddressKey common.Address, ) (*Epoch, error) InsertEpoch( - ctx Context, + ctx context.Context, epoch *Epoch, ) (uint64, error) } @@ -72,18 +58,18 @@ type EvmReaderRepository interface { // interface needed by the EvmReader. It must be bound to an HTTP endpoint type EthClient interface { HeaderByNumber( - ctx Context, + ctx context.Context, number *big.Int, - ) (*Header, error) + ) (*types.Header, error) } // EthWsClient mimics part of ethclient.Client functions to narrow down the // interface needed by the EvmReader. It must be bound to a WS endpoint type EthWsClient interface { SubscribeNewHead( - ctx Context, - ch chan<- *Header, - ) (Subscription, error) + ctx context.Context, + ch chan<- *types.Header, + ) (ethereum.Subscription, error) } type SubscriptionError struct { @@ -144,10 +130,10 @@ func (r *EvmReader) Run( // Watch for new blocks and reads new inputs based on the // default block configuration, which have not been processed yet. func (r *EvmReader) watchForNewBlocks( - ctx Context, + ctx context.Context, ready chan<- struct{}, ) error { - headers := make(chan *Header) + headers := make(chan *types.Header) sub, err := r.wsClient.SubscribeNewHead(ctx, headers) if err != nil { return fmt.Errorf("could not start subscription: %v", err) @@ -177,7 +163,7 @@ func (r *EvmReader) watchForNewBlocks( } // Check if is there new Inputs for all running Applications -func (r *EvmReader) checkForNewInputs(ctx Context) error { +func (r *EvmReader) checkForNewInputs(ctx context.Context) error { // Get All Applications apps, err := r.repository.GetAllRunningApplications(ctx) @@ -255,19 +241,19 @@ func (r *EvmReader) classifyApplicationsByLastProcessedInput( // Fetch the most recent header up till the // given default block func (r *EvmReader) fetchMostRecentHeader( - ctx Context, + ctx context.Context, defaultBlock DefaultBlock, ) (*types.Header, error) { var defaultBlockNumber int64 switch defaultBlock { - case model.DefaultBlockStatusPending: + case DefaultBlockStatusPending: defaultBlockNumber = rpc.PendingBlockNumber.Int64() - case model.DefaultBlockStatusLatest: + case DefaultBlockStatusLatest: defaultBlockNumber = rpc.LatestBlockNumber.Int64() - case model.DefaultBlockStatusFinalized: + case DefaultBlockStatusFinalized: defaultBlockNumber = rpc.FinalizedBlockNumber.Int64() - case model.DefaultBlockStatusSafe: + case DefaultBlockStatusSafe: defaultBlockNumber = rpc.SafeBlockNumber.Int64() default: return nil, fmt.Errorf("Default block '%v' not supported", defaultBlock) @@ -294,9 +280,9 @@ func (r *EvmReader) readInputs( endBlock uint64, apps []Application, ) error { - filter := []Address{} + filter := []common.Address{} - var inputsMap = make(map[Address][]Input) + var inputsMap = make(map[common.Address][]Input) for _, app := range apps { filter = append(filter, app.ContractAddress) inputsMap[app.ContractAddress] = []Input{} @@ -320,7 +306,7 @@ func (r *EvmReader) readInputs( slog.Debug("received input ", "app", event.AppContract, "index", event.Index) input := Input{ Index: event.Index.Uint64(), - CompletionStatus: model.InputStatusNone, + CompletionStatus: InputStatusNone, RawData: event.Input, BlockNumber: event.Raw.BlockNumber, AppAddress: event.AppContract, diff --git a/internal/evmreader/evmreader_test.go b/internal/evmreader/evmreader_test.go index 98c501e8b..567be22c8 100644 --- a/internal/evmreader/evmreader_test.go +++ b/internal/evmreader/evmreader_test.go @@ -14,8 +14,9 @@ import ( "testing" "time" - "github.com/cartesi/rollups-node/internal/node/model" + . "github.com/cartesi/rollups-node/internal/node/model" "github.com/cartesi/rollups-node/pkg/contracts/inputbox" + "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" @@ -116,7 +117,7 @@ func (s *EvmReaderSuite) SetupTest() { s.inputBox, s.repository, NodePersistentConfig{ - DefaultBlock: model.DefaultBlockStatusLatest, + DefaultBlock: DefaultBlockStatusLatest, InputBoxDeploymentBlock: 0, }, ) @@ -170,16 +171,16 @@ func (s *EvmReaderSuite) TestItReadsInputsFromNewBlocks() { waitGroup := sync.WaitGroup{} wsClient := FakeWSEhtClient{} - wsClient.NewHeaders = []*Header{&header0, &header1} + wsClient.NewHeaders = []*types.Header{&header0, &header1} wsClient.WaitGroup = &waitGroup inputReader := NewEvmReader( s.client, &wsClient, s.inputBox, s.repository, - model.NodePersistentConfig{ + NodePersistentConfig{ InputBoxDeploymentBlock: 0x10, - DefaultBlock: model.DefaultBlockStatusLatest, + DefaultBlock: DefaultBlockStatusLatest, }, ) @@ -220,7 +221,7 @@ func (s *EvmReaderSuite) TestItReadsInputsFromNewBlocks() { // Prepare sequence of inputs s.inputBox.Unset("RetrieveInputs") - events_0 := []InputBoxInputAdded{inputAddedEvent0} + events_0 := []inputbox.InputBoxInputAdded{inputAddedEvent0} currentMostRecentFinalizedBlockNumber_0 := uint64(0x11) retrieveInputsOpts_0 := bind.FilterOpts{ Context: s.ctx, @@ -234,7 +235,7 @@ func (s *EvmReaderSuite) TestItReadsInputsFromNewBlocks() { mock.Anything, ).Return(events_0, nil) - events_1 := []InputBoxInputAdded{inputAddedEvent1} + events_1 := []inputbox.InputBoxInputAdded{inputAddedEvent1} currentMostRecentFinalizedBlockNumber_1 := uint64(0x12) retrieveInputsOpts_1 := bind.FilterOpts{ Context: s.ctx, @@ -278,16 +279,16 @@ func (s *EvmReaderSuite) TestItUpdatesLastProcessedBlockWhenThereIsNoInputs() { waitGroup := sync.WaitGroup{} wsClient := FakeWSEhtClient{} - wsClient.NewHeaders = []*Header{&header0, &header1} + wsClient.NewHeaders = []*types.Header{&header0, &header1} wsClient.WaitGroup = &waitGroup inputReader := NewEvmReader( s.client, &wsClient, s.inputBox, s.repository, - model.NodePersistentConfig{ + NodePersistentConfig{ InputBoxDeploymentBlock: 0x10, - DefaultBlock: model.DefaultBlockStatusLatest, + DefaultBlock: DefaultBlockStatusLatest, }, ) @@ -328,7 +329,7 @@ func (s *EvmReaderSuite) TestItUpdatesLastProcessedBlockWhenThereIsNoInputs() { // Prepare sequence of inputs s.inputBox.Unset("RetrieveInputs") - events_0 := []InputBoxInputAdded{} + events_0 := []inputbox.InputBoxInputAdded{} currentMostRecentFinalizedBlockNumber_0 := uint64(0x11) retrieveInputsOpts_0 := bind.FilterOpts{ Context: s.ctx, @@ -342,7 +343,7 @@ func (s *EvmReaderSuite) TestItUpdatesLastProcessedBlockWhenThereIsNoInputs() { mock.Anything, ).Return(events_0, nil) - events_1 := []InputBoxInputAdded{} + events_1 := []inputbox.InputBoxInputAdded{} currentMostRecentFinalizedBlockNumber_1 := uint64(0x12) retrieveInputsOpts_1 := bind.FilterOpts{ Context: s.ctx, @@ -386,16 +387,16 @@ func (s *EvmReaderSuite) TestItReadsMultipleInputsFromSingleNewBlock() { waitGroup := sync.WaitGroup{} wsClient := FakeWSEhtClient{} - wsClient.NewHeaders = []*Header{&header2} + wsClient.NewHeaders = []*types.Header{&header2} wsClient.WaitGroup = &waitGroup inputReader := NewEvmReader( s.client, &wsClient, s.inputBox, s.repository, - model.NodePersistentConfig{ + NodePersistentConfig{ InputBoxDeploymentBlock: 0x10, - DefaultBlock: model.DefaultBlockStatusLatest, + DefaultBlock: DefaultBlockStatusLatest, }, ) @@ -439,9 +440,9 @@ func (s *EvmReaderSuite) TestItReadsMultipleInputsFromSingleNewBlock() { mock.Anything, mock.Anything, ).Once().Run(func(arguments mock.Arguments) { - var inputs []model.Input + var inputs []Input obj := arguments.Get(1) - inputs, ok := obj.([]model.Input) + inputs, ok := obj.([]Input) s.Require().True(ok) s.Assert().Equal(2, len(inputs)) }).Return(nil) @@ -476,16 +477,16 @@ func (s *EvmReaderSuite) TestItStartsWhenLasProcessedBlockIsTheMostRecentBlock() waitGroup := sync.WaitGroup{} wsClient := FakeWSEhtClient{} - wsClient.NewHeaders = []*Header{&header2} + wsClient.NewHeaders = []*types.Header{&header2} wsClient.WaitGroup = &waitGroup inputReader := NewEvmReader( s.client, &wsClient, s.inputBox, s.repository, - model.NodePersistentConfig{ + NodePersistentConfig{ InputBoxDeploymentBlock: 0x10, - DefaultBlock: model.DefaultBlockStatusLatest, + DefaultBlock: DefaultBlockStatusLatest, }, ) @@ -565,17 +566,17 @@ func (m *MockEthClient) Unset(methodName string) { func (m *MockEthClient) HeaderByNumber( ctx context.Context, number *big.Int, -) (*Header, error) { +) (*types.Header, error) { args := m.Called(ctx, number) - return args.Get(0).(*Header), args.Error(1) + return args.Get(0).(*types.Header), args.Error(1) } func (m *MockEthClient) SubscribeNewHead( ctx context.Context, - ch chan<- *Header, -) (Subscription, error) { + ch chan<- *types.Header, +) (ethereum.Subscription, error) { args := m.Called(ctx, ch) - return args.Get(0).(Subscription), args.Error(1) + return args.Get(0).(ethereum.Subscription), args.Error(1) } // Mock ethereum.Subscription @@ -602,14 +603,14 @@ func (m *MockSubscription) Err() <-chan error { // FakeClient type FakeWSEhtClient struct { - NewHeaders []*Header + NewHeaders []*types.Header WaitGroup *sync.WaitGroup } func (f *FakeWSEhtClient) SubscribeNewHead( - ctx Context, - ch chan<- *Header, -) (Subscription, error) { + ctx context.Context, + ch chan<- *types.Header, +) (ethereum.Subscription, error) { go func() { for _, header := range f.NewHeaders { @@ -630,7 +631,7 @@ type MockInputBox struct { func newMockInputBox(s *EvmReaderSuite) *MockInputBox { inputSource := &MockInputBox{} - events := []InputBoxInputAdded{inputAddedEvent0} + events := []inputbox.InputBoxInputAdded{inputAddedEvent0} inputSource.On("RetrieveInputs", mock.Anything, mock.Anything, @@ -649,12 +650,12 @@ func (m *MockInputBox) Unset(methodName string) { } func (m *MockInputBox) RetrieveInputs( - opts *FilterOpts, - appContract []Address, + opts *bind.FilterOpts, + appContract []common.Address, index []*big.Int, -) ([]InputBoxInputAdded, error) { +) ([]inputbox.InputBoxInputAdded, error) { args := m.Called(opts, appContract, index) - return args.Get(0).([]InputBoxInputAdded), args.Error(1) + return args.Get(0).([]inputbox.InputBoxInputAdded), args.Error(1) } // Mock InputReaderRepository @@ -678,12 +679,12 @@ func newMockRepository() *MockRepository { mock.Anything, mock.Anything, mock.Anything).Return( - &model.Epoch{ + &Epoch{ Id: 1, Index: 0, FirstBlock: 0, LastBlock: math.MaxUint64, - Status: model.EpochStatusOpen, + Status: EpochStatusOpen, AppAddress: common.HexToAddress("0x2E663fe9aE92275242406A185AA4fC8174339D3E"), ClaimHash: nil, TransactionHash: nil, @@ -706,40 +707,40 @@ func (m *MockRepository) Unset(methodName string) { } func (m *MockRepository) InsertInputsAndUpdateLastProcessedBlock( - ctx Context, + ctx context.Context, inputs []Input, blockNumber uint64, - appAddress Address, + appAddress common.Address, ) error { args := m.Called(ctx, inputs, blockNumber) return args.Error(0) } func (m *MockRepository) GetAllRunningApplications( - ctx Context, + ctx context.Context, ) ([]Application, error) { args := m.Called(ctx) return args.Get(0).([]Application), args.Error(1) } func (m *MockRepository) GetNodeConfig( - ctx Context, + ctx context.Context, ) (*NodePersistentConfig, error) { args := m.Called(ctx) return args.Get(0).(*NodePersistentConfig), args.Error(1) } func (m *MockRepository) GetEpoch( - ctx Context, + ctx context.Context, index uint64, - appAddress Address, + appAddress common.Address, ) (*Epoch, error) { args := m.Called(ctx) return args.Get(0).(*Epoch), args.Error(1) } func (m *MockRepository) InsertEpoch( - ctx Context, + ctx context.Context, epoch *Epoch, ) (uint64, error) { args := m.Called(ctx) diff --git a/internal/evmreader/inputsource_adapter.go b/internal/evmreader/inputsource_adapter.go index 6f91f4df4..eda9754a4 100644 --- a/internal/evmreader/inputsource_adapter.go +++ b/internal/evmreader/inputsource_adapter.go @@ -8,20 +8,17 @@ import ( "github.com/cartesi/rollups-node/pkg/contracts/inputbox" "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethclient" ) -type ( - InputBox = inputbox.InputBox -) - // InputBox Wrapper type InputSourceAdapter struct { - inputbox *InputBox + inputbox *inputbox.InputBox } func NewInputSourceAdapter( - inputBoxAddress Address, + inputBoxAddress common.Address, client *ethclient.Client, ) (*InputSourceAdapter, error) { inputbox, err := inputbox.NewInputBox(inputBoxAddress, client) @@ -35,9 +32,9 @@ func NewInputSourceAdapter( func (i *InputSourceAdapter) RetrieveInputs( opts *bind.FilterOpts, - appContract []Address, + appContract []common.Address, index []*big.Int, -) ([]InputBoxInputAdded, error) { +) ([]inputbox.InputBoxInputAdded, error) { itr, err := i.inputbox.FilterInputAdded(opts, appContract, index) if err != nil { @@ -45,7 +42,7 @@ func (i *InputSourceAdapter) RetrieveInputs( } defer itr.Close() - var events []InputBoxInputAdded + var events []inputbox.InputBoxInputAdded for itr.Next() { inputAddedEvent := itr.Event events = append(events, *inputAddedEvent) diff --git a/internal/evmreader/retrypolicy/retrypolicy_ethclient_delegator.go b/internal/evmreader/retrypolicy/retrypolicy_ethclient_delegator.go index 3b655d818..ea796c278 100644 --- a/internal/evmreader/retrypolicy/retrypolicy_ethclient_delegator.go +++ b/internal/evmreader/retrypolicy/retrypolicy_ethclient_delegator.go @@ -6,31 +6,26 @@ package retrypolicy import ( "context" "math/big" + "time" "github.com/cartesi/rollups-node/internal/evmreader" "github.com/cartesi/rollups-node/internal/util/retrypolicy" "github.com/ethereum/go-ethereum/core/types" ) -type ( - EthClient = evmreader.EthClient - Header = types.Header - Context = context.Context -) - // A EthClient Delegator that // calls HeaderByNumber with the retry // policy defined by util.RetryFunction type EthClientRetryPolicyDelegator struct { - delegate EthClient + delegate evmreader.EthClient maxRetries uint64 - delayBetweenCalls Duration + delayBetweenCalls time.Duration } func NewEhtClientWithRetryPolicy( - delegate EthClient, + delegate evmreader.EthClient, maxRetries uint64, - delayBetweenCalls Duration, + delayBetweenCalls time.Duration, ) *EthClientRetryPolicyDelegator { return &EthClientRetryPolicyDelegator{ delegate: delegate, @@ -40,14 +35,14 @@ func NewEhtClientWithRetryPolicy( } type headerByNumberArgs struct { - ctx Context + ctx context.Context number *big.Int } func (d *EthClientRetryPolicyDelegator) HeaderByNumber( - ctx Context, + ctx context.Context, number *big.Int, -) (*Header, error) { +) (*types.Header, error) { return retrypolicy.CallFunctionWithRetryPolicy(d.headerByNumber, headerByNumberArgs{ @@ -63,6 +58,6 @@ func (d *EthClientRetryPolicyDelegator) HeaderByNumber( func (d *EthClientRetryPolicyDelegator) headerByNumber( args headerByNumberArgs, -) (*Header, error) { +) (*types.Header, error) { return d.delegate.HeaderByNumber(args.ctx, args.number) } diff --git a/internal/evmreader/retrypolicy/retrypolicy_ethwsclient_delegator.go b/internal/evmreader/retrypolicy/retrypolicy_ethwsclient_delegator.go index ae5eee997..93f2a298a 100644 --- a/internal/evmreader/retrypolicy/retrypolicy_ethwsclient_delegator.go +++ b/internal/evmreader/retrypolicy/retrypolicy_ethwsclient_delegator.go @@ -13,18 +13,14 @@ import ( "github.com/ethereum/go-ethereum/core/types" ) -type ( - EthWsClient = evmreader.EthWsClient -) - type EthWsClientRetryPolicyDelegator struct { - delegate EthWsClient + delegate evmreader.EthWsClient maxRetries uint64 delayBetweenCalls time.Duration } func NewEthWsClientWithRetryPolicy( - delegate EthWsClient, + delegate evmreader.EthWsClient, maxRetries uint64, delayBetweenCalls time.Duration, ) *EthWsClientRetryPolicyDelegator { diff --git a/internal/evmreader/retrypolicy/retrypolicy_inputsource_delegator.go b/internal/evmreader/retrypolicy/retrypolicy_inputsource_delegator.go index 02b6b5135..2da908688 100644 --- a/internal/evmreader/retrypolicy/retrypolicy_inputsource_delegator.go +++ b/internal/evmreader/retrypolicy/retrypolicy_inputsource_delegator.go @@ -14,22 +14,14 @@ import ( "github.com/ethereum/go-ethereum/common" ) -type ( - InputSource = evmreader.InputSource - Duration = time.Duration - Address = common.Address - FilterOpts = bind.FilterOpts - InputBoxInputAdded = inputbox.InputBoxInputAdded -) - type InputSourceWithRetryPolicyDelegator struct { - delegate InputSource + delegate evmreader.InputSource maxRetries uint64 delay time.Duration } func NewInputSourceWithRetryPolicy( - delegate InputSource, + delegate evmreader.InputSource, maxRetries uint64, delay time.Duration, ) *InputSourceWithRetryPolicyDelegator { @@ -41,8 +33,8 @@ func NewInputSourceWithRetryPolicy( } type retrieveInputsArgs struct { - opts *FilterOpts - appContract []Address + opts *bind.FilterOpts + appContract []common.Address index []*big.Int } @@ -50,7 +42,7 @@ func (d *InputSourceWithRetryPolicyDelegator) RetrieveInputs( opts *bind.FilterOpts, appContract []common.Address, index []*big.Int, -) ([]InputBoxInputAdded, error) { +) ([]inputbox.InputBoxInputAdded, error) { return retrypolicy.CallFunctionWithRetryPolicy(d.retrieveInputs, retrieveInputsArgs{ opts: opts, @@ -65,7 +57,7 @@ func (d *InputSourceWithRetryPolicyDelegator) RetrieveInputs( func (d *InputSourceWithRetryPolicyDelegator) retrieveInputs( args retrieveInputsArgs, -) ([]InputBoxInputAdded, error) { +) ([]inputbox.InputBoxInputAdded, error) { return d.delegate.RetrieveInputs( args.opts, args.appContract,