Skip to content

Commit

Permalink
feat: indexer service to replace etherscan dependency
Browse files Browse the repository at this point in the history
  • Loading branch information
tuxcanfly authored and mslipper committed Mar 7, 2022
1 parent f8b5803 commit 0838522
Show file tree
Hide file tree
Showing 44 changed files with 10,635 additions and 0 deletions.
135 changes: 135 additions & 0 deletions go/indexer/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
GITCOMMIT := $(shell git rev-parse HEAD)
GITDATE := $(shell git show -s --format='%ct')
GITVERSION := $(shell cat package.json | jq .version)

LDFLAGSSTRING +=-X main.GitCommit=$(GITCOMMIT)
LDFLAGSSTRING +=-X main.GitDate=$(GITDATE)
LDFLAGSSTRING +=-X main.GitVersion=$(GITVERSION)
LDFLAGS := -ldflags "$(LDFLAGSSTRING)"

L1BRIDGE_ABI_ARTIFACT = ../../packages/contracts/artifacts/contracts/L1/messaging/L1StandardBridge.sol/L1StandardBridge.json
L2BRIDGE_ABI_ARTIFACT = ../../packages/contracts/artifacts/contracts/L2/messaging/L2StandardBridge.sol/L2StandardBridge.json

ERC20_ABI_ARTIFACT = ./contracts/ERC20.sol/ERC20.json

SCC_ABI_ARTIFACT = ../../packages/contracts/artifacts/contracts/L1/rollup/StateCommitmentChain.sol/StateCommitmentChain.json

indexer:
env GO111MODULE=on go build -v $(LDFLAGS) ./cmd/indexer

clean:
rm indexer

test:
go test -v ./...

lint:
golangci-lint run ./...

bindings: bindings-l1bridge bindings-l2bridge bindings-l1erc20 bindings-l2erc20 bindings-scc

bindings-l1bridge:
$(eval temp := $(shell mktemp))

cat $(L1BRIDGE_ABI_ARTIFACT) \
| jq -r .bytecode > $(temp)

cat $(L1BRIDGE_ABI_ARTIFACT) \
| jq .abi \
| abigen --pkg l1bridge \
--abi - \
--out bindings/l1bridge/l1_standard_bridge.go \
--type L1StandardBridge \
--bin $(temp)

rm $(temp)

bindings-l2bridge:
$(eval temp := $(shell mktemp))

cat $(L2BRIDGE_ABI_ARTIFACT) \
| jq -r .bytecode > $(temp)

cat $(L2BRIDGE_ABI_ARTIFACT) \
| jq .abi \
| ../../l2geth/build/bin/abigen --pkg l2bridge \
--abi - \
--out bindings/l2bridge/l2_standard_bridge.go \
--type L2StandardBridge \
--bin $(temp)

rm $(temp)

bindings-l1erc20:
$(eval temp := $(shell mktemp))

cat $(ERC20_ABI_ARTIFACT) \
| jq -r .bytecode > $(temp)

cat $(ERC20_ABI_ARTIFACT) \
| jq .abi \
| abigen --pkg l1erc20 \
--abi - \
--out bindings/l1erc20/l1erc20.go \
--type L1ERC20 \
--bin $(temp)

rm $(temp)

bindings-l2erc20:
$(eval temp := $(shell mktemp))

cat $(ERC20_ABI_ARTIFACT) \
| jq -r .bytecode > $(temp)

cat $(ERC20_ABI_ARTIFACT) \
| jq .abi \
| ../../l2geth/build/bin/abigen --pkg l2erc20 \
--abi - \
--out bindings/l2erc20/l2erc20.go \
--type L2ERC20 \
--bin $(temp)

rm $(temp)

bindings-scc:
$(eval temp := $(shell mktemp))

cat $(SCC_ABI_ARTIFACT) \
| jq -r .bytecode > $(temp)

cat $(SCC_ABI_ARTIFACT) \
| jq .abi \
| abigen --pkg scc \
--abi - \
--out bindings/scc/statecommitmentchain.go \
--type StateCommitmentChain \
--bin $(temp)

rm $(temp)

bindings-address-manager:
$(eval temp := $(shell mktemp))

cat $(ADDRESS_MANAGER_ABI_ARTIFACT) \
| jq -r .bytecode > $(temp)

cat $(ADDRESS_MANAGER_ABI_ARTIFACT) \
| jq .abi \
| abigen --pkg address_manager \
--abi - \
--out ./bindings/address_manager/address_manager.go \
--type AddressManager \
--bin $(temp)

