Skip to content

Commit

Permalink
make separate network_metrics table instead of using blocks table
Browse files Browse the repository at this point in the history
  • Loading branch information
chris124567 committed May 29, 2024
1 parent 7b88185 commit b70d4b0
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 43 deletions.
1 change: 0 additions & 1 deletion explorer/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,6 @@ type Block struct {

ParentID types.BlockID `json:"parentID"`
Nonce uint64 `json:"nonce"`
Difficulty consensus.Work `json:"difficulty"`
Timestamp time.Time `json:"timestamp"`
MinerPayouts []SiacoinOutput `json:"minerPayouts"`
Transactions []Transaction `json:"transactions"`
Expand Down
2 changes: 1 addition & 1 deletion persist/sqlite/blocks.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
// Block implements explorer.Store.
func (s *Store) Block(id types.BlockID) (result explorer.Block, err error) {
err = s.transaction(func(tx *txn) error {
err = tx.QueryRow(`SELECT parent_id, nonce, difficulty, timestamp, height FROM blocks WHERE id=?`, encode(id)).Scan(decode(&result.ParentID), decode(&result.Nonce), decode(&result.Difficulty), decode(&result.Timestamp), &result.Height)
err = tx.QueryRow(`SELECT parent_id, nonce, timestamp, height FROM blocks WHERE id=?`, encode(id)).Scan(decode(&result.ParentID), decode(&result.Nonce), decode(&result.Timestamp), &result.Height)
if err != nil {
return err
}
Expand Down
64 changes: 27 additions & 37 deletions persist/sqlite/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,36 +17,10 @@ type updateTx struct {
tx *txn
}

func addBlock(tx *txn, b types.Block, height uint64, difficulty consensus.Work) (explorer.Metrics, error) {
var totalHosts, activeContracts, failedContracts, successfulContracts, storageUtilization uint64
var circulatingSupply, contractRevenue types.Currency
if height > 0 {
err := tx.QueryRow("SELECT total_hosts, active_contracts, failed_contracts, successful_contracts, storage_utilization, circulating_supply, contract_revenue from blocks WHERE height = ?", height-1).Scan(&totalHosts, &activeContracts, &failedContracts, &successfulContracts, &storageUtilization, decode(&circulatingSupply), decode(&contractRevenue))
if err != nil {
return explorer.Metrics{}, fmt.Errorf("addBlock: failed to get previous metrics: %w", err)
}
} else {
// add genesis outputs
for _, txn := range b.Transactions {
for _, sco := range txn.SiacoinOutputs {
circulatingSupply = circulatingSupply.Add(sco.Value)
}
}
}

func addBlock(tx *txn, b types.Block, height uint64) error {
// nonce is encoded because database/sql doesn't support uint64 with high bit set
_, err := tx.Exec("INSERT INTO blocks(id, height, parent_id, nonce, timestamp, difficulty, total_hosts, active_contracts, failed_contracts, successful_contracts, storage_utilization, circulating_supply, contract_revenue) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);", encode(b.ID()), height, encode(b.ParentID), encode(b.Nonce), encode(b.Timestamp), encode(difficulty), totalHosts, activeContracts, failedContracts, successfulContracts, storageUtilization, encode(circulatingSupply), encode(contractRevenue))
return explorer.Metrics{
Height: height,
Difficulty: difficulty,
TotalHosts: totalHosts,
ActiveContracts: activeContracts,
FailedContracts: failedContracts,
SuccessfulContracts: successfulContracts,
StorageUtilization: storageUtilization,
CirculatingSupply: circulatingSupply,
ContractRevenue: contractRevenue,
}, err
_, err := tx.Exec("INSERT INTO blocks(id, height, parent_id, nonce, timestamp) VALUES (?, ?, ?, ?, ?);", encode(b.ID()), height, encode(b.ParentID), encode(b.Nonce), encode(b.Timestamp))
return err
}

func addMinerPayouts(tx *txn, bid types.BlockID, scos []types.SiacoinOutput, dbIDs map[types.SiacoinOutputID]int64) error {
Expand Down Expand Up @@ -840,10 +814,25 @@ func addFileContractElements(tx *txn, b types.Block, fces []explorer.FileContrac
return fcDBIds, updateErr
}

func updateMetrics(tx *txn, b types.Block, fces []explorer.FileContractUpdate, events []explorer.Event, existingMetrics explorer.Metrics) error {
func addMetrics(tx *txn, height uint64, difficulty consensus.Work, b types.Block, fces []explorer.FileContractUpdate, events []explorer.Event) error {
var existingMetrics explorer.Metrics
if height > 0 {
err := tx.QueryRow("SELECT total_hosts, active_contracts, failed_contracts, successful_contracts, storage_utilization, circulating_supply, contract_revenue from network_metrics WHERE height = ?", height-1).Scan(&existingMetrics.TotalHosts, &existingMetrics.ActiveContracts, &existingMetrics.FailedContracts, &existingMetrics.SuccessfulContracts, &existingMetrics.StorageUtilization, decode(&existingMetrics.CirculatingSupply), decode(&existingMetrics.ContractRevenue))
if err != nil {
return fmt.Errorf("addMetrics: failed to get previous metrics: %w", err)
}
} else {
// add genesis outputs
for _, txn := range b.Transactions {
for _, sco := range txn.SiacoinOutputs {
existingMetrics.CirculatingSupply = existingMetrics.CirculatingSupply.Add(sco.Value)
}
}
}

hostExistsQuery, err := tx.Prepare(`SELECT EXISTS(SELECT public_key FROM host_announcements WHERE public_key = ?)`)
if err != nil {
return fmt.Errorf("updateMetrics: failed to prepare host announcement query: %w", err)
return fmt.Errorf("addMetrics: failed to prepare host announcement query: %w", err)
}
defer hostExistsQuery.Close()

Expand Down Expand Up @@ -900,25 +889,26 @@ func updateMetrics(tx *txn, b types.Block, fces []explorer.FileContractUpdate, e
circulatingSupplyDelta = circulatingSupplyDelta.Add(mp.Value)
}

_, err = tx.Exec(`UPDATE blocks SET total_hosts = ?, active_contracts = ?, failed_contracts = ?, successful_contracts = ?, storage_utilization = ?, circulating_supply = ?, contract_revenue = ? WHERE id = ?`,
_, err = tx.Exec(`INSERT INTO network_metrics(block_id, height, difficulty, total_hosts, active_contracts, failed_contracts, successful_contracts, storage_utilization, circulating_supply, contract_revenue) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
encode(b.ID()),
height,
encode(difficulty),
int64(existingMetrics.TotalHosts)+totalHostsDelta,
int64(existingMetrics.ActiveContracts)+activeContractsDelta,
int64(existingMetrics.FailedContracts)+failedContractsDelta,
int64(existingMetrics.SuccessfulContracts)+successfulContractsDelta,
int64(existingMetrics.StorageUtilization)+storageUtilizationDelta,
encode(existingMetrics.CirculatingSupply.Add(circulatingSupplyDelta)),
encode(existingMetrics.ContractRevenue.Add(contractRevenueDelta)),
encode(b.ID()),
)
if err != nil {
return fmt.Errorf("updateMetrics: failed to execute metrics update query: %w", err)
return fmt.Errorf("addMetrics: failed to execute metrics update query: %w", err)
}
return nil
}

func (ut *updateTx) ApplyIndex(state explorer.UpdateState) error {
existingMetrics, err := addBlock(ut.tx, state.Block, state.Index.Height, state.Difficulty)
if err != nil {
if err := addBlock(ut.tx, state.Block, state.Index.Height); err != nil {
return fmt.Errorf("ApplyIndex: failed to add block: %w", err)
} else if err := updateMaturedBalances(ut.tx, false, state.Index.Height); err != nil {
return fmt.Errorf("ApplyIndex: failed to update matured balances: %w", err)
Expand Down Expand Up @@ -957,7 +947,7 @@ func (ut *updateTx) ApplyIndex(state explorer.UpdateState) error {
return fmt.Errorf("ApplyIndex: failed to add transactions: addTransactions: %w", err)
} else if err := updateStateTree(ut.tx, state.TreeUpdates); err != nil {
return fmt.Errorf("ApplyIndex: failed to update state tree: %w", err)
} else if err := updateMetrics(ut.tx, state.Block, state.FileContractElements, state.Events, existingMetrics); err != nil {
} else if err := addMetrics(ut.tx, state.Index.Height, state.Difficulty, state.Block, state.FileContractElements, state.Events); err != nil {
return fmt.Errorf("ApplyIndex: failed to update metrics: %w", err)
} else if err := addEvents(ut.tx, scDBIds, fcDBIds, txnDBIds, state.Events); err != nil {
return fmt.Errorf("ApplyIndex: failed to add events: %w", err)
Expand Down
11 changes: 9 additions & 2 deletions persist/sqlite/init.sql
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,15 @@ CREATE TABLE blocks (
height INTEGER NOT NULL,
parent_id BLOB NOT NULL,
nonce BLOB NOT NULL,
timestamp INTEGER NOT NULL,
timestamp INTEGER NOT NULL
);

CREATE INDEX blocks_height_index ON blocks(height);

CREATE TABLE network_metrics (
block_id BLOB PRIMARY KEY REFERENCES blocks(id) ON DELETE CASCADE NOT NULL,

height INTEGER NOT NULL,
difficulty BLOB NOT NULL,
total_hosts INTEGER NOT NULL,
active_contracts INTEGER NOT NULL,
Expand All @@ -20,7 +27,7 @@ CREATE TABLE blocks (
contract_revenue BLOB NOT NULL
);

CREATE INDEX blocks_height_index ON blocks(height);
CREATE INDEX network_metrics_height_index ON network_metrics(height);

CREATE TABLE address_balance (
id INTEGER PRIMARY KEY,
Expand Down
4 changes: 2 additions & 2 deletions persist/sqlite/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ import (
// Metrics implements explorer.Store
func (s *Store) Metrics(id types.BlockID) (result explorer.Metrics, err error) {
err = s.transaction(func(tx *txn) error {
err = tx.QueryRow(`SELECT height, difficulty, total_hosts, active_contracts, failed_contracts, successful_contracts, storage_utilization, circulating_supply, contract_revenue FROM blocks WHERE id = ?`, encode(id)).Scan(&result.Height, decode(&result.Difficulty), &result.TotalHosts, &result.ActiveContracts, &result.FailedContracts, &result.SuccessfulContracts, &result.StorageUtilization, decode(&result.CirculatingSupply), decode(&result.ContractRevenue))
err = tx.QueryRow(`SELECT height, difficulty, total_hosts, active_contracts, failed_contracts, successful_contracts, storage_utilization, circulating_supply, contract_revenue FROM network_metrics WHERE block_id = ?`, encode(id)).Scan(&result.Height, decode(&result.Difficulty), &result.TotalHosts, &result.ActiveContracts, &result.FailedContracts, &result.SuccessfulContracts, &result.StorageUtilization, decode(&result.CirculatingSupply), decode(&result.ContractRevenue))
if err != nil {
return fmt.Errorf("failed to get height and difficulty: %w", err)
return fmt.Errorf("failed to get metrics: %w", err)
}
return nil
})
Expand Down

0 comments on commit b70d4b0

Please sign in to comment.