add instruction constructors

This commit is contained in:
Hendrik Hofstadt 2020-08-07 16:10:30 +02:00
parent 86dd02e0e6
commit ff0b4766ae
7 changed files with 203 additions and 68 deletions

View File

@ -28,13 +28,11 @@ Parameters:
| ----- | -------- | ------------------- | ------ | --------- | ----- | ------- | | ----- | -------- | ------------------- | ------ | --------- | ----- | ------- |
| 0 | sys | SystemProgram | | | | | | 0 | sys | SystemProgram | | | | |
| 1 | token_program | SplToken | | | | | | 1 | token_program | SplToken | | | | |
| 2 | clock | Sysvar | | | | ✅ | | 2 | token_account | TokenAccount | | ✅ | | |
| 3 | sender | TokenAccount | | ✅ | | | | 3 | bridge | BridgeConfig | | | | |
| 4 | bridge | BridgeConfig | | | | | | 4 | proposal | TransferOutProposal | | ✅ | ✅ | ✅ |
| 5 | proposal | TransferOutProposal | | ✅ | ✅ | ✅ | | 5 | token | WrappedAsset | | ✅ | | ✅ |
| 6 | token | WrappedAsset | | ✅ | | ✅ | | 6 | payer | Account | ✅ | | | |
| 7 | payer | Account | ✅ | | | |
| 8-n | sender_owner | Account | ✅ | | | |
#### TransferOutNative #### TransferOutNative
@ -47,14 +45,12 @@ The transfer proposal will be tracked at a new account `proposal` where a VAA wi
| ----- | --------------- | ------------------- | ------ | --------- | ----- | ------- | | ----- | --------------- | ------------------- | ------ | --------- | ----- | ------- |
| 0 | sys | SystemProgram | | | | | | 0 | sys | SystemProgram | | | | |
| 1 | token_program | SplToken | | | | | | 1 | token_program | SplToken | | | | |
| 2 | clock | Sysvar | | | | ✅ | | 2 | token_account | TokenAccount | | ✅ | | |
| 3 | sender | TokenAccount | | ✅ | | | | 3 | bridge | BridgeConfig | | | | |
| 4 | bridge | BridgeConfig | | | | | | 4 | proposal | TransferOutProposal | | ✅ | ✅ | ✅ |
| 5 | proposal | TransferOutProposal | | ✅ | ✅ | ✅ | | 5 | token | Mint | | ✅ | | |
| 6 | token | Mint | | ✅ | | | | 6 | payer | Account | ✅ | | | |
| 7 | custody_account | TokenAccount | | ✅ | opt | ✅ | | 7 | custody_account | TokenAccount | | ✅ | opt | ✅ |
| 8 | payer | Account | ✅ | | | |
| 9-n | sender_owner | Account | ✅ | | | |
#### EvictTransferOut #### EvictTransferOut
@ -108,9 +104,8 @@ followed by:
| Index | Name | Type | signer | writeable | empty | derived | | Index | Name | Type | signer | writeable | empty | derived |
| ----- | ------------ | ------------ | ------ | --------- | ----- | ------- | | ----- | ------------ | ------------ | ------ | --------- | ----- | ------- |
| 6 | token_program | SplToken | | | | | | 6 | token_program | SplToken | | | | |
| 7 | token | WrappedAsset | | | opt | ✅ | | 7 | token | WrappedAsset | | | opt | ✅ |
| 8 | destination | TokenAccount | | ✅ | opt | | | 8 | destination | TokenAccount | | ✅ | opt | |
| 9 | sender | Account | ✅ | | | |
##### Transfer: Ethereum (wrapped) -> Solana (native) ##### Transfer: Ethereum (wrapped) -> Solana (native)
@ -125,7 +120,6 @@ followed by:
| Index | Name | Type | signer | writeable | empty | derived | | Index | Name | Type | signer | writeable | empty | derived |
| ----- | ------------ | ------------------- | ------ | --------- | ----- | ------- | | ----- | ------------ | ------------------- | ------ | --------- | ----- | ------- |
| 6 | token_program | SplToken | | | | |
| 7 | out_proposal | TransferOutProposal | | ✅ | | ✅ | | 7 | out_proposal | TransferOutProposal | | ✅ | | ✅ |
| 8 | sender | Account | ✅ | | | | | 8 | sender | Account | ✅ | | | |

View File

@ -91,6 +91,9 @@ pub enum Error {
/// Invalid transfer with src=dst /// Invalid transfer with src=dst
#[error("SameChainTransfer")] #[error("SameChainTransfer")]
SameChainTransfer, SameChainTransfer,
/// VAA is longer than the maximum size
#[error("VAATooLong")]
VAATooLong,
} }
impl From<Error> for ProgramError { impl From<Error> for ProgramError {

View File

@ -35,6 +35,7 @@ impl PrintProgramError for Error {
Error::ExpectedTransferOutProposal => info!("Error: ExpectedTransferOutProposal"), Error::ExpectedTransferOutProposal => info!("Error: ExpectedTransferOutProposal"),
Error::VAAProposalMismatch => info!("Error: VAAProposalMismatch"), Error::VAAProposalMismatch => info!("Error: VAAProposalMismatch"),
Error::SameChainTransfer => info!("Error: SameChainTransfer"), Error::SameChainTransfer => info!("Error: SameChainTransfer"),
Error::VAATooLong => info!("Error: VAATooLong"),
} }
} }
} }

View File

@ -10,21 +10,23 @@ use solana_sdk::{
pubkey::Pubkey, pubkey::Pubkey,
}; };
use crate::error::Error::VAATooLong;
use crate::instruction::BridgeInstruction::Initialize; use crate::instruction::BridgeInstruction::Initialize;
use crate::state::{AssetMeta, BridgeConfig}; use crate::state::{AssetMeta, Bridge, BridgeConfig};
use crate::syscalls::RawKey; use crate::syscalls::RawKey;
use crate::vaa::{VAABody, VAA};
/// chain id of this chain /// chain id of this chain
pub const CHAIN_ID_SOLANA: u8 = 1; pub const CHAIN_ID_SOLANA: u8 = 1;
/// size of a VAA in bytes /// size of a VAA in bytes
const VAA_SIZE: usize = 100; const VAA_SIZE: usize = 200;
/// size of a foreign address in bytes /// size of a foreign address in bytes
const FOREIGN_ADDRESS_SIZE: usize = 32; const FOREIGN_ADDRESS_SIZE: usize = 32;
/// validator payment approval /// length-prefixed serialized validator payment approval data
pub type VAA_BODY = [u8; VAA_SIZE]; pub type VAAData = [u8; VAA_SIZE];
/// X and Y point of P for guardians /// X and Y point of P for guardians
pub type GuardianKey = [u8; 64]; pub type GuardianKey = [u8; 64];
/// address on a foreign chain /// address on a foreign chain
@ -50,6 +52,8 @@ pub struct TransferOutPayload {
pub asset: AssetMeta, pub asset: AssetMeta,
/// address on the foreign chain to transfer to /// address on the foreign chain to transfer to
pub target: ForeignAddress, pub target: ForeignAddress,
/// unique nonce of the transfer
pub nonce: u32,
} }
/// Instructions supported by the SwapInfo program. /// Instructions supported by the SwapInfo program.
@ -91,7 +95,7 @@ pub enum BridgeInstruction {
/// Submits a VAA signed by `guardian` on a valid `proposal`. /// Submits a VAA signed by `guardian` on a valid `proposal`.
/// See docs for accounts /// See docs for accounts
PostVAA(VAA_BODY), PostVAA(VAAData),
/// Deletes a `proposal` after the `VAA_EXPIRATION_TIME` is over to free up space on chain. /// Deletes a `proposal` after the `VAA_EXPIRATION_TIME` is over to free up space on chain.
/// This returns the rent to the sender. /// This returns the rent to the sender.
@ -143,7 +147,7 @@ impl BridgeInstruction {
output[0] = 2; output[0] = 2;
#[allow(clippy::cast_ptr_alignment)] #[allow(clippy::cast_ptr_alignment)]
let value = let value =
unsafe { &mut *(&mut output[size_of::<u8>()] as *mut u8 as *mut VAA_BODY) }; unsafe { &mut *(&mut output[size_of::<u8>()] as *mut u8 as *mut VAAData) };
*value = payload; *value = payload;
} }
Self::EvictTransferOut() => { Self::EvictTransferOut() => {
@ -161,7 +165,6 @@ impl BridgeInstruction {
pub fn initialize( pub fn initialize(
program_id: &Pubkey, program_id: &Pubkey,
sender: &Pubkey, sender: &Pubkey,
bridge: &Pubkey,
initial_guardian: RawKey, initial_guardian: RawKey,
config: &BridgeConfig, config: &BridgeConfig,
) -> Result<Instruction, ProgramError> { ) -> Result<Instruction, ProgramError> {
@ -171,9 +174,15 @@ pub fn initialize(
}) })
.serialize()?; .serialize()?;
let bridge_key = Bridge::derive_bridge_id(program_id)?;
let guardian_set_key = Bridge::derive_guardian_set_id(program_id, &bridge_key, 0)?;
let accounts = vec![ let accounts = vec![
AccountMeta::new_readonly(solana_sdk::system_program::id(), false),
AccountMeta::new_readonly(solana_sdk::sysvar::clock::id(), false),
AccountMeta::new(bridge_key, false),
AccountMeta::new(guardian_set_key, false),
AccountMeta::new(*sender, true), AccountMeta::new(*sender, true),
AccountMeta::new(*bridge, false),
]; ];
Ok(Instruction { Ok(Instruction {
@ -183,6 +192,138 @@ pub fn initialize(
}) })
} }
/// Creates an 'TransferOut' instruction.
pub fn transfer_out(
program_id: &Pubkey,
payer: &Pubkey,
token_account: &Pubkey,
token_mint: &Pubkey,
t: &TransferOutPayload,
) -> Result<Instruction, ProgramError> {
let data = BridgeInstruction::TransferOut(*t).serialize()?;
let bridge_key = Bridge::derive_bridge_id(program_id)?;
let transfer_key = Bridge::derive_transfer_id(
program_id,
&bridge_key,
t.asset.chain,
t.asset.address,
t.chain_id,
t.target,
token_account.to_bytes(),
t.nonce,
)?;
let mut accounts = vec![
AccountMeta::new_readonly(solana_sdk::system_program::id(), false),
AccountMeta::new_readonly(spl_token::id(), false),
AccountMeta::new(*token_account, false),
AccountMeta::new(bridge_key, false),
AccountMeta::new(transfer_key, false),
AccountMeta::new(*token_mint, false),
AccountMeta::new(*payer, true),
];
// If the token is a native solana token add a custody account
if t.asset.chain == CHAIN_ID_SOLANA {
let custody_key = Bridge::derive_custody_id(program_id, &bridge_key, token_mint)?;
accounts.push(AccountMeta::new(custody_key, false));
}
Ok(Instruction {
program_id: *program_id,
accounts,
data,
})
}
/// Creates a 'PostVAA' instruction.
pub fn post_vaa(
program_id: &Pubkey,
payer: &Pubkey,
v: &[u8],
) -> Result<Instruction, ProgramError> {
// VAA must be <= VAA_SIZE-1 to allow for the length prefix
if v.len() > VAA_SIZE - 1 {
return Err(VAATooLong.into());
}
// Convert data to length-prefixed on-chain format
let mut vaa_data: Vec<u8> = vec![];
vaa_data.push(v.len() as u8);
vaa_data.append(&mut v.to_vec());
let mut vaa_chain: [u8; 200] = [0; 200];
vaa_chain.copy_from_slice(vaa_data.as_slice());
let data = BridgeInstruction::PostVAA(vaa_chain).serialize()?;
// Parse VAA
let vaa = VAA::deserialize(&v[..])?;
let bridge_key = Bridge::derive_bridge_id(program_id)?;
let guardian_set_key =
Bridge::derive_guardian_set_id(program_id, &bridge_key, vaa.guardian_set_index)?;
let claim_key = Bridge::derive_claim_id(program_id, &bridge_key, &vaa.body_hash()?)?;
let mut accounts = vec![
AccountMeta::new_readonly(solana_sdk::system_program::id(), false),
AccountMeta::new_readonly(solana_sdk::sysvar::clock::id(), false),
AccountMeta::new(bridge_key, false),
AccountMeta::new(guardian_set_key, false),
AccountMeta::new(claim_key, false),
AccountMeta::new(*payer, true),
];
match vaa.payload.unwrap() {
VAABody::UpdateGuardianSet(u) => {
let guardian_set_key =
Bridge::derive_guardian_set_id(program_id, &bridge_key, u.new_index)?;
accounts.push(AccountMeta::new(guardian_set_key, false));
}
VAABody::Transfer(t) => {
if t.source_chain == CHAIN_ID_SOLANA {
// Solana (any) -> Ethereum (any)
let transfer_key = Bridge::derive_transfer_id(
program_id,
&bridge_key,
t.asset.chain,
t.asset.address,
t.target_chain,
t.target_address,
t.source_address,
t.nonce,
)?;
accounts.push(AccountMeta::new(transfer_key, false))
} else if t.asset.chain == CHAIN_ID_SOLANA {
// Foreign (wrapped) -> Solana (native)
let mint_key = Pubkey::new(&t.asset.address);
let custody_key = Bridge::derive_custody_id(program_id, &bridge_key, &mint_key)?;
accounts.push(AccountMeta::new_readonly(spl_token::id(), false));
accounts.push(AccountMeta::new(mint_key, false));
accounts.push(AccountMeta::new(Pubkey::new(&t.target_address), false));
accounts.push(AccountMeta::new(custody_key, false));
} else {
// Foreign (native) -> Solana (wrapped)
let wrapped_key = Bridge::derive_wrapped_asset_id(
program_id,
&bridge_key,
t.asset.chain,
t.asset.address,
)?;
accounts.push(AccountMeta::new_readonly(spl_token::id(), false));
accounts.push(AccountMeta::new(wrapped_key, false));
accounts.push(AccountMeta::new(Pubkey::new(&t.target_address), false));
}
}
}
Ok(Instruction {
program_id: *program_id,
accounts,
data,
})
}
/// Unpacks a reference from a bytes buffer. /// Unpacks a reference from a bytes buffer.
pub fn unpack<T>(input: &[u8]) -> Result<&T, ProgramError> { pub fn unpack<T>(input: &[u8]) -> Result<&T, ProgramError> {
if input.len() < size_of::<u8>() + size_of::<T>() { if input.len() < size_of::<u8>() + size_of::<T>() {

View File

@ -1,13 +1,11 @@
//! Program instruction processing logic //! Program instruction processing logic
#![cfg(feature = "program")] #![cfg(feature = "program")]
use std::io::Write;
use std::mem::size_of; use std::mem::size_of;
use std::slice::Iter; use std::slice::Iter;
use num_traits::AsPrimitive; use num_traits::AsPrimitive;
use primitive_types::U256; use primitive_types::U256;
use sha3::Digest;
use solana_sdk::clock::Clock; use solana_sdk::clock::Clock;
#[cfg(not(target_arch = "bpf"))] #[cfg(not(target_arch = "bpf"))]
use solana_sdk::instruction::Instruction; use solana_sdk::instruction::Instruction;
@ -24,7 +22,7 @@ use spl_token::state::Mint;
use crate::error::Error; use crate::error::Error;
use crate::instruction::BridgeInstruction::*; use crate::instruction::BridgeInstruction::*;
use crate::instruction::{BridgeInstruction, TransferOutPayload, CHAIN_ID_SOLANA}; use crate::instruction::{BridgeInstruction, TransferOutPayload, VAAData, CHAIN_ID_SOLANA};
use crate::state::*; use crate::state::*;
use crate::syscalls::RawKey; use crate::syscalls::RawKey;
use crate::vaa::{BodyTransfer, BodyUpdateGuardianSet, VAABody, VAA}; use crate::vaa::{BodyTransfer, BodyUpdateGuardianSet, VAABody, VAA};
@ -59,13 +57,9 @@ impl Bridge {
let vaa_data = &vaa_body[..len]; let vaa_data = &vaa_body[..len];
let vaa = VAA::deserialize(vaa_data)?; let vaa = VAA::deserialize(vaa_data)?;
let mut k = sha3::Keccak256::default(); let hash = vaa.body_hash()?;
if let Err(_) = k.write(vaa_data) {
return Err(Error::ParseFailed.into());
};
let hash = k.finalize();
Self::process_vaa(program_id, accounts, &vaa_body, &vaa, hash.as_ref()) Self::process_vaa(program_id, accounts, vaa_body, &vaa, &hash)
} }
_ => panic!(""), _ => panic!(""),
} }
@ -88,7 +82,7 @@ impl Bridge {
let clock = Clock::from_account_info(clock_info)?; let clock = Clock::from_account_info(clock_info)?;
// Create bridge account // Create bridge account
let bridge_seed = Bridge::derive_bridge_seeds(program_id); let bridge_seed = Bridge::derive_bridge_seeds();
Bridge::check_and_create_account::<BridgeConfig>( Bridge::check_and_create_account::<BridgeConfig>(
program_id, program_id,
accounts, accounts,
@ -142,7 +136,6 @@ impl Bridge {
let account_info_iter = &mut accounts.iter(); let account_info_iter = &mut accounts.iter();
next_account_info(account_info_iter)?; // System program next_account_info(account_info_iter)?; // System program
next_account_info(account_info_iter)?; // Token program next_account_info(account_info_iter)?; // Token program
let clock_info = next_account_info(account_info_iter)?;
let sender_account_info = next_account_info(account_info_iter)?; let sender_account_info = next_account_info(account_info_iter)?;
let bridge_info = next_account_info(account_info_iter)?; let bridge_info = next_account_info(account_info_iter)?;
let transfer_info = next_account_info(account_info_iter)?; let transfer_info = next_account_info(account_info_iter)?;
@ -150,7 +143,6 @@ impl Bridge {
let payer_info = next_account_info(account_info_iter)?; let payer_info = next_account_info(account_info_iter)?;
let authority_info = next_account_info(account_info_iter)?; let authority_info = next_account_info(account_info_iter)?;
let clock = Clock::from_account_info(clock_info)?;
let sender = Bridge::token_account_deserialize(sender_account_info)?; let sender = Bridge::token_account_deserialize(sender_account_info)?;
let bridge = Bridge::bridge_deserialize(bridge_info)?; let bridge = Bridge::bridge_deserialize(bridge_info)?;
let mint = Bridge::mint_deserialize(mint_info)?; let mint = Bridge::mint_deserialize(mint_info)?;
@ -184,7 +176,7 @@ impl Bridge {
t.chain_id, t.chain_id,
t.target, t.target,
sender.owner.to_bytes(), sender.owner.to_bytes(),
clock.slot.as_(), //TODO use nonce t.nonce,
); );
Bridge::check_and_create_account::<TransferOutProposal>( Bridge::check_and_create_account::<TransferOutProposal>(
program_id, program_id,
@ -229,16 +221,13 @@ impl Bridge {
let account_info_iter = &mut accounts.iter(); let account_info_iter = &mut accounts.iter();
next_account_info(account_info_iter)?; // System program next_account_info(account_info_iter)?; // System program
next_account_info(account_info_iter)?; // Token program next_account_info(account_info_iter)?; // Token program
let clock_info = next_account_info(account_info_iter)?;
let sender_account_info = next_account_info(account_info_iter)?; let sender_account_info = next_account_info(account_info_iter)?;
let bridge_info = next_account_info(account_info_iter)?; let bridge_info = next_account_info(account_info_iter)?;
let transfer_info = next_account_info(account_info_iter)?; let transfer_info = next_account_info(account_info_iter)?;
let mint_info = next_account_info(account_info_iter)?; let mint_info = next_account_info(account_info_iter)?;
let custody_info = next_account_info(account_info_iter)?;
let payer_info = next_account_info(account_info_iter)?; let payer_info = next_account_info(account_info_iter)?;
let sender_info = next_account_info(account_info_iter)?; let custody_info = next_account_info(account_info_iter)?;
let clock = Clock::from_account_info(clock_info)?;
let sender = Bridge::token_account_deserialize(sender_account_info)?; let sender = Bridge::token_account_deserialize(sender_account_info)?;
let bridge = Bridge::bridge_deserialize(bridge_info)?; let bridge = Bridge::bridge_deserialize(bridge_info)?;
let mint = Bridge::mint_deserialize(mint_info)?; let mint = Bridge::mint_deserialize(mint_info)?;
@ -260,8 +249,8 @@ impl Bridge {
t.asset.address, t.asset.address,
t.chain_id, t.chain_id,
t.target, t.target,
sender.owner.to_bytes(), sender_account_info.key.to_bytes(),
clock.slot.as_(), //TODO use nonce t.nonce,
); );
Bridge::check_and_create_account::<TransferOutProposal>( Bridge::check_and_create_account::<TransferOutProposal>(
program_id, program_id,
@ -310,7 +299,7 @@ impl Bridge {
&bridge.config.token_program, &bridge.config.token_program,
sender_account_info.key, sender_account_info.key,
custody_info.key, custody_info.key,
sender_info.key, bridge_info.key,
t.amount, t.amount,
)?; )?;
@ -333,7 +322,7 @@ impl Bridge {
pub fn process_vaa( pub fn process_vaa(
program_id: &Pubkey, program_id: &Pubkey,
accounts: &[AccountInfo], accounts: &[AccountInfo],
vaa_data: &[u8; 100], vaa_data: VAAData,
vaa: &VAA, vaa: &VAA,
hash: &[u8; 32], hash: &[u8; 32],
) -> ProgramResult { ) -> ProgramResult {
@ -508,6 +497,7 @@ impl Bridge {
bridge: &mut Bridge, bridge: &mut Bridge,
b: &BodyTransfer, b: &BodyTransfer,
) -> ProgramResult { ) -> ProgramResult {
next_account_info(account_info_iter)?; // Token program
let mint_info = next_account_info(account_info_iter)?; let mint_info = next_account_info(account_info_iter)?;
let destination_info = next_account_info(account_info_iter)?; let destination_info = next_account_info(account_info_iter)?;
@ -578,7 +568,7 @@ impl Bridge {
bridge_info: &AccountInfo, bridge_info: &AccountInfo,
vaa: &VAA, vaa: &VAA,
b: &BodyTransfer, b: &BodyTransfer,
vaa_data: &[u8; 100], vaa_data: VAAData,
) -> ProgramResult { ) -> ProgramResult {
let proposal_info = next_account_info(account_info_iter)?; let proposal_info = next_account_info(account_info_iter)?;
@ -603,7 +593,7 @@ impl Bridge {
} }
// Set vaa // Set vaa
proposal.vaa = *vaa_data; proposal.vaa = vaa_data;
proposal.vaa_time = vaa.timestamp; proposal.vaa_time = vaa.timestamp;
Ok(()) Ok(())
@ -671,7 +661,7 @@ impl Bridge {
all_signers.as_slice(), all_signers.as_slice(),
amount, amount,
)?; )?;
invoke_signed(&ix, accounts, &[]) invoke_signed(&ix, accounts, &[&["bridge".as_bytes()]])
} }
/// Mint a wrapped asset to account /// Mint a wrapped asset to account
@ -691,7 +681,7 @@ impl Bridge {
&[], &[],
amount, amount,
)?; )?;
invoke_signed(&ix, accounts, &[&[&bridge.to_bytes()[..32]][..]]) invoke_signed(&ix, accounts, &[&["bridge".as_bytes()]])
} }
/// Transfer tokens from a caller /// Transfer tokens from a caller
@ -703,19 +693,15 @@ impl Bridge {
authority: &Pubkey, authority: &Pubkey,
amount: U256, amount: U256,
) -> Result<(), ProgramError> { ) -> Result<(), ProgramError> {
let all_signers: Vec<&Pubkey> = accounts
.iter()
.filter_map(|item| if item.is_signer { Some(item.key) } else { None })
.collect();
let ix = spl_token::instruction::transfer( let ix = spl_token::instruction::transfer(
token_program_id, token_program_id,
source, source,
destination, destination,
authority, authority,
all_signers.as_slice(), &[],
amount, amount,
)?; )?;
invoke_signed(&ix, accounts, &[]) invoke_signed(&ix, accounts, &[&["bridge".as_bytes()]])
} }
/// Transfer tokens from a custody account /// Transfer tokens from a custody account
@ -735,7 +721,7 @@ impl Bridge {
&[], &[],
amount, amount,
)?; )?;
invoke_signed(&ix, accounts, &[&[&bridge.to_bytes()[..32]][..]]) invoke_signed(&ix, accounts, &[&["bridge".as_bytes()]])
} }
/// Create a new account /// Create a new account
@ -756,7 +742,7 @@ impl Bridge {
&Self::derive_custody_seeds(bridge, mint), &Self::derive_custody_seeds(bridge, mint),
)?; )?;
let ix = spl_token::instruction::initialize_account(token_program, account, mint, bridge)?; let ix = spl_token::instruction::initialize_account(token_program, account, mint, bridge)?;
invoke_signed(&ix, accounts, &[&[&bridge.to_bytes()[..32]][..]]) invoke_signed(&ix, accounts, &[&["bridge".as_bytes()]])
} }
/// Create a mint for a wrapped asset /// Create a mint for a wrapped asset
@ -784,7 +770,7 @@ impl Bridge {
U256::from(0), U256::from(0),
8, 8,
)?; )?;
invoke_signed(&ix, accounts, &[&[&bridge.to_bytes()[..32]][..]]) invoke_signed(&ix, accounts, &[&["bridge".as_bytes()]])
} }
/// Check that a key was derived correctly and create account /// Check that a key was derived correctly and create account

View File

@ -2,15 +2,14 @@
use std::mem::size_of; use std::mem::size_of;
use primitive_types::U256;
use solana_sdk::{account_info::AccountInfo, program_error::ProgramError, pubkey::Pubkey}; use solana_sdk::{account_info::AccountInfo, program_error::ProgramError, pubkey::Pubkey};
use zerocopy::AsBytes;
use crate::instruction::{ForeignAddress, VAA_BODY};
use crate::error::Error; use crate::error::Error;
use crate::instruction::{ForeignAddress, VAAData};
use crate::syscalls::RawKey; use crate::syscalls::RawKey;
use crate::vaa::BodyTransfer; use crate::vaa::BodyTransfer;
use primitive_types::U256;
use zerocopy::AsBytes;
/// fee rate as a ratio /// fee rate as a ratio
#[repr(C)] #[repr(C)]
@ -58,7 +57,7 @@ pub struct TransferOutProposal {
/// asset that is being transferred /// asset that is being transferred
pub asset: AssetMeta, pub asset: AssetMeta,
/// vaa to unlock the tokens on the foreign chain /// vaa to unlock the tokens on the foreign chain
pub vaa: VAA_BODY, pub vaa: VAAData,
/// time the vaa was submitted /// time the vaa was submitted
pub vaa_time: u32, pub vaa_time: u32,
@ -244,8 +243,8 @@ impl Bridge {
} }
/// Calculates derived seeds for a bridge /// Calculates derived seeds for a bridge
pub fn derive_bridge_seeds(program_id: &Pubkey) -> Vec<Vec<u8>> { pub fn derive_bridge_seeds() -> Vec<Vec<u8>> {
vec![program_id.to_bytes().to_vec()] vec!["bridge".as_bytes().to_vec()]
} }
/// Calculates derived seeds for a custody account /// Calculates derived seeds for a custody account
@ -268,7 +267,7 @@ impl Bridge {
/// Calculates a derived address for this program /// Calculates a derived address for this program
pub fn derive_bridge_id(program_id: &Pubkey) -> Result<Pubkey, Error> { pub fn derive_bridge_id(program_id: &Pubkey) -> Result<Pubkey, Error> {
Self::derive_key(program_id, &Self::derive_bridge_seeds(program_id)) Self::derive_key(program_id, &Self::derive_bridge_seeds())
} }
/// Calculates a derived address for a custody account /// Calculates a derived address for a custody account

View File

@ -55,6 +55,18 @@ impl VAA {
sol_verify_schnorr(&schnorr_input) sol_verify_schnorr(&schnorr_input)
} }
pub fn body_hash(&self) -> Result<[u8; 32], Error> {
let body_bytes = self.signature_body()?;
let mut k = sha3::Keccak256::default();
if let Err(_) = k.write(body_bytes.as_slice()) {
return Err(Error::ParseFailed.into());
};
let hash = k.finalize();
return Ok(hash.into());
}
pub fn serialize(&self) -> Result<Vec<u8>, Error> { pub fn serialize(&self) -> Result<Vec<u8>, Error> {
let mut v = Cursor::new(Vec::new()); let mut v = Cursor::new(Vec::new());
@ -252,7 +264,6 @@ impl BodyTransfer {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use hex; use hex;
use primitive_types::U256; use primitive_types::U256;