Implement a bridge stub for testing

Change-Id: Ide97a1df9d55658eeea79f7886a3a504a9108fda
This commit is contained in:
Hendrik Hofstadt 2021-07-26 21:26:17 +02:00
parent f6932bebca
commit 897af148fc
8 changed files with 214 additions and 3 deletions

View File

@ -339,6 +339,26 @@ dependencies = [
"solitaire-client",
]
[[package]]
name = "bridge_stub"
version = "0.1.0"
dependencies = [
"borsh",
"bridge",
"byteorder",
"hex",
"hex-literal",
"libsecp256k1",
"primitive-types 0.9.0",
"rand 0.7.3",
"sha3",
"solana-client",
"solana-program",
"solana-sdk",
"solitaire",
"solitaire-client",
]
[[package]]
name = "bs58"
version = "0.3.1"

View File

@ -1,2 +1,2 @@
[workspace]
members = ["agent", "program", "client"]
members = ["agent", "program", "client", "program_stub"]

View File

@ -50,8 +50,8 @@ pub use vaa::{
SerializePayload,
};
const MAX_LEN_GUARDIAN_KEYS: usize = 19;
const CHAIN_ID_SOLANA: u16 = 1;
pub const MAX_LEN_GUARDIAN_KEYS: usize = 19;
pub const CHAIN_ID_SOLANA: u16 = 1;
solitaire! {
Initialize(InitializeData) => initialize,

View File

@ -0,0 +1,34 @@
[package]
name = "bridge_stub"
version = "0.1.0"
description = "Wormhole bridge core contract"
edition = "2018"
[lib]
crate-type = ["cdylib", "lib"]
name = "bridge_stub"
[features]
client = ["solitaire/client", "solitaire-client", "no-entrypoint"]
cpi = ["no-entrypoint"]
default = []
no-entrypoint = ["solitaire/no-entrypoint"]
trace = ["solitaire/trace"]
[dependencies]
borsh = "0.8.1"
byteorder = "1.4.3"
primitive-types = { version = "0.9.0", default-features = false }
sha3 = "0.9.1"
solana-program = "=1.7.0"
solitaire-client = { path = "../../solitaire/client", optional = true }
solitaire = { path = "../../solitaire/program" }
bridge = { path = "../program", features = ["no-entrypoint"] }
[dev-dependencies]
hex = "*"
rand = "0.7.3"
hex-literal = "0.3.1"
libsecp256k1 = { version = "0.3.5", features = [] }
solana-client = "1.7.0"
solana-sdk = "=1.7.0"

View File

@ -0,0 +1,2 @@
[target.bpfel-unknown-unknown.dependencies.std]
features = []

View File

@ -0,0 +1,7 @@
pub mod post_vaa;
pub use bridge::{
initialize::*,
post_message::*,
};
pub use post_vaa::*;

View File

@ -0,0 +1,121 @@
use solitaire::*;
use borsh::{
BorshDeserialize,
BorshSerialize,
};
use solana_program::{
self,
sysvar::clock::Clock,
};
use bridge::{
accounts::{
Bridge,
GuardianSetDerivationData,
Message,
MessageDerivationData,
},
CHAIN_ID_SOLANA,
};
use solana_program::pubkey::Pubkey;
use solitaire::{
processors::seeded::Seeded,
CreationLamports::Exempt,
};
impl From<&PostVAAData> for GuardianSetDerivationData {
fn from(data: &PostVAAData) -> Self {
GuardianSetDerivationData {
index: data.guardian_set_index,
}
}
}
#[derive(FromAccounts)]
pub struct PostVAA<'b> {
/// Information about the current guardian set.
pub guardian_set: Info<'b>,
/// Bridge Info
pub bridge_info: Bridge<'b, { AccountState::Initialized }>,
/// Signature Info
pub signature_set: Info<'b>,
/// Message the VAA is associated with.
pub message: Mut<Message<'b, { AccountState::MaybeInitialized }>>,
/// Account used to pay for auxillary instructions.
pub payer: Mut<Signer<Info<'b>>>,
/// Clock used for timestamping.
pub clock: Sysvar<'b, Clock>,
}
impl<'b> InstructionContext<'b> for PostVAA<'b> {
fn verify(&self, _program_id: &Pubkey) -> Result<()> {
Ok(())
}
}
#[derive(Default, BorshSerialize, BorshDeserialize)]
pub struct Signature {
pub index: u8,
pub r: [u8; 32],
pub s: [u8; 32],
pub v: u8,
}
pub type ForeignAddress = [u8; 32];
#[derive(Default, BorshSerialize, BorshDeserialize)]
pub struct PostVAAData {
// Header part
pub version: u8,
pub guardian_set_index: u32,
// Body part
pub timestamp: u32,
pub nonce: u32,
pub emitter_chain: u16,
pub emitter_address: ForeignAddress,
pub sequence: u64,
pub consistency_level: u8,
pub payload: Vec<u8>,
}
pub fn post_vaa(ctx: &ExecutionContext, accs: &mut PostVAA, vaa: PostVAAData) -> Result<()> {
let mut msg_derivation = MessageDerivationData {
emitter_key: vaa.emitter_address,
emitter_chain: vaa.emitter_chain,
nonce: vaa.nonce,
payload: vaa.payload.clone(),
sequence: None,
};
if vaa.emitter_chain != CHAIN_ID_SOLANA {
msg_derivation.sequence = Some(vaa.sequence)
}
accs.message
.verify_derivation(ctx.program_id, &msg_derivation)?;
// If the VAA originates from another chain we need to create the account and populate all fields
if !accs.message.is_initialized() {
accs.message.nonce = vaa.nonce;
accs.message.emitter_chain = vaa.emitter_chain;
accs.message.emitter_address = vaa.emitter_address;
accs.message.sequence = vaa.sequence;
accs.message.payload = vaa.payload;
accs.message.consistency_level = vaa.consistency_level;
accs.message
.create(&msg_derivation, ctx, accs.payer.key, Exempt)?;
}
// Store VAA data in associated message.
accs.message.vaa_version = vaa.version;
accs.message.vaa_time = vaa.timestamp;
accs.message.vaa_signature_account = *accs.signature_set.info().key;
Ok(())
}

View File

@ -0,0 +1,27 @@
#![feature(const_generics)]
#![allow(non_upper_case_globals)]
#![allow(incomplete_features)]
pub mod api;
use solitaire::*;
pub use api::{
initialize,
post_message,
post_vaa,
Initialize,
InitializeData,
PostMessage,
PostMessageData,
PostVAA,
PostVAAData,
Signature,
UninitializedMessage,
};
solitaire! {
Initialize(InitializeData) => initialize,
PostMessage(PostMessageData) => post_message,
PostVAA(PostVAAData) => post_vaa,
}