//! VAA's represent a collection of signatures combined with a message and its metadata. VAA's are //! used as a form of proof; by submitting a VAA to a target contract, the receiving contract can //! make assumptions about the validity of state on the source chain. //! //! Wormhole defines several VAA's for use within Token/NFT bridge implemenetations, as well as //! governance specific VAA's used within Wormhole's guardian network. //! //! This module provides definitions and parsers for all current Wormhole standard VAA's, and //! includes parsers for the core VAA type. Programs targetting wormhole can use this module to //! parse and verify incoming VAA's securely. use std::io::{self, Write}; use anyhow::Context; use serde::{Deserialize, Serialize}; use sha3::Digest as Sha3Digest; use crate::{Address, Chain, GuardianAddress}; /// Signatures are typical ECDSA signatures prefixed with a Guardian position. These have the /// following byte layout: /// ```markdown /// 0 .. 64: Signature (ECDSA) /// 64 .. 65: Recovery ID (ECDSA) /// ``` #[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Signature { pub index: u8, #[serde(with = "crate::serde_array")] pub signature: [u8; 65], } impl Default for Signature { fn default() -> Self { Self { index: 0, signature: [0; 65], } } } /// The core VAA itself. This structure is what is received by a contract on the receiving side of /// a wormhole message passing flow. The generic parameter `P` represents the user-defined payload /// for the VAA. #[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Vaa
{
// Implementation note: it would be nice if we could use `#[serde(flatten)]` and directly embed the
// `Header` and `Body` structs. Unfortunately using flatten causes serde to serialize/deserialize
// the struct as a map, which requires the underlying data format to encode field names on the
// wire, which the wormhole data format does not do. So instead we have to duplicate the fields
// and provide a conversion function to/from `Vaa` to `(Header, Body)`.
pub version: u8,
pub guardian_set_index: u32,
pub signatures: Vec {
/// Seconds since UNIX epoch.
pub timestamp: u32,
pub nonce: u32,
pub emitter_chain: Chain,
pub emitter_address: Address,
pub sequence: u64,
pub consistency_level: u8,
pub payload: P,
}
/// Digest data for the Body.
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Digest {
/// Guardians don't hash the VAA body directly, instead they hash the VAA and sign the hash. The
/// purpose of this is it means when submitting a VAA on-chain we only have to submit the hash
/// which reduces gas costs.
pub hash: [u8; 32],
/// The secp256k_hash is the hash of the hash of the VAA. The reason we provide this is because
/// of how secp256k works internally. It hashes its payload before signing. This means that
/// when verifying secp256k signatures, we're actually checking if a guardian has signed the
/// hash of the hash of the VAA. Functions such as `ecrecover` expect the secp256k hash rather
/// than the original payload.
pub secp256k_hash: [u8; 32],
}
/// Calculates and returns the digest for `body` to be used in VAA operations.
///
/// A VAA is distinguished by the unique 256bit Keccak256 hash of its body. This hash is
/// utilised in all Wormhole components for identifying unique VAA's, including the bridge,
/// modules, and core guardian software. The `Digest` is documented with reasoning for
/// each field.
///
/// NOTE: This function uses a library to do Keccak256 hashing, but on-chain this may not be
/// efficient. If efficiency is needed, consider calling `body()` instead and hashing the
/// result using on-chain primitives.
pub fn digest(body: &[u8]) -> io::Result Vaa {
/// Check if the VAA is a Governance VAA.
pub fn is_governance(&self) -> bool {
self.emitter_address == crate::GOVERNANCE_EMITTER && self.emitter_chain == Chain::Solana
}
}
impl From ) {
fn from(v: Vaa ) -> Self {
(
Header {
version: v.version,
guardian_set_index: v.guardian_set_index,
signatures: v.signatures,
},
Body {
timestamp: v.timestamp,
nonce: v.nonce,
emitter_chain: v.emitter_chain,
emitter_address: v.emitter_address,
sequence: v.sequence,
consistency_level: v.consistency_level,
payload: v.payload,
},
)
}
}
impl From<(Header, Body )> for Vaa {
fn from((hdr, body): (Header, Body )) -> Self {
Vaa {
version: hdr.version,
guardian_set_index: hdr.guardian_set_index,
signatures: hdr.signatures,
timestamp: body.timestamp,
nonce: body.nonce,
emitter_chain: body.emitter_chain,
emitter_address: body.emitter_address,
sequence: body.sequence,
consistency_level: body.consistency_level,
payload: body.payload,
}
}
}
impl Header {
pub fn verify(&self, _body: &[u8], _addrs: &[GuardianAddress]) -> anyhow::Result {
/// Body Digest Components.
///
/// A VAA is distinguished by the unique 256bit Keccak256 hash of its body. This hash is
/// utilised in all Wormhole components for identifying unique VAA's, including the bridge,
/// modules, and core guardian software. The `Digest` is documented with reasoning for
/// each field.
///
/// NOTE: This function uses a library to do Keccak256 hashing, but on-chain this may not be
/// efficient. If efficiency is needed, consider calling `serde_wormhole::to_writer` instead
/// and hashing the result using on-chain primitives.
#[inline]
pub fn digest(&self) -> anyhow::Result