6
script "gitverse.ru/IvanTimofeev/cranberry/internal/db/sql"
7
pbapi "gitverse.ru/IvanTimofeev/cranberry/pkg/grpc"
8
"gitverse.ru/IvanTimofeev/cranberry/pkg/utility"
20
type Queryable interface {
21
Query(query string, args ...any) (*sql.Rows, error)
24
func NewDb(host string, port int, login string, password string, sqlPath string) *Db {
34
func (db *Db) Connect() error {
35
coon, err := sql.Open("sqlite3", "./cranberry.db")
43
func (db *Db) Init() error {
44
return db.RunTransaction(func(tx *sql.Tx) error {
45
script, err := script.ReadInitSqlFile(db.sqlPath)
49
_, err = tx.Exec(string(script))
57
func (db *Db) SavePeer(name string, addr string, port int, tx *sql.Tx) error {
58
stmt, err := tx.Prepare("INSERT INTO PEERS (NAME, ADDR, PORT) VALUES (?, ?, ?)")
62
_, err = stmt.Exec(name, addr, port)
66
func (db *Db) SaveTx(txc *pbapi.TxContainer, bc *pbapi.BlockContainer, tx *sql.Tx) error {
67
stmt, err := tx.Prepare("INSERT INTO TXS (HASH, BLOCK_HEIGHT, ORDER_IN_BLOCK, FROM_ACC, TO_ACC, AMOUNT, SIGNATURE_R, SIGNATURE_S) VALUES (?, ?, ?, ?, ?, ?, ?, ?)")
71
from := utility.GetAddrFromPubKey(txc.PubKey)
85
func (db *Db) SaveBlock(b *pbapi.BlockContainer, tx *sql.Tx) error {
86
insertBlockHeaderStmt, err := tx.Prepare("INSERT INTO BLOCK_HEADERS (HASH, PREV_HASH, HEIGHT, MERKLE_ROOT) VALUES (?, ?, ?, ?)")
90
_, err = insertBlockHeaderStmt.Exec(
100
for _, s := range b.ValidatorSignatures {
101
insertBlockHeaderSignatureStmt, err := tx.Prepare("INSERT INTO BLOCK_HEADER_SIGNATURES (BLOCK_HEADER_HASH, VALIDATOR_ID, SIGNATURE_R, SIGNATURE_S) VALUES (?, ?, ?, ?)")
105
_, err = insertBlockHeaderSignatureStmt.Exec(
118
func (db *Db) SaveUint64Param(name string, value uint64, tx *sql.Tx) error {
119
_, ok, err := db.GetUint64Param(name)
124
stmt, err := tx.Prepare("UPDATE PARAMS SET VALUE = ? WHERE NAME = ?")
128
_, err = stmt.Exec(value, name)
133
stmt, err := tx.Prepare("INSERT INTO PARAMS (NAME, VALUE) VALUES (?, ?)")
137
_, err = stmt.Exec(name, value)
145
func (db *Db) SaveString64Param(name string, value string, tx *sql.Tx) error {
146
_, ok, err := db.GetString64Param(name)
151
stmt, err := tx.Prepare("UPDATE PARAMS SET VALUE = ? WHERE NAME = ?")
155
_, err = stmt.Exec(value, name)
160
stmt, err := tx.Prepare("INSERT INTO PARAMS (NAME, VALUE) VALUES (?, ?)")
164
_, err = stmt.Exec(name, value)
172
func (db *Db) GetUint64Param(name string) (uint64, bool, error) {
173
rows, err := db.coon.Query("SELECT VALUE FROM PARAMS WHERE NAME = ?", name)
180
if err := rows.Scan(&value); err != nil {
183
return value, true, nil
188
func (db *Db) GetString64Param(name string) (string, bool, error) {
189
rows, err := db.coon.Query("SELECT VALUE FROM PARAMS WHERE NAME = ?", name)
191
return "", false, err
196
if err := rows.Scan(&value); err != nil {
197
return "", false, err
199
return value, true, nil
201
return "", false, nil
204
func (db *Db) GetBlockByHeight(height uint64) (*pbapi.BlockContainer, bool, error) {
205
blockRows, err := db.coon.Query("SELECT HASH, PREV_HASH, HEIGHT, MERKLE_ROOT FROM BLOCK_HEADERS WHERE HEIGHT = ?", height)
207
return nil, false, err
209
defer blockRows.Close()
210
blockContainer := &pbapi.BlockContainer{
211
Header: &pbapi.BlockHeader{},
212
ValidatorSignatures: []*pbapi.SignatureItem{},
214
if blockRows.Next() {
215
if err := blockRows.Scan(
216
&blockContainer.Hash,
217
&blockContainer.Header.PrevHash,
218
&blockContainer.Header.Height,
219
&blockContainer.Header.MerkleRoot,
221
return nil, false, err
224
signaturesRows, err := db.coon.Query("SELECT VALIDATOR_ID, SIGNATURE_R, SIGNATURE_S FROM BLOCK_HEADER_SIGNATURES "+
225
"WHERE BLOCK_HEADER_HASH = ?", blockContainer.Hash)
227
return nil, false, err
229
defer signaturesRows.Close()
230
for signaturesRows.Next() {
231
si := &pbapi.SignatureItem{
232
Signature: &pbapi.Signature{},
234
if err := signaturesRows.Scan(
239
return nil, false, err
241
blockContainer.ValidatorSignatures = append(blockContainer.ValidatorSignatures, si)
243
return blockContainer, true, nil
246
func (db *Db) GetAllTxsByBlockHeight(height uint64) ([]*pbapi.TxContainer, error) {
247
rows, err := db.coon.Query("SELECT HASH, ORDER_IN_BLOCK, PUB_KEY, TO_ACC, AMOUNT, SIGNATURE_R, SIGNATURE_S FROM "+
248
"TXS LEFT JOIN ACCOUNTS ON TXS.FROM_ACC = ACCOUNTS.ADDR "+
249
"WHERE BLOCK_HEIGHT = ? ORDER BY ORDER_IN_BLOCK ASC", height)
254
txcs := make([]*pbapi.TxContainer, 0)
256
txc := &pbapi.TxContainer{
258
Signature: &pbapi.Signature{},
272
txcs = append(txcs, txc)
277
func (db *Db) SaveAccount(acc *pbapi.Account, tx *sql.Tx) error {
278
_, ok, err := db.GetAccount(acc.Addr)
283
stmt, err := tx.Prepare("UPDATE ACCOUNTS SET PUB_KEY = ?, BALANCE = ? WHERE ADDR = ?")
287
_, err = stmt.Exec(acc.PubKey, acc.Balance, acc.Addr)
292
stmt, err := tx.Prepare("INSERT INTO ACCOUNTS (ADDR, PUB_KEY, BALANCE) VALUES (?, ?, ?)")
296
_, err = stmt.Exec(acc.Addr, acc.PubKey, acc.Balance)
304
func (db *Db) GetAccountByTx(addr string, dbtx *sql.Tx) (*pbapi.Account, bool, error) {
305
return db.getAccount(addr, dbtx)
308
func (db *Db) GetAccount(addr string) (*pbapi.Account, bool, error) {
309
return db.getAccount(addr, db.coon)
312
func (db *Db) getAccount(addr string, q Queryable) (*pbapi.Account, bool, error) {
313
rows, err := q.Query("SELECT ADDR, PUB_KEY, BALANCE FROM ACCOUNTS WHERE ADDR = ?", addr)
315
return nil, false, err
319
acc := &pbapi.Account{}
323
&acc.Balance); err != nil {
324
return nil, false, err
326
return acc, true, nil
328
return nil, false, nil
331
func (db *Db) GetValidator(addr string) (*pbapi.Validator, bool, error) {
332
rows, err := db.coon.Query("SELECT ADDR, PUB_KEY FROM VALIDATORS WHERE ADDR = ?", addr)
334
return nil, false, err
338
validator := &pbapi.Validator{}
341
&validator.PubKey); err != nil {
342
return nil, false, err
344
return validator, true, nil
346
return nil, false, nil
349
func (db *Db) SaveValidator(validator *pbapi.Validator, tx *sql.Tx) error {
350
_, ok, err := db.GetValidator(validator.Addr)
355
stmt, err := tx.Prepare("UPDATE VALIDATORS SET PUB_KEY = ? WHERE ADDR = ?")
359
_, err = stmt.Exec(validator.PubKey, validator.Addr)
364
stmt, err := tx.Prepare("INSERT INTO VALIDATORS (ADDR, PUB_KEY) VALUES (?, ?)")
368
_, err = stmt.Exec(validator.Addr, validator.PubKey)
376
func (db *Db) RunTransaction(txfn func(tx *sql.Tx) error) func() error {
377
return func() error {
378
tx, err := db.coon.Begin()
384
if rerr := tx.Rollback(); rerr != nil {