Allow account reuse for message posting (#1077)
* Implement message posting with account reuse Change-Id: I195f493f6816048f5f8f76e1f0f6e561fa0fe692 * Use different magic for unreliable messages * guardiand: Ignore solana instructions with empty data Co-authored-by: Csongor Kiss <ckiss@jumptrading.com>
This commit is contained in:
parent
c3e7b33388
commit
f1dba4adfe
|
@ -87,8 +87,9 @@ func (c ConsistencyLevel) Commitment() (rpc.CommitmentType, error) {
|
|||
}
|
||||
|
||||
const (
|
||||
postMessageInstructionNumAccounts = 9
|
||||
postMessageInstructionID = 0x01
|
||||
postMessageInstructionNumAccounts = 9
|
||||
postMessageInstructionID = 0x01
|
||||
postMessageUnreliableInstructionID = 0x08
|
||||
)
|
||||
|
||||
// PostMessageData represents the user-supplied, untrusted instruction data
|
||||
|
@ -387,7 +388,11 @@ func (s *SolanaWatcher) processInstruction(ctx context.Context, logger *zap.Logg
|
|||
return false, nil
|
||||
}
|
||||
|
||||
if inst.Data[0] != postMessageInstructionID {
|
||||
if len(inst.Data) == 0 {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
if inst.Data[0] != postMessageInstructionID && inst.Data[0] != postMessageUnreliableInstructionID {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -7,11 +7,13 @@ pub mod posted_vaa;
|
|||
pub mod sequence;
|
||||
pub mod signature_set;
|
||||
|
||||
pub use self::bridge::*;
|
||||
pub use self::claim::*;
|
||||
pub use self::fee_collector::*;
|
||||
pub use self::guardian_set::*;
|
||||
pub use self::posted_message::*;
|
||||
pub use self::posted_vaa::*;
|
||||
pub use self::sequence::*;
|
||||
pub use self::signature_set::*;
|
||||
pub use self::{
|
||||
bridge::*,
|
||||
claim::*,
|
||||
fee_collector::*,
|
||||
guardian_set::*,
|
||||
posted_message::*,
|
||||
posted_vaa::*,
|
||||
sequence::*,
|
||||
signature_set::*,
|
||||
};
|
||||
|
|
|
@ -14,7 +14,11 @@ use solitaire::{
|
|||
Owned,
|
||||
};
|
||||
use std::{
|
||||
io::Write,
|
||||
io::{
|
||||
Error,
|
||||
ErrorKind::InvalidData,
|
||||
Write,
|
||||
},
|
||||
ops::{
|
||||
Deref,
|
||||
DerefMut,
|
||||
|
@ -23,11 +27,20 @@ use std::{
|
|||
|
||||
pub type PostedMessage<'a, const State: AccountState> = Data<'a, PostedMessageData, { State }>;
|
||||
|
||||
// This is using the same payload as the PostedVAA for backwards compatibility.
|
||||
// This will be deprecated in a future release.
|
||||
#[repr(transparent)]
|
||||
#[derive(Default)]
|
||||
pub struct PostedMessageData(pub MessageData);
|
||||
pub struct PostedMessageData {
|
||||
pub message: MessageData,
|
||||
}
|
||||
|
||||
pub type PostedMessageUnreliable<'a, const State: AccountState> =
|
||||
Data<'a, PostedMessageUnreliableData, { State }>;
|
||||
|
||||
#[repr(transparent)]
|
||||
#[derive(Default)]
|
||||
pub struct PostedMessageUnreliableData {
|
||||
pub message: MessageData,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, BorshSerialize, BorshDeserialize, Clone, Serialize, Deserialize)]
|
||||
pub struct MessageData {
|
||||
|
@ -62,19 +75,36 @@ pub struct MessageData {
|
|||
pub payload: Vec<u8>,
|
||||
}
|
||||
|
||||
// PostedMessageData impls
|
||||
|
||||
impl BorshSerialize for PostedMessageData {
|
||||
fn serialize<W: Write>(&self, writer: &mut W) -> std::io::Result<()> {
|
||||
writer.write_all(b"msg")?;
|
||||
BorshSerialize::serialize(&self.0, writer)
|
||||
BorshSerialize::serialize(&self.message, writer)
|
||||
}
|
||||
}
|
||||
|
||||
impl BorshDeserialize for PostedMessageData {
|
||||
fn deserialize(buf: &mut &[u8]) -> std::io::Result<Self> {
|
||||
if buf.len() < 3 {
|
||||
return Err(Error::new(InvalidData, "Not enough bytes"))
|
||||
}
|
||||
|
||||
let expected = b"msg";
|
||||
let magic: &[u8] = &buf[0..3];
|
||||
if magic != expected {
|
||||
return Err(Error::new(
|
||||
InvalidData,
|
||||
format!(
|
||||
"Magic mismatch. Expected {:?} but got {:?}",
|
||||
expected, magic
|
||||
),
|
||||
));
|
||||
};
|
||||
*buf = &buf[3..];
|
||||
Ok(PostedMessageData(
|
||||
<MessageData as BorshDeserialize>::deserialize(buf)?,
|
||||
))
|
||||
Ok(PostedMessageData {
|
||||
message: <MessageData as BorshDeserialize>::deserialize(buf)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -82,19 +112,21 @@ impl Deref for PostedMessageData {
|
|||
type Target = MessageData;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
unsafe { std::mem::transmute(&self.0) }
|
||||
&self.message
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for PostedMessageData {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
unsafe { std::mem::transmute(&mut self.0) }
|
||||
&mut self.message
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for PostedMessageData {
|
||||
fn clone(&self) -> Self {
|
||||
PostedMessageData(self.0.clone())
|
||||
PostedMessageData {
|
||||
message: self.message.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -112,3 +144,73 @@ impl Owned for PostedMessageData {
|
|||
AccountOwner::Other(Pubkey::from_str(env!("BRIDGE_ADDRESS")).unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
// PostedMessageUnreliableData impls
|
||||
|
||||
impl BorshSerialize for PostedMessageUnreliableData {
|
||||
fn serialize<W: Write>(&self, writer: &mut W) -> std::io::Result<()> {
|
||||
writer.write_all(b"msu")?;
|
||||
BorshSerialize::serialize(&self.message, writer)
|
||||
}
|
||||
}
|
||||
|
||||
impl BorshDeserialize for PostedMessageUnreliableData {
|
||||
fn deserialize(buf: &mut &[u8]) -> std::io::Result<Self> {
|
||||
if buf.len() < 3 {
|
||||
return Err(Error::new(InvalidData, "Not enough bytes"))
|
||||
}
|
||||
|
||||
let expected = b"msu";
|
||||
let magic: &[u8] = &buf[0..3];
|
||||
if magic != expected {
|
||||
return Err(Error::new(
|
||||
InvalidData,
|
||||
format!(
|
||||
"Magic mismatch. Expected {:?} but got {:?}",
|
||||
expected, magic
|
||||
),
|
||||
));
|
||||
};
|
||||
*buf = &buf[3..];
|
||||
Ok(PostedMessageUnreliableData {
|
||||
message: <MessageData as BorshDeserialize>::deserialize(buf)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for PostedMessageUnreliableData {
|
||||
type Target = MessageData;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.message
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for PostedMessageUnreliableData {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.message
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for PostedMessageUnreliableData {
|
||||
fn clone(&self) -> Self {
|
||||
PostedMessageUnreliableData {
|
||||
message: self.message.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "cpi"))]
|
||||
impl Owned for PostedMessageUnreliableData {
|
||||
fn owner(&self) -> AccountOwner {
|
||||
AccountOwner::This
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "cpi")]
|
||||
impl Owned for PostedMessageUnreliableData {
|
||||
fn owner(&self) -> AccountOwner {
|
||||
use std::str::FromStr;
|
||||
AccountOwner::Other(Pubkey::from_str(env!("BRIDGE_ADDRESS")).unwrap())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,11 @@ use solitaire::{
|
|||
Owned,
|
||||
};
|
||||
use std::{
|
||||
io::Write,
|
||||
io::{
|
||||
Error,
|
||||
ErrorKind::InvalidData,
|
||||
Write,
|
||||
},
|
||||
ops::{
|
||||
Deref,
|
||||
DerefMut,
|
||||
|
@ -26,27 +30,39 @@ pub struct PostedVAADerivationData {
|
|||
|
||||
impl<'a, const State: AccountState> Seeded<&PostedVAADerivationData> for PostedVAA<'a, { State }> {
|
||||
fn seeds(data: &PostedVAADerivationData) -> Vec<Vec<u8>> {
|
||||
vec!["PostedVAA".as_bytes().to_vec(), data.payload_hash.to_vec()]
|
||||
vec![b"PostedVAA".to_vec(), data.payload_hash.to_vec()]
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(transparent)]
|
||||
#[derive(Default)]
|
||||
pub struct PostedVAAData(pub MessageData);
|
||||
pub struct PostedVAAData {
|
||||
pub message: MessageData,
|
||||
}
|
||||
|
||||
impl BorshSerialize for PostedVAAData {
|
||||
fn serialize<W: Write>(&self, writer: &mut W) -> std::io::Result<()> {
|
||||
writer.write_all(b"vaa")?;
|
||||
BorshSerialize::serialize(&self.0, writer)
|
||||
BorshSerialize::serialize(&self.message, writer)
|
||||
}
|
||||
}
|
||||
|
||||
impl BorshDeserialize for PostedVAAData {
|
||||
fn deserialize(buf: &mut &[u8]) -> std::io::Result<Self> {
|
||||
if buf.len() < 3 {
|
||||
return Err(Error::new(InvalidData, "Not enough bytes"));
|
||||
}
|
||||
|
||||
// We accept "vaa", "msg", or "msu" because it's convenient to read all of these as PostedVAAData
|
||||
let expected: [&[u8]; 3] = [b"vaa", b"msg", b"msu"];
|
||||
let magic: &[u8] = &buf[0..3];
|
||||
if !expected.contains(&magic) {
|
||||
return Err(Error::new(InvalidData, "Magic mismatch."));
|
||||
};
|
||||
*buf = &buf[3..];
|
||||
Ok(PostedVAAData(
|
||||
<MessageData as BorshDeserialize>::deserialize(buf)?,
|
||||
))
|
||||
Ok(PostedVAAData {
|
||||
message: <MessageData as BorshDeserialize>::deserialize(buf)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,19 +70,21 @@ impl Deref for PostedVAAData {
|
|||
type Target = MessageData;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
unsafe { std::mem::transmute(&self.0) }
|
||||
&self.message
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for PostedVAAData {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
unsafe { std::mem::transmute(&mut self.0) }
|
||||
&mut self.message
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for PostedVAAData {
|
||||
fn clone(&self) -> Self {
|
||||
PostedVAAData(self.0.clone())
|
||||
PostedVAAData {
|
||||
message: self.message.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
#[cfg(not(feature = "cpi"))]
|
||||
|
@ -79,8 +97,8 @@ impl Owned for PostedVAAData {
|
|||
#[cfg(feature = "cpi")]
|
||||
impl Owned for PostedVAAData {
|
||||
fn owner(&self) -> AccountOwner {
|
||||
use std::str::FromStr;
|
||||
use solana_program::pubkey::Pubkey;
|
||||
use std::str::FromStr;
|
||||
AccountOwner::Other(Pubkey::from_str(env!("BRIDGE_ADDRESS")).unwrap())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,19 +3,24 @@ use crate::{
|
|||
Bridge,
|
||||
FeeCollector,
|
||||
PostedMessage,
|
||||
PostedMessageUnreliable,
|
||||
Sequence,
|
||||
SequenceDerivationData,
|
||||
},
|
||||
error::Error::{
|
||||
EmitterChanged,
|
||||
InsufficientFees,
|
||||
InvalidPayloadLength,
|
||||
MathOverflow,
|
||||
},
|
||||
types::ConsistencyLevel,
|
||||
IsSigned::*,
|
||||
MessageData,
|
||||
CHAIN_ID_SOLANA,
|
||||
};
|
||||
use solana_program::{
|
||||
msg,
|
||||
pubkey::Pubkey,
|
||||
sysvar::clock::Clock,
|
||||
};
|
||||
use solitaire::{
|
||||
|
@ -27,14 +32,6 @@ use solitaire::{
|
|||
|
||||
pub type UninitializedMessage<'b> = PostedMessage<'b, { AccountState::Uninitialized }>;
|
||||
|
||||
impl<'a> From<&PostMessage<'a>> for SequenceDerivationData<'a> {
|
||||
fn from(accs: &PostMessage<'a>) -> Self {
|
||||
SequenceDerivationData {
|
||||
emitter_key: accs.emitter.key,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(FromAccounts)]
|
||||
pub struct PostMessage<'b> {
|
||||
/// Bridge config needed for fee calculation.
|
||||
|
@ -58,6 +55,29 @@ pub struct PostMessage<'b> {
|
|||
pub clock: Sysvar<'b, Clock>,
|
||||
}
|
||||
|
||||
#[derive(FromAccounts)]
|
||||
pub struct PostMessageUnreliable<'b> {
|
||||
/// Bridge config needed for fee calculation.
|
||||
pub bridge: Mut<Bridge<'b, { AccountState::Initialized }>>,
|
||||
|
||||
/// Account to store the posted message
|
||||
pub message: Signer<Mut<PostedMessageUnreliable<'b, { AccountState::MaybeInitialized }>>>,
|
||||
|
||||
/// Emitter of the VAA
|
||||
pub emitter: Signer<MaybeMut<Info<'b>>>,
|
||||
|
||||
/// Tracker for the emitter sequence
|
||||
pub sequence: Mut<Sequence<'b>>,
|
||||
|
||||
/// Payer for account creation
|
||||
pub payer: Mut<Signer<Info<'b>>>,
|
||||
|
||||
/// Account to collect tx fee
|
||||
pub fee_collector: Mut<FeeCollector<'b>>,
|
||||
|
||||
pub clock: Sysvar<'b, Clock>,
|
||||
}
|
||||
|
||||
#[derive(BorshDeserialize, BorshSerialize)]
|
||||
pub struct PostMessageData {
|
||||
/// Unique nonce for this message
|
||||
|
@ -75,55 +95,18 @@ pub fn post_message(
|
|||
accs: &mut PostMessage,
|
||||
data: PostMessageData,
|
||||
) -> Result<()> {
|
||||
trace!("Message Address: {}", accs.message.info().key);
|
||||
trace!("Emitter Address: {}", accs.emitter.info().key);
|
||||
trace!("Nonce: {}", data.nonce);
|
||||
|
||||
accs.sequence
|
||||
.verify_derivation(ctx.program_id, &(&*accs).into())?;
|
||||
|
||||
let fee = accs.bridge.config.fee;
|
||||
// Fee handling, checking previously known balance allows us to not care who is the payer of
|
||||
// this submission.
|
||||
if accs
|
||||
.fee_collector
|
||||
.lamports()
|
||||
.checked_sub(accs.bridge.last_lamports)
|
||||
.ok_or(MathOverflow)?
|
||||
< fee
|
||||
{
|
||||
trace!(
|
||||
"Expected fee not found: fee, last_lamports, collector: {} {} {}",
|
||||
fee,
|
||||
accs.bridge.last_lamports,
|
||||
accs.fee_collector.lamports(),
|
||||
);
|
||||
return Err(InsufficientFees.into());
|
||||
}
|
||||
accs.bridge.last_lamports = accs.fee_collector.lamports();
|
||||
|
||||
// Init sequence tracker if it does not exist yet.
|
||||
if !accs.sequence.is_initialized() {
|
||||
trace!("Initializing Sequence account to 0.");
|
||||
accs.sequence
|
||||
.create(&(&*accs).into(), ctx, accs.payer.key, Exempt)?;
|
||||
}
|
||||
|
||||
// DO NOT REMOVE - CRITICAL OUTPUT
|
||||
msg!("Sequence: {}", accs.sequence.sequence);
|
||||
|
||||
// Initialize transfer
|
||||
trace!("Setting Message Details");
|
||||
accs.message.submission_time = accs.clock.unix_timestamp as u32;
|
||||
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;
|
||||
accs.message.sequence = accs.sequence.sequence;
|
||||
accs.message.consistency_level = match data.consistency_level {
|
||||
ConsistencyLevel::Confirmed => 1,
|
||||
ConsistencyLevel::Finalized => 32,
|
||||
};
|
||||
post_message_internal(
|
||||
ctx,
|
||||
&mut accs.bridge,
|
||||
accs.message.info().key,
|
||||
&mut accs.message,
|
||||
&mut accs.emitter,
|
||||
&mut accs.sequence,
|
||||
&mut accs.payer,
|
||||
&mut accs.fee_collector,
|
||||
&mut accs.clock,
|
||||
data,
|
||||
)?;
|
||||
|
||||
// Create message account
|
||||
let size = accs.message.size();
|
||||
|
@ -137,9 +120,126 @@ pub fn post_message(
|
|||
NotSigned,
|
||||
)?;
|
||||
|
||||
// Bump sequence number
|
||||
trace!("New Sequence: {}", accs.sequence.sequence + 1);
|
||||
accs.sequence.sequence += 1;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Post a message while reusing the message account. This saves the rent that would be required for
|
||||
/// allocating a new message account. When an account is reused and the guardians don't pick up the
|
||||
/// message due to network instability or a bug there is NO way to recover the message if it has
|
||||
/// been overwritten. This makes this instruction useful for use-cases that require high number of
|
||||
/// messages to be published but don't require 100% delivery guarantee.
|
||||
/// DO NOT USE THIS FOR USE-CASES THAT MOVE VALUE; MESSAGES MAY NOT BE DELIVERED
|
||||
pub fn post_message_unreliable(
|
||||
ctx: &ExecutionContext,
|
||||
accs: &mut PostMessageUnreliable,
|
||||
data: PostMessageData,
|
||||
) -> Result<()> {
|
||||
// Accounts can't be resized so the payload sizes need to match
|
||||
if accs.message.is_initialized() && accs.message.payload.len() != data.payload.len() {
|
||||
return Err(InvalidPayloadLength.into());
|
||||
}
|
||||
// The emitter must be identical
|
||||
if accs.message.is_initialized() && accs.emitter.key.to_bytes() != accs.message.emitter_address
|
||||
{
|
||||
return Err(EmitterChanged.into());
|
||||
}
|
||||
|
||||
post_message_internal(
|
||||
ctx,
|
||||
&mut accs.bridge,
|
||||
accs.message.info().key,
|
||||
&mut accs.message,
|
||||
&mut accs.emitter,
|
||||
&mut accs.sequence,
|
||||
&mut accs.payer,
|
||||
&mut accs.fee_collector,
|
||||
&mut accs.clock,
|
||||
data,
|
||||
)?;
|
||||
|
||||
if !accs.message.is_initialized() {
|
||||
// Create message account
|
||||
let size = accs.message.size();
|
||||
create_account(
|
||||
ctx,
|
||||
accs.message.info(),
|
||||
accs.payer.key,
|
||||
Exempt,
|
||||
size,
|
||||
ctx.program_id,
|
||||
NotSigned,
|
||||
)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[allow(unused_variables)] // message_key is used in `trace!`
|
||||
fn post_message_internal<'b>(
|
||||
ctx: &ExecutionContext,
|
||||
bridge: &mut Mut<Bridge<'b, { AccountState::Initialized }>>,
|
||||
message_key: &Pubkey,
|
||||
message: &mut MessageData,
|
||||
emitter: &mut Signer<MaybeMut<Info<'b>>>,
|
||||
sequence: &mut Mut<Sequence<'b>>,
|
||||
payer: &mut Mut<Signer<Info<'b>>>,
|
||||
fee_collector: &mut Mut<FeeCollector<'b>>,
|
||||
clock: &mut Sysvar<'b, Clock>,
|
||||
data: PostMessageData,
|
||||
) -> Result<()> {
|
||||
trace!("Message Address: {}", message_key);
|
||||
trace!("Emitter Address: {}", emitter.info().key);
|
||||
trace!("Nonce: {}", data.nonce);
|
||||
|
||||
let sequence_derivation = SequenceDerivationData {
|
||||
emitter_key: emitter.key,
|
||||
};
|
||||
sequence.verify_derivation(ctx.program_id, &sequence_derivation)?;
|
||||
|
||||
let fee = bridge.config.fee;
|
||||
// Fee handling, checking previously known balance allows us to not care who is the payer of
|
||||
// this submission.
|
||||
if fee_collector
|
||||
.lamports()
|
||||
.checked_sub(bridge.last_lamports)
|
||||
.ok_or(MathOverflow)?
|
||||
< fee
|
||||
{
|
||||
trace!(
|
||||
"Expected fee not found: fee, last_lamports, collector: {} {} {}",
|
||||
fee,
|
||||
bridge.last_lamports,
|
||||
fee_collector.lamports(),
|
||||
);
|
||||
return Err(InsufficientFees.into());
|
||||
}
|
||||
bridge.last_lamports = fee_collector.lamports();
|
||||
|
||||
// Init sequence tracker if it does not exist yet.
|
||||
if !sequence.is_initialized() {
|
||||
trace!("Initializing Sequence account to 0.");
|
||||
sequence.create(&sequence_derivation, ctx, payer.key, Exempt)?;
|
||||
}
|
||||
|
||||
// DO NOT REMOVE - CRITICAL OUTPUT
|
||||
msg!("Sequence: {}", sequence.sequence);
|
||||
|
||||
// Initialize transfer
|
||||
trace!("Setting Message Details");
|
||||
message.submission_time = clock.unix_timestamp as u32;
|
||||
message.emitter_chain = CHAIN_ID_SOLANA;
|
||||
message.emitter_address = emitter.key.to_bytes();
|
||||
message.nonce = data.nonce;
|
||||
message.payload = data.payload;
|
||||
message.sequence = sequence.sequence;
|
||||
message.consistency_level = match data.consistency_level {
|
||||
ConsistencyLevel::Confirmed => 1,
|
||||
ConsistencyLevel::Finalized => 32,
|
||||
};
|
||||
|
||||
// Bump sequence number
|
||||
trace!("New Sequence: {}", sequence.sequence + 1);
|
||||
sequence.sequence += 1;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -24,6 +24,8 @@ pub enum Error {
|
|||
TooManyGuardians,
|
||||
VAAAlreadyExecuted,
|
||||
VAAInvalid,
|
||||
InvalidPayloadLength,
|
||||
EmitterChanged,
|
||||
}
|
||||
|
||||
/// Errors thrown by the program will bubble up to the solitaire wrapper, which needs a way to
|
||||
|
|
|
@ -104,7 +104,6 @@ pub fn post_message(
|
|||
|
||||
Ok(Instruction {
|
||||
program_id,
|
||||
|
||||
accounts: vec![
|
||||
AccountMeta::new(bridge, false),
|
||||
AccountMeta::new(message, true),
|
||||
|
@ -116,7 +115,6 @@ pub fn post_message(
|
|||
AccountMeta::new_readonly(sysvar::rent::id(), false),
|
||||
AccountMeta::new_readonly(solana_program::system_program::id(), false),
|
||||
],
|
||||
|
||||
data: (
|
||||
crate::instruction::Instruction::PostMessage,
|
||||
PostMessageData {
|
||||
|
@ -129,6 +127,49 @@ pub fn post_message(
|
|||
})
|
||||
}
|
||||
|
||||
pub fn post_message_unreliable(
|
||||
program_id: Pubkey,
|
||||
payer: Pubkey,
|
||||
emitter: Pubkey,
|
||||
message: Pubkey,
|
||||
nonce: u32,
|
||||
payload: Vec<u8>,
|
||||
commitment: ConsistencyLevel,
|
||||
) -> solitaire::Result<Instruction> {
|
||||
let bridge = Bridge::<'_, { AccountState::Uninitialized }>::key(None, &program_id);
|
||||
let fee_collector = FeeCollector::<'_>::key(None, &program_id);
|
||||
let sequence = Sequence::<'_>::key(
|
||||
&SequenceDerivationData {
|
||||
emitter_key: &emitter,
|
||||
},
|
||||
&program_id,
|
||||
);
|
||||
|
||||
Ok(Instruction {
|
||||
program_id,
|
||||
accounts: vec![
|
||||
AccountMeta::new(bridge, false),
|
||||
AccountMeta::new(message, true),
|
||||
AccountMeta::new_readonly(emitter, true),
|
||||
AccountMeta::new(sequence, false),
|
||||
AccountMeta::new(payer, true),
|
||||
AccountMeta::new(fee_collector, false),
|
||||
AccountMeta::new_readonly(sysvar::clock::id(), false),
|
||||
AccountMeta::new_readonly(sysvar::rent::id(), false),
|
||||
AccountMeta::new_readonly(solana_program::system_program::id(), false),
|
||||
],
|
||||
data: (
|
||||
crate::instruction::Instruction::PostMessageUnreliable,
|
||||
PostMessageData {
|
||||
nonce,
|
||||
payload,
|
||||
consistency_level: commitment,
|
||||
},
|
||||
)
|
||||
.try_to_vec()?,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn verify_signatures(
|
||||
program_id: Pubkey,
|
||||
payer: Pubkey,
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#![feature(adt_const_params)]
|
||||
#![allow(non_upper_case_globals)]
|
||||
#![allow(incomplete_features)]
|
||||
|
@ -20,32 +19,37 @@ extern crate wasm_bindgen;
|
|||
pub mod wasm;
|
||||
|
||||
pub mod accounts;
|
||||
|
||||
pub use accounts::{
|
||||
BridgeConfig,
|
||||
BridgeData,
|
||||
Claim,
|
||||
ClaimData,
|
||||
ClaimDerivationData,
|
||||
ClaimDerivationData,
|
||||
FeeCollector,
|
||||
GuardianSet,
|
||||
GuardianSetData,
|
||||
GuardianSetDerivationData,
|
||||
MessageData,
|
||||
PostedMessage,
|
||||
PostedMessageData,
|
||||
MessageData,
|
||||
PostedMessageUnreliable,
|
||||
PostedMessageUnreliableData,
|
||||
PostedVAA,
|
||||
PostedVAAData,
|
||||
Sequence,
|
||||
SequenceTracker,
|
||||
SequenceDerivationData,
|
||||
SequenceTracker,
|
||||
SignatureSet,
|
||||
SignatureSetData,
|
||||
};
|
||||
|
||||
pub mod api;
|
||||
|
||||
pub use api::{
|
||||
initialize,
|
||||
post_message,
|
||||
post_message_unreliable,
|
||||
post_vaa,
|
||||
set_fees,
|
||||
transfer_fees,
|
||||
|
@ -56,6 +60,7 @@ pub use api::{
|
|||
InitializeData,
|
||||
PostMessage,
|
||||
PostMessageData,
|
||||
PostMessageUnreliable,
|
||||
PostVAA,
|
||||
PostVAAData,
|
||||
SetFees,
|
||||
|
@ -93,4 +98,5 @@ solitaire! {
|
|||
UpgradeContract => upgrade_contract,
|
||||
UpgradeGuardianSet => upgrade_guardian_set,
|
||||
VerifySignatures => verify_signatures,
|
||||
PostMessageUnreliable => post_message_unreliable,
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ use crate::{
|
|||
instructions::{
|
||||
hash_vaa,
|
||||
post_message,
|
||||
post_message_unreliable,
|
||||
post_vaa,
|
||||
set_fees,
|
||||
transfer_fees,
|
||||
|
@ -82,6 +83,34 @@ pub fn post_message_ix(
|
|||
return JsValue::from_serde(&ix).unwrap();
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn post_message_unreliable_ix(
|
||||
program_id: String,
|
||||
payer: String,
|
||||
emitter: String,
|
||||
message: String,
|
||||
nonce: u32,
|
||||
msg: Vec<u8>,
|
||||
consistency: String,
|
||||
) -> JsValue {
|
||||
let consistency_level = match consistency.as_str() {
|
||||
"CONFIRMED" => ConsistencyLevel::Confirmed,
|
||||
"FINALIZED" => ConsistencyLevel::Finalized,
|
||||
_ => panic!("invalid consistency level"),
|
||||
};
|
||||
let ix = post_message_unreliable(
|
||||
Pubkey::from_str(program_id.as_str()).unwrap(),
|
||||
Pubkey::from_str(payer.as_str()).unwrap(),
|
||||
Pubkey::from_str(emitter.as_str()).unwrap(),
|
||||
Pubkey::from_str(message.as_str()).unwrap(),
|
||||
nonce,
|
||||
msg,
|
||||
consistency_level,
|
||||
)
|
||||
.unwrap();
|
||||
return JsValue::from_serde(&ix).unwrap();
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn post_vaa_ix(
|
||||
program_id: String,
|
||||
|
@ -363,7 +392,7 @@ pub fn claim_address(program_id: String, vaa: Vec<u8>) -> Vec<u8> {
|
|||
|
||||
#[wasm_bindgen]
|
||||
pub fn parse_posted_message(data: Vec<u8>) -> JsValue {
|
||||
JsValue::from_serde(&PostedVAAData::try_from_slice(data.as_slice()).unwrap().0).unwrap()
|
||||
JsValue::from_serde(&PostedVAAData::try_from_slice(data.as_slice()).unwrap().message).unwrap()
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
|
|
|
@ -116,12 +116,7 @@ mod helpers {
|
|||
|
||||
/// Fetch account balance
|
||||
pub async fn get_account_balance(client: &mut BanksClient, account: Pubkey) -> u64 {
|
||||
client
|
||||
.get_account(account)
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
.lamports
|
||||
client.get_account(account).await.unwrap().unwrap().lamports
|
||||
}
|
||||
|
||||
/// Generate `count` secp256k1 private keys, along with their ethereum-styled public key
|
||||
|
@ -236,6 +231,8 @@ mod helpers {
|
|||
program: &Pubkey,
|
||||
payer: &Keypair,
|
||||
emitter: &Keypair,
|
||||
// when None, then a new keypair is generated
|
||||
message: Option<&Keypair>,
|
||||
nonce: u32,
|
||||
data: Vec<u8>,
|
||||
fee: u64,
|
||||
|
@ -243,7 +240,12 @@ mod helpers {
|
|||
// Transfer money into the fee collector as it needs a balance/must exist.
|
||||
let fee_collector = FeeCollector::<'_>::key(None, program);
|
||||
|
||||
let message = Keypair::new();
|
||||
let new_message_pair = &Keypair::new();
|
||||
|
||||
let message: &Keypair = match message {
|
||||
Some(keypair) => keypair,
|
||||
None => new_message_pair
|
||||
};
|
||||
|
||||
// Capture the resulting message, later functions will need this.
|
||||
let instruction = instructions::post_message(
|
||||
|
@ -272,6 +274,44 @@ mod helpers {
|
|||
Ok(message.pubkey())
|
||||
}
|
||||
|
||||
pub async fn post_message_unreliable(
|
||||
client: &mut BanksClient,
|
||||
program: &Pubkey,
|
||||
payer: &Keypair,
|
||||
emitter: &Keypair,
|
||||
message: &Keypair,
|
||||
nonce: u32,
|
||||
data: Vec<u8>,
|
||||
fee: u64,
|
||||
) -> Result<(), TransportError> {
|
||||
// Transfer money into the fee collector as it needs a balance/must exist.
|
||||
let fee_collector = FeeCollector::<'_>::key(None, program);
|
||||
|
||||
// Capture the resulting message, later functions will need this.
|
||||
let instruction = instructions::post_message_unreliable(
|
||||
*program,
|
||||
payer.pubkey(),
|
||||
emitter.pubkey(),
|
||||
message.pubkey(),
|
||||
nonce,
|
||||
data,
|
||||
ConsistencyLevel::Confirmed,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
execute(
|
||||
client,
|
||||
payer,
|
||||
&[payer, emitter, &message],
|
||||
&[
|
||||
system_instruction::transfer(&payer.pubkey(), &fee_collector, fee),
|
||||
instruction,
|
||||
],
|
||||
CommitmentLevel::Processed,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn verify_signatures(
|
||||
client: &mut BanksClient,
|
||||
program: &Pubkey,
|
||||
|
|
|
@ -145,6 +145,7 @@ async fn bridge_messages() {
|
|||
program,
|
||||
payer,
|
||||
&emitter,
|
||||
None,
|
||||
nonce,
|
||||
message.clone(),
|
||||
10_000,
|
||||
|
@ -153,15 +154,15 @@ async fn bridge_messages() {
|
|||
.unwrap();
|
||||
|
||||
let posted_message: PostedVAAData = common::get_account_data(client, message_key).await;
|
||||
assert_eq!(posted_message.0.vaa_version, 0);
|
||||
assert_eq!(posted_message.0.consistency_level, 1);
|
||||
assert_eq!(posted_message.0.nonce, nonce);
|
||||
assert_eq!(posted_message.0.sequence, sequence);
|
||||
assert_eq!(posted_message.0.emitter_chain, 1);
|
||||
assert_eq!(&posted_message.0.emitter_address, emitter.pubkey().as_ref());
|
||||
assert_eq!(posted_message.0.payload, message);
|
||||
assert_eq!(posted_message.message.vaa_version, 0);
|
||||
assert_eq!(posted_message.message.consistency_level, 1);
|
||||
assert_eq!(posted_message.message.nonce, nonce);
|
||||
assert_eq!(posted_message.message.sequence, sequence);
|
||||
assert_eq!(posted_message.message.emitter_chain, 1);
|
||||
assert_eq!(&posted_message.message.emitter_address, emitter.pubkey().as_ref());
|
||||
assert_eq!(posted_message.message.payload, message);
|
||||
assert_eq!(
|
||||
posted_message.0.emitter_address,
|
||||
posted_message.message.emitter_address,
|
||||
emitter.pubkey().to_bytes()
|
||||
);
|
||||
|
||||
|
@ -192,20 +193,20 @@ async fn bridge_messages() {
|
|||
let signatures: SignatureSetData = common::get_account_data(client, signature_set).await;
|
||||
|
||||
// Verify on chain Message
|
||||
assert_eq!(posted_message.0.vaa_version, 0);
|
||||
assert_eq!(posted_message.message.vaa_version, 0);
|
||||
assert_eq!(
|
||||
posted_message.0.consistency_level,
|
||||
posted_message.message.consistency_level,
|
||||
ConsistencyLevel::Confirmed as u8
|
||||
);
|
||||
assert_eq!(posted_message.0.vaa_time, vaa_time);
|
||||
assert_eq!(posted_message.0.vaa_signature_account, signature_set);
|
||||
assert_eq!(posted_message.0.nonce, nonce);
|
||||
assert_eq!(posted_message.0.sequence, sequence);
|
||||
assert_eq!(posted_message.0.emitter_chain, 1);
|
||||
assert_eq!(&posted_message.0.emitter_address, emitter.pubkey().as_ref());
|
||||
assert_eq!(posted_message.0.payload, message);
|
||||
assert_eq!(posted_message.message.vaa_time, vaa_time);
|
||||
assert_eq!(posted_message.message.vaa_signature_account, signature_set);
|
||||
assert_eq!(posted_message.message.nonce, nonce);
|
||||
assert_eq!(posted_message.message.sequence, sequence);
|
||||
assert_eq!(posted_message.message.emitter_chain, 1);
|
||||
assert_eq!(&posted_message.message.emitter_address, emitter.pubkey().as_ref());
|
||||
assert_eq!(posted_message.message.payload, message);
|
||||
assert_eq!(
|
||||
posted_message.0.emitter_address,
|
||||
posted_message.message.emitter_address,
|
||||
emitter.pubkey().to_bytes()
|
||||
);
|
||||
|
||||
|
@ -229,6 +230,7 @@ async fn bridge_messages() {
|
|||
program,
|
||||
payer,
|
||||
&emitter,
|
||||
None,
|
||||
nonce,
|
||||
message.clone(),
|
||||
10_000,
|
||||
|
@ -237,15 +239,15 @@ async fn bridge_messages() {
|
|||
.unwrap();
|
||||
|
||||
let posted_message: PostedVAAData = common::get_account_data(client, message_key).await;
|
||||
assert_eq!(posted_message.0.vaa_version, 0);
|
||||
assert_eq!(posted_message.0.consistency_level, 1);
|
||||
assert_eq!(posted_message.0.nonce, nonce);
|
||||
assert_eq!(posted_message.0.sequence, sequence);
|
||||
assert_eq!(posted_message.0.emitter_chain, 1);
|
||||
assert_eq!(&posted_message.0.emitter_address, emitter.pubkey().as_ref());
|
||||
assert_eq!(posted_message.0.payload, message);
|
||||
assert_eq!(posted_message.message.vaa_version, 0);
|
||||
assert_eq!(posted_message.message.consistency_level, 1);
|
||||
assert_eq!(posted_message.message.nonce, nonce);
|
||||
assert_eq!(posted_message.message.sequence, sequence);
|
||||
assert_eq!(posted_message.message.emitter_chain, 1);
|
||||
assert_eq!(&posted_message.message.emitter_address, emitter.pubkey().as_ref());
|
||||
assert_eq!(posted_message.message.payload, message);
|
||||
assert_eq!(
|
||||
posted_message.0.emitter_address,
|
||||
posted_message.message.emitter_address,
|
||||
emitter.pubkey().to_bytes()
|
||||
);
|
||||
|
||||
|
@ -274,20 +276,20 @@ async fn bridge_messages() {
|
|||
let signatures: SignatureSetData = common::get_account_data(client, signature_set).await;
|
||||
|
||||
// Verify on chain Message
|
||||
assert_eq!(posted_message.0.vaa_version, 0);
|
||||
assert_eq!(posted_message.message.vaa_version, 0);
|
||||
assert_eq!(
|
||||
posted_message.0.consistency_level,
|
||||
posted_message.message.consistency_level,
|
||||
ConsistencyLevel::Confirmed as u8
|
||||
);
|
||||
assert_eq!(posted_message.0.vaa_time, vaa_time);
|
||||
assert_eq!(posted_message.0.vaa_signature_account, signature_set);
|
||||
assert_eq!(posted_message.0.nonce, nonce);
|
||||
assert_eq!(posted_message.0.sequence, sequence);
|
||||
assert_eq!(posted_message.0.emitter_chain, 1);
|
||||
assert_eq!(&posted_message.0.emitter_address, emitter.pubkey().as_ref());
|
||||
assert_eq!(posted_message.0.payload, message);
|
||||
assert_eq!(posted_message.message.vaa_time, vaa_time);
|
||||
assert_eq!(posted_message.message.vaa_signature_account, signature_set);
|
||||
assert_eq!(posted_message.message.nonce, nonce);
|
||||
assert_eq!(posted_message.message.sequence, sequence);
|
||||
assert_eq!(posted_message.message.emitter_chain, 1);
|
||||
assert_eq!(&posted_message.message.emitter_address, emitter.pubkey().as_ref());
|
||||
assert_eq!(posted_message.message.payload, message);
|
||||
assert_eq!(
|
||||
posted_message.0.emitter_address,
|
||||
posted_message.message.emitter_address,
|
||||
emitter.pubkey().to_bytes()
|
||||
);
|
||||
|
||||
|
@ -300,6 +302,166 @@ async fn bridge_messages() {
|
|||
}
|
||||
}
|
||||
|
||||
// Make sure that posting messages with account reuse works and only accepts messages with the same
|
||||
// length.
|
||||
#[tokio::test]
|
||||
async fn test_bridge_messages_unreliable() {
|
||||
let (ref mut context, ref mut client, ref payer, ref program) = initialize().await;
|
||||
|
||||
// Data/Nonce used for emitting a message we want to prove exists. Run this twice to make sure
|
||||
// that duplicate data does not clash.
|
||||
let emitter = Keypair::new();
|
||||
let message_key = Keypair::new();
|
||||
|
||||
for _ in 0..2 {
|
||||
let nonce = rand::thread_rng().gen();
|
||||
let message: [u8; 32] = rand::thread_rng().gen();
|
||||
let sequence = context.seq.next(emitter.pubkey().to_bytes());
|
||||
|
||||
// Post the message, publishing the data for guardian consumption.
|
||||
common::post_message_unreliable(
|
||||
client,
|
||||
program,
|
||||
payer,
|
||||
&emitter,
|
||||
&message_key,
|
||||
nonce,
|
||||
message.to_vec(),
|
||||
10_000,
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// Verify on chain Message
|
||||
let posted_message: PostedVAAData =
|
||||
common::get_account_data(client, message_key.pubkey()).await;
|
||||
assert_eq!(posted_message.message.vaa_version, 0);
|
||||
assert_eq!(posted_message.message.nonce, nonce);
|
||||
assert_eq!(posted_message.message.sequence, sequence);
|
||||
assert_eq!(posted_message.message.emitter_chain, 1);
|
||||
assert_eq!(posted_message.message.payload, message);
|
||||
assert_eq!(
|
||||
posted_message.message.emitter_address,
|
||||
emitter.pubkey().to_bytes()
|
||||
);
|
||||
|
||||
// Emulate Guardian behaviour, verifying the data and publishing signatures/VAA.
|
||||
let (vaa, body, body_hash) =
|
||||
common::generate_vaa(&emitter, message.to_vec(), nonce, sequence, 0, 1);
|
||||
let signature_set =
|
||||
common::verify_signatures(client, program, payer, body, &context.secret, 0)
|
||||
.await
|
||||
.unwrap();
|
||||
common::post_vaa(client, program, payer, signature_set, vaa)
|
||||
.await
|
||||
.unwrap();
|
||||
let message_key = PostedVAA::<'_, { AccountState::MaybeInitialized }>::key(
|
||||
&PostedVAADerivationData {
|
||||
payload_hash: body.to_vec(),
|
||||
},
|
||||
program,
|
||||
);
|
||||
common::sync(client, payer).await;
|
||||
|
||||
// Fetch chain accounts to verify state.
|
||||
let posted_message: PostedVAAData = common::get_account_data(client, message_key).await;
|
||||
let signatures: SignatureSetData = common::get_account_data(client, signature_set).await;
|
||||
|
||||
// Verify on chain vaa
|
||||
assert_eq!(posted_message.message.vaa_version, 0);
|
||||
assert_eq!(posted_message.message.vaa_signature_account, signature_set);
|
||||
assert_eq!(posted_message.message.nonce, nonce);
|
||||
assert_eq!(posted_message.message.sequence, sequence);
|
||||
assert_eq!(posted_message.message.emitter_chain, 1);
|
||||
assert_eq!(posted_message.message.payload, message);
|
||||
assert_eq!(
|
||||
posted_message.message.emitter_address,
|
||||
emitter.pubkey().to_bytes()
|
||||
);
|
||||
|
||||
// Verify on chain Signatures
|
||||
assert_eq!(signatures.hash, body);
|
||||
assert_eq!(signatures.guardian_set_index, 0);
|
||||
|
||||
for (signature, secret_key) in signatures.signatures.iter().zip(context.secret.iter()) {
|
||||
assert_eq!(*signature, true);
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure that posting a message with a different length fails (<len)
|
||||
let nonce = rand::thread_rng().gen();
|
||||
let message: [u8; 16] = rand::thread_rng().gen();
|
||||
|
||||
assert!(common::post_message_unreliable(
|
||||
client,
|
||||
program,
|
||||
payer,
|
||||
&emitter,
|
||||
&message_key,
|
||||
nonce,
|
||||
message.to_vec(),
|
||||
10_000,
|
||||
)
|
||||
.await
|
||||
.is_err());
|
||||
|
||||
// Make sure that posting a message with a different length fails (>len)
|
||||
let nonce = rand::thread_rng().gen();
|
||||
let message: [u8; 128] = [0u8; 128];
|
||||
|
||||
assert!(common::post_message_unreliable(
|
||||
client,
|
||||
program,
|
||||
payer,
|
||||
&emitter,
|
||||
&message_key,
|
||||
nonce,
|
||||
message.to_vec(),
|
||||
10_000,
|
||||
)
|
||||
.await
|
||||
.is_err());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_bridge_messages_unreliable_do_not_override_reliable() {
|
||||
let (ref mut _context, ref mut client, ref payer, ref program) = initialize().await;
|
||||
|
||||
let emitter = Keypair::new();
|
||||
let message_key = Keypair::new();
|
||||
|
||||
let nonce = rand::thread_rng().gen();
|
||||
let message: [u8; 32] = rand::thread_rng().gen();
|
||||
|
||||
// Post the message using the reliable method
|
||||
common::post_message(
|
||||
client,
|
||||
program,
|
||||
payer,
|
||||
&emitter,
|
||||
Some(&message_key),
|
||||
nonce,
|
||||
message.to_vec(),
|
||||
10_000,
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// Make sure that posting an unreliable message to the same message account fails
|
||||
assert!(common::post_message_unreliable(
|
||||
client,
|
||||
program,
|
||||
payer,
|
||||
&emitter,
|
||||
&message_key,
|
||||
nonce,
|
||||
message.to_vec(),
|
||||
10_000,
|
||||
)
|
||||
.await
|
||||
.is_err());
|
||||
}
|
||||
|
||||
// Make sure that solitaire can claim accounts that already hold lamports so the protocol can't be
|
||||
// DoSd by someone funding derived accounts making CreateAccount fail.
|
||||
#[tokio::test]
|
||||
|
@ -363,13 +525,13 @@ async fn test_bridge_message_prefunded_account() {
|
|||
|
||||
// Verify on chain Message
|
||||
let posted_message: PostedVAAData = common::get_account_data(client, message.pubkey()).await;
|
||||
assert_eq!(posted_message.0.vaa_version, 0);
|
||||
assert_eq!(posted_message.0.nonce, nonce);
|
||||
assert_eq!(posted_message.0.sequence, sequence);
|
||||
assert_eq!(posted_message.0.emitter_chain, 1);
|
||||
assert_eq!(posted_message.0.payload, payload);
|
||||
assert_eq!(posted_message.message.vaa_version, 0);
|
||||
assert_eq!(posted_message.message.nonce, nonce);
|
||||
assert_eq!(posted_message.message.sequence, sequence);
|
||||
assert_eq!(posted_message.message.emitter_chain, 1);
|
||||
assert_eq!(posted_message.message.payload, payload);
|
||||
assert_eq!(
|
||||
posted_message.0.emitter_address,
|
||||
posted_message.message.emitter_address,
|
||||
emitter.pubkey().to_bytes()
|
||||
);
|
||||
}
|
||||
|
@ -448,6 +610,7 @@ async fn guardian_set_change() {
|
|||
program,
|
||||
payer,
|
||||
&emitter,
|
||||
None,
|
||||
nonce,
|
||||
message.clone(),
|
||||
10_000,
|
||||
|
@ -456,15 +619,15 @@ async fn guardian_set_change() {
|
|||
.unwrap();
|
||||
|
||||
let posted_message: PostedVAAData = common::get_account_data(client, message_key).await;
|
||||
assert_eq!(posted_message.0.vaa_version, 0);
|
||||
assert_eq!(posted_message.0.consistency_level, 1);
|
||||
assert_eq!(posted_message.0.nonce, nonce);
|
||||
assert_eq!(posted_message.0.sequence, sequence);
|
||||
assert_eq!(posted_message.0.emitter_chain, 1);
|
||||
assert_eq!(&posted_message.0.emitter_address, emitter.pubkey().as_ref());
|
||||
assert_eq!(posted_message.0.payload, message);
|
||||
assert_eq!(posted_message.message.vaa_version, 0);
|
||||
assert_eq!(posted_message.message.consistency_level, 1);
|
||||
assert_eq!(posted_message.message.nonce, nonce);
|
||||
assert_eq!(posted_message.message.sequence, sequence);
|
||||
assert_eq!(posted_message.message.emitter_chain, 1);
|
||||
assert_eq!(&posted_message.message.emitter_address, emitter.pubkey().as_ref());
|
||||
assert_eq!(posted_message.message.payload, message);
|
||||
assert_eq!(
|
||||
posted_message.0.emitter_address,
|
||||
posted_message.message.emitter_address,
|
||||
emitter.pubkey().to_bytes()
|
||||
);
|
||||
|
||||
|
@ -510,20 +673,20 @@ async fn guardian_set_change() {
|
|||
let guardian_set: GuardianSetData = common::get_account_data(client, guardian_set_key).await;
|
||||
|
||||
// Verify on chain Message
|
||||
assert_eq!(posted_message.0.vaa_version, 0);
|
||||
assert_eq!(posted_message.message.vaa_version, 0);
|
||||
assert_eq!(
|
||||
posted_message.0.consistency_level,
|
||||
posted_message.message.consistency_level,
|
||||
ConsistencyLevel::Confirmed as u8
|
||||
);
|
||||
assert_eq!(posted_message.0.vaa_time, vaa_time);
|
||||
assert_eq!(posted_message.0.vaa_signature_account, signature_set);
|
||||
assert_eq!(posted_message.0.nonce, nonce);
|
||||
assert_eq!(posted_message.0.sequence, sequence);
|
||||
assert_eq!(posted_message.0.emitter_chain, 1);
|
||||
assert_eq!(&posted_message.0.emitter_address, emitter.pubkey().as_ref());
|
||||
assert_eq!(posted_message.0.payload, message);
|
||||
assert_eq!(posted_message.message.vaa_time, vaa_time);
|
||||
assert_eq!(posted_message.message.vaa_signature_account, signature_set);
|
||||
assert_eq!(posted_message.message.nonce, nonce);
|
||||
assert_eq!(posted_message.message.sequence, sequence);
|
||||
assert_eq!(posted_message.message.emitter_chain, 1);
|
||||
assert_eq!(&posted_message.message.emitter_address, emitter.pubkey().as_ref());
|
||||
assert_eq!(posted_message.message.payload, message);
|
||||
assert_eq!(
|
||||
posted_message.0.emitter_address,
|
||||
posted_message.message.emitter_address,
|
||||
emitter.pubkey().to_bytes()
|
||||
);
|
||||
|
||||
|
@ -544,6 +707,7 @@ async fn guardian_set_change() {
|
|||
program,
|
||||
payer,
|
||||
&emitter,
|
||||
None,
|
||||
nonce,
|
||||
message.clone(),
|
||||
10_000,
|
||||
|
@ -577,19 +741,19 @@ async fn guardian_set_change() {
|
|||
let signatures: SignatureSetData = common::get_account_data(client, signature_set).await;
|
||||
|
||||
// Verify on chain Message
|
||||
assert_eq!(posted_message.0.vaa_version, 0);
|
||||
assert_eq!(posted_message.message.vaa_version, 0);
|
||||
assert_eq!(
|
||||
posted_message.0.consistency_level,
|
||||
posted_message.message.consistency_level,
|
||||
ConsistencyLevel::Confirmed as u8
|
||||
);
|
||||
assert_eq!(posted_message.0.vaa_time, vaa_time);
|
||||
assert_eq!(posted_message.0.vaa_signature_account, signature_set);
|
||||
assert_eq!(posted_message.0.nonce, nonce);
|
||||
assert_eq!(posted_message.0.sequence, sequence);
|
||||
assert_eq!(posted_message.0.emitter_chain, 1);
|
||||
assert_eq!(posted_message.0.payload, message);
|
||||
assert_eq!(posted_message.message.vaa_time, vaa_time);
|
||||
assert_eq!(posted_message.message.vaa_signature_account, signature_set);
|
||||
assert_eq!(posted_message.message.nonce, nonce);
|
||||
assert_eq!(posted_message.message.sequence, sequence);
|
||||
assert_eq!(posted_message.message.emitter_chain, 1);
|
||||
assert_eq!(posted_message.message.payload, message);
|
||||
assert_eq!(
|
||||
posted_message.0.emitter_address,
|
||||
posted_message.message.emitter_address,
|
||||
emitter.pubkey().to_bytes()
|
||||
);
|
||||
|
||||
|
@ -626,6 +790,7 @@ async fn guardian_set_change_fails() {
|
|||
program,
|
||||
payer,
|
||||
&emitter,
|
||||
None,
|
||||
nonce,
|
||||
message.clone(),
|
||||
10_000,
|
||||
|
@ -666,6 +831,7 @@ async fn set_fees() {
|
|||
program,
|
||||
payer,
|
||||
&emitter,
|
||||
None,
|
||||
nonce,
|
||||
message.clone(),
|
||||
10_000,
|
||||
|
@ -705,7 +871,7 @@ async fn set_fees() {
|
|||
let nonce = rand::thread_rng().gen();
|
||||
let message = [0u8; 32].to_vec();
|
||||
assert!(
|
||||
common::post_message(client, program, payer, &emitter, nonce, message.clone(), 50)
|
||||
common::post_message(client, program, payer, &emitter, None, nonce, message.clone(), 50)
|
||||
.await
|
||||
.is_err()
|
||||
);
|
||||
|
@ -726,6 +892,7 @@ async fn set_fees() {
|
|||
program,
|
||||
payer,
|
||||
&emitter,
|
||||
None,
|
||||
nonce,
|
||||
message.clone(),
|
||||
100,
|
||||
|
@ -761,20 +928,20 @@ async fn set_fees() {
|
|||
let signatures: SignatureSetData = common::get_account_data(client, signature_set).await;
|
||||
|
||||
// Verify on chain Message
|
||||
assert_eq!(posted_message.0.vaa_version, 0);
|
||||
assert_eq!(posted_message.message.vaa_version, 0);
|
||||
assert_eq!(
|
||||
posted_message.0.consistency_level,
|
||||
posted_message.message.consistency_level,
|
||||
ConsistencyLevel::Confirmed as u8
|
||||
);
|
||||
assert_eq!(posted_message.0.vaa_time, vaa_time);
|
||||
assert_eq!(posted_message.0.vaa_signature_account, signature_set);
|
||||
assert_eq!(posted_message.0.nonce, nonce);
|
||||
assert_eq!(posted_message.0.sequence, sequence);
|
||||
assert_eq!(posted_message.0.emitter_chain, 1);
|
||||
assert_eq!(&posted_message.0.emitter_address, emitter.pubkey().as_ref());
|
||||
assert_eq!(posted_message.0.payload, message);
|
||||
assert_eq!(posted_message.message.vaa_time, vaa_time);
|
||||
assert_eq!(posted_message.message.vaa_signature_account, signature_set);
|
||||
assert_eq!(posted_message.message.nonce, nonce);
|
||||
assert_eq!(posted_message.message.sequence, sequence);
|
||||
assert_eq!(posted_message.message.emitter_chain, 1);
|
||||
assert_eq!(&posted_message.message.emitter_address, emitter.pubkey().as_ref());
|
||||
assert_eq!(posted_message.message.payload, message);
|
||||
assert_eq!(
|
||||
posted_message.0.emitter_address,
|
||||
posted_message.message.emitter_address,
|
||||
emitter.pubkey().to_bytes()
|
||||
);
|
||||
|
||||
|
@ -808,6 +975,7 @@ async fn set_fees_fails() {
|
|||
program,
|
||||
payer,
|
||||
&emitter,
|
||||
None,
|
||||
nonce,
|
||||
message.clone(),
|
||||
10_000,
|
||||
|
@ -856,6 +1024,7 @@ async fn free_fees() {
|
|||
program,
|
||||
payer,
|
||||
&emitter,
|
||||
None,
|
||||
nonce,
|
||||
message.clone(),
|
||||
10_000,
|
||||
|
@ -896,7 +1065,7 @@ async fn free_fees() {
|
|||
let nonce = rand::thread_rng().gen();
|
||||
let message = [0u8; 32].to_vec();
|
||||
let _message_key =
|
||||
common::post_message(client, program, payer, &emitter, nonce, message.clone(), 0)
|
||||
common::post_message(client, program, payer, &emitter, None, nonce, message.clone(), 0)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
|
@ -928,20 +1097,20 @@ async fn free_fees() {
|
|||
let signatures: SignatureSetData = common::get_account_data(client, signature_set).await;
|
||||
|
||||
// Verify on chain Message
|
||||
assert_eq!(posted_message.0.vaa_version, 0);
|
||||
assert_eq!(posted_message.message.vaa_version, 0);
|
||||
assert_eq!(
|
||||
posted_message.0.consistency_level,
|
||||
posted_message.message.consistency_level,
|
||||
ConsistencyLevel::Confirmed as u8
|
||||
);
|
||||
assert_eq!(posted_message.0.vaa_time, vaa_time);
|
||||
assert_eq!(posted_message.0.vaa_signature_account, signature_set);
|
||||
assert_eq!(posted_message.0.nonce, nonce);
|
||||
assert_eq!(posted_message.0.sequence, sequence);
|
||||
assert_eq!(posted_message.0.emitter_chain, 1);
|
||||
assert_eq!(&posted_message.0.emitter_address, emitter.pubkey().as_ref());
|
||||
assert_eq!(posted_message.0.payload, message);
|
||||
assert_eq!(posted_message.message.vaa_time, vaa_time);
|
||||
assert_eq!(posted_message.message.vaa_signature_account, signature_set);
|
||||
assert_eq!(posted_message.message.nonce, nonce);
|
||||
assert_eq!(posted_message.message.sequence, sequence);
|
||||
assert_eq!(posted_message.message.emitter_chain, 1);
|
||||
assert_eq!(&posted_message.message.emitter_address, emitter.pubkey().as_ref());
|
||||
assert_eq!(posted_message.message.payload, message);
|
||||
assert_eq!(
|
||||
posted_message.0.emitter_address,
|
||||
posted_message.message.emitter_address,
|
||||
emitter.pubkey().to_bytes()
|
||||
);
|
||||
|
||||
|
@ -977,6 +1146,7 @@ async fn transfer_fees() {
|
|||
program,
|
||||
payer,
|
||||
&emitter,
|
||||
None,
|
||||
nonce,
|
||||
message.clone(),
|
||||
10_000,
|
||||
|
@ -1038,6 +1208,7 @@ async fn transfer_fees_fails() {
|
|||
program,
|
||||
payer,
|
||||
&emitter,
|
||||
None,
|
||||
nonce,
|
||||
message.clone(),
|
||||
10_000,
|
||||
|
@ -1097,6 +1268,7 @@ async fn transfer_too_much() {
|
|||
program,
|
||||
payer,
|
||||
&emitter,
|
||||
None,
|
||||
nonce,
|
||||
message.clone(),
|
||||
10_000,
|
||||
|
@ -1167,14 +1339,14 @@ async fn foreign_bridge_messages() {
|
|||
let posted_message: PostedVAAData = common::get_account_data(client, message_key).await;
|
||||
let signatures: SignatureSetData = common::get_account_data(client, signature_set).await;
|
||||
|
||||
assert_eq!(posted_message.0.vaa_version, 0);
|
||||
assert_eq!(posted_message.0.vaa_signature_account, signature_set);
|
||||
assert_eq!(posted_message.0.nonce, nonce);
|
||||
assert_eq!(posted_message.0.sequence, sequence);
|
||||
assert_eq!(posted_message.0.emitter_chain, 2);
|
||||
assert_eq!(posted_message.0.payload, message);
|
||||
assert_eq!(posted_message.message.vaa_version, 0);
|
||||
assert_eq!(posted_message.message.vaa_signature_account, signature_set);
|
||||
assert_eq!(posted_message.message.nonce, nonce);
|
||||
assert_eq!(posted_message.message.sequence, sequence);
|
||||
assert_eq!(posted_message.message.emitter_chain, 2);
|
||||
assert_eq!(posted_message.message.payload, message);
|
||||
assert_eq!(
|
||||
posted_message.0.emitter_address,
|
||||
posted_message.message.emitter_address,
|
||||
emitter.pubkey().to_bytes()
|
||||
);
|
||||
|
||||
|
@ -1214,6 +1386,7 @@ async fn transfer_total_fails() {
|
|||
program,
|
||||
payer,
|
||||
&emitter,
|
||||
None,
|
||||
nonce,
|
||||
message.clone(),
|
||||
10_000,
|
||||
|
@ -1278,6 +1451,7 @@ async fn upgrade_contract() {
|
|||
program,
|
||||
payer,
|
||||
&emitter,
|
||||
None,
|
||||
nonce,
|
||||
message.clone(),
|
||||
10_000,
|
||||
|
|
Loading…
Reference in New Issue