Data Layouts
O SDK do Wormhole utiliza o pacote layout
para definir, serializar e desserializar estruturas de dados de forma eficiente. Esse sistema modular garante um formato de dados consistente e compatibilidade entre diferentes ambientes, beneficiando projetos que exigem um manuseio robusto de dados estruturados.
Ao compreender o mecanismo de layout, você será capaz de:
Definir estruturas de dados (números, arrays e tipos personalizados)
Serializar e desserializar dados de forma eficiente utilizando as utilidades do SDK
Lidar com layouts específicos de protocolo com facilidade
Este guia é útil para desenvolvedores que buscam integrar o Wormhole em suas aplicações ou protocolos, especialmente aqueles que lidam com payloads complexos ou comunicação entre blockchains.
Conceitos Chave Itens de Layout Um layout define como as estruturas de dados devem ser serializadas (convertidas para formato binário) e desserializadas (convertidas de volta para sua estrutura original). Isso garante um formato de dados consistente ao transmitir informações entre diferentes ambientes de blockchain.
Os layouts são compostos por itens de layout, que descrevem campos individuais ou conjuntos de campos em seus dados. Cada item de layout especifica:
name
- nome do campobinary
- tipo de dado (ex: uint, bytes)size
- comprimento em bytes para campos de tamanho fixo dentro de itensuint
ebytes
apenas
Os itens de layout podem representar:
Tipos primitivos - tipos básicos de dados como inteiros não assinados (uint) ou arrays de bytes (bytes)
Tipos compostos - estruturas mais complexas, como arrays ou objetos aninhados
Abaixo está um exemplo de um layout que poderia ser usado para serializar uma mensagem através do protocolo Wormhole:
Neste exemplo:
sourceChain
é um inteiro não assinado de 2 bytes (uint) identificando a blockchain de origemorderSender
é um array de bytes de 32 bytes representando o endereço do remetenteredeemer
é outro array de 32 bytes utilizado para o endereço do resgatadorredeemerMessage
é uma sequência de bytes de comprimento variável, com seu comprimento especificado por um inteiro de 4 bytes
Essa definição de layout garante que todos os campos de dados necessários sejam codificados de forma consistente e possam ser interpretados corretamente quando desserializados.
Serialização e Desserialização A serialização converte dados estruturados em formato binário; a desserialização reverte isso, reconstruindo os objetos originais.
Você pode serializar dados utilizando a função serializeLayout
:
Para desserializar os dados binários de volta em um objeto estruturado, utilize a função deserializeLayout
:
Conversões Personalizadas Os layouts também permitem conversões personalizadas, o que ajuda a mapear tipos complexos ou personalizados (como IDs de cadeia ou endereços universais) para um formato mais utilizável. Isso é útil ao serializar ou desserializar dados que não se encaixam bem em tipos simples, como inteiros ou arrays de bytes.
Por exemplo, considere uma conversão personalizada para um ID de cadeia:
Essa configuração permite que o Wormhole converta entre formatos legíveis por humanos e dados codificados binariamente usados em payloads.
Tratamento de Erros O sistema de layout realiza verificações de erro durante a serialização e desserialização. Um erro é lançado se os dados estiverem com tamanho incorreto ou no formato errado. Veja o exemplo abaixo:
Aplicação de Layouts Esta seção se concentrará na aplicação dos conceitos explicados anteriormente através de exemplos. Eles ajudarão os desenvolvedores a entender melhor como definir layouts, serializar e desserializar dados, e usar conversões personalizadas quando necessário.
Definindo Layouts Para começar com layouts no Wormhole, você precisa definir sua estrutura. Um layout é simplesmente uma lista de campos (itens de layout) que descrevem como cada parte dos dados será serializada.
Considere o seguinte layout para um payload:
Neste exemplo:
sourceChain
é um inteiro não assinado (uint) de 2 bytesorderSender
é um array de bytes de 32 bytes de comprimento fixoredeemer
é outro array de 32 bytesredeemerMessage
é um array de bytes com comprimento prefixado, com o comprimento especificado por um inteiro de 4 bytes
Serializar Dados
Uma vez que o layout esteja definido, o próximo passo é serializar os dados de acordo com essa estrutura. Você pode fazer isso utilizando a função serializeLayout
do SDK do Wormhole:
Isso pega a estrutura de dados (examplePayload
) e a serializa de acordo com as regras definidas no layout (exampleLayout
). O resultado é um Uint8Array
representando os dados binários serializados.
Desserializar Dados
A desserialização é o processo reverso da serialização. Dado um Uint8Array
serializado, podemos convertê-lo de volta para sua estrutura original utilizando a função deserializeLayout
:
Isso gerará o objeto estruturado, facilitando o trabalho com dados transmitidos ou recebidos de outra cadeia.
Manipulando Campos de Comprimento Variável Um aspecto relevante do sistema de layout do SDK do Wormhole é a capacidade de lidar com campos de comprimento variável, como arrays e sequências de bytes com comprimento prefixado.
Por exemplo, se você deseja serializar ou desserializar uma mensagem onde o comprimento do conteúdo não é conhecido de antemão, você pode definir um item de layout com o campo lengthSize
:
Isso informa ao SDK para ler ou escrever o comprimento da mensagem (em 4 bytes) e depois manipular o conteúdo.
Layouts Aninhados e Tipagem Forte O SDK do Wormhole simplifica o manuseio de estruturas complexas com layouts aninhados e tipagem forte. Layouts aninhados representam dados hierárquicos, enquanto a tipagem forte garante a consistência dos dados e captura erros durante o desenvolvimento.
Layout Aninhado Em protocolos complexos, os layouts podem conter estruturas aninhadas. Layouts aninhados são úteis para representar dados hierárquicos (como transações ou mensagens multipartes) de maneira estruturada.
Veja o seguinte layout aninhado onde uma mensagem contém campos aninhados:
Neste layout:
source
é um objeto com dois campos:chainId
esender
redeemer
é outro objeto com dois campos:address
e uma mensagem com comprimento prefixado
Tipagem Forte Uma das vantagens de usar o SDK do Wormhole com TypeScript é seu suporte para tipagem forte. Isso garante que os dados serializados e desserializados estejam conformes as estruturas esperadas, reduzindo erros durante o desenvolvimento ao aplicar verificações de tipo em tempo de compilação.
Usando o TypeScript, a utilidade LayoutToType
fornecida pelo SDK gera automaticamente uma estrutura tipada de forma forte com base no layout:
Isso garante que, ao serializar ou desserializar dados, eles correspondam à estrutura esperada.
Tentar atribuir dados de tipos incorretos resultará em um erro de compilação. O sistema de layouts do SDK Wormhole aplica tipos fortes, reduzindo erros em tempo de execução e melhorando a confiabilidade do código.
Serialização e Desserialização com Estruturas Aninhadas
Você pode serializar e desserializar estruturas aninhadas da mesma forma que layouts mais simples:
A tipagem forte em TypeScript garante que o objeto message
esteja em conformidade com a estrutura do layout aninhado, reduzindo o risco de inconsistência de dados durante a comunicação cross-chain.
Layouts Comumente Usados
O SDK Wormhole inclui layouts pré-definidos comumente usados em mensagens cross-chain. Estes layouts são otimizados para campos padrão, como IDs de cadeia, endereços e assinaturas. Você pode explorar o conjunto completo de layouts pré-definidos no diretório layout-items
do SDK Wormhole.
Layouts de Chain ID
Os layouts de Chain ID no SDK Wormhole derivam de uma fundação comum: chainItemBase
. Esta estrutura define a representação binária de um Chain ID como um inteiro sem sinal de 2 bytes, garantindo consistência nos processos de serialização e desserialização.
Estrutura Base
Esta estrutura simples é o modelo para layouts mais específicos, padronizando o formato e o tamanho binário.
Layout Dinâmico de Chain ID
O layout dinâmico de Chain ID, chainItem
, estende chainItemBase
, adicionando lógica de conversão personalizada. Ele permite validação em tempo de execução de Chain IDs, suporta valores nulos opcionais e restringe os Chain IDs a um conjunto predefinido quando necessário.
Este layout é versátil. Ele permite a serialização de nomes de cadeias legíveis (ex: Ethereum) para IDs numéricos (ex: 1) e vice-versa, sendo especialmente útil ao trabalhar com configurações dinâmicas ou protocolos que suportam múltiplas cadeias.
Layout Fixo de Chain ID
O layout fixo de Chain ID, fixedChainItem
, é mais rígido. Ele também estende chainItemBase
, mas o campo custom
é codificado para uma única cadeia. Isso elimina a validação em tempo de execução e força a adesão rigorosa a uma cadeia específica.
Este layout permite que os desenvolvedores serializem e desserializem eficientemente mensagens que envolvem um único Chain ID fixo.
Layout de Endereço
O SDK Wormhole usa um Layout de Endereço Universal para serializar e desserializar endereços de blockchain em um formato padronizado. Este layout garante que os endereços sejam sempre representados como valores binários fixos de 32 bytes, possibilitando uma comunicação cross-chain sem problemas.
Estrutura Base
O universalAddressItem
define o layout para endereços. Ele usa o tipo binário bytes
e impõe um tamanho fixo de 32 bytes para consistência.
Este layout garante o manuseio consistente de endereços, definindo o seguinte:
Serialização: converte um objeto de
UniversalAddress
de alto nível em binário bruto (32 bytes) para armazenamento ou transmissão eficientes.Desserialização: converte o binário bruto de volta para um objeto
UniversalAddress
, permitindo interação adicional em um formato legível ou programático.
Layout de Assinatura
No SDK Wormhole, o Layout de Assinatura define como serializar e desserializar assinaturas criptográficas. Essas assinaturas verificam a autenticidade da mensagem e garantem a integridade dos dados, particularmente nas VAAs assinadas por Guardiões.
Estrutura Base
O signatureLayout
especifica a estrutura binária de uma assinatura secp256k1
. Ele divide a assinatura em três componentes:
Este layout fornece um formato binário claro para a assinatura secp256k1
, tornando o processamento eficiente dentro do protocolo Wormhole.
Layout com Conversão Personalizada
O signatureItem
baseia-se no signatureLayout
adicionando lógica de conversão personalizada. Essa conversão transforma os dados binários brutos em um objeto Signature
de alto nível e vice-versa.
O campo custom
garante a integração perfeita de dados binários brutos com a classe Signature
, encapsulando a lógica específica da assinatura.
Casos de Uso Avançados
O sistema de layout do SDK Wormhole foi projetado para lidar com várias estruturas de dados e necessidades de serialização. Esta seção explorará casos de uso mais avançados, como o tratamento de estruturas de dados condicionais, conversões fixas e otimização de desempenho de serialização.
Instruções Switch para Layouts Condicionais
Em alguns casos, a estrutura dos dados serializados pode mudar com base em um campo específico, como um ID de payload. O tipo de layout switch
define layouts condicionalmente com base em um valor.
Por exemplo, diferentes tipos de mensagens podem ser identificados usando um ID de payload, e o layout para cada mensagem pode ser determinado em tempo de execução:
A instrução switch
ajuda os desenvolvedores a analisar múltiplos tipos de payload usando a mesma estrutura, dependendo de um campo de controle como um ID.
Conversões Fixas e Campos Omitidos
Conversões fixas e campos omitidos permitem que os desenvolvedores manipulem dados estáticos conhecidos sem incluí-los em cada operação de serialização ou desserialização. Por exemplo, quando campos específicos em um layout sempre contêm um valor constante, eles podem ser omitidos do objeto desserializado.
Exemplo: Conversão Fixa
Em alguns casos, um campo pode sempre conter um valor predefinido. O sistema de layout oferece suporte a conversões fixas, permitindo que os desenvolvedores "codifiquem" esses valores:
Exemplo: Campos Omitidos
Campos omitidos são úteis para lidar com preenchimento ou campos reservados que não carregam informações significativas e podem ser excluídos com segurança da saída desserializada:
Neste exemplo, reserved
é um campo de preenchimento com um valor fixo, não dinâmico, que não tem propósito funcional. Ele é omitido do resultado desserializado, mas ainda é considerado durante a serialização para manter o formato binário correto.
Somente campos com valor fixo e conhecido, como preenchimento ou campos reservados, devem ser marcados como omit: true
. Campos com informações significativas ou dinâmicas, como sourceChain
ou version
, devem permanecer na estrutura desserializada para garantir a integridade dos dados e permitir conversões consistentes entre as representações serializadas e desserializadas.
Integração com o Protocolo Wormhole
O sistema de layout facilita a interação com o protocolo Wormhole, especialmente quando se trata de VAAs. Essas mensagens cross-chain precisam ser serializadas e desserializadas para garantir que possam ser transmitidas e processadas com precisão entre diferentes cadeias.
VAAs e Layouts
VAAs são a espinha dorsal da comunicação cross-chain do Wormhole. Cada VAA é uma mensagem assinada que encapsula informações importantes, como a cadeia de origem, o endereço do emissor, um número de sequência e assinaturas de Guardiões. O SDK Wormhole usa seu sistema de layout para definir, serializar e desserializar VAAs, garantindo integridade dos dados e compatibilidade entre as cadeias.
Estrutura Base do VAA
O SDK Wormhole organiza a estrutura do VAA em três componentes principais:
Cabeçalho: contém metadados, como o índice do conjunto de Guardiões e um array de assinaturas de Guardiões.
Envelope: inclui detalhes específicos da cadeia, como a cadeia do emissor, o endereço, a sequência e o nível de consistência.
Payload: fornece dados específicos da aplicação, como a mensagem ou operação sendo realizada.
Layout do Cabeçalho:
O cabeçalho define os metadados para validar e processar o VAA, como o índice do conjunto de Guardiões e as assinaturas. Cada assinatura é representada usando o layout signatureItem
, garantindo consistência e compatibilidade entre plataformas.
Layout do Envelope:
O envelope encapsula os dados principais da mensagem VAA, incluindo informações específicas da cadeia, como o endereço do emissor e o número da sequência. Este layout estruturado garante que o VAA possa ser transmitido de forma segura entre cadeias.
Layout da Payload:
A Payload contém os dados definidos pelo usuário específicos para o aplicativo ou protocolo, como uma mensagem de transferência de token, ação de governança ou outra operação entre cadeias. O layout da payload é dinâmico e depende do tipo de payload, identificado pelo campo payloadLiteral
.
Este exemplo demonstra uma payload contendo:
Um campo
type
que especifica o tipo da operação (por exemplo, transferência ou ação de governança)Um campo
data
que possui prefixo de comprimento e pode armazenar informações específicas da operação
Layouts de payload dinâmicos são selecionados em tempo de execução utilizando o campo payloadLiteral
, que mapeia para um layout predefinido no SDK Wormhole.
Layout Base Combinado:
O layout base VAA combina o cabeçalho, envelope e o layout de payload selecionado dinamicamente:
Em tempo de execução, o layout da payload é adicionado ao baseLayout
para formar a estrutura completa.
Serializando Dados VAA:
O SDK Wormhole fornece a função serialize
para serializar uma mensagem VAA. Essa função combina o layout base (cabeçalho e envelope) com o layout da payload apropriado, garantindo que o formato da mensagem esteja correto para transmissão entre cadeias.
Como funciona?
Internamente, a função serialize
combina dinamicamente o baseLayout
(cabeçalho e envelope) com o layout da payload definido pelo payloadLiteral
. O layout completo é passado para a função serializeLayout
, que converte os dados em formato binário.
Deserializando Dados VAA:
O SDK Wormhole fornece a função deserialize
para analisar um VAA de seu formato binário de volta para um objeto estruturado. Essa função usa o baseLayout
e a lógica de discriminador de payload para garantir que o VAA seja interpretado corretamente.
Como funciona?
Internamente, a função deserialize
usa o baseLayout
(cabeçalho e envelope) para analisar a estrutura principal do VAA. Em seguida, ela identifica o layout adequado da payload usando o tipo de payload ou discriminador fornecido.
Registrando Payloads Personalizadas:
No SDK Wormhole, as payloads dependem de layouts para definir sua estrutura binária, garantindo consistência e segurança de tipo entre protocolos. Payloads personalizadas ampliam essa funcionalidade, permitindo que os desenvolvedores tratem recursos específicos de protocolos ou casos de uso exclusivos.
Para aprender como definir e registrar payloads usando layouts, consulte a página "Construindo Protocolos e Payloads" para um guia detalhado.
Armadilhas Comuns e Melhores Práticas:
Ao trabalhar com o sistema de layouts do SDK Wormhole, é importante estar atento a alguns problemas comuns que podem surgir. Abaixo estão algumas armadilhas a evitar e melhores práticas para garantir uma integração suave.
Armadilhas a Evitar:
Definindo Tamanhos para Tipos de Dados: Ao definir os tamanhos para cada tipo de dado, certifique-se de que o comprimento dos dados corresponda ao tamanho especificado para evitar erros de serialização e deserialização.
Arrays Definidos de Forma Incorreta: Arrays podem ser de comprimento fixo ou prefixados por comprimento, por isso é importante definí-los corretamente.
Melhores Práticas:
Reutilizar Itens de Layout Predefinidos: Em vez de definir tamanhos ou tipos manualmente, reutilize os itens de layout predefinidos fornecidos pelo SDK Wormhole. Esses itens garantem formatação consistente e reforçam tipos fortes.
Usar Instâncias de Classes: Sempre que possível, converta dados desserializados em instâncias de classes de nível superior. Isso facilita a validação, manipulação e interação com dados estruturados.
Considerações de Desempenho:
A serialização e desserialização eficientes são cruciais ao lidar com grandes volumes de dados entre cadeias. Algumas estratégias incluem a Instanciação Preguiçosa para construir discriminadores apenas quando necessário, o que melhora a eficiência.
Recursos:
SDK TypeScript Wormhole: O repositório do SDK Wormhole contém a implementação central dos layouts, incluindo itens de layout predefinidos e utilitários como
serializeLayout
edeserializeLayout
.Repositório de Testes de Layout: Para experimentação prática, consulte este repositório de pacotes de layout, que fornece exemplos e testes unitários para ajudar a entender melhor a serialização, desserialização e o mecanismo de tipos fortes.
Last updated