use sequence as seed for persisted VAAs from foreign chains

Without the additional seed, messages with identical (emitter_chain, emitter_address, nonce, payload) but different sequence could fail to be persisted.

Change-Id: I6786f7be33bcc6da7289f54fc62c7a5b10821594
This commit is contained in:
Hendrik Hofstadt 2021-07-02 18:51:06 +02:00
parent b85cbacd3b
commit 049177db37
7 changed files with 43 additions and 25 deletions

View File

@ -74,6 +74,8 @@ pub struct MessageDerivationData {
pub emitter_chain: u16,
pub nonce: u32,
pub payload: Vec<u8>,
// This field is only used when a VAA from a foreign chain is posted
pub sequence: Option<u64>,
}
impl<'b, const State: AccountState> Seeded<&MessageDerivationData> for Message<'b, { State }> {
@ -83,6 +85,9 @@ impl<'b, const State: AccountState> Seeded<&MessageDerivationData> for Message<'
data.emitter_chain.to_be_bytes().to_vec(),
data.nonce.to_be_bytes().to_vec(),
];
if let Some(seq) = data.sequence {
seeds.push(seq.to_be_bytes().to_vec())
}
seeds.append(&mut data.payload.chunks(32).map(|v| v.to_vec()).collect());
seeds
}

View File

