PageSourceSearch

https://docs.kurtosis.com/assets/js/485cdbc9.9fe48359.js

js kurtosis.com collected 2026-10-03 21:43:34 UTC 30,212 bytes, 1 lines download raw bytes

1"use strict";(globalThis.webpackChunkkurtosis_docs=globalThis.webpackChunkkurtosis_docs||[]).push([[553],{9074(e,t,n){n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>a,default:()=>d,frontMatter:()=>r,metadata:()=>o,toc:()=>c});const o=JSON.parse('{"id":"guides/how-to-full-mev-with-eth2-package","title":"How to launch a private Ethereum testnet with Flashbot\'s MEV Boost implementation of Proposer Builder Separation (PBS)","description":"Here are some quick short-cuts for folks who would prefer:","source":"@site/docs/guides/how-to-full-mev-with-eth2-package.md","sourceDirName":"guides","slug":"/how-to-full-mev-with-ethereum-package","permalink":"/how-to-full-mev-with-ethereum-package","draft":false,"unlisted":false,"tags":[],"version":"current","sidebarPosition":12,"frontMatter":{"title":"How to launch a private Ethereum testnet with Flashbot\'s MEV Boost implementation of Proposer Builder Separation (PBS)","sidebar_label":"Launch a testnet with MEV infra","slug":"/how-to-full-mev-with-ethereum-package","toc_max_heading_level":2,"sidebar_position":12},"sidebar":"main","previous":{"title":"Build your own testnet from scratch","permalink":"/how-to-compose-your-own-testnet"},"next":{"title":"Running Docker Compose","permalink":"/docker-compose"}}');var s=n(4848),i=n(8453);const r={title:"How to launch a private Ethereum testnet with Flashbot's MEV Boost implementation of Proposer Builder Separation (PBS)",sidebar_label:"Launch a testnet with MEV infra",slug:"/how-to-full-mev-with-ethereum-package",toc_max_heading_level:2,sidebar_position:12},a=void 0,l={},c=[{value:"Why <code>ethereum-package</code>?",id:"why-ethereum-package",level:4},{value:"What if I only want the MEV parts?",id:"what-if-i-only-want-the-mev-parts",level:4},{value:"Brief overview of the architecture",id:"brief-overview-of-the-architecture",level:2},{value:"Caveats:",id:"caveats",level:4},{value:"Quickstart",id:"quickstart",level:2},{value:"Install dependencies",id:"install-dependencies",level:4},{value:"Configure your network",id:"configure-your-network",level:4},{value:"Launch the network with <code>full MEV</code>",id:"launch-the-network-with-full-mev",level:4},{value:"Visit the website to see registered validators and delivered payloads",id:"visit-the-website-to-see-registered-validators-and-delivered-payloads",level:4},{value:"Roadmap",id:"roadmap",level:2},{value:"Conclusion",id:"conclusion",level:2}];function h(e){const t={a:"a",admonition:"admonition",code:"code",em:"em",h2:"h2",h4:"h4",img:"img",li:"li",ol:"ol",p:"p",pre:"pre",ul:"ul",...(0,i.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)(t.admonition,{type:"tip",children:[(0,s.jsx)(t.p,{children:"Here are some quick short-cuts for folks who would prefer:"}),(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:["To get going right away: install Kurtosis & Docker and then run: ",(0,s.jsx)(t.code,{children:'kurtosis run github.com/ethpandaops/ethereum-package \'{"mev_type": "full"}\''})]}),"\n",(0,s.jsxs)(t.li,{children:["To dive into the code example: visit the repository ",(0,s.jsx)(t.a,{href:"https://github.com/ethpandaops/ethereum-package",children:"here"}),"."]}),"\n",(0,s.jsxs)(t.li,{children:["Not to run this package on their local machine: try it out on the ",(0,s.jsx)(t.a,{href:"https://gitpod.io/?autoStart=true&editor=code#https://github.com/ethpandaops/ethereum-package",children:"Kurtosis playground"})]}),"\n"]})]}),"\n",(0,s.jsxs)(t.p,{children:["We're elated to share that the ",(0,s.jsx)(t.a,{href:"https://github.com/ethpandaops/ethereum-package",children:(0,s.jsx)(t.code,{children:"ethereum-package"})})," now supports the Flashbot's implementation of ",(0,s.jsx)(t.a,{href:"https://ethereum.org/en/roadmap/pbs/",children:"Proposer-Builder Separation (PBS)"})," using ",(0,s.jsx)(t.a,{href:"https://boost.flashbots.net",children:"MEV-Boost"})," protocol."]}),"\n",(0,s.jsx)(t.p,{children:"This milestone marks a huge step forward in the journey towards a full, in-protocol PBS implementation for Proof-of-Stake Ethereum as developers across the ecosystem now have a way to instantiate fully functioning testnets to validate functionality, behvaior, and scales across all client combinations with a Builder API implementation (Flashbots', in this case)."}),"\n",(0,s.jsxs)(t.p,{children:["Keep reading to learn ",(0,s.jsx)(t.a,{href:"#brief-overview-of-the-architecture",children:"how it all works"})," & ",(0,s.jsxs)(t.a,{href:"#quickstart",children:["how to get started with the ",(0,s.jsx)(t.code,{children:"ethereum-package"})]}),"."]}),"\n",(0,s.jsxs)(t.h4,{id:"why-ethereum-package",children:["Why ",(0,s.jsx)(t.code,{children:"ethereum-package"}),"?"]}),"\n",(0,s.jsxs)(t.p,{children:["As a reminder, the ",(0,s.jsx)(t.a,{href:"https://github.com/ethpandaops/ethereum-package",children:(0,s.jsx)(t.code,{children:"ethereum-package"})})," is a reproducible and portable environment definition that should be used to bootstrap & deploy private testnets. The package will function the exact same way locally or in the cloud over Docker or Kubernetes, supports all major Execution Layer (EL) and Consensus Layer (CL) client implementations, and can be scaled to whatever size your team needs - limited only by your underlying hardware/backend."]}),"\n",(0,s.jsx)(t.h4,{id:"what-if-i-only-want-the-mev-parts",children:"What if I only want the MEV parts?"}),"\n",(0,s.jsxs)(t.p,{children:["And if that wasn't enough, Kurtosis environment definitions (known as ",(0,s.jsx)(t.a,{href:"https://docs.kurtosis.com/advanced-concepts/packages/",children:"Packages"}),") are entirely composable, meaning you can define and build-your-own private testnet using only the parts you need and with the option of adding your own services (e.g. MEV searcher tools). Feel free to check out the following ",(0,s.jsx)(t.a,{href:"https://github.com/kurtosis-tech/2-el-cl-mev-package/blob/main/main.star",children:"code example"}),"."]}),"\n",(0,s.jsx)(t.h2,{id:"brief-overview-of-the-architecture",children:"Brief overview of the architecture"}),"\n",(0,s.jsxs)(t.p,{children:["Explicitly, the ",(0,s.jsx)(t.a,{href:"https://github.com/ethpandaops/ethereum-package",children:(0,s.jsx)(t.code,{children:"ethereum-package"})})," supports two modes: ",(0,s.jsx)(t.code,{children:"full-mev"})," and ",(0,s.jsx)(t.code,{children:"mock-mev"}),"."]}),"\n",(0,s.jsxs)(t.p,{children:["The former mode is valuable for validating behavior between the protocol and out-of-protocol middle-ware infrastru
1cture (e.g. searchers, relayer) and instantiates ",(0,s.jsx)(t.a,{href:"https://github.com/flashbots/mev-boost",children:(0,s.jsx)(t.code,{children:"mev-boost"})}),", ",(0,s.jsx)(t.a,{href:"https://github.com/flashbots/mev-boost-relay",children:(0,s.jsx)(t.code,{children:"mev-relay"})}),", ",(0,s.jsx)(t.a,{href:"https://github.com/flashbots/mev-flood",children:(0,s.jsx)(t.code,{children:"mev-flood"})})," and Flashbot's Geth-based block builder called ",(0,s.jsx)(t.a,{href:"https://github.com/flashbots/builder",children:(0,s.jsx)(t.code,{children:"mev-builder"})}),". The latter mode will only spin up ",(0,s.jsx)(t.a,{href:"https://github.com/flashbots/mev-boost",children:(0,s.jsx)(t.code,{children:"mev-boost"})})," and a ",(0,s.jsx)(t.a,{href:"https://github.com/marioevz/mock-builder",children:(0,s.jsx)(t.code,{children:"mock-builder"})}),", which is useful for testing in-protocol behavior like testing if clients are able to call the relayer for a payload via ",(0,s.jsx)(t.code,{children:"mev-boost"}),", reject invalid payloads, or trigger the ",(0,s.jsx)(t.a,{href:"https://hackmd.io/@ralexstokes/BJn9N6Thc",children:"circuit breaker"})," to ensure functionality of the beacon chain."]}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"ethereum-package"})," with MEV emulation are already in use by client teams to help uncover bugs (examples ",(0,s.jsx)(t.a,{href:"https://github.com/prysmaticlabs/prysm/pull/12736",children:"here"})," and ",(0,s.jsx)(t.a,{href:"https://github.com/NethermindEth/nethermind/commit/4d805769159dc0717aa1ba38cc3ebc53f9a375cf",children:"here"}),")."]}),"\n",(0,s.jsx)(t.p,{children:"Everything you see below in the architecture diagram gets configured, initialized, and bootstrapped together by Kurtosis."}),"\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.img,{alt:"mev-arch",src:n(1897).A+"",width:"1618",height:"1168"})}),"\n",(0,s.jsx)(t.h4,{id:"caveats",children:"Caveats:"}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:["The ",(0,s.jsx)(t.code,{children:"mev-boost-relay"})," service requires Capella at an epoch of non-zero. For the ethereum-package, the Capella fork is set to happen after the first epoch to be started up and fully connected to the CL client."]}),"\n",(0,s.jsxs)(t.li,{children:["Validators (64 per node by default, so 128 in the example in this guide) will get registered with the relay automatically after the 2nd epoch. This registration process is simply a configuration addition to the mev-boost config - which Kurtosis will automatically take care of as part of the set up. This means that the ",(0,s.jsx)(t.code,{children:"mev-relay"})," infrastructure only becomes aware of the existence of the validators after the 2nd epoch."]}),"\n",(0,s.jsxs)(t.li,{children:["After the 3rd epoch, the ",(0,s.jsx)(t.code,{children:"mev-relay"})," service will begin to receive execution payloads (",(0,s.jsx)(t.code,{children:"eth_sendPayload"}),", which does not contain transaction content) from the ",(0,s.jsx)(t.code,{children:"mev-builder"})," service (or ",(0,s.jsx)(t.code,{children:"mock-builder"})," in ",(0,s.jsx)(t.code,{children:"mock-mev"})," mode)."]}),"\n",(0,s.jsxs)(t.li,{children:["Validators will then start to receive validated execution payload headers from the ",(0,s.jsx)(t.code,{children:"mev-relay"})," service (via ",(0,s.jsx)(t.code,{children:"mev-boost"}),") after the 4th epoch. The validator selects the most valuable header, signs the payload, and returns the signed header to the relay - effectively proposing the payload of transactions to be included in the soon-to-be-proposed block. Once the relay verifies the block proposer's signature, the relay will respond with the full execution payload body (incl. the transaction contents) for the validator to use when proposing a ",(0,s.jsx)(t.code,{children:"SignedBeaconBlock"})," to the network."]}),"\n",(0,s.jsxs)(t.li,{children:["You may notice in the ",(0,s.jsx)(t.code,{children:"mev-flood"})," logs that there may be transactions that fail to get processed by the node(s) in your devnet with the following errors: ",(0,s.jsx)(t.code,{children:"Error: replacement fee too low [ See: https://links.ethers.org/v5-errors-REPLACEMENT_UNDERPRICED ]"}),". Don't be alarmed: this can happen when transactions are sent too quickly to the network, resulting in the node receiving transactions with the same nonce. When this happens, the node rejects the transactions becauase the node assumes you're trying to replace the old pending transaction with a new one. You can change the frequency using ",(0,s.jsx)(t.code,{children:"mev-flood"}),"'s ",(0,s.jsx)(t.code,{children:"--secondsPerBundle (-p )"})," flag in the ",(0,s.jsxs)(t.a,{href:"https://github.com/flashbots/mev-flood#send-swaps",children:[(0,s.jsx)(t.code,{children:"spam"})," command"]}),"."]}),"\n"]}),"\n",(0,s.jsx)(t.admonition,{type:"note",children:(0,s.jsxs)(t.p,{children:["Quick aside on what ",(0,s.jsx)(t.code,{children:"mev-flood"})," does:\nOnce the network is online, ",(0,s.jsx)(t.code,{children:"mev-flood"})," will deploy UniV2 smart contracts, provision liquidity on UniV2 pairs, & begin to send a constant stream of UniV2 swap transactions to the network's public mempool. Depending on the mode you're running, either the ",(0,s.jsx)(t.code,{children:"mock-builder"})," or Flashbot's ",(0,s.jsx)(t.code,{children:"mev-builder"}),", the transactions will be bundled into payloads for downstream use by the relayer or by validators themselves. It is important to note that ",(0,s.jsx)(t.code,{children:"mev-flood"})," will only be initialized with the ",(0,s.jsx)(t.code,{children:"full-mev"})," set up and will send transactions with a non-zero block value. Read more about ",(0,s.jsxs)(t.a,{href:"https://github.com/flashbots/mev-flood",children:[(0,s.jsx)(t.code,{children:"mev-flood"})," here"]}),"."]})}
1),"\n",(0,s.jsx)(t.h2,{id:"quickstart",children:"Quickstart"}),"\n",(0,s.jsxs)(t.p,{children:["Leveraging the ",(0,s.jsx)(t.a,{href:"https://github.com/ethpandaops/ethereum-package",children:(0,s.jsx)(t.code,{children:"ethereum-package"})})," is simple. In this short quickstart, you will:"]}),"\n",(0,s.jsxs)(t.ol,{children:["\n",(0,s.jsx)(t.li,{children:"Install Docker & Kurtosis locally."}),"\n",(0,s.jsxs)(t.li,{children:["Configure your network using a ",(0,s.jsx)(t.code,{children:".yaml"})," file."]}),"\n",(0,s.jsxs)(t.li,{children:["Run a single command to launch your network with ",(0,s.jsx)(t.code,{children:"full MEV"}),"."]}),"\n",(0,s.jsxs)(t.li,{children:["Visit the website to witness payloads being delivered from the Relayer to the ",(0,s.jsx)(t.code,{children:"mev-boost"})," sidecar connected to each validator (for block proposals)."]}),"\n"]}),"\n",(0,s.jsx)(t.h4,{id:"install-dependencies",children:"Install dependencies"}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.a,{href:"https://docs.docker.com/get-docker/",children:"Install Docker"})," and ensure the Docker Daemon is running on your machine (e.g. open Docker Desktop). You can quickly check if Docker is running by running: ",(0,s.jsx)(t.code,{children:"docker image ls"})," from your terminal to see all your Docker images."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.a,{href:"https://docs.kurtosis.com/install/#ii-install-the-cli",children:"Install Kurtosis"})," or ",(0,s.jsx)(t.a,{href:"https://docs.kurtosis.com/upgrade",children:"upgrade Kurtosis to the latest version"}),". You can check if Kurtosis is running using the command: ",(0,s.jsx)(t.code,{children:"kurtosis version"}),", which will print your current Kurtosis engine version and CLI version."]}),"\n"]}),"\n",(0,s.jsx)(t.h4,{id:"configure-your-network",children:"Configure your network"}),"\n",(0,s.jsxs)(t.p,{children:["Next, create a file titled: ",(0,s.jsx)(t.code,{children:"ethereum-package-params.yaml"})," in your working directory and populate it with:"]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-yaml",children:"participants:\n\t- el_client_type: geth\n\t\tel_client_image: ethereum/client-go:latest\n\t\tel_client_log_level: ''\n\t\tel_extra_params: []\n\t\tcl_client_type: lighthouse\n\t\tcl_client_image: sigp/lighthouse:latest\n\t\tcl_client_log_level: ''\n\t\tbeacon_extra_params: []\n\t\tvalidator_extra_params: []\n\t\tbuilder_network_params: null\nnetwork_params:\n  network_id: '3151908'\n  deposit_contract_address: '0x4242424242424242424242424242424242424242'\n  seconds_per_slot: 12\n  slots_per_epoch: 32\n  num_validator_keys_per_node: 64\n  preregistered_validator_keys_mnemonic: 'giant issue aisle success illegal bike spike\n    question tent bar rely arctic volcano long crawl hungry vocal artwork sniff fantasy\n    very lucky have athlete'\n  deneb_for_epoch: 500\nverifications_epoch_limit: 5\nglobal_client_log_level: info\nmev_type: full\n"})}),"\n",(0,s.jsx)(t.p,{children:"You will use the above file by passing it in at runtime, effectively enabling you to define the way your network should look using parameters."}),"\n",(0,s.jsxs)(t.h4,{id:"launch-the-network-with-full-mev",children:["Launch the network with ",(0,s.jsx)(t.code,{children:"full MEV"})]}),"\n",(0,s.jsx)(t.p,{children:"Great! You're now ready to bring up your own network. Simply run:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-bash",children:'kurtosis run --enclave eth-network github.com/ethpandaops/ethereum-package "$(cat ~/ethereum-package-params.yaml)"\n'})}),"\n",(0,s.jsxs)(t.p,{children:["Kurtosis will then begin to spin up your private Ethereum testnet with ",(0,s.jsx)(t.code,{children:"full MEV"}),". You will see a stream of text get printed in your terminal as Kurtosis begins to generate genesis files, configure the Ethereum nodes, launch a Grafana and Prometheus instance, and bootstrap the network together with the full suite of MEV products from Flashbots. In ~2 minutes, you should see the following output at the end:"]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-bash",children:'Starlark code successfully run. Output was:\n{\n\t"grafana_info": {\n\t\t"dashboard_path": "/d/QdTOwy-nz/ethereum-merge-kurtosis-module-dashboard?orgId=1",\n\t\t"password": "admin",\n\t\t"user": "admin"\n\t}\n}\n\nINFO[2023-08-03T11:16:00+02:00] ====================================================\nINFO[2023-08-03T11:16:00+02:00] ||          Created enclave: eth-network          ||\nINFO[2023-08-03T11:16:00+02:00] ====================================================\nName:            eth-network\nUUID:            1d467f353496\nStatus:          RUNNING\nCreation Time:   Thu, 03 Aug 2023 11:06:50 CEST\n\n========================================= Files Artifacts =========================================\nUUID           Name\n004cb2a16def   1-lighthouse
1-geth-0-63\ne98eee4d8a99   2-lighthouse-geth-64-127\n601b49f6e437   cl-forkmon-config\n21192db4c9b4   cl-genesis-data\nfcdd39be227b   el-forkmon-config\n38905cf9e831   el-genesis-data\n0ba35b186c20   genesis-generation-config-cl\nb477313c48f4   genesis-generation-config-el\nb119fb95bd44   geth-prefunded-keys\nc4fd103c5447   grafana-config\n122cfb453ebe   grafana-dashboards\nb86556fccf74   prometheus-config\n2d2d99849ff0   prysm-password\n\n========================================== User Services ==========================================\nUUID           Name                                       Ports                                                  Status\n1bde5712f965   cl-1-lighthouse-geth                       http: 4000/tcp -> http://127.0.0.1:62873               RUNNING\n                                                          metrics: 5054/tcp -> http://127.0.0.1:62874\n                                                          tcp-discovery: 9000/tcp -> 127.0.0.1:62875\n                                                          udp-discovery: 9000/udp -> 127.0.0.1:53993\n57f94044300c   cl-1-lighthouse-geth-validator             http: 5042/tcp -> 127.0.0.1:62876                      RUNNING\n                                                          metrics: 5064/tcp -> http://127.0.0.1:62877\nae2d5b824656   cl-2-lighthouse-geth                       http: 4000/tcp -> http://127.0.0.1:62879               RUNNING\n                                                          metrics: 5054/tcp -> http://127.0.0.1:62880\n                                                          tcp-discovery: 9000/tcp -> 127.0.0.1:62878\n                                                          udp-discovery: 9000/udp -> 127.0.0.1:65058\nc1eb34a91b7e   cl-2-lighthouse-geth-validator             http: 5042/tcp -> 127.0.0.1:62882                      RUNNING\n                                                          metrics: 5064/tcp -> http://127.0.0.1:62881\n65e1ae6652c9   cl-forkmon                                 http: 80/tcp -> http://127.0.0.1:62933                 RUNNING\ne7f673086384   el-1-geth-lighthouse                       engine-rpc: 8551/tcp -> 127.0.0.1:62861                RUNNING\n                                                          rpc: 8545/tcp -> 127.0.0.1:62863\n                                                          tcp-discovery: 30303/tcp -> 127.0.0.1:62862\n                                                          udp-discovery: 30303/udp -> 127.0.0.1:56858\n                                                          ws: 8546/tcp -> 127.0.0.1:62860\n3048d9aafc12   el-2-geth-lighthouse                       engine-rpc: 8551/tcp -> 127.0.0.1:62866                RUNNING\n                                                          rpc: 8545/tcp -> 127.0.0.1:62864\n                                                          tcp-discovery: 30303/tcp -> 127.0.0.1:62867\n                                                          udp-discovery: 30303/udp -> 127.0.0.1:62287\n                                                          ws: 8546/tcp -> 127.0.0.1:62865\n70e19424c664   el-forkmon                                 http: 8080/tcp -> http://127.0.0.1:62934               RUNNING\nf4bebfdc819b   grafana                                    http: 3000/tcp -> http://127.0.0.1:62937               RUNNING\n219954ae8f7e   mev-boost-0                                api: 18550/tcp -> 127.0.0.1:62931                      RUNNING\n287c555090c6   mev-boost-1                                api: 18550/tcp -> 127.0.0.1:62932                      RUNNING\n2fedae36a1f8   mev-flood                                  <none>                                                 RUNNING\nbb163cad3912   mev-relay-api                              api: 9062/tcp -> 127.0.0.1:62929                       RUNNING\n5591d1d17ec5   mev-relay-housekeeper                      <none>                                                 RUNNING\n026f3744c98f   mev-relay-website                          api: 9060/tcp -> 127.0.0.1:62930                       RUNNING\n096fdfb33909   postgres                                   postgresql: 5432/tcp -> postgresql://127.0.0.1:62928   RUNNING\nf283002d8c77   prelaunch-data-generator-cl-genesis-data   <none>                                                 RUNNING\naf010cabc0ce   prelaunch-data-generator-el-genesis-data   <none>                                                 RUNNING\n3fcd033e1d38   prometheus                                 http: 9090/tcp -> http://127.0.0.1:62936               RUNNING\n145b673410f9   redis                                      client: 6379/tcp -> 127.0.0.1:62927                    RUNNING\n2172a3e173f8   testnet-verifier                           <none>                                                 RUNNING\nf833b940ae5b   transaction-spammer                        <none>                                                 RUNNING\n'})}),"\n",(0,s.jsxs)(t.p,{children:["As you can see above, there is ",(0,s.jsx)(t.em,{children:"a lot"})," going on in your enclave - but don't worry, let's go through everything together."]}),"\n",(0,s.jsxs)(t.p,{children:["The first section that gets printed contains some basic metadata about the enclave that was spun up. This includes the name of the enclave ",(0,s.jsx)(t.code,{children:"eth-network"}),", its ",(0,s.jsx)(t.a,{href:"https://docs.kurtosis.com/advanced-concepts/resource-identifier/",children:"Resource Idenfitier"}),", your enclave's status, and the time it was created."]}),"\n",(0,s.jsxs)(t.p,{children:["Next, you'll see a section dedicated to ",(0,s.jsx)(t.a,{href:"https://docs.kurtosis.com/advanced-concepts/files-artifacts/",children:"Files Artifacts"}),", which are Kurtosis' first-class representation of data inside your enclave, stored as compressed TGZ files. You'll notice there are configuration files for the nodes, grafana, and prometheus as well as private keys for pre-funded accounts and genesis-related data. These files artifacts were generated and used by Kurtosis to start the network and abstracts away the complexities and overhead that come with generating validator keys and getting genesis and node config files produced and mounted to the right containers yourself."]}
1),"\n",(0,s.jsxs)(t.p,{children:["Lastly, there is a section called ",(0,s.jsx)(t.code,{children:"User Services"})," which display the number of services (running in Docker containers) that make up your network. You will notice that there are 2 Ethereum nodes, each with a ",(0,s.jsx)(t.code,{children:"MEV-Boost"})," instance spun up & connected to it. In addition to this, you will see the rest of the Flashbots MEV infrastructure including the ",(0,s.jsx)(t.code,{children:"mev-relay"})," suite of services (read more about the ",(0,s.jsx)(t.code,{children:"mev-relay"})," services ",(0,s.jsx)(t.a,{href:"https://github.com/flashbots/mev-boost-relay/blob/main/ARCHITECTURE.md",children:"here"}),") and ",(0,s.jsx)(t.code,{children:"mev-flood"}),". By default, the ",(0,s.jsx)(t.code,{children:"ethereum-package"})," also comes with supporting services which include a fork monitor, redis, postgres, grafana, prometheus, a transaction spammer, a testnet-verifier, and the services used to generate genesis data. Both of the Redis and Postgres instances are required for ",(0,s.jsx)(t.code,{children:"mev-relay"})," to function properly. Each of these services are running in Docker containers inside your local enclave & Kurtosis has automatically mapped each container port to your machine's ephemeral ports for seamless interaction with the services running in your enclave."]}),"\n",(0,s.jsx)(t.h4,{id:"visit-the-website-to-see-registered-validators-and-delivered-payloads",children:"Visit the website to see registered validators and delivered payloads"}),"\n",(0,s.jsxs)(t.p,{children:["Now that your network is online, you can visit the relay website using the local port mapped to that endpoint. For this example, it will be ",(0,s.jsx)(t.code,{children:"127.0.0.1:62930"}),", but it will be different for you."]}),"\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.img,{alt:"flashbots-website",src:n(2408).A+"",width:"2434",height:"2394"})}),"\n",(0,s.jsxs)(t.p,{children:["The screenshot above is what the website looks like after the 4th epoch. You can see that all 128 validators (2 nodes, each with 64 validators) are registered. The table below will display recently delivered and verified payloads from ",(0,s.jsx)(t.code,{children:"mev-relay"})," to the ",(0,s.jsx)(t.code,{children:"mev-boost"})," sidecar on each node."]}),"\n",(0,s.jsx)(t.p,{children:"And there you have it! You've now spun up a private Ethereum testnet over Docker with the Flashbot's implementation of PBS!"}),"\n",(0,s.jsx)(t.h2,{id:"roadmap",children:"Roadmap"}),"\n",(0,s.jsx)(t.p,{children:"The inclusion of a Proposer Builder Separation (PBS) implemention was in support of the Ethereum Foundation's efforts to validate functionality and behavior in end-to-end testing (between in-protocol and out-of-protocol infrastructure), as well as the functionality of the beacon chain for in-protocol code paths (e.g. can clients: call for payloads reject invalid payloads, and trigger the circuit breaker when necessary)."}),"\n",(0,s.jsxs)(t.p,{children:["The next immediate thing we hope to do is to ",(0,s.jsx)(t.em,{children:"decompose"})," the environment definition into smaller pieces, enabling developers to build-their-own MEV-enabled systems by simply importing only the parts of the MEV infrastructure that they need. We've begun working on this already with ",(0,s.jsx)(t.a,{href:"https://github.com/kurtosis-tech/eth-kurtosis",children:"eth-kurtosis"}),", which contains an index of composable building blocks to define your own testnet."]}),"\n",(0,s.jsxs)(t.p,{children:["If there are other use cases you had in mind (e.g. fuzzing the network at the protocol level) or have questions about ",(0,s.jsx)(t.code,{children:"eth-kurtosis"})," or this ",(0,s.jsx)(t.code,{children:"ethereum-package"}),", please don't hesitate to reach out!"]}),"\n",(0,s.jsx)(t.h2,{id:"conclusion",children:"Conclusion"}),"\n",(0,s.jsx)(t.p,{children:"This guide was meant to be quick - we hope it was. To recap, you:"}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsx)(t.li,{children:"Installed Kurtosis and Docker"}),"\n",(0,s.jsxs)(t.li,{children:["Created a ",(0,s.jsx)(t.code,{children:".yaml"})," file that contains the necessary parameters for the network"]}),"\n",(0,s.jsx)(t.li,{children:"Ran a single command to spin up a private Ethereum testnet with MEV infrastru
1cture"}),"\n"]}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"ethereum-package"})," is available for anyone to use, will work the same way on your local machine or in the cloud, and will run on Docker or Kubernetes."]}),"\n",(0,s.jsx)(t.p,{children:"You saw first-hand how packages, effectively environment definitions, are written once and then can be used by anyone in a very trivial way to reproduce the environment. This accelerates developer velocity by enabling engineers to spend less time on configuring and setting up development and testing frameworks, and more time instead on building the unique features and capabilities for their projects."}),"\n",(0,s.jsxs)(t.p,{children:["Additionally, we hope you also enjoyed the parameterizability aspect of Kurtosis Packages. By changing the ",(0,s.jsx)(t.code,{children:"ethereum-package-params.yaml"}),", you can get a fine-tune your testnet however you see fit."]}),"\n",(0,s.jsxs)(t.p,{children:["We hope this guide was helpful and we'd love to hear from you. Please don't hesitate to share with us what went well, and what didn't, using ",(0,s.jsx)(t.a,{href:"/feedback",children:(0,s.jsx)(t.code,{children:"kurtosis feedback"})})," from the CLI to file an issue in our ",(0,s.jsx)(t.a,{href:"https://github.com/kurtosis-tech/eth-kurtosis/issues",children:"Github"})," or post your question in our ",(0,s.jsx)(t.a,{href:"https://github.com/kurtosis-tech/kurtosis/discussions",children:"Github Discussions"}),"."]}),"\n",(0,s.jsx)(t.p,{children:"Thank you!"})]})}function d(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(h,{...e})}):h(e)}},2408(e,t,n){n.d(t,{A:()=>o});const o=n.p+"assets/images/full-mev-flashbots-website-30cc561411ed5babf6029d5a4d7fe4e9.png"},1897(e,t,n){n.d(t,{A:()=>o});const o=n.p+"assets/images/full-mev-infra-arch-diagram-ee260244eb30c7ba12e3013f9775d88e.png"},8453(e,t,n){n.d(t,{R:()=>r,x:()=>a});var o=n(6540);const s={},i=o.createContext(s);function r(e){const t=o.useContext(i);return o.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),o.createElement(i.Provider,{value:t},e.children)}}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.