Skip to content

Commit

Permalink
feat(evm-reader): Read output execution statuses
Browse files Browse the repository at this point in the history
  • Loading branch information
fmoura committed Sep 3, 2024
1 parent 25d491b commit b6d2f44
Show file tree
Hide file tree
Showing 5 changed files with 169 additions and 11 deletions.
55 changes: 55 additions & 0 deletions internal/evmreader/application_adapter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// (c) Cartesi and individual authors (see AUTHORS)
// SPDX-License-Identifier: Apache-2.0 (see LICENSE)

package evmreader

import (
appcontract "github.com/cartesi/rollups-node/pkg/contracts/application"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
)

// IConsensus Wrapper
type ApplicationContractAdapter struct {
application *appcontract.Application
}

func NewApplicationContractAdapter(
appAddress common.Address,
client *ethclient.Client,
) (*ApplicationContractAdapter, error) {
applicationContract, err := appcontract.NewApplication(appAddress, client)
if err != nil {
return nil, err
}
return &ApplicationContractAdapter{
application: applicationContract,
}, nil
}

func (a *ApplicationContractAdapter) GetConsensus(opts *bind.CallOpts) (common.Address, error) {
return a.application.GetConsensus(opts)
}

func (a *ApplicationContractAdapter) RetrieveOutputExecutionEvents(
opts *bind.FilterOpts,
) ([]*appcontract.ApplicationOutputExecuted, error) {

itr, err := a.application.FilterOutputExecuted(opts)
if err != nil {
return nil, err
}
defer itr.Close()

var events []*appcontract.ApplicationOutputExecuted
for itr.Next() {
outputExecutedEvent := itr.Event
events = append(events, outputExecutedEvent)
}
err = itr.Error()
if err != nil {
return nil, err
}
return events, nil
}
13 changes: 9 additions & 4 deletions internal/evmreader/evmreader.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"slices"

. "github.com/cartesi/rollups-node/internal/node/model"
appcontract "github.com/cartesi/rollups-node/pkg/contracts/application"
"github.com/cartesi/rollups-node/pkg/contracts/iconsensus"
"github.com/cartesi/rollups-node/pkg/contracts/inputbox"
"github.com/ethereum/go-ethereum"
Expand Down Expand Up @@ -41,10 +42,11 @@ type EvmReaderRepository interface {
GetNodeConfig(ctx context.Context) (*NodePersistentConfig, error)
GetEpoch(ctx context.Context, indexKey uint64, appAddressKey Address) (*Epoch, error)
GetPreviousSubmittedClaims(ctx context.Context, app Address, lastBlock uint64) ([]Epoch, error)
StoreClaimsTransaction(ctx context.Context,
app Address,
claims []*Epoch,
mostRecentBlockNumber uint64,
StoreClaimsTransaction(
ctx context.Context, app Address, claims []*Epoch, mostRecentBlockNumber uint64,
) error
UpdateOutputExecutedTransaction(
ctx context.Context, app Address, executedOutputs []uint64, blockNumber uint64,
) error
}

Expand All @@ -68,6 +70,9 @@ type ConsensusContract interface {

type ApplicationContract interface {
GetConsensus(opts *bind.CallOpts) (Address, error)
RetrieveOutputExecutionEvents(
opts *bind.FilterOpts,
) ([]*appcontract.ApplicationOutputExecuted, error)
}

type ContractFactory interface {
Expand Down
88 changes: 88 additions & 0 deletions internal/evmreader/output.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
// (c) Cartesi and individual authors (see AUTHORS)
// SPDX-License-Identifier: Apache-2.0 (see LICENSE)

package evmreader

import (
"context"
"log/slog"

. "github.com/cartesi/rollups-node/internal/node/model"

Check failure on line 10 in internal/evmreader/output.go

View workflow job for this annotation

GitHub Actions / test-go

"github.com/cartesi/rollups-node/internal/node/model" imported and not used) (typecheck)

Check failure on line 10 in internal/evmreader/output.go

View workflow job for this annotation

GitHub Actions / test-go

"github.com/cartesi/rollups-node/internal/node/model" imported and not used) (typecheck)
"github.com/ethereum/go-ethereum/accounts/abi/bind"
)

func (r *EvmReader) checkForOutputExecution(
ctx context.Context,
apps []application,
mostRecentBlockNumber uint64,
) {

appAddresses := appToAddresses(apps)

slog.Debug("Checking for new Output Executed Events", "apps", appAddresses)

for _, app := range apps {

LastOutputCheck := app.LastOutputCheckBlock

// Safeguard: Only check blocks starting from the block where the InputBox
// contract was deployed as Inputs can be added to that same block
if LastOutputCheck < r.inputBoxDeploymentBlock {
LastOutputCheck = r.inputBoxDeploymentBlock
}

if mostRecentBlockNumber > LastOutputCheck {

slog.Info("Checking output execution for applications",
"apps", appAddresses,
"last output check block", LastOutputCheck,
"most recent block", mostRecentBlockNumber)

r.readAndUpdateOutputs(ctx, app, LastOutputCheck, mostRecentBlockNumber)

} else if mostRecentBlockNumber < LastOutputCheck {
slog.Warn(
"Not reading output execution: most recent block is lower than the last processed one", //nolint:lll
"apps", appAddresses,
"last output check block", LastOutputCheck,
"most recent block", mostRecentBlockNumber,
)
} else {
slog.Info("Not reading output execution: already checked the most recent blocks",
"apps", appAddresses,
"last output check block", LastOutputCheck,
"most recent block", mostRecentBlockNumber,
)
}
}

}

func (r *EvmReader) readAndUpdateOutputs(ctx context.Context, app application, lastOutputCheck, mostRecentBlockNumber uint64) {

contract := app.applicationContract

opts := &bind.FilterOpts{
Start: lastOutputCheck + 1,
End: &mostRecentBlockNumber,
}

outputExecutedEvents, err := contract.RetrieveOutputExecutionEvents(opts)
if err != nil {
slog.Error("Error reading output events", "app", app.ContractAddress, "error", err)
return
}

// Should we check the output hash??
var executedOutputs []uint64
for _, event := range outputExecutedEvents {
slog.Info("Output executed", "app", app, "index", event.OutputIndex)
executedOutputs = append(executedOutputs, event.OutputIndex)
}

err = r.repository.UpdateOutputExecutedTransaction(ctx, app.ContractAddress, executedOutputs, mostRecentBlockNumber)
if err != nil {
slog.Error("Error storing output execution statuses", "app", app, "error", err)
}

}
15 changes: 8 additions & 7 deletions internal/node/model/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,14 @@ type NodePersistentConfig struct {
}

type Application struct {
Id uint64
ContractAddress Address
TemplateHash Hash
LastProcessedBlock uint64
Status ApplicationStatus
IConsensusAddress Address
LastClaimCheckBlock uint64
Id uint64
ContractAddress Address
TemplateHash Hash
LastProcessedBlock uint64
Status ApplicationStatus
IConsensusAddress Address
LastClaimCheckBlock uint64
LastOutputCheckBlock uint64
}

type Epoch struct {
Expand Down
9 changes: 9 additions & 0 deletions internal/repository/evmreader.go
Original file line number Diff line number Diff line change
Expand Up @@ -371,3 +371,12 @@ func (pg *Database) StoreClaimsTransaction(

return nil
}

func (pg *Database) UpdateOutputExecutedTransaction(
ctx context.Context,
app Address,
executedOutputs []uint64,
blockNumber uint64,
) error {

}

Check failure on line 382 in internal/repository/evmreader.go

View workflow job for this annotation

GitHub Actions / test-go

missing return) (typecheck)

Check failure on line 382 in internal/repository/evmreader.go

View workflow job for this annotation

GitHub Actions / test-go

missing return) (typecheck)

Check failure on line 382 in internal/repository/evmreader.go

View workflow job for this annotation

GitHub Actions / test-go

missing return) (typecheck)

0 comments on commit b6d2f44

Please sign in to comment.