From bcc9bfe5fb220f5444355171882dcfbafd08bc8f Mon Sep 17 00:00:00 2001 From: Francisco Moura Date: Fri, 2 Aug 2024 01:36:42 -0300 Subject: [PATCH 1/4] feat(db): Add Epoch and Snapshot --- internal/evmreader/evmreader.go | 14 +- internal/evmreader/evmreader_test.go | 38 +++ internal/node/model/models.go | 38 ++- internal/repository/base.go | 226 +++++++++++++++++- internal/repository/base_test.go | 176 +++++++++++--- internal/repository/evmreader.go | 15 +- internal/repository/evmreader_test.go | 10 +- ...ut_claim_output_report_nodeconfig.down.sql | 3 + ...nput_claim_output_report_nodeconfig.up.sql | 32 ++- .../000002_create_postgraphile_view.up.sql | 40 +++- internal/repository/validator.go | 86 ++++--- internal/repository/validator_test.go | 63 +++-- 12 files changed, 609 insertions(+), 132 deletions(-) diff --git a/internal/evmreader/evmreader.go b/internal/evmreader/evmreader.go index e7f4d22fa..41ca2ab3b 100644 --- a/internal/evmreader/evmreader.go +++ b/internal/evmreader/evmreader.go @@ -29,6 +29,7 @@ type ( Context = context.Context Header = types.Header Subscription = ethereum.Subscription + Epoch = model.Epoch ) // Interface for Input reading @@ -51,11 +52,20 @@ type EvmReaderRepository interface { appAddress Address, ) error GetAllRunningApplications( - ctx context.Context, + ctx Context, ) ([]Application, error) GetNodeConfig( - ctx context.Context, + ctx Context, ) (*NodePersistentConfig, error) + GetEpoch( + ctx Context, + indexKey uint64, + appAddressKey Address, + ) (*Epoch, error) + InsertEpoch( + ctx Context, + epoch *Epoch, + ) (uint64, error) } // EthClient mimics part of ethclient.Client functions to narrow down the diff --git a/internal/evmreader/evmreader_test.go b/internal/evmreader/evmreader_test.go index eb15e01f7..98c501e8b 100644 --- a/internal/evmreader/evmreader_test.go +++ b/internal/evmreader/evmreader_test.go @@ -8,6 +8,7 @@ import ( _ "embed" "encoding/json" "fmt" + "math" "math/big" "sync" "testing" @@ -673,7 +674,27 @@ func newMockRepository() *MockRepository { mock.Anything, mock.Anything).Return(nil) + repo.On("GetEpoch", + mock.Anything, + mock.Anything, + mock.Anything).Return( + &model.Epoch{ + Id: 1, + Index: 0, + FirstBlock: 0, + LastBlock: math.MaxUint64, + Status: model.EpochStatusOpen, + AppAddress: common.HexToAddress("0x2E663fe9aE92275242406A185AA4fC8174339D3E"), + ClaimHash: nil, + TransactionHash: nil, + }, nil) + + repo.On("InsertEpoch", + mock.Anything, + mock.Anything).Return(1, nil) + return repo + } func (m *MockRepository) Unset(methodName string) { @@ -707,3 +728,20 @@ func (m *MockRepository) GetNodeConfig( args := m.Called(ctx) return args.Get(0).(*NodePersistentConfig), args.Error(1) } + +func (m *MockRepository) GetEpoch( + ctx Context, + index uint64, + appAddress Address, +) (*Epoch, error) { + args := m.Called(ctx) + return args.Get(0).(*Epoch), args.Error(1) +} + +func (m *MockRepository) InsertEpoch( + ctx Context, + epoch *Epoch, +) (uint64, error) { + args := m.Called(ctx) + return args.Get(0).(uint64), args.Error(1) +} diff --git a/internal/node/model/models.go b/internal/node/model/models.go index b70b6b1b2..407cc239a 100644 --- a/internal/node/model/models.go +++ b/internal/node/model/models.go @@ -11,10 +11,12 @@ import ( type ( Hash = common.Hash Address = common.Address + Bytes = hexutil.Bytes InputCompletionStatus string ClaimStatus string ApplicationStatus string DefaultBlock string + EpochStatus string ) const ( @@ -46,6 +48,16 @@ const ( DefaultBlockStatusSafe DefaultBlock = "SAFE" ) +const ( + EpochStatusOpen EpochStatus = "OPEN" + EpochStatusClosed EpochStatus = "CLOSED" + EpochStatusProcessedAllInputs EpochStatus = "PROCESSED_ALL_INPUTS" + EpochStatusClaimComputed EpochStatus = "CLAIM_COMPUTED" + EpochStatusClaimSubmitted EpochStatus = "CLAIM_SUBMITTED" + EpochStatusClaimAccepted EpochStatus = "CLAIM_ACCEPTED" + EpochStatusClaimRejected EpochStatus = "CLAIM_REJECTED" +) + type NodePersistentConfig struct { DefaultBlock DefaultBlock InputBoxDeploymentBlock uint64 @@ -58,27 +70,38 @@ type Application struct { Id uint64 ContractAddress Address TemplateHash Hash - SnapshotURI string LastProcessedBlock uint64 EpochLength uint64 Status ApplicationStatus } +type Epoch struct { + Id uint64 + Index uint64 + FirstBlock uint64 + LastBlock uint64 + ClaimHash *Hash + TransactionHash *Hash + Status EpochStatus + AppAddress Address +} + type Input struct { Id uint64 Index uint64 CompletionStatus InputCompletionStatus - RawData hexutil.Bytes + RawData Bytes BlockNumber uint64 MachineHash *Hash OutputsHash *Hash AppAddress Address + EpochId uint64 } type Output struct { Id uint64 Index uint64 - RawData hexutil.Bytes + RawData Bytes Hash *Hash OutputHashesSiblings []Hash InputId uint64 @@ -87,7 +110,7 @@ type Output struct { type Report struct { Id uint64 Index uint64 - RawData hexutil.Bytes + RawData Bytes InputId uint64 } @@ -99,3 +122,10 @@ type Claim struct { TransactionHash *Hash AppAddress Address } + +type Snapshot struct { + Id uint64 + URI string + InputId uint64 + AppAddress Address +} diff --git a/internal/repository/base.go b/internal/repository/base.go index 9bfc6dac4..3ced8684f 100644 --- a/internal/repository/base.go +++ b/internal/repository/base.go @@ -92,14 +92,12 @@ func (pg *Database) InsertApplication( INSERT INTO application (contract_address, template_hash, - snapshot_uri, last_processed_block, epoch_length, status) VALUES (@contractAddress, @templateHash, - @snapshotUri, @lastProcessedBlock, @epochLength, @status)` @@ -107,7 +105,6 @@ func (pg *Database) InsertApplication( args := pgx.NamedArgs{ "contractAddress": app.ContractAddress, "templateHash": app.TemplateHash, - "snapshotUri": app.SnapshotURI, "lastProcessedBlock": app.LastProcessedBlock, "epochLength": app.EpochLength, "status": app.Status, @@ -121,6 +118,51 @@ func (pg *Database) InsertApplication( return nil } +func (pg *Database) InsertEpoch( + ctx context.Context, + epoch *Epoch, +) (uint64, error) { + + var id uint64 + + query := ` + INSERT INTO epoch + (index, + first_block, + last_block, + transaction_hash, + claim_hash, + status, + application_address) + VALUES + (@index, + @firstBlock, + @lastBlock, + @transactionHash, + @claimHash, + @status, + @applicationAddress) + RETURNING + id` + + args := pgx.NamedArgs{ + "index": epoch.Index, + "firstBlock": epoch.FirstBlock, + "lastBlock": epoch.LastBlock, + "transactionHash": epoch.TransactionHash, + "claimHash": epoch.ClaimHash, + "status": epoch.Status, + "applicationAddress": epoch.AppAddress, + } + + err := pg.db.QueryRow(ctx, query, args).Scan(&id) + if err != nil { + return 0, fmt.Errorf("%w: %w", ErrInsertRow, err) + } + + return id, nil +} + func (pg *Database) InsertInput( ctx context.Context, input *Input, @@ -133,7 +175,8 @@ func (pg *Database) InsertInput( block_number, machine_hash, outputs_hash, - application_address) + application_address, + epoch_id) VALUES (@index, @status, @@ -141,7 +184,8 @@ func (pg *Database) InsertInput( @blockNumber, @machineHash, @outputsHash, - @applicationAddress)` + @applicationAddress, + @epochId)` args := pgx.NamedArgs{ "index": input.Index, @@ -151,6 +195,7 @@ func (pg *Database) InsertInput( "machineHash": input.MachineHash, "outputsHash": input.OutputsHash, "applicationAddress": input.AppAddress, + "epochId": input.EpochId, } _, err := pg.db.Exec(ctx, query, args) @@ -254,6 +299,35 @@ func (pg *Database) InsertClaim( return nil } +func (pg *Database) InsertSnapshot( + ctx context.Context, + snapshot *Snapshot, +) (id uint64, _ error) { + query := ` + INSERT INTO snapshot + (input_id, + application_address, + uri) + VALUES + (@inputId, + @appAddress, + @uri) + RETURNING id` + + args := pgx.NamedArgs{ + "inputId": snapshot.InputId, + "appAddress": snapshot.AppAddress, + "uri": snapshot.URI, + } + + err := pg.db.QueryRow(ctx, query, args).Scan(&id) + if err != nil { + return 0, fmt.Errorf("%w: %w", ErrInsertRow, err) + } + + return id, nil +} + func (pg *Database) GetNodeConfig( ctx context.Context, ) (*NodePersistentConfig, error) { @@ -305,7 +379,6 @@ func (pg *Database) GetApplication( id uint64 contractAddress Address templateHash Hash - snapshotUri string lastProcessedBlock uint64 epochLength uint64 status ApplicationStatus @@ -316,7 +389,6 @@ func (pg *Database) GetApplication( id, contract_address, template_hash, - snapshot_uri, last_processed_block, epoch_length, status @@ -333,7 +405,6 @@ func (pg *Database) GetApplication( &id, &contractAddress, &templateHash, - &snapshotUri, &lastProcessedBlock, &epochLength, &status, @@ -350,7 +421,6 @@ func (pg *Database) GetApplication( Id: id, ContractAddress: contractAddress, TemplateHash: templateHash, - SnapshotURI: snapshotUri, LastProcessedBlock: lastProcessedBlock, EpochLength: epochLength, Status: status, @@ -359,6 +429,75 @@ func (pg *Database) GetApplication( return &app, nil } +func (pg *Database) GetEpoch( + ctx context.Context, + indexKey uint64, + appAddressKey Address, +) (*Epoch, error) { + var ( + id uint64 + index uint64 + firstBlock uint64 + lastBlock uint64 + transactionHash *Hash + claimHash *Hash + status EpochStatus + applicationAddress Address + ) + + query := ` + SELECT + id, + index, + first_block, + last_block, + transaction_hash, + claim_hash, + status, + application_address + FROM + epoch + WHERE + index=@index AND application_address=@appAddress` + + args := pgx.NamedArgs{ + "index": indexKey, + "appAddress": appAddressKey, + } + + err := pg.db.QueryRow(ctx, query, args).Scan( + &id, + &index, + &firstBlock, + &lastBlock, + &transactionHash, + &claimHash, + &status, + &applicationAddress, + ) + if err != nil { + if errors.Is(err, pgx.ErrNoRows) { + slog.Info("GetEpoch returned no rows", "service", "repository") + return nil, nil + } + return nil, fmt.Errorf("GetEpoch QueryRow failed: %w\n", err) + } + + epoch := Epoch{ + Id: id, + Index: index, + FirstBlock: firstBlock, + LastBlock: lastBlock, + TransactionHash: transactionHash, + ClaimHash: claimHash, + Status: status, + AppAddress: applicationAddress, + } + + return &epoch, nil + +} + func (pg *Database) GetInput( ctx context.Context, indexKey uint64, @@ -373,6 +512,7 @@ func (pg *Database) GetInput( machineHash *Hash outputsHash *Hash appAddress Address + epochId uint64 ) query := ` @@ -384,11 +524,12 @@ func (pg *Database) GetInput( block_number, machine_hash, outputs_hash, - application_address + application_address, + epoch_id FROM input WHERE - index=@index and application_address=@appAddress` + index=@index AND application_address=@appAddress` args := pgx.NamedArgs{ "index": indexKey, @@ -404,6 +545,7 @@ func (pg *Database) GetInput( &machineHash, &outputsHash, &appAddress, + &epochId, ) if err != nil { if errors.Is(err, pgx.ErrNoRows) { @@ -422,6 +564,7 @@ func (pg *Database) GetInput( MachineHash: machineHash, OutputsHash: outputsHash, AppAddress: appAddress, + EpochId: epochId, } return &input, nil @@ -456,7 +599,7 @@ func (pg *Database) GetOutput( ON o.input_id=i.id WHERE - o.index=@index and i.application_address=@appAddress` + o.index=@index AND i.application_address=@appAddress` args := pgx.NamedArgs{ "index": indexKey, @@ -515,7 +658,7 @@ func (pg *Database) GetReport( ON r.input_id=i.id WHERE - r.index=@index and i.application_address=@appAddress` + r.index=@index AND i.application_address=@appAddress` args := pgx.NamedArgs{ "index": indexKey, @@ -604,3 +747,60 @@ func (pg *Database) GetClaim( return &claim, nil } + + +func (pg *Database) GetSnapshot( + ctx context.Context, + inputIndexKey uint64, + appAddressKey Address, +) (*Snapshot, error) { + var ( + id uint64 + inputId uint64 + appAddress Address + uri string + ) + query := ` + SELECT + s.id, + s.input_id, + s.application_address, + s.uri + FROM + snapshot s + INNER JOIN + input i + ON + i.id = s.input_id + WHERE + s.application_address=@appAddress AND i.index=@inputIndex + ` + + args := pgx.NamedArgs{ + "inputIndex": inputIndexKey, + "appAddress": appAddressKey, + } + err := pg.db.QueryRow(ctx, query, args).Scan( + &id, + &inputId, + &appAddress, + &uri, + ) + if err != nil { + if errors.Is(err, pgx.ErrNoRows) { + slog.Info("GetSnapshot returned no rows", "service", "repository") + return nil, nil + } + return nil, fmt.Errorf("GetSnapshot QueryRow failed: %w\n", err) + } + + snapshot := Snapshot{ + Id: id, + InputId: inputId, + AppAddress: appAddress, + URI: uri, + } + + return &snapshot, nil + +} diff --git a/internal/repository/base_test.go b/internal/repository/base_test.go index 29b7f1d6b..4c2d80e05 100644 --- a/internal/repository/base_test.go +++ b/internal/repository/base_test.go @@ -5,6 +5,7 @@ package repository import ( "context" + "math" "testing" "time" @@ -68,20 +69,16 @@ func (s *RepositorySuite) SetupDatabase() { s.Require().Nil(err) app := Application{ - Id: 1, ContractAddress: common.HexToAddress("deadbeef"), TemplateHash: common.HexToHash("deadbeef"), - SnapshotURI: "this/is/a/test", LastProcessedBlock: 1, EpochLength: 10, Status: ApplicationStatusRunning, } app2 := Application{ - Id: 1, ContractAddress: common.HexToAddress("feadbeef"), TemplateHash: common.HexToHash("deadbeef"), - SnapshotURI: "this/is/a/test", LastProcessedBlock: 1, EpochLength: 10, Status: ApplicationStatusNotRunning, @@ -95,32 +92,79 @@ func (s *RepositorySuite) SetupDatabase() { genericHash := common.HexToHash("deadbeef") + epoch1 := Epoch{ + Id: 1, + Index: 0, + FirstBlock: 0, + LastBlock: math.MaxUint64 / 2, + AppAddress: app.ContractAddress, + ClaimHash: nil, + TransactionHash: nil, + Status: EpochStatusOpen, + } + + _, err = s.database.InsertEpoch(s.ctx, &epoch1) + s.Require().Nil(err) + + epoch2 := Epoch{ + Id: 2, + Index: 1, + FirstBlock: (math.MaxUint64 / 2) + 1, + LastBlock: math.MaxUint64, + AppAddress: app.ContractAddress, + ClaimHash: nil, + TransactionHash: nil, + Status: EpochStatusOpen, + } + + _, err = s.database.InsertEpoch(s.ctx, &epoch2) + s.Require().Nil(err) + input1 := Input{ + Id: 1, Index: 1, CompletionStatus: InputStatusAccepted, RawData: common.Hex2Bytes("deadbeef"), BlockNumber: 1, MachineHash: &genericHash, OutputsHash: &genericHash, - AppAddress: common.HexToAddress("deadbeef"), + AppAddress: app.ContractAddress, + EpochId: 1, } err = s.database.InsertInput(s.ctx, &input1) s.Require().Nil(err) input2 := Input{ + Id: 2, Index: 2, CompletionStatus: InputStatusNone, RawData: common.Hex2Bytes("deadbeef"), BlockNumber: 3, MachineHash: &genericHash, OutputsHash: &genericHash, - AppAddress: common.HexToAddress("deadbeef"), + AppAddress: app.ContractAddress, + EpochId: 1, } err = s.database.InsertInput(s.ctx, &input2) s.Require().Nil(err) + input3 := Input{ + Id: 3, + Index: 3, + CompletionStatus: InputStatusAccepted, + RawData: common.Hex2Bytes("deadbeef"), + BlockNumber: (math.MaxUint64 / 2) + 1, + MachineHash: &genericHash, + OutputsHash: &genericHash, + AppAddress: app.ContractAddress, + EpochId: 2, + } + + err = s.database.InsertInput(s.ctx, &input3) + s.Require().Nil(err) + var siblings []Hash siblings = append(siblings, genericHash) @@ -128,7 +172,7 @@ func (s *RepositorySuite) SetupDatabase() { Index: 1, InputId: 1, RawData: common.Hex2Bytes("deadbeef"), - OutputHashesSiblings: nil, + OutputHashesSiblings: siblings, } err = s.database.InsertOutput(s.ctx, &output0) @@ -138,19 +182,29 @@ func (s *RepositorySuite) SetupDatabase() { Index: 2, InputId: 1, RawData: common.Hex2Bytes("deadbeef"), - OutputHashesSiblings: nil, + OutputHashesSiblings: siblings, } err = s.database.InsertOutput(s.ctx, &output1) s.Require().Nil(err) - output3 := Output{ + output2 := Output{ Index: 3, InputId: 2, RawData: common.Hex2Bytes("deadbeef"), OutputHashesSiblings: siblings, } + err = s.database.InsertOutput(s.ctx, &output2) + s.Require().Nil(err) + + output3 := Output{ + Index: 4, + InputId: 3, + RawData: common.Hex2Bytes("deadbeef"), + OutputHashesSiblings: siblings, + } + err = s.database.InsertOutput(s.ctx, &output3) s.Require().Nil(err) @@ -173,6 +227,16 @@ func (s *RepositorySuite) SetupDatabase() { err = s.database.InsertClaim(s.ctx, &claim) s.Require().Nil(err) + + snapshot := Snapshot{ + InputId: 1, + AppAddress: app.ContractAddress, + URI: "/some/path", + } + + id, err := s.database.InsertSnapshot(s.ctx, &snapshot) + s.Require().Nil(err) + s.Require().Equal(uint64(1), id) } func (s *RepositorySuite) TestApplicationExists() { @@ -180,7 +244,6 @@ func (s *RepositorySuite) TestApplicationExists() { Id: 1, ContractAddress: common.HexToAddress("deadbeef"), TemplateHash: common.HexToHash("deadbeef"), - SnapshotURI: "this/is/a/test", LastProcessedBlock: 1, EpochLength: 10, Status: ApplicationStatusRunning, @@ -202,7 +265,6 @@ func (s *RepositorySuite) TestApplicationFailsDuplicateRow() { Id: 1, ContractAddress: common.HexToAddress("deadbeef"), TemplateHash: common.HexToHash("deadbeef"), - SnapshotURI: "this/is/a/test", LastProcessedBlock: 1, EpochLength: 10, Status: ApplicationStatusRunning, @@ -224,6 +286,7 @@ func (s *RepositorySuite) TestInputExists() { MachineHash: &genericHash, OutputsHash: &genericHash, AppAddress: common.HexToAddress("deadbeef"), + EpochId: 1, } response, err := s.database.GetInput(s.ctx, 1, common.HexToAddress("deadbeef")) @@ -351,53 +414,88 @@ func (s *RepositorySuite) TestReportFailsInputDoesntExist() { s.Require().ErrorContains(err, "violates foreign key constraint") } -func (s *RepositorySuite) TestClaimExists() { - genericHash := common.HexToHash("deadbeef") - - claim := Claim{ - Id: 1, - Status: ClaimStatusPending, - Index: 1, - TransactionHash: &genericHash, - OutputMerkleRootHash: common.HexToHash("deadbeef"), - AppAddress: common.HexToAddress("deadbeef"), +func (s *RepositorySuite) TestEpochExists() { + + epoch := Epoch{ + Id: 1, + Status: EpochStatusOpen, + Index: 0, + FirstBlock: 0, + LastBlock: (math.MaxUint64 / 2), + TransactionHash: nil, + ClaimHash: nil, + AppAddress: common.HexToAddress("deadbeef"), } - response, err := s.database.GetClaim(s.ctx, common.HexToAddress("deadbeef"), 1) - s.Require().Equal(claim, *response) + response, err := s.database.GetEpoch(s.ctx, 0, common.HexToAddress("deadbeef")) + s.Require().Equal(epoch, *response) s.Require().Nil(err) } -func (s *RepositorySuite) TestClaimDoesntExist() { - response, err := s.database.GetClaim(s.ctx, common.HexToAddress("deadbeef"), 0) +func (s *RepositorySuite) TestEpochDoesntExist() { + response, err := s.database.GetEpoch(s.ctx, 3, common.HexToAddress("deadbeef")) s.Require().Nil(response) s.Require().Nil(err) } -func (s *RepositorySuite) TestClaimFailsDuplicateRow() { - claim := Claim{ - Status: ClaimStatusPending, - Index: 1, - OutputMerkleRootHash: common.HexToHash("deadbeef"), - AppAddress: common.HexToAddress("deadbeef"), +func (s *RepositorySuite) TestEpochFailsDuplicateRow() { + epoch := Epoch{ + Status: EpochStatusOpen, + Index: 0, + FirstBlock: 0, + LastBlock: math.MaxUint64, + TransactionHash: nil, + ClaimHash: nil, + AppAddress: common.HexToAddress("deadbeef"), } - err := s.database.InsertClaim(s.ctx, &claim) + _, err := s.database.InsertEpoch(s.ctx, &epoch) s.Require().ErrorContains(err, "duplicate key value") } -func (s *RepositorySuite) TestClaimFailsApplicationDoesntExist() { - claim := Claim{ - Status: ClaimStatusPending, - Index: 2, - OutputMerkleRootHash: common.HexToHash("deadbeef"), - AppAddress: common.HexToAddress("deadbeefaaa"), +func (s *RepositorySuite) TestEpochFailsApplicationDoesntExist() { + hash := common.HexToHash("deadbeef") + epoch := Epoch{ + Status: EpochStatusOpen, + Index: 2, + FirstBlock: 0, + LastBlock: math.MaxUint64, + ClaimHash: &hash, + AppAddress: common.HexToAddress("deadbeefaaa"), } - err := s.database.InsertClaim(s.ctx, &claim) + _, err := s.database.InsertEpoch(s.ctx, &epoch) s.Require().ErrorContains(err, "violates foreign key constraint") } +func (s *RepositorySuite) TestGetSnapshot() { + + expectedSnapshot := Snapshot{ + Id: 1, + InputId: 1, + AppAddress: common.HexToAddress("deadbeef"), + URI: "/some/path", + } + + actualSnapshot, err := s.database.GetSnapshot(s.ctx, 1, common.HexToAddress("deadbeef")) + s.Require().Nil(err) + s.Require().NotNil(actualSnapshot) + s.Require().Equal(&expectedSnapshot, actualSnapshot) +} + +func (s *RepositorySuite) TestInsertSnapshotFailsSameInputId() { + + snapshot := Snapshot{ + InputId: 1, + AppAddress: common.HexToAddress("feadbeef"), + URI: "/some/path", + } + + _, err := s.database.InsertSnapshot(s.ctx, &snapshot) + s.Require().ErrorContains(err, "violates unique constraint") + +} + func TestRepositorySuite(t *testing.T) { suite.Run(t, new(RepositorySuite)) } diff --git a/internal/repository/evmreader.go b/internal/repository/evmreader.go index 1fa7a5be9..388f104e4 100644 --- a/internal/repository/evmreader.go +++ b/internal/repository/evmreader.go @@ -26,13 +26,15 @@ func (pg *Database) InsertInputsAndUpdateLastProcessedBlock( status, raw_data, block_number, - application_address) + application_address, + epoch_id) VALUES (@index, @status, @rawData, @blockNumber, - @appAddress)` + @appAddress, + @epochId)` query2 := ` UPDATE application @@ -57,21 +59,22 @@ func (pg *Database) InsertInputsAndUpdateLastProcessedBlock( "rawData": input.RawData, "blockNumber": input.BlockNumber, "appAddress": input.AppAddress, + "epochId": input.EpochId, } _, err = tx.Exec(ctx, query, inputArgs) if err != nil { - return fmt.Errorf("%w: %w", errInsertInputs, err) + return errors.Join(errInsertInputs, err, tx.Rollback(ctx)) } } _, err = tx.Exec(ctx, query2, args) if err != nil { - return fmt.Errorf("%w: %w", errInsertInputs, err) + return errors.Join(errInsertInputs, err, tx.Rollback(ctx)) } err = tx.Commit(ctx) if err != nil { - return fmt.Errorf("%w: %w", errInsertInputs, err) + return errors.Join(errInsertInputs, err, tx.Rollback(ctx)) } return nil @@ -98,7 +101,6 @@ func (pg *Database) getAllApplicationsByStatus( id uint64 contractAddress Address templateHash Hash - snapshotUri string lastProcessedBlock uint64 epochLength uint64 status ApplicationStatus @@ -110,7 +112,6 @@ func (pg *Database) getAllApplicationsByStatus( id, contract_address, template_hash, - snapshot_uri, last_processed_block, epoch_length, status diff --git a/internal/repository/evmreader_test.go b/internal/repository/evmreader_test.go index be106c9cc..ad9e86f74 100644 --- a/internal/repository/evmreader_test.go +++ b/internal/repository/evmreader_test.go @@ -10,21 +10,23 @@ import ( func (s *RepositorySuite) TestInsertInputsAndUpdateLastProcessedBlock() { input0 := Input{ - Id: 5, + Id: 6, Index: 5, CompletionStatus: InputStatusNone, RawData: common.Hex2Bytes("deadbeef"), BlockNumber: 5, AppAddress: common.HexToAddress("deadbeef"), + EpochId: 1, } input1 := Input{ - Id: 6, + Id: 7, Index: 6, CompletionStatus: InputStatusNone, RawData: common.Hex2Bytes("deadbeef"), BlockNumber: 6, AppAddress: common.HexToAddress("deadbeef"), + EpochId: 1, } var inputs []Input @@ -74,6 +76,7 @@ func (s *RepositorySuite) TestInsertInputsAndUpdateLastProcessedBlockInputAlread RawData: common.Hex2Bytes("deadbeef"), BlockNumber: 5, AppAddress: common.HexToAddress("deadbeef"), + EpochId: 1, } var inputs []Input @@ -96,6 +99,7 @@ func (s *RepositorySuite) TestInsertInputsAndUpdateLastProcessedBlockDuplicateIn RawData: common.Hex2Bytes("deadbeef"), BlockNumber: 7, AppAddress: common.HexToAddress("deadbeef"), + EpochId: 1, } input1 := Input{ @@ -105,6 +109,7 @@ func (s *RepositorySuite) TestInsertInputsAndUpdateLastProcessedBlockDuplicateIn RawData: common.Hex2Bytes("deadbeef"), BlockNumber: 7, AppAddress: common.HexToAddress("deadbeef"), + EpochId: 1, } var inputs []Input @@ -125,7 +130,6 @@ func (s *RepositorySuite) TestGetAllRunningApplications() { Id: 1, ContractAddress: common.HexToAddress("deadbeef"), TemplateHash: common.HexToHash("deadbeef"), - SnapshotURI: "this/is/a/test", LastProcessedBlock: 1, EpochLength: 10, Status: ApplicationStatusRunning, diff --git a/internal/repository/migrations/000001_create_application_input_claim_output_report_nodeconfig.down.sql b/internal/repository/migrations/000001_create_application_input_claim_output_report_nodeconfig.down.sql index 0fba61bf5..5a92600fc 100644 --- a/internal/repository/migrations/000001_create_application_input_claim_output_report_nodeconfig.down.sql +++ b/internal/repository/migrations/000001_create_application_input_claim_output_report_nodeconfig.down.sql @@ -2,13 +2,16 @@ -- SPDX-License-Identifier: Apache-2.0 (see LICENSE) DROP TABLE IF EXISTS "node_config"; +DROP TABLE IF EXISTS "snapshot"; DROP TABLE IF EXISTS "report"; DROP TABLE IF EXISTS "output"; DROP TABLE IF EXISTS "claim"; DROP TABLE IF EXISTS "input"; +DROP TABLE IF EXISTS "epoch"; DROP TABLE IF EXISTS "application"; DROP TYPE IF EXISTS "InputCompletionStatus"; DROP TYPE IF EXISTS "ClaimStatus"; DROP TYPE IF EXISTS "ApplicationStatus"; DROP TYPE IF EXISTS "DefaultBlock"; +DROP TYPE IF EXISTS "EpochStatus"; diff --git a/internal/repository/migrations/000001_create_application_input_claim_output_report_nodeconfig.up.sql b/internal/repository/migrations/000001_create_application_input_claim_output_report_nodeconfig.up.sql index 31a0fd635..018502c1b 100644 --- a/internal/repository/migrations/000001_create_application_input_claim_output_report_nodeconfig.up.sql +++ b/internal/repository/migrations/000001_create_application_input_claim_output_report_nodeconfig.up.sql @@ -9,6 +9,8 @@ CREATE TYPE "ClaimStatus" AS ENUM ('PENDING', 'SUBMITTED', 'FINALIZED'); CREATE TYPE "DefaultBlock" AS ENUM ('FINALIZED', 'LATEST', 'PENDING', 'SAFE'); +CREATE TYPE "EpochStatus" AS ENUM ('OPEN', 'CLOSED', 'PROCESSED_ALL_INPUTS', 'CLAIM_COMPUTED', 'CLAIM_SUBMITTED', 'CLAIM_ACCEPTED', 'CLAIM_REJECTED'); + CREATE FUNCTION public.f_maxuint64() RETURNS NUMERIC(20,0) LANGUAGE sql IMMUTABLE PARALLEL SAFE AS @@ -19,7 +21,6 @@ CREATE TABLE "application" "id" SERIAL, "contract_address" BYTEA NOT NULL, "template_hash" BYTEA NOT NULL, - "snapshot_uri" VARCHAR(4096) NOT NULL, "last_processed_block" NUMERIC(20,0) NOT NULL CHECK ("last_processed_block" >= 0 AND "last_processed_block" <= f_maxuint64()), "status" "ApplicationStatus" NOT NULL, "epoch_length" INT NOT NULL, @@ -27,6 +28,21 @@ CREATE TABLE "application" UNIQUE("contract_address") ); +CREATE TABLE "epoch" +( + "id" BIGSERIAL, + "application_address" BYTEA NOT NULL, + "index" BIGINT NOT NULL, + "first_block" NUMERIC(20,0) NOT NULL CHECK ("first_block" >= 0 AND "first_block" <= f_maxuint64()), + "last_block" NUMERIC(20,0) NOT NULL CHECK ("last_block" >= 0 AND "last_block" <= f_maxuint64()), + "claim_hash" BYTEA, + "transaction_hash" BYTEA, + "status" "EpochStatus" NOT NULL, + CONSTRAINT "epoch_pkey" PRIMARY KEY ("id"), + CONSTRAINT "epoch_application_address_fkey" FOREIGN KEY ("application_address") REFERENCES "application"("contract_address"), + UNIQUE ("index","application_address") +); + CREATE TABLE "input" ( "id" BIGSERIAL, @@ -37,8 +53,10 @@ CREATE TABLE "input" "machine_hash" BYTEA, "outputs_hash" BYTEA, "application_address" BYTEA NOT NULL, + "epoch_id" BIGINT NOT NULL, CONSTRAINT "input_pkey" PRIMARY KEY ("id"), CONSTRAINT "input_application_address_fkey" FOREIGN KEY ("application_address") REFERENCES "application"("contract_address"), + CONSTRAINT "input_epoch_fkey" FOREIGN KEY ("epoch_id") REFERENCES "epoch"("id"), UNIQUE("index", "application_address") ); @@ -83,6 +101,18 @@ CREATE TABLE "report" CREATE UNIQUE INDEX "report_idx" ON "report"("index"); +CREATE TABLE "snapshot" +( + "id" BIGSERIAL, + "input_id" BIGINT NOT NULL, + "application_address" BYTEA NOT NULL, + "uri" VARCHAR(4096) NOT NULL, + CONSTRAINT "snapshot_pkey" PRIMARY KEY ("id"), + CONSTRAINT "snapshot_input_id_fkey" FOREIGN KEY ("input_id") REFERENCES "input"("id"), + CONSTRAINT "snapshot_application_address_fkey" FOREIGN KEY ("application_address") REFERENCES "application"("contract_address"), + UNIQUE("input_id") +); + CREATE TABLE "node_config" ( "default_block" "DefaultBlock" NOT NULL, diff --git a/internal/repository/migrations/000002_create_postgraphile_view.up.sql b/internal/repository/migrations/000002_create_postgraphile_view.up.sql index e1062596b..6e59bbebc 100644 --- a/internal/repository/migrations/000002_create_postgraphile_view.up.sql +++ b/internal/repository/migrations/000002_create_postgraphile_view.up.sql @@ -8,24 +8,38 @@ CREATE OR REPLACE VIEW graphql."applications" AS SELECT "contract_address", "template_hash", - "snapshot_uri", "last_processed_block", "epoch_length", "status" FROM "application"; -CREATE OR REPLACE VIEW graphql."inputs" AS +CREATE OR REPLACE VIEW graphql."epochs" AS SELECT "index", - "status", - "block_number", - "raw_data", - "machine_hash", - "outputs_hash", - "application_address" + "application_address", + "first_block", + "last_block", + "transaction_hash", + "claim_hash", + "status" + FROM + "epoch"; + +CREATE OR REPLACE VIEW graphql."inputs" AS + SELECT + i."index", + i."status", + i."block_number", + i."raw_data", + i."machine_hash", + i."outputs_hash", + i."application_address", + e."index" as "epoch_index" FROM - "input"; + "input" i + INNER JOIN + "epoch" e on i."epoch_id" = e."id"; CREATE OR REPLACE VIEW graphql."outputs" AS SELECT @@ -65,7 +79,7 @@ CREATE OR REPLACE VIEW graphql."claims" AS "output" o ON i."id"=o."input_id"; COMMENT ON VIEW graphql."inputs" is - E'@foreignKey (application_address) references applications(contract_address)|@fieldName applicationByApplicationAddress'; + E'@foreignKey (application_address) references applications(contract_address)|@fieldName applicationByApplicationAddress\n@foreignKey (epoch_index) references epochs(index)|@fieldName epochByEpochIndex'; COMMENT ON VIEW graphql."outputs" is E'@foreignKey (input_index) references inputs(index)|@fieldName inputByInputIndex'; @@ -74,4 +88,8 @@ COMMENT ON VIEW graphql."reports" is E'@foreignKey (input_index) references inputs(index)|@fieldName inputByInputIndex'; COMMENT ON VIEW graphql."claims" is - E'@foreignKey (output_index) references outputs(index)|@fieldName outputByOutputIndex\n@foreignKey (application_address) references applications(contract_address)|@fieldName applicationByApplicationAddress'; \ No newline at end of file + E'@foreignKey (output_index) references outputs(index)|@fieldName outputByOutputIndex\n@foreignKey (application_address) references applications(contract_address)|@fieldName applicationByApplicationAddress'; + +COMMENT ON VIEW graphql."epochs" is + E'@foreignKey (application_address) references applications(contract_address)|@fieldName applicationByApplicationAddress'; + \ No newline at end of file diff --git a/internal/repository/validator.go b/internal/repository/validator.go index cc4b5a558..f65ccaa7f 100644 --- a/internal/repository/validator.go +++ b/internal/repository/validator.go @@ -5,6 +5,7 @@ package repository import ( "context" + "errors" "fmt" "time" @@ -130,60 +131,89 @@ func (pg *Database) getAllOutputsFromProcessedInputs( return nil, nil } -func (pg *Database) FinishEpoch( +func (pg *Database) SetEpochClaimAndInsertProofsTransaction( ctx context.Context, - claim *Claim, + epoch Epoch, outputs []Output, ) error { query1 := ` - INSERT INTO claim - (index, - output_merkle_root_hash, - status, - application_address) - VALUES - (@index, - @outputMerkleRootHash, - @status, - @appAddress)` - - query2 := ` - UPDATE output + UPDATE epoch SET - output_hashes_siblings=@outputHashesSiblings + claim_hash=@claimHash, + status=@status WHERE - index=@index` + id=@id` args := pgx.NamedArgs{ - "index": claim.Index, - "status": ClaimStatusPending, - "outputMerkleRootHash": claim.OutputMerkleRootHash, - "appAddress": claim.AppAddress, + "id": epoch.Id, + "claimHash": epoch.ClaimHash, + "status": EpochStatusClaimComputed, } tx, err := pg.db.Begin(ctx) if err != nil { - return fmt.Errorf("unable to finish epoch: %w\n", err) + return fmt.Errorf("unable to set claim. epoch: '%d' ,error: %w\n", epoch.Index, err) } - _, err = tx.Exec(ctx, query1, args) + tag, err := tx.Exec(ctx, query1, args) if err != nil { - return fmt.Errorf("unable to finish epoch: %w\n", err) + return errors.Join( + fmt.Errorf("unable to set claim. epoch '%d' ,error: %w\n", epoch.Index, err), + tx.Rollback(ctx), + ) + } + if tag.RowsAffected() != 1 { + return errors.Join( + fmt.Errorf( + "unable to set claim. epoch '%d' , error: no rows affected ", + epoch.Index, + ), + tx.Rollback(ctx), + ) } + query2 := ` + UPDATE output + SET + output_hashes_siblings=@outputHashesSiblings + WHERE + id=@id` + for _, output := range outputs { outputArgs := pgx.NamedArgs{ "outputHashesSiblings": output.OutputHashesSiblings, - "index": output.Index, + "id": output.Id, } - _, err = tx.Exec(ctx, query2, outputArgs) + tag, err := tx.Exec(ctx, query2, outputArgs) if err != nil { - return fmt.Errorf("unable to finish epoch: %w\n", err) + return errors.Join( + fmt.Errorf( + `unable to set claim. epoch '%d' + , error: unable to insert proof for output '%d' %w\n`, + epoch.Index, output.Index, err), + tx.Rollback(ctx), + ) + } + if tag.RowsAffected() != 1 { + return errors.Join( + fmt.Errorf( + `unable to set claim. epoch '%d' + , error: no rows affected on output '%d' update`, + epoch.Index, + output.Index, + ), + tx.Rollback(ctx), + ) } } err = tx.Commit(ctx) if err != nil { - return fmt.Errorf("unable to finish epoch: %w\n", err) + return errors.Join( + fmt.Errorf("unable to set claim. epoch '%d', error: %w\n", + epoch.Index, + err), + tx.Rollback(ctx), + ) } return nil diff --git a/internal/repository/validator_test.go b/internal/repository/validator_test.go index fc0061f09..dc59942dd 100644 --- a/internal/repository/validator_test.go +++ b/internal/repository/validator_test.go @@ -51,7 +51,7 @@ func (s *RepositorySuite) TestGetAllOutputsFromProcessedInputsTimeout() { s.Require().ErrorContains(err, "timeout") } -func (s *RepositorySuite) TestFinishEpochTransaction() { +func (s *RepositorySuite) TestSetEpochClaimAndInsertProofsTransaction() { var siblings []Hash siblings = append(siblings, common.HexToHash("deadbeef")) @@ -63,51 +63,66 @@ func (s *RepositorySuite) TestFinishEpochTransaction() { OutputHashesSiblings: siblings, } - claim := Claim{ - Id: 4, - Index: 2, - Status: ClaimStatusPending, - OutputMerkleRootHash: common.HexToHash("deadbeef"), - AppAddress: common.HexToAddress("deadbeef"), - } + hash := common.HexToHash("deadbeef") + + expectedEpoch, err := s.database.GetEpoch(s.ctx, 0, common.HexToAddress("deadbeef")) + s.Require().Nil(err) + + expectedEpoch.ClaimHash = &hash + expectedEpoch.Status = EpochStatusClaimComputed + + epoch, err := s.database.GetEpoch(s.ctx, 0, common.HexToAddress("deadbeef")) + s.Require().Nil(err) + + epoch.ClaimHash = &hash + epoch.Status = EpochStatusClaimComputed var outputs []Output outputs = append(outputs, output) - err := s.database.FinishEpoch(s.ctx, &claim, outputs) + err = s.database.SetEpochClaimAndInsertProofsTransaction(s.ctx, *epoch, outputs) s.Require().Nil(err) - response0, err := s.database.GetClaim(s.ctx, common.HexToAddress("deadbeef"), 2) + actualEpoch, err := s.database.GetEpoch(s.ctx, epoch.Index, common.HexToAddress("deadbeef")) s.Require().Nil(err) - s.Require().Equal(claim, *response0) + s.Require().Equal(expectedEpoch, actualEpoch) - response1, err := s.database.GetOutput(s.ctx, 1, common.HexToAddress("deadbeef")) + actualOutput, err := s.database.GetOutput(s.ctx, output.Index, common.HexToAddress("deadbeef")) s.Require().Nil(err) - s.Require().Equal(output, *response1) + s.Require().Equal(output, *actualOutput) } -func (s *RepositorySuite) TestFinishEpochTransactionRollback() { +func (s *RepositorySuite) TestSetEpochClaimAndInsertProofsTransactionRollback() { var siblings []Hash siblings = append(siblings, common.HexToHash("deadbeef")) output := Output{ - Id: 2, - Index: 2, + Id: 5, + Index: 4, InputId: 1, RawData: common.Hex2Bytes("deadbeef"), OutputHashesSiblings: siblings, } - claim := Claim{ - Index: 2, - Status: ClaimStatusPending, - OutputMerkleRootHash: common.HexToHash("deadbeef"), - AppAddress: common.HexToAddress("deadbeef"), - } + hash := common.HexToHash("deadbeef") + + epoch, err := s.database.GetEpoch(s.ctx, 1, common.HexToAddress("deadbeef")) + s.Require().Nil(err) + + epoch.ClaimHash = &hash + epoch.Status = EpochStatusClaimComputed + + expectedEpoch, err := s.database.GetEpoch(s.ctx, epoch.Index, common.HexToAddress("deadbeef")) + s.Require().Nil(err) var outputs []Output outputs = append(outputs, output) - err := s.database.FinishEpoch(s.ctx, &claim, outputs) - s.Require().ErrorContains(err, "unable to finish epoch") + err = s.database.SetEpochClaimAndInsertProofsTransaction(s.ctx, *epoch, outputs) + s.Require().ErrorContains(err, "unable to set claim") + + actualEpoch, err := s.database.GetEpoch(s.ctx, expectedEpoch.Index, expectedEpoch.AppAddress) + s.Require().Nil(err) + s.Require().NotNil(actualEpoch) + s.Require().Equal(expectedEpoch, actualEpoch) } From 13fd1453738ea430d01ee8c7fcf12eeeb138df3e Mon Sep 17 00:00:00 2001 From: Francisco Moura Date: Fri, 2 Aug 2024 01:39:41 -0300 Subject: [PATCH 2/4] feat(db): Remove Claim --- internal/node/model/models.go | 16 ---- internal/repository/base.go | 95 ------------------- internal/repository/base_test.go | 11 --- ...ut_claim_output_report_nodeconfig.down.sql | 3 +- ...nput_claim_output_report_nodeconfig.up.sql | 15 --- .../000002_create_postgraphile_view.up.sql | 18 ---- 6 files changed, 1 insertion(+), 157 deletions(-) diff --git a/internal/node/model/models.go b/internal/node/model/models.go index 407cc239a..c5af3e280 100644 --- a/internal/node/model/models.go +++ b/internal/node/model/models.go @@ -13,7 +13,6 @@ type ( Address = common.Address Bytes = hexutil.Bytes InputCompletionStatus string - ClaimStatus string ApplicationStatus string DefaultBlock string EpochStatus string @@ -30,12 +29,6 @@ const ( InputStatusPayloadLengthLimitExceeded InputCompletionStatus = "PAYLOAD_LENGTH_LIMIT_EXCEEDED" ) -const ( - ClaimStatusPending ClaimStatus = "PENDING" - ClaimStatusSubmitted ClaimStatus = "SUBMITTED" - ClaimStatusFinalized ClaimStatus = "FINALIZED" -) - const ( ApplicationStatusRunning ApplicationStatus = "RUNNING" ApplicationStatusNotRunning ApplicationStatus = "NOT RUNNING" @@ -114,15 +107,6 @@ type Report struct { InputId uint64 } -type Claim struct { - Id uint64 - Index uint64 - Status ClaimStatus - OutputMerkleRootHash Hash - TransactionHash *Hash - AppAddress Address -} - type Snapshot struct { Id uint64 URI string diff --git a/internal/repository/base.go b/internal/repository/base.go index 3ced8684f..56cec988b 100644 --- a/internal/repository/base.go +++ b/internal/repository/base.go @@ -265,40 +265,6 @@ func (pg *Database) InsertReport( return nil } -func (pg *Database) InsertClaim( - ctx context.Context, - claim *Claim, -) error { - query := ` - INSERT INTO claim - (index, - output_merkle_root_hash, - transaction_hash, - status, - application_address) - VALUES - (@index, - @outputMerkleRootHash, - @transactionHash, - @status, - @applicationAddress)` - - args := pgx.NamedArgs{ - "index": claim.Index, - "outputMerkleRootHash": claim.OutputMerkleRootHash, - "transactionHash": claim.TransactionHash, - "status": claim.Status, - "applicationAddress": claim.AppAddress, - } - - _, err := pg.db.Exec(ctx, query, args) - if err != nil { - return fmt.Errorf("%w: %w", ErrInsertRow, err) - } - - return nil -} - func (pg *Database) InsertSnapshot( ctx context.Context, snapshot *Snapshot, @@ -688,67 +654,6 @@ func (pg *Database) GetReport( return &report, nil } -func (pg *Database) GetClaim( - ctx context.Context, - appAddressKey Address, - indexKey uint64, -) (*Claim, error) { - var ( - id uint64 - index uint64 - outputMerkleRootHash Hash - transactionHash *Hash - status ClaimStatus - address Address - ) - - query := ` - SELECT - id, - index, - output_merkle_root_hash, - transaction_hash, - status, - application_address - FROM - claim - WHERE - application_address=@appAddress and index=@index` - - args := pgx.NamedArgs{ - "appAddress": appAddressKey, - "index": indexKey, - } - - err := pg.db.QueryRow(ctx, query, args).Scan( - &id, - &index, - &outputMerkleRootHash, - &transactionHash, - &status, - &address, - ) - if err != nil { - if errors.Is(err, pgx.ErrNoRows) { - slog.Info("GetClaim returned no rows", "service", "repository") - return nil, nil - } - return nil, fmt.Errorf("GetClaim QueryRow failed: %w\n", err) - } - - claim := Claim{ - Id: id, - Index: index, - OutputMerkleRootHash: outputMerkleRootHash, - TransactionHash: transactionHash, - Status: status, - AppAddress: address, - } - - return &claim, nil -} - - func (pg *Database) GetSnapshot( ctx context.Context, inputIndexKey uint64, diff --git a/internal/repository/base_test.go b/internal/repository/base_test.go index 4c2d80e05..915e4ade1 100644 --- a/internal/repository/base_test.go +++ b/internal/repository/base_test.go @@ -217,17 +217,6 @@ func (s *RepositorySuite) SetupDatabase() { err = s.database.InsertReport(s.ctx, &report) s.Require().Nil(err) - claim := Claim{ - Status: ClaimStatusPending, - Index: 1, - OutputMerkleRootHash: genericHash, - TransactionHash: &genericHash, - AppAddress: common.HexToAddress("deadbeef"), - } - - err = s.database.InsertClaim(s.ctx, &claim) - s.Require().Nil(err) - snapshot := Snapshot{ InputId: 1, AppAddress: app.ContractAddress, diff --git a/internal/repository/migrations/000001_create_application_input_claim_output_report_nodeconfig.down.sql b/internal/repository/migrations/000001_create_application_input_claim_output_report_nodeconfig.down.sql index 5a92600fc..2c4628a58 100644 --- a/internal/repository/migrations/000001_create_application_input_claim_output_report_nodeconfig.down.sql +++ b/internal/repository/migrations/000001_create_application_input_claim_output_report_nodeconfig.down.sql @@ -5,13 +5,12 @@ DROP TABLE IF EXISTS "node_config"; DROP TABLE IF EXISTS "snapshot"; DROP TABLE IF EXISTS "report"; DROP TABLE IF EXISTS "output"; -DROP TABLE IF EXISTS "claim"; DROP TABLE IF EXISTS "input"; DROP TABLE IF EXISTS "epoch"; DROP TABLE IF EXISTS "application"; + DROP TYPE IF EXISTS "InputCompletionStatus"; -DROP TYPE IF EXISTS "ClaimStatus"; DROP TYPE IF EXISTS "ApplicationStatus"; DROP TYPE IF EXISTS "DefaultBlock"; DROP TYPE IF EXISTS "EpochStatus"; diff --git a/internal/repository/migrations/000001_create_application_input_claim_output_report_nodeconfig.up.sql b/internal/repository/migrations/000001_create_application_input_claim_output_report_nodeconfig.up.sql index 018502c1b..6cfb5d8f5 100644 --- a/internal/repository/migrations/000001_create_application_input_claim_output_report_nodeconfig.up.sql +++ b/internal/repository/migrations/000001_create_application_input_claim_output_report_nodeconfig.up.sql @@ -5,8 +5,6 @@ CREATE TYPE "ApplicationStatus" AS ENUM ('RUNNING', 'NOT RUNNING'); CREATE TYPE "InputCompletionStatus" AS ENUM ('NONE', 'ACCEPTED', 'REJECTED', 'EXCEPTION', 'MACHINE_HALTED', 'CYCLE_LIMIT_EXCEEDED', 'TIME_LIMIT_EXCEEDED', 'PAYLOAD_LENGTH_LIMIT_EXCEEDED'); -CREATE TYPE "ClaimStatus" AS ENUM ('PENDING', 'SUBMITTED', 'FINALIZED'); - CREATE TYPE "DefaultBlock" AS ENUM ('FINALIZED', 'LATEST', 'PENDING', 'SAFE'); CREATE TYPE "EpochStatus" AS ENUM ('OPEN', 'CLOSED', 'PROCESSED_ALL_INPUTS', 'CLAIM_COMPUTED', 'CLAIM_SUBMITTED', 'CLAIM_ACCEPTED', 'CLAIM_REJECTED'); @@ -62,19 +60,6 @@ CREATE TABLE "input" CREATE INDEX "input_idx" ON "input"("block_number"); -CREATE TABLE "claim" -( - "id" BIGSERIAL, - "index" NUMERIC(20,0) NOT NULL CHECK ("index" >= 0 AND "index" <= f_maxuint64()), - "output_merkle_root_hash" BYTEA NOT NULL, - "transaction_hash" BYTEA, - "status" "ClaimStatus" NOT NULL, - "application_address" BYTEA NOT NULL, - CONSTRAINT "claim_pkey" PRIMARY KEY ("id"), - CONSTRAINT "claim_application_address_fkey" FOREIGN KEY ("application_address") REFERENCES "application"("contract_address"), - UNIQUE("index", "application_address") -); - CREATE TABLE "output" ( "id" BIGSERIAL, diff --git a/internal/repository/migrations/000002_create_postgraphile_view.up.sql b/internal/repository/migrations/000002_create_postgraphile_view.up.sql index 6e59bbebc..0f6a9a2e2 100644 --- a/internal/repository/migrations/000002_create_postgraphile_view.up.sql +++ b/internal/repository/migrations/000002_create_postgraphile_view.up.sql @@ -62,21 +62,6 @@ CREATE OR REPLACE VIEW graphql."reports" AS INNER JOIN "input" i on r."input_id"=i."id"; -CREATE OR REPLACE VIEW graphql."claims" AS - SELECT - c."index", - c."output_merkle_root_hash", - c."status", - c."application_address", - o."index" as "output_index" - FROM - "claim" c - INNER JOIN - "application" a ON c."application_address"=a."contract_address" - INNER JOIN - "input" i ON a."contract_address"=i."application_address" - INNER JOIN - "output" o ON i."id"=o."input_id"; COMMENT ON VIEW graphql."inputs" is E'@foreignKey (application_address) references applications(contract_address)|@fieldName applicationByApplicationAddress\n@foreignKey (epoch_index) references epochs(index)|@fieldName epochByEpochIndex'; @@ -87,9 +72,6 @@ COMMENT ON VIEW graphql."outputs" is COMMENT ON VIEW graphql."reports" is E'@foreignKey (input_index) references inputs(index)|@fieldName inputByInputIndex'; -COMMENT ON VIEW graphql."claims" is - E'@foreignKey (output_index) references outputs(index)|@fieldName outputByOutputIndex\n@foreignKey (application_address) references applications(contract_address)|@fieldName applicationByApplicationAddress'; - COMMENT ON VIEW graphql."epochs" is E'@foreignKey (application_address) references applications(contract_address)|@fieldName applicationByApplicationAddress'; \ No newline at end of file From 668633178b47bada6063214aeaf917de58b9ccd9 Mon Sep 17 00:00:00 2001 From: Francisco Moura Date: Fri, 2 Aug 2024 01:54:34 -0300 Subject: [PATCH 3/4] feat(db): Move epochLength from Application to NodeConfig --- cmd/cartesi-rollups-cli/root/app/add/add.go | 11 ----------- docs/cli/cartesi-rollups-cli_app_add.md | 1 - internal/node/model/models.go | 2 +- internal/repository/base.go | 14 +++++--------- internal/repository/base_test.go | 5 +---- internal/repository/evmreader.go | 8 ++------ internal/repository/evmreader_test.go | 1 - ...ion_input_claim_output_report_nodeconfig.up.sql | 6 ++++-- .../000002_create_postgraphile_view.up.sql | 1 - 9 files changed, 13 insertions(+), 36 deletions(-) diff --git a/cmd/cartesi-rollups-cli/root/app/add/add.go b/cmd/cartesi-rollups-cli/root/app/add/add.go index 3deff428b..53f2303d0 100644 --- a/cmd/cartesi-rollups-cli/root/app/add/add.go +++ b/cmd/cartesi-rollups-cli/root/app/add/add.go @@ -34,7 +34,6 @@ var ( templateHash string inputBoxDeploymentBlockNumber uint64 snapshotUri string - epochLength uint64 status string ) @@ -72,14 +71,6 @@ func init() { "Application snapshot URI", ) - Cmd.Flags().Uint64VarP( - &epochLength, - "epoch-length", - "e", - 1, - "Application epoch length in blocks", - ) - Cmd.Flags().StringVarP( &status, "status", @@ -113,8 +104,6 @@ func run(cmd *cobra.Command, args []string) { ContractAddress: common.HexToAddress(applicationAddress), TemplateHash: common.HexToHash(templateHash), LastProcessedBlock: inputBoxDeploymentBlockNumber, - SnapshotURI: snapshotUri, - EpochLength: epochLength, Status: applicationStatus, } diff --git a/docs/cli/cartesi-rollups-cli_app_add.md b/docs/cli/cartesi-rollups-cli_app_add.md index 669666d3e..8c4552420 100644 --- a/docs/cli/cartesi-rollups-cli_app_add.md +++ b/docs/cli/cartesi-rollups-cli_app_add.md @@ -17,7 +17,6 @@ cartesi-rollups-cli app add -a 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF -n 10 ``` -a, --address string Application contract address - -e, --epoch-length uint Application epoch length in blocks (default 1) -h, --help help for add -n, --inputbox-block-number uint InputBox deployment block number -u, --snapshot-uri string Application snapshot URI diff --git a/internal/node/model/models.go b/internal/node/model/models.go index c5af3e280..0a7da5468 100644 --- a/internal/node/model/models.go +++ b/internal/node/model/models.go @@ -57,6 +57,7 @@ type NodePersistentConfig struct { InputBoxAddress Address ChainId uint64 IConsensusAddress Address + EpochLength uint64 } type Application struct { @@ -64,7 +65,6 @@ type Application struct { ContractAddress Address TemplateHash Hash LastProcessedBlock uint64 - EpochLength uint64 Status ApplicationStatus } diff --git a/internal/repository/base.go b/internal/repository/base.go index 56cec988b..8372dc50e 100644 --- a/internal/repository/base.go +++ b/internal/repository/base.go @@ -59,13 +59,15 @@ func (pg *Database) InsertNodeConfig( input_box_deployment_block, input_box_address, chain_id, - iconsensus_address) + iconsensus_address, + epoch_length) SELECT @defaultBlock, @deploymentBlock, @inputBoxAddress, @chainId, - @iConsensusAddress + @iConsensusAddress, + @epochLength WHERE NOT EXISTS (SELECT * FROM node_config)` args := pgx.NamedArgs{ @@ -74,6 +76,7 @@ func (pg *Database) InsertNodeConfig( "inputBoxAddress": config.InputBoxAddress, "chainId": config.ChainId, "iConsensusAddress": config.IConsensusAddress, + "epochLength": config.EpochLength, } _, err := pg.db.Exec(ctx, query, args) @@ -93,20 +96,17 @@ func (pg *Database) InsertApplication( (contract_address, template_hash, last_processed_block, - epoch_length, status) VALUES (@contractAddress, @templateHash, @lastProcessedBlock, - @epochLength, @status)` args := pgx.NamedArgs{ "contractAddress": app.ContractAddress, "templateHash": app.TemplateHash, "lastProcessedBlock": app.LastProcessedBlock, - "epochLength": app.EpochLength, "status": app.Status, } @@ -346,7 +346,6 @@ func (pg *Database) GetApplication( contractAddress Address templateHash Hash lastProcessedBlock uint64 - epochLength uint64 status ApplicationStatus ) @@ -356,7 +355,6 @@ func (pg *Database) GetApplication( contract_address, template_hash, last_processed_block, - epoch_length, status FROM application @@ -372,7 +370,6 @@ func (pg *Database) GetApplication( &contractAddress, &templateHash, &lastProcessedBlock, - &epochLength, &status, ) if err != nil { @@ -388,7 +385,6 @@ func (pg *Database) GetApplication( ContractAddress: contractAddress, TemplateHash: templateHash, LastProcessedBlock: lastProcessedBlock, - EpochLength: epochLength, Status: status, } diff --git a/internal/repository/base_test.go b/internal/repository/base_test.go index 915e4ade1..b92976577 100644 --- a/internal/repository/base_test.go +++ b/internal/repository/base_test.go @@ -63,6 +63,7 @@ func (s *RepositorySuite) SetupDatabase() { InputBoxAddress: common.HexToAddress("deadbeef"), ChainId: 1, IConsensusAddress: common.HexToAddress("deadbeef"), + EpochLength: 10, } err := s.database.InsertNodeConfig(s.ctx, &config) @@ -72,7 +73,6 @@ func (s *RepositorySuite) SetupDatabase() { ContractAddress: common.HexToAddress("deadbeef"), TemplateHash: common.HexToHash("deadbeef"), LastProcessedBlock: 1, - EpochLength: 10, Status: ApplicationStatusRunning, } @@ -80,7 +80,6 @@ func (s *RepositorySuite) SetupDatabase() { ContractAddress: common.HexToAddress("feadbeef"), TemplateHash: common.HexToHash("deadbeef"), LastProcessedBlock: 1, - EpochLength: 10, Status: ApplicationStatusNotRunning, } @@ -234,7 +233,6 @@ func (s *RepositorySuite) TestApplicationExists() { ContractAddress: common.HexToAddress("deadbeef"), TemplateHash: common.HexToHash("deadbeef"), LastProcessedBlock: 1, - EpochLength: 10, Status: ApplicationStatusRunning, } @@ -255,7 +253,6 @@ func (s *RepositorySuite) TestApplicationFailsDuplicateRow() { ContractAddress: common.HexToAddress("deadbeef"), TemplateHash: common.HexToHash("deadbeef"), LastProcessedBlock: 1, - EpochLength: 10, Status: ApplicationStatusRunning, } diff --git a/internal/repository/evmreader.go b/internal/repository/evmreader.go index 388f104e4..d494beed1 100644 --- a/internal/repository/evmreader.go +++ b/internal/repository/evmreader.go @@ -102,7 +102,6 @@ func (pg *Database) getAllApplicationsByStatus( contractAddress Address templateHash Hash lastProcessedBlock uint64 - epochLength uint64 status ApplicationStatus results []Application ) @@ -113,7 +112,6 @@ func (pg *Database) getAllApplicationsByStatus( contract_address, template_hash, last_processed_block, - epoch_length, status FROM application @@ -131,16 +129,14 @@ func (pg *Database) getAllApplicationsByStatus( } _, err = pgx.ForEachRow(rows, - []any{&id, &contractAddress, &templateHash, &snapshotUri, - &lastProcessedBlock, &epochLength, &status}, + []any{&id, &contractAddress, &templateHash, + &lastProcessedBlock, &status}, func() error { app := Application{ Id: id, ContractAddress: contractAddress, TemplateHash: templateHash, - SnapshotURI: snapshotUri, LastProcessedBlock: lastProcessedBlock, - EpochLength: epochLength, Status: status, } results = append(results, app) diff --git a/internal/repository/evmreader_test.go b/internal/repository/evmreader_test.go index ad9e86f74..124bd5149 100644 --- a/internal/repository/evmreader_test.go +++ b/internal/repository/evmreader_test.go @@ -131,7 +131,6 @@ func (s *RepositorySuite) TestGetAllRunningApplications() { ContractAddress: common.HexToAddress("deadbeef"), TemplateHash: common.HexToHash("deadbeef"), LastProcessedBlock: 1, - EpochLength: 10, Status: ApplicationStatusRunning, } diff --git a/internal/repository/migrations/000001_create_application_input_claim_output_report_nodeconfig.up.sql b/internal/repository/migrations/000001_create_application_input_claim_output_report_nodeconfig.up.sql index 6cfb5d8f5..51de4402d 100644 --- a/internal/repository/migrations/000001_create_application_input_claim_output_report_nodeconfig.up.sql +++ b/internal/repository/migrations/000001_create_application_input_claim_output_report_nodeconfig.up.sql @@ -21,7 +21,6 @@ CREATE TABLE "application" "template_hash" BYTEA NOT NULL, "last_processed_block" NUMERIC(20,0) NOT NULL CHECK ("last_processed_block" >= 0 AND "last_processed_block" <= f_maxuint64()), "status" "ApplicationStatus" NOT NULL, - "epoch_length" INT NOT NULL, CONSTRAINT "application_pkey" PRIMARY KEY ("id"), UNIQUE("contract_address") ); @@ -104,5 +103,8 @@ CREATE TABLE "node_config" "input_box_deployment_block" INT NOT NULL, "input_box_address" BYTEA NOT NULL, "chain_id" INT NOT NULL, - "iconsensus_address" BYTEA NOT NULL + "iconsensus_address" BYTEA NOT NULL, + "epoch_length" INT NOT NULL ); + + diff --git a/internal/repository/migrations/000002_create_postgraphile_view.up.sql b/internal/repository/migrations/000002_create_postgraphile_view.up.sql index 0f6a9a2e2..5cd3bcdf6 100644 --- a/internal/repository/migrations/000002_create_postgraphile_view.up.sql +++ b/internal/repository/migrations/000002_create_postgraphile_view.up.sql @@ -9,7 +9,6 @@ CREATE OR REPLACE VIEW graphql."applications" AS "contract_address", "template_hash", "last_processed_block", - "epoch_length", "status" FROM "application"; From 94d13b8e653d1364214ab44d33ffa77aa6662baa Mon Sep 17 00:00:00 2001 From: Francisco Moura Date: Tue, 6 Aug 2024 17:22:52 -0300 Subject: [PATCH 4/4] 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,