@ -11,6 +11,7 @@ use crate::{
InsufficientFees,
MathOverflow,
},
CHAIN_ID_SOLANA,
};
use solana_program::{
pubkey::Pubkey,
@ -80,9 +81,10 @@ pub fn post_message(
let msg_derivation = MessageDerivationData {
emitter_key: accs.emitter.key.to_bytes(),
emitter_chain: 1,
emitter_chain: CHAIN_ID_SOLANA,
nonce: data.nonce,
payload: data.payload.clone(),
sequence: None,
};
trace!("Verifying Message: {}, {}", accs.emitter.key, data.nonce);
@ -118,7 +120,7 @@ pub fn post_message(
// Initialize transfer
trace!("Setting Message Details");
accs.message.submission_time = accs.clock.unix_timestamp as u32;
accs.message.emitter_chain = 1;
accs.message.emitter_chain = CHAIN_ID_SOLANA;
accs.message.emitter_address = accs.emitter.key.to_bytes();
accs.message.nonce = data.nonce;
accs.message.payload = data.payload;

View File

@ -21,6 +21,7 @@ use crate::{
},
Error,
Error::GuardianSetMismatch,
CHAIN_ID_SOLANA,
};
use byteorder::{
BigEndian,
@ -111,12 +112,16 @@ pub struct PostVAAData {
}
pub fn post_vaa(ctx: &ExecutionContext, accs: &mut PostVAA, vaa: PostVAAData) -> Result<()> {
let msg_derivation = MessageDerivationData {
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)?;
@ -153,7 +158,7 @@ pub fn post_vaa(ctx: &ExecutionContext, accs: &mut PostVAA, vaa: PostVAAData) ->
}
// If the VAA originates from another chain we need to create the account and populate all fields
if vaa.emitter_chain != 1 {
if vaa.emitter_chain != CHAIN_ID_SOLANA {
accs.message.nonce = vaa.nonce;
accs.message.emitter_chain = vaa.emitter_chain;
accs.message.emitter_address = vaa.emitter_address;

View File

@ -28,21 +28,16 @@ use crate::{
SignatureSet,
SignatureSetDerivationData,
},
types::{
GovernancePayloadUpgrade,
PostedMessage,
},
InitializeData,
PayloadMessage,
PostMessageData,
PostVAAData,
SetFees,
SetFeesData,
TransferFees,
TransferFeesData,
UpgradeContractData,
UpgradeGuardianSetData,
VerifySignaturesData,
CHAIN_ID_SOLANA,
};
pub fn initialize(
@ -96,8 +91,9 @@ pub fn post_message(
let message = Message::<'_, { AccountState::MaybeInitialized }>::key(
&MessageDerivationData {
emitter_key: emitter.to_bytes(),
emitter_chain: 1,
emitter_chain: CHAIN_ID_SOLANA,
nonce,
sequence: None,
payload: payload.clone(),
},
&program_id,
@ -179,15 +175,19 @@ pub fn post_vaa(program_id: Pubkey, payer: Pubkey, vaa: PostVAAData) -> Instruct
&program_id,
);
let message = Message::<'_, { AccountState::MaybeInitialized }>::key(
&MessageDerivationData {
emitter_key: vaa.emitter_address,
emitter_chain: vaa.emitter_chain,
nonce: vaa.nonce,
payload: vaa.payload.clone(),
},
&program_id,
);
let mut msg_derivation_data = MessageDerivationData {
emitter_key: vaa.emitter_address,
emitter_chain: vaa.emitter_chain,
nonce: vaa.nonce,
sequence: None,
payload: vaa.payload.clone(),
};
if vaa.emitter_chain != CHAIN_ID_SOLANA {
msg_derivation_data.sequence = Some(vaa.sequence);
}
let message =
Message::<'_, { AccountState::MaybeInitialized }>::key(&msg_derivation_data, &program_id);
Instruction {
program_id,
@ -218,7 +218,7 @@ pub fn upgrade_contract(
let claim = Claim::<'_, { AccountState::Uninitialized }>::key(
&ClaimDerivationData {
emitter_address: [0u8; 32],
emitter_chain: 1,
emitter_chain: CHAIN_ID_SOLANA,
sequence: 0,
},
&program_id,
@ -256,7 +256,7 @@ pub fn upgrade_guardian_set(
let claim = Claim::<'_, { AccountState::Uninitialized }>::key(
&ClaimDerivationData {
emitter_address: emitter.to_bytes(),
emitter_chain: 1,
emitter_chain: CHAIN_ID_SOLANA,
sequence: 1,
},
&program_id,
@ -297,7 +297,7 @@ pub fn set_fees(program_id: Pubkey, payer: Pubkey, fee: u32) -> Instruction {
let claim = Claim::<'_, { AccountState::Uninitialized }>::key(
&ClaimDerivationData {
emitter_address: [0u8; 32],
emitter_chain: 1,
emitter_chain: CHAIN_ID_SOLANA,
sequence: 0,
},
&program_id,
@ -326,7 +326,7 @@ pub fn transfer_fees(program_id: Pubkey, payer: Pubkey, recipient: Pubkey) -> In
let claim = Claim::<'_, { AccountState::Uninitialized }>::key(
&ClaimDerivationData {
emitter_address: [0u8; 32],
emitter_chain: 1,
emitter_chain: CHAIN_ID_SOLANA,
sequence: 0,
},
&program_id,

View File

@ -51,6 +51,8 @@ pub use vaa::{
const MAX_LEN_GUARDIAN_KEYS: usize = 19;
const CHAIN_ID_SOLANA: u16 = 1;
#[derive(Debug)]
enum Error {
GuardianSetMismatch,

View File

@ -11,6 +11,7 @@ use crate::{
VAAAlreadyExecuted,
},
Result,
CHAIN_ID_SOLANA,
};
use byteorder::{
BigEndian,
@ -69,7 +70,7 @@ pub trait DeserializeGovernancePayload {
}
let chain = c.read_u16::<BigEndian>()?;
if chain != 1 && chain != 0 {
if chain != CHAIN_ID_SOLANA && chain != 0 {
return Err(InvalidGovernanceChain.into());
}

View File

@ -327,6 +327,7 @@ pub fn transfer_native(
emitter_chain: 1,
nonce: data.nonce,
payload: payload.try_to_vec().unwrap(),
sequence: None,
},
&bridge_id,
);
@ -412,6 +413,7 @@ pub fn transfer_wrapped(
emitter_chain: 1,
nonce: data.nonce,
payload: payload.try_to_vec().unwrap(),
sequence: None,
},
&bridge_id,
);
@ -476,6 +478,7 @@ pub fn attest(
emitter_key: emitter_key.to_bytes(),
emitter_chain: 1,
nonce,
sequence: None,
payload: payload.try_to_vec().unwrap(),
},
&bridge_id,