forked from cerc-io/ipld-eth-server
Handle headers from POA chain
- Fetching headers from Kovan requires custom type without mixHash/Nonce
This commit is contained in:
+42
-7
@@ -7,29 +7,32 @@ import (
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/vulcanize/vulcanizedb/pkg/core"
|
||||
vulcCommon "github.com/vulcanize/vulcanizedb/pkg/geth/converters/common"
|
||||
)
|
||||
|
||||
type BlockChain struct {
|
||||
client core.EthClient
|
||||
blockConverter vulcCommon.BlockConverter
|
||||
ethClient core.EthClient
|
||||
headerConverter vulcCommon.HeaderConverter
|
||||
node core.Node
|
||||
rpcClient core.RpcClient
|
||||
}
|
||||
|
||||
func NewBlockChain(client core.EthClient, node core.Node, converter vulcCommon.TransactionConverter) *BlockChain {
|
||||
func NewBlockChain(ethClient core.EthClient, rpcClient core.RpcClient, node core.Node, converter vulcCommon.TransactionConverter) *BlockChain {
|
||||
return &BlockChain{
|
||||
client: client,
|
||||
blockConverter: vulcCommon.NewBlockConverter(converter),
|
||||
ethClient: ethClient,
|
||||
headerConverter: vulcCommon.HeaderConverter{},
|
||||
node: node,
|
||||
rpcClient: rpcClient,
|
||||
}
|
||||
}
|
||||
|
||||
func (blockChain *BlockChain) GetBlockByNumber(blockNumber int64) (block core.Block, err error) {
|
||||
gethBlock, err := blockChain.client.BlockByNumber(context.Background(), big.NewInt(blockNumber))
|
||||
gethBlock, err := blockChain.ethClient.BlockByNumber(context.Background(), big.NewInt(blockNumber))
|
||||
if err != nil {
|
||||
return block, err
|
||||
}
|
||||
@@ -37,13 +40,45 @@ func (blockChain *BlockChain) GetBlockByNumber(blockNumber int64) (block core.Bl
|
||||
}
|
||||
|
||||
func (blockChain *BlockChain) GetHeaderByNumber(blockNumber int64) (header core.Header, err error) {
|
||||
gethHeader, err := blockChain.client.HeaderByNumber(context.Background(), big.NewInt(blockNumber))
|
||||
if blockChain.node.NetworkID == core.KOVAN_NETWORK_ID {
|
||||
return blockChain.getPOAHeader(blockNumber)
|
||||
}
|
||||
return blockChain.getPOWHeader(blockNumber)
|
||||
}
|
||||
|
||||
func (blockChain *BlockChain) getPOWHeader(blockNumber int64) (header core.Header, err error) {
|
||||
gethHeader, err := blockChain.ethClient.HeaderByNumber(context.Background(), big.NewInt(blockNumber))
|
||||
if err != nil {
|
||||
return header, err
|
||||
}
|
||||
return blockChain.headerConverter.Convert(gethHeader)
|
||||
}
|
||||
|
||||
func (blockChain *BlockChain) getPOAHeader(blockNumber int64) (header core.Header, err error) {
|
||||
var POAHeader core.POAHeader
|
||||
blockNumberArg := hexutil.EncodeBig(big.NewInt(blockNumber))
|
||||
includeTransactions := false
|
||||
err = blockChain.rpcClient.CallContext(context.Background(), &POAHeader, "eth_getBlockByNumber", blockNumberArg, includeTransactions)
|
||||
if err != nil {
|
||||
return header, err
|
||||
}
|
||||
return blockChain.headerConverter.Convert(&types.Header{
|
||||
ParentHash: POAHeader.ParentHash,
|
||||
UncleHash: POAHeader.UncleHash,
|
||||
Coinbase: POAHeader.Coinbase,
|
||||
Root: POAHeader.Root,
|
||||
TxHash: POAHeader.TxHash,
|
||||
ReceiptHash: POAHeader.ReceiptHash,
|
||||
Bloom: POAHeader.Bloom,
|
||||
Difficulty: POAHeader.Difficulty.ToInt(),
|
||||
Number: POAHeader.Number.ToInt(),
|
||||
GasLimit: uint64(POAHeader.GasLimit),
|
||||
GasUsed: uint64(POAHeader.GasUsed),
|
||||
Time: POAHeader.Time.ToInt(),
|
||||
Extra: POAHeader.Extra,
|
||||
})
|
||||
}
|
||||
|
||||
func (blockChain *BlockChain) GetLogs(contract core.Contract, startingBlockNumber, endingBlockNumber *big.Int) ([]core.Log, error) {
|
||||
if endingBlockNumber == nil {
|
||||
endingBlockNumber = startingBlockNumber
|
||||
@@ -64,7 +99,7 @@ func (blockChain *BlockChain) GetLogs(contract core.Contract, startingBlockNumbe
|
||||
}
|
||||
|
||||
func (blockChain *BlockChain) GetEthLogsWithCustomQuery(query ethereum.FilterQuery) ([]types.Log, error) {
|
||||
gethLogs, err := blockChain.client.FilterLogs(context.Background(), query)
|
||||
gethLogs, err := blockChain.ethClient.FilterLogs(context.Background(), query)
|
||||
if err != nil {
|
||||
return []types.Log{}, err
|
||||
}
|
||||
@@ -72,7 +107,7 @@ func (blockChain *BlockChain) GetEthLogsWithCustomQuery(query ethereum.FilterQue
|
||||
}
|
||||
|
||||
func (blockChain *BlockChain) LastBlock() *big.Int {
|
||||
block, _ := blockChain.client.HeaderByNumber(context.Background(), nil)
|
||||
block, _ := blockChain.ethClient.HeaderByNumber(context.Background(), nil)
|
||||
return block.Number
|
||||
}
|
||||
|
||||
|
||||
+48
-20
@@ -18,16 +18,19 @@ import (
|
||||
|
||||
var _ = Describe("Geth blockchain", func() {
|
||||
var mockClient *fakes.MockEthClient
|
||||
var mockRpcClient *fakes.MockRpcClient
|
||||
var node vulcCore.Node
|
||||
var blockChain *geth.BlockChain
|
||||
|
||||
BeforeEach(func() {
|
||||
mockClient = fakes.NewMockEthClient()
|
||||
node := vulcCore.Node{}
|
||||
blockChain = geth.NewBlockChain(mockClient, node, cold_db.NewColdDbTransactionConverter())
|
||||
mockRpcClient = fakes.NewMockRpcClient()
|
||||
node = vulcCore.Node{}
|
||||
blockChain = geth.NewBlockChain(mockClient, mockRpcClient, node, cold_db.NewColdDbTransactionConverter())
|
||||
})
|
||||
|
||||
Describe("getting a block", func() {
|
||||
It("fetches block from client", func() {
|
||||
It("fetches block from ethClient", func() {
|
||||
mockClient.SetBlockByNumberReturnBlock(types.NewBlockWithHeader(&types.Header{}))
|
||||
blockNumber := int64(100)
|
||||
|
||||
@@ -37,7 +40,7 @@ var _ = Describe("Geth blockchain", func() {
|
||||
mockClient.AssertBlockByNumberCalledWith(context.Background(), big.NewInt(blockNumber))
|
||||
})
|
||||
|
||||
It("returns err if client returns err", func() {
|
||||
It("returns err if ethClient returns err", func() {
|
||||
mockClient.SetBlockByNumberErr(fakes.FakeError)
|
||||
|
||||
_, err := blockChain.GetBlockByNumber(100)
|
||||
@@ -48,28 +51,53 @@ var _ = Describe("Geth blockchain", func() {
|
||||
})
|
||||
|
||||
Describe("getting a header", func() {
|
||||
It("fetches header from client", func() {
|
||||
blockNumber := int64(100)
|
||||
mockClient.SetHeaderByNumberReturnHeader(&types.Header{Number: big.NewInt(blockNumber)})
|
||||
Describe("default/mainnet", func() {
|
||||
It("fetches header from ethClient", func() {
|
||||
blockNumber := int64(100)
|
||||
mockClient.SetHeaderByNumberReturnHeader(&types.Header{Number: big.NewInt(blockNumber)})
|
||||
|
||||
_, err := blockChain.GetHeaderByNumber(blockNumber)
|
||||
_, err := blockChain.GetHeaderByNumber(blockNumber)
|
||||
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
mockClient.AssertHeaderByNumberCalledWith(context.Background(), big.NewInt(blockNumber))
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
mockClient.AssertHeaderByNumberCalledWith(context.Background(), big.NewInt(blockNumber))
|
||||
})
|
||||
|
||||
It("returns err if ethClient returns err", func() {
|
||||
mockClient.SetHeaderByNumberErr(fakes.FakeError)
|
||||
|
||||
_, err := blockChain.GetHeaderByNumber(100)
|
||||
|
||||
Expect(err).To(HaveOccurred())
|
||||
Expect(err).To(MatchError(fakes.FakeError))
|
||||
})
|
||||
})
|
||||
|
||||
It("returns err if client returns err", func() {
|
||||
mockClient.SetHeaderByNumberErr(fakes.FakeError)
|
||||
Describe("POA/Kovan", func() {
|
||||
It("fetches header from rpcClient", func() {
|
||||
node.NetworkID = vulcCore.KOVAN_NETWORK_ID
|
||||
blockChain = geth.NewBlockChain(mockClient, mockRpcClient, node, cold_db.NewColdDbTransactionConverter())
|
||||
|
||||
_, err := blockChain.GetHeaderByNumber(100)
|
||||
_, err := blockChain.GetHeaderByNumber(100)
|
||||
|
||||
Expect(err).To(HaveOccurred())
|
||||
Expect(err).To(MatchError(fakes.FakeError))
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
mockRpcClient.AssertCallContextCalledWith(context.Background(), &vulcCore.POAHeader{}, "eth_getBlockByNumber")
|
||||
})
|
||||
|
||||
It("returns err if rpcClient returns err", func() {
|
||||
node.NetworkID = vulcCore.KOVAN_NETWORK_ID
|
||||
mockRpcClient.SetCallContextErr(fakes.FakeError)
|
||||
blockChain = geth.NewBlockChain(mockClient, mockRpcClient, node, cold_db.NewColdDbTransactionConverter())
|
||||
|
||||
_, err := blockChain.GetHeaderByNumber(100)
|
||||
|
||||
Expect(err).To(HaveOccurred())
|
||||
Expect(err).To(MatchError(fakes.FakeError))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Describe("getting logs with default FilterQuery", func() {
|
||||
It("fetches logs from client", func() {
|
||||
It("fetches logs from ethClient", func() {
|
||||
mockClient.SetFilterLogsReturnLogs([]types.Log{{}})
|
||||
contract := vulcCore.Contract{Hash: common.BytesToHash([]byte{1, 2, 3, 4, 5}).Hex()}
|
||||
startingBlockNumber := big.NewInt(1)
|
||||
@@ -86,7 +114,7 @@ var _ = Describe("Geth blockchain", func() {
|
||||
mockClient.AssertFilterLogsCalledWith(context.Background(), expectedQuery)
|
||||
})
|
||||
|
||||
It("returns err if client returns err", func() {
|
||||
It("returns err if ethClient returns err", func() {
|
||||
mockClient.SetFilterLogsErr(fakes.FakeError)
|
||||
contract := vulcCore.Contract{Hash: common.BytesToHash([]byte{1, 2, 3, 4, 5}).Hex()}
|
||||
startingBlockNumber := big.NewInt(1)
|
||||
@@ -100,7 +128,7 @@ var _ = Describe("Geth blockchain", func() {
|
||||
})
|
||||
|
||||
Describe("getting logs with a custom FilterQuery", func() {
|
||||
It("fetches logs from client", func() {
|
||||
It("fetches logs from ethClient", func() {
|
||||
mockClient.SetFilterLogsReturnLogs([]types.Log{{}})
|
||||
address := common.HexToAddress("0x")
|
||||
startingBlockNumber := big.NewInt(1)
|
||||
@@ -119,7 +147,7 @@ var _ = Describe("Geth blockchain", func() {
|
||||
mockClient.AssertFilterLogsCalledWith(context.Background(), query)
|
||||
})
|
||||
|
||||
It("returns err if client returns err", func() {
|
||||
It("returns err if ethClient returns err", func() {
|
||||
mockClient.SetFilterLogsErr(fakes.FakeError)
|
||||
contract := vulcCore.Contract{Hash: common.BytesToHash([]byte{1, 2, 3, 4, 5}).Hex()}
|
||||
startingBlockNumber := big.NewInt(1)
|
||||
@@ -139,7 +167,7 @@ var _ = Describe("Geth blockchain", func() {
|
||||
})
|
||||
|
||||
Describe("getting the most recent block number", func() {
|
||||
It("fetches latest header from client", func() {
|
||||
It("fetches latest header from ethClient", func() {
|
||||
blockNumber := int64(100)
|
||||
mockClient.SetHeaderByNumberReturnHeader(&types.Header{Number: big.NewInt(blockNumber)})
|
||||
|
||||
|
||||
@@ -38,5 +38,5 @@ func (blockChain *BlockChain) FetchContractData(abiJSON string, address string,
|
||||
func (blockChain *BlockChain) callContract(contractHash string, input []byte, blockNumber *big.Int) ([]byte, error) {
|
||||
to := common.HexToAddress(contractHash)
|
||||
msg := ethereum.CallMsg{To: &to, Data: input}
|
||||
return blockChain.client.CallContract(context.Background(), msg, blockNumber)
|
||||
return blockChain.ethClient.CallContract(context.Background(), msg, blockNumber)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user