Fix Derivation issues for PostVAA accounts.
Change-Id: Ia08003dc8aadfe3963598c81745813e6e09e5d3a
This commit is contained in:
parent
a28540de0d
commit
16f7e156ae
|
@ -85,7 +85,6 @@ impl<'b, const State: AccountState> Seeded<&MessageDerivationData> for Message<'
|
||||||
data.nonce.to_be_bytes().to_vec(),
|
data.nonce.to_be_bytes().to_vec(),
|
||||||
];
|
];
|
||||||
seeds.append(&mut data.payload.chunks(32).map(|v| v.to_vec()).collect());
|
seeds.append(&mut data.payload.chunks(32).map(|v| v.to_vec()).collect());
|
||||||
|
|
||||||
seeds
|
seeds
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
use solitaire::*;
|
use solitaire::*;
|
||||||
|
|
||||||
use solana_program::{self,};
|
|
||||||
|
|
||||||
use crate::types::{
|
use crate::types::{
|
||||||
self,
|
self,
|
||||||
GovernancePayloadSetMessageFee,
|
GovernancePayloadSetMessageFee,
|
||||||
|
|
|
@ -114,7 +114,6 @@ pub struct PostVAAData {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn post_vaa(ctx: &ExecutionContext, accs: &mut PostVAA, vaa: PostVAAData) -> Result<()> {
|
pub fn post_vaa(ctx: &ExecutionContext, accs: &mut PostVAA, vaa: PostVAAData) -> Result<()> {
|
||||||
msg!("Post VAA Entered");
|
|
||||||
let msg_derivation = MessageDerivationData {
|
let msg_derivation = MessageDerivationData {
|
||||||
emitter_key: vaa.emitter_address,
|
emitter_key: vaa.emitter_address,
|
||||||
emitter_chain: vaa.emitter_chain,
|
emitter_chain: vaa.emitter_chain,
|
||||||
|
@ -135,11 +134,7 @@ pub fn post_vaa(ctx: &ExecutionContext, accs: &mut PostVAA, vaa: PostVAAData) ->
|
||||||
.signature_set
|
.signature_set
|
||||||
.signatures
|
.signatures
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|v|
|
.filter(|v| v.iter().filter(|v| **v != 0).count() != 0)
|
||||||
v.0.iter().filter(|v| **v != 0).count() != 0 ||
|
|
||||||
v.1.iter().filter(|v| **v != 0).count() != 0 ||
|
|
||||||
v.2 != 0
|
|
||||||
)
|
|
||||||
.count();
|
.count();
|
||||||
|
|
||||||
// Calculate how many signatures are required to reach consensus. This calculation is in
|
// Calculate how many signatures are required to reach consensus. This calculation is in
|
||||||
|
|
|
@ -200,6 +200,7 @@ pub fn verify_signatures(
|
||||||
// Track whether the account needs initialization
|
// Track whether the account needs initialization
|
||||||
// Prepare message/payload-specific sig_info account
|
// Prepare message/payload-specific sig_info account
|
||||||
if !accs.signature_set.is_initialized() {
|
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.guardian_set_index = accs.guardian_set.index;
|
||||||
accs.signature_set.hash = data.hash;
|
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
|
// Overwritten content should be zeros except double signs by the signer or harmless replays
|
||||||
accs.signature_set.signatures[s.signer_index as usize].0
|
accs.signature_set.signatures[s.signer_index as usize]
|
||||||
.copy_from_slice(&secp_ixs[s.sig_index as usize].signature[0..32]);
|
.copy_from_slice(&secp_ixs[s.sig_index as usize].signature);
|
||||||
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];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -73,6 +73,7 @@ pub struct BridgeConfig {
|
||||||
/// guarantees that VAAs issued by that set can still be submitted for a certain period. In
|
/// 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.
|
/// this period we still trust the old guardian set.
|
||||||
pub guardian_set_expiration_time: u32,
|
pub guardian_set_expiration_time: u32,
|
||||||
|
|
||||||
/// Amount of lamports that needs to be paid to the protocol to post a message
|
/// Amount of lamports that needs to be paid to the protocol to post a message
|
||||||
pub fee: u64,
|
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)]
|
#[derive(Default, BorshSerialize, BorshDeserialize)]
|
||||||
pub struct SignatureSet {
|
pub struct SignatureSet {
|
||||||
/// Signatures of validators
|
/// Signatures of validators
|
||||||
pub signatures: [SplitSignature; 19],
|
pub signatures: Vec<[u8; 65]>,
|
||||||
|
|
||||||
/// Hash of the data
|
/// Hash of the data
|
||||||
pub hash: [u8; 32],
|
pub hash: [u8; 32],
|
||||||
|
@ -126,6 +119,7 @@ pub struct PostedMessage(pub PostedMessageData);
|
||||||
|
|
||||||
impl BorshSerialize for PostedMessage {
|
impl BorshSerialize for PostedMessage {
|
||||||
fn serialize<W: Write>(&self, writer: &mut W) -> std::io::Result<()> {
|
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]);
|
writer.write(&['m' as u8, 's' as u8, 'g' as u8]);
|
||||||
BorshSerialize::serialize(&self.0, writer)
|
BorshSerialize::serialize(&self.0, writer)
|
||||||
}
|
}
|
||||||
|
@ -133,8 +127,9 @@ impl BorshSerialize for PostedMessage {
|
||||||
|
|
||||||
impl BorshDeserialize for PostedMessage {
|
impl BorshDeserialize for PostedMessage {
|
||||||
fn deserialize(buf: &mut &[u8]) -> std::io::Result<Self> {
|
fn deserialize(buf: &mut &[u8]) -> std::io::Result<Self> {
|
||||||
|
*buf = &buf[3..];
|
||||||
Ok(PostedMessage(
|
Ok(PostedMessage(
|
||||||
<PostedMessageData as BorshDeserialize>::deserialize(&mut &buf[3..])?,
|
<PostedMessageData as BorshDeserialize>::deserialize(buf)?,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
use secp256k1::SecretKey;
|
use secp256k1::SecretKey;
|
||||||
use borsh::BorshSerialize;
|
use borsh::BorshSerialize;
|
||||||
use solana_client::rpc_client::RpcClient;
|
use solana_client::rpc_client::RpcClient;
|
||||||
|
use solana_client::rpc_config::RpcSendTransactionConfig;
|
||||||
use solana_program::{
|
use solana_program::{
|
||||||
borsh::try_from_slice_unchecked,
|
borsh::try_from_slice_unchecked,
|
||||||
hash,
|
hash,
|
||||||
|
@ -29,6 +30,7 @@ use std::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
|
commitment_config::CommitmentConfig,
|
||||||
secp256k1_instruction::new_secp256k1_instruction,
|
secp256k1_instruction::new_secp256k1_instruction,
|
||||||
signature::{
|
signature::{
|
||||||
read_keypair_file,
|
read_keypair_file,
|
||||||
|
@ -44,6 +46,7 @@ use bridge::{
|
||||||
GuardianSetDerivationData,
|
GuardianSetDerivationData,
|
||||||
SignatureSet,
|
SignatureSet,
|
||||||
SignaturesSetDerivationData,
|
SignaturesSetDerivationData,
|
||||||
|
Message,
|
||||||
MessageDerivationData,
|
MessageDerivationData,
|
||||||
},
|
},
|
||||||
instruction,
|
instruction,
|
||||||
|
@ -68,6 +71,18 @@ pub use instructions::*;
|
||||||
mod helpers {
|
mod helpers {
|
||||||
use super::*;
|
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) {
|
pub fn setup() -> (Keypair, RpcClient, Pubkey) {
|
||||||
let payer = read_keypair_file(env::var("BRIDGE_PAYER").unwrap_or("./payer.json".to_string())).unwrap();
|
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()));
|
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())
|
.unwrap_or("6mFKdAtUBVbsQ5dgvBrUkn1Pixb7BMTUtVKj4dpwrmQs".to_string())
|
||||||
.parse::<Pubkey>()
|
.parse::<Pubkey>()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
(payer, rpc, program)
|
(payer, rpc, program)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,7 +99,7 @@ mod helpers {
|
||||||
let mut transaction = Transaction::new_with_payer(&instructions, Some(&from.pubkey()));
|
let mut transaction = Transaction::new_with_payer(&instructions, Some(&from.pubkey()));
|
||||||
let recent_blockhash = client.get_recent_blockhash().unwrap().0;
|
let recent_blockhash = client.get_recent_blockhash().unwrap().0;
|
||||||
transaction.sign(&signers, recent_blockhash);
|
transaction.sign(&signers, recent_blockhash);
|
||||||
client.send_and_confirm_transaction(&transaction).unwrap();
|
rpc_send(client, transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn initialize(
|
pub fn initialize(
|
||||||
|
@ -112,7 +126,7 @@ mod helpers {
|
||||||
let recent_blockhash = client.get_recent_blockhash().unwrap().0;
|
let recent_blockhash = client.get_recent_blockhash().unwrap().0;
|
||||||
|
|
||||||
transaction.sign(&signers, recent_blockhash);
|
transaction.sign(&signers, recent_blockhash);
|
||||||
client.send_and_confirm_transaction(&transaction).unwrap();
|
rpc_send(client, transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn post_message(
|
pub fn post_message(
|
||||||
|
@ -132,7 +146,7 @@ mod helpers {
|
||||||
emitter_key: emitter.pubkey().to_bytes(),
|
emitter_key: emitter.pubkey().to_bytes(),
|
||||||
emitter_chain: message.emitter_chain,
|
emitter_chain: message.emitter_chain,
|
||||||
nonce: message.nonce,
|
nonce: message.nonce,
|
||||||
payload: message.payload,
|
payload: message.payload.clone(),
|
||||||
}, program);
|
}, program);
|
||||||
|
|
||||||
println!("PostMessage: Derived Keys:");
|
println!("PostMessage: Derived Keys:");
|
||||||
|
@ -160,7 +174,7 @@ mod helpers {
|
||||||
let recent_blockhash = client.get_recent_blockhash().unwrap().0;
|
let recent_blockhash = client.get_recent_blockhash().unwrap().0;
|
||||||
|
|
||||||
transaction.sign(&signers, recent_blockhash);
|
transaction.sign(&signers, recent_blockhash);
|
||||||
client.send_and_confirm_transaction(&transaction).unwrap();
|
rpc_send(client, transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn verify_signatures(
|
pub fn verify_signatures(
|
||||||
|
@ -208,23 +222,45 @@ mod helpers {
|
||||||
let recent_blockhash = client.get_recent_blockhash().unwrap().0;
|
let recent_blockhash = client.get_recent_blockhash().unwrap().0;
|
||||||
|
|
||||||
transaction.sign(&signers, recent_blockhash);
|
transaction.sign(&signers, recent_blockhash);
|
||||||
client.send_and_confirm_transaction(&transaction).unwrap();
|
rpc_send(client, transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn post_vaa(
|
pub fn post_vaa(
|
||||||
client: &RpcClient,
|
client: &RpcClient,
|
||||||
program: &Pubkey,
|
program: &Pubkey,
|
||||||
payer: &Keypair,
|
payer: &Keypair,
|
||||||
|
body_hash: [u8; 32],
|
||||||
|
message: Vec<u8>,
|
||||||
|
emitter: &Keypair,
|
||||||
guardian_set: GuardianSetDerivationData,
|
guardian_set: GuardianSetDerivationData,
|
||||||
vaa: PostVAAData,
|
vaa: PostVAAData,
|
||||||
) {
|
) {
|
||||||
|
let (bridge, _) = Pubkey::find_program_address(&["Bridge".as_ref()], program);
|
||||||
let guardian_set = GuardianSet::<'_, { AccountState::Uninitialized }>::key(
|
let guardian_set = GuardianSet::<'_, { AccountState::Uninitialized }>::key(
|
||||||
&guardian_set,
|
&guardian_set,
|
||||||
&program,
|
&program,
|
||||||
);
|
);
|
||||||
let (bridge, _) = Pubkey::find_program_address(&["Bridge".as_ref()], program);
|
|
||||||
let signature_set = Pubkey::new_unique();
|
let signatures = SignatureSet::<'_, { AccountState::Uninitialized }>::key(
|
||||||
let message = Pubkey::new_unique();
|
&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 signers = vec![payer];
|
||||||
let instructions = [instructions::create_post_vaa(
|
let instructions = [instructions::create_post_vaa(
|
||||||
|
@ -232,7 +268,7 @@ mod helpers {
|
||||||
payer.pubkey(),
|
payer.pubkey(),
|
||||||
guardian_set,
|
guardian_set,
|
||||||
bridge,
|
bridge,
|
||||||
signature_set,
|
signatures,
|
||||||
message,
|
message,
|
||||||
vaa,
|
vaa,
|
||||||
)];
|
)];
|
||||||
|
@ -241,7 +277,7 @@ mod helpers {
|
||||||
let recent_blockhash = client.get_recent_blockhash().unwrap().0;
|
let recent_blockhash = client.get_recent_blockhash().unwrap().0;
|
||||||
|
|
||||||
transaction.sign(&signers, recent_blockhash);
|
transaction.sign(&signers, recent_blockhash);
|
||||||
client.send_and_confirm_transaction(&transaction).unwrap();
|
rpc_send(client, transaction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -53,6 +53,7 @@ use bridge::{
|
||||||
types::{
|
types::{
|
||||||
BridgeConfig,
|
BridgeConfig,
|
||||||
PostedMessage,
|
PostedMessage,
|
||||||
|
PostedMessageData,
|
||||||
SequenceTracker,
|
SequenceTracker,
|
||||||
SignatureSet,
|
SignatureSet,
|
||||||
},
|
},
|
||||||
|
@ -94,7 +95,7 @@ fn test_bridge_messages() {
|
||||||
// Guardians sign, verify, and we produce VAA data here.
|
// Guardians sign, verify, and we produce VAA data here.
|
||||||
let (vaa, body, body_hash, secret_key) = guardian_sign_round(
|
let (vaa, body, body_hash, secret_key) = guardian_sign_round(
|
||||||
&emitter,
|
&emitter,
|
||||||
data,
|
data.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
common::verify_signatures(
|
common::verify_signatures(
|
||||||
|
@ -112,12 +113,14 @@ fn test_bridge_messages() {
|
||||||
client,
|
client,
|
||||||
program,
|
program,
|
||||||
payer,
|
payer,
|
||||||
|
body_hash,
|
||||||
|
data,
|
||||||
|
&emitter,
|
||||||
GuardianSetDerivationData { index: 0 },
|
GuardianSetDerivationData { index: 0 },
|
||||||
vaa,
|
vaa,
|
||||||
);
|
);
|
||||||
|
|
||||||
// // Verify a Signature
|
// Did it actually work?
|
||||||
// common::verify_signature(client, program, payer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A utility function for emulating what the guardians should be doing, I.E, detecting a message
|
/// 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()
|
h.finalize().into()
|
||||||
};
|
};
|
||||||
|
|
||||||
println!("Ahs: {:?}", body_hash);
|
|
||||||
|
|
||||||
// Sign the body hash of the VAA.
|
// Sign the body hash of the VAA.
|
||||||
let sig = secp256k1::sign(
|
let sig = secp256k1::sign(
|
||||||
&Message::parse(&body_hash),
|
&Message::parse(&body_hash),
|
||||||
|
@ -193,7 +194,7 @@ fn guardian_sign_round(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_message(data: Vec<u8>) -> PostedMessage {
|
fn create_message(data: Vec<u8>) -> PostedMessage {
|
||||||
PostedMessage {
|
PostedMessage(PostedMessageData {
|
||||||
vaa_version: 0,
|
vaa_version: 0,
|
||||||
vaa_time: 0,
|
vaa_time: 0,
|
||||||
vaa_signature_account: Pubkey::new_unique(),
|
vaa_signature_account: Pubkey::new_unique(),
|
||||||
|
@ -207,5 +208,5 @@ fn create_message(data: Vec<u8>) -> PostedMessage {
|
||||||
.duration_since(SystemTime::UNIX_EPOCH)
|
.duration_since(SystemTime::UNIX_EPOCH)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.as_secs() as u32,
|
.as_secs() as u32,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,8 +19,9 @@ macro_rules! solitaire {
|
||||||
use solana_program::{
|
use solana_program::{
|
||||||
account_info::AccountInfo,
|
account_info::AccountInfo,
|
||||||
entrypoint::ProgramResult,
|
entrypoint::ProgramResult,
|
||||||
program_error::ProgramError,
|
program_error::ProgramError,
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
|
msg,
|
||||||
};
|
};
|
||||||
use solitaire::{FromAccounts, Persist, Result};
|
use solitaire::{FromAccounts, Persist, Result};
|
||||||
|
|
||||||
|
@ -39,6 +40,7 @@ macro_rules! solitaire {
|
||||||
match Instruction::try_from_slice(d).map_err(|e| SolitaireError::InstructionDeserializeFailed(e))? {
|
match Instruction::try_from_slice(d).map_err(|e| SolitaireError::InstructionDeserializeFailed(e))? {
|
||||||
$(
|
$(
|
||||||
Instruction::$row(ix_data) => {
|
Instruction::$row(ix_data) => {
|
||||||
|
msg!("Dispatch: {}", stringify!($row));
|
||||||
let (mut accounts): ($row) = FromAccounts::from(p, &mut a.iter(), &())?;
|
let (mut accounts): ($row) = FromAccounts::from(p, &mut a.iter(), &())?;
|
||||||
$fn(&ExecutionContext{program_id: p, accounts: a}, &mut accounts, ix_data)?;
|
$fn(&ExecutionContext{program_id: p, accounts: a}, &mut accounts, ix_data)?;
|
||||||
Persist::persist(&accounts, p)?;
|
Persist::persist(&accounts, p)?;
|
||||||
|
|
|
@ -158,7 +158,7 @@ impl<
|
||||||
}
|
}
|
||||||
AccountState::Initialized => {
|
AccountState::Initialized => {
|
||||||
initialized = true;
|
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 => {
|
AccountState::MaybeInitialized => {
|
||||||
if **ctx.info().lamports.borrow() == 0 {
|
if **ctx.info().lamports.borrow() == 0 {
|
||||||
|
|
|
@ -45,7 +45,7 @@ pub enum AccountState {
|
||||||
///
|
///
|
||||||
/// Data<(), { AccountState::Uninitialized }>
|
/// Data<(), { AccountState::Uninitialized }>
|
||||||
#[rustfmt::skip]
|
#[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 Info<'r>,
|
||||||
pub T,
|
pub T,
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in New Issue