forked from cerc-io/ipld-eth-server
batch headers by 100s
This commit is contained in:
+104
-2
@@ -6,16 +6,19 @@ import (
|
||||
|
||||
"github.com/ethereum/go-ethereum"
|
||||
"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/ethereum/go-ethereum/rpc"
|
||||
"github.com/vulcanize/vulcanizedb/pkg/core"
|
||||
vulcCommon "github.com/vulcanize/vulcanizedb/pkg/geth/converters/common"
|
||||
"golang.org/x/net/context"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
var ErrEmptyHeader = errors.New("empty header returned over RPC")
|
||||
|
||||
const MAX_BATCH_SIZE = 100
|
||||
|
||||
type BlockChain struct {
|
||||
blockConverter vulcCommon.BlockConverter
|
||||
ethClient core.EthClient
|
||||
@@ -49,6 +52,13 @@ func (blockChain *BlockChain) GetHeaderByNumber(blockNumber int64) (header core.
|
||||
return blockChain.getPOWHeader(blockNumber)
|
||||
}
|
||||
|
||||
func (blockChain *BlockChain) GetHeaderByNumbers(blockNumbers []int64) (header []core.Header, err error) {
|
||||
if blockChain.node.NetworkID == core.KOVAN_NETWORK_ID {
|
||||
return blockChain.getPOAHeaders(blockNumbers)
|
||||
}
|
||||
return blockChain.getPOWHeaders(blockNumbers)
|
||||
}
|
||||
|
||||
func (blockChain *BlockChain) getPOWHeader(blockNumber int64) (header core.Header, err error) {
|
||||
gethHeader, err := blockChain.ethClient.HeaderByNumber(context.Background(), big.NewInt(blockNumber))
|
||||
if err != nil {
|
||||
@@ -57,6 +67,42 @@ func (blockChain *BlockChain) getPOWHeader(blockNumber int64) (header core.Heade
|
||||
return blockChain.headerConverter.Convert(gethHeader, gethHeader.Hash().String())
|
||||
}
|
||||
|
||||
func (blockChain *BlockChain) getPOWHeaders(blockNumbers []int64) (headers []core.Header, err error) {
|
||||
var batch []rpc.BatchElem
|
||||
var POWHeaders [MAX_BATCH_SIZE]types.Header
|
||||
includeTransactions := false
|
||||
|
||||
for index, blockNumber := range blockNumbers {
|
||||
|
||||
if index >= MAX_BATCH_SIZE {
|
||||
break
|
||||
}
|
||||
|
||||
blockNumberArg := hexutil.EncodeBig(big.NewInt(blockNumber))
|
||||
|
||||
batchElem := rpc.BatchElem{
|
||||
Method: "eth_getBlockByNumber",
|
||||
Result: &POWHeaders[index],
|
||||
Args: []interface{}{blockNumberArg, includeTransactions},
|
||||
}
|
||||
|
||||
batch = append(batch, batchElem)
|
||||
}
|
||||
|
||||
err = blockChain.rpcClient.BatchCall(batch)
|
||||
if err != nil {
|
||||
return headers, err
|
||||
}
|
||||
|
||||
for index, _ := range blockNumbers {
|
||||
header, _ := blockChain.headerConverter.Convert(&POWHeaders[index], POWHeaders[index].Hash().String())
|
||||
|
||||
headers = append(headers, header)
|
||||
}
|
||||
|
||||
return headers, err
|
||||
}
|
||||
|
||||
func (blockChain *BlockChain) getPOAHeader(blockNumber int64) (header core.Header, err error) {
|
||||
var POAHeader core.POAHeader
|
||||
blockNumberArg := hexutil.EncodeBig(big.NewInt(blockNumber))
|
||||
@@ -85,6 +131,62 @@ func (blockChain *BlockChain) getPOAHeader(blockNumber int64) (header core.Heade
|
||||
}, POAHeader.Hash.String())
|
||||
}
|
||||
|
||||
func (blockChain *BlockChain) getPOAHeaders(blockNumbers []int64) (headers []core.Header, err error) {
|
||||
|
||||
var batch []rpc.BatchElem
|
||||
var POAHeaders [MAX_BATCH_SIZE]core.POAHeader
|
||||
includeTransactions := false
|
||||
|
||||
for index, blockNumber := range blockNumbers {
|
||||
|
||||
if index >= MAX_BATCH_SIZE {
|
||||
break
|
||||
}
|
||||
|
||||
blockNumberArg := hexutil.EncodeBig(big.NewInt(blockNumber))
|
||||
|
||||
batchElem := rpc.BatchElem{
|
||||
Method: "eth_getBlockByNumber",
|
||||
Result: &POAHeaders[index],
|
||||
Args: []interface{}{blockNumberArg, includeTransactions},
|
||||
}
|
||||
|
||||
batch = append(batch, batchElem)
|
||||
}
|
||||
|
||||
err = blockChain.rpcClient.BatchCall(batch)
|
||||
if err != nil {
|
||||
return headers, err
|
||||
}
|
||||
|
||||
for index, _ := range blockNumbers {
|
||||
var header core.Header
|
||||
var POAHeader = POAHeaders[index]
|
||||
//Header.Number of the newest block will return nil.
|
||||
if _, err := strconv.ParseUint(POAHeader.Number.ToInt().String(), 16, 64); err == nil {
|
||||
header, _ = 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,
|
||||
}, POAHeader.Hash.String())
|
||||
|
||||
headers = append(headers, header)
|
||||
}
|
||||
}
|
||||
|
||||
return headers, err
|
||||
}
|
||||
|
||||
func (blockChain *BlockChain) GetLogs(contract core.Contract, startingBlockNumber, endingBlockNumber *big.Int) ([]core.Log, error) {
|
||||
if endingBlockNumber == nil {
|
||||
endingBlockNumber = startingBlockNumber
|
||||
|
||||
@@ -5,12 +5,12 @@ import (
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
vulcCore "github.com/vulcanize/vulcanizedb/pkg/core"
|
||||
"github.com/vulcanize/vulcanizedb/pkg/fakes"
|
||||
"github.com/vulcanize/vulcanizedb/pkg/geth"
|
||||
@@ -71,12 +71,21 @@ var _ = Describe("Geth blockchain", func() {
|
||||
Expect(err).To(HaveOccurred())
|
||||
Expect(err).To(MatchError(fakes.FakeError))
|
||||
})
|
||||
|
||||
It("fetches headers with multiple blocks", func() {
|
||||
blockChain = geth.NewBlockChain(mockClient, mockRpcClient, node, cold_db.NewColdDbTransactionConverter())
|
||||
|
||||
_, err := blockChain.GetHeaderByNumbers([]int64{100, 99})
|
||||
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
mockRpcClient.AssertBatchCalledWith("eth_getBlockByNumber", 2)
|
||||
})
|
||||
})
|
||||
|
||||
Describe("POA/Kovan", func() {
|
||||
It("fetches header from rpcClient", func() {
|
||||
node.NetworkID = vulcCore.KOVAN_NETWORK_ID
|
||||
blockNumber := hexutil.Big(*big.NewInt(123))
|
||||
blockNumber := hexutil.Big(*big.NewInt(100))
|
||||
mockRpcClient.SetReturnPOAHeader(vulcCore.POAHeader{Number: &blockNumber})
|
||||
blockChain = geth.NewBlockChain(mockClient, mockRpcClient, node, cold_db.NewColdDbTransactionConverter())
|
||||
|
||||
@@ -106,6 +115,18 @@ var _ = Describe("Geth blockchain", func() {
|
||||
Expect(err).To(HaveOccurred())
|
||||
Expect(err).To(MatchError(geth.ErrEmptyHeader))
|
||||
})
|
||||
|
||||
It("returns multiple headers with multiple blocknumbers", func() {
|
||||
node.NetworkID = vulcCore.KOVAN_NETWORK_ID
|
||||
blockNumber := hexutil.Big(*big.NewInt(100))
|
||||
mockRpcClient.SetReturnPOAHeaders([]vulcCore.POAHeader{{Number: &blockNumber}})
|
||||
blockChain = geth.NewBlockChain(mockClient, mockRpcClient, node, cold_db.NewColdDbTransactionConverter())
|
||||
|
||||
_, err := blockChain.GetHeaderByNumbers([]int64{100, 99})
|
||||
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
mockRpcClient.AssertBatchCalledWith("eth_getBlockByNumber", 2)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -35,3 +35,7 @@ func (client RpcClient) IpcPath() string {
|
||||
func (client RpcClient) SupportedModules() (map[string]string, error) {
|
||||
return client.client.SupportedModules()
|
||||
}
|
||||
|
||||
func (client RpcClient) BatchCall(batch []rpc.BatchElem) error {
|
||||
return client.client.BatchCall(batch)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user