Add Block + Uncle Rewards calculation
This commit is contained in:
parent
cb4e745464
commit
3ca4370221
36
integration_test/block_rewards_test.go
Normal file
36
integration_test/block_rewards_test.go
Normal file
@ -0,0 +1,36 @@
|
||||
package integration
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
cfg "github.com/8thlight/vulcanizedb/pkg/config"
|
||||
"github.com/8thlight/vulcanizedb/pkg/geth"
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
var _ = Describe("Reading contracts", 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 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))
|
||||
})
|
||||
})
|
||||
|
||||
})
|
@ -1,6 +1,7 @@
|
||||
package core
|
||||
|
||||
type Block struct {
|
||||
BlockReward float64
|
||||
Difficulty int64
|
||||
ExtraData string
|
||||
GasLimit int64
|
||||
@ -15,4 +16,5 @@ type Block struct {
|
||||
Time int64
|
||||
Transactions []Transaction
|
||||
UncleHash string
|
||||
UncleReward float64
|
||||
}
|
||||
|
54
pkg/geth/geth_block_rewards.go
Normal file
54
pkg/geth/geth_block_rewards.go
Normal file
@ -0,0 +1,54 @@
|
||||
package geth
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
)
|
||||
|
||||
func UncleReward(gethBlock *types.Block, client GethClient) float64 {
|
||||
var uncleReward float64
|
||||
for _, uncle := range gethBlock.Uncles() {
|
||||
staticBlockReward := float64(blockNumberStaticReward(gethBlock)) / float64(8)
|
||||
uncleReward += float64(uncle.Number.Int64()-gethBlock.Number().Int64()+int64(8)) * staticBlockReward
|
||||
}
|
||||
return uncleReward
|
||||
}
|
||||
|
||||
func BlockReward(gethBlock *types.Block, client GethClient) float64 {
|
||||
staticBlockReward := blockNumberStaticReward(gethBlock)
|
||||
transactionFees := calcTransactionFees(gethBlock, client)
|
||||
uncleInclusionRewards := uncleInclusionRewards(gethBlock, staticBlockReward)
|
||||
return transactionFees + uncleInclusionRewards + staticBlockReward
|
||||
}
|
||||
|
||||
func uncleInclusionRewards(gethBlock *types.Block, staticBlockReward float64) float64 {
|
||||
var uncleInclusionRewards float64
|
||||
for range gethBlock.Uncles() {
|
||||
uncleInclusionRewards += staticBlockReward * 1 / 32
|
||||
}
|
||||
return uncleInclusionRewards
|
||||
}
|
||||
|
||||
func calcTransactionFees(gethBlock *types.Block, client GethClient) float64 {
|
||||
var transactionFees float64
|
||||
for _, transaction := range gethBlock.Transactions() {
|
||||
receipt, err := client.TransactionReceipt(context.Background(), transaction.Hash())
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
transactionFees += float64(transaction.GasPrice().Int64() * receipt.GasUsed.Int64())
|
||||
}
|
||||
return transactionFees / params.Ether
|
||||
}
|
||||
|
||||
func blockNumberStaticReward(gethBlock *types.Block) float64 {
|
||||
var staticBlockReward float64
|
||||
if gethBlock.Number().Int64() > 4269999 {
|
||||
staticBlockReward = 3
|
||||
} else {
|
||||
staticBlockReward = 5
|
||||
}
|
||||
return staticBlockReward
|
||||
}
|
@ -12,6 +12,7 @@ import (
|
||||
|
||||
type GethClient interface {
|
||||
TransactionSender(ctx context.Context, tx *types.Transaction, block common.Hash, index uint) (common.Address, error)
|
||||
TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error)
|
||||
}
|
||||
|
||||
func GethBlockToCoreBlock(gethBlock *types.Block, client GethClient) core.Block {
|
||||
@ -21,6 +22,8 @@ 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)
|
||||
return core.Block{
|
||||
Difficulty: gethBlock.Difficulty().Int64(),
|
||||
GasLimit: gethBlock.GasLimit().Int64(),
|
||||
@ -34,7 +37,9 @@ func GethBlockToCoreBlock(gethBlock *types.Block, client GethClient) core.Block
|
||||
Size: gethBlock.Size().Int64(),
|
||||
Time: gethBlock.Time().Int64(),
|
||||
Transactions: transactions,
|
||||
BlockReward: blockReward,
|
||||
UncleHash: gethBlock.UncleHash().Hex(),
|
||||
UncleReward: uncleReward,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,28 @@ import (
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
type FakeGethClient struct{}
|
||||
type FakeGethClient struct {
|
||||
receipts map[string]*types.Receipt
|
||||
}
|
||||
|
||||
func NewFakeClient() *FakeGethClient {
|
||||
return &FakeGethClient{
|
||||
receipts: make(map[string]*types.Receipt),
|
||||
}
|
||||
}
|
||||
|
||||
func (client *FakeGethClient) AddReceipts(receipts []*types.Receipt) {
|
||||
for _, receipt := range receipts {
|
||||
client.receipts[receipt.TxHash.Hex()] = receipt
|
||||
}
|
||||
}
|
||||
|
||||
func (client *FakeGethClient) TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) {
|
||||
if gasUsed, ok := client.receipts[txHash.Hex()]; ok {
|
||||
return gasUsed, nil
|
||||
}
|
||||
return &types.Receipt{GasUsed: big.NewInt(0)}, nil
|
||||
}
|
||||
|
||||
func (client *FakeGethClient) TransactionSender(ctx context.Context, tx *types.Transaction, block common.Hash, index uint) (common.Address, error) {
|
||||
return common.HexToAddress("0x123"), nil
|
||||
@ -62,6 +83,103 @@ 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)
|
||||
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.BlockReward(block, client)).To(Equal(5.31355))
|
||||
})
|
||||
|
||||
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
|
||||
|
||||
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)
|
||||
|
||||
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)}
|
||||
receipts := []*types.Receipt{&receiptOne, &receiptTwo}
|
||||
|
||||
header := types.Header{
|
||||
Number: big.NewInt(number),
|
||||
}
|
||||
block := types.NewBlock(&header, transactions, uncles, receipts)
|
||||
|
||||
client := NewFakeClient()
|
||||
client.AddReceipts(receipts)
|
||||
|
||||
Expect(geth.BlockReward(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() {
|
||||
It("is empty", func() {
|
||||
header := types.Header{}
|
||||
@ -72,7 +190,7 @@ var _ = Describe("Conversion of GethBlock to core.Block", func() {
|
||||
Expect(len(coreBlock.Transactions)).To(Equal(0))
|
||||
})
|
||||
|
||||
It("converts a single transations", func() {
|
||||
It("converts a single transaction", func() {
|
||||
nonce := uint64(10000)
|
||||
header := types.Header{}
|
||||
to := common.Address{1}
|
||||
@ -82,7 +200,9 @@ var _ = Describe("Conversion of GethBlock to core.Block", func() {
|
||||
payload := []byte("1234")
|
||||
|
||||
gethTransaction := types.NewTransaction(nonce, to, amount, gasLimit, gasPrice, payload)
|
||||
client := &FakeGethClient{}
|
||||
|
||||
client := NewFakeClient()
|
||||
|
||||
gethBlock := types.NewBlock(&header, []*types.Transaction{gethTransaction}, []*types.Header{}, []*types.Receipt{})
|
||||
coreBlock := geth.GethBlockToCoreBlock(gethBlock, client)
|
||||
|
||||
@ -100,8 +220,8 @@ var _ = Describe("Conversion of GethBlock to core.Block", func() {
|
||||
It("has an empty to field when transaction creates a new contract", func() {
|
||||
gethTransaction := types.NewContractCreation(uint64(10000), big.NewInt(10), big.NewInt(5000), big.NewInt(3), []byte("1234"))
|
||||
gethBlock := types.NewBlock(&types.Header{}, []*types.Transaction{gethTransaction}, []*types.Header{}, []*types.Receipt{})
|
||||
client := &FakeGethClient{}
|
||||
|
||||
client := NewFakeClient()
|
||||
coreBlock := geth.GethBlockToCoreBlock(gethBlock, client)
|
||||
|
||||
coreTransaction := coreBlock.Transactions[0]
|
||||
|
Loading…
Reference in New Issue
Block a user