From a9bea4f49210ac4ba6da132d0fe379ea1bc9fbb7 Mon Sep 17 00:00:00 2001 From: Matt K <1036969+mkrump@users.noreply.github.com> Date: Wed, 10 Jan 2018 15:54:36 -0600 Subject: [PATCH] Allow for multiple Geth nodes (#128) --- .../1515613181_add_fields_to_node.down.sql | 3 ++ .../1515613181_add_fields_to_node.up.sql | 3 ++ .../1515613715_update_node_index.down.sql | 9 ++++ .../1515613715_update_node_index.up.sql | 9 ++++ integration_test/geth_blockchain_test.go | 2 + pkg/core/node_info.go | 2 + pkg/fakes/blockchain.go | 2 +- pkg/geth/blockchain.go | 15 +++++- pkg/geth/node/node.go | 47 ++++++++++++++----- pkg/repositories/postgres.go | 13 +++-- pkg/repositories/postgres_test.go | 10 ++-- pkg/repositories/testing/helpers.go | 9 +++- 12 files changed, 98 insertions(+), 26 deletions(-) create mode 100644 db/migrations/1515613181_add_fields_to_node.down.sql create mode 100644 db/migrations/1515613181_add_fields_to_node.up.sql create mode 100644 db/migrations/1515613715_update_node_index.down.sql create mode 100644 db/migrations/1515613715_update_node_index.up.sql diff --git a/db/migrations/1515613181_add_fields_to_node.down.sql b/db/migrations/1515613181_add_fields_to_node.down.sql new file mode 100644 index 00000000..66ffb290 --- /dev/null +++ b/db/migrations/1515613181_add_fields_to_node.down.sql @@ -0,0 +1,3 @@ +ALTER TABLE nodes + DROP COLUMN node_id, + DROP COLUMN client_name; \ No newline at end of file diff --git a/db/migrations/1515613181_add_fields_to_node.up.sql b/db/migrations/1515613181_add_fields_to_node.up.sql new file mode 100644 index 00000000..5396e26a --- /dev/null +++ b/db/migrations/1515613181_add_fields_to_node.up.sql @@ -0,0 +1,3 @@ +ALTER TABLE nodes + ADD COLUMN node_id VARCHAR(128), + ADD COLUMN client_name VARCHAR; \ No newline at end of file diff --git a/db/migrations/1515613715_update_node_index.down.sql b/db/migrations/1515613715_update_node_index.down.sql new file mode 100644 index 00000000..5c252c4b --- /dev/null +++ b/db/migrations/1515613715_update_node_index.down.sql @@ -0,0 +1,9 @@ +BEGIN; + +ALTER TABLE nodes + DROP CONSTRAINT node_uc; + +ALTER TABLE nodes + ADD CONSTRAINT node_uc UNIQUE (genesis_block, network_id); + +COMMIT; diff --git a/db/migrations/1515613715_update_node_index.up.sql b/db/migrations/1515613715_update_node_index.up.sql new file mode 100644 index 00000000..6abf9347 --- /dev/null +++ b/db/migrations/1515613715_update_node_index.up.sql @@ -0,0 +1,9 @@ +BEGIN; + +ALTER TABLE nodes + DROP CONSTRAINT node_uc; + +ALTER TABLE nodes + ADD CONSTRAINT node_uc UNIQUE (genesis_block, network_id, node_id); + +COMMIT; \ No newline at end of file diff --git a/integration_test/geth_blockchain_test.go b/integration_test/geth_blockchain_test.go index 279fbef5..c3a5b86d 100644 --- a/integration_test/geth_blockchain_test.go +++ b/integration_test/geth_blockchain_test.go @@ -52,6 +52,8 @@ var _ = Describe("Reading from the Geth blockchain", func() { Expect(node.GenesisBlock).To(Equal(devNetworkGenesisBlock)) Expect(node.NetworkId).To(Equal(devNetworkNodeId)) + Expect(len(node.Id)).To(Equal(128)) + Expect(node.ClientName).To(ContainSubstring("Geth")) close(done) }, 15) diff --git a/pkg/core/node_info.go b/pkg/core/node_info.go index 79ae55fb..fe88c928 100644 --- a/pkg/core/node_info.go +++ b/pkg/core/node_info.go @@ -3,4 +3,6 @@ package core type Node struct { GenesisBlock string NetworkId float64 + Id string + ClientName string } diff --git a/pkg/fakes/blockchain.go b/pkg/fakes/blockchain.go index 2af3a024..cdc4619a 100644 --- a/pkg/fakes/blockchain.go +++ b/pkg/fakes/blockchain.go @@ -50,7 +50,7 @@ func NewBlockchain() *Blockchain { blocks: make(map[int64]core.Block), logs: make(map[string][]core.Log), contractAttributes: make(map[string]map[string]string), - node: core.Node{GenesisBlock: "GENESIS"}, + node: core.Node{GenesisBlock: "GENESIS", NetworkId: 1, Id: "x123", ClientName: "Geth"}, } } diff --git a/pkg/geth/blockchain.go b/pkg/geth/blockchain.go index a7bba5f0..c519706f 100644 --- a/pkg/geth/blockchain.go +++ b/pkg/geth/blockchain.go @@ -3,6 +3,8 @@ package geth import ( "math/big" + "strings" + "github.com/8thlight/vulcanizedb/pkg/core" "github.com/8thlight/vulcanizedb/pkg/geth/node" "github.com/ethereum/go-ethereum" @@ -25,11 +27,22 @@ func NewBlockchain(ipcPath string) *Blockchain { blockchain := Blockchain{} rpcClient, _ := rpc.Dial(ipcPath) client := ethclient.NewClient(rpcClient) - blockchain.node = node.Retrieve(rpcClient) + blockchain.node = node.Info(rpcClient) + if infura := isInfuraNode(ipcPath); infura { + blockchain.node.Id = "infura" + blockchain.node.ClientName = "infura" + } blockchain.client = client return &blockchain } +func isInfuraNode(ipcPath string) bool { + if strings.Contains(ipcPath, "infura") { + return true + } + return false +} + func (blockchain *Blockchain) GetLogs(contract core.Contract, startingBlockNumber *big.Int, endingBlockNumber *big.Int) ([]core.Log, error) { if endingBlockNumber == nil { endingBlockNumber = startingBlockNumber diff --git a/pkg/geth/node/node.go b/pkg/geth/node/node.go index 524316dd..71deb4a3 100644 --- a/pkg/geth/node/node.go +++ b/pkg/geth/node/node.go @@ -7,22 +7,43 @@ import ( "github.com/8thlight/vulcanizedb/pkg/core" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/rpc" ) -func Retrieve(client *rpc.Client) core.Node { +func Info(client *rpc.Client) core.Node { node := core.Node{} - - var version string - client.CallContext(context.Background(), &version, "net_version") - node.NetworkId, _ = strconv.ParseFloat(version, 64) - - var protocolVersion string - client.CallContext(context.Background(), &protocolVersion, "eth_protocolVersion") - - var header *types.Header - client.CallContext(context.Background(), &header, "eth_getBlockByNumber", "0x0", false) - node.GenesisBlock = header.Hash().Hex() - + node.NetworkId = NetworkId(client) + node.GenesisBlock = GenesisBlock(client) + node.Id, node.ClientName = IdClientName(client) return node } + +func IdClientName(client *rpc.Client) (string, string) { + var info p2p.NodeInfo + modules, _ := client.SupportedModules() + if _, ok := modules["admin"]; ok { + client.CallContext(context.Background(), &info, "admin_nodeInfo") + return info.ID, info.Name + } + return "", "" +} + +func NetworkId(client *rpc.Client) float64 { + var version string + client.CallContext(context.Background(), &version, "net_version") + networkId, _ := strconv.ParseFloat(version, 64) + return networkId +} + +func ProtocolVersion(client *rpc.Client) string { + var protocolVersion string + client.CallContext(context.Background(), &protocolVersion, "eth_protocolVersion") + return protocolVersion +} + +func GenesisBlock(client *rpc.Client) string { + var header *types.Header + client.CallContext(context.Background(), &header, "eth_getBlockByNumber", "0x0", false) + return header.Hash().Hex() +} diff --git a/pkg/repositories/postgres.go b/pkg/repositories/postgres.go index de8b8128..4418073a 100644 --- a/pkg/repositories/postgres.go +++ b/pkg/repositories/postgres.go @@ -111,13 +111,16 @@ func (repository Postgres) FindLogs(address string, blockNumber int64) []core.Lo func (repository *Postgres) CreateNode(node *core.Node) error { var nodeId int64 err := repository.Db.QueryRow( - `INSERT INTO nodes (genesis_block, network_id) - VALUES ($1, $2) - ON CONFLICT (genesis_block, network_id) + `INSERT INTO nodes (genesis_block, network_id, node_id, client_name) + VALUES ($1, $2, $3, $4) + ON CONFLICT (genesis_block, network_id, node_id) DO UPDATE - SET genesis_block = $1, network_id = $2 + SET genesis_block = $1, + network_id = $2, + node_id = $3, + client_name = $4 RETURNING id`, - node.GenesisBlock, node.NetworkId).Scan(&nodeId) + node.GenesisBlock, node.NetworkId, node.Id, node.ClientName).Scan(&nodeId) if err != nil { return ErrUnableToSetNode } diff --git a/pkg/repositories/postgres_test.go b/pkg/repositories/postgres_test.go index 7768d907..ce75c2c5 100644 --- a/pkg/repositories/postgres_test.go +++ b/pkg/repositories/postgres_test.go @@ -47,7 +47,7 @@ var _ = Describe("Postgres repository", func() { Transactions: []core.Transaction{}, } cfg, _ := config.NewConfig("private") - node := core.Node{GenesisBlock: "GENESIS", NetworkId: 1} + node := core.Node{GenesisBlock: "GENESIS", NetworkId: 1, Id: "x123", ClientName: "geth"} repository, _ := repositories.NewPostgres(cfg.Database, node) err1 := repository.CreateOrUpdateBlock(badBlock) @@ -60,7 +60,7 @@ var _ = Describe("Postgres repository", func() { It("throws error when can't connect to the database", func() { invalidDatabase := config.Database{} - node := core.Node{GenesisBlock: "GENESIS", NetworkId: 1} + node := core.Node{GenesisBlock: "GENESIS", NetworkId: 1, Id: "x123", ClientName: "geth"} _, err := repositories.NewPostgres(invalidDatabase, node) Expect(err).To(Equal(repositories.ErrDBConnectionFailed)) }) @@ -68,7 +68,7 @@ var _ = Describe("Postgres repository", func() { It("throws error when can't create node", func() { cfg, _ := config.NewConfig("private") badHash := fmt.Sprintf("x %s", strings.Repeat("1", 100)) - node := core.Node{GenesisBlock: badHash, NetworkId: 1} + node := core.Node{GenesisBlock: badHash, NetworkId: 1, Id: "x123", ClientName: "geth"} _, err := repositories.NewPostgres(cfg.Database, node) Expect(err).To(Equal(repositories.ErrUnableToSetNode)) }) @@ -82,7 +82,7 @@ var _ = Describe("Postgres repository", func() { TxHash: badTxHash, } cfg, _ := config.NewConfig("private") - node := core.Node{GenesisBlock: "GENESIS", NetworkId: 1} + node := core.Node{GenesisBlock: "GENESIS", NetworkId: 1, Id: "x123", ClientName: "geth"} repository, _ := repositories.NewPostgres(cfg.Database, node) err := repository.CreateLogs([]core.Log{badLog}) @@ -101,7 +101,7 @@ var _ = Describe("Postgres repository", func() { Transactions: []core.Transaction{badTransaction}, } cfg, _ := config.NewConfig("private") - node := core.Node{GenesisBlock: "GENESIS", NetworkId: 1} + node := core.Node{GenesisBlock: "GENESIS", NetworkId: 1, Id: "x123", ClientName: "geth"} repository, _ := repositories.NewPostgres(cfg.Database, node) err1 := repository.CreateOrUpdateBlock(block) diff --git a/pkg/repositories/testing/helpers.go b/pkg/repositories/testing/helpers.go index 784217b1..f2b42138 100644 --- a/pkg/repositories/testing/helpers.go +++ b/pkg/repositories/testing/helpers.go @@ -22,7 +22,12 @@ func AssertRepositoryBehavior(buildRepository func(node core.Node) repositories. var repository repositories.Repository BeforeEach(func() { - node := core.Node{GenesisBlock: "GENESIS", NetworkId: 1} + node := core.Node{ + GenesisBlock: "GENESIS", + NetworkId: 1, + Id: "b6f90c0fdd8ec9607aed8ee45c69322e47b7063f0bfb7a29c8ecafab24d0a22d24dd2329b5ee6ed4125a03cb14e57fd584e67f9e53e6c631055cbbd82f080845", + ClientName: "Geth/v1.7.2-stable-1db4ecdc/darwin-amd64/go1.9", + } repository = buildRepository(node) }) @@ -48,6 +53,8 @@ func AssertRepositoryBehavior(buildRepository func(node core.Node) repositories. nodeTwo := core.Node{ GenesisBlock: "0x456", NetworkId: 1, + Id: "x123456", + ClientName: "Geth", } repositoryTwo := buildRepository(nodeTwo)