Add block rewards to db

This commit is contained in:
Matt Krump 2017-12-28 10:06:13 -06:00
parent 3ca4370221
commit 8b024bade9
10 changed files with 149 additions and 121 deletions

View File

@ -0,0 +1,3 @@
ALTER TABLE blocks
DROP COLUMN block_reward,
DROP COLUMN block_uncles_reward;

View File

@ -0,0 +1,3 @@
ALTER TABLE blocks
ADD COLUMN block_reward NUMERIC,
ADD COLUMN block_uncles_reward NUMERIC;

View File

@ -53,7 +53,9 @@ CREATE TABLE blocks (
node_id integer NOT NULL,
is_final boolean,
block_miner character varying(42),
block_extra_data character varying
block_extra_data character varying,
block_reward numeric,
block_uncles_reward numeric
);

View File

@ -9,28 +9,26 @@ import (
. "github.com/onsi/gomega"
)
var _ = Describe("Reading contracts", func() {
var _ = Describe("Rewards calculations", func() {
Describe("Block and Uncle rewards", func() {
It("calculates a block reward for a real block", func() {
config, err := cfg.NewConfig("infura")
if err != nil {
log.Fatalln(err)
}
blockchain := geth.NewGethBlockchain(config.Client.IPCPath)
block := blockchain.GetBlockByNumber(1071819)
Expect(block.BlockReward).To(Equal(5.31355))
})
It("calculates a block reward for a real block", func() {
config, err := cfg.NewConfig("infura")
if err != nil {
log.Fatalln(err)
}
blockchain := geth.NewGethBlockchain(config.Client.IPCPath)
block := blockchain.GetBlockByNumber(1071819)
Expect(block.Reward).To(Equal(5.31355))
})
It("calculates an uncle reward for a real block", func() {
config, err := cfg.NewConfig("infura")
if err != nil {
log.Fatalln(err)
}
blockchain := geth.NewGethBlockchain(config.Client.IPCPath)
block := blockchain.GetBlockByNumber(1071819)
Expect(block.UncleReward).To(Equal(6.875))
})
It("calculates an uncle reward for a real block", func() {
config, err := cfg.NewConfig("infura")
if err != nil {
log.Fatalln(err)
}
blockchain := geth.NewGethBlockchain(config.Client.IPCPath)
block := blockchain.GetBlockByNumber(1071819)
Expect(block.UnclesReward).To(Equal(6.875))
})
})

View File

@ -1,7 +1,7 @@
package core
type Block struct {
BlockReward float64
Reward float64
Difficulty int64
ExtraData string
GasLimit int64
@ -16,5 +16,5 @@ type Block struct {
Time int64
Transactions []Transaction
UncleHash string
UncleReward float64
UnclesReward float64
}

View File

@ -7,24 +7,27 @@ import (
"github.com/ethereum/go-ethereum/params"
)
func UncleReward(gethBlock *types.Block, client GethClient) float64 {
var uncleReward float64
func CalcUnclesReward(gethBlock *types.Block) float64 {
var unclesReward float64
for _, uncle := range gethBlock.Uncles() {
staticBlockReward := float64(blockNumberStaticReward(gethBlock)) / float64(8)
uncleReward += float64(uncle.Number.Int64()-gethBlock.Number().Int64()+int64(8)) * staticBlockReward
blockNumber := gethBlock.Number().Int64()
staticBlockReward := float64(staticRewardByBlockNumber(blockNumber))
unclesReward += (1.0 + float64(uncle.Number.Int64()-gethBlock.Number().Int64())/8.0) * staticBlockReward
}
return uncleReward
return unclesReward
}
func BlockReward(gethBlock *types.Block, client GethClient) float64 {
staticBlockReward := blockNumberStaticReward(gethBlock)
func CalcBlockReward(gethBlock *types.Block, client GethClient) float64 {
blockNumber := gethBlock.Number().Int64()
staticBlockReward := staticRewardByBlockNumber(blockNumber)
transactionFees := calcTransactionFees(gethBlock, client)
uncleInclusionRewards := uncleInclusionRewards(gethBlock, staticBlockReward)
uncleInclusionRewards := calcUncleInclusionRewards(gethBlock)
return transactionFees + uncleInclusionRewards + staticBlockReward
}
func uncleInclusionRewards(gethBlock *types.Block, staticBlockReward float64) float64 {
func calcUncleInclusionRewards(gethBlock *types.Block) float64 {
var uncleInclusionRewards float64
staticBlockReward := staticRewardByBlockNumber(gethBlock.Number().Int64())
for range gethBlock.Uncles() {
uncleInclusionRewards += staticBlockReward * 1 / 32
}
@ -43,9 +46,10 @@ func calcTransactionFees(gethBlock *types.Block, client GethClient) float64 {
return transactionFees / params.Ether
}
func blockNumberStaticReward(gethBlock *types.Block) float64 {
func staticRewardByBlockNumber(blockNumber int64) float64 {
var staticBlockReward float64
if gethBlock.Number().Int64() > 4269999 {
//https://blog.ethereum.org/2017/10/12/byzantium-hf-announcement/
if blockNumber >= 4370000 {
staticBlockReward = 3
} else {
staticBlockReward = 5

View File

@ -22,24 +22,24 @@ func GethBlockToCoreBlock(gethBlock *types.Block, client GethClient) core.Block
transaction := gethTransToCoreTrans(gethTransaction, &from)
transactions = append(transactions, transaction)
}
blockReward := BlockReward(gethBlock, client)
uncleReward := UncleReward(gethBlock, client)
blockReward := CalcBlockReward(gethBlock, client)
uncleReward := CalcUnclesReward(gethBlock)
return core.Block{
Difficulty: gethBlock.Difficulty().Int64(),
ExtraData: hexutil.Encode(gethBlock.Extra()),
GasLimit: gethBlock.GasLimit().Int64(),
GasUsed: gethBlock.GasUsed().Int64(),
Hash: gethBlock.Hash().Hex(),
ExtraData: hexutil.Encode(gethBlock.Extra()),
Miner: gethBlock.Coinbase().Hex(),
Nonce: hexutil.Encode(gethBlock.Header().Nonce[:]),
Number: gethBlock.Number().Int64(),
Miner: gethBlock.Coinbase().Hex(),
ParentHash: gethBlock.ParentHash().Hex(),
Reward: blockReward,
Size: gethBlock.Size().Int64(),
Time: gethBlock.Time().Int64(),
Transactions: transactions,
BlockReward: blockReward,
UncleHash: gethBlock.UncleHash().Hex(),
UncleReward: uncleReward,
UnclesReward: uncleReward,
}
}

View File

@ -83,104 +83,110 @@ var _ = Describe("Conversion of GethBlock to core.Block", func() {
Expect(gethBlock.IsFinal).To(BeFalse())
})
Describe("the block and uncle rewards calculations", func() {
It("Calculates block rewards for a block", func() {
number := int64(1071819)
uncles := []*types.Header{{Number: big.NewInt(1071817)}, {Number: big.NewInt(1071818)}}
nonce := uint64(226823)
to := common.HexToAddress("0x108fedb097c1dcfed441480170144d8e19bb217f")
amount := big.NewInt(1080900090000000000)
gasLimit := big.NewInt(90000)
gasPrice := big.NewInt(50000000000)
var payload []byte
transaction := types.NewTransaction(nonce, to, amount, gasLimit, gasPrice, payload)
Describe("The block and uncle rewards calculations", func() {
It("calculates block rewards for a block", func() {
transaction := types.NewTransaction(
uint64(226823),
common.HexToAddress("0x108fedb097c1dcfed441480170144d8e19bb217f"),
big.NewInt(1080900090000000000),
big.NewInt(90000),
big.NewInt(50000000000),
[]byte{},
)
transactions := []*types.Transaction{transaction}
txHash := transaction.Hash()
receipt := types.Receipt{TxHash: txHash, GasUsed: big.NewInt(21000)}
receipts := []*types.Receipt{&receipt}
number := int64(1071819)
header := types.Header{
Number: big.NewInt(number),
}
uncles := []*types.Header{{Number: big.NewInt(1071817)}, {Number: big.NewInt(1071818)}}
block := types.NewBlock(&header, transactions, uncles, []*types.Receipt{})
client := NewFakeClient()
client.AddReceipts(receipts)
Expect(geth.CalcBlockReward(block, client)).To(Equal(5.31355))
})
It("calculates the uncles reward for a block", func() {
transaction := types.NewTransaction(
uint64(226823),
common.HexToAddress("0x108fedb097c1dcfed441480170144d8e19bb217f"),
big.NewInt(1080900090000000000),
big.NewInt(90000),
big.NewInt(50000000000),
[]byte{})
transactions := []*types.Transaction{transaction}
receipt := types.Receipt{
TxHash: transaction.Hash(),
GasUsed: big.NewInt(21000),
}
receipts := []*types.Receipt{&receipt}
header := types.Header{
Number: big.NewInt(int64(1071819)),
}
uncles := []*types.Header{
{Number: big.NewInt(1071816)},
{Number: big.NewInt(1071817)},
}
block := types.NewBlock(&header, transactions, uncles, []*types.Receipt{})
client := NewFakeClient()
client.AddReceipts(receipts)
Expect(geth.BlockReward(block, client)).To(Equal(5.31355))
Expect(geth.CalcUnclesReward(block)).To(Equal(6.875))
})
It("decreases the static block reward from 5 to 3 for blocks after block 4,269,999", func() {
number := int64(4370055)
var uncles []*types.Header
transactionOne := types.NewTransaction(
uint64(8072),
common.HexToAddress("0xebd17720aeb7ac5186c5dfa7bafeb0bb14c02551 "),
big.NewInt(0),
big.NewInt(500000),
big.NewInt(42000000000),
[]byte{},
)
nonce := uint64(8072)
to := common.HexToAddress("0xebd17720aeb7ac5186c5dfa7bafeb0bb14c02551 ")
amount := big.NewInt(0)
gasLimit := big.NewInt(500000)
gasPrice := big.NewInt(42000000000)
var payload []byte
transactionOne := types.NewTransaction(nonce, to, amount, gasLimit, gasPrice, payload)
nonce = uint64(8071)
to = common.HexToAddress("0x3cdab63d764c8c5048ed5e8f0a4e95534ba7e1ea")
amount = big.NewInt(0)
gasLimit = big.NewInt(500000)
gasPrice = big.NewInt(42000000000)
transactionTwo := types.NewTransaction(nonce, to, amount, gasLimit, gasPrice, payload)
transactionTwo := types.NewTransaction(uint64(8071),
common.HexToAddress("0x3cdab63d764c8c5048ed5e8f0a4e95534ba7e1ea"),
big.NewInt(0),
big.NewInt(500000),
big.NewInt(42000000000),
[]byte{})
transactions := []*types.Transaction{transactionOne, transactionTwo}
txHashOne := transactionOne.Hash()
receiptOne := types.Receipt{TxHash: txHashOne, GasUsed: big.NewInt(297508)}
txHashTwo := transactionTwo.Hash()
receiptTwo := types.Receipt{TxHash: txHashTwo, GasUsed: big.NewInt(297508)}
receiptOne := types.Receipt{
TxHash: transactionOne.Hash(),
GasUsed: big.NewInt(297508),
}
receiptTwo := types.Receipt{
TxHash: transactionTwo.Hash(),
GasUsed: big.NewInt(297508),
}
receipts := []*types.Receipt{&receiptOne, &receiptTwo}
number := int64(4370055)
header := types.Header{
Number: big.NewInt(number),
}
var uncles []*types.Header
block := types.NewBlock(&header, transactions, uncles, receipts)
client := NewFakeClient()
client.AddReceipts(receipts)
Expect(geth.BlockReward(block, client)).To(Equal(3.024990672))
Expect(geth.CalcBlockReward(block, client)).To(Equal(3.024990672))
})
It("Calculates uncle rewards for a block", func() {
number := int64(1071819)
uncles := []*types.Header{{Number: big.NewInt(1071816)}, {Number: big.NewInt(1071817)}}
nonce := uint64(226823)
to := common.HexToAddress("0x108fedb097c1dcfed441480170144d8e19bb217f")
amount := big.NewInt(1080900090000000000)
gasLimit := big.NewInt(90000)
gasPrice := big.NewInt(50000000000)
var payload []byte
transaction := types.NewTransaction(nonce, to, amount, gasLimit, gasPrice, payload)
transactions := []*types.Transaction{transaction}
txHash := transaction.Hash()
receipt := types.Receipt{TxHash: txHash, GasUsed: big.NewInt(21000)}
receipts := []*types.Receipt{&receipt}
header := types.Header{
Number: big.NewInt(number),
}
block := types.NewBlock(&header, transactions, uncles, []*types.Receipt{})
client := NewFakeClient()
client.AddReceipts(receipts)
Expect(geth.UncleReward(block, client)).To(Equal(6.875))
})
})
Describe("the converted transations", func() {
Describe("the converted transactions", func() {
It("is empty", func() {
header := types.Header{}
block := types.NewBlock(&header, []*types.Transaction{}, []*types.Header{}, []*types.Receipt{})

View File

@ -200,7 +200,9 @@ func (repository Postgres) FindBlockByNumber(blockNumber int64) (core.Block, err
uncle_hash,
is_final,
block_miner,
block_extra_data
block_extra_data,
block_reward,
block_uncles_reward
FROM blocks
WHERE node_id = $1 AND block_number = $2`, repository.nodeId, blockNumber)
savedBlock, err := repository.loadBlock(blockRows)
@ -258,10 +260,10 @@ func (repository Postgres) insertBlock(block core.Block) error {
tx, _ := repository.Db.BeginTx(context.Background(), nil)
err := tx.QueryRow(
`INSERT INTO blocks
(node_id, block_number, block_gaslimit, block_gasused, block_time, block_difficulty, block_hash, block_nonce, block_parenthash, block_size, uncle_hash, is_final, block_miner, block_extra_data)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14)
(node_id, block_number, block_gaslimit, block_gasused, block_time, block_difficulty, block_hash, block_nonce, block_parenthash, block_size, uncle_hash, is_final, block_miner, block_extra_data, block_reward, block_uncles_reward)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16)
RETURNING id `,
repository.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).
repository.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).
Scan(&blockId)
if err != nil {
tx.Rollback()
@ -312,12 +314,14 @@ func (repository Postgres) loadBlock(blockRows *sql.Row) (core.Block, error) {
var blockParentHash string
var blockSize int64
var blockTime float64
var blockReward float64
var difficulty int64
var gasLimit float64
var gasUsed float64
var uncleHash string
var unclesReward float64
var isFinal bool
err := blockRows.Scan(&blockId, &blockNumber, &gasLimit, &gasUsed, &blockTime, &difficulty, &blockHash, &blockNonce, &blockParentHash, &blockSize, &uncleHash, &isFinal, &blockMiner, &blockExtraData)
err := blockRows.Scan(&blockId, &blockNumber, &gasLimit, &gasUsed, &blockTime, &difficulty, &blockHash, &blockNonce, &blockParentHash, &blockSize, &uncleHash, &isFinal, &blockMiner, &blockExtraData, &blockReward, &unclesReward)
if err != nil {
return core.Block{}, err
}
@ -334,6 +338,7 @@ func (repository Postgres) loadBlock(blockRows *sql.Row) (core.Block, error) {
ORDER BY tx_hash`, blockId)
transactions := repository.loadTransactions(transactionRows)
return core.Block{
Reward: blockReward,
Difficulty: difficulty,
ExtraData: blockExtraData,
GasLimit: int64(gasLimit),
@ -348,6 +353,7 @@ func (repository Postgres) loadBlock(blockRows *sql.Row) (core.Block, error) {
Time: int64(blockTime),
Transactions: transactions,
UncleHash: uncleHash,
UnclesReward: unclesReward,
}, nil
}

View File

@ -67,25 +67,30 @@ func AssertRepositoryBehavior(buildRepository func(node core.Node) repositories.
uncleHash := "x789"
blockSize := int64(1000)
difficulty := int64(10)
blockReward := float64(5.132)
unclesReward := float64(3.580)
block := core.Block{
Difficulty: difficulty,
GasLimit: gasLimit,
GasUsed: gasUsed,
Hash: blockHash,
ExtraData: extraData,
Nonce: blockNonce,
Miner: miner,
Number: blockNumber,
ParentHash: blockParentHash,
Size: blockSize,
Time: blockTime,
UncleHash: uncleHash,
Reward: blockReward,
Difficulty: difficulty,
GasLimit: gasLimit,
GasUsed: gasUsed,
Hash: blockHash,
ExtraData: extraData,
Nonce: blockNonce,
Miner: miner,
Number: blockNumber,
ParentHash: blockParentHash,
Size: blockSize,
Time: blockTime,
UncleHash: uncleHash,
UnclesReward: unclesReward,
}
repository.CreateOrUpdateBlock(block)
savedBlock, err := repository.FindBlockByNumber(blockNumber)
Expect(err).NotTo(HaveOccurred())
Expect(savedBlock.Reward).To(Equal(blockReward))
Expect(savedBlock.Difficulty).To(Equal(difficulty))
Expect(savedBlock.GasLimit).To(Equal(gasLimit))
Expect(savedBlock.GasUsed).To(Equal(gasUsed))
@ -98,6 +103,7 @@ func AssertRepositoryBehavior(buildRepository func(node core.Node) repositories.
Expect(savedBlock.Size).To(Equal(blockSize))
Expect(savedBlock.Time).To(Equal(blockTime))
Expect(savedBlock.UncleHash).To(Equal(uncleHash))
Expect(savedBlock.UnclesReward).To(Equal(unclesReward))
})
It("does not find a block when searching for a number that does not exist", func() {