Merge pull request #47 from vulcanize/track_uncle_rewards
Track uncle rewards + direct balance polling
This commit is contained in:
@@ -19,9 +19,9 @@ package repositories
|
||||
import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/jmoiron/sqlx"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/vulcanize/vulcanizedb/libraries/shared/utilities"
|
||||
|
||||
"github.com/vulcanize/vulcanizedb/pkg/core"
|
||||
"github.com/vulcanize/vulcanizedb/pkg/datastore"
|
||||
@@ -90,13 +90,13 @@ func (blockRepository BlockRepository) GetBlock(blockNumber int64) (core.Block,
|
||||
blockRows := blockRepository.database.QueryRowx(
|
||||
`SELECT id,
|
||||
number,
|
||||
gaslimit,
|
||||
gasused,
|
||||
gas_limit,
|
||||
gas_used,
|
||||
time,
|
||||
difficulty,
|
||||
hash,
|
||||
nonce,
|
||||
parenthash,
|
||||
parent_hash,
|
||||
size,
|
||||
uncle_hash,
|
||||
is_final,
|
||||
@@ -127,10 +127,26 @@ func (blockRepository BlockRepository) insertBlock(block core.Block) (int64, err
|
||||
}
|
||||
insertBlockErr := tx.QueryRow(
|
||||
`INSERT INTO blocks
|
||||
(eth_node_id, number, gaslimit, gasused, time, difficulty, hash, nonce, parenthash, size, uncle_hash, is_final, miner, extra_data, reward, uncles_reward, eth_node_fingerprint)
|
||||
(eth_node_id, number, gas_limit, gas_used, time, difficulty, hash, nonce, parent_hash, size, uncle_hash, is_final, miner, extra_data, reward, uncles_reward, eth_node_fingerprint)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17)
|
||||
RETURNING id `,
|
||||
blockRepository.database.NodeID, block.Number, block.GasLimit, block.GasUsed, block.Time, block.Difficulty, block.Hash, block.Nonce, block.ParentHash, block.Size, block.UncleHash, block.IsFinal, block.Miner, block.ExtraData, block.Reward, block.UnclesReward, blockRepository.database.Node.ID).
|
||||
blockRepository.database.NodeID,
|
||||
block.Number,
|
||||
block.GasLimit,
|
||||
block.GasUsed,
|
||||
block.Time,
|
||||
block.Difficulty,
|
||||
block.Hash,
|
||||
block.Nonce,
|
||||
block.ParentHash,
|
||||
block.Size,
|
||||
block.UncleHash,
|
||||
block.IsFinal,
|
||||
block.Miner,
|
||||
block.ExtraData,
|
||||
utilities.NullToZero(block.Reward),
|
||||
utilities.NullToZero(block.UnclesReward),
|
||||
blockRepository.database.Node.ID).
|
||||
Scan(&blockId)
|
||||
if insertBlockErr != nil {
|
||||
rollbackErr := tx.Rollback()
|
||||
@@ -139,6 +155,13 @@ func (blockRepository BlockRepository) insertBlock(block core.Block) (int64, err
|
||||
}
|
||||
return 0, postgres.ErrDBInsertFailed(insertBlockErr)
|
||||
}
|
||||
if len(block.Uncles) > 0 {
|
||||
insertUncleErr := blockRepository.createUncles(tx, blockId, block.Hash, block.Uncles)
|
||||
if insertUncleErr != nil {
|
||||
tx.Rollback()
|
||||
return 0, postgres.ErrDBInsertFailed(insertUncleErr)
|
||||
}
|
||||
}
|
||||
if len(block.Transactions) > 0 {
|
||||
insertTxErr := blockRepository.createTransactions(tx, blockId, block.Transactions)
|
||||
if insertTxErr != nil {
|
||||
@@ -160,6 +183,26 @@ func (blockRepository BlockRepository) insertBlock(block core.Block) (int64, err
|
||||
return blockId, nil
|
||||
}
|
||||
|
||||
func (blockRepository BlockRepository) createUncles(tx *sqlx.Tx, blockId int64, blockHash string, uncles []core.Uncle) error {
|
||||
for _, uncle := range uncles {
|
||||
err := blockRepository.createUncle(tx, blockId, uncle)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (blockRepository BlockRepository) createUncle(tx *sqlx.Tx, blockId int64, uncle core.Uncle) error {
|
||||
_, err := tx.Exec(
|
||||
`INSERT INTO uncles
|
||||
(hash, block_id, reward, miner, raw, block_timestamp, eth_node_id, eth_node_fingerprint)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7::NUMERIC, $8)
|
||||
RETURNING id`,
|
||||
uncle.Hash, blockId, utilities.NullToZero(uncle.Reward), uncle.Miner, uncle.Raw, uncle.Timestamp, blockRepository.database.NodeID, blockRepository.database.Node.ID)
|
||||
return err
|
||||
}
|
||||
|
||||
func (blockRepository BlockRepository) createTransactions(tx *sqlx.Tx, blockId int64, transactions []core.TransactionModel) error {
|
||||
for _, transaction := range transactions {
|
||||
err := blockRepository.createTransaction(tx, blockId, transaction)
|
||||
@@ -183,10 +226,10 @@ func nullStringToZero(s string) string {
|
||||
func (blockRepository BlockRepository) createTransaction(tx *sqlx.Tx, blockId int64, transaction core.TransactionModel) error {
|
||||
_, err := tx.Exec(
|
||||
`INSERT INTO full_sync_transactions
|
||||
(block_id, gaslimit, gasprice, hash, input_data, nonce, raw, tx_from, tx_index, tx_to, "value")
|
||||
(block_id, gas_limit, gas_price, hash, input_data, nonce, raw, tx_from, tx_index, tx_to, "value")
|
||||
VALUES ($1, $2::NUMERIC, $3::NUMERIC, $4, $5, $6::NUMERIC, $7, $8, $9::NUMERIC, $10, $11::NUMERIC)
|
||||
RETURNING id`, blockId, transaction.GasLimit, transaction.GasPrice, transaction.Hash, transaction.Data,
|
||||
transaction.Nonce, transaction.Raw, transaction.From, transaction.TxIndex, transaction.To, transaction.Value)
|
||||
transaction.Nonce, transaction.Raw, transaction.From, transaction.TxIndex, transaction.To, nullStringToZero(transaction.Value))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -282,8 +325,8 @@ func (blockRepository BlockRepository) loadBlock(blockRows *sqlx.Row) (core.Bloc
|
||||
}
|
||||
transactionRows, err := blockRepository.database.Queryx(`
|
||||
SELECT hash,
|
||||
gaslimit,
|
||||
gasprice,
|
||||
gas_limit,
|
||||
gas_price,
|
||||
input_data,
|
||||
nonce,
|
||||
raw,
|
||||
|
||||
@@ -84,8 +84,8 @@ var _ = Describe("Saving blocks", func() {
|
||||
uncleHash := "x789"
|
||||
blockSize := string("1000")
|
||||
difficulty := int64(10)
|
||||
blockReward := float64(5.132)
|
||||
unclesReward := float64(3.580)
|
||||
blockReward := "5132000000000000000"
|
||||
unclesReward := "3580000000000000000"
|
||||
block := core.Block{
|
||||
Reward: blockReward,
|
||||
Difficulty: difficulty,
|
||||
@@ -158,6 +158,72 @@ var _ = Describe("Saving blocks", func() {
|
||||
Expect(len(savedBlock.Transactions)).To(Equal(2))
|
||||
})
|
||||
|
||||
It("saves one uncle associated to the block", func() {
|
||||
block := core.Block{
|
||||
Hash: fakes.FakeHash.String(),
|
||||
Number: 123,
|
||||
Transactions: []core.TransactionModel{fakes.FakeTransaction},
|
||||
Uncles: []core.Uncle{fakes.GetFakeUncle(common.BytesToHash([]byte{1, 2, 3}).String(), "100000")},
|
||||
UnclesReward: "156250000000000000",
|
||||
}
|
||||
|
||||
id, insertErr := blockRepository.CreateOrUpdateBlock(block)
|
||||
|
||||
Expect(insertErr).NotTo(HaveOccurred())
|
||||
savedBlock, getErr := blockRepository.GetBlock(123)
|
||||
Expect(getErr).NotTo(HaveOccurred())
|
||||
Expect(len(savedBlock.Transactions)).To(Equal(1))
|
||||
Expect(savedBlock.UnclesReward).To(Equal(big.NewInt(0).Div(big.NewInt(5000000000000000000), big.NewInt(32)).String()))
|
||||
|
||||
var uncleModel core.Uncle
|
||||
err := db.Get(&uncleModel, `SELECT hash, reward, miner, raw, block_timestamp FROM uncles
|
||||
WHERE block_id = $1 AND hash = $2`, id, common.BytesToHash([]byte{1, 2, 3}).Hex())
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(uncleModel.Hash).To(Equal(common.BytesToHash([]byte{1, 2, 3}).Hex()))
|
||||
Expect(uncleModel.Reward).To(Equal("100000"))
|
||||
Expect(uncleModel.Miner).To(Equal(fakes.FakeAddress.Hex()))
|
||||
Expect(uncleModel.Timestamp).To(Equal("111111111"))
|
||||
})
|
||||
|
||||
It("saves two uncles associated to the block", func() {
|
||||
block := core.Block{
|
||||
Hash: fakes.FakeHash.String(),
|
||||
Number: 123,
|
||||
Transactions: []core.TransactionModel{fakes.FakeTransaction},
|
||||
Uncles: []core.Uncle{
|
||||
fakes.GetFakeUncle(common.BytesToHash([]byte{1, 2, 3}).String(), "100000"),
|
||||
fakes.GetFakeUncle(common.BytesToHash([]byte{3, 2, 1}).String(), "90000")},
|
||||
UnclesReward: "312500000000000000",
|
||||
}
|
||||
|
||||
id, insertErr := blockRepository.CreateOrUpdateBlock(block)
|
||||
|
||||
Expect(insertErr).NotTo(HaveOccurred())
|
||||
savedBlock, getErr := blockRepository.GetBlock(123)
|
||||
Expect(getErr).NotTo(HaveOccurred())
|
||||
Expect(len(savedBlock.Transactions)).To(Equal(1))
|
||||
b := new(big.Int)
|
||||
b.SetString("10000000000000000000", 10)
|
||||
Expect(savedBlock.UnclesReward).To(Equal(big.NewInt(0).Div(b, big.NewInt(32)).String()))
|
||||
|
||||
var uncleModel core.Uncle
|
||||
err := db.Get(&uncleModel, `SELECT hash, reward, miner, raw, block_timestamp FROM uncles
|
||||
WHERE block_id = $1 AND hash = $2`, id, common.BytesToHash([]byte{1, 2, 3}).Hex())
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(uncleModel.Hash).To(Equal(common.BytesToHash([]byte{1, 2, 3}).Hex()))
|
||||
Expect(uncleModel.Reward).To(Equal("100000"))
|
||||
Expect(uncleModel.Miner).To(Equal(fakes.FakeAddress.Hex()))
|
||||
Expect(uncleModel.Timestamp).To(Equal("111111111"))
|
||||
|
||||
err = db.Get(&uncleModel, `SELECT hash, reward, miner, raw, block_timestamp FROM uncles
|
||||
WHERE block_id = $1 AND hash = $2`, id, common.BytesToHash([]byte{3, 2, 1}).Hex())
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(uncleModel.Hash).To(Equal(common.BytesToHash([]byte{3, 2, 1}).Hex()))
|
||||
Expect(uncleModel.Reward).To(Equal("90000"))
|
||||
Expect(uncleModel.Miner).To(Equal(fakes.FakeAddress.Hex()))
|
||||
Expect(uncleModel.Timestamp).To(Equal("111111111"))
|
||||
})
|
||||
|
||||
It(`replaces blocks and transactions associated to the block
|
||||
when a more new block is in conflict (same block number + nodeid)`, func() {
|
||||
blockOne := core.Block{
|
||||
|
||||
@@ -82,8 +82,8 @@ func (contractRepository ContractRepository) addTransactions(contract core.Contr
|
||||
nonce,
|
||||
tx_to,
|
||||
tx_from,
|
||||
gaslimit,
|
||||
gasprice,
|
||||
gas_limit,
|
||||
gas_price,
|
||||
value,
|
||||
input_data
|
||||
FROM full_sync_transactions
|
||||
|
||||
@@ -52,7 +52,7 @@ func (repository HeaderRepository) CreateOrUpdateHeader(header core.Header) (int
|
||||
func (repository HeaderRepository) CreateTransactions(headerID int64, transactions []core.TransactionModel) error {
|
||||
for _, transaction := range transactions {
|
||||
_, err := repository.database.Exec(`INSERT INTO public.light_sync_transactions
|
||||
(header_id, hash, gaslimit, gasprice, input_data, nonce, raw, tx_from, tx_index, tx_to, "value")
|
||||
(header_id, hash, gas_limit, gas_price, input_data, nonce, raw, tx_from, tx_index, tx_to, "value")
|
||||
VALUES ($1, $2, $3::NUMERIC, $4::NUMERIC, $5, $6::NUMERIC, $7, $8, $9::NUMERIC, $10, $11::NUMERIC)
|
||||
ON CONFLICT DO NOTHING`, headerID, transaction.Hash, transaction.GasLimit, transaction.GasPrice,
|
||||
transaction.Data, transaction.Nonce, transaction.Raw, transaction.From, transaction.TxIndex, transaction.To,
|
||||
|
||||
@@ -226,7 +226,7 @@ var _ = Describe("Block header repository", func() {
|
||||
It("adds transactions", func() {
|
||||
var dbTransactions []core.TransactionModel
|
||||
err = db.Select(&dbTransactions,
|
||||
`SELECT hash, gaslimit, gasprice, input_data, nonce, raw, tx_from, tx_index, tx_to, "value"
|
||||
`SELECT hash, gas_limit, gas_price, input_data, nonce, raw, tx_from, tx_index, tx_to, "value"
|
||||
FROM public.light_sync_transactions WHERE header_id = $1`, headerID)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(dbTransactions).To(ConsistOf(transactions))
|
||||
@@ -238,7 +238,7 @@ var _ = Describe("Block header repository", func() {
|
||||
|
||||
var dbTransactions []core.TransactionModel
|
||||
err = db.Select(&dbTransactions,
|
||||
`SELECT hash, gaslimit, gasprice, input_data, nonce, raw, tx_from, tx_index, tx_to, "value"
|
||||
`SELECT hash, gas_limit, gas_price, input_data, nonce, raw, tx_from, tx_index, tx_to, "value"
|
||||
FROM public.light_sync_transactions WHERE header_id = $1`, headerID)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(len(dbTransactions)).To(Equal(2))
|
||||
|
||||
Reference in New Issue
Block a user