Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: check runtime vs database db #254

Merged
merged 28 commits into from
Mar 19, 2025

Conversation

joanestebanr
Copy link
Contributor

@joanestebanr joanestebanr commented Feb 28, 2025

Description

  • Each database have a new key/value table (key_value)
  • The system, at startup, checks that each database is compatible with this run. To achieve this:
    • It checks previous data from key/value table, if it's empty it stores the revelant data to database (in case of syncer is chainID plus the addresses, in case of aggsender is networkID)
    • If the database data and runtime are compatible (is checked with function IsCompatible(storage T) error can run, if not it's a fail (you can override that setting config variable RequireStorageContentCompatibility to false)
  • The evmdriver for syncer check that the runtime environment match what is stored on DB:
  • Aggsender use the networkID

Config changes

  • There are a new param RequireStorageContentCompatibility (by default is true) as global var that is injected in: BridgeL1Sync, BridgeL2Sync, LastGERSync, AggSender:

[BridgeL1Sync]
RequireStorageContentCompatibility = {{RequireStorageContentCompatibility}}

[BridgeL2Sync]
RequireStorageContentCompatibility = {{RequireStorageContentCompatibility}}

[LastGERSync]
RequireStorageContentCompatibility = {{RequireStorageContentCompatibility}}

[AggSender]
RequireStorageContentCompatibility = {{RequireStorageContentCompatibility}}

Fixes #165

Review comments:

  • The interface Logger have been moved from aggsender/types to common packages because it's required by multiples modules
  • The integration of this feature in syncer is:
  • The compatibility data is sync.RuntimeData:
type RuntimeData struct {
	ChainID   uint64
	Addresses []common.Address
}
  • sync.EVMDriver have a new fields compatibilityChecker compatibility.CompatibilityChecker that implements the logic of this feature
  • The current (runtime) data is provided by sync.downloader interface using GetRuntimeData
  • The stored data is provided by sync.processorInterface implementing interface compatibility.CompatibilityDataStorager[RuntimeData]: There are a helper objects to allow provide this funcionality directly: that is compatibility.NewKeyValueToCompatibilityStorage[T]

The objects in compatibility module:

---
title: CompatibilityCheck class diagram
---
classDiagram
   
    CompatibilityCheck <|-- RuntimeDataGetter
    CompatibilityCheck <|-- CompatibilityDataStorager
    
    class CompatibilityCheck{
        +Check(ctx context.Context, tx db.Querier)
    }
    class CompatibilityDataStorager{
        + GetCompatibilityData(ctx context.Context, tx db.Querier) (bool, T, error)
        + SetCompatibilityData(ctx context.Context, tx db.Querier, data T) error
    }

    class RuntimeDataGetter{
        + func(ctx context.Context) (T, error)
    }
Loading

To implement CompatibilityDataStorager you can use:

PR Checklist:

  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • I have added or updated tests that comprehensively prove my change is effective or that my feature works

@joanestebanr joanestebanr self-assigned this Feb 28, 2025
@joanestebanr joanestebanr marked this pull request as ready for review March 4, 2025 10:04
@joanestebanr joanestebanr requested a review from vcastellm March 14, 2025 10:20
@rachit77 rachit77 self-requested a review March 14, 2025 14:32
Copy link
Contributor

@rachit77 rachit77 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Comment on lines +104 to +106
if s.Logger == nil {
s.Logger = log.WithFields("module", "compatibilityCheck")
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't we move this to the constructor function (NewCompatibilityCheck)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer a lazy initialization: if I create the object but I don't use it doesn't produce any error, but if you try to use it you need to fullfil the parameters.

I case that your question if over populating s.Logger. It's for the same reason, if I don't need Logger I don't need to populate until I'm going to use it, also, in the first version, not setting the Logger variable was an error

WDTY?

return nil
}

func (s *CompatibilityCheck[T]) initialize() error {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WDYT, in order to be semantically more correct?

Suggested change
func (s *CompatibilityCheck[T]) initialize() error {
func (s *CompatibilityCheck[T]) validate() error {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In fact it's doing both things: the field Logger is initialized and the rest checked... I don't mind if you prefer validate for me it's ok. WDYT?

@joanestebanr joanestebanr merged commit 50cf476 into develop Mar 19, 2025
11 checks passed
@joanestebanr joanestebanr deleted the feat/check-db-compatibility-165 branch March 19, 2025 09:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants