Skip to content
This repository was archived by the owner on Oct 20, 2021. It is now read-only.

Commit 72db2ff

Browse files
authored
Merge pull request #2 from vulcanize/headerSync
Updates
2 parents 02fff11 + ce48d2f commit 72db2ff

37 files changed

+160
-459
lines changed

Dockerfile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
FROM golang:alpine as builder
22
RUN apk --update --no-cache add make git g++
33

4-
# Build statically linked vDB binary (wonky path because of Dep)
4+
# Build statically linked binary (wonky path because of Dep)
55
RUN mkdir -p /go/src/github.com/vulcanize/eth-header-sync
66
ADD . /go/src/github.com/vulcanize/eth-header-sync
77
WORKDIR /go/src/github.com/vulcanize/eth-header-sync
@@ -14,7 +14,7 @@ RUN GCO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -ldflags '-extldflag
1414

1515
# Second stage
1616
FROM alpine
17-
COPY --from=builder /go/src/github.com/vulcanize/eth-header-sync/vulcanizedb /app/vulcanizedb
17+
COPY --from=builder /go/src/github.com/vulcanize/eth-header-sync/eth-header-sync /app/eth-header-sync
1818
COPY --from=builder /go/src/github.com/vulcanize/eth-header-sync/environments/staging.toml /app/environments/
1919
COPY --from=builder /go/src/github.com/vulcanize/eth-header-sync/dockerfiles/startup_script.sh /app/
2020
COPY --from=builder /go/src/github.com/vulcanize/eth-header-sync/db/migrations/* /app/

Makefile

Lines changed: 0 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -87,76 +87,8 @@ checkdbvars:
8787
test -n "$(NAME)" # $$NAME
8888
@echo $(CONNECT_STRING)
8989

90-
## Check that the migration variable (id/timestamp) is provided
91-
.PHONY: checkmigration
92-
checkmigration:
93-
test -n "$(MIGRATION)" # $$MIGRATION
94-
95-
# Check that the migration name is provided
96-
.PHONY: checkmigname
97-
checkmigname:
98-
test -n "$(NAME)" # $$NAME
99-
100-
# Migration operations
101-
## Rollback the last migration
102-
.PHONY: rollback
103-
rollback: $(GOOSE) checkdbvars
104-
$(GOOSE) -dir db/migrations postgres "$(CONNECT_STRING)" down
105-
pg_dump -O -s $(CONNECT_STRING) > db/schema.sql
106-
107-
108-
## Rollbackt to a select migration (id/timestamp)
109-
.PHONY: rollback_to
110-
rollback_to: $(GOOSE) checkmigration checkdbvars
111-
$(GOOSE) -dir db/migrations postgres "$(CONNECT_STRING)" down-to "$(MIGRATION)"
112-
11390
## Apply all migrations not already run
11491
.PHONY: migrate
11592
migrate: $(GOOSE) checkdbvars
11693
$(GOOSE) -dir db/migrations postgres "$(CONNECT_STRING)" up
11794
pg_dump -O -s $(CONNECT_STRING) > db/schema.sql
118-
119-
## Create a new migration file
120-
.PHONY: new_migration
121-
new_migration: $(GOOSE) checkmigname
122-
$(GOOSE) -dir db/migrations create $(NAME) sql
123-
124-
## Check which migrations are applied at the moment
125-
.PHONY: migration_status
126-
migration_status: $(GOOSE) checkdbvars
127-
$(GOOSE) -dir db/migrations postgres "$(CONNECT_STRING)" status
128-
129-
# Convert timestamped migrations to versioned (to be run in CI);
130-
# merge timestamped files to prevent conflict
131-
.PHONY: version_migrations
132-
version_migrations:
133-
$(GOOSE) -dir db/migrations fix
134-
135-
# Import a psql schema to the database
136-
.PHONY: import
137-
import:
138-
test -n "$(NAME)" # $$NAME
139-
psql $(NAME) < db/schema.sql
140-
141-
142-
# Docker actions
143-
## Rinkeby docker environment
144-
RINKEBY_COMPOSE_FILE=dockerfiles/rinkeby/docker-compose.yml
145-
146-
.PHONY: rinkeby_env_up
147-
rinkeby_env_up:
148-
docker-compose -f $(RINKEBY_COMPOSE_FILE) up -d geth
149-
docker-compose -f $(RINKEBY_COMPOSE_FILE) up --build migrations
150-
docker-compose -f $(RINKEBY_COMPOSE_FILE) up -d --build vulcanizedb
151-
152-
.PHONY: rinkeby_env_deploy
153-
rinkeby_env_deploy:
154-
docker-compose -f $(RINKEBY_COMPOSE_FILE) up -d --build vulcanizedb
155-
156-
.PHONY: dev_env_migrate
157-
rinkeby_env_migrate:
158-
docker-compose -f $(RINKEBY_COMPOSE_FILE) up --build migrations
159-
160-
.PHONY: rinkeby_env_down
161-
rinkeby_env_down:
162-
docker-compose -f $(RINKEBY_COMPOSE_FILE) down

README.md

Lines changed: 39 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,31 @@
1-
# Vulcanize DB
1+
# eth-header-sync
22

3-
[![Build Status](https://travis-ci.org/vulcanize/vulcanizedb.svg?branch=master)](https://travis-ci.org/vulcanize/vulcanizedb)
43
[![Go Report Card](https://goreportcard.com/badge/github.com/vulcanize/eth-header-sync)](https://goreportcard.com/report/github.com/vulcanize/eth-header-sync)
54

6-
> Vulcanize DB is a set of tools that make it easier for developers to write application-specific indexes and caches for dapps built on Ethereum.
5+
> Tool for syncing Ethereum headers into a Postgres database
76
8-
9-
## Table of Contents
7+
## Table of Contents
108
1. [Background](#background)
119
1. [Install](#install)
1210
1. [Usage](#usage)
1311
1. [Contributing](#contributing)
1412
1. [License](#license)
1513

16-
1714
## Background
18-
The same data structures and encodings that make Ethereum an effective and trust-less distributed virtual machine
19-
complicate data accessibility and usability for dApp developers. VulcanizeDB improves Ethereum data accessibility by
20-
providing a suite of tools to ease the extraction and transformation of data into a more useful state, including
21-
allowing for exposing aggregate data from a suite of smart contracts.
15+
Ethereum data is natively stored in key-value databases such as leveldb (geth) and rocksdb (openethereum).
16+
Storage of Ethereum in these KV databases is optimized for scalability and ideal for the purposes of consensus,
17+
it is not necessarily ideal for use by external applications. Moving Ethereum data into a relational database can provide
18+
many advantages for downstream data consumers.
19+
20+
This tool syncs Ethereum headers in Postgres. Addtionally, it validates headers from the last 15 blocks to ensure the data is up to date and
21+
handles chain reorgs by validating the most recent blocks' hashes and upserting invalid header records.
2222

23-
VulanizeDB includes processes that sync, transform and expose data. Syncing involves
24-
querying an Ethereum node and then persisting core data into a Postgres database. Transforming focuses on using previously synced data to
25-
query for and transform log event and storage data for specifically configured smart contract addresses. Exposing data is a matter of getting
26-
data from VulcanizeDB's underlying Postgres database and making it accessible.
23+
This is useful when you want a minimal baseline from which to track and hash-link targeted data on the blockchain (e.g. individual smart contract storage values or event logs).
24+
Some examples of this are the [eth-contract-watcher]() and [eth-account-watcher]().
25+
26+
Headers are fetched by RPC queries to the standard `eth_getBlockByNumber` JSON-RPC endpoint, headers can be synced from anything
27+
that supports this endpoint.
2728

28-
![VulcanizeDB Overview Diagram](documentation/diagrams/vdb-overview.png)
2929

3030
## Install
3131

@@ -38,8 +38,8 @@ data from VulcanizeDB's underlying Postgres database and making it accessible.
3838
- Go 1.12+
3939
- Postgres 11.2
4040
- Ethereum Node
41-
- [Go Ethereum](https://ethereum.github.io/go-ethereum/downloads/) (1.8.23+)
42-
- [Parity 1.8.11+](https://github.com/paritytech/parity/releases)
41+
- [Go Ethereum](https://github.com/ethereum/go-ethereum/releases) (1.8.23+)
42+
- [Open Ethereum](https://github.com/openethereum/openethereum/releases) (1.8.11+)
4343

4444
### Building the project
4545
Download the codebase to your local `GOPATH` via:
@@ -81,74 +81,56 @@ localhost. To allow access on Ubuntu, set localhost connections via hostname, ip
8181

8282
### Configuring a synced Ethereum node
8383
- To use a local Ethereum node, copy `environments/public.toml.example` to
84-
`environments/public.toml` and update the `ipcPath` and `levelDbPath`.
85-
- `ipcPath` should match the local node's IPC filepath:
84+
`environments/public.toml` and update the `rpcPath` in the config file.
85+
- `rpcPath` should match the local node's IPC filepath:
8686
- For Geth:
8787
- The IPC file is called `geth.ipc`.
8888
- The geth IPC file path is printed to the console when you start geth.
8989
- The default location is:
9090
- Mac: `<full home path>/Library/Ethereum/geth.ipc`
9191
- Linux: `<full home path>/ethereum/geth.ipc`
9292
- Note: the geth.ipc file may not exist until you've started the geth process
93+
- The default localhost HTTP URL is "http://127.0.0.1:8545"
9394

94-
- For Parity:
95+
- For OpenEthereum:
9596
- The IPC file is called `jsonrpc.ipc`.
9697
- The default location is:
9798
- Mac: `<full home path>/Library/Application\ Support/io.parity.ethereum/`
9899
- Linux: `<full home path>/local/share/io.parity.ethereum/`
99100

100-
- `levelDbPath` should match Geth's chaindata directory path.
101-
- The geth LevelDB chaindata path is printed to the console when you start geth.
102-
- The default location is:
103-
- Mac: `<full home path>/Library/Ethereum/geth/chaindata`
104-
- Linux: `<full home path>/ethereum/geth/chaindata`
105-
- `levelDbPath` is irrelevant (and `coldImport` is currently unavailable) if only running parity.
106-
101+
- To use a remote Ethereum node, simply set the `rpcPath` in the config file to the HTTP RPC endpoint url for the remote node
102+
- The default HTTP port # for Geth and OpenEthereum is 8545
107103

108104
## Usage
109-
As mentioned above, VulcanizeDB's processes can be split into three categories: syncing, transforming and exposing data.
110-
111-
### Data syncing
112-
To provide data for transformations, raw Ethereum data must first be synced into VulcanizeDB.
113-
This is accomplished through the use of the `headerSync` command.
114-
These commands are described in detail [here](documentation/data-syncing.md).
105+
`./eth-header-sync sync --config <config.toml> --starting-block-number <block-number>`
115106

116-
### Data transformation
117-
Data transformation uses the raw data that has been synced into Postgres to filter out and apply transformations to
118-
specific data of interest. Since there are different types of data that may be useful for observing smart contracts, it
119-
follows that there are different ways to transform this data. We've started by categorizing this into Generic and
120-
Custom transformers:
107+
The config file must be formatted as follows, and should contain an RPC path to a running Ethereum node:
121108

122-
- Generic Contract Transformer: Generic contract transformation can be done using a built-in command,
123-
`contractWatcher`, which transforms contract events provided the contract's ABI is available. It also
124-
provides some state variable coverage by automating polling of public methods, with some restrictions.
125-
`contractWatcher` is described further [here](documentation/generic-transformer.md).
109+
```toml
110+
[database]
111+
name = "vulcanize_public"
112+
hostname = "localhost"
113+
user = "postgres"
114+
password = ""
115+
port = 5432
126116

127-
- Custom Transformers: In many cases custom transformers will need to be written to provide
128-
more comprehensive coverage of contract data. In this case we have provided the `compose`, `execute`, and
129-
`composeAndExecute` commands for running custom transformers from external repositories. Documentation on how to write,
130-
build and run custom transformers as Go plugins can be found
131-
[here](documentation/custom-transformers.md).
117+
[client]
118+
rpcPath = "http://127.0.0.1:8545"
119+
```
132120

133-
### Exposing the data
134-
[Postgraphile](https://www.graphile.org/postgraphile/) is used to expose GraphQL endpoints for our database schemas, this is described in detail [here](documentation/postgraphile.md).
135121

122+
## Maintainers
123+
@vulcanize
124+
@AFDudley
125+
@i-norden
136126

137-
### Tests
138-
- Replace the empty `ipcPath` in the `environments/testing.toml` with a path to a full node's eth_jsonrpc endpoint (e.g. local geth node ipc path or infura url)
139-
- Note: must be mainnet
140-
- Note: integration tests require configuration with an archival node
141-
- `make test` will run the unit tests and skip the integration tests
142-
- `make integrationtest` will run just the integration tests
143-
- `make test` and `make integrationtest` setup a clean `vulcanize_testing` db
144127

145128

146129
## Contributing
147130
Contributions are welcome!
148131

149132
VulcanizeDB follows the [Contributor Covenant Code of Conduct](https://www.contributor-covenant.org/version/1/4/code-of-conduct).
150133

151-
For more information on contributing, please see [here](documentation/contributing.md).
152134

153135
## License
154136
[AGPL-3.0](LICENSE) © Vulcanize Inc

cmd/root.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,13 @@ const (
4949
)
5050

5151
var rootCmd = &cobra.Command{
52-
Use: "vulcanizedb",
52+
Use: "eth-header-sync",
5353
PersistentPreRun: initFuncs,
5454
}
5555

56+
// Execute begins execution of the command
5657
func Execute() {
57-
log.Info("----- Starting vDB -----")
58+
log.Info("----- Starting eth-header-sync -----")
5859
if err := rootCmd.Execute(); err != nil {
5960
log.Fatal(err)
6061
}
@@ -119,7 +120,7 @@ func init() {
119120
rootCmd.PersistentFlags().String("database-hostname", "localhost", "database hostname")
120121
rootCmd.PersistentFlags().String("database-user", "", "database user")
121122
rootCmd.PersistentFlags().String("database-password", "", "database password")
122-
rootCmd.PersistentFlags().String("client-ipcPath", "", "location of geth.ipc file")
123+
rootCmd.PersistentFlags().String("client-rpcPath", "", "path for calling eth http rpc endpoints")
123124
rootCmd.PersistentFlags().String("log-level", log.InfoLevel.String(), "Log level (trace, debug, info, warn, error, fatal, panic")
124125

125126
viper.BindPFlag("logfile", rootCmd.PersistentFlags().Lookup("logfile"))
@@ -128,7 +129,7 @@ func init() {
128129
viper.BindPFlag("database.hostname", rootCmd.PersistentFlags().Lookup("database-hostname"))
129130
viper.BindPFlag("database.user", rootCmd.PersistentFlags().Lookup("database-user"))
130131
viper.BindPFlag("database.password", rootCmd.PersistentFlags().Lookup("database-password"))
131-
viper.BindPFlag("client.ipcPath", rootCmd.PersistentFlags().Lookup("client-ipcPath"))
132+
viper.BindPFlag("client.rpcPath", rootCmd.PersistentFlags().Lookup("client-rpcPath"))
132133
viper.BindPFlag("log.level", rootCmd.PersistentFlags().Lookup("log-level"))
133134
}
134135

@@ -147,9 +148,8 @@ func initConfig() {
147148

148149
func getFetcher() *fetcher.Fetcher {
149150
rpcClient, ethClient := getClients()
150-
vdbEthClient := client.NewEthClient(ethClient)
151151
vdbNode := node.MakeNode(rpcClient)
152-
return fetcher.NewFetcher(vdbEthClient, rpcClient, vdbNode)
152+
return fetcher.NewFetcher(ethClient, rpcClient, vdbNode)
153153
}
154154

155155
func getClients() (client.RPCClient, *ethclient.Client) {

cmd/sync.go

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ import (
2525
"github.com/vulcanize/eth-header-sync/pkg/core"
2626
"github.com/vulcanize/eth-header-sync/pkg/fetcher"
2727
"github.com/vulcanize/eth-header-sync/pkg/history"
28+
"github.com/vulcanize/eth-header-sync/pkg/postgres"
2829
"github.com/vulcanize/eth-header-sync/pkg/repository"
29-
"github.com/vulcanize/eth-header-sync/utils"
3030
)
3131

3232
// syncCmd represents the sync command
@@ -36,7 +36,7 @@ var syncCmd = &cobra.Command{
3636
Long: `Syncs VulcanizeDB with local ethereum node. Populates
3737
Postgres with block headers.
3838
39-
./vulcanizedb sync --starting-block-number 0 --config public.toml
39+
./eth-header-sync sync --starting-block-number 0 --config public.toml
4040
4141
Expects ethereum node to be running and requires a .toml config:
4242
@@ -46,7 +46,7 @@ Expects ethereum node to be running and requires a .toml config:
4646
port = 5432
4747
4848
[client]
49-
ipcPath = "/Users/user/Library/Ethereum/geth.ipc"
49+
rpcPath = "/Users/user/Library/Ethereum/geth.ipc"
5050
`,
5151
Run: func(cmd *cobra.Command, args []string) {
5252
subCommand = cmd.CalledAs()
@@ -73,14 +73,17 @@ func backFillAllHeaders(fetcher core.Fetcher, headerRepository core.HeaderReposi
7373
func sync() {
7474
ticker := time.NewTicker(pollingInterval)
7575
defer ticker.Stop()
76-
blockChain := getFetcher()
77-
validateArgs(blockChain)
78-
db := utils.LoadPostgres(databaseConfig, blockChain.Node())
76+
f := getFetcher()
77+
validateArgs(f)
78+
db, err := postgres.NewDB(databaseConfig, f.Node())
79+
if err != nil {
80+
logWithCommand.Fatal(err)
81+
}
7982

80-
headerRepository := repository.NewHeaderRepository(&db)
81-
validator := history.NewHeaderValidator(blockChain, headerRepository, validationWindow)
83+
headerRepository := repository.NewHeaderRepository(db)
84+
validator := history.NewHeaderValidator(f, headerRepository, validationWindow)
8285
missingBlocksPopulated := make(chan int)
83-
go backFillAllHeaders(blockChain, headerRepository, missingBlocksPopulated, startingBlockNumber)
86+
go backFillAllHeaders(f, headerRepository, missingBlocksPopulated, startingBlockNumber)
8487

8588
for {
8689
select {
@@ -94,13 +97,13 @@ func sync() {
9497
if n == 0 {
9598
time.Sleep(3 * time.Second)
9699
}
97-
go backFillAllHeaders(blockChain, headerRepository, missingBlocksPopulated, startingBlockNumber)
100+
go backFillAllHeaders(f, headerRepository, missingBlocksPopulated, startingBlockNumber)
98101
}
99102
}
100103
}
101104

102-
func validateArgs(fetcher *fetcher.Fetcher) {
103-
lastBlock, err := fetcher.LastBlock()
105+
func validateArgs(f *fetcher.Fetcher) {
106+
lastBlock, err := f.LastBlock()
104107
if err != nil {
105108
logWithCommand.Error("validateArgs: Error getting last block: ", err)
106109
}

environments/example.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
port = 5432
55

66
[client]
7-
ipcPath = ""
7+
rpcPath = ""
88

99
[contract]
1010
network = ""

environments/public.toml.example

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@
44
port = 5432
55

66
[client]
7-
ipcPath = <local node's IPC filepath>
7+
rpcPath = <local node's IPC filepath or remote node's HTTP rpc url>
88
levelDbPath = <local node's LevelDB chaindata filepath>

environments/testing.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@
44
port = 5432
55

66
[client]
7-
ipcPath = "http://127.0.0.1:8545"
7+
rpcPath = "http://127.0.0.1:8545"

0 commit comments

Comments
 (0)