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: commit transaction data to L1 #85

Merged
merged 23 commits into from
Jul 17, 2024

Conversation

MujkicA
Copy link
Contributor

@MujkicA MujkicA commented Jun 30, 2024

Initial setup for committing transaction data to L1.

Changes:

New runnable tasks:

  • StateImporter - Fetches blocks from L2, performs fragmentation and stores
    a StateSubmission and the corresponding StateFragment to the db
  • StateCommitter - Fetches fragments from the db and submits to L1 them via a blob transaction

Database:

  • l1_state_submission
  • l1_state_fragment
  • l1_pending_transaction

Changes to config:

  • separate wallet key for posting blobs due to a limitation where transactions cannot exist in both the blob pool and the regular pool simultaneously

@MujkicA MujkicA self-assigned this Jun 30, 2024
@MujkicA MujkicA marked this pull request as ready for review July 3, 2024 13:58
@MujkicA MujkicA added the enhancement New feature or request label Jul 3, 2024
@hal3e hal3e changed the title Commit transaction data to L1 feat: commit transaction data to L1 Jul 4, 2024
Copy link
Contributor

@hal3e hal3e left a comment

Choose a reason for hiding this comment

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

Awesome work! Thanks for the hard work!

committer/src/main.rs Outdated Show resolved Hide resolved
committer/src/setup.rs Outdated Show resolved Hide resolved
packages/services/src/state_importer.rs Outdated Show resolved Hide resolved
Copy link
Member

@digorithm digorithm left a comment

Choose a reason for hiding this comment

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

Great work so far! I'm still going through the whole PR (it's a beefy one), but I thought I'd leave some comments before I finish it all, mostly around some maintainability improvements.

committer/src/main.rs Outdated Show resolved Hide resolved
packages/eth/src/eip_4844/types.rs Outdated Show resolved Hide resolved
packages/eth/src/eip_4844/types.rs Outdated Show resolved Hide resolved
packages/eth/src/eip_4844/types.rs Outdated Show resolved Hide resolved
packages/eth/src/eip_4844/types.rs Show resolved Hide resolved
packages/eth/src/eip_4844/utils.rs Show resolved Hide resolved
packages/eth/src/websocket/connection.rs Outdated Show resolved Hide resolved
@MujkicA MujkicA requested review from digorithm and hal3e July 5, 2024 23:19
Copy link
Contributor

@segfault-magnet segfault-magnet left a comment

Choose a reason for hiding this comment

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

Great work! Must have been soul deadening to get the blob txs to work with ethers.

I have a suggestion for the schema:

I feel we might be denormalizing the schema a bit too early. Wdyt about replacing all the completed fields with queries:

Say we have 3 entities:
submissions
fragments
transactions

We retain the current relationship that a submission can have many fragments, while one fragment only belongs to one submission.

A fragment can appear in many l1 transactions (*), and one L1 transaction can have many fragments.

(*) because we plan on supporting retries, a fragment might be in one tx that failed and in another that succeeded, or in two that both succeeded (if we screw up and send two due to edge cases, we only care that one succeeds).

So the question:
Give me all successfully finished submissions would turn into:

Give me all submissions, whose fragments appear in at least one successful L1 transaction.

POC:

-- Create the tables
CREATE TABLE submissions (
    id SERIAL PRIMARY KEY
);

CREATE TABLE fragments (
    id SERIAL PRIMARY KEY,
    position BIGINT NOT NULL CHECK (position >= 0),
    submission_id INTEGER NOT NULL REFERENCES submissions(id),
    data BYTEA NOT NULL
);

CREATE TABLE transactions (
    id SERIAL PRIMARY KEY,
    hash BYTEA NOT NULL UNIQUE,
    status TEXT NOT NULL CHECK (status IN ('succeeded', 'pending', 'failed'))
);

CREATE TABLE transaction_fragments (
    transaction_id INTEGER NOT NULL REFERENCES transactions(id),
    fragment_id INTEGER NOT NULL REFERENCES fragments(id),
    PRIMARY KEY (transaction_id, fragment_id)
);

