sdk: add underlying sdk for wormhole programs
Change-Id: I858f3e43e6458af51131de9165a63078e4bb024c
This commit is contained in:
parent
97566d878a
commit
ee0fea0436
File diff suppressed because it is too large
Load Diff
|
@ -1,4 +1,5 @@
|
|||
[workspace]
|
||||
members = [
|
||||
"core",
|
||||
"sdk"
|
||||
]
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
[package]
|
||||
name = "wormhole-sdk"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
|
||||
[features]
|
||||
# Helper methods will target the Wormhole mainnet contract addresses.
|
||||
mainnet = []
|
||||
|
||||
# Helper methosd will target the Wormhole devnet contract addresses.
|
||||
devnet = []
|
||||
|
||||
# Enable Optional dependencies that are only required when targetting Terra.
|
||||
terra = [
|
||||
"cosmwasm-std",
|
||||
"cosmwasm-storage",
|
||||
"schemars",
|
||||
"serde",
|
||||
"wormhole-bridge-terra",
|
||||
]
|
||||
|
||||
# Enable Optional dependencies that are only required when targetting Solana.
|
||||
solana = [
|
||||
"solana-program",
|
||||
"wormhole-bridge-solana",
|
||||
]
|
||||
|
||||
[profile.release]
|
||||
opt-level = 3
|
||||
lto = "thin"
|
||||
|
||||
[dependencies]
|
||||
borsh = { version="0.8.1" }
|
||||
nom = { version="7", default-features=false, features=["alloc"] }
|
||||
primitive-types = { version = "0.9.0", default-features = false }
|
||||
wormhole-core = { path="../core", version="0.1.0" }
|
||||
|
||||
# Solana Specific
|
||||
solana-program = { version="1.7.0", optional=true }
|
||||
|
||||
# Terra Specific
|
||||
cosmwasm-std = { version = "0.16.0", optional=true }
|
||||
cosmwasm-storage = { version = "0.16.0", optional=true }
|
||||
schemars = { version = "0.8.1", optional=true }
|
||||
serde = { version = "1.0.103", default-features = false, features = ["derive"], optional=true }
|
||||
|
||||
[dependencies.wormhole-bridge-solana]
|
||||
path = "../../../solana/bridge/program"
|
||||
version = "0.1.0"
|
||||
optional = true
|
||||
features = [ "no-entrypoint" ]
|
||||
|
||||
[dependencies.wormhole-bridge-terra]
|
||||
path = "../../../terra/contracts/wormhole"
|
||||
version = "0.1.0"
|
||||
optional = true
|
||||
|
||||
|
||||
[dev-dependencies]
|
||||
byteorder = "*"
|
||||
hex = "*"
|
|
@ -0,0 +1,7 @@
|
|||
[build]
|
||||
rustflags = [
|
||||
"-Cpasses=sancov-module",
|
||||
"-Cllvm-args=-sanitizer-coverage-level=3",
|
||||
"-Cllvm-args=-sanitizer-coverage-inline-8bit-counters",
|
||||
"-Zsanitizer=address",
|
||||
]
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,27 @@
|
|||
[package]
|
||||
name = "wormhole-sdk-fuzz"
|
||||
version = "0.0.0"
|
||||
edition = "2021"
|
||||
publish = false
|
||||
|
||||
[package.metadata]
|
||||
cargo-fuzz = true
|
||||
|
||||
[dependencies]
|
||||
libfuzzer-sys = "0.4"
|
||||
|
||||
[dependencies.wormhole-sdk]
|
||||
path = ".."
|
||||
features = ["solana", "vaa"]
|
||||
|
||||
# Create isolated workspace.
|
||||
[workspace]
|
||||
members = ["."]
|
||||
|
||||
[[bin]]
|
||||
name = "vaa"
|
||||
path = "fuzzers/vaa.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "governance"
|
||||
path = "fuzzers/governance.rs"
|
|
@ -0,0 +1,8 @@
|
|||
#![no_main]
|
||||
use libfuzzer_sys::fuzz_target;
|
||||
use wormhole_sdk::VAA;
|
||||
|
||||
fuzz_target!(|data: &[u8]| {
|
||||
VAA::from_bytes(data);
|
||||
});
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
#![no_main]
|
||||
use libfuzzer_sys::fuzz_target;
|
||||
use wormhole_sdk::vaa::VAA;
|
||||
|
||||
fuzz_target!(|data: &[u8]| {
|
||||
VAA::from_bytes(data);
|
||||
});
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
//! Exposes an API implementation depending on which feature flags have been toggled for the
|
||||
//! library. Check submodules for chain runtime specific documentation.
|
||||
|
||||
|
||||
#[cfg(feature = "solana")]
|
||||
pub mod solana;
|
||||
#[cfg(feature = "solana")]
|
||||
pub use solana::*;
|
||||
|
||||
|
||||
#[cfg(feature = "terra")]
|
||||
pub mod terra;
|
||||
#[cfg(feature = "terra")]
|
||||
pub use terra::*;
|
|
@ -0,0 +1,134 @@
|
|||
use borsh::BorshDeserialize;
|
||||
use solana_program::pubkey::Pubkey;
|
||||
use solana_program::account_info::AccountInfo;
|
||||
use solana_program::entrypoint::ProgramResult;
|
||||
use solana_program::program::invoke_signed;
|
||||
use std::str::FromStr;
|
||||
|
||||
// Export Bridge API
|
||||
pub use bridge::BridgeConfig;
|
||||
pub use bridge::BridgeData;
|
||||
pub use bridge::MessageData;
|
||||
pub use bridge::PostVAAData;
|
||||
pub use bridge::PostedVAAData;
|
||||
pub use bridge::VerifySignaturesData;
|
||||
pub use bridge::instructions;
|
||||
pub use bridge::solitaire as bridge_entrypoint;
|
||||
pub use bridge::types::ConsistencyLevel;
|
||||
|
||||
use wormhole_core::WormholeError;
|
||||
use wormhole_core::VAA;
|
||||
|
||||
/// Export Core Mainnet Contract Address
|
||||
#[cfg(feature = "mainnet")]
|
||||
pub fn id() -> Pubkey {
|
||||
Pubkey::from_str("worm2ZoG2kUd4vFXhvjh93UUH596ayRfgQ2MgjNMTth").unwrap()
|
||||
}
|
||||
|
||||
/// Export Core Devnet Contract Address
|
||||
#[cfg(feature = "testnet")]
|
||||
pub fn id() -> Pubkey {
|
||||
Pubkey::from_str("3u8hJUVTA4jH1wYAyUur7FFZVQ8H635K3tSHHF4ssjQ5").unwrap()
|
||||
}
|
||||
|
||||
/// Export Local Tilt Devnet Contract Address
|
||||
#[cfg(feature = "devnet")]
|
||||
pub fn id() -> Pubkey {
|
||||
Pubkey::from_str("Bridge1p5gheXUvJ6jGWGeCsgPKgnE3YgdGKRVCMY9o").unwrap()
|
||||
}
|
||||
|
||||
/// Derives the Wormhole configuration account address.
|
||||
pub fn config(id: &Pubkey) -> Pubkey {
|
||||
let (config, _) = Pubkey::find_program_address(&[b"Bridge"], &id);
|
||||
config
|
||||
}
|
||||
|
||||
/// Derives the Wormhole fee account address, users of the bridge must pay this address before
|
||||
/// submitting messages to the bridge.
|
||||
pub fn fee_collector(id: &Pubkey) -> Pubkey {
|
||||
let (fee_collector, _) = Pubkey::find_program_address(&[b"fee_collector"], &id);
|
||||
fee_collector
|
||||
}
|
||||
|
||||
/// Derives the sequence address for an emitter, which is incremented after each message post.
|
||||
pub fn sequence(id: &Pubkey, emitter: &Pubkey) -> Pubkey {
|
||||
let (sequence, _) = Pubkey::find_program_address(&[b"Sequence", &emitter.to_bytes()], &id);
|
||||
sequence
|
||||
}
|
||||
|
||||
/// Derives the emitter address for a Solana contract, the emitter on Solana must be a signer, this
|
||||
/// function helps generate a PDA and bump seed so users can emit using a PDA as the emitter.
|
||||
pub fn emitter(id: &Pubkey) -> (Pubkey, Vec<&[u8]>, u8) {
|
||||
let seeds = &["emitter".as_bytes()];
|
||||
let (emitter, bump) = Pubkey::find_program_address(seeds, id);
|
||||
(emitter, seeds.to_vec(), bump)
|
||||
}
|
||||
|
||||
/// Deserialize helper the BridgeConfig from a Wormhole config account.
|
||||
pub fn read_config(config: &AccountInfo) -> Result<BridgeConfig, WormholeError> {
|
||||
let bridge_data = BridgeData::try_from_slice(&config.data.borrow())
|
||||
.map_err(|_| WormholeError::DeserializeFailed)?;
|
||||
Ok(bridge_data.config)
|
||||
}
|
||||
|
||||
/// Deserialize helper for parsing from Borsh encoded VAA's from Solana accounts.
|
||||
pub fn read_vaa(vaa: &AccountInfo) -> Result<PostedVAAData, WormholeError> {
|
||||
Ok(PostedVAAData::try_from_slice(&vaa.data.borrow())
|
||||
.map_err(|_| WormholeError::DeserializeFailed)?)
|
||||
}
|
||||
|
||||
/// This helper method wraps the steps required to invoke Wormhole, it takes care of fee payment,
|
||||
/// emitter derivation, and function invocation. This will be the right thing to use if you need to
|
||||
/// simply emit a message in the most straight forward way possible.
|
||||
pub fn post_message(
|
||||
program_id: Pubkey,
|
||||
payer: Pubkey,
|
||||
message: Pubkey,
|
||||
payload: impl AsRef<[u8]>,
|
||||
consistency: ConsistencyLevel,
|
||||
seeds: Option<&[&[u8]]>,
|
||||
accounts: &[AccountInfo],
|
||||
nonce: u32,
|
||||
) -> ProgramResult {
|
||||
// Derive any necessary Pubkeys, derivation makes sure that we match the accounts the are being
|
||||
// provided by the user as well.
|
||||
let id = id();
|
||||
let fee_collector = fee_collector(&id);
|
||||
let (emitter, mut emitter_seeds, bump) = emitter(&program_id);
|
||||
let bump = &[bump];
|
||||
emitter_seeds.push(bump);
|
||||
|
||||
// Filter for the Config AccountInfo so we can access its data.
|
||||
let config = config(&id);
|
||||
let config = accounts.iter().find(|item| *item.key == config).unwrap();
|
||||
let config = read_config(config).unwrap();
|
||||
|
||||
// Pay Fee to the Wormhole
|
||||
invoke_signed(
|
||||
&solana_program::system_instruction::transfer(
|
||||
&payer,
|
||||
&fee_collector,
|
||||
config.fee
|
||||
),
|
||||
accounts,
|
||||
&[],
|
||||
)?;
|
||||
|
||||
// Invoke the Wormhole post_message endpoint to create an on-chain message.
|
||||
invoke_signed(
|
||||
&instructions::post_message(
|
||||
id,
|
||||
payer,
|
||||
emitter,
|
||||
message,
|
||||
nonce,
|
||||
payload.as_ref().to_vec(),
|
||||
consistency,
|
||||
)
|
||||
.unwrap(),
|
||||
accounts,
|
||||
&[&emitter_seeds, seeds.unwrap_or(&[])],
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
use cosmwasm_std::{
|
||||
to_binary,
|
||||
Addr,
|
||||
Binary,
|
||||
CosmosMsg,
|
||||
DepsMut,
|
||||
Env,
|
||||
QueryRequest,
|
||||
StdResult,
|
||||
WasmMsg,
|
||||
WasmQuery,
|
||||
};
|
||||
use serde::Serialize;
|
||||
|
||||
use bridge::msg::{
|
||||
ExecuteMsg,
|
||||
QueryMsg,
|
||||
};
|
||||
use bridge::state::ParsedVAA;
|
||||
|
||||
/// Export Core Mainnet Contract Address
|
||||
#[cfg(feature = "mainnet")]
|
||||
pub fn id() -> Addr {
|
||||
Addr::unchecked("terra1dq03ugtd40zu9hcgdzrsq6z2z4hwhc9tqk2uy5")
|
||||
}
|
||||
|
||||
/// Export Core Devnet Contract Address
|
||||
#[cfg(feature = "devnet")]
|
||||
pub fn id() -> Addr {
|
||||
Addr::unchecked("terra1pd65m0q9tl3v8znnz5f5ltsfegyzah7g42cx5v")
|
||||
}
|
||||
|
||||
pub fn post_message<T>(wormhole: Addr, nonce: u32, message: &T) -> StdResult<CosmosMsg>
|
||||
where
|
||||
T: Serialize,
|
||||
T: ?Sized,
|
||||
{
|
||||
Ok(CosmosMsg::Wasm(WasmMsg::Execute {
|
||||
contract_addr: wormhole.to_string(),
|
||||
funds: vec![],
|
||||
msg: to_binary(&ExecuteMsg::PostMessage {
|
||||
message: to_binary(message)?,
|
||||
nonce,
|
||||
})?,
|
||||
}))
|
||||
}
|
||||
|
||||
/// Parse a VAA using the Wormhole contract Query interface.
|
||||
pub fn parse_vaa(
|
||||
wormhole: Addr,
|
||||
deps: DepsMut,
|
||||
env: Env,
|
||||
data: &Binary,
|
||||
) -> StdResult<ParsedVAA> {
|
||||
let vaa: ParsedVAA = deps.querier.query(&QueryRequest::Wasm(WasmQuery::Smart {
|
||||
contract_addr: wormhole.to_string(),
|
||||
msg: to_binary(&QueryMsg::VerifyVAA {
|
||||
vaa: data.clone(),
|
||||
block_time: env.block.time.seconds(),
|
||||
})?,
|
||||
}))?;
|
||||
Ok(vaa)
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
//! This SDK provides API's for implementing cross-chain message passing via the Wormhole protocol.
|
||||
//! This package aims to provide a consistent API regardless of the underlying runtime, but some
|
||||
//! types will differ depending on which implementation is being targeted.
|
||||
//!
|
||||
//! Each implementation can be toggled using feature flags, which will switch out the underlying
|
||||
//! depenencies to pull in the depenendices for the corresponding runtimes.
|
||||
//!
|
||||
//! Implementations:
|
||||
//!
|
||||
//! Runtime | Feature Flag | Version
|
||||
//! ----------|-------------------------|----------------------------------------------------
|
||||
//! Solana | --feature=solana | solana-sdk 1.7.1
|
||||
//! Terra | --feature=terra | cosmos-sdk 0.16.0
|
||||
//!
|
||||
//! Docs specific to each blockchain's runtime can be found in submodules within the chains module
|
||||
//! at the root of this package.
|
||||
|
||||
pub mod chains;
|
||||
|
||||
pub use wormhole_core::*;
|
||||
pub use chains::*;
|
|
@ -28,7 +28,7 @@ pub type PostedMessage<'a, const State: AccountState> = Data<'a, PostedMessageDa
|
|||
#[repr(transparent)]
|
||||
pub struct PostedMessageData(pub MessageData);
|
||||
|
||||
#[derive(Default, BorshSerialize, BorshDeserialize, Clone, Serialize, Deserialize)]
|
||||
#[derive(Debug, Default, BorshSerialize, BorshDeserialize, Clone, Serialize, Deserialize)]
|
||||
pub struct MessageData {
|
||||
/// Header of the posted VAA
|
||||
pub vaa_version: u8,
|
||||
|
|
Loading…
Reference in New Issue