From 16f7e156ae1f4498d299018bae2f96a8a0492cf5 Mon Sep 17 00:00:00 2001 From: Reisen Date: Wed, 23 Jun 2021 10:46:21 +0000 Subject: [PATCH] Fix Derivation issues for PostVAA accounts. Change-Id: Ia08003dc8aadfe3963598c81745813e6e09e5d3a --- solana/bridge/program/src/accounts.rs | 1 - solana/bridge/program/src/api/governance.rs | 2 - solana/bridge/program/src/api/post_vaa.rs | 7 +-- .../program/src/api/verify_signature.rs | 9 +-- solana/bridge/program/src/types.rs | 15 ++--- solana/bridge/program/tests/common.rs | 58 +++++++++++++++---- solana/bridge/program/tests/integration.rs | 15 ++--- solana/solitaire/program/src/macros.rs | 4 +- .../solitaire/program/src/processors/peel.rs | 2 +- .../solitaire/program/src/types/accounts.rs | 2 +- 10 files changed, 69 insertions(+), 46 deletions(-) diff --git a/solana/bridge/program/src/accounts.rs b/solana/bridge/program/src/accounts.rs index b659f084..11c87b94 100644 --- a/solana/bridge/program/src/accounts.rs +++ b/solana/bridge/program/src/accounts.rs @@ -85,7 +85,6 @@ impl<'b, const State: AccountState> Seeded<&MessageDerivationData> for Message<' data.nonce.to_be_bytes().to_vec(), ]; seeds.append(&mut data.payload.chunks(32).map(|v| v.to_vec()).collect()); - seeds } } diff --git a/solana/bridge/program/src/api/governance.rs b/solana/bridge/program/src/api/governance.rs index 436b2d7d..c9a5a4d3 100644 --- a/solana/bridge/program/src/api/governance.rs +++ b/solana/bridge/program/src/api/governance.rs @@ -1,7 +1,5 @@ use solitaire::*; -use solana_program::{self,}; - use crate::types::{ self, GovernancePayloadSetMessageFee, diff --git a/solana/bridge/program/src/api/post_vaa.rs b/solana/bridge/program/src/api/post_vaa.rs index b4b5ff2e..e7a91fb7 100644 --- a/solana/bridge/program/src/api/post_vaa.rs +++ b/solana/bridge/program/src/api/post_vaa.rs @@ -114,7 +114,6 @@ pub struct PostVAAData { } pub fn post_vaa(ctx: &ExecutionContext, accs: &mut PostVAA, vaa: PostVAAData) -> Result<()> { - msg!("Post VAA Entered"); let msg_derivation = MessageDerivationData { emitter_key: vaa.emitter_address, emitter_chain: vaa.emitter_chain, @@ -135,11 +134,7 @@ pub fn post_vaa(ctx: &ExecutionContext, accs: &mut PostVAA, vaa: PostVAAData) -> .signature_set .signatures .iter() - .filter(|v| - v.0.iter().filter(|v| **v != 0).count() != 0 || - v.1.iter().filter(|v| **v != 0).count() != 0 || - v.2 != 0 - ) + .filter(|v| v.iter().filter(|v| **v != 0).count() != 0) .count(); // Calculate how many signatures are required to reach consensus. This calculation is in diff --git a/solana/bridge/program/src/api/verify_signature.rs b/solana/bridge/program/src/api/verify_signature.rs index 2573ded6..4bd795db 100644 --- a/solana/bridge/program/src/api/verify_signature.rs +++ b/solana/bridge/program/src/api/verify_signature.rs @@ -200,6 +200,7 @@ pub fn verify_signatures( // Track whether the account needs initialization // Prepare message/payload-specific sig_info account if !accs.signature_set.is_initialized() { + accs.signature_set.signatures = vec![[0u8; 65]; 19]; accs.signature_set.guardian_set_index = accs.guardian_set.index; accs.signature_set.hash = data.hash; @@ -237,12 +238,8 @@ pub fn verify_signatures( } // Overwritten content should be zeros except double signs by the signer or harmless replays - accs.signature_set.signatures[s.signer_index as usize].0 - .copy_from_slice(&secp_ixs[s.sig_index as usize].signature[0..32]); - accs.signature_set.signatures[s.signer_index as usize].1 - .copy_from_slice(&secp_ixs[s.sig_index as usize].signature[32..64]); - accs.signature_set.signatures[s.signer_index as usize].2 = - secp_ixs[s.sig_index as usize].signature[64]; + accs.signature_set.signatures[s.signer_index as usize] + .copy_from_slice(&secp_ixs[s.sig_index as usize].signature); } Ok(()) diff --git a/solana/bridge/program/src/types.rs b/solana/bridge/program/src/types.rs index e6de2c08..915868bc 100644 --- a/solana/bridge/program/src/types.rs +++ b/solana/bridge/program/src/types.rs @@ -73,6 +73,7 @@ pub struct BridgeConfig { /// guarantees that VAAs issued by that set can still be submitted for a certain period. In /// this period we still trust the old guardian set. pub guardian_set_expiration_time: u32, + /// Amount of lamports that needs to be paid to the protocol to post a message pub fee: u64, } @@ -95,18 +96,10 @@ impl Owned for BridgeData { } } -// Temporary work around the fact there is no Default for [u8; 64/65] and therefore no Borsh -// implementation for the type. Cannot use Vec<> as we don't know the size to deserialize. -type SplitSignature = ( - [u8; 32], - [u8; 32], - u8, -); - #[derive(Default, BorshSerialize, BorshDeserialize)] pub struct SignatureSet { /// Signatures of validators - pub signatures: [SplitSignature; 19], + pub signatures: Vec<[u8; 65]>, /// Hash of the data pub hash: [u8; 32], @@ -126,6 +119,7 @@ pub struct PostedMessage(pub PostedMessageData); impl BorshSerialize for PostedMessage { fn serialize(&self, writer: &mut W) -> std::io::Result<()> { + // King of Flavour writer.write(&['m' as u8, 's' as u8, 'g' as u8]); BorshSerialize::serialize(&self.0, writer) } @@ -133,8 +127,9 @@ impl BorshSerialize for PostedMessage { impl BorshDeserialize for PostedMessage { fn deserialize(buf: &mut &[u8]) -> std::io::Result { + *buf = &buf[3..]; Ok(PostedMessage( - ::deserialize(&mut &buf[3..])?, + ::deserialize(buf)?, )) } } diff --git a/solana/bridge/program/tests/common.rs b/solana/bridge/program/tests/common.rs index 53967747..1cb7aec3 100644 --- a/solana/bridge/program/tests/common.rs +++ b/solana/bridge/program/tests/common.rs @@ -3,6 +3,7 @@ use secp256k1::SecretKey; use borsh::BorshSerialize; use solana_client::rpc_client::RpcClient; +use solana_client::rpc_config::RpcSendTransactionConfig; use solana_program::{ borsh::try_from_slice_unchecked, hash, @@ -29,6 +30,7 @@ use std::{ }; use solana_sdk::{ + commitment_config::CommitmentConfig, secp256k1_instruction::new_secp256k1_instruction, signature::{ read_keypair_file, @@ -44,6 +46,7 @@ use bridge::{ GuardianSetDerivationData, SignatureSet, SignaturesSetDerivationData, + Message, MessageDerivationData, }, instruction, @@ -68,6 +71,18 @@ pub use instructions::*; mod helpers { use super::*; + fn rpc_send(client: &RpcClient, tx: Transaction) { + client.send_and_confirm_transaction_with_spinner_and_config( + &tx, + CommitmentConfig::processed(), + RpcSendTransactionConfig { + skip_preflight: true, + preflight_commitment: None, + encoding: None, + }, + ).unwrap(); + } + pub fn setup() -> (Keypair, RpcClient, Pubkey) { let payer = read_keypair_file(env::var("BRIDGE_PAYER").unwrap_or("./payer.json".to_string())).unwrap(); let rpc = RpcClient::new(env::var("BRIDGE_RPC").unwrap_or("http://127.0.0.1:8899".to_string())); @@ -75,7 +90,6 @@ mod helpers { .unwrap_or("6mFKdAtUBVbsQ5dgvBrUkn1Pixb7BMTUtVKj4dpwrmQs".to_string()) .parse::() .unwrap(); - (payer, rpc, program) } @@ -85,7 +99,7 @@ mod helpers { let mut transaction = Transaction::new_with_payer(&instructions, Some(&from.pubkey())); let recent_blockhash = client.get_recent_blockhash().unwrap().0; transaction.sign(&signers, recent_blockhash); - client.send_and_confirm_transaction(&transaction).unwrap(); + rpc_send(client, transaction); } pub fn initialize( @@ -112,7 +126,7 @@ mod helpers { let recent_blockhash = client.get_recent_blockhash().unwrap().0; transaction.sign(&signers, recent_blockhash); - client.send_and_confirm_transaction(&transaction).unwrap(); + rpc_send(client, transaction); } pub fn post_message( @@ -132,7 +146,7 @@ mod helpers { emitter_key: emitter.pubkey().to_bytes(), emitter_chain: message.emitter_chain, nonce: message.nonce, - payload: message.payload, + payload: message.payload.clone(), }, program); println!("PostMessage: Derived Keys:"); @@ -160,7 +174,7 @@ mod helpers { let recent_blockhash = client.get_recent_blockhash().unwrap().0; transaction.sign(&signers, recent_blockhash); - client.send_and_confirm_transaction(&transaction).unwrap(); + rpc_send(client, transaction); } pub fn verify_signatures( @@ -208,23 +222,45 @@ mod helpers { let recent_blockhash = client.get_recent_blockhash().unwrap().0; transaction.sign(&signers, recent_blockhash); - client.send_and_confirm_transaction(&transaction).unwrap(); + rpc_send(client, transaction); } pub fn post_vaa( client: &RpcClient, program: &Pubkey, payer: &Keypair, + body_hash: [u8; 32], + message: Vec, + emitter: &Keypair, guardian_set: GuardianSetDerivationData, vaa: PostVAAData, ) { + let (bridge, _) = Pubkey::find_program_address(&["Bridge".as_ref()], program); let guardian_set = GuardianSet::<'_, { AccountState::Uninitialized }>::key( &guardian_set, &program, ); - let (bridge, _) = Pubkey::find_program_address(&["Bridge".as_ref()], program); - let signature_set = Pubkey::new_unique(); - let message = Pubkey::new_unique(); + + let signatures = SignatureSet::<'_, { AccountState::Uninitialized }>::key( + &SignaturesSetDerivationData { + hash: body_hash, + }, + &program, + ); + + let message = Message::<'_, { AccountState::MaybeInitialized }>::key( + &MessageDerivationData { + emitter_key: emitter.pubkey().to_bytes(), + emitter_chain: 1, + nonce: 0, + payload: message, + }, + &program, + ); + + println!("PostVAA: Derived Key:"); + println!("GuardianSet: {}", guardian_set); + println!("Signatures: {}", signatures); let signers = vec![payer]; let instructions = [instructions::create_post_vaa( @@ -232,7 +268,7 @@ mod helpers { payer.pubkey(), guardian_set, bridge, - signature_set, + signatures, message, vaa, )]; @@ -241,7 +277,7 @@ mod helpers { let recent_blockhash = client.get_recent_blockhash().unwrap().0; transaction.sign(&signers, recent_blockhash); - client.send_and_confirm_transaction(&transaction).unwrap(); + rpc_send(client, transaction); } } diff --git a/solana/bridge/program/tests/integration.rs b/solana/bridge/program/tests/integration.rs index 2f9c2ab0..401824a3 100644 --- a/solana/bridge/program/tests/integration.rs +++ b/solana/bridge/program/tests/integration.rs @@ -53,6 +53,7 @@ use bridge::{ types::{ BridgeConfig, PostedMessage, + PostedMessageData, SequenceTracker, SignatureSet, }, @@ -94,7 +95,7 @@ fn test_bridge_messages() { // Guardians sign, verify, and we produce VAA data here. let (vaa, body, body_hash, secret_key) = guardian_sign_round( &emitter, - data, + data.clone(), ); common::verify_signatures( @@ -112,12 +113,14 @@ fn test_bridge_messages() { client, program, payer, + body_hash, + data, + &emitter, GuardianSetDerivationData { index: 0 }, vaa, ); - // // Verify a Signature - // common::verify_signature(client, program, payer); + // Did it actually work? } /// A utility function for emulating what the guardians should be doing, I.E, detecting a message @@ -172,8 +175,6 @@ fn guardian_sign_round( h.finalize().into() }; - println!("Ahs: {:?}", body_hash); - // Sign the body hash of the VAA. let sig = secp256k1::sign( &Message::parse(&body_hash), @@ -193,7 +194,7 @@ fn guardian_sign_round( } fn create_message(data: Vec) -> PostedMessage { - PostedMessage { + PostedMessage(PostedMessageData { vaa_version: 0, vaa_time: 0, vaa_signature_account: Pubkey::new_unique(), @@ -207,5 +208,5 @@ fn create_message(data: Vec) -> PostedMessage { .duration_since(SystemTime::UNIX_EPOCH) .unwrap() .as_secs() as u32, - } + }) } diff --git a/solana/solitaire/program/src/macros.rs b/solana/solitaire/program/src/macros.rs index b06efaf2..5e44c758 100644 --- a/solana/solitaire/program/src/macros.rs +++ b/solana/solitaire/program/src/macros.rs @@ -19,8 +19,9 @@ macro_rules! solitaire { use solana_program::{ account_info::AccountInfo, entrypoint::ProgramResult, - program_error::ProgramError, + program_error::ProgramError, pubkey::Pubkey, + msg, }; use solitaire::{FromAccounts, Persist, Result}; @@ -39,6 +40,7 @@ macro_rules! solitaire { match Instruction::try_from_slice(d).map_err(|e| SolitaireError::InstructionDeserializeFailed(e))? { $( Instruction::$row(ix_data) => { + msg!("Dispatch: {}", stringify!($row)); let (mut accounts): ($row) = FromAccounts::from(p, &mut a.iter(), &())?; $fn(&ExecutionContext{program_id: p, accounts: a}, &mut accounts, ix_data)?; Persist::persist(&accounts, p)?; diff --git a/solana/solitaire/program/src/processors/peel.rs b/solana/solitaire/program/src/processors/peel.rs index 6c3d51c3..84e27a01 100644 --- a/solana/solitaire/program/src/processors/peel.rs +++ b/solana/solitaire/program/src/processors/peel.rs @@ -158,7 +158,7 @@ impl< } AccountState::Initialized => { initialized = true; - T::try_from_slice(&mut *ctx.info().data.borrow_mut())? + T::try_from_slice(&mut *ctx.info().data.borrow_mut()).expect("Blew up in Initialized") } AccountState::MaybeInitialized => { if **ctx.info().lamports.borrow() == 0 { diff --git a/solana/solitaire/program/src/types/accounts.rs b/solana/solitaire/program/src/types/accounts.rs index 1a2a411f..037cb12b 100644 --- a/solana/solitaire/program/src/types/accounts.rs +++ b/solana/solitaire/program/src/types/accounts.rs @@ -45,7 +45,7 @@ pub enum AccountState { /// /// Data<(), { AccountState::Uninitialized }> #[rustfmt::skip] -pub struct Data<'r, T: Owned + Default + Default, const IsInitialized: AccountState> ( +pub struct Data<'r, T: Owned + Default, const IsInitialized: AccountState> ( pub Info<'r>, pub T, );