|
| 1 | +# Blockchain nodes |
| 2 | + |
| 3 | +It is highly advised that if you did decide to play around with these Docker containers that you use an existing Ethereum enviroment builder |
| 4 | +instead of trying to put all the pieces together. That's especially important for Proof-Of-Stake networks, where the setup is a multi-stage |
| 5 | +operation that needs to be executed in specific order and where multiple containers need access to the same (or shared) state. |
| 6 | + |
| 7 | +By default, each of supported clients has a default image version that's defined [here](https://github.com/smartcontractkit/chainlink-testing-framework/blob/main/lib/docker/ethereum/images.go). |
| 8 | +All of them apart from Reth, come in two flavours: one that is a Proof-Of-Stake (Ethereum 2.0) network and another that's a Proof-Of-Work/Authority (Ethereum 1.0). Reth has only the former |
| 9 | +since the latter was never implemented by its creators. |
| 10 | + |
| 11 | +All of these epehemeral networks are using a grossly simplified configuration that is composed of a single blockchain node. Technically that's also true, in case of PoS networks, |
| 12 | +even though they are running three containers: |
| 13 | +* execution layer container |
| 14 | +* consensus layer container |
| 15 | +* validator |
| 16 | + |
| 17 | +> [!NOTE] |
| 18 | +> We use our own fork of [Ethereum Genesis Generator](https://github.com/ethpandaops/ethereum-genesis-generator) to |
| 19 | +> create genesis files both for PoW/PoA and PoS Ethereum networks. |
| 20 | +
|
| 21 | +## Execution Layer |
| 22 | +Following execution layers are available |
| 23 | +* Besu |
| 24 | +* Erigon |
| 25 | +* Geth |
| 26 | +* Nethermind |
| 27 | +* Reth |
| 28 | + |
| 29 | +## Consensus Layer |
| 30 | +Only one consensus client is available: Prysm. |
| 31 | + |
| 32 | +# Quick start |
| 33 | +The simplest of starting a new Ethereum network is by specifying only the execution layer: |
| 34 | +```go |
| 35 | +builder := NewEthereumNetworkBuilder() |
| 36 | +cfg, err := builder. |
| 37 | + WithExecutionLayer(types.ExecutionLayer_Nethermind). |
| 38 | + Build() |
| 39 | +if err != nil { |
| 40 | + panic(err) |
| 41 | +} |
| 42 | + |
| 43 | +net, rpcs, err := cfg.Start() |
| 44 | +if err != nil { |
| 45 | + panic(err) |
| 46 | +} |
| 47 | +``` |
| 48 | + |
| 49 | +If no Ethereum version is specified, Ethereum 1.0 (pre-Merge) will be used. |
| 50 | + |
| 51 | +# Ethereum 2 network |
| 52 | +To start Ethereum 2.0 network you need to pass one more parameter to the builder: |
| 53 | +```go |
| 54 | +builder := NewEthereumNetworkBuilder() |
| 55 | +cfg, err := builder. |
| 56 | + // notice the new parameter |
| 57 | + WithEthereumVersion(config_types.EthereumVersion_Eth2). |
| 58 | + WithExecutionLayer(config_types.ExecutionLayer_Geth). |
| 59 | + Build() |
| 60 | +if err != nil { |
| 61 | + panic(err) |
| 62 | +} |
| 63 | + |
| 64 | +net, rpcs, err := cfg.Start() |
| 65 | +if err != nil { |
| 66 | + panic(err) |
| 67 | +} |
| 68 | +``` |
| 69 | + |
| 70 | +> [!NOTE] |
| 71 | +> It takes significantly longer to boot up an Ethereum 2.0 network due to number of |
| 72 | +> containers involved. 1 minute long wait times are not unheard of, so if startup |
| 73 | +> speed is crucial think if Ethereum 1.0 is good enough for your use case. |
| 74 | +
|
| 75 | +# Custom docker images |
| 76 | +If you don't want to use default image versions you can pass custom ones in the following manner: |
| 77 | +```go |
| 78 | +builder := NewEthereumNetworkBuilder() |
| 79 | +cfg, err := builder. |
| 80 | + WithCustomDockerImages(map[config.ContainerType]string{ |
| 81 | + config.ContainerType_ExecutionLayer: "ethereum/client-go:v1.15.0", |
| 82 | + }). |
| 83 | + Build() |
| 84 | +if err != nil { |
| 85 | + panic(err) |
| 86 | +} |
| 87 | + |
| 88 | +net, rpcs, err := cfg.Start() |
| 89 | +if err != nil { |
| 90 | + panic(err) |
| 91 | +} |
| 92 | +``` |
| 93 | +Where available container types are: |
| 94 | +```go |
| 95 | +const ( |
| 96 | + ContainerType_ExecutionLayer ContainerType = "execution_layer" |
| 97 | + ContainerType_ConsensusLayer ContainerType = "consensus_layer" |
| 98 | + ContainerType_ConsensusValidator ContainerType = "consensus_validator" |
| 99 | + ContainerType_GenesisGenerator ContainerType = "genesis_generator" |
| 100 | + ContainerType_ValKeysGenerator ContainerType = "val_keys_generator" |
| 101 | +) |
| 102 | +``` |
| 103 | +When passing custom docker image for execution layer you don't need to use neither `WithEthereumVersion()` nor `WithExecutionLayer()` functions |
| 104 | +as we will get these from the Docker image. |
| 105 | + |
| 106 | +> [!NOTE] |
| 107 | +> There are two useful "synthetic" Docker tags you can use with custom images: |
| 108 | +> - `latest_available` - which represents the latest release (including pre-releases) |
| 109 | +> - `latest_stable` - which represents latest **stable** release |
| 110 | +
|
| 111 | +# Existing Docker network(s) |
| 112 | +By default, the chain will be started on a new Docker network with random name. If you want it to connect to existing one instead, use the following option: |
| 113 | +```go |
| 114 | +builder := NewEthereumNetworkBuilder() |
| 115 | +cfg, err := builder. |
| 116 | + WithExecutionLayer(types.ExecutionLayer_Nethermind). |
| 117 | + WithDockerNetworks([]string{"my-existing-network"}). |
| 118 | + Build() |
| 119 | +if err != nil { |
| 120 | + panic(err) |
| 121 | +} |
| 122 | +``` |
| 123 | + |
| 124 | +# Chain customisation |
| 125 | +Below you will find a description of easily customisable parameters of the chain or its startup. |
| 126 | + |
| 127 | +## Slots per epoch and seconds per slot (Ethereum 2.0 only) |
| 128 | +These parameters control how fast epochs progress. |
| 129 | + |
| 130 | +`Seconds per slot` represents the number of seconds that validator have to vote on blocks. |
| 131 | +The lower the value the faster the epoch finalisation. If it's too low, validators will not be |
| 132 | +able to vote and no new blocks will be produced. Minimum allowed value is `3`. |
| 133 | + |
| 134 | +`Slots per epoch` represent the number of voting runds per epoch. The lower the number, the faster |
| 135 | +the finalization. Minimum allowed value is `2.` |
| 136 | + |
| 137 | +## ChainID |
| 138 | +Can be anything as long as it's an integer. |
| 139 | + |
| 140 | +## Addresses to fund |
| 141 | +Addresses that will be funded with `9000000000000000000000000000 wei` in the genesis. |
| 142 | + |
| 143 | +## Hard Forks (Ethereum 2.0 only) |
| 144 | +Map of hard fork name to epoch, in which the fork should happen. Has to be `> 0`. It's useful for testing |
| 145 | +how software will behave during the fork. Currently, the only fork that's supported is `Deneb`, but it can |
| 146 | +only be used with Docker images that belong to "pre-Deneb times" and running on `Shanghai` version of Ethereum 2.0 |
| 147 | +(so pretty old versions). For the latest images there are no supported future forks as of time of this documentation |
| 148 | +creation there were no dates set for any of the incoming forks (which means none of them is supported by neither |
| 149 | +execution nor consensus layer clients). |
| 150 | + |
| 151 | +## Validator count (Ethereum 2.0 only) |
| 152 | +Number of validators to run. `4` is a minimum allowed. |
| 153 | + |
| 154 | +## Genesis Delay (Ethereum 2.0 only) |
| 155 | +Extra delay added to genesis block timestamp to be sure that both layers are up and running before it happens. Increasing it could be |
| 156 | +useful in case of running on very slow system. |
| 157 | + |
| 158 | +## Default values |
| 159 | +Default chain config comes with the following values: |
| 160 | +```toml |
| 161 | +seconds_per_slot=12 |
| 162 | +slots_per_epoch=6 |
| 163 | +genesis_delay=15 |
| 164 | +validator_count=8 |
| 165 | +chain_id=1337 |
| 166 | +addresses_to_fund=["0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"] |
| 167 | +``` |
| 168 | + |
| 169 | +# Other useful options |
| 170 | +## Blockchain node log level |
| 171 | +By default, all blockchain nodes use `info` log level, but you can change that with the following option: |
| 172 | +```go |
| 173 | +builder := NewEthereumNetworkBuilder() |
| 174 | +cfg, err := builder. |
| 175 | + WithCustomDockerImages(map[config.ContainerType]string{ |
| 176 | + config.ContainerType_ExecutionLayer: "ethereum/client-go:v1.15.0", |
| 177 | + }). |
| 178 | + WithNodeLogLevel("debug"). |
| 179 | + Build() |
| 180 | +if err != nil { |
| 181 | + panic(err) |
| 182 | +} |
| 183 | +``` |
| 184 | +This configuration is applied only to execution layer nodes. Following values are supported: |
| 185 | +* `trace` |
| 186 | +* `debug` |
| 187 | +* `info` |
| 188 | +* `warn` |
| 189 | +* `error` |
| 190 | + |
| 191 | +## Waiting for first epoch finalization (Ethereum 2.0 only) |
| 192 | +In case you want the network to wait until first epoch has been finalised you can use the following option: |
| 193 | +```go |
| 194 | +builder := NewEthereumNetworkBuilder() |
| 195 | +cfg, err := builder. |
| 196 | + WithCustomDockerImages(map[config.ContainerType]string{ |
| 197 | + config.ContainerType_ExecutionLayer: "ethereum/client-go:v1.15.0", |
| 198 | + }). |
| 199 | + WithWaitingForFinalization(). |
| 200 | + Build() |
| 201 | +if err != nil { |
| 202 | + panic(err) |
| 203 | +} |
| 204 | +``` |
| 205 | + |
| 206 | +# Accessing containers from inside and outside of the Docker network |
| 207 | +Function that starts the environment returns an error or two values: |
| 208 | +* instance of `blockchain.Network` that can be used to start our test clients |
| 209 | +* instance of `test_env.RpcProvider` that has a list of useful endpoints |
| 210 | + |
| 211 | +These endpoints come in two flavours: |
| 212 | +* public (accessible from other Docker networks and the host machine) |
| 213 | +* private (accessible only from inside the same Docker network) |
| 214 | + |
| 215 | +And are the HTTP and WS endpoints of the execution layer clients, ones which the Chainlink Node |
| 216 | +needs to communicate with. Beacon Chain (consensus layer) endpoints are not exposed. |
| 217 | + |
| 218 | +If you're wondering which one to use, the usual case would be: |
| 219 | +* public for the Ethereum Client that will interact with the chain, deploy contracts, etc. |
| 220 | +* private for the Chainlink Node if it uses the same Docker network as the chain, public otherwise |
| 221 | + |
| 222 | +# Ethereum 2.0 container creation sequence |
| 223 | +Since the sequence of container creation and interaction for Ethereum 2.0 is much more complicated |
| 224 | +than for Ethereum 1.0 (where we only need to start a single container) below you will find a sequence |
| 225 | +diagram that explains it in more detail: |
| 226 | + |
| 227 | +```mermaid |
| 228 | +--- |
| 229 | +title: Ethereum 2.0 container creation sequence |
| 230 | +--- |
| 231 | +sequenceDiagram |
| 232 | + participant Host Machine |
| 233 | + participant Validators Keys Generator |
| 234 | + participant Genesis Generator |
| 235 | + participant Execution Layer (e.g. Besu or Geth) |
| 236 | + participant Consensus Layer (Prysm Beacon Chain) |
| 237 | + participant Consensus Layer (Prysm Validator) |
| 238 | + participant After Genesis Helper |
| 239 | + participant User |
| 240 | + Validators Keys Generator->>Host Machine: Generate new validators keys<br/> and save them to on the host |
| 241 | + Genesis Generator->>Host Machine: Generate Ethereum 1.0 and Ethereum 2.0 genesis files<br/> and save them on the host |
| 242 | + Host Machine->>Execution Layer (e.g. Besu or Geth): Read Ehtereum 1.0 genesis and start |
| 243 | + Host Machine->>Consensus Layer (Prysm Beacon Chain): Read Ehtereum 2.0 genesis and start |
| 244 | + Consensus Layer (Prysm Beacon Chain)->>Execution Layer (e.g. Besu or Geth): Conntect and start<br/> following the chain |
| 245 | + Host Machine->>Consensus Layer (Prysm Validator): Read validator keys and start |
| 246 | + Consensus Layer (Prysm Validator)->>Consensus Layer (Prysm Beacon Chain): Connect and start voting on blocks |
| 247 | + loop observe chain |
| 248 | + After Genesis Helper->>Execution Layer (e.g. Besu or Geth): Wait until new blocks are produced |
| 249 | + end |
| 250 | + After Genesis Helper->>User: Allow to proceed<br/> and interact with the chain |
| 251 | +``` |
0 commit comments