Commit 1f372382 authored by Hamdi Allam's avatar Hamdi Allam

update database to account for output proposals

parent ab15393d
...@@ -3,9 +3,9 @@ package database ...@@ -3,9 +3,9 @@ package database
import ( import (
"context" "context"
"errors" "errors"
"math/big"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/google/uuid"
"gorm.io/gorm" "gorm.io/gorm"
) )
...@@ -27,11 +27,6 @@ type L1BlockHeader struct { ...@@ -27,11 +27,6 @@ type L1BlockHeader struct {
type L2BlockHeader struct { type L2BlockHeader struct {
BlockHeader BlockHeader
// Marked when the proposed output is finalized on L1.
// All bedrock blocks will have `LegacyStateBatchIndex ^== NULL`
L1BlockHash *common.Hash `gorm:"serializer:json"`
LegacyStateBatchIndex *uint64
} }
type LegacyStateBatch struct { type LegacyStateBatch struct {
...@@ -42,22 +37,30 @@ type LegacyStateBatch struct { ...@@ -42,22 +37,30 @@ type LegacyStateBatch struct {
Root common.Hash `gorm:"serializer:json"` Root common.Hash `gorm:"serializer:json"`
Size uint64 Size uint64
PrevTotal uint64 PrevTotal uint64
L1BlockHash common.Hash `gorm:"serializer:json"` L1ContractEventGUID uuid.UUID
}
type OutputProposal struct {
OutputRoot common.Hash `gorm:"primaryKey;serializer:json"`
L2BlockNumber U256
L1ContractEventGUID uuid.UUID
} }
type BlocksView interface { type BlocksView interface {
FinalizedL1BlockHeader() (*L1BlockHeader, error) LatestL1BlockHeader() (*L1BlockHeader, error)
FinalizedL2BlockHeader() (*L2BlockHeader, error) LatestOutputProposed() (*OutputProposal, error)
LatestL2BlockHeader() (*L2BlockHeader, error)
} }
type BlocksDB interface { type BlocksDB interface {
BlocksView BlocksView
StoreL1BlockHeaders([]*L1BlockHeader) error StoreL1BlockHeaders([]*L1BlockHeader) error
StoreLegacyStateBatch(*LegacyStateBatch) error
StoreL2BlockHeaders([]*L2BlockHeader) error StoreL2BlockHeaders([]*L2BlockHeader) error
MarkFinalizedL1RootForL2Block(common.Hash, common.Hash) error
StoreLegacyStateBatches([]*LegacyStateBatch) error
StoreOutputProposals([]*OutputProposal) error
} }
/** /**
...@@ -79,39 +82,33 @@ func (db *blocksDB) StoreL1BlockHeaders(headers []*L1BlockHeader) error { ...@@ -79,39 +82,33 @@ func (db *blocksDB) StoreL1BlockHeaders(headers []*L1BlockHeader) error {
return result.Error return result.Error
} }
func (db *blocksDB) StoreLegacyStateBatch(stateBatch *LegacyStateBatch) error { func (db *blocksDB) StoreLegacyStateBatches(stateBatches []*LegacyStateBatch) error {
result := db.gorm.Create(stateBatch) result := db.gorm.Create(stateBatches)
if result.Error != nil {
return result.Error return result.Error
} }
// Mark this state batch index & l1 block hash for all applicable l2 blocks func (db *blocksDB) StoreOutputProposals(outputs []*OutputProposal) error {
l2Headers := make([]*L2BlockHeader, stateBatch.Size) result := db.gorm.Create(outputs)
return result.Error
}
// [start, end] range is inclusive. Since `PrevTotal` is the index of the prior batch, no func (db *blocksDB) LatestL1BlockHeader() (*L1BlockHeader, error) {
// need to subtract one when adding the size var l1Header L1BlockHeader
startHeight := U256{Int: big.NewInt(int64(stateBatch.PrevTotal + 1))} result := db.gorm.Order("number DESC").Take(&l1Header)
endHeight := U256{Int: big.NewInt(int64(stateBatch.PrevTotal + stateBatch.Size))}
result = db.gorm.Where("number BETWEEN ? AND ?", &startHeight, &endHeight).Find(&l2Headers)
if result.Error != nil { if result.Error != nil {
return result.Error if errors.Is(result.Error, gorm.ErrRecordNotFound) {
} else if result.RowsAffected != int64(stateBatch.Size) { return nil, nil
return errors.New("state batch size exceeds number of indexed l2 blocks")
} }
for _, header := range l2Headers { return nil, result.Error
header.LegacyStateBatchIndex = &stateBatch.Index
header.L1BlockHash = &stateBatch.L1BlockHash
} }
result = db.gorm.Save(&l2Headers) return &l1Header, nil
return result.Error
} }
// FinalizedL1BlockHeader returns the latest L1 block header stored in the database, nil otherwise func (db *blocksDB) LatestOutputProposed() (*OutputProposal, error) {
func (db *blocksDB) FinalizedL1BlockHeader() (*L1BlockHeader, error) { var outputProposal OutputProposal
var l1Header L1BlockHeader result := db.gorm.Order("l2_block_number DESC").Take(&outputProposal)
result := db.gorm.Order("number DESC").Take(&l1Header)
if result.Error != nil { if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) { if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return nil, nil return nil, nil
...@@ -120,7 +117,7 @@ func (db *blocksDB) FinalizedL1BlockHeader() (*L1BlockHeader, error) { ...@@ -120,7 +117,7 @@ func (db *blocksDB) FinalizedL1BlockHeader() (*L1BlockHeader, error) {
return nil, result.Error return nil, result.Error
} }
return &l1Header, nil return &outputProposal, nil
} }
// L2 // L2
...@@ -130,8 +127,7 @@ func (db *blocksDB) StoreL2BlockHeaders(headers []*L2BlockHeader) error { ...@@ -130,8 +127,7 @@ func (db *blocksDB) StoreL2BlockHeaders(headers []*L2BlockHeader) error {
return result.Error return result.Error
} }
// FinalizedL2BlockHeader returns the latest L2 block header stored in the database, nil otherwise func (db *blocksDB) LatestL2BlockHeader() (*L2BlockHeader, error) {
func (db *blocksDB) FinalizedL2BlockHeader() (*L2BlockHeader, error) {
var l2Header L2BlockHeader var l2Header L2BlockHeader
result := db.gorm.Order("number DESC").Take(&l2Header) result := db.gorm.Order("number DESC").Take(&l2Header)
if result.Error != nil { if result.Error != nil {
...@@ -145,19 +141,3 @@ func (db *blocksDB) FinalizedL2BlockHeader() (*L2BlockHeader, error) { ...@@ -145,19 +141,3 @@ func (db *blocksDB) FinalizedL2BlockHeader() (*L2BlockHeader, error) {
result.Logger.Info(context.Background(), "number ", l2Header.Number) result.Logger.Info(context.Background(), "number ", l2Header.Number)
return &l2Header, nil return &l2Header, nil
} }
// MarkFinalizedL1RootForL2Block updates the stored L2 block header with the L1 block
// that contains the output proposal for the L2 root.
func (db *blocksDB) MarkFinalizedL1RootForL2Block(l2Root, l1Root common.Hash) error {
var l2Header L2BlockHeader
l2Header.Hash = l2Root // set the primary key
result := db.gorm.First(&l2Header)
if result.Error != nil {
return result.Error
}
l2Header.L1BlockHash = &l1Root
result = db.gorm.Save(&l2Header)
return result.Error
}
...@@ -13,28 +13,11 @@ CREATE TABLE IF NOT EXISTS l1_block_headers ( ...@@ -13,28 +13,11 @@ CREATE TABLE IF NOT EXISTS l1_block_headers (
timestamp INTEGER NOT NULL timestamp INTEGER NOT NULL
); );
CREATE TABLE IF NOT EXISTS legacy_state_batches (
index INTEGER NOT NULL PRIMARY KEY,
root VARCHAR NOT NULL,
size INTEGER NOT NULL,
prev_total INTEGER NOT NULL,
-- Finalization information. Unlike `l2_block_headers` the NOT NULL
-- constraint is added since the l1 block hash will be known when
-- when reading the output event
l1_block_hash VARCHAR NOT NULL REFERENCES l1_block_headers(hash)
);
CREATE TABLE IF NOT EXISTS l2_block_headers ( CREATE TABLE IF NOT EXISTS l2_block_headers (
-- Block header
hash VARCHAR NOT NULL PRIMARY KEY, hash VARCHAR NOT NULL PRIMARY KEY,
parent_hash VARCHAR NOT NULL, parent_hash VARCHAR NOT NULL,
number UINT256, number UINT256,
timestamp INTEGER NOT NULL, timestamp INTEGER NOT NULL
-- Finalization information
l1_block_hash VARCHAR REFERENCES l1_block_headers(hash),
legacy_state_batch_index INTEGER REFERENCES legacy_state_batches(index)
); );
/** /**
...@@ -59,6 +42,24 @@ CREATE TABLE IF NOT EXISTS l2_contract_events ( ...@@ -59,6 +42,24 @@ CREATE TABLE IF NOT EXISTS l2_contract_events (
timestamp INTEGER NOT NULL timestamp INTEGER NOT NULL
); );
-- Tables that index finalization markers for L2 blocks.
CREATE TABLE IF NOT EXISTS legacy_state_batches (
index INTEGER NOT NULL PRIMARY KEY,
root VARCHAR NOT NULL,
size INTEGER NOT NULL,
prev_total INTEGER NOT NULL,
l1_contract_event_guid VARCHAR REFERENCES l1_contract_events(guid)
);
CREATE TABLE IF NOT EXISTS output_proposals (
output_root VARCHAR NOT NULL PRIMARY KEY,
l2_block_number UINT256,
l1_contract_event_guid VARCHAR REFERENCES l1_contract_events(guid)
);
/** /**
* BRIDGING DATA * BRIDGING DATA
*/ */
...@@ -71,6 +72,7 @@ CREATE TABLE IF NOT EXISTS deposits ( ...@@ -71,6 +72,7 @@ CREATE TABLE IF NOT EXISTS deposits (
-- Deposit information (do we need indexes on from/to?) -- Deposit information (do we need indexes on from/to?)
from_address VARCHAR NOT NULL, from_address VARCHAR NOT NULL,
to_address VARCHAR NOT NULL, to_address VARCHAR NOT NULL,
l1_token_address VARCHAR NOT NULL, l1_token_address VARCHAR NOT NULL,
l2_token_address VARCHAR NOT NULL, l2_token_address VARCHAR NOT NULL,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment