Skip to content

The execution payload envelope duty stops after BLOCK_ERROR_ALREADY_KNOWN, and it asks for the wrong block root #1293

Description

@ovidiu-ssv-labs

Summary

We found two defects in the execution payload envelope duty. Each one alone stops Anchor from
publishing the envelope.

  1. When the beacon node answers BLOCK_ERROR_ALREADY_KNOWN to the block publication, Anchor stops the
    full task. It then does not do the envelope duty for that slot.
  2. When Anchor does the envelope duty, it asks the beacon node for the envelope of its own local
    candidate block
    , and not of the block that the committee decided.

Together, at most one Anchor operator joins each envelope consensus instance. In a committee where
two of the three operators in the quorum are Anchor operators, the envelope duty then never completes,
and the blocks are empty. See issue #1294, "A committee with two Anchor operators and one Go SSV operator
makes empty blocks"
.

Test environment

  • Network: ssv-mini, a local Kurtosis testnet with 4 SSV operators. The quorum is 3 of 4.
  • Operators 1 and 2 run Anchor, commit 52ba589 on branch epbs (Anchor/v1.3.1-52ba589).
  • Operators 3 and 4 run the Go SSV node, commit 613dd52c9 on branch epbs-gloas.
  • Consensus client: Lodestar v1.46.0/aa8303e. All 4 operators use the same beacon node.
  • Execution client: go-ethereum, glamsterdam-devnet-8 image.
  • Gloas fork epoch: 4 (slot 128). The Boole fork is not scheduled.

Note: all 4 operators use one beacon node. Thus every operator builds the same block and the same
envelope, and every operator sends the block to the same beacon node. Only the first operator gets a
success answer.

Defect 1: BLOCK_ERROR_ALREADY_KNOWN stops the full task

All operators of the committee send the same reconstructed block. The beacon node accepts the first
block and answers BLOCK_ERROR_ALREADY_KNOWN to the others. This answer is normal.

Anchor treats this answer as Irrecoverable:

11:52:33.134036 INFO  Publishing signed block  slot=205
11:52:33.147757 DEBUG Request to beacon node failed
                      error=Irrecoverable("... message: \"BLOCK_ERROR_ALREADY_KNOWN\" ...")
11:52:33.150819 ERROR Error whilst producing block   error="Some endpoints failed, num_failed: 2 ..."

After this error there is no Fetching execution payload envelope line for slot 205, and Anchor does
not join the envelope consensus instance of that slot.

The correlation is exact and opposite on the two Anchor nodes. One node stopped the task on slots 128,
134, 166, 175, 203 and 205, and did the envelope duty on slots 139, 143, 153, 202 and 217. The other
node did the opposite.

The Go SSV node treats BLOCK_ERROR_ALREADY_KNOWN as a success on the Gloas path
(beacon/goclient/gloas_proposer.go). In the same window the beacon node gave this answer 172 times,
and all Go SSV block proposals were a success.

What we expect

Treat BLOCK_ERROR_ALREADY_KNOWN as a success. Continue with the envelope duty.

Defect 2: the envelope request uses the local candidate root

Anchor asks for the envelope of the block root of its own candidate block:

anchor-node-0 11:38:21.233871 INFO Fetching execution payload envelope
                                   slot=134 beacon_block_root=0xfc43256b6aff...
canonical root of slot 134       = 0x9bcce65952...

The beacon node answers HTTP 404 for the root 0xfc43256b6aff....

8 of the 12 envelope requests used a root that the beacon node does not know. The root was correct
only when an Anchor operator was the leader of the block proposal consensus (slots 128, 153, 205 and
217).

Lodestar writes the root of the request into the envelope that it gives:

Produced execution payload envelope slot=134, blockRoot=0xfc43256b...
Produced execution payload envelope slot=134, blockRoot=0x9bcce659...   (two times)

All three envelopes have the same blockHash=0x9327.... Thus the cached envelope of Anchor has a
different root from the value that the committee decided. The content check then stops the
publication.

This is not an error of the root calculation. The partial signature of Anchor for the decided block
was a part of a valid signature in every block that the chain accepted, and also in the blocks where a
Go SSV operator was the leader.

What we expect

Ask for the envelope of the block root that the committee decided.

Defect 3 (small): the correct skip is also an error

Anchor has a correct message for the condition "another operator built the decided envelope":

INFO Cluster decided another operator's envelope, skipping publish (expected)   (4 times)

But the same condition also gives an error message:

ERROR Error whilst producing block
      error="Error signing execution payload envelope:
             SpecificError(EnvelopeNotBuiltLocally { local_root: 0x..., decided_root: 0x... })"

We counted 8 of these error messages. The blocks of those slots are on the chain. Please use only the
INFO message for this condition.

Effect

In a committee with 2 Anchor operators and 2 Go SSV operators, the envelope duty completed 11 of 11.
The Anchor operator that won the block publication race always joined the instance, so the quorum of 3
was possible.

In a committee with 2 Anchor operators and 1 Go SSV operator, the envelope duty completed 0 of 4, and
all 4 blocks are empty on the chain.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions