Browse Source

Implement a bridge stub for testing

Change-Id: Ide97a1df9d55658eeea79f7886a3a504a9108fda
Hendrik Hofstadt 4 years ago
parent
commit
897af148fc

+ 20 - 0
solana/bridge/Cargo.lock

@@ -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"

+ 1 - 1
solana/bridge/Cargo.toml

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

+ 2 - 2
solana/bridge/program/src/lib.rs

@@ -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,

+ 34 - 0
solana/bridge/program_stub/Cargo.toml

@@ -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"

+ 2 - 0
solana/bridge/program_stub/Xargo.toml

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

+ 7 - 0
solana/bridge/program_stub/src/api.rs

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

+ 121 - 0
solana/bridge/program_stub/src/api/post_vaa.rs

@@ -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(())
+}

+ 27 - 0
solana/bridge/program_stub/src/lib.rs

@@ -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,
+}