Add FlipKick log events transformer

This commit is contained in:
Elizabeth
2018-08-07 10:51:34 -05:00
committed by GitHub
parent 66decaaa78
commit c617cd9c9d
1066 changed files with 200929 additions and 95 deletions
+6 -1
View File
@@ -1,12 +1,17 @@
package core
import "math/big"
import (
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/core/types"
"math/big"
)
type BlockChain interface {
ContractDataFetcher
GetBlockByNumber(blockNumber int64) (Block, error)
GetHeaderByNumber(blockNumber int64) (Header, error)
GetLogs(contract Contract, startingBlockNumber *big.Int, endingBlockNumber *big.Int) ([]Log, error)
GetEthLogsWithCustomQuery(query ethereum.FilterQuery) ([]types.Log, error)
LastBlock() *big.Int
Node() Node
}
+1
View File
@@ -1,6 +1,7 @@
package core
type Header struct {
Id int64
BlockNumber int64 `db:"block_number"`
Hash string
Raw []byte
+1
View File
@@ -10,6 +10,7 @@ const (
GETH NodeType = iota
PARITY
INFURA
GANACHE
)
type Node struct {
+17
View File
@@ -5,6 +5,8 @@ import (
. "github.com/onsi/gomega"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/core/types"
"github.com/vulcanize/vulcanizedb/pkg/core"
)
@@ -17,6 +19,8 @@ type MockBlockChain struct {
fetchContractDataPassedResult interface{}
fetchContractDataPassedBlockNumber int64
getBlockByNumberErr error
logQuery ethereum.FilterQuery
logQueryErr error
lastBlock *big.Int
node core.Node
}
@@ -39,6 +43,15 @@ func (blockChain *MockBlockChain) SetGetBlockByNumberErr(err error) {
blockChain.getBlockByNumberErr = err
}
func (blockChain *MockBlockChain) SetGetLogsErr(err error) {
blockChain.logQueryErr = err
}
func (blockChain *MockBlockChain) GetEthLogsWithCustomQuery(query ethereum.FilterQuery) ([]types.Log, error) {
blockChain.logQuery = query
return []types.Log{}, blockChain.logQueryErr
}
func (blockChain *MockBlockChain) GetHeaderByNumber(blockNumber int64) (core.Header, error) {
return core.Header{BlockNumber: blockNumber}, nil
}
@@ -81,3 +94,7 @@ func (blockChain *MockBlockChain) AssertFetchContractDataCalledWith(abiJSON stri
Expect(blockChain.fetchContractDataPassedResult).To(Equal(result))
Expect(blockChain.fetchContractDataPassedBlockNumber).To(Equal(blockNumber))
}
func (blockChain *MockBlockChain) AssertGetEthLogsWithCustomQueryCalledWith(query ethereum.FilterQuery) {
Expect(blockChain.logQuery).To(Equal(query))
}
+8 -11
View File
@@ -8,18 +8,15 @@ import (
)
type MockRpcClient struct {
ipcPath string
nodeType core.NodeType
ipcPath string
nodeType core.NodeType
supportedModules map[string]string
}
func NewMockRpcClient() *MockRpcClient {
return &MockRpcClient{}
}
func (client *MockRpcClient) SetNodeType(nodeType core.NodeType) {
client.nodeType = nodeType
}
func (client *MockRpcClient) SetIpcPath(ipcPath string) {
client.ipcPath = ipcPath
}
@@ -65,9 +62,9 @@ func (client *MockRpcClient) IpcPath() string {
}
func (client *MockRpcClient) SupportedModules() (map[string]string, error) {
result := make(map[string]string)
if client.nodeType == core.GETH {
result["admin"] = "ok"
}
return result, nil
return client.supportedModules, nil
}
func (client *MockRpcClient) SetSupporedModules(supportedModules map[string]string) {
client.supportedModules = supportedModules
}
+10 -1
View File
@@ -7,6 +7,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"golang.org/x/net/context"
"github.com/ethereum/go-ethereum/core/types"
"github.com/vulcanize/vulcanizedb/pkg/core"
vulcCommon "github.com/vulcanize/vulcanizedb/pkg/geth/converters/common"
)
@@ -53,7 +54,7 @@ func (blockChain *BlockChain) GetLogs(contract core.Contract, startingBlockNumbe
ToBlock: endingBlockNumber,
Addresses: []common.Address{contractAddress},
}
gethLogs, err := blockChain.client.FilterLogs(context.Background(), fc)
gethLogs, err := blockChain.GetEthLogsWithCustomQuery(fc)
if err != nil {
return []core.Log{}, err
}
@@ -61,6 +62,14 @@ func (blockChain *BlockChain) GetLogs(contract core.Contract, startingBlockNumbe
return logs, nil
}
func (blockChain *BlockChain) GetEthLogsWithCustomQuery(query ethereum.FilterQuery) ([]types.Log, error) {
gethLogs, err := blockChain.client.FilterLogs(context.Background(), query)
if err != nil {
return []types.Log{}, err
}
return gethLogs, nil
}
func (blockChain *BlockChain) LastBlock() *big.Int {
block, _ := blockChain.client.HeaderByNumber(context.Background(), nil)
return block.Number
+42 -22
View File
@@ -17,12 +17,18 @@ import (
)
var _ = Describe("Geth blockchain", func() {
var mockClient *fakes.MockEthClient
var blockChain *geth.BlockChain
BeforeEach(func() {
mockClient = fakes.NewMockEthClient()
node := vulcCore.Node{}
blockChain = geth.NewBlockChain(mockClient, node, cold_db.NewColdDbTransactionConverter())
})
Describe("getting a block", func() {
It("fetches block from client", func() {
mockClient := fakes.NewMockEthClient()
mockClient.SetBlockByNumberReturnBlock(types.NewBlockWithHeader(&types.Header{}))
node := vulcCore.Node{}
blockChain := geth.NewBlockChain(mockClient, node, cold_db.NewColdDbTransactionConverter())
blockNumber := int64(100)
_, err := blockChain.GetBlockByNumber(blockNumber)
@@ -32,10 +38,7 @@ var _ = Describe("Geth blockchain", func() {
})
It("returns err if client returns err", func() {
mockClient := fakes.NewMockEthClient()
mockClient.SetBlockByNumberErr(fakes.FakeError)
node := vulcCore.Node{}
blockChain := geth.NewBlockChain(mockClient, node, cold_db.NewColdDbTransactionConverter())
_, err := blockChain.GetBlockByNumber(100)
@@ -46,11 +49,8 @@ var _ = Describe("Geth blockchain", func() {
Describe("getting a header", func() {
It("fetches header from client", func() {
mockClient := fakes.NewMockEthClient()
blockNumber := int64(100)
mockClient.SetHeaderByNumberReturnHeader(&types.Header{Number: big.NewInt(blockNumber)})
node := vulcCore.Node{}
blockChain := geth.NewBlockChain(mockClient, node, cold_db.NewColdDbTransactionConverter())
_, err := blockChain.GetHeaderByNumber(blockNumber)
@@ -59,10 +59,7 @@ var _ = Describe("Geth blockchain", func() {
})
It("returns err if client returns err", func() {
mockClient := fakes.NewMockEthClient()
mockClient.SetHeaderByNumberErr(fakes.FakeError)
node := vulcCore.Node{}
blockChain := geth.NewBlockChain(mockClient, node, cold_db.NewColdDbTransactionConverter())
_, err := blockChain.GetHeaderByNumber(100)
@@ -71,12 +68,9 @@ var _ = Describe("Geth blockchain", func() {
})
})
Describe("getting logs", func() {
Describe("getting logs with default FilterQuery", func() {
It("fetches logs from client", func() {
mockClient := fakes.NewMockEthClient()
mockClient.SetFilterLogsReturnLogs([]types.Log{{}})
node := vulcCore.Node{}
blockChain := geth.NewBlockChain(mockClient, node, cold_db.NewColdDbTransactionConverter())
contract := vulcCore.Contract{Hash: common.BytesToHash([]byte{1, 2, 3, 4, 5}).Hex()}
startingBlockNumber := big.NewInt(1)
endingBlockNumber := big.NewInt(2)
@@ -93,10 +87,39 @@ var _ = Describe("Geth blockchain", func() {
})
It("returns err if client returns err", func() {
mockClient := fakes.NewMockEthClient()
mockClient.SetFilterLogsErr(fakes.FakeError)
node := vulcCore.Node{}
blockChain := geth.NewBlockChain(mockClient, node, cold_db.NewColdDbTransactionConverter())
contract := vulcCore.Contract{Hash: common.BytesToHash([]byte{1, 2, 3, 4, 5}).Hex()}
startingBlockNumber := big.NewInt(1)
endingBlockNumber := big.NewInt(2)
_, err := blockChain.GetLogs(contract, startingBlockNumber, endingBlockNumber)
Expect(err).To(HaveOccurred())
Expect(err).To(MatchError(fakes.FakeError))
})
})
Describe("getting logs with a custom FilterQuery", func() {
It("fetches logs from client", func() {
mockClient.SetFilterLogsReturnLogs([]types.Log{{}})
address := common.HexToAddress("0x")
startingBlockNumber := big.NewInt(1)
endingBlockNumber := big.NewInt(2)
topic := common.HexToHash("0x")
query := ethereum.FilterQuery{
FromBlock: startingBlockNumber,
ToBlock: endingBlockNumber,
Addresses: []common.Address{address},
Topics: [][]common.Hash{{topic}},
}
_, err := blockChain.GetEthLogsWithCustomQuery(query)
Expect(err).NotTo(HaveOccurred())
mockClient.AssertFilterLogsCalledWith(context.Background(), query)
})
It("returns err if client returns err", func() {
mockClient.SetFilterLogsErr(fakes.FakeError)
contract := vulcCore.Contract{Hash: common.BytesToHash([]byte{1, 2, 3, 4, 5}).Hex()}
startingBlockNumber := big.NewInt(1)
endingBlockNumber := big.NewInt(2)
@@ -110,11 +133,8 @@ var _ = Describe("Geth blockchain", func() {
Describe("getting the most recent block number", func() {
It("fetches latest header from client", func() {
mockClient := fakes.NewMockEthClient()
blockNumber := int64(100)
mockClient.SetHeaderByNumberReturnHeader(&types.Header{Number: big.NewInt(blockNumber)})
node := vulcCore.Node{}
blockChain := geth.NewBlockChain(mockClient, node, cold_db.NewColdDbTransactionConverter())
result := blockChain.LastBlock()
+8 -1
View File
@@ -18,7 +18,14 @@ func NewRpcClient(client *rpc.Client, ipcPath string) RpcClient {
}
func (client RpcClient) CallContext(ctx context.Context, result interface{}, method string, args ...interface{}) error {
return client.client.CallContext(ctx, result, method, args)
//If an empty interface (or other nil object) is passed to CallContext, when the JSONRPC message is created the params will
//be interpreted as [null]. This seems to work fine for most of the ethereum clients (which presumably ignore a null parameter.
//Ganache however does not ignore it, and throws an 'Incorrect number of arguments' error.
if args == nil {
return client.client.CallContext(ctx, result, method)
} else {
return client.client.CallContext(ctx, result, method, args)
}
}
func (client RpcClient) IpcPath() string {
+13
View File
@@ -37,6 +37,10 @@ type InfuraClient struct {
PropertiesReader
}
type GanacheClient struct {
PropertiesReader
}
func MakeNode(rpcClient core.RpcClient) core.Node {
pr := makePropertiesReader(rpcClient)
id, name := pr.NodeInfo()
@@ -56,6 +60,8 @@ func makePropertiesReader(client core.RpcClient) IPropertiesReader {
return ParityClient{PropertiesReader: PropertiesReader{client: client}}
case core.INFURA:
return InfuraClient{PropertiesReader: PropertiesReader{client: client}}
case core.GANACHE:
return GanacheClient{PropertiesReader: PropertiesReader{client: client}}
default:
return PropertiesReader{client: client}
}
@@ -65,6 +71,9 @@ func getNodeType(client core.RpcClient) core.NodeType {
if strings.Contains(client.IpcPath(), "infura") {
return core.INFURA
}
if strings.Contains(client.IpcPath(), "127.0.0.1") || strings.Contains(client.IpcPath(), "localhost") {
return core.GANACHE
}
modules, _ := client.SupportedModules()
if _, ok := modules["admin"]; ok {
return core.GETH
@@ -106,6 +115,10 @@ func (client InfuraClient) NodeInfo() (string, string) {
return "infura", "infura"
}
func (client GanacheClient) NodeInfo() (string, string) {
return "ganache", "ganache"
}
func (client ParityClient) parityNodeInfo() string {
var nodeInfo core.ParityNodeInfo
client.client.CallContext(context.Background(), &nodeInfo, "parity_versionInfo")
+51 -36
View File
@@ -1,23 +1,22 @@
package node_test
import (
"encoding/json"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/vulcanize/vulcanizedb/pkg/core"
"github.com/vulcanize/vulcanizedb/pkg/fakes"
"github.com/vulcanize/vulcanizedb/pkg/geth/node"
"encoding/json"
)
var EmpytHeaderHash = "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
var _ = Describe("Parity Node Info", func() {
It("verifies parity_versionInfo can be unmarshalled into ParityNodeInfo", func() {
var parityNodeInfo core.ParityNodeInfo
nodeInfoJSON := []byte(
`{
var _ = Describe("Node Info", func() {
Describe("Parity Node Info", func() {
It("verifies parity_versionInfo can be unmarshalled into ParityNodeInfo", func() {
var parityNodeInfo core.ParityNodeInfo
nodeInfoJSON := []byte(
`{
"hash": "0x2ae8b4ca278dd7b896090366615fef81cbbbc0e0",
"track": "null",
"version": {
@@ -26,25 +25,34 @@ var _ = Describe("Parity Node Info", func() {
"patch": 0
}
}`)
json.Unmarshal(nodeInfoJSON, &parityNodeInfo)
Expect(parityNodeInfo.Hash).To(Equal("0x2ae8b4ca278dd7b896090366615fef81cbbbc0e0"))
Expect(parityNodeInfo.Track).To(Equal("null"))
Expect(parityNodeInfo.Major).To(Equal(1))
Expect(parityNodeInfo.Minor).To(Equal(6))
Expect(parityNodeInfo.Patch).To(Equal(0))
})
json.Unmarshal(nodeInfoJSON, &parityNodeInfo)
Expect(parityNodeInfo.Hash).To(Equal("0x2ae8b4ca278dd7b896090366615fef81cbbbc0e0"))
Expect(parityNodeInfo.Track).To(Equal("null"))
Expect(parityNodeInfo.Major).To(Equal(1))
Expect(parityNodeInfo.Minor).To(Equal(6))
Expect(parityNodeInfo.Patch).To(Equal(0))
})
It("Creates client string", func() {
parityNodeInfo := core.ParityNodeInfo{
Track: "null",
ParityVersion: core.ParityVersion{
Major: 1,
Minor: 6,
Patch: 0,
},
Hash: "0x1232144j",
}
Expect(parityNodeInfo.String()).To(Equal("Parity/v1.6.0/"))
It("Creates client string", func() {
parityNodeInfo := core.ParityNodeInfo{
Track: "null",
ParityVersion: core.ParityVersion{
Major: 1,
Minor: 6,
Patch: 0,
},
Hash: "0x1232144j",
}
Expect(parityNodeInfo.String()).To(Equal("Parity/v1.6.0/"))
})
It("returns parity ID and client name for parity node", func() {
client := fakes.NewMockRpcClient()
n := node.MakeNode(client)
Expect(n.ID).To(Equal("ParityNode"))
Expect(n.ClientName).To(Equal("Parity/v1.2.3/"))
})
})
It("returns the genesis block for any client", func() {
@@ -59,17 +67,12 @@ var _ = Describe("Parity Node Info", func() {
Expect(n.NetworkID).To(Equal(float64(1234)))
})
It("returns parity ID and client name for parity node", func() {
client := fakes.NewMockRpcClient()
client.SetNodeType(core.PARITY)
n := node.MakeNode(client)
Expect(n.ID).To(Equal("ParityNode"))
Expect(n.ClientName).To(Equal("Parity/v1.2.3/"))
})
It("returns geth ID and client name for geth node", func() {
client := fakes.NewMockRpcClient()
client.SetNodeType(core.GETH)
supportedModules := make(map[string]string)
supportedModules["admin"] = "ok"
client.SetSupporedModules(supportedModules)
n := node.MakeNode(client)
Expect(n.ID).To(Equal("enode://GethNode@172.17.0.1:30303"))
Expect(n.ClientName).To(Equal("Geth/v1.7"))
@@ -77,10 +80,22 @@ var _ = Describe("Parity Node Info", func() {
It("returns infura ID and client name for infura node", func() {
client := fakes.NewMockRpcClient()
client.SetNodeType(core.INFURA)
client.SetIpcPath("infura/path")
n := node.MakeNode(client)
Expect(n.ID).To(Equal("infura"))
Expect(n.ClientName).To(Equal("infura"))
})
It("returns local id and client name for Local node", func() {
client := fakes.NewMockRpcClient()
client.SetIpcPath("127.0.0.1")
n := node.MakeNode(client)
Expect(n.ID).To(Equal("ganache"))
Expect(n.ClientName).To(Equal("ganache"))
client.SetIpcPath("localhost")
n = node.MakeNode(client)
Expect(n.ID).To(Equal("ganache"))
Expect(n.ClientName).To(Equal("ganache"))
})
})
+46
View File
@@ -0,0 +1,46 @@
// Copyright 2018 Vulcanize
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package test_helpers
import (
. "github.com/onsi/gomega"
"github.com/vulcanize/vulcanizedb/pkg/core"
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres"
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres/repositories"
"github.com/vulcanize/vulcanizedb/test_config"
)
func CreateNewDatabase() *postgres.DB {
var node core.Node
node = core.Node{
GenesisBlock: "GENESIS",
NetworkID: 1,
ID: "b6f90c0fdd8ec9607aed8ee45c69322e47b7063f0bfb7a29c8ecafab24d0a22d24dd2329b5ee6ed4125a03cb14e57fd584e67f9e53e6c631055cbbd82f080845",
ClientName: "Geth/v1.7.2-stable-1db4ecdc/darwin-amd64/go1.9",
}
db := test_config.NewTestDB(node)
_, err := db.Exec(`DELETE FROM logs`)
Expect(err).NotTo(HaveOccurred())
return db
}
func CreateBlock(blockNumber int64, repository repositories.BlockRepository) (blockId int64) {
blockId, err := repository.CreateOrUpdateBlock(core.Block{Number: blockNumber})
Expect(err).NotTo(HaveOccurred())
return blockId
}