.PHONY: \
indexer \
bindings \
bindings-l1bridge \
bindings-l2bridge \
bindings-l1erc20 \
bindings-l2erc20 \
bindings-scc \
clean \
test \
lint
626 changes: 626 additions & 0 deletions go/indexer/bindings/address_manager/address_manager.go

Large diffs are not rendered by default.

1,124 changes: 1,124 additions & 0 deletions go/indexer/bindings/l1bridge/l1_standard_bridge.go

Large diffs are not rendered by default.

842 changes: 842 additions & 0 deletions go/indexer/bindings/l1erc20/l1erc20.go

Large diffs are not rendered by default.

797 changes: 797 additions & 0 deletions go/indexer/bindings/l2bridge/l2_standard_bridge.go

Large diffs are not rendered by default.

788 changes: 788 additions & 0 deletions go/indexer/bindings/l2erc20/l2erc20.go

Large diffs are not rendered by default.

862 changes: 862 additions & 0 deletions go/indexer/bindings/scc/statecommitmentchain.go

Large diffs are not rendered by default.

44 changes: 44 additions & 0 deletions go/indexer/cmd/indexer/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package main

import (
"fmt"
"os"

"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"github.com/urfave/cli"

"github.com/ethereum-optimism/optimism/go/indexer"
"github.com/ethereum-optimism/optimism/go/indexer/flags"
)

var (
GitVersion = ""
GitCommit = ""
GitDate = ""
)

func main() {
// Set up logger with a default INFO level in case we fail to parse flags.
// Otherwise the final crtiical log won't show what the parsing error was.
log.Root().SetHandler(
log.LvlFilterHandler(
log.LvlInfo,
log.StreamHandler(os.Stdout, log.TerminalFormat(true)),
),
)

app := cli.NewApp()
app.Flags = flags.Flags
app.Version = fmt.Sprintf("%s-%s", GitVersion, params.VersionWithCommit(GitCommit, GitDate))
app.Name = "indexer"
app.Usage = "Indexer Service"
app.Description = "Service for indexing deposits and withdrawals " +
"by account on L1 and L2"

app.Action = indexer.Main(GitVersion)
err := app.Run(os.Args)
if err != nil {
log.Crit("Application failed", "message", err)
}
}
173 changes: 173 additions & 0 deletions go/indexer/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
package indexer

import (
"errors"
"time"

"github.com/ethereum/go-ethereum/log"
"github.com/urfave/cli"

"github.com/ethereum-optimism/optimism/go/indexer/flags"
)

var (
// ErrSentryDSNNotSet signals that not Data Source Name was provided
// with which to configure Sentry logging.
ErrSentryDSNNotSet = errors.New("sentry-dsn must be set if use-sentry " +
"is true")
)

type Config struct {
/* Required Params */

// BuildEnv identifies the environment this binary is intended for, i.e.
// production, development, etc.
BuildEnv string

// EthNetworkName identifies the intended Ethereum network.
EthNetworkName string

// ChainID identifies the chain being indexed.
ChainID int64

// L1EthRpc is the HTTP provider URL for L1.
L1EthRpc string

// L2EthRpc is the HTTP provider URL for L1.
L2EthRpc string

// L1AddressManagerAddress is the address of the address manager for L1.
L1AddressManagerAddress string

// L2GenesisBlockHash is the l2 genesis block hash.
L2GenesisBlockHash string

// PollInterval is the delay between querying L2 for more transaction
// and creating a new batch.
PollInterval time.Duration

// Hostname of the database connection.
DBHost string

// Port of the database connection.
DBPort uint64

// Username of the database connection.
DBUser string

// Password of the database connection.
DBPassword string

// Database name of the database connection.
DBName string

/* Optional Params */

// LogLevel is the lowest log level that will be output.
LogLevel string

// LogTerminal if true, prints to stdout in terminal format, otherwise
// prints using JSON. If SentryEnable is true this flag is ignored, and logs
// are printed using JSON.
LogTerminal bool

// SentryEnable if true, logs any error messages to sentry. SentryDsn
// must also be set if SentryEnable is true.
SentryEnable bool

// SentryDsn is the sentry Data Source Name.
SentryDsn string

// SentryTraceRate the frequency with which Sentry should flush buffered
// events.
SentryTraceRate time.Duration

// StartBlockNumber is the block number to start indexing from.
StartBlockNumber uint64

// StartBlockHash is the block hash to start indexing from.
StartBlockHash string

// ConfDepth is the number of confirmations after which headers are
// considered confirmed.
ConfDepth uint64

// MaxHeaderBatchSize is the maximum number of headers to request as a
// batch.
MaxHeaderBatchSize uint64

// MetricsServerEnable if true, will create a metrics client and log to
// Prometheus.
MetricsServerEnable bool

// MetricsHostname is the hostname at which the metrics server is running.
MetricsHostname string

// MetricsPort is the port at which the metrics server is running.
MetricsPort uint64

// DisableIndexer enables/disables the indexer.
DisableIndexer bool
}

// NewConfig parses the Config from the provided flags or environment variables.
// This method fails if ValidateConfig deems the configuration to be malformed.
func NewConfig(ctx *cli.Context) (Config, error) {
cfg := Config{
/* Required Flags */
BuildEnv: ctx.GlobalString(flags.BuildEnvFlag.Name),
EthNetworkName: ctx.GlobalString(flags.EthNetworkNameFlag.Name),
ChainID: ctx.GlobalInt64(flags.ChainIDFlag.Name),
L1EthRpc: ctx.GlobalString(flags.L1EthRpcFlag.Name),
L2EthRpc: ctx.GlobalString(flags.L2EthRpcFlag.Name),
L1AddressManagerAddress: ctx.GlobalString(flags.L1AddressManagerAddressFlag.Name),
L2GenesisBlockHash: ctx.GlobalString(flags.L2GenesisBlockHashFlag.Name),
DBHost: ctx.GlobalString(flags.DBHostFlag.Name),
DBPort: ctx.GlobalUint64(flags.DBPortFlag.Name),
DBUser: ctx.GlobalString(flags.DBUserFlag.Name),
DBPassword: ctx.GlobalString(flags.DBPasswordFlag.Name),
DBName: ctx.GlobalString(flags.DBNameFlag.Name),
/* Optional Flags */
DisableIndexer: ctx.GlobalBool(flags.DisableIndexer.Name),
LogLevel: ctx.GlobalString(flags.LogLevelFlag.Name),
LogTerminal: ctx.GlobalBool(flags.LogTerminalFlag.Name),
SentryEnable: ctx.GlobalBool(flags.SentryEnableFlag.Name),
SentryDsn: ctx.GlobalString(flags.SentryDsnFlag.Name),
SentryTraceRate: ctx.GlobalDuration(flags.SentryTraceRateFlag.Name),
StartBlockNumber: ctx.GlobalUint64(flags.StartBlockNumberFlag.Name),
StartBlockHash: ctx.GlobalString(flags.StartBlockHashFlag.Name),
ConfDepth: ctx.GlobalUint64(flags.ConfDepthFlag.Name),
MaxHeaderBatchSize: ctx.GlobalUint64(flags.MaxHeaderBatchSizeFlag.Name),
MetricsServerEnable: ctx.GlobalBool(flags.MetricsServerEnableFlag.Name),
MetricsHostname: ctx.GlobalString(flags.MetricsHostnameFlag.Name),
MetricsPort: ctx.GlobalUint64(flags.MetricsPortFlag.Name),
}

err := ValidateConfig(&cfg)
if err != nil {
return Config{}, err
}

return cfg, nil
}

// ValidateConfig ensures additional constraints on the parsed configuration to
// ensure that it is well-formed.
func ValidateConfig(cfg *Config) error {
// Sanity check log level.
if cfg.LogLevel == "" {
cfg.LogLevel = "debug"
}

_, err := log.LvlFromString(cfg.LogLevel)
if err != nil {
return err
}

// Ensure the Sentry Data Source Name is set when using Sentry.
if cfg.SentryEnable && cfg.SentryDsn == "" {
return ErrSentryDSNNotSet
}

return nil
}
34 changes: 34 additions & 0 deletions go/indexer/config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package indexer_test

import (
"fmt"
"testing"

indexer "github.com/ethereum-optimism/optimism/go/indexer"
"github.com/stretchr/testify/require"
)

var validateConfigTests = []struct {
name string
cfg indexer.Config
expErr error
}{
{
name: "bad log level",
cfg: indexer.Config{
LogLevel: "unknown",
},
expErr: fmt.Errorf("unknown level: unknown"),
},
}

// TestValidateConfig asserts the behavior of ValidateConfig by testing expected
// error and success configurations.
func TestValidateConfig(t *testing.T) {
for _, test := range validateConfigTests {
t.Run(test.name, func(t *testing.T) {
err := indexer.ValidateConfig(&test.cfg)
require.Equal(t, err, test.expErr)
})
}
}
4 changes: 4 additions & 0 deletions go/indexer/contracts/ERC20.sol/ERC20.dbg.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"_format": "hh-sol-dbg-1",
"buildInfo": "../../build-info/d8a0f286587dfbd9a9d1e4f1e98e7119.json"
}
Loading

0 comments on commit 0838522

Please sign in to comment.