Skip to content

engine: add payload witness endpoint to REST + SSZ proposal - #885

Open
jsign wants to merge 4 commits into
ethereum:mainfrom
jsign:jsign-rest-ssz-payload-witness
Open

jsign wants to merge 4 commits into
ethereum:mainfrom
jsign:jsign-rest-ssz-payload-witness

Conversation

@jsign

@jsign jsign commented Sep 11, 2026

Copy link
Copy Markdown

Note: this PR is based on previous work from @developeruche, plus some extra refinements

This PR adds POST /engine/v1/payloads/witness to the REST + SSZ proposal. It lets zkVM provers and stateless validators submit a payload and receive its validation result, execution witness, and transaction sender public keys in one call, avoiding a separate witness request and hex-JSON encoding.

The endpoint is optional from Amsterdam onward and advertised through capabilities. It accepts the same request as /payloads. Every VALID response must include a complete witness, including for already-known payloads; other statuses must omit it.

Responses also include public_keys, allowing proving hosts to populate StatelessInput.public_keys without recovering keys themselves. For VALID payloads, including already-known payloads, the list contains one 65-byte uncompressed sender public key per transaction, in transaction order; for other statuses, it is empty. Stateless validators must still verify the supplied keys against transaction signatures and recovery IDs.

The proposal defines witness contents, public-key semantics, SSZ containers, and size bounds. Behavioral requirements live in refactor.md; encoding definitions live in refactor-ssz.md.

jsign and others added 3 commits September 11, 2026 10:27
Co-authored-by: developeruche <developeruche@gmail.com>
Require a complete witness for every VALID response and clarify trie,
bytecode, and ancestor-header contents. Keep behavioral rules in
refactor.md and SSZ definitions in refactor-ssz.md.
@developeruche

Copy link
Copy Markdown

This looks good to me!..

But currently, this capability is not being advertised.

I guess /engine/v1/capabilities could return an extra field "optional_endpoints": ["payloads/witness"], the overall response would be something like this;

{
  "supported_forks":          ["paris", "shanghai", "cancun", "prague", "osaka", "amsterdam"],
  "optional_endpoints":       ["payloads/witness"],
  "fork_scoped_endpoints":    ["payloads", "forkchoice", "bodies"],
  "independently_versioned":  { "blobs": ["v1", "v2", "v3", "v4"] },
  "unscoped_endpoints":       ["capabilities", "identity"],
  "limits": {
    "bodies.max_count":           32,
    "blobs.max_versioned_hashes": 128,
    "payload.max_bytes":          67108864
  }
}

What do you think?

also made a PR adding an example for this route here

@jsign

jsign commented Sep 12, 2026

Copy link
Copy Markdown
Author

This looks good to me!..

But currently, this capability is not being advertised.

I guess /engine/v1/capabilities could return an extra field "optional_endpoints": ["payloads/witness"], the overall response would be something like this;

{
  "supported_forks":          ["paris", "shanghai", "cancun", "prague", "osaka", "amsterdam"],
  "optional_endpoints":       ["payloads/witness"],
  "fork_scoped_endpoints":    ["payloads", "forkchoice", "bodies"],
  "independently_versioned":  { "blobs": ["v1", "v2", "v3", "v4"] },
  "unscoped_endpoints":       ["capabilities", "identity"],
  "limits": {
    "bodies.max_count":           32,
    "blobs.max_versioned_hashes": 128,
    "payload.max_bytes":          67108864
  }
}

What do you think?

Uhm, I'm not sure this is necessary, since in this PR we already say that this optional endpoint is advertised in fork_scoped_endpoints here:

ELs that implement it advertise payloads/witness in the fork_scoped_endpoints list of GET /capabilities

So if it is advertised there, I'm not sure we need a new optional_endpoints field.
Curious to get @MariusVanDerWijden opinion on this.

Reg the example PR, I'll take a look soon! Merged!

@MysticRyuujin MysticRyuujin mentioned this pull request Sep 13, 2026
29 tasks
* added example for sumbit payload witness

* nit fixes
@jsign
jsign marked this pull request as ready for review September 16, 2026 18:16
@jsign

jsign commented Sep 16, 2026

Copy link
Copy Markdown
Author

@MariusVanDerWijden opened for review!

@MariusVanDerWijden MariusVanDerWijden left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally LGTM, theres one change that I couldn't understand

Comment thread src/engine/refactor.md
```

The 41 bytes break down as: `status` (1 byte = `0x01`, `VALID`) +
The 41 bytes break down as: `status` (1 byte = `0x00`, `VALID`) +

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whats up with this?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, this just fixes a typo in an existing example. The existing PayloadStatus enum defines VALID = 0 and INVALID = 1, so the byte here should be 0x00.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants