Skip to content

Commit

Permalink
feat: transfer ops event, message executed event, rkyv encoding (#416)
Browse files Browse the repository at this point in the history
* refactor: clean up axelar message primitives
* refactor: remove command PDA parameter from `rotate_signers`
* feat: gateway events will be rkyv encoded
  • Loading branch information
roberts-pumpurs authored Sep 2, 2024
1 parent aea9fe6 commit dd37ef2
Show file tree
Hide file tree
Showing 28 changed files with 365 additions and 263 deletions.
4 changes: 0 additions & 4 deletions solana/helpers/axelar-message-primitives/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,3 @@ pub use address::*;
pub use destination_program_id::*;
pub use payload::*;
pub use u256::*;

pub mod command {
pub use super::u256::*;
}
6 changes: 3 additions & 3 deletions solana/helpers/test-fixtures/src/execute_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ pub fn prepare_execute_data(
payload: Payload,
signers: &SigningVerifierSet,
domain_separator: &[u8; 32],
) -> (Vec<u8>, VerifierSet) {
) -> (ExecuteData, VerifierSet) {
// Setup
let verifier_set = signers.verifier_set();
let payload_hash = hash_payload(domain_separator, &verifier_set, &payload, hasher_impl());
Expand Down Expand Up @@ -40,10 +40,10 @@ pub fn prepare_execute_data(
.unwrap();

// Confidence check: ExecuteData can be deserialized
ExecuteData::from_bytes(&execute_data_bytes).expect("valid deserialization");
let execute_data = ExecuteData::from_bytes(&execute_data_bytes).expect("valid deserialization");

// Confidence check: ExecuteData can be cast to its archive
ArchivedExecuteData::from_bytes(&execute_data_bytes).expect("valid archival");

(execute_data_bytes, verifier_set)
(execute_data, verifier_set)
}
74 changes: 48 additions & 26 deletions solana/helpers/test-fixtures/src/test_setup.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
use std::path::PathBuf;

use axelar_message_primitives::command::U256;
use axelar_message_primitives::DataPayload;
use axelar_message_primitives::{DataPayload, U256};
use axelar_rkyv_encoding::rkyv::validation::validators::DefaultValidator;
use axelar_rkyv_encoding::rkyv::CheckBytes;
use axelar_rkyv_encoding::types::u128::U128;
use axelar_rkyv_encoding::types::{Message, Payload, VerifierSet};
use axelar_rkyv_encoding::types::{ExecuteData, Message, Payload, VerifierSet};
use borsh::BorshDeserialize;
use gateway::commands::OwnedCommand;
use gateway::hasher_impl;
Expand Down Expand Up @@ -438,42 +437,62 @@ impl TestFixture {
.unwrap();
}

async fn init_approve_messages_execute_data(
pub async fn init_approve_messages_execute_data(
&mut self,
gateway_root_pda: &Pubkey,
payload: Payload,
signers: &SigningVerifierSet,
domain_separator: &[u8; 32],
) -> (Pubkey, Vec<u8>) {
) -> (
Pubkey,
ExecuteData,
GatewayExecuteData<ApproveMessagesVariant>,
) {
let (raw_data, _) = prepare_execute_data(payload, signers, domain_separator);
let execute_data_pda = self
.init_approve_messages_execute_data_with_custom_data(
gateway_root_pda,
&raw_data,
&raw_data.to_bytes::<0>().unwrap(),
domain_separator,
)
.await;
let execute_data = GatewayExecuteData::new(
&raw_data.to_bytes::<0>().unwrap(),
gateway_root_pda,
domain_separator,
)
.unwrap();

(execute_data_pda, raw_data)
(execute_data_pda, raw_data, execute_data)
}

async fn init_rotate_signers_execute_data(
pub async fn init_rotate_signers_execute_data(
&mut self,
gateway_root_pda: &Pubkey,
payload: Payload,
signers: &SigningVerifierSet,
domain_separator: &[u8; 32],
) -> (Pubkey, Vec<u8>) {
) -> (
Pubkey,
ExecuteData,
GatewayExecuteData<RotateSignersVariant>,
) {
let (raw_data, _) = prepare_execute_data(payload, signers, domain_separator);
let execute_data_pda = self
.init_rotate_signers_execute_data_with_custom_data(
gateway_root_pda,
&raw_data,
&raw_data.to_bytes::<0>().unwrap(),
domain_separator,
)
.await;
let execute_data = GatewayExecuteData::new(
&raw_data.to_bytes::<0>().unwrap(),
gateway_root_pda,
domain_separator,
)
.unwrap();

(execute_data_pda, raw_data)
(execute_data_pda, raw_data, execute_data)
}

pub async fn init_execute_data(
Expand All @@ -485,22 +504,26 @@ impl TestFixture {
) -> (Pubkey, Vec<u8>) {
match &payload {
Payload::Messages(_) => {
self.init_approve_messages_execute_data(
gateway_root_pda,
payload,
signers,
domain_separator,
)
.await
let res = self
.init_approve_messages_execute_data(
gateway_root_pda,
payload,
signers,
domain_separator,
)
.await;
(res.0, res.1.to_bytes::<0>().unwrap())
}
Payload::VerifierSet(_) => {
self.init_rotate_signers_execute_data(
gateway_root_pda,
payload,
signers,
domain_separator,
)
.await
let res = self
.init_rotate_signers_execute_data(
gateway_root_pda,
payload,
signers,
domain_separator,
)
.await;
(res.0, res.1.to_bytes::<0>().unwrap())
}
}
}
Expand Down Expand Up @@ -818,7 +841,6 @@ impl TestFixture {
domain_separator,
)
.await;

let tx = self
.rotate_signers_with_metadata(
gateway_root_pda,
Expand Down
8 changes: 4 additions & 4 deletions solana/programs/axelar-solana-memo-program/src/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ pub enum AxelarMemoInstruction {
/// Memo to send to the gateway
memo: String,
/// Destination chain we want to communicate with
destination_chain: Vec<u8>,
destination_chain: String,
/// Destination contract address on the destination chain
destination_address: Vec<u8>,
destination_address: String,
},
}

Expand Down Expand Up @@ -75,8 +75,8 @@ pub fn call_gateway_with_memo(
gateway_root_pda: &Pubkey,
sender: &Pubkey,
memo: String,
destination_chain: Vec<u8>,
destination_address: Vec<u8>,
destination_chain: String,
destination_address: String,
) -> Result<Instruction, ProgramError> {
let instruction_data =
AxelarCallableInstruction::Native(AxelarMemoInstruction::SendToGateway {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
use std::borrow::Cow;
use std::str::FromStr;

use axelar_solana_memo_program::instruction::call_gateway_with_memo;
use ethers_core::utils::hex::ToHex;
use ethers_core::utils::keccak256;
use evm_contracts_test_suite::evm_contracts_rs::contracts::axelar_memo::ReceivedMemoFilter;
use gateway::events::{CallContract, GatewayEvent};
use gateway::events::{ArchivedCallContract, ArchivedGatewayEvent, EventContainer, GatewayEvent};
use solana_program_test::tokio;
use solana_sdk::pubkey::Pubkey;
use solana_sdk::signature::Signer;
use solana_sdk::transaction::Transaction;

Expand All @@ -28,22 +30,26 @@ async fn test_send_from_solana_to_evm() {
let solana_id = "solana-localnet";
let memo = "🐪🐪🐪🐪";
let destination_address: ethers_core::types::Address = evm_memo.address();
let destination_chain = "ethereum".to_string().into_bytes();
let destination_chain = "ethereum".to_string();

// Action:
// - send message from Solana memo program to Solana gateway
let call_contract = call_solana_gateway(
let gateway_event = call_solana_gateway(
&solana_chain.gateway_root_pda,
&mut solana_chain.fixture,
memo,
destination_chain,
&destination_address,
)
.await;
let ArchivedGatewayEvent::CallContract(call_contract) = gateway_event.parse() else {
panic!("Expected CallContract event, got {:?}", gateway_event);
};

// - EVM operators sign the contract call
let (messages, proof) = evm_prepare_approve_contract_call(
solana_id,
&call_contract,
call_contract,
&mut weighted_signers,
domain_separator,
);
Expand Down Expand Up @@ -71,12 +77,12 @@ async fn test_send_from_solana_to_evm() {
.unwrap();
assert!(is_approved, "contract call was not approved");
assert_eq!(
keccak256(call_contract.payload.clone()),
keccak256(&call_contract.payload),
call_contract.payload_hash
);
assert_eq!(
evm_memo.address(),
ethers_core::types::Address::from_slice(call_contract.destination_address.as_slice())
ethers_core::types::Address::from_str(call_contract.destination_address.as_str()).unwrap()
);

// Action - Relayer calls the EVM memo program with the payload
Expand All @@ -85,7 +91,7 @@ async fn test_send_from_solana_to_evm() {
message.source_chain,
message.message_id,
message.source_address,
call_contract.payload.into(),
call_contract.payload.to_vec().into(),
)
.send()
.await
Expand All @@ -112,7 +118,7 @@ async fn test_send_from_solana_to_evm() {

fn evm_prepare_approve_contract_call(
solana_id: &str,
call_contract: &CallContract,
call_contract: &ArchivedCallContract,
signer_set: &mut evm_contracts_test_suite::evm_weighted_signers::WeightedSigners,
domain_separator: [u8; 32],
) -> (
Expand All @@ -123,10 +129,11 @@ fn evm_prepare_approve_contract_call(
evm_contracts_test_suite::evm_contracts_rs::contracts::axelar_amplifier_gateway::Message {
source_chain: solana_id.to_string(),
message_id: "message555".to_string(),
source_address: call_contract.sender.to_string(),
contract_address: ethers_core::types::Address::from_slice(
call_contract.destination_address.as_slice(),
),
source_address: Pubkey::from(call_contract.sender).to_string(),
contract_address: ethers_core::types::Address::from_str(
call_contract.destination_address.as_str(),
)
.unwrap(),
payload_hash: call_contract.payload_hash,
};
let approve_contract_call_command =
Expand All @@ -145,16 +152,18 @@ async fn call_solana_gateway(
gateway_root_pda: &solana_sdk::pubkey::Pubkey,
solana_fixture: &mut test_fixtures::test_setup::TestFixture,
memo: &str,
destination_chain: Vec<u8>,
destination_chain: String,
destination_address: &ethers_core::types::H160,
) -> CallContract {
) -> EventContainer {
let destination_address = destination_address.encode_hex();
dbg!(&destination_address);
let transaction = Transaction::new_signed_with_payer(
&[call_gateway_with_memo(
gateway_root_pda,
&solana_fixture.payer.pubkey(),
memo.to_string(),
destination_chain,
destination_address.as_bytes().to_vec(),
destination_address,
)
.unwrap()],
Some(&solana_fixture.payer.pubkey()),
Expand All @@ -178,9 +187,6 @@ async fn call_solana_gateway(
.iter()
.find_map(GatewayEvent::parse_log)
.expect("Gateway event was not emitted?");
let GatewayEvent::CallContract(Cow::Owned(call_contract)) = gateway_event else {
panic!("Expected CallContract event, got {:?}", gateway_event);
};

call_contract
gateway_event
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
use std::borrow::Cow;

use axelar_solana_memo_program::instruction::call_gateway_with_memo;
use ethers_core::abi::AbiEncode;
use ethers_core::utils::keccak256;
use gateway::events::GatewayEvent;
use gateway::events::{CallContract, GatewayEvent};
use solana_program_test::tokio;
use solana_sdk::signer::Signer;
use solana_sdk::transaction::Transaction;
Expand All @@ -14,8 +13,8 @@ async fn test_succesfully_send_to_gateway() {
// Setup
let mut solana_chain = program_test().await;
let memo = "🐪🐪🐪🐪";
let destination_address = ethers_core::types::Address::random().0.to_vec();
let destination_chain = "ethereum".to_string().into_bytes();
let destination_address = ethers_core::types::Address::random().encode_hex();
let destination_chain = "ethereum".to_string();

// Action: send message to gateway
let transaction = Transaction::new_signed_with_payer(
Expand Down Expand Up @@ -53,15 +52,16 @@ async fn test_succesfully_send_to_gateway() {
.iter()
.find_map(GatewayEvent::parse_log)
.expect("Gateway event was not emitted?");
let gateway_event = gateway_event.parse();
assert_eq!(
gateway_event,
GatewayEvent::CallContract(Cow::Owned(gateway::events::CallContract {
sender: solana_chain.fixture.payer.pubkey(),
&GatewayEvent::CallContract(CallContract {
sender: solana_chain.fixture.payer.pubkey().to_bytes(),
destination_chain,
destination_address: destination_address.to_vec(),
payload_hash: keccak256(memo.as_bytes()),
destination_address,
payload: memo.as_bytes().to_vec(),
})),
payload_hash: keccak256(memo.as_bytes())
}),
"Mismatched gateway event"
);
}
2 changes: 1 addition & 1 deletion solana/programs/gas-service/src/events.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Axelar Gas Service events.

use axelar_message_primitives::command::U256;
use axelar_message_primitives::U256;
use base64::engine::general_purpose;
use base64::Engine as _;
use borsh::{BorshDeserialize, BorshSerialize};
Expand Down
2 changes: 1 addition & 1 deletion solana/programs/gas-service/src/instruction.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Instruction module; consist of fasade instructions, test ix constructors and
//! internal helpers.

use axelar_message_primitives::command::U256;
use axelar_message_primitives::U256;
use borsh::{to_vec, BorshDeserialize, BorshSerialize};
use solana_program::instruction::{AccountMeta, Instruction};
use solana_program::program_error::ProgramError;
Expand Down
2 changes: 1 addition & 1 deletion solana/programs/gas-service/src/processor.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Program processor

use axelar_message_primitives::command::U256;
use axelar_message_primitives::U256;
use borsh::BorshDeserialize;
use solana_program::account_info::{next_account_info, AccountInfo};
use solana_program::entrypoint::ProgramResult;
Expand Down
2 changes: 1 addition & 1 deletion solana/programs/gas-service/tests/integration.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
mod common;

use anyhow::{Ok, Result};
use axelar_message_primitives::command::U256;
use axelar_message_primitives::U256;
use base64::engine::general_purpose;
use base64::Engine;
use borsh::BorshDeserialize;
Expand Down
Loading

0 comments on commit dd37ef2

Please sign in to comment.