Remove pubsub and replace w/ polling head of chain (#122)

* Rename geth package structs to not be prefaced with package name

* No longer need to dump schema since Travis uses migrate

* Rearrange history package

* Removed double request for receipt from block rewards

* Remove Listener + Observers and Replace w/ Polling Head

* Potential Short term Issue w/ Infura (ignore these tests for now)
This commit is contained in:
Matt K
2018-01-05 11:55:00 -06:00
committed by GitHub
parent 095cb1e7b7
commit 6decf0b54b
38 changed files with 368 additions and 1034 deletions
+54
View File
@@ -0,0 +1,54 @@
package geth
import (
"github.com/8thlight/vulcanizedb/pkg/core"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
)
func CalcUnclesReward(block core.Block, uncles []*types.Header) float64 {
var unclesReward float64
for _, uncle := range uncles {
blockNumber := block.Number
staticBlockReward := float64(staticRewardByBlockNumber(blockNumber))
unclesReward += (1.0 + float64(uncle.Number.Int64()-block.Number)/8.0) * staticBlockReward
}
return unclesReward
}
func CalcBlockReward(block core.Block, uncles []*types.Header) float64 {
blockNumber := block.Number
staticBlockReward := staticRewardByBlockNumber(blockNumber)
transactionFees := calcTransactionFees(block)
uncleInclusionRewards := calcUncleInclusionRewards(block, uncles)
return transactionFees + uncleInclusionRewards + staticBlockReward
}
func calcTransactionFees(block core.Block) float64 {
var transactionFees float64
for _, transaction := range block.Transactions {
receipt := transaction.Receipt
transactionFees += float64(transaction.GasPrice * receipt.GasUsed)
}
return transactionFees / params.Ether
}
func calcUncleInclusionRewards(block core.Block, uncles []*types.Header) float64 {
var uncleInclusionRewards float64
staticBlockReward := staticRewardByBlockNumber(block.Number)
for range uncles {
uncleInclusionRewards += staticBlockReward * 1 / 32
}
return uncleInclusionRewards
}
func staticRewardByBlockNumber(blockNumber int64) float64 {
var staticBlockReward float64
//https://blog.ethereum.org/2017/10/12/byzantium-hf-announcement/
if blockNumber >= 4370000 {
staticBlockReward = 3
} else {
staticBlockReward = 5
}
return staticBlockReward
}
@@ -17,11 +17,9 @@ type GethClient interface {
TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error)
}
func GethBlockToCoreBlock(gethBlock *types.Block, client GethClient) core.Block {
transactions := convertGethTransactionsToCore(gethBlock, client)
blockReward := CalcBlockReward(gethBlock, client)
uncleReward := CalcUnclesReward(gethBlock)
return core.Block{
func ToCoreBlock(gethBlock *types.Block, client GethClient) core.Block {
transactions := convertTransactionsToCore(gethBlock, client)
coreBlock := core.Block{
Difficulty: gethBlock.Difficulty().Int64(),
ExtraData: hexutil.Encode(gethBlock.Extra()),
GasLimit: gethBlock.GasLimit().Int64(),
@@ -31,23 +29,24 @@ func GethBlockToCoreBlock(gethBlock *types.Block, client GethClient) core.Block
Nonce: hexutil.Encode(gethBlock.Header().Nonce[:]),
Number: gethBlock.Number().Int64(),
ParentHash: gethBlock.ParentHash().Hex(),
Reward: blockReward,
Size: gethBlock.Size().Int64(),
Time: gethBlock.Time().Int64(),
Transactions: transactions,
UncleHash: gethBlock.UncleHash().Hex(),
UnclesReward: uncleReward,
}
coreBlock.Reward = CalcBlockReward(coreBlock, gethBlock.Uncles())
coreBlock.UnclesReward = CalcUnclesReward(coreBlock, gethBlock.Uncles())
return coreBlock
}
func convertGethTransactionsToCore(gethBlock *types.Block, client GethClient) []core.Transaction {
func convertTransactionsToCore(gethBlock *types.Block, client GethClient) []core.Transaction {
transactions := make([]core.Transaction, 0)
for i, gethTransaction := range gethBlock.Transactions() {
from, err := client.TransactionSender(context.Background(), gethTransaction, gethBlock.Hash(), uint(i))
if err != nil {
log.Println(err)
}
transaction := gethTransToCoreTrans(gethTransaction, &from)
transaction := transToCoreTrans(gethTransaction, &from)
transaction, err = appendReceiptToTransaction(client, transaction)
if err != nil {
log.Println(err)
@@ -59,12 +58,12 @@ func convertGethTransactionsToCore(gethBlock *types.Block, client GethClient) []
func appendReceiptToTransaction(client GethClient, transaction core.Transaction) (core.Transaction, error) {
gethReceipt, err := client.TransactionReceipt(context.Background(), common.HexToHash(transaction.Hash))
receipt := GethReceiptToCoreReceipt(gethReceipt)
receipt := ReceiptToCoreReceipt(gethReceipt)
transaction.Receipt = receipt
return transaction, err
}
func gethTransToCoreTrans(transaction *types.Transaction, from *common.Address) core.Transaction {
func transToCoreTrans(transaction *types.Transaction, from *common.Address) core.Transaction {
data := hexutil.Encode(transaction.Data())
return core.Transaction{
Hash: transaction.Hash().Hex(),
@@ -66,7 +66,7 @@ var _ = Describe("Conversion of GethBlock to core.Block", func() {
}
block := types.NewBlock(&header, []*types.Transaction{}, []*types.Header{}, []*types.Receipt{})
client := &FakeGethClient{}
gethBlock := geth.GethBlockToCoreBlock(block, client)
gethBlock := geth.ToCoreBlock(block, client)
Expect(gethBlock.Difficulty).To(Equal(difficulty.Int64()))
Expect(gethBlock.GasLimit).To(Equal(gasLimit))
@@ -85,6 +85,7 @@ var _ = Describe("Conversion of GethBlock to core.Block", func() {
Describe("The block and uncle rewards calculations", func() {
It("calculates block rewards for a block", func() {
transaction := types.NewTransaction(
uint64(226823),
common.HexToAddress("0x108fedb097c1dcfed441480170144d8e19bb217f"),
@@ -96,20 +97,25 @@ var _ = Describe("Conversion of GethBlock to core.Block", func() {
transactions := []*types.Transaction{transaction}
txHash := transaction.Hash()
receipt := types.Receipt{TxHash: txHash, GasUsed: big.NewInt(21000)}
receipt := types.Receipt{
TxHash: txHash,
GasUsed: big.NewInt(21000),
CumulativeGasUsed: big.NewInt(21000),
}
receipts := []*types.Receipt{&receipt}
client := NewFakeClient()
client.AddReceipts(receipts)
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{})
block := types.NewBlock(&header, transactions, uncles, []*types.Receipt{&receipt})
coreBlock := geth.ToCoreBlock(block, client)
client := NewFakeClient()
client.AddReceipts(receipts)
Expect(geth.CalcBlockReward(block, client)).To(Equal(5.31355))
Expect(geth.CalcBlockReward(coreBlock, block.Uncles())).To(Equal(5.31355))
})
It("calculates the uncles reward for a block", func() {
@@ -123,8 +129,9 @@ var _ = Describe("Conversion of GethBlock to core.Block", func() {
transactions := []*types.Transaction{transaction}
receipt := types.Receipt{
TxHash: transaction.Hash(),
GasUsed: big.NewInt(21000),
TxHash: transaction.Hash(),
GasUsed: big.NewInt(21000),
CumulativeGasUsed: big.NewInt(21000),
}
receipts := []*types.Receipt{&receipt}
@@ -135,12 +142,14 @@ var _ = Describe("Conversion of GethBlock to core.Block", func() {
{Number: big.NewInt(1071816)},
{Number: big.NewInt(1071817)},
}
block := types.NewBlock(&header, transactions, uncles, []*types.Receipt{})
block := types.NewBlock(&header, transactions, uncles, receipts)
client := NewFakeClient()
client.AddReceipts(receipts)
Expect(geth.CalcUnclesReward(block)).To(Equal(6.875))
coreBlock := geth.ToCoreBlock(block, client)
Expect(geth.CalcUnclesReward(coreBlock, block.Uncles())).To(Equal(6.875))
})
It("decreases the static block reward from 5 to 3 for blocks after block 4,269,999", func() {
@@ -163,12 +172,14 @@ var _ = Describe("Conversion of GethBlock to core.Block", func() {
transactions := []*types.Transaction{transactionOne, transactionTwo}
receiptOne := types.Receipt{
TxHash: transactionOne.Hash(),
GasUsed: big.NewInt(297508),
TxHash: transactionOne.Hash(),
GasUsed: big.NewInt(297508),
CumulativeGasUsed: big.NewInt(0),
}
receiptTwo := types.Receipt{
TxHash: transactionTwo.Hash(),
GasUsed: big.NewInt(297508),
TxHash: transactionTwo.Hash(),
GasUsed: big.NewInt(297508),
CumulativeGasUsed: big.NewInt(0),
}
receipts := []*types.Receipt{&receiptOne, &receiptTwo}
@@ -181,8 +192,9 @@ var _ = Describe("Conversion of GethBlock to core.Block", func() {
client := NewFakeClient()
client.AddReceipts(receipts)
coreBlock := geth.ToCoreBlock(block, client)
Expect(geth.CalcBlockReward(block, client)).To(Equal(3.024990672))
Expect(geth.CalcBlockReward(coreBlock, block.Uncles())).To(Equal(3.024990672))
})
})
@@ -191,7 +203,7 @@ var _ = Describe("Conversion of GethBlock to core.Block", func() {
header := types.Header{}
block := types.NewBlock(&header, []*types.Transaction{}, []*types.Header{}, []*types.Receipt{})
client := &FakeGethClient{}
coreBlock := geth.GethBlockToCoreBlock(block, client)
coreBlock := geth.ToCoreBlock(block, client)
Expect(len(coreBlock.Transactions)).To(Equal(0))
})
@@ -225,7 +237,7 @@ var _ = Describe("Conversion of GethBlock to core.Block", func() {
[]*types.Header{},
[]*types.Receipt{gethReceipt},
)
coreBlock := geth.GethBlockToCoreBlock(gethBlock, client)
coreBlock := geth.ToCoreBlock(gethBlock, client)
Expect(len(coreBlock.Transactions)).To(Equal(1))
coreTransaction := coreBlock.Transactions[0]
@@ -238,7 +250,7 @@ var _ = Describe("Conversion of GethBlock to core.Block", func() {
Expect(coreTransaction.Nonce).To(Equal(gethTransaction.Nonce()))
coreReceipt := coreTransaction.Receipt
expectedReceipt := geth.GethReceiptToCoreReceipt(gethReceipt)
expectedReceipt := geth.ReceiptToCoreReceipt(gethReceipt)
Expect(coreReceipt).To(Equal(expectedReceipt))
})
@@ -269,13 +281,13 @@ var _ = Describe("Conversion of GethBlock to core.Block", func() {
[]*types.Receipt{gethReceipt},
)
coreBlock := geth.GethBlockToCoreBlock(gethBlock, client)
coreBlock := geth.ToCoreBlock(gethBlock, client)
coreTransaction := coreBlock.Transactions[0]
Expect(coreTransaction.To).To(Equal(""))
coreReceipt := coreTransaction.Receipt
expectedReceipt := geth.GethReceiptToCoreReceipt(gethReceipt)
expectedReceipt := geth.ReceiptToCoreReceipt(gethReceipt)
Expect(coreReceipt).To(Equal(expectedReceipt))
})
})
@@ -3,8 +3,6 @@ package geth
import (
"math/big"
"log"
"github.com/8thlight/vulcanizedb/pkg/core"
"github.com/8thlight/vulcanizedb/pkg/geth/node"
"github.com/ethereum/go-ethereum"
@@ -15,7 +13,7 @@ import (
"golang.org/x/net/context"
)
type GethBlockchain struct {
type Blockchain struct {
client *ethclient.Client
readGethHeaders chan *types.Header
outputBlocks chan core.Block
@@ -23,7 +21,16 @@ type GethBlockchain struct {
node core.Node
}
func (blockchain *GethBlockchain) GetLogs(contract core.Contract, startingBlockNumber *big.Int, endingBlockNumber *big.Int) ([]core.Log, error) {
func NewBlockchain(ipcPath string) *Blockchain {
blockchain := Blockchain{}
rpcClient, _ := rpc.Dial(ipcPath)
client := ethclient.NewClient(rpcClient)
blockchain.node = node.Retrieve(rpcClient)
blockchain.client = client
return &blockchain
}
func (blockchain *Blockchain) GetLogs(contract core.Contract, startingBlockNumber *big.Int, endingBlockNumber *big.Int) ([]core.Log, error) {
if endingBlockNumber == nil {
endingBlockNumber = startingBlockNumber
}
@@ -41,46 +48,16 @@ func (blockchain *GethBlockchain) GetLogs(contract core.Contract, startingBlockN
return logs, nil
}
func (blockchain *GethBlockchain) Node() core.Node {
func (blockchain *Blockchain) Node() core.Node {
return blockchain.node
}
func (blockchain *GethBlockchain) GetBlockByNumber(blockNumber int64) core.Block {
func (blockchain *Blockchain) GetBlockByNumber(blockNumber int64) core.Block {
gethBlock, _ := blockchain.client.BlockByNumber(context.Background(), big.NewInt(blockNumber))
return GethBlockToCoreBlock(gethBlock, blockchain.client)
return ToCoreBlock(gethBlock, blockchain.client)
}
func NewGethBlockchain(ipcPath string) *GethBlockchain {
blockchain := GethBlockchain{}
rpcClient, _ := rpc.Dial(ipcPath)
client := ethclient.NewClient(rpcClient)
blockchain.node = node.Retrieve(rpcClient)
blockchain.client = client
return &blockchain
}
func (blockchain *GethBlockchain) SubscribeToBlocks(blocks chan core.Block) {
blockchain.outputBlocks = blocks
log.Println("SubscribeToBlocks")
inputHeaders := make(chan *types.Header, 10)
myContext := context.Background()
blockchain.readGethHeaders = inputHeaders
subscription, _ := blockchain.client.SubscribeNewHead(myContext, inputHeaders)
blockchain.newHeadSubscription = subscription
}
func (blockchain *GethBlockchain) StartListening() {
for header := range blockchain.readGethHeaders {
block := blockchain.GetBlockByNumber(header.Number.Int64())
blockchain.outputBlocks <- block
}
}
func (blockchain *GethBlockchain) StopListening() {
blockchain.newHeadSubscription.Unsubscribe()
}
func (blockchain *GethBlockchain) LastBlock() *big.Int {
func (blockchain *Blockchain) LastBlock() *big.Int {
block, _ := blockchain.client.HeaderByNumber(context.Background(), nil)
return block.Number
}
+3 -3
View File
@@ -17,7 +17,7 @@ var (
ErrInvalidStateAttribute = errors.New("invalid state attribute")
)
func (blockchain *GethBlockchain) GetAttribute(contract core.Contract, attributeName string, blockNumber *big.Int) (interface{}, error) {
func (blockchain *Blockchain) GetAttribute(contract core.Contract, attributeName string, blockNumber *big.Int) (interface{}, error) {
parsed, err := ParseAbi(contract.Abi)
var result interface{}
if err != nil {
@@ -38,13 +38,13 @@ func (blockchain *GethBlockchain) GetAttribute(contract core.Contract, attribute
return result, nil
}
func callContract(contractHash string, input []byte, blockchain *GethBlockchain, blockNumber *big.Int) ([]byte, error) {
func callContract(contractHash string, input []byte, blockchain *Blockchain, blockNumber *big.Int) ([]byte, error) {
to := common.HexToAddress(contractHash)
msg := ethereum.CallMsg{To: &to, Data: input}
return blockchain.client.CallContract(context.Background(), msg, blockNumber)
}
func (blockchain *GethBlockchain) GetAttributes(contract core.Contract) (core.ContractAttributes, error) {
func (blockchain *Blockchain) GetAttributes(contract core.Contract) (core.ContractAttributes, error) {
parsed, _ := ParseAbi(contract.Abi)
var contractAttributes core.ContractAttributes
for _, abiElement := range parsed.Methods {
-58
View File
@@ -1,58 +0,0 @@
package geth
import (
"context"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
)
func CalcUnclesReward(gethBlock *types.Block) float64 {
var unclesReward float64
for _, uncle := range gethBlock.Uncles() {
blockNumber := gethBlock.Number().Int64()
staticBlockReward := float64(staticRewardByBlockNumber(blockNumber))
unclesReward += (1.0 + float64(uncle.Number.Int64()-gethBlock.Number().Int64())/8.0) * staticBlockReward
}
return unclesReward
}
func CalcBlockReward(gethBlock *types.Block, client GethClient) float64 {
blockNumber := gethBlock.Number().Int64()
staticBlockReward := staticRewardByBlockNumber(blockNumber)
transactionFees := calcTransactionFees(gethBlock, client)
uncleInclusionRewards := calcUncleInclusionRewards(gethBlock)
return transactionFees + uncleInclusionRewards + staticBlockReward
}
func calcUncleInclusionRewards(gethBlock *types.Block) float64 {
var uncleInclusionRewards float64
staticBlockReward := staticRewardByBlockNumber(gethBlock.Number().Int64())
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 staticRewardByBlockNumber(blockNumber int64) float64 {
var staticBlockReward float64
//https://blog.ethereum.org/2017/10/12/byzantium-hf-announcement/
if blockNumber >= 4370000 {
staticBlockReward = 3
} else {
staticBlockReward = 5
}
return staticBlockReward
}
@@ -6,7 +6,7 @@ import (
"github.com/ethereum/go-ethereum/core/types"
)
func GethLogToCoreLog(gethLog types.Log) core.Log {
func LogToCoreLog(gethLog types.Log) core.Log {
topics := gethLog.Topics
var hexTopics = make(map[int]string)
for i, topic := range topics {
@@ -26,7 +26,7 @@ func GethLogToCoreLog(gethLog types.Log) core.Log {
func GethLogsToCoreLogs(gethLogs []types.Log) []core.Log {
var logs []core.Log
for _, log := range gethLogs {
log := GethLogToCoreLog(log)
log := LogToCoreLog(log)
logs = append(logs, log)
}
return logs
@@ -39,7 +39,7 @@ var _ = Describe("Conversion of GethLog to core.Log", func() {
},
}
coreLog := geth.GethLogToCoreLog(gethLog)
coreLog := geth.LogToCoreLog(gethLog)
Expect(coreLog.Address).To(Equal(expected.Address))
Expect(coreLog.BlockNumber).To(Equal(expected.BlockNumber))
@@ -79,8 +79,8 @@ var _ = Describe("Conversion of GethLog to core.Log", func() {
},
}
expectedOne := geth.GethLogToCoreLog(gethLogOne)
expectedTwo := geth.GethLogToCoreLog(gethLogTwo)
expectedOne := geth.LogToCoreLog(gethLogOne)
expectedTwo := geth.LogToCoreLog(gethLogTwo)
coreLogs := geth.GethLogsToCoreLogs([]types.Log{gethLogOne, gethLogTwo})
@@ -18,7 +18,7 @@ func BigTo64(n *big.Int) int64 {
return 0
}
func GethReceiptToCoreReceipt(gethReceipt *types.Receipt) core.Receipt {
func ReceiptToCoreReceipt(gethReceipt *types.Receipt) core.Receipt {
bloom := hexutil.Encode(gethReceipt.Bloom.Bytes())
var postState string
var status int
@@ -49,7 +49,7 @@ func setContractAddress(gethReceipt *types.Receipt) string {
func dereferenceLogs(gethReceipt *types.Receipt) []core.Log {
logs := []core.Log{}
for _, log := range gethReceipt.Logs {
logs = append(logs, GethLogToCoreLog(*log))
logs = append(logs, LogToCoreLog(*log))
}
return logs
}
@@ -36,7 +36,7 @@ var _ = Describe("Conversion of GethReceipt to core.Receipt", func() {
TxHash: receipt.TxHash.Hex(),
}
coreReceipt := geth.GethReceiptToCoreReceipt(&receipt)
coreReceipt := geth.ReceiptToCoreReceipt(&receipt)
Expect(coreReceipt.Bloom).To(Equal(expected.Bloom))
Expect(coreReceipt.ContractAddress).To(Equal(expected.ContractAddress))
Expect(coreReceipt.CumulativeGasUsed).To(Equal(expected.CumulativeGasUsed))
@@ -70,7 +70,7 @@ var _ = Describe("Conversion of GethReceipt to core.Receipt", func() {
TxHash: receipt.TxHash.Hex(),
}
coreReceipt := geth.GethReceiptToCoreReceipt(&receipt)
coreReceipt := geth.ReceiptToCoreReceipt(&receipt)
Expect(coreReceipt.Bloom).To(Equal(expected.Bloom))
Expect(coreReceipt.ContractAddress).To(Equal(""))
Expect(coreReceipt.CumulativeGasUsed).To(Equal(expected.CumulativeGasUsed))