-- Create the additional index
CREATE INDEX idx_transactions_status ON transactions(status);

-- Insert values into submissions
INSERT INTO submissions (id) VALUES (DEFAULT), (DEFAULT);

-- Insert values into fragments
-- For completed submission (submission_id = 1)
INSERT INTO fragments (position, submission_id, data) VALUES
(0, 1, '\x010203'),
(1, 1, '\x040506'),
(2, 1, '\x070809');

-- For incomplete submission (submission_id = 2)
INSERT INTO fragments (position, submission_id, data) VALUES
(0, 2, '\x0a0b0c'),
(1, 2, '\x0d0e0f'),
(2, 2, '\x101112');

-- Insert values into transactions
INSERT INTO transactions (hash, status) VALUES
('\xa1b2c3d4', 'succeeded'),
('\xb2c3d4e5', 'succeeded'),
('\xc3d4e5f6', 'pending');

-- Insert values into transaction_fragments
-- For completed submission (submission_id = 1)
INSERT INTO transaction_fragments (transaction_id, fragment_id) VALUES
(1, 1), -- fragment_id 1 belongs to succeeded transaction
(1, 2), -- fragment_id 2 belongs to succeeded transaction
(1, 3); -- fragment_id 3 belongs to succeeded transaction

-- For incomplete submission (submission_id = 2)
INSERT INTO transaction_fragments (transaction_id, fragment_id) VALUES
(3, 4), -- fragment_id 4 belongs to pending transaction
(3, 5); -- fragment_id 5 belongs to pending transaction
-- fragment_id 6 is not in a succeeded transaction

SELECT
    s.id AS submission_id,
    (
        SELECT COUNT(*)
        FROM fragments f
        WHERE f.submission_id = s.id
    ) = (
        SELECT COUNT(DISTINCT f.id)
        FROM fragments f
        JOIN transaction_fragments tf ON tf.fragment_id = f.id
        JOIN transactions t ON t.id = tf.transaction_id
        WHERE f.submission_id = s.id
        AND t.status = 'succeeded'
    ) AS is_completed
FROM
    submissions s;

Would result in:

 submission_id | is_completed 
---------------+--------------
             1 | t
             2 | f
(2 rows)

So a single write to inform the db of a successful l1 transaction will be all that it takes to mark a submission as completed.

The query should be optimal as is, eventually an index on the tx status. But I think that our expected load plus the cleaning we'll be doing periodically is enough to keep the performance of this query optimal.

committer/src/config.rs Outdated Show resolved Hide resolved
packages/eth/src/eip_4844/types.rs Outdated Show resolved Hide resolved
packages/eth/src/eip_4844/types.rs Outdated Show resolved Hide resolved
packages/eth/src/eip_4844/types.rs Outdated Show resolved Hide resolved
packages/eth/src/eip_4844/types.rs Outdated Show resolved Hide resolved
packages/services/src/state_importer.rs Outdated Show resolved Hide resolved
packages/storage/migrations/0002_state_submission.up.sql Outdated Show resolved Hide resolved
packages/storage/migrations/0002_state_submission.up.sql Outdated Show resolved Hide resolved
packages/storage/src/postgres.rs Outdated Show resolved Hide resolved
packages/storage/src/postgres.rs Outdated Show resolved Hide resolved
packages/eth/src/websocket.rs Outdated Show resolved Hide resolved
MujkicA and others added 3 commits July 13, 2024 00:15
…uel-block-committer into feature/transaction-committer
@An-tol

This comment was marked as off-topic.

Copy link

@Br1ght0ne Br1ght0ne left a comment

Choose a reason for hiding this comment

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

Huge PR, but I think with the previous review comments it's as good as it can be. Legend 🚀

Copy link
Member

@digorithm digorithm left a comment

Choose a reason for hiding this comment

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

:shipit: -- incredible work!

@segfault-magnet segfault-magnet self-assigned this Jul 17, 2024
@segfault-magnet segfault-magnet merged commit c70eae2 into master Jul 17, 2024
7 checks passed
@segfault-magnet segfault-magnet deleted the feature/transaction-committer branch July 17, 2024 18:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants