Skip to content
pk910 edited this page Sep 21, 2023 · 17 revisions

Welcome to the dora-the-explorer wiki!

My own test Instances:

Setup

Use Release

To run the explorer, you need to create a configuration file first. Download a copy of the default config and change it for your needs.

Afterwards, download the latest binary for your distribution from the releases page and start the explorer with the following command:

./explorer_linux_amd64 -config=explorer-config.yaml

You should now be able to access the explorer via http://localhost:8080

Use docker image

I'm maintaining a docker image for this explorer: pk910/dora-the-explorer

There are various images available:

  • latest: The latest release
  • unstable: That latest master branch version (automatically built)
  • v1.x.x: Version specific images for all releases.

Follow these steps to run the docker image:

  1. Create a copy of the default config and change it for your needs.
    You'll especially need to configure the chain, beaconapi & database sections.
    wget -O explorer-config.yaml https://raw.githubusercontent.com/pk910/dora-the-explorer/master/config/default.config.yml
    nano explorer-config.yaml
    
  2. Start the container
    docker run -d --restart unless-stopped --name=beaconlight -v $(pwd):/config -p 8080:8080 -it pk910/dora-the-explorer:latest -config=/config/explorer-config.yaml
    

You should now be able to access the explorer via http://localhost:8080

read logs:

docker logs beaconlight --follow

stop & remove container:

docker stop beaconlight

docker rm -f beaconlight

Build from source

To build the explorer from source, you need a machine with go 1.20 and a C compiler installed.

Run the following commands to clone the repository and compile the binaries:

git clone https://github.com/pk910/dora-the-explorer.git
cd dora-the-explorer
make

This should build the binaries to ./bin.
Afterwards, you can run the binary as described in the "Use Release" section.

Dependencies

The explorer has no mandatory external dependencies. It can even run completely in memory only.
However, for best performance I recommend using a PostgreSQL database.

Configuration

There is a default configuration that should be used as a base for your own explorer configuration.
You can find the default config here: /config/default.config.yml

The configuration sections are described more detailed below:

chain

The chain section configures the chain details the explorer is running for.

You can either use one of the built in configurations via the name setting or supply your own custom network config via the configPath/genesisTimestamp settings.

The following network configs are built in and can be used via the name setting:

  • Mainnet (mainnet)
  • Goerli (prater)
  • Sepolia (sepolia)

To use a explorer in a custom testnet, set name to an empty string and supply the network genesis config (often called config.yaml) via the configPath setting.
If your testnet does not start from MIN_GENESIS_TIME + GENESIS_DELAY (eg. because min validator threshold was not reached at genesis), you need to supply the actual genesis time via the genesisTimestamp setting.

Apart from the logic above, you may override the chain name (defaults to CONFIG_NAME) which is displayed on various explorer pages via the displayName setting.

chain:
  # use built in config by name ("mainnet", "prater", "sepolia")
  name: "mainnet"
  
  # or use custom network config
  #genesisTimestamp: 1688126460
  #configPath: "../ephemery/config.yaml"
  
  # override chain name for UI
  displayName: "My Testnet"

server

The server section configures the host and port, which the internal webserver will listen on.

I strongly recommend using the explorer with a proper webserver (nginx, apache, ...) in front, which supports SSL and stuff.

server:
  host: "localhost" # Address to listen on
  port: "8080" # Port to listen on

frontend

The frontend sections contains all frontend related settings.

The siteName & siteSubtitle settings are used to set the site title and subtitle. The name/subtitle is shown in the header of all pages and is also part of the html title tag.

The ethExplorerLink setting is used to configure links to a EL block explorer. When configured, all EL related hashed / block numbers are linked to this EL explorer following the standardized linking schema.

The validatorNamesYaml / validatorNamesInventory settings can be used to give validator indexes a name.
You can either supply validator names via a yaml file following this format via validatorNamesYaml.
Or you can configure the explorer to fetch validator names from a pandaops inventory api via validatorNamesYaml (see this for more details on the api).

frontend:
  enabled: true # Enable or disable to web frontend
  debug: false # for development only, loads templates and static files from FS instead of using the embedded files

  # Name of the site, displayed in the title tag
  siteName: "Beaconchain Light"
  siteSubtitle: "Ephemery"
  
  # link to EL Explorer
  ethExplorerLink: "https://explorer.ephemery.dev/"

  # file or inventory url to load validator names from
  validatorNamesYaml: "validator_names.yaml"
  #validatorNamesInventory: "https://config.4844-devnet-7.ethpandaops.io/api/v1/nodes/validator-ranges"

beaconapi

The beaconapi section configures the underlying beacon node api which is used to fetch all beaconchain data from.

The most important setting in this section is the endpoint setting, which configures the URL to the underlying bn API.

The explorer uses the default API endpoints only, so it should be compatible with any CL client.

Due to the need to fetch assignment data for any epoch quickly, the beacon node needs to run with a higher amount of restore points.
For maximum performance, you may lower the restore point interval to 32 slots (default is much higher), however this comes with a significant increase of storage needs and may only be suitable for small testnets.
The lighthouse flag to set the restore point interval is --slots-per-restore-point 32

The endpoint url supports basic http authentication by encoding username & password via http://<user>:<password>@127.0.0.1:5052/.

Besides of the endpoint there are also some caching related settings in this section. This cache is mostly used to cache page models (not RPC calls), so the location of these settings might be moved to the frontend section in future :)
There are two caching types supported:

  • Local caching: cache directly in the explorer process, limited by the localCacheSize setting (in MByte)
  • Redis caching: remote redis cache, configured via redisCacheAddr.
    Might be left out entirely if not needed.
    To prevent collisions on a shared redis cache, use the redisCachePrefix setting to configure a unique key prefix.
beaconapi:
  # CL Client RPC
  endpoint: "http://127.0.0.1:5052"

  # local cache for page models
  localCacheSize: 100 # 100MB

  # remote cache for page models
  redisCacheAddr: ""
  redisCachePrefix: ""

indexer

The indexer section contains all settings related to indexing.

The explorer includes a indexing algorithm that keeps track of blocks from the latest epochs in memory.
This indexer data is used for live aggregations and caching too, so it is a required part of the explorer.

On startup, the explorer fills up the local cache with all blocks from unfinalized epochs. The explorer needs to know about all non-finalized blocks in memory to work properly. To avoid a big memory consumption, the explorer moves block bodies from old unfinalized epochs into the db. The inMemoryEpochs setting controls how many unfinalized block bodies are kept in memory before being moved to the DB.

On finalization, the explorer does the actual block & epoch processing. This includes doing vote & other aggregations and writing blocks & epoch stats to the db.

Besides of indexing (which takes care of the head), there is also a synchronizer which takes care of indexing already passed epochs.
Synchronizing old epochs can be disabled via the disableSynchronizer setting.

In multi process environments (where the explorer runs on multiple servers for load balancing), all writing db access must be done by one node only.
Updating the index from multiple explorer instances may cause DB inconsistencies. To disable writing to the database, you can set disableIndexWriter to true on non-primary nodes.

During synchronization, there is a cooldown after each epoch to not overwhelm the bn api. The cooldown can be configured via syncEpochCooldown. It can be disabled, but will cause some high load on the the CL node during synchronization then ;)

indexer:

  # max number of epochs to keep in memory
  inMemoryEpochs: 3

  # disable everything that writes to the db (indexer just maintains local cache)
  disableIndexWriter: false
  
  # disable synchronizer (don't index historic epochs)
  disableSynchronizer: false

  # number of seconds to wait between each epoch (don't overload CL client)
  syncEpochCooldown: 2

database

The database section contains all settings related to the explorer database.

There are different database engines supported:

  • sqlite Local SQLite3 database
  • pgsql PgSQL database

The SQLite engine stores all data in a local file, which is specified via the file setting. You may run the explorer completely in memory by setting the filename to :memory:. However, this comes with the negative effect of having to resynchronize the chain after each restart.

The PgSQL engine allows defining a separate set of writer credentials to allow more complex replication setups.
For small testnets / low access activity it's totally fine to use a local database and suppress the pgsqlWriter section completely.
When specifying both sections, the explorer uses the normal credentials for all SELECT statements, and executes INSERT/UPDATE/DELETE queries via the writer connection.

You don't need to care about schema initialization or upgrades. The explorer will take care of that itself.

database:
  engine: "sqlite" # sqlite / pgsql

  # sqlite settings
  sqlite:
    file: "./explorer-db.sqlite"

  # pgsql settings
  pgsql:
    host: "127.0.0.1"
    port: 5432
    user: ""
    password: ""
    name: ""
  pgsqlWriter: # optional separate writer connection (used for replication setups)
    host: "127.0.0.1"
    port: 5432
    user: ""
    password: ""
    name: ""