-
Notifications
You must be signed in to change notification settings - Fork 658
/
db.go
154 lines (132 loc) · 4.1 KB
/
db.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
package db
import (
"context"
"fmt"
"time"
"github.com/0xPolygonHermez/zkevm-node/log"
"github.com/0xPolygonHermez/zkevm-node/state"
"github.com/ethereum/go-ethereum/common"
"github.com/jackc/pgx/v4"
"github.com/jackc/pgx/v4/pgxpool"
)
// StateDB implements the StateDB interface
type StateDB struct {
*pgxpool.Pool
}
// NewStateDB creates a new StateDB
func NewStateDB(db *pgxpool.Pool) *StateDB {
return &StateDB{
db,
}
}
// NewSQLDB creates a new SQL DB
func NewSQLDB(cfg Config) (*pgxpool.Pool, error) {
config, err := pgxpool.ParseConfig(fmt.Sprintf("postgres://%s:%s@%s:%s/%s?pool_max_conns=%d", cfg.User, cfg.Password, cfg.Host, cfg.Port, cfg.Name, cfg.MaxConns))
if err != nil {
log.Errorf("Unable to parse DB config: %v\n", err)
return nil, err
}
if cfg.EnableLog {
config.ConnConfig.Logger = logger{}
}
conn, err := pgxpool.ConnectConfig(context.Background(), config)
if err != nil {
log.Errorf("Unable to connect to database: %v\n", err)
return nil, err
}
return conn, nil
}
// GetGenesisBlock returns the genesis block
func (db *StateDB) GetGenesisBlock(ctx context.Context) (*state.DSL2Block, error) {
const genesisL2BlockSQL = `SELECT 0 as batch_num, l2b.block_num, l2b.created_at, '0x0000000000000000000000000000000000000000' as global_exit_root, l2b.header->>'miner' AS coinbase, 0 as fork_id, l2b.block_hash, l2b.state_root
FROM state.l2block l2b
WHERE l2b.block_num = 0`
row := db.QueryRow(ctx, genesisL2BlockSQL)
l2block, err := scanL2Block(row)
if err != nil {
return nil, err
}
return l2block, nil
}
// GetL2Blocks returns the L2 blocks
func (db *StateDB) GetL2Blocks(ctx context.Context, limit, offset uint64) ([]*state.DSL2Block, error) {
const l2BlockSQL = `SELECT l2b.batch_num, l2b.block_num, l2b.created_at, b.global_exit_root, l2b.header->>'miner' AS coinbase, f.fork_id, l2b.block_hash, l2b.state_root
FROM state.l2block l2b, state.batch b, state.fork_id f
WHERE l2b.batch_num = b.batch_num AND l2b.batch_num between f.from_batch_num AND f.to_batch_num
ORDER BY l2b.block_num ASC limit $1 offset $2`
rows, err := db.Query(ctx, l2BlockSQL, limit, offset)
if err != nil {
return nil, err
}
defer rows.Close()
l2blocks := make([]*state.DSL2Block, 0, len(rows.RawValues()))
for rows.Next() {
l2block, err := scanL2Block(rows)
if err != nil {
return nil, err
}
l2blocks = append(l2blocks, l2block)
}
return l2blocks, nil
}
func scanL2Block(row pgx.Row) (*state.DSL2Block, error) {
l2Block := state.DSL2Block{}
var (
gerStr string
coinbaseStr string
timestamp time.Time
blockHashStr string
stateRootStr string
)
if err := row.Scan(
&l2Block.BatchNumber,
&l2Block.L2BlockNumber,
×tamp,
&gerStr,
&coinbaseStr,
&l2Block.ForkID,
&blockHashStr,
&stateRootStr,
); err != nil {
return &l2Block, err
}
l2Block.GlobalExitRoot = common.HexToHash(gerStr)
l2Block.Coinbase = common.HexToAddress(coinbaseStr)
l2Block.Timestamp = timestamp.Unix()
l2Block.BlockHash = common.HexToHash(blockHashStr)
l2Block.StateRoot = common.HexToHash(stateRootStr)
return &l2Block, nil
}
// GetL2Transactions returns the L2 transactions
func (db *StateDB) GetL2Transactions(ctx context.Context, minL2Block, maxL2Block uint64) ([]*state.DSL2Transaction, error) {
const l2TxSQL = `SELECT t.effective_percentage, LENGTH(t.encoded), t.encoded
FROM state.transaction t
WHERE l2_block_num BETWEEN $1 AND $2
ORDER BY t.l2_block_num ASC`
rows, err := db.Query(ctx, l2TxSQL, minL2Block, maxL2Block)
if err != nil {
return nil, err
}
defer rows.Close()
l2Txs := make([]*state.DSL2Transaction, 0, len(rows.RawValues()))
for rows.Next() {
l2Tx, err := scanL2Transaction(rows)
if err != nil {
return nil, err
}
l2Txs = append(l2Txs, l2Tx)
}
return l2Txs, nil
}
func scanL2Transaction(row pgx.Row) (*state.DSL2Transaction, error) {
l2Transaction := state.DSL2Transaction{}
if err := row.Scan(
&l2Transaction.EffectiveGasPricePercentage,
&l2Transaction.EncodedLength,
&l2Transaction.Encoded,
); err != nil {
return &l2Transaction, err
}
l2Transaction.IsValid = 1
return &l2Transaction, nil
}