Autor: Giulio Rebuffo

Introdução

A especificação da API SSZ Engine propõe a substituição da codificação JSON-RPC por SSZ (Simple Serialize) binário para a API Ethereum Engine – a interface entre os clientes da camada de consenso (CL) e da camada de execução (EL).

Hoje, cada mensagem entre CL e EL é codificada em JSON: cada byte de cada transação, blob e retirada é codificado em hexadecimal e empacotado em JSON. Para pequenas cargas como forkchoiceUpdatedestá tudo bem. Para engine_getPayloadV5 – que retorna o completo ExecutionPayload mais BlobsBundle — a sobrecarga de codificação torna-se um contribuinte significativo para bloquear a latência de propagação.

Transporte

Ambos os transportes coexistem na mesma porta Engine API (padrão 8551):

Transporte Tipo de conteúdo Ponto final
JSON-RPC application/json POST /
RESTO SSZ application/octet-stream POST /engine/v{N}/{resource}

Com o PeerDAS e o fork Fulu aumentando a contagem de blobs de 6 para 72 (alvo 48), os tamanhos de carga útil por meio da API do mecanismo crescerão significativamente. Esta postagem apresenta benchmarks de codificação de um devnet Kurtosis ativo executando três implementações EL com instrumentação de transporte SSZ.

Metodologia

Configuração do desenvolvedor

Um devnet Kurtosis foi implantado com 12 pares EL+CL — cada combinação de três clientes EL (Geth, Erigon, Nethermind) e quatro clientes CL (Prysm, Lighthouse, Teku, Lodestar) — todos executando imagens Docker personalizadas com suporte de transporte SSZ e instrumentação de codificação.

Parâmetros de rede: slots de 6 segundos, garfo Fulu na gênese, 72 bolhas no máximo, 48 bolhas alvo32 validadores por nó. Carga de transação gerada com spamoor a 200 EOA tx/s mais transações blob (6 sidecars cada).

Medição

Cada EL foi instrumentado para codificar cada GetPayloadV5 resposta em ambos SSZ e JSON, registrando o tamanho e a hora de cada um:

GetPayloadV5 encoding: SSZ=9,930,470 bytes in 19,700 us | JSON=19,906,846 bytes in 59,531 us | ratio=2.0x size, 3.0x time blobs=72

Resultados

getPayload Tempo de codificação em 72 Blobs (Fulu Max)

Piores tempos de codificação observados por par EL+CL em 72 blobs (~9,9 MB SSZ / ~19,9 MB JSON) após 17 horas de operação contínua devnet:

CL\EL Mente Infernal Geth Erígon
Prisma SSZ 5 ms / JSON 103 ms (20,6×) SSZ 19 ms / JSON 180 ms (9,3×) SSZ 15 ms / JSON 63 ms (4,2×)
Farol SSZ 8 ms / JSON 114 ms (14,3×) SSZ 24 ms / JSON 181 ms (7,5×) SSZ 6 ms / JSON 82 ms (12,7×)
Teku SSZ 14 ms / JSON 120 ms (8,6×) SSZ 28 ms / JSON 358 ms (12,8×) SSZ 13 ms / JSON 81 ms (6,1×)
Estrela Polar SSZ 8 ms / JSON 91 ms (11,4×) SSZ 36 ms / JSON 446 ms (12,3×) SSZ 31 ms / JSON 101 ms (3,3×)

Essas são medições do pior caso (tempos de codificação observados mais altos) em uma execução de 17 horas – os tempos típicos do mundo real são mais baixos, mas a latência do pior caso é o que importa para os prazos de propagação de blocos.

Principais observações:

  • A codificação SSZ permanece abaixo de 36 ms em todos os 12 pares no pior caso – consistentemente rápida, independentemente da implementação.
  • A codificação JSON de pior caso varia de 63 ms a 446 ms – altamente variável entre implementações EL.
  • Geth tem a maior sobrecarga JSON (180–446 ms), tornando a aceleração do SSZ mais dramática (7,5–12,8×).
  • A codificação JSON do pior caso do Nethermind varia de 91 a 120 ms, com SSZ 8,6 a 20,6 × mais rápido.
  • Erigon fica no meio (63–101 ms JSON), com aceleração SSZ de 3,3–12,7×.

Tamanho do fio

Consistentemente em todas as cargas que transportam blobs:

Carga útil Tamanho SSZ Tamanho JSON Razão
Bloco de 72 bolhas ~9,9MB ~19,9MB 2,0×
Bloco de 24 bolhas ~3,3MB ~6,6 MB 2,0×
Bloco de 6 bolhas ~837KB ~1,68MB 2,0×

A proporção 2× é estrutural: a codificação hexadecimal JSON dobra cada byte (0xff"0xff" = 4 caracteres).

Outros métodos de API do mecanismo

