Skip to content

v0.8.0

Latest

Choose a tag to compare

@github-actions github-actions released this 25 Sep 02:24
· 5 commits to main since this release

Not phase F. The oracle waits while what exists is made to earn its place: a
chain with traffic on it, the pool it waits in, two execution clients as well
as three consensus clients, a 3D scene that keeps time and names who is who,
pictures on the front page, and walkthroughs that CI now runs. Bringing Reth up
turned up the release's most consequential fix — the devnet's execution clients
had never peered.

Added

  • Reth on the devnet. Node 3 runs Reth under Teku instead of a third geth,
    so client diversity now holds on both layers: a block Reth builds for Teku's
    proposer has to be executed and accepted by the two geth nodes before
    Lighthouse and Prysm attest to it, and the other way round. Verified on a
    fresh devnet — blocks built by each accepted by the other, one head hash on
    all three. A swap rather than a fourth node, because the 22/21/21 validator
    split and the finality arithmetic the walkthroughs teach depend on there
    being three.

    The flags follow geth's for the same reasons; the differences are written
    beside them in network.yml (no init step, no tip floor to disable, archive
    unless told otherwise, metrics at the root path, a health check over bash's
    /dev/tcp because the image has no curl). The banner, network status,
    walkthrough 4, the agreement table and the 3D scene's labels all name both
    clients on each node, and tests check that the compose file, NODES and the
    control room's copy agree.

  • cupel traffic: a chain with something happening on it. Every picture of
    an idle chain is the same flat line, so this sends what a used one carries —
    ether payments, token mints and transfers, vault deposits and redemptions,
    wrapping and unwrapping ether — from development accounts 0, 1 and 3 at once,
    in bursts of none to five every second or two. Blocks stand tall or stay
    empty, and gas varies because the work does. Account 2 never sends: it is the
    signer's key, and its audit log stays about the signer.

    Now and then it does, on purpose, the two things people are most surprised
    by: a transaction that reverts, which is still mined and still pays for its
    gas, and one sent with a nonce too far ahead, which is accepted, parks in
    queued and runs only once the gap in front of it is filled. Each is
    explained the first time it happens. --clean turns both off, and a clean run
    exits non-zero if anything reverted or was accepted and never included — the
    second being how geth reports a tip below its floor, which is not at all. At
    the end it asks for every receipt and says what became of each transaction.

    Everything is signed locally and sent raw, so it needs no Foundry, and it
    works against either chain: --rpc http://127.0.0.1:8555 sends to a devnet
    node directly. It replaces the throwaway script that fed the 3D page.

  • The 3D scene names its clients, and keeps time. In network mode each
    marker carries its client's name — node1 Lighthouse — on a row of its own
    with a line down to the marker, so the scene reads without the legend under
    it. The labels are HTML moved to each marker's place on screen every frame,
    so they stay crisp and follow the theme; rows are handed out from the right
    so no line ever crosses a label.

    Blocks now sit at their place in time rather than one after another: one
    box-width is the slot time on the devnet and the block time in the lab, a
    slot nobody proposed in leaves a gap the width of a block, and a line across
    the floor marks the moment each epoch began. The legend says how much time
    the window covers — fifty seconds in the lab, ten minutes on the devnet —
    which is the difference the two lanes used to hide. Absolute seconds were
    tried on paper and rejected: at a fixed scale the devnet lane is twelve times
    longer and every box a pixel wide.

  • The pool, as a page. Every other page shows transactions that ran; this
    one shows where they wait first. txpool_content through the gateway, read
    four times a second in lab mode: pending (ready for the next block),
    queued (accepted and parked — with the nonce each one is waiting for,
    worked out from the sender's pending run or its account nonce), and just
    left
    , with how long each stayed. That last is shown as the range the
    readings allow rather than a single number: two readings a few milliseconds
    apart, one either side of a block, once timed everything at 0.0s. In network
    mode it also shows each node's own counts, because there is no network-wide
    pool — only each node's view of one. Calls are named (Token.transfer,
    Vault.deposit) on this page and the transaction page.

    The selectors behind those names, and the ones the page already used to read
    the contracts, are now checked against the bytecode in the committed genesis
    file. A comment had claimed that check existed; nothing did it.

  • The README shows the thing. A moving picture of the 3D page under
    cupel traffic at the top, and the overview, a block and the walkthrough in
    the control-room section, each in the reader's own theme. An audit flagged a
    project about making machinery visible with not one picture of it on the
    front page. CI now fails if the README names an image that is not in the
    repository — a broken screenshot fails nothing on its own. docs/shoot.mjs
    is how they were taken: a headless Chrome or Edge over the DevTools protocol,
    nothing to install, with the commands for each image written at the top.

  • The chain as a solid object. A page that draws the block window in three
    dimensions: one box per block, running away from the camera in the order they
    were made, as tall as the gas each used, orange where a block carried
    transactions and grey where it was empty. Point at a block for its number,
    transactions and gas; click it to open the block page. In network mode a
    marker floats above the block each client calls the head, and a client whose
    head is outside the window is drawn at the end of the lane and named as ahead
    or behind rather than placed on a block the page never fetched.

    Nothing in the scene is ornament — the length is the window, the heights are
    gas, the colour is whether anything was in the block. The height scale climbs
    in round steps and the legend prints the number it has reached: scaled
    straight to the busiest block in view, every box grows the moment that block
    falls out of a window that moves every second, and a block that has not
    changed appears to have.

    three.js is larger than the rest of the interface put together, so the page is
    loaded on its own and only a reader who opens it pays to parse it. The binary
    carries it either way.

Fixed

  • Walkthrough 4 mistook "nothing finalised yet" for a dead node. Asked for
    the finalised block before there is one, geth answers with an error
    (finalized block not found) and Reth answers with the genesis block. The
    walkthrough treated geth's error as silence — with three geth nodes it said
    no execution client was answering at all, while all three were. It now tells
    a transport failure from an answer that happens to be an error, prints "none
    yet" and "genesis" for the two spellings, and says why they differ.

  • The walkthroughs are tested. They are what a newcomer meets first, and
    nothing ran them. CI now runs 1 and 2 against the lab chain and 3 and 4
    against the devnet after finality, and checks each for the conclusion it
    exists to reach — "Four calls, one block", "they agree", "one block, from two
    implementations" — since a walkthrough printing the wrong verdict still exits
    0. It also checks that a devnet walkthrough run against the lab refuses and
    names the command that would start the devnet.

  • The devnet's execution clients never found each other. Given no
    --bootnodes, devp2p discv4 listen bootstraps from mainnet's, so the
    devnet's bootnode joined the public discovery network, filled its table with
    mainnet nodes, and answered every devnet node's lookup with them —
    --netrestrict discarded them all, and geth logged Looking for peers tried=0 for ever. A crawl of the bootnode found 136 nodes, one of them on
    the devnet. Blocks travel over the consensus network, so nothing visibly
    broke; what broke was transaction gossip — a transaction sent to node1 waited
    for one of node1's own validators to propose. The bootnode is now given an
    explicitly empty list, the mesh forms in seconds, network status shows
    execution peers beside consensus peers and says what an isolated execution
    client means, and CI requires every node to see the other two.

  • The 3D page drew sixty frames a second for nobody. The browser stops a
    background tab by itself, but not a canvas scrolled out of view while the
    legend under it is being read — that kept drawing at full rate, which on a
    laptop is a fan and a battery. The scene now stops outright when the tab is
    hidden or the canvas is off screen (measured in headless Edge: 0 animation
    frames in two seconds, against 140–290 in view), and resumes when it comes
    back. With reduced motion asked for it draws only when something changes, and
    a new block appears rather than gliding in — the glide takes about as long as
    a lab block, so it would have kept the scene drawing anyway. The client
    markers also stopped spinning under reduced motion; they used to ignore it.

  • The control room fetched its own typefaces over the internet. The page
    linked fonts.googleapis.com for IBM Plex and Fraunces. It is compiled into a
    binary and served from localhost, and this project exists to run a chain on a
    laptop with no network — so offline, which is most of the point, every heading
    fell back to Georgia and every table to the system sans, with nothing to say
    why. Six woff2 files travel with it now, latin only, and a test asserts the
    page names no font host and that each file is served as font/woff2.

  • The check that starts a chain from a download tripped over the chain
    already running.
    It stopped the previous step's container and then tried to
    bind 8545, which that step's process was still holding — the thing its own
    error message says cupel down cannot help with. It had never run on CI
    before, because the commits that added it had not been pushed.

  • A downloaded binary could not start a chain. The archive holds a binary,
    a README and two licences; every command except --version went looking for
    compose/lab.yml in the working directory or a parent, found none, and said
    "could not find a Cupel checkout". The point of publishing binaries is that
    trying Cupel should not need a toolchain, and what shipped needed a git
    clone instead of a Rust one.

    The binary carries what it reads now — the three compose files, the lab
    genesis, and the Prometheus and Grafana configuration cupel observe mounts
    — and writes them into a directory of its own the first time it runs, named
    by CUPEL_HOME or chosen from where the platform keeps application data. A
    checkout still wins wherever there is one, so editing a compose file works
    exactly as before. The Engine API secret is deliberately not carried: it is
    generated per chain, and one compiled into a release would be the same
    secret on every machine that downloaded it. cupel genesis is the one
    command that still needs a checkout, because it rebuilds the allocation from
    Foundry artifacts, and it now says so instead of failing on a missing path.

    The release's own smoke test could not have caught this. It runs the binary
    inside the checkout, where the file it wants is always a directory up, so it
    passed for four releases while every download failed. Two checks replace it:
    the release unpacks its own archive somewhere with no checkout above it, and
    CI starts a whole chain that way, which is also what proves the mounts in the
    carried compose file resolve against the directory it was written to.

  • The release never checked the version it was publishing. The step titled
    "It runs, and it is the version on the tag" printed cupel --version and
    compared it with nothing. A tag placed on a commit whose Cargo.toml still
    held the previous number would have published a binary that disagreed with
    the release it was attached to. It compares them now and refuses.

  • Publishing did not wait for CI. v0.7.0 published while CI on its own
    commit was red. Building four binaries proves they compile and run; it says
    nothing about the devnet reaching finality or the committed bundle matching
    its source. The publish job now waits for the CI run on the tagged commit,
    and refuses to publish a commit CI rejected.

Changed

  • The workflows use current actions again: checkout v7, setup-node v7,
    upload-artifact v7, download-artifact v8 and action-gh-release v3. GitHub was
    forcing the old ones onto Node 24 and warning about it on every run.