Fix Derivation issues for PostVAA accounts.

Change-Id: Ia08003dc8aadfe3963598c81745813e6e09e5d3a
This commit is contained in:
Reisen 2021-06-23 10:46:21 +00:00 committed by Hendrik Hofstadt
parent a28540de0d
commit 16f7e156ae
10 changed files with 69 additions and 46 deletions

View File

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

View File

@ -1,7 +1,5 @@
use solitaire::*;
use solana_program::{self,};
use crate::types::{
self,
GovernancePayloadSetMessageFee,

View File

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

View File

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

View File

@ -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<W: Write>(&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<Self> {
*buf = &buf[3..];
Ok(PostedMessage(
<PostedMessageData as BorshDeserialize>::deserialize(&mut &buf[3..])?,
<PostedMessageData as BorshDeserialize>::deserialize(buf)?,
))
}
}

View File

@ -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::<Pubkey>()
.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<u8>,
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);
}
}

View File

@ -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<u8>) -> 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<u8>) -> PostedMessage {
.duration_since(SystemTime::UNIX_EPOCH)
.unwrap()
.as_secs() as u32,
}
})
}

View File

@ -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)?;

View File

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

View File

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