Skip to content

Commit e3bde5a

Browse files
committed
Add block and transaction models for the API
1 parent 44501c0 commit e3bde5a

3 files changed

Lines changed: 158 additions & 0 deletions

File tree

api/models/blocks.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package models
2+
3+
import (
4+
"database/sql"
5+
"time"
6+
)
7+
8+
// BlocksModel groups operations on Blocks.
9+
type BlocksModel struct{}
10+
11+
// Block is a block.
12+
type Block struct {
13+
Height int `db:"height" json:"height"` // pk
14+
Hash string `db:"hash" json:"hash"`
15+
Timestamp int64 `db:"timestamp" json:"-"`
16+
TimestampHuman time.Time `db:"-" json:"timestamp"`
17+
Version int32 `db:"version" json:"version"`
18+
Producer string `db:"producer" json:"producer"`
19+
MerkleRoot string `db:"merkle_root" json:"merkle_root"`
20+
Parent string `db:"parent" json:"parent"`
21+
TxCount int `db:"tx_count" json:"tx_count"`
22+
}
23+
24+
// GetBlockList get a list of blocks with height in [from, to).
25+
func (m *BlocksModel) GetBlockList(from, to int) (blocks []*Block, err error) {
26+
query := `SELECT height, hash, timestamp, version, producer, merkle_root, parent, tx_count
27+
FROM indexed_blocks WHERE height >= ? and height < ?`
28+
_, err = chaindb.Select(&blocks, query, from, to)
29+
return blocks, err
30+
}
31+
32+
// GetBlockByHeight get a block by its height.
33+
func (m *BlocksModel) GetBlockByHeight(height int) (block *Block, err error) {
34+
block = &Block{}
35+
query := `SELECT height, hash, timestamp, version, producer, merkle_root, parent, tx_count
36+
FROM indexed_blocks WHERE height = ?`
37+
err = chaindb.SelectOne(block, query, height)
38+
if err == sql.ErrNoRows {
39+
return nil, nil
40+
}
41+
return block, err
42+
}
43+
44+
// GetBlockByHash get a block by its hash.
45+
func (m *BlocksModel) GetBlockByHash(hash string) (block *Block, err error) {
46+
block = &Block{}
47+
query := `SELECT height, hash, timestamp, version, producer, merkle_root, parent, tx_count
48+
FROM indexed_blocks WHERE hash = ?`
49+
err = chaindb.SelectOne(block, query, hash)
50+
if err == sql.ErrNoRows {
51+
return nil, nil
52+
}
53+
return block, err
54+
}

api/models/models.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package models
2+
3+
import (
4+
"database/sql"
5+
"fmt"
6+
7+
"github.com/CovenantSQL/CovenantSQL/conf"
8+
_ "github.com/CovenantSQL/go-sqlite3-encrypt" // sqlite3 driver
9+
"github.com/go-gorp/gorp"
10+
"github.com/pkg/errors"
11+
)
12+
13+
var (
14+
chaindb *gorp.DbMap
15+
)
16+
17+
// InitModels setup the models package.
18+
func InitModels() error {
19+
return initChainDBConnection()
20+
}
21+
22+
func initChainDBConnection() error {
23+
dsn := fmt.Sprintf("%s?_journal=WAL&mode=ro", conf.GConf.BP.ChainFileName)
24+
underdb, err := sql.Open("sqlite3", dsn)
25+
if err != nil {
26+
return errors.WithMessage(err, "unable to open chain.db")
27+
}
28+
chaindb = &gorp.DbMap{
29+
Db: underdb,
30+
Dialect: gorp.SqliteDialect{},
31+
}
32+
33+
// register tables
34+
chaindb.AddTableWithName(Block{}, "indexed_blocks").SetKeys(false, "Height")
35+
chaindb.AddTableWithName(Transaction{}, "indexed_transactions").SetKeys(false, "BlockHeight", "TxIndex")
36+
37+
return nil
38+
}

api/models/transactions.go

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package models
2+
3+
import (
4+
"database/sql"
5+
"fmt"
6+
"time"
7+
)
8+
9+
// TransactionsModel groups operations on Transactions.
10+
type TransactionsModel struct{}
11+
12+
// Transaction is a transaction.
13+
type Transaction struct {
14+
BlockHeight int `db:"block_height" json:"block_height"` // pk1
15+
TxIndex int `db:"tx_index" json:"index"` // pk2
16+
Hash string `db:"hash" json:"hash"`
17+
BlockHash string `db:"block_hash" json:"block_hash"`
18+
Timestamp int64 `db:"timestamp" json:"-"`
19+
TimestampHuman time.Time `db:"-" json:"timestamp"`
20+
TxType int `db:"tx_type" json:"type"`
21+
Signee string `db:"signee" json:"signee"`
22+
Address string `db:"address" json:"address"`
23+
Signature string `db:"signature" json:"signature"`
24+
Raw string `db:"raw" json:"raw"`
25+
Tx interface{} `db:"-" json:"tx"`
26+
}
27+
28+
// GetTransactionByHash get a transaction by its hash.
29+
func (m *TransactionsModel) GetTransactionByHash(hash string) (tx *Transaction, err error) {
30+
tx = &Transaction{}
31+
query := `SELECT block_height, tx_index, hash, block_hash, timestamp, tx_type,
32+
signee, address, signature, raw
33+
FROM indexed_transactions WHERE hash = ?`
34+
err = chaindb.SelectOne(tx, query, hash)
35+
if err == sql.ErrNoRows {
36+
return nil, nil
37+
}
38+
return tx, err
39+
}
40+
41+
// GetTransactionList get a transaction list by hash marker.
42+
func (m *TransactionsModel) GetTransactionList(since, direction string, limit int) (
43+
txs []*Transaction, err error,
44+
) {
45+
tx, err := m.GetTransactionByHash(since)
46+
if tx == nil {
47+
return txs, err
48+
}
49+
50+
orderBy := "DESC"
51+
compare := "<"
52+
if direction == "forward" {
53+
orderBy = "ASC"
54+
compare = ">"
55+
}
56+
57+
query := fmt.Sprintf(`SELECT block_height, tx_index, hash, block_hash,
58+
timestamp, tx_type, signee, address, signature, raw
59+
FROM indexed_transactions
60+
WHERE block_height %s ? and tx_index %s ?
61+
ORDER BY block_height %s, tx_index %s
62+
LIMIT ?`, compare, compare, orderBy, orderBy)
63+
64+
_, err = chaindb.Select(&txs, query, tx.BlockHeight, tx.TxIndex, limit)
65+
return txs, err
66+
}

0 commit comments

Comments
 (0)