Skip to content

Commit

Permalink
op proposer db
Browse files Browse the repository at this point in the history
  • Loading branch information
zobront committed Aug 6, 2024
1 parent 0d40aa1 commit dd53416
Show file tree
Hide file tree
Showing 3 changed files with 258 additions and 0 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ require (
github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-runewidth v0.0.14 // indirect
github.com/mattn/go-sqlite3 v1.14.22 // indirect
github.com/miekg/dns v1.1.58 // indirect
github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect
github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,8 @@ github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzp
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU=
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI=
Expand Down
255 changes: 255 additions & 0 deletions op-proposer/proposer/db.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,255 @@
package proposer

import (
"database/sql"
"fmt"

_ "github.com/mattn/go-sqlite3"
)

type ProofType string

const (
ProofTypeSPAN ProofType = "SPAN"
ProofTypeAGG ProofType = "AGG"
)

type ProofStatus string

const (
ProofStatusUNREQ ProofStatus = "UNREQ"
ProofStatusREQ ProofStatus = "REQ"
ProofStatusFAILED ProofStatus = "FAILED"
ProofStatusCOMPLETE ProofStatus = "COMPLETE"
)

type ProofRequest struct {
Type ProofType
StartBlock uint64
EndBlock uint64
Status ProofStatus
ProverRequestID string
ProofRequestTime int64
L1BlockNumber uint64
L1BlockHash string
}

type ProofDB struct {
db *sql.DB
}

func InitDB(dbPath string) (ProofDB, error) {
db, err := sql.Open("sqlite3", dbPath)
if err != nil {
return ProofDB{}, err
}

_, err = db.Exec(`
CREATE TABLE IF NOT EXISTS proof_requests (
id INTEGER PRIMARY KEY AUTOINCREMENT,
type TEXT NOT NULL CHECK(type IN ('SPAN', 'AGG')),
start_block_number INTEGER NOT NULL,
end_block_number INTEGER NOT NULL,
status TEXT NOT NULL CHECK(status IN ('UNREQ', 'REQ', 'FAILED', 'COMPLETE')),
prover_request_id TEXT,
proof_request_time INTEGER,
l1_block_number INTEGER,
l1_block_hash TEXT
)
`)
if err != nil {
return ProofDB{}, err
}

return ProofDB{db}, nil
}

// TODO: Flip this so it's an arg on the DB?
func (db ProofDB) newEntry(pr ProofRequest) error {
_, err := db.db.Exec(`
INSERT INTO proof_requests
(type, start_block_number, end_block_number, status, prover_request_id, proof_request_time, l1_block_number, l1_block_hash)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
`, pr.Type, pr.StartBlock, pr.EndBlock, pr.Status, pr.ProverRequestID, pr.ProofRequestTime, pr.L1BlockNumber, pr.L1BlockHash)
return err
}

func (db ProofDB) updateProofStatus(proverRequestID string, newStatus ProofStatus) error {
query := `
UPDATE proof_requests
SET status = ?
WHERE prover_request_id = ?
`

result, err := db.db.Exec(query, string(newStatus), proverRequestID)
if err != nil {
return fmt.Errorf("failed to update proof status: %w", err)
}

rowsAffected, err := result.RowsAffected()
if err != nil {
return fmt.Errorf("error getting rows affected: %w", err)
}

if rowsAffected == 0 {
return fmt.Errorf("no proof request found with ProverRequestID: %s", proverRequestID)
}

return nil
}

func (db ProofDB) addL1BlockInfo(proofRequest ProofRequest, l1BlockNumber uint64, l1BlockHash string) error {
query := `
UPDATE proof_requests
SET l1_block_number = ?, l1_block_hash = ?
WHERE type = 'AGG' AND status = 'UNREQ' AND start_block_number = ? AND end_block_number = ?
`

result, err := db.db.Exec(query, l1BlockNumber, l1BlockHash, proofRequest.StartBlock, proofRequest.EndBlock)
if err != nil {
return fmt.Errorf("failed to update proof status: %w", err)
}

rowsAffected, err := result.RowsAffected()
if err != nil {
return fmt.Errorf("error getting rows affected: %w", err)
}

if rowsAffected == 0 {
return fmt.Errorf("no proof request found with ProverRequestID: %s", proofRequest.ProverRequestID)
}

return nil
}

func (db ProofDB) getLatestEndRequested() (uint64, error) {
var endBlock uint64
// claude says err := l.db.QueryRow("SELECT COALESCE(MAX(end_block_number), 0) FROM proof_requests").Scan(&nextBlock)
err := db.db.QueryRow("SELECT MAX(end_block_number) FROM proof_requests").Scan(&endBlock)
return endBlock, err
}

func (db ProofDB) getRequestedProofs() ([]ProofRequest, error) {
rows, err := db.db.Query(`
SELECT type, start_block_number, end_block_number, status, prover_request_id, proof_request_time, l1_block_number, l1_block_hash
FROM proof_requests
WHERE status = 'REQ'
`)
if err != nil {
return nil, err
}
defer rows.Close()

return rowsToProofRequests(rows)
}

func (db ProofDB) getUnrequestedProofs() ([]ProofRequest, error) {
rows, err := db.db.Query(`
SELECT type, start_block_number, end_block_number, status, prover_request_id, proof_request_time, l1_block_number, l1_block_hash
FROM proof_requests
WHERE status = 'UNREQ'
`)
if err != nil {
return nil, err
}
defer rows.Close()

return rowsToProofRequests(rows)
}

func (db *ProofDB) getCompletedAggProofRequest(startBlock uint64) (*ProofRequest, error) {
query := `
SELECT type, start_block_number, end_block_number, status, prover_request_id, proof_request_time, l1_block_number, l1_block_hash
FROM proof_requests
WHERE type = 'AGG' AND start_block_number = ? AND status = 'COMPLETE'
LIMIT 1
`

var proof ProofRequest
err := db.db.QueryRow(query, startBlock).Scan(
&proof.Type, &proof.StartBlock, &proof.EndBlock, &proof.Status, &proof.ProverRequestID,
&proof.ProofRequestTime, &proof.L1BlockNumber, &proof.L1BlockHash,
)

if err == sql.ErrNoRows {
return nil, nil
}
if err != nil {
return nil, fmt.Errorf("failed to query completed AGG proof: %w", err)
}

return &proof, nil
}

func (db *ProofDB) tryCreateAggProofFromSpanProofs(latestOutputIndex, nextOutputIndex uint64) (bool, error) {
tx, err := db.db.Begin()
if err != nil {
return false, fmt.Errorf("failed to begin transaction: %w", err)
}
defer tx.Rollback()

// Check if there's already an AGG proof in progress
var count int
err = tx.QueryRow(`
SELECT COUNT(*) FROM proof_requests
WHERE type = 'AGG' AND start_block_number = ? AND status != 'FAILED'
`, latestOutputIndex).Scan(&count)
if err != nil {
return false, fmt.Errorf("failed to check existing AGG proofs: %w", err)
}
if count > 0 {
return false, nil // There's already an AGG proof in progress
}

// Find consecutive SPAN proofs
// TODO: Handle off by ones. I think output index is where we start (we haven't proceessed txs, but we sill add 1 below?)
start := latestOutputIndex
var end uint64
for {
var spanEnd uint64
err = tx.QueryRow(`
SELECT end_block_number FROM proof_requests
WHERE type = 'SPAN' AND status = 'COMPLETE' AND start_block_number = ?
`, start).Scan(&spanEnd)
if err == sql.ErrNoRows {
break // No more consecutive SPAN proofs
}
if err != nil {
return false, fmt.Errorf("failed to query SPAN proof: %w", err)
}
end = spanEnd
start = spanEnd + 1
}

if end < nextOutputIndex {
return false, nil // Not enough SPAN proofs to create an AGG proof
}

// Create a new AGG proof request
_, err = tx.Exec(`
INSERT INTO proof_requests (type, start_block_number, end_block_number, status)
VALUES ('AGG', ?, ?, 'UNREQ')
`, latestOutputIndex, end)
if err != nil {
return false, fmt.Errorf("failed to insert AGG proof request: %w", err)
}

err = tx.Commit()
if err != nil {
return false, fmt.Errorf("failed to commit transaction: %w", err)
}

return true, nil
}

func rowsToProofRequests(rows *sql.Rows) ([]ProofRequest, error) {
var prs []ProofRequest
for rows.Next() {
var pr ProofRequest
if err := rows.Scan(&pr.Type, &pr.StartBlock, &pr.EndBlock, &pr.Status, &pr.ProverRequestID, &pr.ProofRequestTime, &pr.L1BlockNumber, &pr.L1BlockHash); err != nil {
return nil, err
}
prs = append(prs, pr)
}
return prs, nil
}

0 comments on commit dd53416

Please sign in to comment.