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
|
package core
|
||||||
|
|
||||||
type Block struct {
|
type Block struct {
|
||||||
|
BlockReward float64
|
||||||
Difficulty int64
|
Difficulty int64
|
||||||
ExtraData string
|
ExtraData string
|
||||||
GasLimit int64
|
GasLimit int64
|
||||||
@ -15,4 +16,5 @@ type Block struct {
|
|||||||
Time int64
|
Time int64
|
||||||
Transactions []Transaction
|
Transactions []Transaction
|
||||||
UncleHash string
|
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 {
|
type GethClient interface {
|
||||||
TransactionSender(ctx context.Context, tx *types.Transaction, block common.Hash, index uint) (common.Address, error)
|
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 {
|
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)
|
transaction := gethTransToCoreTrans(gethTransaction, &from)
|
||||||
transactions = append(transactions, transaction)
|
transactions = append(transactions, transaction)
|
||||||
}
|
}
|
||||||
|
blockReward := BlockReward(gethBlock, client)
|
||||||
|
uncleReward := UncleReward(gethBlock, client)
|
||||||
return core.Block{
|
return core.Block{
|
||||||
Difficulty: gethBlock.Difficulty().Int64(),
|
Difficulty: gethBlock.Difficulty().Int64(),
|
||||||
GasLimit: gethBlock.GasLimit().Int64(),
|
GasLimit: gethBlock.GasLimit().Int64(),
|
||||||
@ -34,7 +37,9 @@ func GethBlockToCoreBlock(gethBlock *types.Block, client GethClient) core.Block
|
|||||||
Size: gethBlock.Size().Int64(),
|
Size: gethBlock.Size().Int64(),
|
||||||
Time: gethBlock.Time().Int64(),
|
Time: gethBlock.Time().Int64(),
|
||||||
Transactions: transactions,
|
Transactions: transactions,
|
||||||
|
BlockReward: blockReward,
|
||||||
UncleHash: gethBlock.UncleHash().Hex(),
|
UncleHash: gethBlock.UncleHash().Hex(),
|
||||||
|
UncleReward: uncleReward,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,7 +13,28 @@ import (
|
|||||||
. "github.com/onsi/gomega"
|
. "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) {
|
func (client *FakeGethClient) TransactionSender(ctx context.Context, tx *types.Transaction, block common.Hash, index uint) (common.Address, error) {
|
||||||
return common.HexToAddress("0x123"), nil
|
return common.HexToAddress("0x123"), nil
|
||||||
@ -62,6 +83,103 @@ var _ = Describe("Conversion of GethBlock to core.Block", func() {
|
|||||||
Expect(gethBlock.IsFinal).To(BeFalse())
|
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() {
|
Describe("the converted transations", func() {
|
||||||
It("is empty", func() {
|
It("is empty", func() {
|
||||||
header := types.Header{}
|
header := types.Header{}
|
||||||
@ -72,7 +190,7 @@ var _ = Describe("Conversion of GethBlock to core.Block", func() {
|
|||||||
Expect(len(coreBlock.Transactions)).To(Equal(0))
|
Expect(len(coreBlock.Transactions)).To(Equal(0))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("converts a single transations", func() {
|
It("converts a single transaction", func() {
|
||||||
nonce := uint64(10000)
|
nonce := uint64(10000)
|
||||||
header := types.Header{}
|
header := types.Header{}
|
||||||
to := common.Address{1}
|
to := common.Address{1}
|
||||||
@ -82,7 +200,9 @@ var _ = Describe("Conversion of GethBlock to core.Block", func() {
|
|||||||
payload := []byte("1234")
|
payload := []byte("1234")
|
||||||
|
|
||||||
gethTransaction := types.NewTransaction(nonce, to, amount, gasLimit, gasPrice, payload)
|
gethTransaction := types.NewTransaction(nonce, to, amount, gasLimit, gasPrice, payload)
|
||||||
client := &FakeGethClient{}
|
|
||||||
|
client := NewFakeClient()
|
||||||
|
|
||||||
gethBlock := types.NewBlock(&header, []*types.Transaction{gethTransaction}, []*types.Header{}, []*types.Receipt{})
|
gethBlock := types.NewBlock(&header, []*types.Transaction{gethTransaction}, []*types.Header{}, []*types.Receipt{})
|
||||||
coreBlock := geth.GethBlockToCoreBlock(gethBlock, client)
|
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() {
|
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"))
|
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{})
|
gethBlock := types.NewBlock(&types.Header{}, []*types.Transaction{gethTransaction}, []*types.Header{}, []*types.Receipt{})
|
||||||
client := &FakeGethClient{}
|
|
||||||
|
|
||||||
|
client := NewFakeClient()
|
||||||
coreBlock := geth.GethBlockToCoreBlock(gethBlock, client)
|
coreBlock := geth.GethBlockToCoreBlock(gethBlock, client)
|
||||||
|
|
||||||
coreTransaction := coreBlock.Transactions[0]
|
coreTransaction := coreBlock.Transactions[0]
|
||||||
|
Loading…
Reference in New Issue
Block a user