Nem todas as chamadas da API do mecanismo se beneficiam igualmente do SSZ. Os três métodos chamados de cada slot são forkchoiceUpdated, newPayloade getPayload. Aqui está como eles se comparam em termos de tamanhos de solicitação/resposta e tempos de codificação (todas as medidas do par Erigon + Prysm):

Tamanhos de mensagens:

Método Direção Tamanho SSZ Tamanho JSON
forkchoiceUpdated Solicitação CL → EL 100–200 bilhões 300–600 a.B.
forkchoiceUpdated Resposta EL → CL 49-57B ~200 bilhões
newPayload Solicitação CL → EL 603 B – 46 KB 1,4KB – 92KB
getPayload Resposta EL → CL 837 KB – 9,9 MB 1,68 MB – 19,9 MB

Tempos de codificação:

Método Hora SSZ Hora JSON
forkchoiceUpdated <1 µs <1 µs
newPayload 15–45 µs 60–4.978 µs
getPayload 1,1–25,6ms 16–211ms

forkchoiceUpdated é minúsculo em ambas as direções – menos de 200 bytes. A diferença de sobrecarga entre SSZ e JSON é insignificante nesta escala.

newPayload carrega o ExecutionPayload (transações, saques), mas não blobs – aqueles que se propagam através da camada de fofoca. Mesmo em um bloco mainnet de alto rendimento (cerca de 1.500 transações), newPayload teria aproximadamente 200–400 KB em SSZ. Nesses tamanhos, a sobrecarga de codificação é bem inferior a 1 ms, independentemente do formato.

getPayload é o discrepante. Ele retorna o completo ExecutionPayload mais o BlobsBundle (compromissos, provas e todos os dados do blob). Com 72 blobs, esta resposta única é 9,9 MB em SSZ (19,9 MB em JSON) — ordens de magnitude maiores do que qualquer outra mensagem da API do mecanismo. É aqui que a sobrecarga de codificação se torna mensurável em milissegundos e é por isso que a especificação de transporte SSZ concentra seu impacto aqui.

Conclusão

A API do mecanismo getPayload resposta é a maior mensagem trocada entre CL e EL em cada slot. Com 72 blobs, ele carrega aproximadamente 9,9 MB de dados em SSZ (19,9 MB em JSON) e essa única etapa de codificação pode levar de 63 ms a 446 ms em JSON, dependendo do cliente, consumindo diretamente o orçamento de propagação de bloco.

A codificação SSZ da mesma carga leva de 5 a 36 ms em todos os 12 pares EL + CL testados. A aceleração varia de 3× a 20× dependendo do par, com o tempo SSZ do pior caso ainda bem abaixo do tempo JSON do melhor caso para a maioria das implementações.

A redução do tamanho do fio é consistente em 2× em todos os tamanhos de carga útil – uma consequência estrutural da eliminação da codificação hexadecimal. Para um bloco de 72 blobs, são aproximadamente 10 MB salvos por slot no link CL↔EL.

O custo de adoção é baixo: ambos os transportes coexistem na mesma porta, JSON-RPC continua sendo o padrão e SSZ é opcional por meio de negociação de tipo de conteúdo. Já existem implementações para Geth, Erigon, Nethermind, Prysm, Lighthouse, Teku e Lodestar.

Reprodução

Configuração de devnet de curtose

participants:
  # 3 ELs × 4 CLs = 12 pairs
  - el_type: geth
    cl_type: prysm
    supernode: true
    validator_count: 32
  - el_type: geth
    cl_type: lodestar
    supernode: true
    validator_count: 32
  - el_type: geth
    cl_type: teku
    supernode: true
    validator_count: 32
  - el_type: geth
    cl_type: lighthouse
    supernode: true
    validator_count: 32
  - el_type: erigon
    cl_type: prysm
    supernode: true
    validator_count: 32
  - el_type: erigon
    cl_type: lodestar
    supernode: true
    validator_count: 32
  - el_type: erigon
    cl_type: teku
    supernode: true
    validator_count: 32
  - el_type: erigon
    cl_type: lighthouse
    supernode: true
    validator_count: 32
  - el_type: nethermind
    cl_type: prysm
    supernode: true
    validator_count: 32
  - el_type: nethermind
    cl_type: lodestar
    supernode: true
    validator_count: 32
  - el_type: nethermind
    cl_type: teku
    supernode: true
    validator_count: 32
  - el_type: nethermind
    cl_type: lighthouse
    supernode: true
    validator_count: 32
network_params:
  seconds_per_slot: 6
  fulu_fork_epoch: 0
  bpo_1_max_blobs: 72
  bpo_1_target_blobs: 48
additional_services:
  - spamoor
spamoor_params:
  spammers:
    - scenario: eoatx
      config:
        throughput: 200
        max_pending: 400
        max_wallets: 200
    - scenario: blob-combined
      config:
        throughput: 40
        max_pending: 80
        sidecars: 6
kurtosis run github.com/ethpandaops/ethereum-package --args-file ssz_bench_net.yml

Implementações

Fontesethresear

By victor

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *