From 4887e1093bcc6896cc107e0032988e0e9c4f7f6f Mon Sep 17 00:00:00 2001 From: albert Date: Thu, 13 Feb 2025 11:13:50 +0100 Subject: [PATCH 1/4] chore: add ci when PR against base branch --- .github/workflows/ci-development.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci-development.yml b/.github/workflows/ci-development.yml index 5cf46a275c4..eb20a5c53d7 100644 --- a/.github/workflows/ci-development.yml +++ b/.github/workflows/ci-development.yml @@ -5,6 +5,7 @@ on: branches: - main - "release/*" + - "feat/solana-versioned-transaction-base-branch" concurrency: group: ${{ github.ref }}-release-development cancel-in-progress: true From 2e3613b3451f3360823f007624e583cfb8f23971 Mon Sep 17 00:00:00 2001 From: Roy Yang Date: Wed, 19 Feb 2025 10:18:37 +1300 Subject: [PATCH 2/4] feat: use Solana versioned transaction to build api calls (#5633) * Added versioned transaction and versioned message support * Added unit test for Versioned transactions with Address lookup table * Moved (almost) everything in sol_tx_core into sol-prim Moved ALT related stuff to its own file. * Initial commit for changing Solana Transaction to VersionedTransaction * chore: update bouncer to get versioned transactions * Updated unit tests for transaction building Removed all uses of Legacy message and Transaction. * Fix broken unit test * Make solana api calls more consistent with the use of ALT --------- Co-authored-by: Daniel Co-authored-by: albert --- Cargo.lock | 1 + bouncer/shared/sol_vault_swap.ts | 5 +- bouncer/shared/utils.ts | 4 +- bouncer/tests/gaslimit_ccm.ts | 1 + foreign-chains/solana/sol-prim/Cargo.toml | 3 +- foreign-chains/solana/sol-prim/src/alt.rs | 19 +- foreign-chains/solana/sol-prim/src/consts.rs | 2 + .../solana/sol-prim/src/transaction.rs | 301 +++----------- state-chain/cf-integration-tests/Cargo.toml | 1 + .../cf-integration-tests/src/solana.rs | 9 +- .../cf-integration-tests/src/swapping.rs | 1 + .../src/threshold_signing.rs | 6 +- state-chain/cfe-events/src/tests.rs | 19 +- state-chain/chains/Cargo.toml | 2 +- state-chain/chains/src/arb/api.rs | 1 + state-chain/chains/src/btc/api.rs | 1 + state-chain/chains/src/ccm_checker.rs | 229 +++++++--- state-chain/chains/src/dot/api.rs | 1 + state-chain/chains/src/eth/api.rs | 1 + state-chain/chains/src/lib.rs | 4 +- state-chain/chains/src/sol.rs | 16 +- state-chain/chains/src/sol/api.rs | 55 ++- state-chain/chains/src/sol/benchmarking.rs | 14 +- .../chains/src/sol/instruction_builder.rs | 27 +- state-chain/chains/src/sol/sol_tx_core.rs | 56 ++- state-chain/chains/src/sol/tests.rs | 393 ++++++++---------- .../chains/src/sol/transaction_builder.rs | 118 ++++-- .../pallets/cf-environment/src/mock.rs | 24 +- .../pallets/cf-ingress-egress/src/lib.rs | 4 + .../pallets/cf-ingress-egress/src/tests.rs | 3 + state-chain/runtime/src/chainflip.rs | 39 +- state-chain/runtime/src/lib.rs | 6 +- state-chain/traits/src/mocks/api_call.rs | 4 +- 33 files changed, 734 insertions(+), 636 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0187d45d030..d4d69f6a65c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1475,6 +1475,7 @@ dependencies = [ "frame-support", "frame-system", "frame-system-rpc-runtime-api", + "hex", "hex-literal", "libsecp256k1", "log", diff --git a/bouncer/shared/sol_vault_swap.ts b/bouncer/shared/sol_vault_swap.ts index bdedf68e7a3..2e5501c0b08 100644 --- a/bouncer/shared/sol_vault_swap.ts +++ b/bouncer/shared/sol_vault_swap.ts @@ -166,7 +166,10 @@ export async function executeSolVaultSwap( { commitment: 'confirmed' }, ); - const transactionData = await connection.getTransaction(txHash, { commitment: 'confirmed' }); + const transactionData = await connection.getTransaction(txHash, { + commitment: 'confirmed', + maxSupportedTransactionVersion: 0, + }); if (transactionData === null) { throw new Error('Solana TransactionData is empty'); } diff --git a/bouncer/shared/utils.ts b/bouncer/shared/utils.ts index dba2ca06088..6cdc39b13b9 100644 --- a/bouncer/shared/utils.ts +++ b/bouncer/shared/utils.ts @@ -800,7 +800,9 @@ export async function observeSolanaCcmEvent( for (let i = 0; i < 300; i++) { const txSignatures = await connection.getSignaturesForAddress(cfTesterAddress); for (const txSignature of txSignatures) { - const tx = await connection.getTransaction(txSignature.signature); + const tx = await connection.getTransaction(txSignature.signature, { + maxSupportedTransactionVersion: 0, + }); if (tx) { // eslint-disable-next-line @typescript-eslint/no-explicit-any const eventParser = new EventParser(cfTesterAddress, new BorshCoder(idl as any)); diff --git a/bouncer/tests/gaslimit_ccm.ts b/bouncer/tests/gaslimit_ccm.ts index 330648e2a38..03c335d35ba 100644 --- a/bouncer/tests/gaslimit_ccm.ts +++ b/bouncer/tests/gaslimit_ccm.ts @@ -184,6 +184,7 @@ async function testGasLimitSwapToSolana(logger: Logger, sourceAsset: Asset, dest const transaction = await connection.getTransaction(txSignature, { commitment: 'confirmed', + maxSupportedTransactionVersion: 0, }); // Checking that the compute limit is set correctly (and < MAX_CAP) is cumbersome without manually parsing instructions const totalFee = diff --git a/foreign-chains/solana/sol-prim/Cargo.toml b/foreign-chains/solana/sol-prim/Cargo.toml index 94b88570a9b..086aa4fa559 100644 --- a/foreign-chains/solana/sol-prim/Cargo.toml +++ b/foreign-chains/solana/sol-prim/Cargo.toml @@ -63,5 +63,4 @@ std = [ "sp-std/std", "sp-core/std", "cf-primitives/std", -] -runtime-integration-tests = ["std", "ed25519-dalek/rand_core"] \ No newline at end of file +] \ No newline at end of file diff --git a/foreign-chains/solana/sol-prim/src/alt.rs b/foreign-chains/solana/sol-prim/src/alt.rs index 61fbe9ce32a..a834961f376 100644 --- a/foreign-chains/solana/sol-prim/src/alt.rs +++ b/foreign-chains/solana/sol-prim/src/alt.rs @@ -1,12 +1,16 @@ pub use crate::{ short_vec, Address, CompileError, CompiledInstruction, Digest, Instruction, Pubkey, Signature, }; +use codec::{Decode, Encode}; +use scale_info::TypeInfo; use serde::{Deserialize, Serialize}; use sp_std::{collections::btree_map::BTreeMap, vec::Vec}; /// Address table lookups describe an on-chain address lookup table to use /// for loading more readonly and writable accounts in a single tx. -#[derive(Serialize, Deserialize, Default, Debug, PartialEq, Eq, Clone)] +#[derive( + Serialize, Deserialize, Default, Debug, PartialEq, Eq, Clone, Encode, Decode, TypeInfo, +)] #[serde(rename_all = "camelCase")] pub struct MessageAddressTableLookup { /// Address lookup table account key @@ -28,6 +32,19 @@ pub struct AddressLookupTableAccount { pub addresses: Vec, } +impl AddressLookupTableAccount { + pub fn new(key: Address, addresses: Vec
) -> AddressLookupTableAccount { + AddressLookupTableAccount { + key: key.into(), + addresses: addresses.into_iter().map(|a| a.into()).collect::>(), + } + } + + pub fn is_empty(&self) -> bool { + self.addresses.is_empty() + } +} + /// Collection of static and dynamically loaded keys used to load accounts /// during transaction processing. #[derive(Clone, Default, Debug, Eq)] diff --git a/foreign-chains/solana/sol-prim/src/consts.rs b/foreign-chains/solana/sol-prim/src/consts.rs index 8ab5d87624d..b52e02624ba 100644 --- a/foreign-chains/solana/sol-prim/src/consts.rs +++ b/foreign-chains/solana/sol-prim/src/consts.rs @@ -56,3 +56,5 @@ pub const NONCE_ACCOUNT_LENGTH: u64 = 80u64; pub const SOL_USDC_DECIMAL: u8 = 6u8; pub const ACCOUNT_KEY_LENGTH_IN_TRANSACTION: usize = 32usize; pub const ACCOUNT_REFERENCE_LENGTH_IN_TRANSACTION: usize = 1usize; + +pub const MAX_CCM_USER_ALTS: u8 = 5u8; // TODO: Albert come up with a good number for this diff --git a/foreign-chains/solana/sol-prim/src/transaction.rs b/foreign-chains/solana/sol-prim/src/transaction.rs index 6ef94f1c4cd..6360970358f 100644 --- a/foreign-chains/solana/sol-prim/src/transaction.rs +++ b/foreign-chains/solana/sol-prim/src/transaction.rs @@ -1,7 +1,7 @@ use crate::{ - compile_instructions, consts::MESSAGE_VERSION_PREFIX, short_vec, AddressLookupTableAccount, - CompiledInstruction, CompiledKeys, Hash, Instruction, MessageAddressTableLookup, MessageHeader, - Pubkey, RawSignature, Signature, + consts::MESSAGE_VERSION_PREFIX, short_vec, AddressLookupTableAccount, CompiledInstruction, + CompiledKeys, Hash, Instruction, MessageAddressTableLookup, MessageHeader, Pubkey, + RawSignature, Signature, }; use codec::{Decode, Encode}; use scale_info::TypeInfo; @@ -14,12 +14,10 @@ use serde::{ Deserializer, Serializer, }; use sp_std::fmt; +use v0::VersionedMessageV0; -#[cfg(any(test, feature = "runtime-integration-tests"))] -use crate::{ - errors::TransactionError, - signer::{Signer, SignerError, TestSigners}, -}; +#[cfg(feature = "std")] +use crate::signer::{Signer, TestSigners}; #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "camelCase", untagged)] @@ -46,13 +44,27 @@ pub enum Legacy { /// which message version is serialized starting from version `0`. If the first /// is bit is not set, all bytes are used to encode the legacy `Message` /// format. -#[derive(Debug, PartialEq, Eq, Clone)] +#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode, TypeInfo)] pub enum VersionedMessage { - Legacy(legacy::LegacyMessage), + Legacy(legacy::DeprecatedLegacyMessage), V0(v0::VersionedMessageV0), } impl VersionedMessage { + pub fn new( + instructions: &[Instruction], + payer: Option, + blockhash: Option, + lookup_tables: &[AddressLookupTableAccount], + ) -> VersionedMessage { + VersionedMessage::V0(v0::VersionedMessageV0::new_with_blockhash( + instructions, + payer, + blockhash.unwrap_or_default(), + lookup_tables, + )) + } + pub fn header(&self) -> &MessageHeader { match self { Self::Legacy(message) => &message.header, @@ -67,6 +79,19 @@ impl VersionedMessage { } } + pub fn map_static_account_keys(&mut self, f: impl Fn(Pubkey) -> Pubkey) { + match self { + Self::Legacy(message) => + for k in message.account_keys.iter_mut() { + *k = f(*k); + }, + Self::V0(message) => + for k in message.account_keys.iter_mut() { + *k = f(*k); + }, + } + } + pub fn address_table_lookups(&self) -> Option<&[MessageAddressTableLookup]> { match self { Self::Legacy(_) => None, @@ -110,7 +135,7 @@ impl VersionedMessage { impl Default for VersionedMessage { fn default() -> Self { - Self::Legacy(legacy::LegacyMessage::default()) + Self::V0(VersionedMessageV0::default()) } } @@ -218,7 +243,7 @@ impl<'de> serde::Deserialize<'de> for VersionedMessage { de::Error::invalid_length(1, &self) })?; - Ok(VersionedMessage::Legacy(legacy::LegacyMessage { + Ok(VersionedMessage::Legacy(legacy::DeprecatedLegacyMessage { header: MessageHeader { num_required_signatures, num_readonly_signed_accounts: message.num_readonly_signed_accounts, @@ -261,7 +286,9 @@ impl<'de> serde::Deserialize<'de> for VersionedMessage { // NOTE: Serialization-related changes must be paired with the direct read at sigverify. /// An atomic transaction -#[derive(Debug, PartialEq, Default, Eq, Clone, Serialize, Deserialize)] +#[derive( + Debug, PartialEq, Default, Eq, Clone, Serialize, Deserialize, Encode, Decode, TypeInfo, +)] pub struct VersionedTransaction { /// List of signatures #[serde(with = "short_vec")] @@ -270,15 +297,6 @@ pub struct VersionedTransaction { pub message: VersionedMessage, } -impl From for VersionedTransaction { - fn from(transaction: legacy::LegacyTransaction) -> Self { - Self { - signatures: transaction.signatures, - message: VersionedMessage::Legacy(transaction.message), - } - } -} - impl VersionedTransaction { pub fn new_unsigned(message: VersionedMessage) -> Self { Self { @@ -290,19 +308,8 @@ impl VersionedTransaction { } } - #[cfg(any(test, feature = "runtime-integration-tests"))] - pub fn new_with_payer( - instructions: &[Instruction], - payer: Option, - lookup_tables: &[AddressLookupTableAccount], - ) -> Self { - let message = - VersionedMessage::V0(v0::VersionedMessageV0::new(instructions, payer, lookup_tables)); - Self::new_unsigned(message) - } - - #[cfg(any(test, feature = "runtime-integration-tests"))] - pub fn sign(&mut self, signers: TestSigners, recent_blockhash: Hash) { + #[cfg(feature = "std")] + pub fn test_only_sign(&mut self, signers: TestSigners, recent_blockhash: Hash) { let positions = self.get_signing_keypair_positions(signers.pubkeys()); // if you change the blockhash, you're re-signing... @@ -321,8 +328,8 @@ impl VersionedTransaction { } } - #[cfg(any(test, feature = "runtime-integration-tests"))] - pub fn get_signing_keypair_positions(&self, pubkeys: Vec) -> Vec { + #[cfg(feature = "std")] + fn get_signing_keypair_positions(&self, pubkeys: Vec) -> Vec { let account_keys = self.message.static_account_keys(); let required_sigs = self.message.header().num_required_signatures as usize; if account_keys.len() < required_sigs { @@ -366,15 +373,6 @@ impl VersionedTransaction { VersionedMessage::V0(_) => TransactionVersion::Number(0), } } - - /// Returns a legacy transaction if the transaction message is legacy. - pub fn into_legacy_transaction(self) -> Option { - match self.message { - VersionedMessage::Legacy(message) => - Some(legacy::LegacyTransaction { signatures: self.signatures, message }), - _ => None, - } - } } pub mod v0 { @@ -392,7 +390,9 @@ pub mod v0 { /// See the [`message`] module documentation for further description. /// /// [`message`]: crate::message - #[derive(Serialize, Deserialize, Default, Debug, PartialEq, Eq, Clone)] + #[derive( + Serialize, Deserialize, Default, Debug, PartialEq, Eq, Clone, Encode, Decode, TypeInfo, + )] #[serde(rename_all = "camelCase")] pub struct VersionedMessageV0 { /// The message header, identifying signed and read-only `account_keys`. @@ -583,12 +583,11 @@ pub mod v0 { } } +/// Placeholder code for Solana's Legacy Message and Transaction. This code +/// is no longer used by Chainflip. The code is kept here for placeholder purpose. pub mod legacy { use super::*; - #[cfg(test)] - use crate::instructions::program_instructions; - /// A Solana transaction message (legacy). /// /// See the [`message`] module documentation for further description. @@ -609,7 +608,7 @@ pub mod legacy { Encode, Decode, TypeInfo, Serialize, Deserialize, Default, Debug, PartialEq, Eq, Clone, )] #[serde(rename_all = "camelCase")] - pub struct LegacyMessage { + pub struct DeprecatedLegacyMessage { /// The message header, identifying signed and read-only `account_keys`. // NOTE: Serialization-related changes must be paired with the direct read at sigverify. pub header: MessageHeader, @@ -627,71 +626,6 @@ pub mod legacy { pub instructions: Vec, } - impl LegacyMessage { - pub fn new_with_blockhash( - instructions: &[Instruction], - payer: Option<&Pubkey>, - blockhash: &Hash, - ) -> Self { - let compiled_keys = CompiledKeys::compile(instructions, payer.cloned()); - let (header, account_keys) = compiled_keys - .try_into_message_components() - .expect("overflow when compiling message keys"); - let instructions = compile_instructions(instructions, &account_keys); - Self::new_with_compiled_instructions( - header.num_required_signatures, - header.num_readonly_signed_accounts, - header.num_readonly_unsigned_accounts, - account_keys, - *blockhash, - instructions, - ) - } - - pub fn new(instructions: &[Instruction], payer: Option<&Pubkey>) -> Self { - Self::new_with_blockhash(instructions, payer, &Hash::default()) - } - - #[cfg(test)] - pub fn new_with_nonce( - mut instructions: Vec, - payer: Option<&Pubkey>, - nonce_account_pubkey: &Pubkey, - nonce_authority_pubkey: &Pubkey, - ) -> Self { - let nonce_ix = program_instructions::SystemProgramInstruction::advance_nonce_account( - nonce_account_pubkey, - nonce_authority_pubkey, - ); - instructions.insert(0, nonce_ix); - Self::new(&instructions, payer) - } - - fn new_with_compiled_instructions( - num_required_signatures: u8, - num_readonly_signed_accounts: u8, - num_readonly_unsigned_accounts: u8, - account_keys: Vec, - recent_blockhash: Hash, - instructions: Vec, - ) -> Self { - Self { - header: MessageHeader { - num_required_signatures, - num_readonly_signed_accounts, - num_readonly_unsigned_accounts, - }, - account_keys, - recent_blockhash, - instructions, - } - } - - pub fn serialize(&self) -> Vec { - bincode::serde::encode_to_vec(self, bincode::config::legacy()).unwrap() - } - } - /// An atomically-committed sequence of instructions. /// /// While [`Instruction`]s are the basic unit of computation in Solana, @@ -715,7 +649,7 @@ pub mod legacy { #[derive( Encode, Decode, TypeInfo, Debug, PartialEq, Default, Eq, Clone, Serialize, Deserialize, )] - pub struct LegacyTransaction { + pub struct DeprecatedLegacyTransaction { /// A set of signatures of a serialized [`Message`], signed by the first /// keys of the `Message`'s [`account_keys`], where the number of signatures /// is equal to [`num_required_signatures`] of the `Message`'s @@ -729,144 +663,19 @@ pub mod legacy { pub signatures: Vec, /// The message to sign. - pub message: LegacyMessage, - } - - impl LegacyTransaction { - pub fn new_unsigned(message: LegacyMessage) -> Self { - Self { - signatures: vec![ - Signature::default(); - message.header.num_required_signatures as usize - ], - message, - } - } - - #[cfg(any(test, feature = "runtime-integration-tests"))] - pub fn new_with_payer(instructions: &[Instruction], payer: Option<&Pubkey>) -> Self { - let message = LegacyMessage::new(instructions, payer); - Self::new_unsigned(message) - } - - #[cfg(any(test, feature = "runtime-integration-tests"))] - pub fn sign(&mut self, signers: TestSigners, recent_blockhash: Hash) { - if let Err(e) = self.try_sign(signers, recent_blockhash) { - panic!("Transaction::sign failed with error {e:?}"); - } - } - - #[cfg(any(test, feature = "runtime-integration-tests"))] - pub fn try_sign( - &mut self, - signers: TestSigners, - recent_blockhash: Hash, - ) -> Result<(), SignerError> { - self.try_partial_sign(signers, recent_blockhash)?; - - if !self.is_signed() { - Err(SignerError::NotEnoughSigners) - } else { - Ok(()) - } - } - - #[cfg(any(test, feature = "runtime-integration-tests"))] - pub fn try_partial_sign( - &mut self, - signers: TestSigners, - recent_blockhash: Hash, - ) -> Result<(), SignerError> { - let positions = self.get_signing_keypair_positions(signers.pubkeys())?; - if positions.iter().any(|pos| pos.is_none()) { - return Err(SignerError::KeypairPubkeyMismatch) - } - let positions: Vec = positions.iter().map(|pos| pos.unwrap()).collect(); - self.try_partial_sign_unchecked(signers, positions, recent_blockhash) - } - - #[cfg(any(test, feature = "runtime-integration-tests"))] - pub fn try_partial_sign_unchecked( - &mut self, - signers: TestSigners, - positions: Vec, - recent_blockhash: Hash, - ) -> Result<(), SignerError> { - // if you change the blockhash, you're re-signing... - if recent_blockhash != self.message.recent_blockhash { - self.message.recent_blockhash = recent_blockhash; - self.signatures - .iter_mut() - .for_each(|signature| *signature = Signature::default()); - } - - let signatures = signers.try_sign_message(&self.message_data())?; - for i in 0..positions.len() { - self.signatures[positions[i]] = signatures[i]; - } - Ok(()) - } - - #[cfg(any(test, feature = "runtime-integration-tests"))] - pub fn get_signing_keypair_positions( - &self, - pubkeys: Vec, - ) -> Result>, TransactionError> { - if self.message.account_keys.len() < - self.message.header.num_required_signatures as usize - { - return Err(TransactionError::InvalidAccountIndex) - } - let signed_keys = - &self.message.account_keys[0..self.message.header.num_required_signatures as usize]; - - Ok(pubkeys - .iter() - .map(|pubkey| signed_keys.iter().position(|x| x == pubkey)) - .collect()) - } - - pub fn is_signed(&self) -> bool { - self.signatures.iter().all(|signature| *signature != Signature::default()) - } - - /// Return the message containing all data that should be signed. - pub fn message(&self) -> &LegacyMessage { - &self.message - } - - /// Return the serialized message data to sign. - pub fn message_data(&self) -> Vec { - self.message().serialize() - } - - /// Due to different Serialization between Signature and Solana native Signature type, - /// the Signatures needs to be converted into the RawSignature type before the - /// transaction is serialized as whole. - pub fn finalize_and_serialize(self) -> Result, bincode::error::EncodeError> { - bincode::serde::encode_to_vec(RawTransaction::from(self), bincode::config::legacy()) - } + pub message: DeprecatedLegacyMessage, } } /// Internal raw transaction type used for correct Serialization and Encoding #[derive(Debug, PartialEq, Default, Eq, Clone, Serialize, Deserialize)] -struct RawTransaction { +struct RawTransaction { #[serde(with = "short_vec")] pub signatures: Vec, - pub message: Message, -} - -impl From for RawTransaction { - fn from(from: legacy::LegacyTransaction) -> Self { - Self { - signatures: from.signatures.into_iter().map(RawSignature::from).collect(), - message: from.message, - } - } + pub message: VersionedMessage, } -impl From for RawTransaction { +impl From for RawTransaction { fn from(from: VersionedTransaction) -> Self { Self { signatures: from.signatures.into_iter().map(RawSignature::from).collect(), diff --git a/state-chain/cf-integration-tests/Cargo.toml b/state-chain/cf-integration-tests/Cargo.toml index 89c978a2603..7dab01bf2c2 100644 --- a/state-chain/cf-integration-tests/Cargo.toml +++ b/state-chain/cf-integration-tests/Cargo.toml @@ -21,6 +21,7 @@ log = { workspace = true } [dev-dependencies] libsecp256k1 = { workspace = true, default-features = true, features = ["static-context"] } rand = { workspace = true, default-features = true } +hex = { workspace = true } hex-literal = { workspace = true, default-features = true } secp256k1 = { workspace = true, features = ["rand-std"] } arrayref = { workspace = true } diff --git a/state-chain/cf-integration-tests/src/solana.rs b/state-chain/cf-integration-tests/src/solana.rs index 9f4a05d3e73..a0f0749603a 100644 --- a/state-chain/cf-integration-tests/src/solana.rs +++ b/state-chain/cf-integration-tests/src/solana.rs @@ -634,11 +634,11 @@ fn solana_resigning() { ).unwrap(); transaction.signatures = vec![[1u8; 64].into()]; - let original_account_keys = transaction.message.account_keys.clone(); + let original_account_keys = transaction.message.static_account_keys(); let apicall = SolanaApi { call_type: cf_chains::sol::api::SolanaTransactionType::Transfer, - transaction, + transaction: transaction.clone(), signer: Some(CURRENT_SIGNER.into()), _phantom: PhantomData::, }; @@ -651,7 +651,7 @@ fn solana_resigning() { if let RequiresSignatureRefresh::True(call) = modified_call { let agg_key = ::current_agg_key().unwrap(); let transaction = call.clone().unwrap().transaction; - for (modified_key, original_key) in transaction.message.account_keys.iter().zip(original_account_keys.iter()) { + for (modified_key, original_key) in transaction.message.static_account_keys().iter().zip(original_account_keys.iter()) { if *original_key != SolPubkey::from(CURRENT_SIGNER) { assert_eq!(modified_key, original_key); assert_ne!(*modified_key, SolPubkey::from(agg_key)); @@ -665,7 +665,8 @@ fn solana_resigning() { // Compare against a manually crafted transaction that works with the current test values and // agg_key. Not the signature itself - let expected_serialized_tx = hex_literal::hex!("010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000306f68d61e8d834034cf583f486f2a08ef53ce4134ed41c4d88f4720c39518745b617eb2b10d3377bda2bc7bea65bec6b8372f4fc3463ec2cd6f9fde4b2c633d192cf1dd130e0341d60a0771ac40ea7900106a423354d2ecd6e609bd5e2ed833dec00000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea9400000c27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e4890004030301050004040000000400090380969800000000000400050284030000030200020c020000008096980000000000").to_vec(); + let expected_serialized_tx = hex_literal::hex!("01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008001000306f68d61e8d834034cf583f486f2a08ef53ce4134ed41c4d88f4720c39518745b617eb2b10d3377bda2bc7bea65bec6b8372f4fc3463ec2cd6f9fde4b2c633d192cf1dd130e0341d60a0771ac40ea7900106a423354d2ecd6e609bd5e2ed833dec00000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea9400000c27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e4890004030301050004040000000400090380969800000000000400050284030000030200020c02000000809698000000000000").to_vec(); + assert_eq!(&serialized_tx[1+64..], &expected_serialized_tx[1+64..]); assert_eq!(&serialized_tx[0], &expected_serialized_tx[0]); } else { diff --git a/state-chain/cf-integration-tests/src/swapping.rs b/state-chain/cf-integration-tests/src/swapping.rs index 3156835a7c1..e8aed28c594 100644 --- a/state-chain/cf-integration-tests/src/swapping.rs +++ b/state-chain/cf-integration-tests/src/swapping.rs @@ -685,6 +685,7 @@ fn ethereum_ccm_can_calculate_gas_limits() { gas_budget, vec![], vec![], + Default::default(), ) .unwrap() }; diff --git a/state-chain/cf-integration-tests/src/threshold_signing.rs b/state-chain/cf-integration-tests/src/threshold_signing.rs index e76c9c39b46..67eacd3d574 100644 --- a/state-chain/cf-integration-tests/src/threshold_signing.rs +++ b/state-chain/cf-integration-tests/src/threshold_signing.rs @@ -4,8 +4,8 @@ use cf_chains::{ dot::{EncodedPolkadotPayload, PolkadotPair, PolkadotPublicKey, PolkadotSignature}, evm::{to_evm_address, AggKey, SchnorrVerificationComponents}, sol::{ - signing_key::SolSigningKey, sol_tx_core::signer::Signer, SolAddress, SolLegacyMessage, - SolSignature, + signing_key::SolSigningKey, sol_tx_core::signer::Signer, SolAddress, SolSignature, + SolVersionedMessage, }, }; use cf_primitives::{EpochIndex, GENESIS_EPOCH}; @@ -258,7 +258,7 @@ impl Default for SolThresholdSigner { impl KeyUtils for SolKeyComponents { type SigVerification = SolSignature; type AggKey = SolAddress; - type Message = SolLegacyMessage; + type Message = SolVersionedMessage; fn sign(&self, message: &Self::Message) -> Self::SigVerification { self.secret.sign_message(message.serialize().as_slice()) diff --git a/state-chain/cfe-events/src/tests.rs b/state-chain/cfe-events/src/tests.rs index 85a0ed8b69c..6bacacc6287 100644 --- a/state-chain/cfe-events/src/tests.rs +++ b/state-chain/cfe-events/src/tests.rs @@ -8,7 +8,8 @@ use cf_chains::{ evm::{self, Address, ParityBit, H256}, sol::{ sol_tx_core::{CompiledInstruction, MessageHeader}, - RawSolHash, SolLegacyMessage, SolLegacyTransaction, SolPubkey, SolanaTransactionData, + RawSolHash, SolPubkey, SolVersionedMessage, SolVersionedMessageV0, SolVersionedTransaction, + SolanaTransactionData, }, }; use cf_primitives::AccountId; @@ -85,7 +86,7 @@ fn event_decoding() { epoch_index: 2, key: [7u8;32].into(), signatories: participants.clone(), - payload: SolLegacyMessage { + payload: SolVersionedMessage::V0(SolVersionedMessageV0{ header: MessageHeader { num_readonly_signed_accounts: 1, num_readonly_unsigned_accounts: 1, @@ -98,8 +99,9 @@ fn event_decoding() { accounts: vec![0], data: vec![3,4,5,6] }], - } - }), "0d010000000000000002000000070707070707070707070707070707070707070707070707070707070707070708010101010101010101010101010101010101010101010101010101010101010102020202020202020202020202020202020202020202020202020202020202020101010407070707070707070707070707070707070707070707070707070707070707070808080808080808080808080808080808080808080808080808080808080808040104001003040506"); + address_table_lookups: vec![] // TODO roy: add test case with ALT + }) + }), "0d0100000000000000020000000707070707070707070707070707070707070707070707070707070707070707080101010101010101010101010101010101010101010101010101010101010101020202020202020202020202020202020202020202020202020202020202020201010101040707070707070707070707070707070707070707070707070707070707070707080808080808080808080808080808080808080808080808080808080808080804010400100304050600"); } // Keygen requests @@ -179,9 +181,9 @@ fn event_decoding() { check_encoding(CfeEvent::SolTxBroadcastRequest(TxBroadcastRequest { broadcast_id: 1, nominee: AccountId::from([1; 32]), - payload: SolanaTransactionData{ serialized_transaction: (SolLegacyTransaction { + payload: SolanaTransactionData{ serialized_transaction: (SolVersionedTransaction { signatures: vec![[9u8; 64].into()], - message: SolLegacyMessage { + message: SolVersionedMessage::V0( SolVersionedMessageV0 { header: MessageHeader { num_readonly_signed_accounts: 2, num_readonly_unsigned_accounts: 2, @@ -194,11 +196,12 @@ fn event_decoding() { accounts: vec![1], data: vec![31,41,51,61] }], - }, + address_table_lookups: vec![] // TODO roy: add test case with ALT + }), }).finalize_and_serialize().unwrap(), skip_preflight: false, } - }), "0f01000000010101010101010101010101010101010101010101010101010101010101010139020109090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909020202010a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b01020101041f29333d00"); + }), "0f0100000001010101010101010101010101010101010101010101010101010101010101014102010909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090980020202010a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b01020101041f29333d0000"); } // P2P registration/deregistration diff --git a/state-chain/chains/Cargo.toml b/state-chain/chains/Cargo.toml index 76134692708..9799eb0c5f2 100644 --- a/state-chain/chains/Cargo.toml +++ b/state-chain/chains/Cargo.toml @@ -131,4 +131,4 @@ try-runtime = [ "cf-runtime-utilities/try-runtime", ] -runtime-integration-tests = ["std", "dep:rand", "ed25519-dalek/rand_core", "sol-prim/runtime-integration-tests"] +runtime-integration-tests = ["std", "dep:rand", "ed25519-dalek/rand_core",] diff --git a/state-chain/chains/src/arb/api.rs b/state-chain/chains/src/arb/api.rs index f7ea4ec0247..bdfdf3a5dae 100644 --- a/state-chain/chains/src/arb/api.rs +++ b/state-chain/chains/src/arb/api.rs @@ -71,6 +71,7 @@ where gas_budget: GasAmount, message: Vec, _ccm_additional_data: Vec, + _swap_request_id: SwapRequestId, ) -> Result { let transfer_param = EncodableTransferAssetParams { asset: E::token_address(transfer_param.asset) diff --git a/state-chain/chains/src/btc/api.rs b/state-chain/chains/src/btc/api.rs index b17e8032eda..9642e445047 100644 --- a/state-chain/chains/src/btc/api.rs +++ b/state-chain/chains/src/btc/api.rs @@ -142,6 +142,7 @@ impl> ExecutexSwapAndCall for Bitc _gas_budget: GasAmount, _message: Vec, _ccm_additional_data: Vec, + _swap_request_id: SwapRequestId, ) -> Result { Err(ExecutexSwapAndCallError::Unsupported) } diff --git a/state-chain/chains/src/ccm_checker.rs b/state-chain/chains/src/ccm_checker.rs index fdf16f67702..86cdcd7e03b 100644 --- a/state-chain/chains/src/ccm_checker.rs +++ b/state-chain/chains/src/ccm_checker.rs @@ -3,9 +3,9 @@ use crate::{ sol::{ sol_tx_core::consts::{ ACCOUNT_KEY_LENGTH_IN_TRANSACTION, ACCOUNT_REFERENCE_LENGTH_IN_TRANSACTION, - SYSTEM_PROGRAM_ID, SYS_VAR_INSTRUCTIONS, TOKEN_PROGRAM_ID, + MAX_CCM_USER_ALTS, SYSTEM_PROGRAM_ID, SYS_VAR_INSTRUCTIONS, TOKEN_PROGRAM_ID, }, - SolAsset, SolCcmAccounts, SolPubkey, MAX_CCM_BYTES_SOL, MAX_CCM_BYTES_USDC, + SolAddress, SolAsset, SolCcmAccounts, SolPubkey, MAX_CCM_BYTES_SOL, MAX_CCM_BYTES_USDC, }, CcmChannelMetadata, }; @@ -13,7 +13,7 @@ use cf_primitives::{Asset, ForeignChain}; use codec::{Decode, Encode}; use scale_info::TypeInfo; use sp_runtime::DispatchError; -use sp_std::{collections::btree_set::BTreeSet, vec::Vec}; +use sp_std::{collections::btree_set::BTreeSet, vec, vec::Vec}; #[derive(Copy, Clone, Debug, PartialEq, Eq, Encode, Decode, TypeInfo)] pub enum CcmValidityError { @@ -22,6 +22,7 @@ pub enum CcmValidityError { CcmAdditionalDataContainsInvalidAccounts, RedundantDataSupplied, InvalidDestinationAddress, + TooManyAddressLookupTables, } impl From for DispatchError { fn from(value: CcmValidityError) -> Self { @@ -35,6 +36,8 @@ impl From for DispatchError { "Invalid Ccm: Additional data supplied but they will not be used".into(), CcmValidityError::InvalidDestinationAddress => "Invalid Ccm: Destination address is not compatible with the target Chain.".into(), + CcmValidityError::TooManyAddressLookupTables => + "Invalid Ccm: Too many Address Lookup tables supplied".into(), } } } @@ -47,6 +50,13 @@ pub trait CcmValidityCheck { ) -> Result { Ok(DecodedCcmAdditionalData::NotRequired) } + + fn decode_unchecked( + _ccm: &CcmChannelMetadata, + _chain: ForeignChain, + ) -> Result { + Ok(DecodedCcmAdditionalData::NotRequired) + } } #[derive(Clone, Debug, Decode, PartialEq, Eq)] @@ -58,6 +68,23 @@ pub enum DecodedCcmAdditionalData { #[derive(Clone, Debug, Encode, Decode, PartialEq, Eq)] pub enum VersionedSolanaCcmAdditionalData { V0(SolCcmAccounts), + V1 { ccm_accounts: SolCcmAccounts, alts: Vec }, +} + +impl VersionedSolanaCcmAdditionalData { + pub fn ccm_accounts(&self) -> SolCcmAccounts { + match self { + VersionedSolanaCcmAdditionalData::V0(ccm_accounts) => ccm_accounts.clone(), + VersionedSolanaCcmAdditionalData::V1 { ccm_accounts, .. } => ccm_accounts.clone(), + } + } + + pub fn address_lookup_tables(&self) -> Vec { + match self { + VersionedSolanaCcmAdditionalData::V0(..) => vec![], + VersionedSolanaCcmAdditionalData::V1 { alts, .. } => alts.clone(), + } + } } pub struct CcmValidityChecker; @@ -80,67 +107,80 @@ impl CcmValidityCheck for CcmValidityChecker { .expect("Only Solana chain's asset will be checked. This conversion must succeed."); // Check if the cf_parameter can be decoded - match VersionedSolanaCcmAdditionalData::decode( - &mut &ccm.ccm_additional_data.clone()[..], - ) - .map_err(|_| CcmValidityError::CannotDecodeCcmAdditionalData)? - { - VersionedSolanaCcmAdditionalData::V0(ccm_accounts) => { - // It's hard at this stage to compute exactly the length of the finally build - // transaction from the message and the additional accounts. Duplicated - // accounts only take one reference byte while new accounts take 32 bytes. - // Technically it shouldn't be necessary to pass duplicated accounts as - // it will all be executed in the same instruction. However when integrating - // with other protocols, many of the account's values are part of a returned - // payload from an API and it makes it cumbersome to then dedpulicate on the - // fly and then make it match with the receiver contract. It can be done - // but it then requires extra configuration bytes in the payload, which - // then defeats the purpose. - // Therefore we want to allow for duplicated accounts, both duplicated - // within the additional accounts and with our accounts. Then we can - // calculate the length accordingly. - // The Chainflip accounts are anyway irrelevant to the user except for a - // few that are acounted for here. The only relevant is the token - let mut seen_addresses = BTreeSet::from_iter([ - SYSTEM_PROGRAM_ID, - SYS_VAR_INSTRUCTIONS, - destination_address.into(), - ccm_accounts.cf_receiver.pubkey.into(), - ]); - - if asset == SolAsset::SolUsdc { - seen_addresses.insert(TOKEN_PROGRAM_ID); - } - let mut accounts_length = ccm_accounts.additional_accounts.len() * - ACCOUNT_REFERENCE_LENGTH_IN_TRANSACTION; - - for ccm_address in &ccm_accounts.additional_accounts { - if seen_addresses.insert(ccm_address.pubkey.into()) { - accounts_length += ACCOUNT_KEY_LENGTH_IN_TRANSACTION; - } - } - - let ccm_length = ccm.message.len() + accounts_length; - - if ccm_length > - match asset { - SolAsset::Sol => MAX_CCM_BYTES_SOL, - SolAsset::SolUsdc => MAX_CCM_BYTES_USDC, - } { - return Err(CcmValidityError::CcmIsTooLong) - } - - Ok(DecodedCcmAdditionalData::Solana(VersionedSolanaCcmAdditionalData::V0( - ccm_accounts, - ))) - }, + let decoded_data = + VersionedSolanaCcmAdditionalData::decode(&mut &ccm.ccm_additional_data.clone()[..]) + .map_err(|_| CcmValidityError::CannotDecodeCcmAdditionalData)?; + + let ccm_accounts = decoded_data.ccm_accounts(); + + // It's hard at this stage to compute exactly the length of the finally build + // transaction from the message and the additional accounts. Duplicated + // accounts only take one reference byte while new accounts take 32 bytes. + // Technically it shouldn't be necessary to pass duplicated accounts as + // it will all be executed in the same instruction. However when integrating + // with other protocols, many of the account's values are part of a returned + // payload from an API and it makes it cumbersome to then deduplicate on the + // fly and then make it match with the receiver contract. It can be done + // but it then requires extra configuration bytes in the payload, which + // then defeats the purpose. + // Therefore we want to allow for duplicated accounts, both duplicated + // within the additional accounts and with our accounts. Then we can + // calculate the length accordingly. + // The Chainflip accounts are irrelevant to the user except for a + // few that are accounted for here. + let mut seen_addresses = BTreeSet::from_iter([ + SYSTEM_PROGRAM_ID, + SYS_VAR_INSTRUCTIONS, + destination_address.into(), + ccm_accounts.cf_receiver.pubkey.into(), + ]); + + if asset == SolAsset::SolUsdc { + seen_addresses.insert(TOKEN_PROGRAM_ID); + } + let mut accounts_length = + ccm_accounts.additional_accounts.len() * ACCOUNT_REFERENCE_LENGTH_IN_TRANSACTION; + + for ccm_address in &ccm_accounts.additional_accounts { + if seen_addresses.insert(ccm_address.pubkey.into()) { + accounts_length += ACCOUNT_KEY_LENGTH_IN_TRANSACTION; + } + } + + let ccm_length = ccm.message.len() + accounts_length; + + if ccm_length > + match asset { + SolAsset::Sol => MAX_CCM_BYTES_SOL, + SolAsset::SolUsdc => MAX_CCM_BYTES_USDC, + } { + return Err(CcmValidityError::CcmIsTooLong) + } + + if decoded_data.address_lookup_tables().len() > MAX_CCM_USER_ALTS as usize { + return Err(CcmValidityError::TooManyAddressLookupTables) } + + Ok(DecodedCcmAdditionalData::Solana(decoded_data)) } else if !ccm.ccm_additional_data.is_empty() { Err(CcmValidityError::RedundantDataSupplied) } else { Ok(DecodedCcmAdditionalData::NotRequired) } } + + fn decode_unchecked( + ccm: &CcmChannelMetadata, + chain: ForeignChain, + ) -> Result { + if chain == ForeignChain::Solana { + VersionedSolanaCcmAdditionalData::decode(&mut &ccm.ccm_additional_data.clone()[..]) + .map(DecodedCcmAdditionalData::Solana) + .map_err(|_| CcmValidityError::CannotDecodeCcmAdditionalData) + } else { + Ok(DecodedCcmAdditionalData::NotRequired) + } + } } /// Checks if the given CCM accounts contains any blacklisted accounts. @@ -166,7 +206,10 @@ mod test { use Asset; use super::*; - use crate::sol::{sol_tx_core::sol_test_values, SolCcmAddress, SolPubkey, MAX_CCM_BYTES_SOL}; + use crate::sol::{ + sol_tx_core::sol_test_values::{self, ccm_accounts, ccm_parameter_v1, user_alt}, + SolCcmAddress, SolPubkey, MAX_CCM_BYTES_SOL, + }; pub const DEST_ADDR: EncodedAddress = EncodedAddress::Sol([0x00; 32]); pub const MOCK_ADDR: SolPubkey = SolPubkey([0x01; 32]); @@ -381,7 +424,7 @@ mod test { pubkey: sol_test_values::TOKEN_VAULT_PDA_ACCOUNT.into(), is_writable: false, }, - SolCcmAddress { pubkey: crate::sol::SolPubkey([0x02; 32]), is_writable: false }, + SolCcmAddress { pubkey: SolPubkey([0x02; 32]), is_writable: false }, ], fallback_address: FALLBACK_ADDR, }; @@ -398,7 +441,7 @@ mod test { }, additional_accounts: vec![ SolCcmAddress { pubkey: MOCK_ADDR, is_writable: false }, - SolCcmAddress { pubkey: crate::sol::SolPubkey([0x02; 32]), is_writable: false }, + SolCcmAddress { pubkey: SolPubkey([0x02; 32]), is_writable: false }, ], fallback_address: FALLBACK_ADDR, }; @@ -411,7 +454,7 @@ mod test { cf_receiver: SolCcmAddress { pubkey: CF_RECEIVER_ADDR, is_writable: true }, additional_accounts: vec![ SolCcmAddress { pubkey: sol_test_values::agg_key().into(), is_writable: false }, - SolCcmAddress { pubkey: crate::sol::SolPubkey([0x02; 32]), is_writable: false }, + SolCcmAddress { pubkey: SolPubkey([0x02; 32]), is_writable: false }, ], fallback_address: FALLBACK_ADDR, }; @@ -549,4 +592,68 @@ mod test { Err(CcmValidityError::InvalidDestinationAddress) ); } + + #[test] + fn can_decode_unchecked() { + let ccm = sol_test_values::ccm_parameter().channel_metadata; + assert_ok!(CcmValidityChecker::decode_unchecked(&ccm, ForeignChain::Solana)); + assert_eq!( + CcmValidityChecker::decode_unchecked(&ccm, ForeignChain::Ethereum), + Ok(DecodedCcmAdditionalData::NotRequired) + ); + } + + #[test] + fn can_decode_unchecked_ccm_v1() { + let ccm = sol_test_values::ccm_parameter_v1().channel_metadata; + assert_ok!(CcmValidityChecker::decode_unchecked(&ccm, ForeignChain::Solana)); + assert_eq!( + CcmValidityChecker::decode_unchecked(&ccm, ForeignChain::Ethereum), + Ok(DecodedCcmAdditionalData::NotRequired) + ); + } + + #[test] + fn additional_data_v1_support_works() { + let mut ccm = sol_test_values::ccm_parameter_v1().channel_metadata; + assert_eq!( + CcmValidityChecker::check_and_decode(&ccm, Asset::Sol, DEST_ADDR), + Ok(DecodedCcmAdditionalData::Solana(VersionedSolanaCcmAdditionalData::V1 { + ccm_accounts: sol_test_values::ccm_accounts(), + alts: vec![user_alt().key.into()], + })) + ); + + assert_eq!( + CcmValidityChecker::check_and_decode(&ccm, Asset::Eth, DEST_ADDR), + Err(CcmValidityError::RedundantDataSupplied) + ); + + ccm.ccm_additional_data.clear(); + assert_eq!( + CcmValidityChecker::check_and_decode(&ccm, Asset::Eth, DEST_ADDR), + Ok(DecodedCcmAdditionalData::NotRequired) + ); + + assert_eq!( + CcmValidityChecker::check_and_decode(&ccm, Asset::Sol, INVALID_DEST_ADDR), + Err(CcmValidityError::InvalidDestinationAddress) + ); + } + + #[test] + fn can_check_for_too_many_alts() { + let mut ccm = ccm_parameter_v1().channel_metadata; + ccm.ccm_additional_data = codec::Encode::encode(&VersionedSolanaCcmAdditionalData::V1 { + ccm_accounts: ccm_accounts(), + alts: (0..=MAX_CCM_USER_ALTS).map(|i| SolAddress([i; 32])).collect(), + }) + .try_into() + .unwrap(); + + assert_eq!( + CcmValidityChecker::check_and_decode(&ccm, Asset::Sol, DEST_ADDR), + Err(CcmValidityError::TooManyAddressLookupTables) + ); + } } diff --git a/state-chain/chains/src/dot/api.rs b/state-chain/chains/src/dot/api.rs index 6193e963c12..cd97f2ebe5e 100644 --- a/state-chain/chains/src/dot/api.rs +++ b/state-chain/chains/src/dot/api.rs @@ -129,6 +129,7 @@ where _gas_budget: GasAmount, _message: Vec, _ccm_additional_data: Vec, + _swap_request_id: SwapRequestId, ) -> Result { Err(ExecutexSwapAndCallError::Unsupported) } diff --git a/state-chain/chains/src/eth/api.rs b/state-chain/chains/src/eth/api.rs index 2acfbaf6225..e4ec3bd767e 100644 --- a/state-chain/chains/src/eth/api.rs +++ b/state-chain/chains/src/eth/api.rs @@ -195,6 +195,7 @@ where gas_budget: GasAmount, message: Vec, _ccm_additional_data: Vec, + _swap_request_id: SwapRequestId, ) -> Result { let transfer_param = EncodableTransferAssetParams { asset: E::token_address(transfer_param.asset) diff --git a/state-chain/chains/src/lib.rs b/state-chain/chains/src/lib.rs index eb16c99190e..509ca522811 100644 --- a/state-chain/chains/src/lib.rs +++ b/state-chain/chains/src/lib.rs @@ -25,7 +25,8 @@ use address::{ }; use cf_amm_math::Price; use cf_primitives::{ - AssetAmount, BlockNumber, BroadcastId, ChannelId, EgressId, EthAmount, GasAmount, TxId, + AssetAmount, BlockNumber, BroadcastId, ChannelId, EgressId, EthAmount, GasAmount, + SwapRequestId, TxId, }; use codec::{Decode, Encode, FullCodec, MaxEncodedLen}; use frame_support::{ @@ -590,6 +591,7 @@ pub trait ExecutexSwapAndCall: ApiCall { gas_budget: GasAmount, message: Vec, ccm_additional_data: Vec, + swap_request_id: SwapRequestId, ) -> Result; } diff --git a/state-chain/chains/src/sol.rs b/state-chain/chains/src/sol.rs index cb847c9cf6d..607f41513b7 100644 --- a/state-chain/chains/src/sol.rs +++ b/state-chain/chains/src/sol.rs @@ -32,12 +32,14 @@ pub use sol_prim::{ TOKEN_ACCOUNT_RENT, }, pda::{Pda as DerivedAddressBuilder, PdaError as AddressDerivationError}, - transaction::legacy::{ - LegacyMessage as SolLegacyMessage, LegacyTransaction as SolLegacyTransaction, + transaction::{ + v0::VersionedMessageV0 as SolVersionedMessageV0, VersionedMessage as SolVersionedMessage, + VersionedTransaction as SolVersionedTransaction, }, - Address as SolAddress, Amount as SolAmount, ComputeLimit as SolComputeLimit, Digest as SolHash, - Hash as RawSolHash, Instruction as SolInstruction, InstructionRpc as SolInstructionRpc, - Pubkey as SolPubkey, Signature as SolSignature, SlotNumber as SolBlockNumber, + Address as SolAddress, AddressLookupTableAccount as SolAddressLookupTableAccount, + Amount as SolAmount, ComputeLimit as SolComputeLimit, Digest as SolHash, Hash as RawSolHash, + Instruction as SolInstruction, InstructionRpc as SolInstructionRpc, Pubkey as SolPubkey, + Signature as SolSignature, SlotNumber as SolBlockNumber, }; pub use sol_tx_core::{ rpc_types, AccountMeta as SolAccountMeta, CcmAccounts as SolCcmAccounts, @@ -107,7 +109,7 @@ impl ChainCrypto for SolanaCrypto { type KeyHandoverIsRequired = ConstBool; type AggKey = SolAddress; - type Payload = SolLegacyMessage; + type Payload = SolVersionedMessage; type ThresholdSignature = SolSignature; type TransactionInId = SolanaTransactionInId; type TransactionOutId = Self::ThresholdSignature; @@ -130,7 +132,7 @@ impl ChainCrypto for SolanaCrypto { } fn agg_key_to_payload(agg_key: Self::AggKey, _for_handover: bool) -> Self::Payload { - SolLegacyMessage::new(&[], Some(&SolPubkey::from(agg_key))) + SolVersionedMessage::new(&[], Some(SolPubkey::from(agg_key)), None, &[]) } fn maybe_broadcast_barriers_on_rotation( diff --git a/state-chain/chains/src/sol/api.rs b/state-chain/chains/src/sol/api.rs index 491f735fd50..de1085de940 100644 --- a/state-chain/chains/src/sol/api.rs +++ b/state-chain/chains/src/sol/api.rs @@ -11,15 +11,15 @@ use sp_std::{vec, vec::Vec}; use crate::{ ccm_checker::{ check_ccm_for_blacklisted_accounts, CcmValidityCheck, CcmValidityChecker, CcmValidityError, - DecodedCcmAdditionalData, VersionedSolanaCcmAdditionalData, + DecodedCcmAdditionalData, }, sol::{ sol_tx_core::{ address_derivation::derive_associated_token_account, consts::SOL_USDC_DECIMAL, }, transaction_builder::SolanaTransactionBuilder, - SolAddress, SolAmount, SolApiEnvironment, SolAsset, SolHash, SolLegacyTransaction, - SolTrackedData, SolanaCrypto, + SolAddress, SolAddressLookupTableAccount, SolAmount, SolApiEnvironment, SolAsset, SolHash, + SolTrackedData, SolVersionedTransaction, SolanaCrypto, }, AllBatch, AllBatchError, ApiCall, CcmChannelMetadata, ChainCrypto, ChainEnvironment, ConsolidateCall, ConsolidationError, ExecutexSwapAndCall, ExecutexSwapAndCallError, @@ -28,7 +28,7 @@ use crate::{ TransferFallbackError, }; -use cf_primitives::{EgressId, ForeignChain, GasAmount}; +use cf_primitives::{EgressId, ForeignChain, GasAmount, SwapRequestId}; #[derive(Clone, Encode, Decode, PartialEq, Debug, TypeInfo)] pub struct ComputePrice; @@ -42,6 +42,10 @@ pub struct ApiEnvironment; pub struct CurrentAggKey; #[derive(Clone, Encode, Decode, PartialEq, Debug, TypeInfo)] pub struct CurrentOnChainKey; +#[derive(Clone, Encode, Decode, PartialEq, Debug, TypeInfo)] +pub struct SolanaAddressLookupTables(pub SwapRequestId); +#[derive(Clone, Encode, Decode, PartialEq, Debug, TypeInfo)] +pub struct ChainflipAddressLookupTable; pub type DurableNonceAndAccount = (SolAddress, SolHash); @@ -73,6 +77,8 @@ pub trait SolanaEnvironment: + ChainEnvironment + ChainEnvironment + ChainEnvironment> + + ChainEnvironment> + + ChainEnvironment + RecoverDurableNonce { fn compute_price() -> Result { @@ -103,6 +109,20 @@ pub trait SolanaEnvironment: .map(|nonces| nonces.into_iter().map(|(addr, _hash)| addr).collect::>()) .ok_or(SolanaTransactionBuildingError::NoNonceAccountsSet) } + + /// Get all relevant Address lookup tables from the Environment. + /// Returns Chainflip's ALT proceeded with user's ALTs. + fn get_address_lookup_tables(id: Option) -> Vec { + let mut alts = Self::get_cf_address_lookup_table().map(|alt| vec![alt]).unwrap_or_default(); + if let Some(id) = id { + alts.extend(Self::lookup(SolanaAddressLookupTables(id)).unwrap_or_default()); + } + alts + } + + fn get_cf_address_lookup_table() -> Option { + Self::lookup(ChainflipAddressLookupTable) + } } /// IMPORTANT: This should only be used if the nonce has not been used to sign a transaction. @@ -162,7 +182,7 @@ pub enum SolanaTransactionType { #[scale_info(skip_type_params(Environment))] pub struct SolanaApi { pub call_type: SolanaTransactionType, - pub transaction: SolLegacyTransaction, + pub transaction: SolVersionedTransaction, pub signer: Option, #[doc(hidden)] #[codec(skip)] @@ -228,6 +248,7 @@ impl SolanaApi { let sol_api_environment = Environment::api_environment()?; let compute_price = Environment::compute_price()?; let durable_nonce = Environment::nonce_account()?; + let address_lookup_tables = Environment::get_address_lookup_tables(None); // Build the transaction let transaction = SolanaTransactionBuilder::fetch_from( @@ -236,6 +257,7 @@ impl SolanaApi { agg_key, durable_nonce, compute_price, + address_lookup_tables, )?; Ok(Self { @@ -253,6 +275,7 @@ impl SolanaApi { let agg_key = Environment::current_agg_key()?; let sol_api_environment = Environment::api_environment()?; let compute_price = Environment::compute_price()?; + let address_lookup_tables = Environment::get_address_lookup_tables(None); transfer_params .into_iter() @@ -285,6 +308,7 @@ impl SolanaApi { durable_nonce, compute_price, SOL_USDC_DECIMAL, + address_lookup_tables.clone(), ) }, }?; @@ -309,6 +333,7 @@ impl SolanaApi { let nonce_accounts = Environment::all_nonce_accounts()?; let compute_price = Environment::compute_price()?; let durable_nonce = Environment::nonce_account()?; + let address_lookup_tables = Environment::get_address_lookup_tables(None); // Build the transaction let transaction = SolanaTransactionBuilder::rotate_agg_key( @@ -319,6 +344,7 @@ impl SolanaApi { agg_key, durable_nonce, compute_price, + address_lookup_tables, ) .inspect_err(|e| { // Vault Rotation call building NOT transactional - meaning when this fails, @@ -350,6 +376,7 @@ impl SolanaApi { gas_budget: GasAmount, message: Vec, ccm_additional_data: Vec, + swap_request_id: SwapRequestId, ) -> Result { // For extra safety, re-verify the validity of the CCM message here // and extract the decoded `ccm_accounts` from `ccm_additional_data`. @@ -375,9 +402,7 @@ impl SolanaApi { let ccm_accounts = if let DecodedCcmAdditionalData::Solana(versioned_sol_data) = decoded_ccm_additional_data { - match versioned_sol_data { - VersionedSolanaCcmAdditionalData::V0(ccm_accounts) => Ok(ccm_accounts), - } + Ok(versioned_sol_data.ccm_accounts()) } else { Err(SolanaTransactionBuildingError::InvalidCcm( CcmValidityError::CannotDecodeCcmAdditionalData, @@ -386,6 +411,8 @@ impl SolanaApi { let sol_api_environment = Environment::api_environment()?; let agg_key = Environment::current_agg_key()?; + // TODO roy: Coordinate with Ramiz on the interface for getting ALTS + let address_lookup_tables = Environment::get_address_lookup_tables(Some(swap_request_id)); // Ensure the CCM parameters do not contain blacklisted accounts. check_ccm_for_blacklisted_accounts( @@ -421,6 +448,7 @@ impl SolanaApi { durable_nonce, compute_price, compute_limit, + address_lookup_tables, ), SolAsset::SolUsdc => { let ata = derive_associated_token_account( @@ -447,6 +475,7 @@ impl SolanaApi { compute_price, SOL_USDC_DECIMAL, compute_limit, + address_lookup_tables, ) }, } @@ -481,6 +510,7 @@ impl SolanaApi { let sol_api_environment = Environment::api_environment()?; let compute_price = Environment::compute_price()?; let durable_nonce = Environment::nonce_account()?; + let address_lookup_tables = Environment::get_address_lookup_tables(None); // Build the transaction let transaction = SolanaTransactionBuilder::fetch_and_close_vault_swap_accounts( @@ -491,6 +521,7 @@ impl SolanaApi { agg_key, durable_nonce, compute_price, + address_lookup_tables, )?; Ok(Self { @@ -513,6 +544,7 @@ impl SolanaApi { let sol_api_environment = Environment::api_environment()?; let compute_price = Environment::compute_price()?; let durable_nonce = Environment::nonce_account()?; + let address_lookup_tables = Environment::get_address_lookup_tables(None); // Build the transaction let transaction = SolanaTransactionBuilder::set_program_swaps_parameters( @@ -528,6 +560,7 @@ impl SolanaApi { agg_key, durable_nonce, compute_price, + address_lookup_tables, )?; Ok(Self { @@ -546,6 +579,7 @@ impl SolanaApi { let sol_api_environment = Environment::api_environment()?; let compute_price = Environment::compute_price()?; let durable_nonce = Environment::nonce_account()?; + let address_lookup_tables = Environment::get_address_lookup_tables(None); // Build the transaction let transaction = SolanaTransactionBuilder::enable_token_support( @@ -558,6 +592,7 @@ impl SolanaApi { agg_key, durable_nonce, compute_price, + address_lookup_tables, )?; Ok(Self { @@ -638,6 +673,7 @@ impl ExecutexSwapAndCall for SolanaApi gas_budget: GasAmount, message: Vec, ccm_additional_data: Vec, + swap_request_id: SwapRequestId, ) -> Result { Self::ccm_transfer( transfer_param, @@ -648,6 +684,7 @@ impl ExecutexSwapAndCall for SolanaApi gas_budget, message, ccm_additional_data, + swap_request_id, ) .map_err(|e| { log::error!("Failed to construct Solana CCM transfer transaction! \nError: {:?}", e); @@ -697,6 +734,7 @@ impl SetGovKeyWithAggKey for Solan let sol_api_environment = Environment::api_environment().map_err(|_e| ())?; let compute_price = Environment::compute_price().map_err(|_e| ())?; let durable_nonce = Environment::nonce_account().map_err(|_e| ())?; + let address_lookup_tables = Environment::get_address_lookup_tables(None); // Build the transaction let transaction = SolanaTransactionBuilder::set_gov_key_with_agg_key( @@ -706,6 +744,7 @@ impl SetGovKeyWithAggKey for Solan agg_key, durable_nonce, compute_price, + address_lookup_tables, ) .map_err(|e| { // SetGovKeyWithAggKey call building NOT transactional - meaning when this fails, diff --git a/state-chain/chains/src/sol/benchmarking.rs b/state-chain/chains/src/sol/benchmarking.rs index 847b937d6fa..a9ba3fef24e 100644 --- a/state-chain/chains/src/sol/benchmarking.rs +++ b/state-chain/chains/src/sol/benchmarking.rs @@ -2,8 +2,8 @@ use super::{ api::{SolanaApi, VaultSwapAccountAndSender}, - SolAddress, SolHash, SolLegacyMessage, SolLegacyTransaction, SolSignature, SolTrackedData, - SolanaTransactionData, + SolAddress, SolHash, SolSignature, SolTrackedData, SolVersionedMessage, + SolVersionedTransaction, SolanaTransactionData, }; use crate::benchmarking_value::{BenchmarkValue, BenchmarkValueExtended}; @@ -26,22 +26,22 @@ impl BenchmarkValue for SolTrackedData { } } -impl BenchmarkValue for SolLegacyMessage { +impl BenchmarkValue for SolVersionedMessage { fn benchmark_value() -> Self { - Self::new_with_blockhash(&[], None, &SolHash::default().into()) + Self::new(&[], None, None, &[]) } } -impl BenchmarkValue for SolLegacyTransaction { +impl BenchmarkValue for SolVersionedTransaction { fn benchmark_value() -> Self { - SolLegacyTransaction::new_unsigned(SolLegacyMessage::benchmark_value()) + SolVersionedTransaction::new_unsigned(SolVersionedMessage::benchmark_value()) } } impl BenchmarkValue for SolanaTransactionData { fn benchmark_value() -> Self { SolanaTransactionData { - serialized_transaction: SolLegacyTransaction::benchmark_value() + serialized_transaction: SolVersionedTransaction::benchmark_value() .finalize_and_serialize() .expect("Failed to serialize payload"), skip_preflight: false, diff --git a/state-chain/chains/src/sol/instruction_builder.rs b/state-chain/chains/src/sol/instruction_builder.rs index 7e9589beb97..a55c3a80a96 100644 --- a/state-chain/chains/src/sol/instruction_builder.rs +++ b/state-chain/chains/src/sol/instruction_builder.rs @@ -108,7 +108,8 @@ mod test { consts::{const_address, MAX_TRANSACTION_LENGTH}, sol_test_values::*, }, - SolAddress, SolHash, SolLegacyMessage, SolLegacyTransaction, + SolAddress, SolAddressLookupTableAccount, SolHash, SolVersionedMessage, + SolVersionedTransaction, }, ChannelRefundParameters, }; @@ -200,11 +201,17 @@ mod test { ) } - fn into_transaction(instructions: SolInstruction, payer: SolPubkey) -> SolLegacyTransaction { + fn into_transaction( + instructions: SolInstruction, + payer: SolPubkey, + alt: &[SolAddressLookupTableAccount], + ) -> SolVersionedTransaction { // Build mock Transaction for testing. - let transaction = SolLegacyTransaction::new_unsigned(SolLegacyMessage::new( + let transaction = SolVersionedTransaction::new_unsigned(SolVersionedMessage::new( &[instructions], - Some(&payer), + Some(payer), + Default::default(), + alt, )); let mock_serialized_tx = transaction @@ -235,9 +242,10 @@ mod test { None, ), FROM.into(), + &[chainflip_alt()], ); - let expected_serialized_tx = hex_literal::hex!("021d485a1e6df1d3b4dcee7f4c1442443d61c33ba047556e5461cfa14fdccf7eb4b16b1bfad0428704b01dc85e46ac29f19a8f4e82620c6c6cc87cc1a1e5fb1908baa3bed94d223389107f6fff96ce9b85d646ab64f95394f6d4be7455f27571030edc6746ed42c9b8a16abdfd6efc4fbc7e1df5c8f9fc24e5b7ff3ccd8ca0ca0c02000307cf2a079e1506b29d02c8feac98d589a9059a740891dcd3dab6c64b3160bc28317f799121d6c125f312c5f423a51959ce1d41df06af977e9a17f48b2c82ecf89f1c1f0efc91eeb48bb80c90cf97775cd5d843a96f16500266cee2c20d053152d2f79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb00000000000000000000000000000000000000000000000000000000000000001ef91c791d2aa8492c90f12540abd10056ce5dd8d9ab08461476c1dcc1622938a1e031c8bc9bec3b610cf7b36eb3bf3aa40237c9e5be2c7893878578439eb00b0000000000000000000000000000000000000000000000000000000000000000010506060300010204ab01a3265ce2f3698dc4d2029649000000000100000014000000756fbde9c71eae05c2f7169f816b0bd11d978020010000000076000000000a0000009e0d6a70e12d54edf90971cc977fa26a1d3bb4b0b26e72470171c36b0006b01f0000000000000000000000000000000000000000000000000000000000000000010a0000001400000002a0edda1a4beee4fe2df32c0802aa6759da49ae6165fcdb5c40d7f4cd5a30db0e010008010a0214").to_vec(); + let expected_serialized_tx = hex_literal::hex!("02297de611719580c43ee59d349f18af1da21fae4c8ed8535b0a6c18281d2cfc8cfb581371896ef2dc3999807e3107889bb2d2f7f7bdf0c291ce0325810b92d70e13ea28637448af5bf7343305cbd6835e1f979307180405573f05ff4b11265e378b5a814166c66600029a78b0eb631d566cddf525a921a40fd7d70d1b70547b088002000205cf2a079e1506b29d02c8feac98d589a9059a740891dcd3dab6c64b3160bc28317f799121d6c125f312c5f423a51959ce1d41df06af977e9a17f48b2c82ecf89ff79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb00000000000000000000000000000000000000000000000000000000000000001ef91c791d2aa8492c90f12540abd10056ce5dd8d9ab08461476c1dcc16229380000000000000000000000000000000000000000000000000000000000000000010406060200010503ab01a3265ce2f3698dc4d2029649000000000100000014000000756fbde9c71eae05c2f7169f816b0bd11d978020010000000076000000000a0000009e0d6a70e12d54edf90971cc977fa26a1d3bb4b0b26e72470171c36b0006b01f0000000000000000000000000000000000000000000000000000000000000000010a0000001400000002a0edda1a4beee4fe2df32c0802aa6759da49ae6165fcdb5c40d7f4cd5a30db0e010008010a0214013001afd71da9456a977233960b08eba77d2e3690b8c7259637c8fb8f82cf58a101080102").to_vec(); let from_signing_key = SolSigningKey::from_bytes(&FROM_KEY_BYTES).unwrap(); let event_data_account_signing_key = @@ -266,9 +274,10 @@ mod test { Some(ccm_parameter().channel_metadata), ), FROM.into(), + &[chainflip_alt()], ); - let expected_serialized_tx = hex_literal::hex!("026b0befc47440952c815d5c94691b3ffab988b83e02ee74731b420cf1e572d8f06774330f43a7639528aa004435e10ec49accee16bd3cb73733a502d61fb10e07d4b8cbf900562ab1f613d70be1b28142c869c3d47bfacb6742dd50fa61e6820ce4ec8f10b2a2f330fdd0a351935fecd850323123223af2acb8bbed4b7e86970102000307cf2a079e1506b29d02c8feac98d589a9059a740891dcd3dab6c64b3160bc28317f799121d6c125f312c5f423a51959ce1d41df06af977e9a17f48b2c82ecf89f1c1f0efc91eeb48bb80c90cf97775cd5d843a96f16500266cee2c20d053152d2f79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb00000000000000000000000000000000000000000000000000000000000000001ef91c791d2aa8492c90f12540abd10056ce5dd8d9ab08461476c1dcc1622938a1e031c8bc9bec3b610cf7b36eb3bf3aa40237c9e5be2c7893878578439eb00b0000000000000000000000000000000000000000000000000000000000000000010506060300010204ad02a3265ce2f3698dc4d20296490000000005000000200000009e0d6a70e12d54edf90971cc977fa26a1d3bb4b0b26e72470171c36b0006b01f0a00000001040000007c1d0f070000000000000000dc000000009101007417da8b99d7748127a76b03d61fee69c80dfef73ad2d5503737beedc5a9ed480104a73bdf31e341218a693b8772c43ecfcecd4cf35fada09a87ea0f860d028168e50090e0b0f5b60147b325842c1fc68f6c90fe26419ea7c4afeb982f71f1f54b5b440a0000009e0d6a70e12d54edf90971cc977fa26a1d3bb4b0b26e72470171c36b0006b01f0000000000000000000000000000000000000000000000000000000000000000010a0000001400000002a0edda1a4beee4fe2df32c0802aa6759da49ae6165fcdb5c40d7f4cd5a30db0e010008010a0214").to_vec(); + let expected_serialized_tx = hex_literal::hex!("029269e0d838f8c7dc39ab8c07c8cdfbf2fd1e09bd6a2d6a91b4be880d699717300c518011cb85822c288016b688177bc3ab7a72809921992e10d081c3dcb4740ed419659340a7ce633192081233b8df64e4689ea25f4cf9ebe9260a27950d1761b7b88d62376f01fecf8f96ea1ca9e7a323ca38f7b60020d1964d246f4da6c3078002000205cf2a079e1506b29d02c8feac98d589a9059a740891dcd3dab6c64b3160bc28317f799121d6c125f312c5f423a51959ce1d41df06af977e9a17f48b2c82ecf89ff79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb00000000000000000000000000000000000000000000000000000000000000001ef91c791d2aa8492c90f12540abd10056ce5dd8d9ab08461476c1dcc16229380000000000000000000000000000000000000000000000000000000000000000010406060200010503ad02a3265ce2f3698dc4d20296490000000005000000200000009e0d6a70e12d54edf90971cc977fa26a1d3bb4b0b26e72470171c36b0006b01f0a00000001040000007c1d0f070000000000000000dc000000009101007417da8b99d7748127a76b03d61fee69c80dfef73ad2d5503737beedc5a9ed480104a73bdf31e341218a693b8772c43ecfcecd4cf35fada09a87ea0f860d028168e50090e0b0f5b60147b325842c1fc68f6c90fe26419ea7c4afeb982f71f1f54b5b440a0000009e0d6a70e12d54edf90971cc977fa26a1d3bb4b0b26e72470171c36b0006b01f0000000000000000000000000000000000000000000000000000000000000000010a0000001400000002a0edda1a4beee4fe2df32c0802aa6759da49ae6165fcdb5c40d7f4cd5a30db0e010008010a0214013001afd71da9456a977233960b08eba77d2e3690b8c7259637c8fb8f82cf58a101080102").to_vec(); let from_signing_key = SolSigningKey::from_bytes(&FROM_KEY_BYTES).unwrap(); let event_data_account_signing_key = @@ -307,9 +316,10 @@ mod test { None, ), FROM.into(), + &[chainflip_alt()], ); - let expected_serialized_tx = hex_literal::hex!("02d546874a4fc16d7c369ea5eb86a3344c3bdeda58b0721de0c2c5a372b455d565232421d5ceabb4782dd2fb23cac7812ef1836032b65afc823094b56d01500201bcc4d183f10ae173e8f7b1fe9fcd8fc2297b4aab8ed58a5d220877dbbbeecedaab2a1d913e1ad6870245e8ed9b4ee0ea1e2f4cb948bf0143defede95c83aa8040200060bcf2a079e1506b29d02c8feac98d589a9059a740891dcd3dab6c64b3160bc28317f799121d6c125f312c5f423a51959ce1d41df06af977e9a17f48b2c82ecf89f1c1f0efc91eeb48bb80c90cf97775cd5d843a96f16500266cee2c20d053152d227fefc7ec198ef3eacb0f17871e1fad81f07a40cd55f4f364c3915877d89bd8ae91372b3d301c202a633da0a92365a736e462131aecfad1fac47322cf8863ada000000000000000000000000000000000000000000000000000000000000000006ddf6e1d765a193d9cbe146ceeb79ac1cb485ed5f5b37913a8cf5857eff00a90fb9ba52b1f09445f1e3a7508d59f0797923acf744fbe2da303fb06da859ee871ef91c791d2aa8492c90f12540abd10056ce5dd8d9ab08461476c1dcc16229382e9acf1ff8568fbe655e616a167591aeedc250afbc88d759ec959b1982e8769ca1e031c8bc9bec3b610cf7b36eb3bf3aa40237c9e5be2c7893878578439eb00b000000000000000000000000000000000000000000000000000000000000000001080a0a040003010209060705ac014532fc63e55377ebd2029649000000000100000014000000756fbde9c71eae05c2f7169f816b0bd11d978020010000000076000000000a0000009e0d6a70e12d54edf90971cc977fa26a1d3bb4b0b26e72470171c36b0006b01f0000000000000000000000000000000000000000000000000000000000000000010a0000001400000002a0edda1a4beee4fe2df32c0802aa6759da49ae6165fcdb5c40d7f4cd5a30db0e010008010a021406").to_vec(); + let expected_serialized_tx = hex_literal::hex!("02e958c1c2694aae31d25837e9b7a36b24e5c14fc2d4132f47e9b92ba7d9d888c7c8647e708686dfccdf365859c7962e30083f4f6568a7f8386980303ee314f00e48f7405e65de9a542320c386db554ca40850614d3aa764cf9d2c82e68f976b15af8a4960b457b5808280e3fc72ae8e19a197de42e56431d9c3ac5b16801884068002000407cf2a079e1506b29d02c8feac98d589a9059a740891dcd3dab6c64b3160bc28317f799121d6c125f312c5f423a51959ce1d41df06af977e9a17f48b2c82ecf89f27fefc7ec198ef3eacb0f17871e1fad81f07a40cd55f4f364c3915877d89bd8a000000000000000000000000000000000000000000000000000000000000000006ddf6e1d765a193d9cbe146ceeb79ac1cb485ed5f5b37913a8cf5857eff00a91ef91c791d2aa8492c90f12540abd10056ce5dd8d9ab08461476c1dcc16229382e9acf1ff8568fbe655e616a167591aeedc250afbc88d759ec959b1982e8769c000000000000000000000000000000000000000000000000000000000000000001050a0a080002010706040903ac014532fc63e55377ebd2029649000000000100000014000000756fbde9c71eae05c2f7169f816b0bd11d978020010000000076000000000a0000009e0d6a70e12d54edf90971cc977fa26a1d3bb4b0b26e72470171c36b0006b01f0000000000000000000000000000000000000000000000000000000000000000010a0000001400000002a0edda1a4beee4fe2df32c0802aa6759da49ae6165fcdb5c40d7f4cd5a30db0e010008010a021406013001afd71da9456a977233960b08eba77d2e3690b8c7259637c8fb8f82cf58a1020805020302").to_vec(); let from_signing_key = SolSigningKey::from_bytes(&FROM_KEY_BYTES).unwrap(); let event_data_account_signing_key = @@ -348,9 +358,10 @@ mod test { Some(ccm_parameter().channel_metadata), ), FROM.into(), + &[chainflip_alt()], ); - let expected_serialized_tx = hex_literal::hex!("0283f23209bc3d33c8e7fc33d4541de8fb6172f28d6d73212d1c7630491c0605a9051648fe23da7870a180649a5fd509af4dd0a5a4b4563ca2a5bf8386ecb9fe053160493fa3dd5274744ec6c42b5c6152ef58aff96c2c1230fefc06a6a89fde864db41185571b1d2740d7639ff64a53b35db561d0ee75a68fa9f8268f5807fd060200060bcf2a079e1506b29d02c8feac98d589a9059a740891dcd3dab6c64b3160bc28317f799121d6c125f312c5f423a51959ce1d41df06af977e9a17f48b2c82ecf89f1c1f0efc91eeb48bb80c90cf97775cd5d843a96f16500266cee2c20d053152d227fefc7ec198ef3eacb0f17871e1fad81f07a40cd55f4f364c3915877d89bd8ae91372b3d301c202a633da0a92365a736e462131aecfad1fac47322cf8863ada000000000000000000000000000000000000000000000000000000000000000006ddf6e1d765a193d9cbe146ceeb79ac1cb485ed5f5b37913a8cf5857eff00a90fb9ba52b1f09445f1e3a7508d59f0797923acf744fbe2da303fb06da859ee871ef91c791d2aa8492c90f12540abd10056ce5dd8d9ab08461476c1dcc16229382e9acf1ff8568fbe655e616a167591aeedc250afbc88d759ec959b1982e8769ca1e031c8bc9bec3b610cf7b36eb3bf3aa40237c9e5be2c7893878578439eb00b000000000000000000000000000000000000000000000000000000000000000001080a0a040003010209060705ae024532fc63e55377ebd20296490000000005000000200000009e0d6a70e12d54edf90971cc977fa26a1d3bb4b0b26e72470171c36b0006b01f0900000001040000007c1d0f070000000000000000dc000000009101007417da8b99d7748127a76b03d61fee69c80dfef73ad2d5503737beedc5a9ed480104a73bdf31e341218a693b8772c43ecfcecd4cf35fada09a87ea0f860d028168e50090e0b0f5b60147b325842c1fc68f6c90fe26419ea7c4afeb982f71f1f54b5b440a0000009e0d6a70e12d54edf90971cc977fa26a1d3bb4b0b26e72470171c36b0006b01f0000000000000000000000000000000000000000000000000000000000000000010a0000001400000002a0edda1a4beee4fe2df32c0802aa6759da49ae6165fcdb5c40d7f4cd5a30db0e010008010a021406").to_vec(); + let expected_serialized_tx = hex_literal::hex!("02e6d173a6df8b9b1dbbd93cf4d94d2089fe6827fd1db8f34963227bbee8ca92f337f4f8e6cf8473ae3b2269e584e41e6aa5b40ed08b3ff1bb82671713724eaf02048c71002512de4926e57d72217bb5786669a083da3ada13b37d3a7b9843c40f06cdab381591ed34dcbd78a7be5c3b68d9ee938b9d061dbab72ea473a62983038002000407cf2a079e1506b29d02c8feac98d589a9059a740891dcd3dab6c64b3160bc28317f799121d6c125f312c5f423a51959ce1d41df06af977e9a17f48b2c82ecf89f27fefc7ec198ef3eacb0f17871e1fad81f07a40cd55f4f364c3915877d89bd8a000000000000000000000000000000000000000000000000000000000000000006ddf6e1d765a193d9cbe146ceeb79ac1cb485ed5f5b37913a8cf5857eff00a91ef91c791d2aa8492c90f12540abd10056ce5dd8d9ab08461476c1dcc16229382e9acf1ff8568fbe655e616a167591aeedc250afbc88d759ec959b1982e8769c000000000000000000000000000000000000000000000000000000000000000001050a0a080002010706040903ae024532fc63e55377ebd20296490000000005000000200000009e0d6a70e12d54edf90971cc977fa26a1d3bb4b0b26e72470171c36b0006b01f0900000001040000007c1d0f070000000000000000dc000000009101007417da8b99d7748127a76b03d61fee69c80dfef73ad2d5503737beedc5a9ed480104a73bdf31e341218a693b8772c43ecfcecd4cf35fada09a87ea0f860d028168e50090e0b0f5b60147b325842c1fc68f6c90fe26419ea7c4afeb982f71f1f54b5b440a0000009e0d6a70e12d54edf90971cc977fa26a1d3bb4b0b26e72470171c36b0006b01f0000000000000000000000000000000000000000000000000000000000000000010a0000001400000002a0edda1a4beee4fe2df32c0802aa6759da49ae6165fcdb5c40d7f4cd5a30db0e010008010a021406013001afd71da9456a977233960b08eba77d2e3690b8c7259637c8fb8f82cf58a1020805020302").to_vec(); let from_signing_key = SolSigningKey::from_bytes(&FROM_KEY_BYTES).unwrap(); let event_data_account_signing_key = diff --git a/state-chain/chains/src/sol/sol_tx_core.rs b/state-chain/chains/src/sol/sol_tx_core.rs index ff51fe72581..d9a7132d64e 100644 --- a/state-chain/chains/src/sol/sol_tx_core.rs +++ b/state-chain/chains/src/sol/sol_tx_core.rs @@ -7,7 +7,6 @@ use sp_std::vec::Vec; use crate::sol::SolAddress; pub use sol_prim::*; -pub use transaction::legacy::{LegacyMessage, LegacyTransaction}; /// Provides alternative version of internal types that uses `Address` instead of Pubkey: /// @@ -125,11 +124,12 @@ pub mod sol_test_values { api::{DurableNonceAndAccount, VaultSwapAccountAndSender}, signing_key::SolSigningKey, sol_tx_core::signer::{Signer, TestSigners}, - SolAddress, SolAmount, SolApiEnvironment, SolAsset, SolCcmAccounts, SolCcmAddress, - SolComputeLimit, SolHash, + SolAddress, SolAddressLookupTableAccount, SolAmount, SolApiEnvironment, SolAsset, + SolCcmAccounts, SolCcmAddress, SolComputeLimit, SolHash, SolVersionedTransaction, }, CcmChannelMetadata, CcmDepositMetadata, ForeignChain, ForeignChainAddress, }; + use itertools::Itertools; use sol_prim::consts::{const_address, const_hash, MAX_TRANSACTION_LENGTH}; use sp_std::vec; @@ -289,19 +289,63 @@ pub mod sol_test_values { } } + pub fn ccm_parameter_v1() -> CcmDepositMetadata { + let mut ccm = ccm_parameter(); + ccm.channel_metadata.ccm_additional_data = + codec::Encode::encode(&VersionedSolanaCcmAdditionalData::V1 { + ccm_accounts: ccm_accounts(), + alts: vec![user_alt().key.into()], + }) + .try_into() + .unwrap(); + ccm + } + pub fn agg_key() -> SolAddress { SolSigningKey::from_bytes(&RAW_KEYPAIR).unwrap().pubkey().into() } + pub fn chainflip_alt() -> SolAddressLookupTableAccount { + SolAddressLookupTableAccount { + key: const_address("4EQ4ZTskvNwkBaQjBJW5grcmV5Js82sUooNLHNTpdHdi").into(), + addresses: vec![ + vec![ + VAULT_PROGRAM, + VAULT_PROGRAM_DATA_ADDRESS, + VAULT_PROGRAM_DATA_ACCOUNT, + USDC_TOKEN_MINT_PUB_KEY, + TOKEN_VAULT_PDA_ACCOUNT, + USDC_TOKEN_VAULT_ASSOCIATED_TOKEN_ACCOUNT, + SWAP_ENDPOINT_DATA_ACCOUNT_ADDRESS, + SWAP_ENDPOINT_PROGRAM, + SWAP_ENDPOINT_PROGRAM_DATA_ACCOUNT, + ], + NONCE_ACCOUNTS.to_vec(), + ] + .into_iter() + .concat() + .into_iter() + .map(|a| a.into()) + .collect::>(), + } + } + + pub fn user_alt() -> SolAddressLookupTableAccount { + SolAddressLookupTableAccount { + key: const_address("3VBLeVu7rZciyk19M9V7VbHBM2uFm9YbnKKPB33mGRW8").into(), + addresses: vec![TRANSFER_TO_ACCOUNT.into()], + } + } + #[track_caller] pub fn test_constructed_transaction_with_signer( - mut transaction: crate::sol::SolLegacyTransaction, + mut transaction: SolVersionedTransaction, expected_serialized_tx: Vec, signers: TestSigners, blockhash: super::Hash, ) { // Sign the transaction with the given singers and blockhash. - transaction.sign(signers, blockhash); + transaction.test_only_sign(signers, blockhash); let serialized_tx = transaction .clone() @@ -321,7 +365,7 @@ pub mod sol_test_values { #[track_caller] pub fn test_constructed_transaction( - transaction: crate::sol::SolLegacyTransaction, + transaction: SolVersionedTransaction, expected_serialized_tx: Vec, ) { let agg_key_keypair = SolSigningKey::from_bytes(&RAW_KEYPAIR).unwrap(); diff --git a/state-chain/chains/src/sol/tests.rs b/state-chain/chains/src/sol/tests.rs index bf50db4d7df..7a770ea3bcb 100644 --- a/state-chain/chains/src/sol/tests.rs +++ b/state-chain/chains/src/sol/tests.rs @@ -19,8 +19,8 @@ use crate::{ signer::Signer, sol_test_values::*, token_instructions::AssociatedTokenAccountInstruction, - AccountMeta, CompiledInstruction, Hash, Instruction, LegacyMessage, LegacyTransaction, - MessageHeader, PdaAndBump, Pubkey, + transaction::{v0::VersionedMessageV0, VersionedMessage, VersionedTransaction}, + CompiledInstruction, Hash, MessageHeader, PdaAndBump, Pubkey, }, SolAddress, SolHash, SolSignature, }, @@ -36,12 +36,21 @@ enum BankInstruction { Withdraw { lamports: u64 }, } +fn check_tx_encoding(serialized: Vec, expected: Vec) { + assert!(serialized.len() <= MAX_TRANSACTION_LENGTH); + if serialized != expected { + println!("Actual: {:?}", hex::encode(serialized.clone())); + println!("Expected: {:?}", hex::encode(expected.clone())); + panic!("Serialized encoding does not match expected value.") + } +} + #[cfg(test)] mod versioned_transaction { - use crate::sol::sol_tx_core::{ - consts::{const_address, const_hash}, - transaction::{v0::VersionedMessageV0, VersionedMessage, VersionedTransaction}, - AddressLookupTableAccount, + use crate::sol::{ + sol_tx_core::consts::{const_address, const_hash}, + SolAddressLookupTableAccount, SolVersionedMessage, SolVersionedMessageV0, + SolVersionedTransaction, }; use super::*; @@ -62,20 +71,19 @@ mod versioned_transaction { ComputeBudgetInstruction::set_compute_unit_limit(COMPUTE_UNIT_LIMIT), SystemProgramInstruction::transfer(&agg_key_pubkey, &to_pubkey, TRANSFER_AMOUNT), ]; - let message = VersionedMessage::V0(VersionedMessageV0::new_with_blockhash( + + let mut tx = SolVersionedTransaction::new_unsigned(SolVersionedMessage::new( &instructions, Some(agg_key_pubkey), - durable_nonce, + Some(durable_nonce), &[], )); - let mut tx = VersionedTransaction::new_unsigned(message); - tx.sign(vec![agg_key_keypair].into(), durable_nonce); + tx.test_only_sign(vec![agg_key_keypair].into(), durable_nonce); let serialized_tx = tx.finalize_and_serialize().unwrap(); - let expected_serialized_tx = "012e1beb02a24f6e59148fc4eb64aeaeaad291e5f241b8b2d01775a6d3956392ac7186fbee0963d6ca0720bddb5d8b555ada6beb2cd3e9bd0415c343a5ca0cde0b8001000306f79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb17eb2b10d3377bda2bc7bea65bec6b8372f4fc3463ec2cd6f9fde4b2c633d19231e9528aae784fecbbd0bee129d9539c57be0e90061af6b6f4a5e274654e5bd400000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea9400000c27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e4890004030301050004040000000400090340420f000000000004000502e0930400030200020c0200000000ca9a3b0000000000"; + let expected_serialized_tx = hex_literal::hex!("012e1beb02a24f6e59148fc4eb64aeaeaad291e5f241b8b2d01775a6d3956392ac7186fbee0963d6ca0720bddb5d8b555ada6beb2cd3e9bd0415c343a5ca0cde0b8001000306f79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb17eb2b10d3377bda2bc7bea65bec6b8372f4fc3463ec2cd6f9fde4b2c633d19231e9528aae784fecbbd0bee129d9539c57be0e90061af6b6f4a5e274654e5bd400000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea9400000c27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e4890004030301050004040000000400090340420f000000000004000502e0930400030200020c0200000000ca9a3b0000000000"); - assert_eq!(hex::encode(serialized_tx.clone()), expected_serialized_tx); - assert!(serialized_tx.len() <= MAX_TRANSACTION_LENGTH) + check_tx_encoding(serialized_tx, expected_serialized_tx.to_vec()); } #[test] @@ -84,7 +92,7 @@ mod versioned_transaction { const_address("2cNMwUCF51djw2xAiiU54wz1WrU8uG4Q8Kp8nfEuwghw").into(), const_hash("2qVz58R5aPmF5Q61VaKXnpWQtngdh4Jgbeko32fEcECu").into(), ); - let alt = AddressLookupTableAccount { + let alt = SolAddressLookupTableAccount { key: const_address("4EQ4ZTskvNwkBaQjBJW5grcmV5Js82sUooNLHNTpdHdi").into(), addresses: vec![const_address("CFnQk1nVmkPThKvLU8EUPFtTuJro45JLSoqux4v23ZGy").into()], }; @@ -99,35 +107,24 @@ mod versioned_transaction { ComputeBudgetInstruction::set_compute_unit_limit(COMPUTE_UNIT_LIMIT), SystemProgramInstruction::transfer(&agg_key_pubkey, &to_pubkey, TRANSFER_AMOUNT), ]; - let message = VersionedMessage::V0(VersionedMessageV0::new_with_blockhash( - &instructions, - Some(agg_key_pubkey), - durable_nonce.1, - &[alt], + + let mut tx = SolVersionedTransaction::new_unsigned(SolVersionedMessage::V0( + SolVersionedMessageV0::new_with_blockhash( + &instructions, + Some(agg_key_pubkey), + durable_nonce.1, + &[alt], + ), )); - let mut tx = VersionedTransaction::new_unsigned(message); - tx.sign(vec![agg_key_keypair].into(), durable_nonce.1); + tx.test_only_sign(vec![agg_key_keypair].into(), durable_nonce.1); let serialized_tx = tx.finalize_and_serialize().unwrap(); - let expected_serialized_tx = "01ed1357672e0e660e9afd6dd948bee446639a232171900b89a1d403e78e58ad30d8da3986888c9e07ec066b19198b59f99428c00fcf858040e669185473ded5008001000305f79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb17eb2b10d3377bda2bc7bea65bec6b8372f4fc3463ec2cd6f9fde4b2c633d19200000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea94000001b48568b09b08111ebdcf9a5073d86a4506a3c3fe2a6d47a8a5ce0c459a65bce04020301040004040000000300090340420f000000000003000502e0930400020200050c0200000000ca9a3b00000000013001afd71da9456a977233960b08eba77d2e3690b8c7259637c8fb8f82cf58a1010000"; + let expected_serialized_tx = hex_literal::hex!("01ed1357672e0e660e9afd6dd948bee446639a232171900b89a1d403e78e58ad30d8da3986888c9e07ec066b19198b59f99428c00fcf858040e669185473ded5008001000305f79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb17eb2b10d3377bda2bc7bea65bec6b8372f4fc3463ec2cd6f9fde4b2c633d19200000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea94000001b48568b09b08111ebdcf9a5073d86a4506a3c3fe2a6d47a8a5ce0c459a65bce04020301040004040000000300090340420f000000000003000502e0930400020200050c0200000000ca9a3b00000000013001afd71da9456a977233960b08eba77d2e3690b8c7259637c8fb8f82cf58a1010000"); - assert_eq!(hex::encode(serialized_tx.clone()), expected_serialized_tx); - assert!(serialized_tx.len() <= MAX_TRANSACTION_LENGTH) + check_tx_encoding(serialized_tx.clone(), expected_serialized_tx.to_vec()); } } -#[test] -fn create_simple_tx() { - let program_id = Pubkey([0u8; 32]); - let payer = SolSigningKey::new(); - let bank_instruction = BankInstruction::Initialize; - - let instruction = Instruction::new_with_borsh(program_id, &bank_instruction, vec![]); - - let mut tx = LegacyTransaction::new_with_payer(&[instruction], Some(&payer.pubkey())); - tx.sign(vec![payer].into(), Default::default()); -} - #[test] fn create_transfer_native() { let durable_nonce = TEST_DURABLE_NONCE.into(); @@ -140,16 +137,19 @@ fn create_transfer_native() { ComputeBudgetInstruction::set_compute_unit_limit(COMPUTE_UNIT_LIMIT), SystemProgramInstruction::transfer(&agg_key_pubkey, &to_pubkey, TRANSFER_AMOUNT), ]; - let message = - LegacyMessage::new_with_blockhash(&instructions, Some(&agg_key_pubkey), &durable_nonce); - let mut tx = LegacyTransaction::new_unsigned(message); - tx.sign(vec![agg_key_keypair].into(), durable_nonce); + + let mut tx = VersionedTransaction::new_unsigned(VersionedMessage::new( + &instructions, + Some(agg_key_pubkey), + Some(durable_nonce), + &[chainflip_alt()], + )); + tx.test_only_sign(vec![agg_key_keypair].into(), durable_nonce); let serialized_tx = tx.finalize_and_serialize().unwrap(); - let expected_serialized_tx = hex_literal::hex!("01345c86d1be2bcdf2c93c75b6054b6232e5b1e7f2fe7b3ca241d48c8a5f993af3e474bf581b2e9a1543af13104b3f3a53530d849731cc403418da313743a57e0401000306f79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb17eb2b10d3377bda2bc7bea65bec6b8372f4fc3463ec2cd6f9fde4b2c633d19231e9528aae784fecbbd0bee129d9539c57be0e90061af6b6f4a5e274654e5bd400000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea9400000c27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e4890004030301050004040000000400090340420f000000000004000502e0930400030200020c0200000000ca9a3b00000000").to_vec(); + let expected_serialized_tx = hex_literal::hex!("012a52f078d535a124578e490e8a1c765e2558b6e8f322bc459c0434dc0d852d6470950fd4a80d3f7e73069feb86895ec42bfb5b4c27323acf9be93f4b2395fa0b8001000305f79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb31e9528aae784fecbbd0bee129d9539c57be0e90061af6b6f4a5e274654e5bd400000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea9400000c27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e4890004020305040004040000000300090340420f000000000003000502e0930400020200010c0200000000ca9a3b00000000013001afd71da9456a977233960b08eba77d2e3690b8c7259637c8fb8f82cf58a1010900").to_vec(); - assert_eq!(serialized_tx, expected_serialized_tx); - assert!(serialized_tx.len() <= MAX_TRANSACTION_LENGTH) + check_tx_encoding(serialized_tx, expected_serialized_tx.to_vec()); } #[test] @@ -166,16 +166,19 @@ fn create_transfer_cu_priority_fees() { ComputeBudgetInstruction::set_compute_unit_limit(COMPUTE_UNIT_LIMIT), SystemProgramInstruction::transfer(&agg_key_pubkey, &to_pubkey, lamports), ]; - let message = - LegacyMessage::new_with_blockhash(&instructions, Some(&agg_key_pubkey), &durable_nonce); - let mut tx = LegacyTransaction::new_unsigned(message); - tx.sign(vec![agg_key_keypair].into(), durable_nonce); + + let mut tx = VersionedTransaction::new_unsigned(VersionedMessage::new( + &instructions, + Some(agg_key_pubkey), + Some(durable_nonce), + &[chainflip_alt()], + )); + tx.test_only_sign(vec![agg_key_keypair].into(), durable_nonce); let serialized_tx = tx.finalize_and_serialize().unwrap(); - let expected_serialized_tx = hex_literal::hex!("017036ecc82313548a7f1ef280b9d7c53f9747e23abcb4e76d86c8df6aa87e82d460ad7cea2e8d972a833d3e1802341448a99be200ad4648c454b9d5a5e2d5020d01000306f79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb17eb2b10d3377bda2bc7bea65bec6b8372f4fc3463ec2cd6f9fde4b2c633d19231e9528aae784fecbbd0bee129d9539c57be0e90061af6b6f4a5e274654e5bd400000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea940000012c57218f6315b83818802f3522fe7e04c596ae4fe08841e7940bc2f958aaaea04030301050004040000000400090340420f000000000004000502e0930400030200020c0200000040420f0000000000").to_vec(); + let expected_serialized_tx = hex_literal::hex!("01b82f5a05f3b904d2e4397b6cfe02e8e128d68ba246d40da920ac6bf110cfcc78605c7c1a4e5654fada4bfd57e699bd271c9e665dc88b1623ae75c745e54dab088001000305f79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb31e9528aae784fecbbd0bee129d9539c57be0e90061af6b6f4a5e274654e5bd400000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea940000012c57218f6315b83818802f3522fe7e04c596ae4fe08841e7940bc2f958aaaea04020305040004040000000300090340420f000000000003000502e0930400020200010c0200000040420f0000000000013001afd71da9456a977233960b08eba77d2e3690b8c7259637c8fb8f82cf58a1010900").to_vec(); - assert_eq!(serialized_tx, expected_serialized_tx); - assert!(serialized_tx.len() <= MAX_TRANSACTION_LENGTH) + check_tx_encoding(serialized_tx, expected_serialized_tx.to_vec()); } #[test] @@ -204,19 +207,22 @@ fn create_fetch_native() { SYSTEM_PROGRAM_ID, ), ]; - let message = - LegacyMessage::new_with_blockhash(&instructions, Some(&agg_key_pubkey), &durable_nonce); - let mut tx = LegacyTransaction::new_unsigned(message); - tx.sign(vec![agg_key_keypair].into(), durable_nonce); + + let mut tx = VersionedTransaction::new_unsigned(VersionedMessage::new( + &instructions, + Some(agg_key_pubkey), + Some(durable_nonce), + &[chainflip_alt()], + )); + tx.test_only_sign(vec![agg_key_keypair].into(), durable_nonce); let serialized_tx = tx.finalize_and_serialize().expect("Transaction serialization should succeed"); // With compute unit price and limit - let expected_serialized_tx = hex_literal::hex!("01292f542c6677c72234d0783809765218bdae59e21008d91213520ab30603fb4af885f82cd76713deddec1d3843887f39c114016a48902d2eeb443877f1d01a0201000509f79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb17eb2b10d3377bda2bc7bea65bec6b8372f4fc3463ec2cd6f9fde4b2c633d1921be0fac7f9583cfe14f5c09dd7653c597f93168e946760abaad3e3c2cc101f5233306d43f017cdb7b1a324afdc62c79317d5b93e2e63b870143344134db9c60000000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea940000072b5d2051d300b10b74314b7e25ace9998ca66eb2c7fbc10ef130dd67028293ca1e031c8bc9bec3b610cf7b36eb3bf3aa40237c9e5be2c7893878578439eb00bc27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e4890004040301060004040000000500090340420f000000000005000502e093040007050800030204158e24658f6c59298c080000000b0c0d3700000000ff").to_vec(); + let expected_serialized_tx = hex_literal::hex!("0162453f56cbd627be56997cc697180398ccf938036c5fc301721797a6a10ba5a2e5e5a5d07ae0c138d3f5326437426231736f478832a13f6ffcfdb513de08a40e8001000407f79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb1be0fac7f9583cfe14f5c09dd7653c597f93168e946760abaad3e3c2cc101f5233306d43f017cdb7b1a324afdc62c79317d5b93e2e63b870143344134db9c60000000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea940000072b5d2051d300b10b74314b7e25ace9998ca66eb2c7fbc10ef130dd67028293cc27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e4890004030307050004040000000400090340420f000000000004000502e093040006050800020103158e24658f6c59298c080000000b0c0d3700000000ff013001afd71da9456a977233960b08eba77d2e3690b8c7259637c8fb8f82cf58a101090102").to_vec(); - assert_eq!(serialized_tx, expected_serialized_tx); - assert!(serialized_tx.len() <= MAX_TRANSACTION_LENGTH) + check_tx_encoding(serialized_tx, expected_serialized_tx.to_vec()); } #[test] @@ -259,19 +265,22 @@ fn create_fetch_native_in_batch() { SYSTEM_PROGRAM_ID, ), ]; - let message = - LegacyMessage::new_with_blockhash(&instructions, Some(&agg_key_pubkey), &durable_nonce); - let mut tx = LegacyTransaction::new_unsigned(message); - tx.sign(vec![agg_key_keypair].into(), durable_nonce); + + let mut tx = VersionedTransaction::new_unsigned(VersionedMessage::new( + &instructions, + Some(agg_key_pubkey), + Some(durable_nonce), + &[chainflip_alt()], + )); + tx.test_only_sign(vec![agg_key_keypair].into(), durable_nonce); let serialized_tx = tx.finalize_and_serialize().expect("Transaction serialization should succeed"); // With compute unit price and limit - let expected_serialized_tx = hex_literal::hex!("01eea631a27abfd2a361f68f2b4d6c25bc9fba2ad0b12dabaf12f1cf97cd47a453dbfb78dc6394c5844e4c198f9ffa508352b543b2c7414605a27e72a4dc4209000100050bf79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb17eb2b10d3377bda2bc7bea65bec6b8372f4fc3463ec2cd6f9fde4b2c633d19238861d2f0bf5cd80031b701a6c25d13b4c812dd92f9d6301fafd9a58fb9e438646cd507258c10454d484e64ba59d3e7570658001c5f854b6b3ebb57be90e7a708d9871ed5fb2ee05765af23b7cabcc0d6b08ed370bb9f616a0d4dea40a25f870b5b9d633289c8fd72fb05f33349bf4cc44e82add5d865311ae346d7c9a67b7dd00000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea940000072b5d2051d300b10b74314b7e25ace9998ca66eb2c7fbc10ef130dd67028293ca1e031c8bc9bec3b610cf7b36eb3bf3aa40237c9e5be2c7893878578439eb00bc27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e4890005060301080004040000000700090340420f000000000007000502e093040009050a00030206158e24658f6c59298c080000000000000000000000ff09050a00040506158e24658f6c59298c080000000100000000000000ff").to_vec(); + let expected_serialized_tx = hex_literal::hex!("01bd2ca6de5c5c706077d78cd63810ed7845b7b7f1317e70443af3b4341fe9ae277ed9fcc502a88b9950304890e37971db6802811abb380a614c13c06a573ddd0e8001000409f79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb38861d2f0bf5cd80031b701a6c25d13b4c812dd92f9d6301fafd9a58fb9e438646cd507258c10454d484e64ba59d3e7570658001c5f854b6b3ebb57be90e7a708d9871ed5fb2ee05765af23b7cabcc0d6b08ed370bb9f616a0d4dea40a25f870b5b9d633289c8fd72fb05f33349bf4cc44e82add5d865311ae346d7c9a67b7dd00000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea940000072b5d2051d300b10b74314b7e25ace9998ca66eb2c7fbc10ef130dd67028293cc27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e4890005050309070004040000000600090340420f000000000006000502e093040008050a00020105158e24658f6c59298c080000000000000000000000ff08050a00030405158e24658f6c59298c080000000100000000000000ff013001afd71da9456a977233960b08eba77d2e3690b8c7259637c8fb8f82cf58a101090102").to_vec(); - assert_eq!(serialized_tx, expected_serialized_tx); - assert!(serialized_tx.len() <= MAX_TRANSACTION_LENGTH) + check_tx_encoding(serialized_tx, expected_serialized_tx.to_vec()); } #[test] @@ -331,16 +340,19 @@ fn create_fetch_tokens() { SYSTEM_PROGRAM_ID, ), ]; - let message = - LegacyMessage::new_with_blockhash(&instructions, Some(&agg_key_pubkey), &durable_nonce); - let mut tx = LegacyTransaction::new_unsigned(message); - tx.sign(vec![agg_key_keypair].into(), durable_nonce); + + let mut tx = VersionedTransaction::new_unsigned(VersionedMessage::new( + &instructions, + Some(agg_key_pubkey), + Some(durable_nonce), + &[chainflip_alt()], + )); + tx.test_only_sign(vec![agg_key_keypair].into(), durable_nonce); let serialized_tx = tx.finalize_and_serialize().unwrap(); - let expected_serialized_tx = hex_literal::hex!("01399c2b68c7fae634a32d15c3417c2a92e3632707fff366cf9f92a085642344915b7de51181defe33f87ac0a718cd6df5849e229d54d7a06b362b621855c367010100080df79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb17eb2b10d3377bda2bc7bea65bec6b8372f4fc3463ec2cd6f9fde4b2c633d19242ff6863b52c3f8faf95739e6541bda5d0ac593f00c6c07d9ab37096bf26d910ae85f2fb6289c70bfe37df150dddb17dd84f403fd0b1aa1bfee85795159de21fe91372b3d301c202a633da0a92365a736e462131aecfad1fac47322cf8863ada00000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea940000006ddf6e1d765a193d9cbe146ceeb79ac1cb485ed5f5b37913a8cf5857eff00a90fb9ba52b1f09445f1e3a7508d59f0797923acf744fbe2da303fb06da859ee8746cd507258c10454d484e64ba59d3e7570658001c5f854b6b3ebb57be90e7a7072b5d2051d300b10b74314b7e25ace9998ca66eb2c7fbc10ef130dd67028293ca1e031c8bc9bec3b610cf7b36eb3bf3aa40237c9e5be2c7893878578439eb00bc27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e4890004050301070004040000000600090340420f000000000006000502e09304000b090c000a02040908030516494710642cb0c646080000000000000000000000ff06").to_vec(); + let expected_serialized_tx = hex_literal::hex!("01ea987b282406e114f8283eabf77e4fe8a5749410257becc09b26432bc8aac48615d59e3c4279b5543a2b1b0113b9a5159572b81ea9e1a9c4ec6a8cc97c8b45018001000609f79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb42ff6863b52c3f8faf95739e6541bda5d0ac593f00c6c07d9ab37096bf26d910ae85f2fb6289c70bfe37df150dddb17dd84f403fd0b1aa1bfee85795159de21f00000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea940000006ddf6e1d765a193d9cbe146ceeb79ac1cb485ed5f5b37913a8cf5857eff00a946cd507258c10454d484e64ba59d3e7570658001c5f854b6b3ebb57be90e7a7072b5d2051d300b10b74314b7e25ace9998ca66eb2c7fbc10ef130dd67028293cc27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e4890004030309050004040000000400090340420f000000000004000502e093040008090c0007010a0b06020316494710642cb0c646080000000000000000000000ff06013001afd71da9456a977233960b08eba77d2e3690b8c7259637c8fb8f82cf58a1020905020302").to_vec(); - assert_eq!(serialized_tx, expected_serialized_tx); - assert!(serialized_tx.len() <= MAX_TRANSACTION_LENGTH) + check_tx_encoding(serialized_tx, expected_serialized_tx.to_vec()); } #[test] @@ -409,15 +421,19 @@ fn create_batch_fetch() { SYSTEM_PROGRAM_ID, ), ]; - let message = LegacyMessage::new(&instructions, Some(&agg_key_pubkey)); - let mut tx = LegacyTransaction::new_unsigned(message); - tx.sign(vec![agg_key_keypair].into(), durable_nonce); + + let mut tx = VersionedTransaction::new_unsigned(VersionedMessage::new( + &instructions, + Some(agg_key_pubkey), + Some(durable_nonce), + &[chainflip_alt()], + )); + tx.test_only_sign(vec![agg_key_keypair].into(), durable_nonce); let serialized_tx = tx.finalize_and_serialize().unwrap(); - let expected_serialized_tx = hex_literal::hex!("018117c8fd4d21069f04599ab5c79c6d093991392ca54dacfcefac64585928ae13ae81a9aa51a003a10a47a0d9372301e36df2ca2a0e7797d179d030b30563b20d01000912f79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb17eb2b10d3377bda2bc7bea65bec6b8372f4fc3463ec2cd6f9fde4b2c633d1921ad0968d57ee79348476716f9b2cd44ec4284b8f52c36648d560949e41589a5540de1c0451cccb6edd1fda9b4a48c282b279350b55a7a9716800cc0132b6f0b042ff6863b52c3f8faf95739e6541bda5d0ac593f00c6c07d9ab37096bf26d910a140fd3d05766f0087d57bf99df05731e894392ffcc8e8d7e960ba73c09824aaae85f2fb6289c70bfe37df150dddb17dd84f403fd0b1aa1bfee85795159de21fb4baefcd4965beb1c71311a2ffe76419d4b8f8d35fbc4cf514b1bd02da2df2e3e91372b3d301c202a633da0a92365a736e462131aecfad1fac47322cf8863ada00000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea940000006ddf6e1d765a193d9cbe146ceeb79ac1cb485ed5f5b37913a8cf5857eff00a90fb9ba52b1f09445f1e3a7508d59f0797923acf744fbe2da303fb06da859ee8746cd507258c10454d484e64ba59d3e7570658001c5f854b6b3ebb57be90e7a7072b5d2051d300b10b74314b7e25ace9998ca66eb2c7fbc10ef130dd67028293c8d9871ed5fb2ee05765af23b7cabcc0d6b08ed370bb9f616a0d4dea40a25f870a1e031c8bc9bec3b610cf7b36eb3bf3aa40237c9e5be2c7893878578439eb00bc27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e48900060903010b0004040000000a00090340420f00000000000a000502e09304000f0911000e04080d0c060916494710642cb0c646080000000000000000000000ff060f0911001002080d0c030916494710642cb0c646080000000100000000000000ff060f051100050709158e24658f6c59298c080000000200000000000000ff").to_vec(); + let expected_serialized_tx = hex_literal::hex!("0108b6f8aaace6dc16bd2d13e0299f1a3637001e62254b0fa8eceea8b8d8bad1f77a3ceedecabef0ebb1ba1e2a8b534961238275f5606fcaaedca4b64c6e130e06800100070ef79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb1ad0968d57ee79348476716f9b2cd44ec4284b8f52c36648d560949e41589a5540de1c0451cccb6edd1fda9b4a48c282b279350b55a7a9716800cc0132b6f0b042ff6863b52c3f8faf95739e6541bda5d0ac593f00c6c07d9ab37096bf26d910a140fd3d05766f0087d57bf99df05731e894392ffcc8e8d7e960ba73c09824aaae85f2fb6289c70bfe37df150dddb17dd84f403fd0b1aa1bfee85795159de21fb4baefcd4965beb1c71311a2ffe76419d4b8f8d35fbc4cf514b1bd02da2df2e300000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea940000006ddf6e1d765a193d9cbe146ceeb79ac1cb485ed5f5b37913a8cf5857eff00a946cd507258c10454d484e64ba59d3e7570658001c5f854b6b3ebb57be90e7a7072b5d2051d300b10b74314b7e25ace9998ca66eb2c7fbc10ef130dd67028293c8d9871ed5fb2ee05765af23b7cabcc0d6b08ed370bb9f616a0d4dea40a25f870c27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e489000607030e090004040000000800090340420f000000000008000502e09304000c0911000b030f100a050716494710642cb0c646080000000000000000000000ff060c0911000d010f100a020716494710642cb0c646080000000100000000000000ff060c051100040607158e24658f6c59298c080000000200000000000000ff013001afd71da9456a977233960b08eba77d2e3690b8c7259637c8fb8f82cf58a1020905020302").to_vec(); - assert_eq!(serialized_tx, expected_serialized_tx); - assert!(serialized_tx.len() <= MAX_TRANSACTION_LENGTH) + check_tx_encoding(serialized_tx, expected_serialized_tx.to_vec()); } #[test] @@ -452,16 +468,19 @@ fn create_transfer_tokens() { TOKEN_PROGRAM_ID, ), ]; - let message = - LegacyMessage::new_with_blockhash(&instructions, Some(&agg_key_pubkey), &durable_nonce); - let mut tx = LegacyTransaction::new_unsigned(message); - tx.sign(vec![agg_key_keypair].into(), durable_nonce); + + let mut tx = VersionedTransaction::new_unsigned(VersionedMessage::new( + &instructions, + Some(agg_key_pubkey), + Some(durable_nonce), + &[chainflip_alt()], + )); + tx.test_only_sign(vec![agg_key_keypair].into(), durable_nonce); let serialized_tx = tx.finalize_and_serialize().unwrap(); - let expected_serialized_tx = hex_literal::hex!("012c77634fbfac44e246e991202e24d1b6c2fc438482fa9dbea617b0387aa3d19e2561dd12929db8cc2ae43ccd0f19185882bfac2ef6f7baf1438929cd5b99dd0701000a0ef79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb17eb2b10d3377bda2bc7bea65bec6b8372f4fc3463ec2cd6f9fde4b2c633d1925ec7baaea7200eb2a66ccd361ee73bc87a7e5222ecedcbc946e97afb59ec4616e91372b3d301c202a633da0a92365a736e462131aecfad1fac47322cf8863ada00000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea940000006ddf6e1d765a193d9cbe146ceeb79ac1cb485ed5f5b37913a8cf5857eff00a90fb9ba52b1f09445f1e3a7508d59f0797923acf744fbe2da303fb06da859ee8731e9528aae784fecbbd0bee129d9539c57be0e90061af6b6f4a5e274654e5bd472b5d2051d300b10b74314b7e25ace9998ca66eb2c7fbc10ef130dd67028293c8c97258f4e2489f1bb3d1029148e0d830b5a1399daff1084048e7bd8dbe9f859a1e031c8bc9bec3b610cf7b36eb3bf3aa40237c9e5be2c7893878578439eb00bab1d2a644046552e73f4d05b5a6ef53848973a9ee9febba42ddefb034b5f5130c27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e4890005040301060004040000000500090340420f000000000005000502e09304000b0600020908040701010a070c000d030208071136b4eeaf4a557ebc00ca9a3b0000000006").to_vec(); + let expected_serialized_tx = hex_literal::hex!("013c282f18c2fac3a49b654718cc25adce651063874877937be879c13696bd0e90fb4130532bc5876383b105315336a2c2b0436a1b72274f36e1c38b21246e46068001000709f79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb5ec7baaea7200eb2a66ccd361ee73bc87a7e5222ecedcbc946e97afb59ec461600000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea940000006ddf6e1d765a193d9cbe146ceeb79ac1cb485ed5f5b37913a8cf5857eff00a931e9528aae784fecbbd0bee129d9539c57be0e90061af6b6f4a5e274654e5bd472b5d2051d300b10b74314b7e25ace9998ca66eb2c7fbc10ef130dd67028293c8c97258f4e2489f1bb3d1029148e0d830b5a1399daff1084048e7bd8dbe9f859c27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e4890005020309040004040000000300090340420f000000000003000502e093040008060001060b0205010107070c000d0a010b051136b4eeaf4a557ebc00ca9a3b0000000006013001afd71da9456a977233960b08eba77d2e3690b8c7259637c8fb8f82cf58a102090503030204").to_vec(); - assert_eq!(serialized_tx, expected_serialized_tx); - assert!(serialized_tx.len() <= MAX_TRANSACTION_LENGTH) + check_tx_encoding(serialized_tx, expected_serialized_tx.to_vec()); } // Full rotation: Use nonce, rotate agg key, transfer nonce authority and transfer upgrade @@ -493,16 +512,18 @@ fn create_full_rotation() { ) })); - let message = - LegacyMessage::new_with_blockhash(&instructions, Some(&agg_key_pubkey), &durable_nonce); - let mut tx = LegacyTransaction::new_unsigned(message); - tx.sign(vec![agg_key_keypair].into(), durable_nonce); + let mut tx = VersionedTransaction::new_unsigned(VersionedMessage::new( + &instructions, + Some(agg_key_pubkey), + Some(durable_nonce), + &[chainflip_alt()], + )); + tx.test_only_sign(vec![agg_key_keypair].into(), durable_nonce); let serialized_tx = tx.finalize_and_serialize().unwrap(); - let expected_serialized_tx = hex_literal::hex!("0118e0ec3502ff3656ffeecb9c56cc0e6676bba9ac1026a535e24ab3e2f9ef78353e1c3698bd3582a1e711b68cc0e39802c04dd48a298a572e55fd2e2a6bc2770101000411f79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb17eb2b10d3377bda2bc7bea65bec6b8372f4fc3463ec2cd6f9fde4b2c633d1926744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be5439900448541f57201f277c5f3ffb631d0212e26e7f47749c26c4808718174a0ab2a09a18cd28baa84f2067bbdf24513c2d44e44bf408f2e6da6e60762e3faa4a62a0adba1e031c8bc9bec3b610cf7b36eb3bf3aa40237c9e5be2c7893878578439eb00bcd644e45426a41a7cb8369b8a0c1c89bb3f86cf278fdd9cc38b0f69784ad5667e392cd98d3284fd551604be95c14cc8e20123e2940ef9fb784e6b591c7442864e5e1869817a4fd88ddf7ab7a5f7252d7c345b39721769888608592912e8ca9acf0f13460b3fd04b7d53d7421fc874ec00eec769cf36480895e1a407bf1249475f2b2e24122be016983be9369965246cc45e1f621d40fba300c56c7ac50c3874df4f83bd213a59c9785110cf83c718f9486c3484f918593bce20c61dc6a96036afecc89e3b031824af6363174d19bbec12d3a13c4a173e5aeb349b63042bc138f00000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea940000072b5d2051d300b10b74314b7e25ace9998ca66eb2c7fbc10ef130dd67028293cc27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e489000e0d03010f0004040000000e00090340420f00000000000e000502e093040010040500020d094e518fabdda5d68b000d02010024070000006744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be5439900440d020b0024070000006744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be5439900440d02090024070000006744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be5439900440d020a0024070000006744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be5439900440d02070024070000006744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be5439900440d02060024070000006744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be5439900440d02030024070000006744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be5439900440d020c0024070000006744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be5439900440d02080024070000006744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be5439900440d02040024070000006744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be543990044").to_vec(); + let expected_serialized_tx = hex_literal::hex!("013c65b7f67437e150caf86536669f5b539404308ba91cf963a8919f2c35ab02e850e93a25261c50cffb3d589eb264f556c79926d1f637a16db9c60690fc8de10e8001000406f79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb6744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be54399004400000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea940000072b5d2051d300b10b74314b7e25ace9998ca66eb2c7fbc10ef130dd67028293cc27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e489000e020306040004040000000300090340420f000000000003000502e0930400050409000102094e518fabdda5d68b000202060024070000006744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be54399004402020f0024070000006744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be54399004402020d0024070000006744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be54399004402020e0024070000006744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be54399004402020b0024070000006744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be54399004402020a0024070000006744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be5439900440202070024070000006744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be5439900440202100024070000006744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be54399004402020c0024070000006744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be5439900440202080024070000006744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be543990044013001afd71da9456a977233960b08eba77d2e3690b8c7259637c8fb8f82cf58a10b090f12020e0d110b0c0a1000").to_vec(); - assert_eq!(serialized_tx, expected_serialized_tx); - assert!(serialized_tx.len() <= MAX_TRANSACTION_LENGTH) + check_tx_encoding(serialized_tx, expected_serialized_tx.to_vec()); } #[test] @@ -535,16 +556,19 @@ fn create_ccm_native_transfer() { ) .with_additional_accounts(extra_accounts.additional_account_metas()), ]; - let message = - LegacyMessage::new_with_blockhash(&instructions, Some(&agg_key_pubkey), &durable_nonce); - let mut tx = LegacyTransaction::new_unsigned(message); - tx.sign(vec![agg_key_keypair].into(), durable_nonce); + + let mut tx = VersionedTransaction::new_unsigned(VersionedMessage::new( + &instructions, + Some(agg_key_pubkey), + Some(durable_nonce), + &[chainflip_alt()], + )); + tx.test_only_sign(vec![agg_key_keypair].into(), durable_nonce); let serialized_tx = tx.finalize_and_serialize().unwrap(); - let expected_serialized_tx = hex_literal::hex!("01be5b6acac88600095a934dc7ae8af889c78281664e6b561f3a18bc26887ae95f35fc76d892da32f4a7314a253c0abed2da1c89d5e6daede4d70cacd37942090a0100070bf79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb17eb2b10d3377bda2bc7bea65bec6b8372f4fc3463ec2cd6f9fde4b2c633d19231e9528aae784fecbbd0bee129d9539c57be0e90061af6b6f4a5e274654e5bd47417da8b99d7748127a76b03d61fee69c80dfef73ad2d5503737beedc5a9ed4800000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517187bd16635dad40455fdc2c0c124c68f215675a5dbbacb5f0800000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea940000072b5d2051d300b10b74314b7e25ace9998ca66eb2c7fbc10ef130dd67028293ca1e031c8bc9bec3b610cf7b36eb3bf3aa40237c9e5be2c7893878578439eb00ba73bdf31e341218a693b8772c43ecfcecd4cf35fada09a87ea0f860d028168e5c27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e4890005040301070004040000000500090340420f000000000005000502e0930400040200020c0200000000ca9a3b0000000008070900020304060a347d050be38042e0b20100000014000000ffffffffffffffffffffffffffffffffffffffff040000007c1d0f0700ca9a3b00000000").to_vec(); + let expected_serialized_tx = hex_literal::hex!("0140e3109e8d8abbced084d63149b477958b284a88df0286dd6a3402042c18d38c1e2f6ee642e2b79933429ec3ceebebf333bbe39ae28edb6a41da1c6e65d909048001000609f79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb31e9528aae784fecbbd0bee129d9539c57be0e90061af6b6f4a5e274654e5bd47417da8b99d7748127a76b03d61fee69c80dfef73ad2d5503737beedc5a9ed4800000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517187bd16635dad40455fdc2c0c124c68f215675a5dbbacb5f0800000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea940000072b5d2051d300b10b74314b7e25ace9998ca66eb2c7fbc10ef130dd67028293ca73bdf31e341218a693b8772c43ecfcecd4cf35fada09a87ea0f860d028168e5c27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e4890005030309060004040000000400090340420f000000000004000502e0930400030200010c0200000000ca9a3b0000000007070a000102030508347d050be38042e0b20100000014000000ffffffffffffffffffffffffffffffffffffffff040000007c1d0f0700ca9a3b00000000013001afd71da9456a977233960b08eba77d2e3690b8c7259637c8fb8f82cf58a101090102").to_vec(); - assert_eq!(serialized_tx, expected_serialized_tx); - assert!(serialized_tx.len() <= MAX_TRANSACTION_LENGTH) + check_tx_encoding(serialized_tx, expected_serialized_tx.to_vec()); } #[test] @@ -597,16 +621,19 @@ fn create_ccm_token_transfer() { ) .with_additional_accounts(extra_accounts.additional_account_metas()), ]; - let message = - LegacyMessage::new_with_blockhash(&instructions, Some(&agg_key_pubkey), &durable_nonce); - let mut tx = LegacyTransaction::new_unsigned(message); - tx.sign(vec![agg_key_keypair].into(), durable_nonce); + + let mut tx = VersionedTransaction::new_unsigned(VersionedMessage::new( + &instructions, + Some(agg_key_pubkey), + Some(durable_nonce), + &[chainflip_alt()], + )); + tx.test_only_sign(vec![agg_key_keypair].into(), durable_nonce); let serialized_tx = tx.finalize_and_serialize().unwrap(); - let expected_serialized_tx = hex_literal::hex!("01bd5f6ad13bbce1d97011814f8b7758b42a392ecc0b993c7b0be88499cbb089b3b364eaed5f3998f1dd97670f5a4b146c3be9681cb2d71fc81066657b7423d40501000c11f79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb17eb2b10d3377bda2bc7bea65bec6b8372f4fc3463ec2cd6f9fde4b2c633d1925ec7baaea7200eb2a66ccd361ee73bc87a7e5222ecedcbc946e97afb59ec46167417da8b99d7748127a76b03d61fee69c80dfef73ad2d5503737beedc5a9ed48e91372b3d301c202a633da0a92365a736e462131aecfad1fac47322cf8863ada00000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517187bd16635dad40455fdc2c0c124c68f215675a5dbbacb5f0800000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea940000006ddf6e1d765a193d9cbe146ceeb79ac1cb485ed5f5b37913a8cf5857eff00a90fb9ba52b1f09445f1e3a7508d59f0797923acf744fbe2da303fb06da859ee8731e9528aae784fecbbd0bee129d9539c57be0e90061af6b6f4a5e274654e5bd472b5d2051d300b10b74314b7e25ace9998ca66eb2c7fbc10ef130dd67028293c8c97258f4e2489f1bb3d1029148e0d830b5a1399daff1084048e7bd8dbe9f859a1e031c8bc9bec3b610cf7b36eb3bf3aa40237c9e5be2c7893878578439eb00ba73bdf31e341218a693b8772c43ecfcecd4cf35fada09a87ea0f860d028168e5ab1d2a644046552e73f4d05b5a6ef53848973a9ee9febba42ddefb034b5f5130c27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e4890006050301080004040000000600090340420f000000000006000502e09304000d0600020b0a050901010c070e001004020a091136b4eeaf4a557ebc00ca9a3b00000000060c080e000203090a070f346cb8a27b9fdeaa230100000014000000ffffffffffffffffffffffffffffffffffffffff040000007c1d0f0700ca9a3b00000000").to_vec(); + let expected_serialized_tx = hex_literal::hex!("01dbe27f4ace1b0e45923618401c63c2c6f61389f775c505174d00616c508d630b665e95a25108fd049c3b054c783685a0909294891fa3d9473896ea1a1ef5a60f800100090cf79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb5ec7baaea7200eb2a66ccd361ee73bc87a7e5222ecedcbc946e97afb59ec46167417da8b99d7748127a76b03d61fee69c80dfef73ad2d5503737beedc5a9ed4800000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517187bd16635dad40455fdc2c0c124c68f215675a5dbbacb5f0800000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea940000006ddf6e1d765a193d9cbe146ceeb79ac1cb485ed5f5b37913a8cf5857eff00a931e9528aae784fecbbd0bee129d9539c57be0e90061af6b6f4a5e274654e5bd472b5d2051d300b10b74314b7e25ace9998ca66eb2c7fbc10ef130dd67028293c8c97258f4e2489f1bb3d1029148e0d830b5a1399daff1084048e7bd8dbe9f859a73bdf31e341218a693b8772c43ecfcecd4cf35fada09a87ea0f860d028168e5c27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e489000603030c060004040000000400090340420f000000000004000502e09304000a060001080e0307010109070f00100d010e071136b4eeaf4a557ebc00ca9a3b000000000609080f000102070e050b346cb8a27b9fdeaa230100000014000000ffffffffffffffffffffffffffffffffffffffff040000007c1d0f0700ca9a3b00000000013001afd71da9456a977233960b08eba77d2e3690b8c7259637c8fb8f82cf58a102090503030204").to_vec(); - assert_eq!(serialized_tx, expected_serialized_tx); - assert!(serialized_tx.len() <= MAX_TRANSACTION_LENGTH) + check_tx_encoding(serialized_tx, expected_serialized_tx.to_vec()); } #[test] @@ -631,16 +658,19 @@ fn create_idempotent_associated_token_account() { &to_ata, ), ]; - let message = - LegacyMessage::new_with_blockhash(&instructions, Some(&agg_key_pubkey), &durable_nonce); - let mut tx = LegacyTransaction::new_unsigned(message); - tx.sign(vec![agg_key_keypair].into(), durable_nonce); + + let mut tx = VersionedTransaction::new_unsigned(VersionedMessage::new( + &instructions, + Some(agg_key_pubkey), + Some(durable_nonce), + &[chainflip_alt()], + )); + tx.test_only_sign(vec![agg_key_keypair].into(), durable_nonce); let serialized_tx = tx.finalize_and_serialize().unwrap(); - let expected_serialized_tx = hex_literal::hex!("01eb287ff9329fbaf83592ec56709d52d3d7f7edcab7ab53fc8371acff871016c51dfadde692630545a91d6534095bb5697b5fb9ee17dc292552eabf9ab6e3390601000609f79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb17eb2b10d3377bda2bc7bea65bec6b8372f4fc3463ec2cd6f9fde4b2c633d192ca03f3e6d6fd79aaf8ebd4ce053492a34f22d0edafbfa88a380848d9a4735150000000000000000000000000000000000000000000000000000000000000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea940000006ddf6e1d765a193d9cbe146ceeb79ac1cb485ed5f5b37913a8cf5857eff00a90c4a8e3702f6e26d9d0c900c1461da4e3debef5743ce253bb9f0308a68c944220f1b83220b1108ea0e171b5391e6c0157370c8353516b74e962f855be6d787038c97258f4e2489f1bb3d1029148e0d830b5a1399daff1084048e7bd8dbe9f85921b22d7dfc8cdeba6027384563948d038a11eba06289de51a15c3d649d1f7e2c020303010400040400000008060002060703050101").to_vec(); + let expected_serialized_tx = hex_literal::hex!("01079723fc8d3a516b39a67643058c7325f3d6d2f485fe730347ba98e5e22e178c8332e8eca86924b90e8de96a7648c96e49621416a61fed3a2ebf9aea54e826078001000608f79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fbca03f3e6d6fd79aaf8ebd4ce053492a34f22d0edafbfa88a380848d9a4735150000000000000000000000000000000000000000000000000000000000000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea940000006ddf6e1d765a193d9cbe146ceeb79ac1cb485ed5f5b37913a8cf5857eff00a90c4a8e3702f6e26d9d0c900c1461da4e3debef5743ce253bb9f0308a68c944220f1b83220b1108ea0e171b5391e6c0157370c8353516b74e962f855be6d787038c97258f4e2489f1bb3d1029148e0d830b5a1399daff1084048e7bd8dbe9f85921b22d7dfc8cdeba6027384563948d038a11eba06289de51a15c3d649d1f7e2c020203080300040400000007060001050602040101013001afd71da9456a977233960b08eba77d2e3690b8c7259637c8fb8f82cf58a1010900").to_vec(); - assert_eq!(serialized_tx, expected_serialized_tx); - assert!(serialized_tx.len() <= MAX_TRANSACTION_LENGTH) + check_tx_encoding(serialized_tx, expected_serialized_tx.to_vec()); } #[test] @@ -667,34 +697,19 @@ fn create_set_program_swaps_parameters() { agg_key_pubkey, ), ]; - let message = - LegacyMessage::new_with_blockhash(&instructions, Some(&agg_key_pubkey), &durable_nonce); - let mut tx = LegacyTransaction::new_unsigned(message); - tx.sign(vec![agg_key_keypair].into(), durable_nonce); + + let mut tx = VersionedTransaction::new_unsigned(VersionedMessage::new( + &instructions, + Some(agg_key_pubkey), + Some(durable_nonce), + &[chainflip_alt()], + )); + tx.test_only_sign(vec![agg_key_keypair].into(), durable_nonce); let serialized_tx = tx.finalize_and_serialize().unwrap(); - let expected_serialized_tx = [ - 1, 156, 69, 62, 23, 230, 241, 160, 66, 97, 25, 239, 135, 44, 207, 147, 43, 156, 74, 175, - 251, 75, 185, 120, 68, 77, 164, 78, 111, 76, 169, 205, 173, 15, 41, 205, 152, 228, 159, - 104, 73, 91, 32, 65, 149, 19, 118, 247, 242, 207, 13, 83, 20, 15, 183, 19, 46, 251, 113, - 166, 119, 114, 198, 182, 5, 1, 0, 3, 6, 247, 157, 94, 2, 111, 18, 237, 198, 68, 58, 83, 75, - 44, 221, 80, 114, 35, 57, 137, 180, 21, 215, 89, 101, 115, 231, 67, 243, 229, 179, 134, - 251, 23, 235, 43, 16, 211, 55, 123, 218, 43, 199, 190, 166, 91, 236, 107, 131, 114, 244, - 252, 52, 99, 236, 44, 214, 249, 253, 228, 178, 198, 51, 209, 146, 161, 224, 49, 200, 188, - 155, 236, 59, 97, 12, 247, 179, 110, 179, 191, 58, 164, 2, 55, 201, 229, 190, 44, 120, 147, - 135, 133, 120, 67, 158, 176, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 167, 213, 23, 25, 44, 86, 142, 224, 138, 132, 95, - 115, 210, 151, 136, 207, 3, 92, 49, 69, 178, 26, 179, 68, 216, 6, 46, 169, 64, 0, 0, 114, - 181, 210, 5, 29, 48, 11, 16, 183, 67, 20, 183, 226, 90, 206, 153, 152, 202, 102, 235, 44, - 127, 188, 16, 239, 19, 13, 214, 112, 40, 41, 60, 194, 126, 144, 116, 250, 197, 232, 211, - 108, 240, 79, 148, 160, 96, 111, 221, 141, 219, 180, 32, 233, 154, 72, 156, 121, 21, 206, - 86, 153, 228, 137, 0, 2, 3, 3, 1, 4, 0, 4, 4, 0, 0, 0, 5, 2, 2, 0, 30, 129, 254, 31, 151, - 111, 149, 135, 77, 0, 242, 5, 42, 1, 0, 0, 0, 128, 0, 16, 39, 0, 0, 208, 7, 0, 0, 244, 1, - 0, 0, - ]; + let expected_serialized_tx = hex_literal::hex!("01a7844359f2b08709be667a0fcbef75d34e03c874b0c1e175339923e7e19c93e2409a1b1636551e20014c1f9689fd82de2d055f65d79464d57a9e01e37748bb008001000304f79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb000000000000000000000000000000000000000000000000000000000000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea940000072b5d2051d300b10b74314b7e25ace9998ca66eb2c7fbc10ef130dd67028293cc27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e489000201030402000404000000030205001e81fe1f976f95874d00f2052a01000000800010270000d0070000f4010000013001afd71da9456a977233960b08eba77d2e3690b8c7259637c8fb8f82cf58a102090200"); - assert_eq!(serialized_tx, expected_serialized_tx); - assert!(serialized_tx.len() <= MAX_TRANSACTION_LENGTH) + check_tx_encoding(serialized_tx, expected_serialized_tx.to_vec()); } #[test] @@ -720,83 +735,19 @@ fn create_enable_token_support() { SYSTEM_PROGRAM_ID, ), ]; - let message = - LegacyMessage::new_with_blockhash(&instructions, Some(&agg_key_pubkey), &durable_nonce); - let mut tx = LegacyTransaction::new_unsigned(message); - tx.sign(vec![agg_key_keypair].into(), durable_nonce); - let serialized_tx = tx.finalize_and_serialize().unwrap(); - let expected_serialized_tx = [ - 1, 58, 110, 210, 42, 122, 243, 74, 142, 157, 80, 145, 131, 252, 211, 101, 40, 57, 232, 136, - 226, 205, 247, 146, 228, 92, 31, 106, 4, 105, 239, 129, 136, 136, 230, 249, 67, 29, 214, - 24, 179, 37, 62, 148, 135, 8, 72, 224, 203, 7, 166, 6, 80, 249, 224, 133, 102, 234, 148, - 160, 151, 33, 1, 69, 13, 1, 0, 4, 8, 247, 157, 94, 2, 111, 18, 237, 198, 68, 58, 83, 75, - 44, 221, 80, 114, 35, 57, 137, 180, 21, 215, 89, 101, 115, 231, 67, 243, 229, 179, 134, - 251, 23, 235, 43, 16, 211, 55, 123, 218, 43, 199, 190, 166, 91, 236, 107, 131, 114, 244, - 252, 52, 99, 236, 44, 214, 249, 253, 228, 178, 198, 51, 209, 146, 130, 120, 55, 161, 106, - 51, 56, 208, 20, 119, 164, 182, 206, 154, 185, 251, 31, 87, 31, 216, 245, 58, 8, 209, 87, - 23, 103, 27, 146, 29, 104, 253, 161, 224, 49, 200, 188, 155, 236, 59, 97, 12, 247, 179, - 110, 179, 191, 58, 164, 2, 55, 201, 229, 190, 44, 120, 147, 135, 133, 120, 67, 158, 176, - 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 6, 167, 213, 23, 25, 44, 86, 142, 224, 138, 132, 95, 115, 210, 151, 136, 207, 3, - 92, 49, 69, 178, 26, 179, 68, 216, 6, 46, 169, 64, 0, 0, 15, 185, 186, 82, 177, 240, 148, - 69, 241, 227, 167, 80, 141, 89, 240, 121, 121, 35, 172, 247, 68, 251, 226, 218, 48, 63, - 176, 109, 168, 89, 238, 135, 114, 181, 210, 5, 29, 48, 11, 16, 183, 67, 20, 183, 226, 90, - 206, 153, 152, 202, 102, 235, 44, 127, 188, 16, 239, 19, 13, 214, 112, 40, 41, 60, 194, - 126, 144, 116, 250, 197, 232, 211, 108, 240, 79, 148, 160, 96, 111, 221, 141, 219, 180, 32, - 233, 154, 72, 156, 121, 21, 206, 86, 153, 228, 137, 0, 2, 4, 3, 1, 5, 0, 4, 4, 0, 0, 0, 7, - 5, 3, 0, 2, 6, 4, 16, 125, 160, 180, 50, 26, 27, 112, 153, 5, 0, 0, 0, 0, 0, 0, 0, - ]; - - assert_eq!(serialized_tx, expected_serialized_tx); - assert!(serialized_tx.len() <= MAX_TRANSACTION_LENGTH) -} - -// Test taken from https://docs.rs/solana-sdk/latest/src/solana_sdk/transaction/mod.rs.html#1354 -// using current serialization (bincode::serde::encode_to_vec) and ensure that it's correct -fn create_sample_transaction() -> LegacyTransaction { - let keypair = SolSigningKey::from_bytes(&[ - 255, 101, 36, 24, 124, 23, 167, 21, 132, 204, 155, 5, 185, 58, 121, 75, 156, 227, 116, 193, - 215, 38, 142, 22, 8, 14, 229, 239, 119, 93, 5, 218, - ]) - .unwrap(); - let to = Pubkey::from([ - 1, 1, 1, 4, 5, 6, 7, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 7, 6, 5, 4, 1, - 1, 1, - ]); - - let program_id = Pubkey::from([ - 2, 2, 2, 4, 5, 6, 7, 8, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 8, 7, 6, 5, 4, 2, - 2, 2, - ]); - let account_metas = vec![AccountMeta::new(keypair.pubkey(), true), AccountMeta::new(to, false)]; - let instruction = Instruction::new_with_bincode(program_id, &(1u8, 2u8, 3u8), account_metas); - let message = LegacyMessage::new(&[instruction], Some(&keypair.pubkey())); - let mut tx: LegacyTransaction = LegacyTransaction::new_unsigned(message); - tx.sign(vec![keypair].into(), Hash::default()); - tx -} + let mut tx = VersionedTransaction::new_unsigned(VersionedMessage::new( + &instructions, + Some(agg_key_pubkey), + Some(durable_nonce), + &[chainflip_alt()], + )); + tx.test_only_sign(vec![agg_key_keypair].into(), durable_nonce); -#[test] -fn test_sdk_serialize() { - let tx = create_sample_transaction(); let serialized_tx = tx.finalize_and_serialize().unwrap(); - // SDK uses serde::serialize instead, but looks like this works. + let expected_serialized_tx = hex_literal::hex!("019ee11181024cef1bdc7ccfc3ce32fb557aa278f73bb831a628c6c045fad646fef0e84e9c5bb1cfa84693b668d529dcd3263b18f260b6c3f3191dc73c90bb8a068001000305f79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb827837a16a3338d01477a4b6ce9ab9fb1f571fd8f53a08d15717671b921d68fd000000000000000000000000000000000000000000000000000000000000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea940000072b5d2051d300b10b74314b7e25ace9998ca66eb2c7fbc10ef130dd67028293cc27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e48900020203050300040400000004050600010702107da0b4321a1b70990500000000000000013001afd71da9456a977233960b08eba77d2e3690b8c7259637c8fb8f82cf58a10209020103"); - assert_eq!( - serialized_tx, - vec![ - 1, 120, 138, 162, 185, 59, 209, 241, 157, 71, 157, 74, 131, 4, 87, 54, 28, 38, 180, - 222, 82, 64, 62, 61, 62, 22, 46, 17, 203, 187, 136, 62, 43, 11, 38, 235, 17, 239, 82, - 240, 139, 130, 217, 227, 214, 9, 242, 141, 223, 94, 29, 184, 110, 62, 32, 87, 137, 63, - 139, 100, 221, 20, 137, 4, 5, 1, 0, 1, 3, 36, 100, 158, 252, 33, 161, 97, 185, 62, 89, - 99, 195, 250, 249, 187, 189, 171, 118, 241, 90, 248, 14, 68, 219, 231, 62, 157, 5, 142, - 27, 210, 117, 1, 1, 1, 4, 5, 6, 7, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 8, 7, 6, 5, 4, 1, 1, 1, 2, 2, 2, 4, 5, 6, 7, 8, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 9, 8, 7, 6, 5, 4, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 0, 1, 3, 1, 2, 3 - ] - ); + check_tx_encoding(serialized_tx, expected_serialized_tx.to_vec()); } // These tests can be used to manually serialize a transaction from a Solana Transaction in @@ -813,13 +764,13 @@ fn test_sdk_serialize() { #[ignore] #[test] fn test_encode_tx() { - let tx: LegacyTransaction = LegacyTransaction { + let tx: VersionedTransaction = VersionedTransaction { signatures: vec![ SolSignature(hex_literal::hex!( "d1144b223b6b600de4b2d96bdceb03573a3e9781953e4c668c57e505f017859d96543243b4d904dc2f02f2f5ab5db7ba4551c7e015e64078add4674ac2e7460c" )), ], - message: LegacyMessage { + message: VersionedMessage::V0( VersionedMessageV0 { header: MessageHeader { num_required_signatures: 1, num_readonly_signed_accounts: 0, @@ -903,24 +854,25 @@ fn test_encode_tx() { data: hex_literal::hex!("494710642cb0c646080000000200000000000000ff06").to_vec(), }, ], - }, + address_table_lookups: vec![], + }), }; let serialized_tx = tx.finalize_and_serialize().unwrap(); - let expected_serialized_tx = hex_literal::hex!("01d1144b223b6b600de4b2d96bdceb03573a3e9781953e4c668c57e505f017859d96543243b4d904dc2f02f2f5ab5db7ba4551c7e015e64078add4674ac2e7460c0100080f2e8944a76efbece296221e736627f4528a947578263a1172a9786410702d2ef222020a74fd97df45db96d2bbf4e485ccbec56945155ff8f668856be26c9de4a979c03bceb9ddea819e956b2b332e87fbbf49fc8968df78488e88cfaa366f30368cd28baa84f2067bbdf24513c2d44e44bf408f2e6da6e60762e3faa4a62a0adb8d9871ed5fb2ee05765af23b7cabcc0d6b08ed370bb9f616a0d4dea40a25f870b5b9d633289c8fd72fb05f33349bf4cc44e82add5d865311ae346d7c9a67b7ddf53a2f4350451db5595a75e231519bc2758798f72550e57487722e7cbe954dbc00000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea940000006ddf6e1d765a193d9cbe146ceeb79ac1cb485ed5f5b37913a8cf5857eff00a90fb9ba52b1f09445f1e3a7508d59f0797923acf744fbe2da303fb06da859ee8772b5d2051d300b10b74314b7e25ace9998ca66eb2c7fbc10ef130dd67028293ca140fd3d05766f0087d57bf99df05731e894392ffcc8e8d7e960ba73c09824aaa1e031c8bc9bec3b610cf7b36eb3bf3aa40237c9e5be2c7893878578439eb00bf7f02ac4729abaa97c01aa6526ba909c3bcb16c7f47c7e13dfdc5a1b15f647b40507030309000404000000080009030a0000000000000008000502336201000c050e00040507158e24658f6c59298c080000000100000000000000ff0c090e000d01020b0a060716494710642cb0c646080000000200000000000000ff06").to_vec(); - assert_eq!(serialized_tx, expected_serialized_tx); + let expected_serialized_tx = hex_literal::hex!("01d1144b223b6b600de4b2d96bdceb03573a3e9781953e4c668c57e505f017859d96543243b4d904dc2f02f2f5ab5db7ba4551c7e015e64078add4674ac2e7460c800100080f2e8944a76efbece296221e736627f4528a947578263a1172a9786410702d2ef222020a74fd97df45db96d2bbf4e485ccbec56945155ff8f668856be26c9de4a979c03bceb9ddea819e956b2b332e87fbbf49fc8968df78488e88cfaa366f30368cd28baa84f2067bbdf24513c2d44e44bf408f2e6da6e60762e3faa4a62a0adb8d9871ed5fb2ee05765af23b7cabcc0d6b08ed370bb9f616a0d4dea40a25f870b5b9d633289c8fd72fb05f33349bf4cc44e82add5d865311ae346d7c9a67b7ddf53a2f4350451db5595a75e231519bc2758798f72550e57487722e7cbe954dbc00000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea940000006ddf6e1d765a193d9cbe146ceeb79ac1cb485ed5f5b37913a8cf5857eff00a90fb9ba52b1f09445f1e3a7508d59f0797923acf744fbe2da303fb06da859ee8772b5d2051d300b10b74314b7e25ace9998ca66eb2c7fbc10ef130dd67028293ca140fd3d05766f0087d57bf99df05731e894392ffcc8e8d7e960ba73c09824aaa1e031c8bc9bec3b610cf7b36eb3bf3aa40237c9e5be2c7893878578439eb00bf7f02ac4729abaa97c01aa6526ba909c3bcb16c7f47c7e13dfdc5a1b15f647b40507030309000404000000080009030a0000000000000008000502336201000c050e00040507158e24658f6c59298c080000000100000000000000ff0c090e000d01020b0a060716494710642cb0c646080000000200000000000000ff0600").to_vec(); + check_tx_encoding(serialized_tx, expected_serialized_tx.to_vec()); } #[ignore] #[test] fn test_encode_tx_fetch() { - let tx: LegacyTransaction = LegacyTransaction { + let tx: VersionedTransaction = VersionedTransaction { signatures: vec![ SolSignature(hex_literal::hex!( "94b38e57e31dc130acdec802f60b2095b72916a44834f8b0a40b7e4949661c9e4e05aa3fa5a3dc3e285c8d16c8eaab079d4477daa76e9e4a1915603eda58bc0c" )), ], - message: LegacyMessage { + message: VersionedMessage::V0( VersionedMessageV0 { header: MessageHeader { num_required_signatures: 1, num_readonly_signed_accounts: 0, @@ -1040,10 +992,11 @@ fn test_encode_tx_fetch() { data: hex_literal::hex!("8e24658f6c59298c080000000500000000000000fe").to_vec(), }, ], - }, + address_table_lookups: vec![], + }), }; let serialized_tx = tx.finalize_and_serialize().unwrap(); - let expected_serialized_tx = hex_literal::hex!("0194b38e57e31dc130acdec802f60b2095b72916a44834f8b0a40b7e4949661c9e4e05aa3fa5a3dc3e285c8d16c8eaab079d4477daa76e9e4a1915603eda58bc0c010009162e8944a76efbece296221e736627f4528a947578263a1172a9786410702d2ef2114f68f4ee9add615457c9a7791269b4d4ab3168d43d5da0e018e2d547d8be92287f3b39b93c6699d704cb3d3edcf633cb8068010c5e5f6e64583078f5cd370e3e1cb8c1bfc20346cebcaa28a53b234acf92771f72151b2d6aaa1d765be4b93c45f3121cddc0bab152917a22710c9fab5be66d121bf2474d4d484f0f2eed97804813c8373d2bfc1592855e2d93b70ecd407fe9338b11ff0bb10650716709f6a7491102d3be1d348108b41a801904392e50cd5b443a0991f3c1db0427634627da5d89a80ca1700def3a784b845b59f9c2a61bb07941ddcb4fd2d709c3243c135079c03bceb9ddea819e956b2b332e87fbbf49fc8968df78488e88cfaa366f3036c9b5b17535d2dcb7a1a505fbadc9ea27cddada4b7c144e549cf880e8db046d77ca586493b85289057a8661f9f2a81e546fcf8cc6f5c9df1f5441c822f6fabfc9e392cd98d3284fd551604be95c14cc8e20123e2940ef9fb784e6b591c7442864efe57cc00ff8edda422ba876d38f5905694bfbef1c35deaea90295968dc1333900000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea940000006ddf6e1d765a193d9cbe146ceeb79ac1cb485ed5f5b37913a8cf5857eff00a90fb9ba52b1f09445f1e3a7508d59f0797923acf744fbe2da303fb06da859ee872b635a1da73cd5bf15a26f1170f49366f0f48d28b0a8b1cebc5f98c75e475e6842be1bb8dfd763b0e83541c9767712ad0d89cecea13b46504370096a20c762fb72b5d2051d300b10b74314b7e25ace9998ca66eb2c7fbc10ef130dd67028293ca1e031c8bc9bec3b610cf7b36eb3bf3aa40237c9e5be2c7893878578439eb00b9a5e41fc2cbe01a629ce980d5c6aa9c0a8b7be9d83ac835586feba35181d4246080d030b0f0004040000000e0009030a000000000000000e000502a71903001409150012090811100a0d16494710642cb0c646080000001e00000000000000fd061405150003010d158e24658f6c59298c080000001400000000000000fd14091500130c081110020d16494710642cb0c646080000000e00000000000000ff061405150004060d158e24658f6c59298c080000000f00000000000000fb1405150007050d158e24658f6c59298c080000000500000000000000fe").to_vec(); - assert_eq!(serialized_tx, expected_serialized_tx); + let expected_serialized_tx = hex_literal::hex!("0194b38e57e31dc130acdec802f60b2095b72916a44834f8b0a40b7e4949661c9e4e05aa3fa5a3dc3e285c8d16c8eaab079d4477daa76e9e4a1915603eda58bc0c80010009162e8944a76efbece296221e736627f4528a947578263a1172a9786410702d2ef2114f68f4ee9add615457c9a7791269b4d4ab3168d43d5da0e018e2d547d8be92287f3b39b93c6699d704cb3d3edcf633cb8068010c5e5f6e64583078f5cd370e3e1cb8c1bfc20346cebcaa28a53b234acf92771f72151b2d6aaa1d765be4b93c45f3121cddc0bab152917a22710c9fab5be66d121bf2474d4d484f0f2eed97804813c8373d2bfc1592855e2d93b70ecd407fe9338b11ff0bb10650716709f6a7491102d3be1d348108b41a801904392e50cd5b443a0991f3c1db0427634627da5d89a80ca1700def3a784b845b59f9c2a61bb07941ddcb4fd2d709c3243c135079c03bceb9ddea819e956b2b332e87fbbf49fc8968df78488e88cfaa366f3036c9b5b17535d2dcb7a1a505fbadc9ea27cddada4b7c144e549cf880e8db046d77ca586493b85289057a8661f9f2a81e546fcf8cc6f5c9df1f5441c822f6fabfc9e392cd98d3284fd551604be95c14cc8e20123e2940ef9fb784e6b591c7442864efe57cc00ff8edda422ba876d38f5905694bfbef1c35deaea90295968dc1333900000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea940000006ddf6e1d765a193d9cbe146ceeb79ac1cb485ed5f5b37913a8cf5857eff00a90fb9ba52b1f09445f1e3a7508d59f0797923acf744fbe2da303fb06da859ee872b635a1da73cd5bf15a26f1170f49366f0f48d28b0a8b1cebc5f98c75e475e6842be1bb8dfd763b0e83541c9767712ad0d89cecea13b46504370096a20c762fb72b5d2051d300b10b74314b7e25ace9998ca66eb2c7fbc10ef130dd67028293ca1e031c8bc9bec3b610cf7b36eb3bf3aa40237c9e5be2c7893878578439eb00b9a5e41fc2cbe01a629ce980d5c6aa9c0a8b7be9d83ac835586feba35181d4246080d030b0f0004040000000e0009030a000000000000000e000502a71903001409150012090811100a0d16494710642cb0c646080000001e00000000000000fd061405150003010d158e24658f6c59298c080000001400000000000000fd14091500130c081110020d16494710642cb0c646080000000e00000000000000ff061405150004060d158e24658f6c59298c080000000f00000000000000fb1405150007050d158e24658f6c59298c080000000500000000000000fe00").to_vec(); + check_tx_encoding(serialized_tx, expected_serialized_tx.to_vec()); } diff --git a/state-chain/chains/src/sol/transaction_builder.rs b/state-chain/chains/src/sol/transaction_builder.rs index 456d11d887d..fed9c8aa220 100644 --- a/state-chain/chains/src/sol/transaction_builder.rs +++ b/state-chain/chains/src/sol/transaction_builder.rs @@ -33,8 +33,9 @@ use crate::{ token_instructions::AssociatedTokenAccountInstruction, AccountMeta, }, - AccountBump, SolAddress, SolAmount, SolApiEnvironment, SolAsset, SolCcmAccounts, - SolComputeLimit, SolInstruction, SolLegacyMessage, SolLegacyTransaction, SolPubkey, Solana, + AccountBump, SolAddress, SolAddressLookupTableAccount, SolAmount, SolApiEnvironment, + SolAsset, SolCcmAccounts, SolComputeLimit, SolInstruction, SolPubkey, SolVersionedMessage, + SolVersionedTransaction, Solana, }, FetchAssetParams, ForeignChainAddress, }; @@ -65,14 +66,15 @@ impl SolanaTransactionBuilder { /// complete. This will add some extra instruction required for the integrity of the Solana /// Transaction. /// - /// Returns the finished Instruction Set to construct the SolLegacyTransaction. + /// Returns the finished Instruction Set to construct the SolVersionedTransaction. fn build( mut instructions: Vec, durable_nonce: DurableNonceAndAccount, agg_key: SolPubkey, compute_price: SolAmount, compute_limit: SolComputeLimit, - ) -> Result { + address_lookup_tables: Vec, + ) -> Result { let mut final_instructions = vec![SystemProgramInstruction::advance_nonce_account( &durable_nonce.0.into(), &agg_key, @@ -88,10 +90,11 @@ impl SolanaTransactionBuilder { final_instructions.append(&mut instructions); // Test serialize the final transaction to obtain its length. - let transaction = SolLegacyTransaction::new_unsigned(SolLegacyMessage::new_with_blockhash( + let transaction = SolVersionedTransaction::new_unsigned(SolVersionedMessage::new( &final_instructions, - Some(&agg_key), - &durable_nonce.1.into(), + Some(agg_key), + Some(durable_nonce.1.into()), + &address_lookup_tables[..], )); let mock_serialized_tx = transaction @@ -116,7 +119,8 @@ impl SolanaTransactionBuilder { agg_key: SolAddress, durable_nonce: DurableNonceAndAccount, compute_price: SolAmount, - ) -> Result { + address_lookup_tables: Vec, + ) -> Result { let mut compute_limit: SolComputeLimit = BASE_COMPUTE_UNITS_PER_TX; let instructions = fetch_params .into_iter() @@ -186,6 +190,7 @@ impl SolanaTransactionBuilder { agg_key.into(), compute_price, compute_limit_with_buffer(compute_limit), + address_lookup_tables, ) } @@ -197,7 +202,7 @@ impl SolanaTransactionBuilder { agg_key: SolAddress, durable_nonce: DurableNonceAndAccount, compute_price: SolAmount, - ) -> Result { + ) -> Result { let instructions = vec![SystemProgramInstruction::transfer(&agg_key.into(), &to.into(), amount)]; @@ -209,6 +214,7 @@ impl SolanaTransactionBuilder { compute_limit_with_buffer( BASE_COMPUTE_UNITS_PER_TX + COMPUTE_UNITS_PER_TRANSFER_NATIVE, ), + vec![], ) } @@ -226,7 +232,8 @@ impl SolanaTransactionBuilder { durable_nonce: DurableNonceAndAccount, compute_price: SolAmount, token_decimals: u8, - ) -> Result { + address_lookup_tables: Vec, + ) -> Result { let instructions = vec![ AssociatedTokenAccountInstruction::create_associated_token_account_idempotent_instruction( &agg_key.into(), @@ -253,6 +260,7 @@ impl SolanaTransactionBuilder { agg_key.into(), compute_price, compute_limit_with_buffer(BASE_COMPUTE_UNITS_PER_TX + COMPUTE_UNITS_PER_TRANSFER_TOKEN), + address_lookup_tables, ) } @@ -265,7 +273,8 @@ impl SolanaTransactionBuilder { agg_key: SolAddress, durable_nonce: DurableNonceAndAccount, compute_price: SolAmount, - ) -> Result { + address_lookup_tables: Vec, + ) -> Result { let mut instructions = vec![VaultProgram::with_id(vault_program).rotate_agg_key( false, vault_program_data_account, @@ -287,6 +296,7 @@ impl SolanaTransactionBuilder { agg_key.into(), compute_price, compute_limit_with_buffer(COMPUTE_UNITS_PER_ROTATION), + address_lookup_tables, ) } @@ -304,7 +314,8 @@ impl SolanaTransactionBuilder { durable_nonce: DurableNonceAndAccount, compute_price: SolAmount, compute_limit: SolComputeLimit, - ) -> Result { + address_lookup_tables: Vec, + ) -> Result { let instructions = vec![ SystemProgramInstruction::transfer(&agg_key.into(), &to.into(), amount), VaultProgram::with_id(vault_program) @@ -323,7 +334,14 @@ impl SolanaTransactionBuilder { .with_additional_accounts(ccm_accounts.additional_account_metas()), ]; - Self::build(instructions, durable_nonce, agg_key.into(), compute_price, compute_limit) + Self::build( + instructions, + durable_nonce, + agg_key.into(), + compute_price, + compute_limit, + address_lookup_tables, + ) } pub fn ccm_transfer_token( @@ -344,7 +362,8 @@ impl SolanaTransactionBuilder { compute_price: SolAmount, token_decimals: u8, compute_limit: SolComputeLimit, - ) -> Result { + address_lookup_tables: Vec, + ) -> Result { let instructions = vec![ AssociatedTokenAccountInstruction::create_associated_token_account_idempotent_instruction( &agg_key.into(), @@ -377,7 +396,14 @@ impl SolanaTransactionBuilder { sys_var_instructions(), ).with_additional_accounts(ccm_accounts.additional_account_metas())]; - Self::build(instructions, durable_nonce, agg_key.into(), compute_price, compute_limit) + Self::build( + instructions, + durable_nonce, + agg_key.into(), + compute_price, + compute_limit, + address_lookup_tables, + ) } /// Create an instruction set to set the current GovKey with the agg key. @@ -388,7 +414,8 @@ impl SolanaTransactionBuilder { agg_key: SolAddress, durable_nonce: DurableNonceAndAccount, compute_price: SolAmount, - ) -> Result { + address_lookup_tables: Vec, + ) -> Result { let instructions = vec![VaultProgram::with_id(vault_program).set_gov_key_with_agg_key( new_gov_key.into(), vault_program_data_account, @@ -401,6 +428,7 @@ impl SolanaTransactionBuilder { agg_key.into(), compute_price, compute_limit_with_buffer(COMPUTE_UNITS_PER_SET_GOV_KEY), + address_lookup_tables, ) } @@ -414,7 +442,8 @@ impl SolanaTransactionBuilder { agg_key: SolAddress, durable_nonce: DurableNonceAndAccount, compute_price: SolAmount, - ) -> Result { + address_lookup_tables: Vec, + ) -> Result { let number_of_accounts = vault_swap_accounts.len(); let swap_and_sender_vec: Vec = vault_swap_accounts .into_iter() @@ -457,6 +486,7 @@ impl SolanaTransactionBuilder { COMPUTE_UNITS_PER_FETCH_AND_CLOSE_VAULT_SWAP_ACCOUNTS + COMPUTE_UNITS_PER_CLOSE_ACCOUNT * number_of_accounts as u32, ), + address_lookup_tables, ) } @@ -472,7 +502,8 @@ impl SolanaTransactionBuilder { gov_key: SolAddress, durable_nonce: DurableNonceAndAccount, compute_price: SolAmount, - ) -> Result { + address_lookup_tables: Vec, + ) -> Result { let instructions = vec![VaultProgram::with_id(vault_program).set_program_swaps_parameters( min_native_swap_amount, max_dst_address_len, @@ -489,6 +520,7 @@ impl SolanaTransactionBuilder { gov_key.into(), compute_price, compute_limit_with_buffer(COMPUTE_UNITS_PER_SET_PROGRAM_SWAPS_PARAMS), + address_lookup_tables, ) } @@ -501,7 +533,8 @@ impl SolanaTransactionBuilder { gov_key: SolAddress, durable_nonce: DurableNonceAndAccount, compute_price: SolAmount, - ) -> Result { + address_lookup_tables: Vec, + ) -> Result { let token_supported_account = derive_token_supported_account(vault_program, token_mint_pubkey) .map_err(SolanaTransactionBuildingError::FailedToDeriveAddress)?; @@ -521,6 +554,7 @@ impl SolanaTransactionBuilder { gov_key.into(), compute_price, compute_limit_with_buffer(COMPUTE_UNITS_PER_ENABLE_TOKEN_SUPPORT), + address_lookup_tables, ) } } @@ -565,11 +599,12 @@ pub mod test { agg_key(), durable_nonce(), compute_price(), + vec![chainflip_alt()], ) .unwrap(); // Serialized tx built in `create_fetch_native` test - let expected_serialized_tx = hex_literal::hex!("015209c97accd5ca5e27c5d3c8a3264ec0e754e0ad6f53ad11ca58e043db14d8f8d25ee05b6d5b263234ce0eea4010bf0211fed0c631b393ad8053b799e7d63f0701000509f79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb17eb2b10d3377bda2bc7bea65bec6b8372f4fc3463ec2cd6f9fde4b2c633d1923a4539fbb757256442c16343f639b15db95c39a6d35721439f7f94f5c8776b7bfd35d0bf8686de2e369c3d97a8033b31e6bc33518629f59314bc3d9050956c8d00000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea940000072b5d2051d300b10b74314b7e25ace9998ca66eb2c7fbc10ef130dd67028293ca1e031c8bc9bec3b610cf7b36eb3bf3aa40237c9e5be2c7893878578439eb00bc27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e489000404030106000404000000050009038096980000000000050005021f95000007050800030204158e24658f6c59298c080000000b0c0d3700000000fc").to_vec(); + let expected_serialized_tx = hex_literal::hex!("014c9e86bf4a01223aaad71560605c3bf8925aebaec28dad02ae7008290cf3682e649ab82d087c387d5ae72d362852737ce5802d48b17e054500bf8ad40787890e8001000407f79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb3a4539fbb757256442c16343f639b15db95c39a6d35721439f7f94f5c8776b7bfd35d0bf8686de2e369c3d97a8033b31e6bc33518629f59314bc3d9050956c8d00000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea940000072b5d2051d300b10b74314b7e25ace9998ca66eb2c7fbc10ef130dd67028293cc27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e489000403030705000404000000040009038096980000000000040005021f95000006050800020103158e24658f6c59298c080000000b0c0d3700000000fc013001afd71da9456a977233960b08eba77d2e3690b8c7259637c8fb8f82cf58a101090102").to_vec(); test_constructed_transaction(transaction, expected_serialized_tx); } @@ -587,11 +622,12 @@ pub mod test { agg_key(), durable_nonce(), compute_price(), + vec![chainflip_alt()], ) .unwrap(); // Serialized tx built in `create_fetch_native_in_batch` test - let expected_serialized_tx = hex_literal::hex!("0196d9b370524f1d7b185958b3eb06b355945a0d50f3b38c034a47e339105ca4ebfd290834dccde71958057e1e82f15ac08dcbf8610838764052f6bf16fa8c08090100050bf79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb17eb2b10d3377bda2bc7bea65bec6b8372f4fc3463ec2cd6f9fde4b2c633d19238861d2f0bf5cd80031b701a6c25d13b4c812dd92f9d6301fafd9a58fb9e438646cd507258c10454d484e64ba59d3e7570658001c5f854b6b3ebb57be90e7a708d9871ed5fb2ee05765af23b7cabcc0d6b08ed370bb9f616a0d4dea40a25f870b5b9d633289c8fd72fb05f33349bf4cc44e82add5d865311ae346d7c9a67b7dd00000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea940000072b5d2051d300b10b74314b7e25ace9998ca66eb2c7fbc10ef130dd67028293ca1e031c8bc9bec3b610cf7b36eb3bf3aa40237c9e5be2c7893878578439eb00bc27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e48900050603010800040400000007000903809698000000000007000502c34a010009050a00030206158e24658f6c59298c080000000000000000000000ff09050a00040506158e24658f6c59298c080000000100000000000000ff").to_vec(); + let expected_serialized_tx = hex_literal::hex!("012a95015c2c1a08af3013fd2575a7f61bf3a4faca1a010f7ec29f017ff10b52c49b9b8113e1adc89a9248c9537bff2eb3b2ca5bfafe9abbe4fbea753fccc139008001000409f79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb38861d2f0bf5cd80031b701a6c25d13b4c812dd92f9d6301fafd9a58fb9e438646cd507258c10454d484e64ba59d3e7570658001c5f854b6b3ebb57be90e7a708d9871ed5fb2ee05765af23b7cabcc0d6b08ed370bb9f616a0d4dea40a25f870b5b9d633289c8fd72fb05f33349bf4cc44e82add5d865311ae346d7c9a67b7dd00000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea940000072b5d2051d300b10b74314b7e25ace9998ca66eb2c7fbc10ef130dd67028293cc27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e48900050503090700040400000006000903809698000000000006000502c34a010008050a00020105158e24658f6c59298c080000000000000000000000ff08050a00030405158e24658f6c59298c080000000100000000000000ff013001afd71da9456a977233960b08eba77d2e3690b8c7259637c8fb8f82cf58a101090102").to_vec(); test_constructed_transaction(transaction, expected_serialized_tx); } @@ -605,11 +641,12 @@ pub mod test { agg_key(), durable_nonce(), compute_price(), + vec![chainflip_alt()], ) .unwrap(); // Serialized tx built in `create_fetch_tokens` test - let expected_serialized_tx = hex_literal::hex!("01adb99aa6d5cef660e14d01cd0d78a74dc0046bb6e8e3719fb524c548271e0348d2253f2ffcbd4ecdf12c1d79f97596dbf8d54638b409982debde797c65e0d3000100080df79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb17eb2b10d3377bda2bc7bea65bec6b8372f4fc3463ec2cd6f9fde4b2c633d19242ff6863b52c3f8faf95739e6541bda5d0ac593f00c6c07d9ab37096bf26d910ae85f2fb6289c70bfe37df150dddb17dd84f403fd0b1aa1bfee85795159de21fe91372b3d301c202a633da0a92365a736e462131aecfad1fac47322cf8863ada00000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea940000006ddf6e1d765a193d9cbe146ceeb79ac1cb485ed5f5b37913a8cf5857eff00a90fb9ba52b1f09445f1e3a7508d59f0797923acf744fbe2da303fb06da859ee8746cd507258c10454d484e64ba59d3e7570658001c5f854b6b3ebb57be90e7a7072b5d2051d300b10b74314b7e25ace9998ca66eb2c7fbc10ef130dd67028293ca1e031c8bc9bec3b610cf7b36eb3bf3aa40237c9e5be2c7893878578439eb00bc27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e489000405030107000404000000060009038096980000000000060005024f0a01000b090c000a02040908030516494710642cb0c646080000000000000000000000ff06").to_vec(); + let expected_serialized_tx = hex_literal::hex!("0171e6c4881666cb11c8ab4402a1b0b5728c5a18acd668b0ffb524d913ff5bb717597564d05880a8e693ea3c6fd329750e88a0b6de6f97fa62a0c428b020cbea0e8001000609f79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb42ff6863b52c3f8faf95739e6541bda5d0ac593f00c6c07d9ab37096bf26d910ae85f2fb6289c70bfe37df150dddb17dd84f403fd0b1aa1bfee85795159de21f00000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea940000006ddf6e1d765a193d9cbe146ceeb79ac1cb485ed5f5b37913a8cf5857eff00a946cd507258c10454d484e64ba59d3e7570658001c5f854b6b3ebb57be90e7a7072b5d2051d300b10b74314b7e25ace9998ca66eb2c7fbc10ef130dd67028293cc27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e489000403030905000404000000040009038096980000000000040005024f0a010008090c0007010a0b06020316494710642cb0c646080000000000000000000000ff06013001afd71da9456a977233960b08eba77d2e3690b8c7259637c8fb8f82cf58a1020905020302").to_vec(); test_constructed_transaction(transaction, expected_serialized_tx); } @@ -626,11 +663,12 @@ pub mod test { agg_key(), durable_nonce(), compute_price(), + vec![chainflip_alt()], ) .unwrap(); // Serialized tx built in `create_batch_fetch` test - let expected_serialized_tx = hex_literal::hex!("0172ba9088cd8a6229db1ec41c83295eebb8ea509103efc26969a1b1cc0cc5901799ced09e740d1bd01430dad236180e7b510a52dfed86fb7c6f527bca2054630401000912f79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb17eb2b10d3377bda2bc7bea65bec6b8372f4fc3463ec2cd6f9fde4b2c633d1921ad0968d57ee79348476716f9b2cd44ec4284b8f52c36648d560949e41589a5540de1c0451cccb6edd1fda9b4a48c282b279350b55a7a9716800cc0132b6f0b042ff6863b52c3f8faf95739e6541bda5d0ac593f00c6c07d9ab37096bf26d910a140fd3d05766f0087d57bf99df05731e894392ffcc8e8d7e960ba73c09824aaae85f2fb6289c70bfe37df150dddb17dd84f403fd0b1aa1bfee85795159de21fb4baefcd4965beb1c71311a2ffe76419d4b8f8d35fbc4cf514b1bd02da2df2e3e91372b3d301c202a633da0a92365a736e462131aecfad1fac47322cf8863ada00000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea940000006ddf6e1d765a193d9cbe146ceeb79ac1cb485ed5f5b37913a8cf5857eff00a90fb9ba52b1f09445f1e3a7508d59f0797923acf744fbe2da303fb06da859ee8746cd507258c10454d484e64ba59d3e7570658001c5f854b6b3ebb57be90e7a7072b5d2051d300b10b74314b7e25ace9998ca66eb2c7fbc10ef130dd67028293c8d9871ed5fb2ee05765af23b7cabcc0d6b08ed370bb9f616a0d4dea40a25f870a1e031c8bc9bec3b610cf7b36eb3bf3aa40237c9e5be2c7893878578439eb00bc27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e48900060903010b0004040000000a00090380969800000000000a000502e7bb02000f0911000e04080d0c060916494710642cb0c646080000000000000000000000ff060f0911001002080d0c030916494710642cb0c646080000000100000000000000ff060f051100050709158e24658f6c59298c080000000200000000000000ff").to_vec(); + let expected_serialized_tx = hex_literal::hex!("015eab79254444f6f235494a180b8c0c11fe4ee73c85656eda36b4dccf717ace5d0613540e9d3febb4b439f86b45bfdb26ba4810e17d224efd8ad13c2f34f09f0a800100070ef79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb1ad0968d57ee79348476716f9b2cd44ec4284b8f52c36648d560949e41589a5540de1c0451cccb6edd1fda9b4a48c282b279350b55a7a9716800cc0132b6f0b042ff6863b52c3f8faf95739e6541bda5d0ac593f00c6c07d9ab37096bf26d910a140fd3d05766f0087d57bf99df05731e894392ffcc8e8d7e960ba73c09824aaae85f2fb6289c70bfe37df150dddb17dd84f403fd0b1aa1bfee85795159de21fb4baefcd4965beb1c71311a2ffe76419d4b8f8d35fbc4cf514b1bd02da2df2e300000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea940000006ddf6e1d765a193d9cbe146ceeb79ac1cb485ed5f5b37913a8cf5857eff00a946cd507258c10454d484e64ba59d3e7570658001c5f854b6b3ebb57be90e7a7072b5d2051d300b10b74314b7e25ace9998ca66eb2c7fbc10ef130dd67028293c8d9871ed5fb2ee05765af23b7cabcc0d6b08ed370bb9f616a0d4dea40a25f870c27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e489000607030e0900040400000008000903809698000000000008000502e7bb02000c0911000b030f100a050716494710642cb0c646080000000000000000000000ff060c0911000d010f100a020716494710642cb0c646080000000100000000000000ff060c051100040607158e24658f6c59298c080000000200000000000000ff013001afd71da9456a977233960b08eba77d2e3690b8c7259637c8fb8f82cf58a1020905020302").to_vec(); test_constructed_transaction(transaction, expected_serialized_tx); } @@ -647,7 +685,7 @@ pub mod test { .unwrap(); // Serialized tx built in `create_transfer_native` test - let expected_serialized_tx = hex_literal::hex!("01c3eec1d2c8ccf7a5eb2bbfe8819a1b46e0fb7409c809f9b01f09b049f455c964ed545aad28cd6b7f8bdc6df41f8b5b2df5e36115893e431053ad6ddc02da0d0701000306f79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb17eb2b10d3377bda2bc7bea65bec6b8372f4fc3463ec2cd6f9fde4b2c633d19231e9528aae784fecbbd0bee129d9539c57be0e90061af6b6f4a5e274654e5bd400000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea9400000c27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e4890004030301050004040000000400090380969800000000000400050284030000030200020c0200000000ca9a3b00000000").to_vec(); + let expected_serialized_tx = hex_literal::hex!("01cf95647e8340f44ff54c971187192f31f12abe07d1a2c12bfa21c8a36b311efdcf4f80323c52025cea58480b3a62ad3b7e39b86fb1f6d2f793fe9d3bd1b3a2018001000306f79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb17eb2b10d3377bda2bc7bea65bec6b8372f4fc3463ec2cd6f9fde4b2c633d19231e9528aae784fecbbd0bee129d9539c57be0e90061af6b6f4a5e274654e5bd400000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea9400000c27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e4890004030301050004040000000400090380969800000000000400050284030000030200020c0200000000ca9a3b0000000000").to_vec(); test_constructed_transaction(transaction, expected_serialized_tx); } @@ -676,11 +714,12 @@ pub mod test { durable_nonce(), compute_price(), SOL_USDC_DECIMAL, + vec![chainflip_alt()], ) .unwrap(); // Serialized tx built in `create_transfer_token` test - let expected_serialized_tx = hex_literal::hex!("01940a66ffe66a72d345e45eedb1c54e6b051ed71ae13f5c354a682e2a3f9aba0161855cd404f1ab0e65c294f350803f9c0a040cb8c16c40fd8103293ab454a40501000a0ef79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb17eb2b10d3377bda2bc7bea65bec6b8372f4fc3463ec2cd6f9fde4b2c633d1925ec7baaea7200eb2a66ccd361ee73bc87a7e5222ecedcbc946e97afb59ec4616e91372b3d301c202a633da0a92365a736e462131aecfad1fac47322cf8863ada00000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea940000006ddf6e1d765a193d9cbe146ceeb79ac1cb485ed5f5b37913a8cf5857eff00a90fb9ba52b1f09445f1e3a7508d59f0797923acf744fbe2da303fb06da859ee8731e9528aae784fecbbd0bee129d9539c57be0e90061af6b6f4a5e274654e5bd472b5d2051d300b10b74314b7e25ace9998ca66eb2c7fbc10ef130dd67028293c8c97258f4e2489f1bb3d1029148e0d830b5a1399daff1084048e7bd8dbe9f859a1e031c8bc9bec3b610cf7b36eb3bf3aa40237c9e5be2c7893878578439eb00bab1d2a644046552e73f4d05b5a6ef53848973a9ee9febba42ddefb034b5f5130c27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e489000504030106000404000000050009038096980000000000050005029b2701000b0600020908040701010a070c000d030208071136b4eeaf4a557ebc00ca9a3b0000000006").to_vec(); + let expected_serialized_tx = hex_literal::hex!("0128fe27ffdfed999b2b9e00e1327bcc1e22370dd2475633023172607ee98df3e14e3f6f45c23ee0988c1b605be91f416ab6d5f0d477a6f30615429d20e443a7098001000709f79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb5ec7baaea7200eb2a66ccd361ee73bc87a7e5222ecedcbc946e97afb59ec461600000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea940000006ddf6e1d765a193d9cbe146ceeb79ac1cb485ed5f5b37913a8cf5857eff00a931e9528aae784fecbbd0bee129d9539c57be0e90061af6b6f4a5e274654e5bd472b5d2051d300b10b74314b7e25ace9998ca66eb2c7fbc10ef130dd67028293c8c97258f4e2489f1bb3d1029148e0d830b5a1399daff1084048e7bd8dbe9f859c27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e489000502030904000404000000030009038096980000000000030005029b27010008060001060b0205010107070c000d0a010b051136b4eeaf4a557ebc00ca9a3b0000000006013001afd71da9456a977233960b08eba77d2e3690b8c7259637c8fb8f82cf58a102090503030204").to_vec(); test_constructed_transaction(transaction, expected_serialized_tx); } @@ -697,11 +736,12 @@ pub mod test { agg_key(), durable_nonce(), compute_price(), + vec![chainflip_alt()], ) .unwrap(); // Serialized tx built in `rotate_agg_key` test - let expected_serialized_tx = hex_literal::hex!("012aed8e2d575872e3068dfdaf234fd02349d6e05015a369efb6fa11997b79aaaa531329bc383dd0e8595bf796cd2729b1a9a1504bfa0f473a4bb5cab3cc154b0701000411f79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb17eb2b10d3377bda2bc7bea65bec6b8372f4fc3463ec2cd6f9fde4b2c633d1926744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be5439900448541f57201f277c5f3ffb631d0212e26e7f47749c26c4808718174a0ab2a09a18cd28baa84f2067bbdf24513c2d44e44bf408f2e6da6e60762e3faa4a62a0adba1e031c8bc9bec3b610cf7b36eb3bf3aa40237c9e5be2c7893878578439eb00bcd644e45426a41a7cb8369b8a0c1c89bb3f86cf278fdd9cc38b0f69784ad5667e392cd98d3284fd551604be95c14cc8e20123e2940ef9fb784e6b591c7442864e5e1869817a4fd88ddf7ab7a5f7252d7c345b39721769888608592912e8ca9acf0f13460b3fd04b7d53d7421fc874ec00eec769cf36480895e1a407bf1249475f2b2e24122be016983be9369965246cc45e1f621d40fba300c56c7ac50c3874df4f83bd213a59c9785110cf83c718f9486c3484f918593bce20c61dc6a96036afecc89e3b031824af6363174d19bbec12d3a13c4a173e5aeb349b63042bc138f00000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea940000072b5d2051d300b10b74314b7e25ace9998ca66eb2c7fbc10ef130dd67028293cc27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e489000e0d03010f0004040000000e00090380969800000000000e000502e02e000010040500020d094e518fabdda5d68b000d02010024070000006744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be5439900440d020b0024070000006744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be5439900440d02090024070000006744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be5439900440d020a0024070000006744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be5439900440d02070024070000006744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be5439900440d02060024070000006744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be5439900440d02030024070000006744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be5439900440d020c0024070000006744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be5439900440d02080024070000006744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be5439900440d02040024070000006744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be543990044").to_vec(); + let expected_serialized_tx = hex_literal::hex!("01ab37f60681ba0afe0aeda3c39f5021f49332695e63243af28769b59de314f4b62445271f2155e4d49c83153b63a9c64ddeb2feda66acf2ad6058f411c95cf7038001000406f79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb6744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be54399004400000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea940000072b5d2051d300b10b74314b7e25ace9998ca66eb2c7fbc10ef130dd67028293cc27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e489000e0203060400040400000003000903809698000000000003000502e02e0000050409000102094e518fabdda5d68b000202060024070000006744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be54399004402020f0024070000006744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be54399004402020d0024070000006744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be54399004402020e0024070000006744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be54399004402020b0024070000006744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be54399004402020a0024070000006744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be5439900440202070024070000006744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be5439900440202100024070000006744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be54399004402020c0024070000006744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be5439900440202080024070000006744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be543990044013001afd71da9456a977233960b08eba77d2e3690b8c7259637c8fb8f82cf58a10b090f12020e0d110b0c0a1000").to_vec(); test_constructed_transaction(transaction, expected_serialized_tx); } @@ -718,11 +758,12 @@ pub mod test { agg_key(), durable_nonce(), compute_price(), + vec![chainflip_alt()], ) .unwrap(); // Serialized tx built in `fetch_and_close_vault_swap_accounts` test - let expected_serialized_tx = hex_literal::hex!("01cd1677377a30a65d0e4640d54ddb5bbf83989f66f72201ad63c2681f618612312cfa488ce6cfc37fe5ecc9046aa9b4d8c50ef5aad8e98bb782ecdceb2bd6cf0d0100050bf79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb17e5cc1f4d51a40626e11c783b75a45a4922615ecd7f5320b9d4d46481a196a317eb2b10d3377bda2bc7bea65bec6b8372f4fc3463ec2cd6f9fde4b2c633d1921c1f0efc91eeb48bb80c90cf97775cd5d843a96f16500266cee2c20d053152d2665730decf59d4cd6db8437dab77302287431eb7562b5997601851a0eab6946fc8bb64258728f7a98b57a72fade81639eb845674b3d259b51991a97a1821a31900000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea94000001ef91c791d2aa8492c90f12540abd10056ce5dd8d9ab08461476c1dcc1622938a1e031c8bc9bec3b610cf7b36eb3bf3aa40237c9e5be2c7893878578439eb00bc27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e489000506030208000404000000070009038096980000000000070005025898000009040a050006098579b3e88abc5343fe09050a0003010408a5663d01b94dbd79").to_vec(); + let expected_serialized_tx = hex_literal::hex!("01d61138dfa0a3d4d9b19a9f10db9d7ad45fcac1a27766ce497bc7490ddceebc91046ae06adfcda2d9533c5670f1bf868e2adc607a9c16c2efe8e969531ec009048001000408f79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb17e5cc1f4d51a40626e11c783b75a45a4922615ecd7f5320b9d4d46481a196a3665730decf59d4cd6db8437dab77302287431eb7562b5997601851a0eab6946fc8bb64258728f7a98b57a72fade81639eb845674b3d259b51991a97a1821a31900000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea94000001ef91c791d2aa8492c90f12540abd10056ce5dd8d9ab08461476c1dcc1622938c27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e489000504030806000404000000050009038096980000000000050005025898000007040a030004098579b3e88abc5343fe07050a0009010208a5663d01b94dbd79013001afd71da9456a977233960b08eba77d2e3690b8c7259637c8fb8f82cf58a10209080102").to_vec(); test_constructed_transaction(transaction, expected_serialized_tx); } @@ -748,10 +789,11 @@ pub mod test { agg_key(), durable_nonce(), compute_price(), + vec![chainflip_alt()], ) .unwrap(); - let expected_serialized_tx = hex_literal::hex!("01266e852bae2d37833fd43fed3c2b24083af053de8e9fade9e65ef13c6475410c0c4573eb832ce790ec7cbfde3f58aa28b1742f791c15041ccab9b2cb8c5acf0101000513f79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb05a557a331e51b8bf444d3bacdf6f48d8fd583aa79f9b956dd68f13a67ad096417e5cc1f4d51a40626e11c783b75a45a4922615ecd7f5320b9d4d46481a196a317eb2b10d3377bda2bc7bea65bec6b8372f4fc3463ec2cd6f9fde4b2c633d1921c11d80c98e8c11e79fd97b6c10ad733782bdbe25a710b807bbf14dedaa314861c1f0efc91eeb48bb80c90cf97775cd5d843a96f16500266cee2c20d053152d257d7f5b3e6c340824caca3b6c34c03e2fe0e636430b2b729ddfe32146ba4b3795c4b1e73c84b8d3f9e006c22fe8b865b9900e296345d88cdaaa7077ef17d9a31665730decf59d4cd6db8437dab77302287431eb7562b5997601851a0eab6946fa7e867ab720f01897e5ede67fc232e41729d0be2a530391619743822ff6d95bea9dff663e1d13345d96daede8066cd30a1474635f2d64052d1a50ac04aed3f99bd9ce2f9674b65bfaefb62c9b8252fd0080357b1cbff44d0dad8568535dbc230c8bb64258728f7a98b57a72fade81639eb845674b3d259b51991a97a1821a319d33096c9d0fa193639345c07abfe81175fc4d153cf0ab7b5668006538f19538200000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea94000001ef91c791d2aa8492c90f12540abd10056ce5dd8d9ab08461476c1dcc1622938a1e031c8bc9bec3b610cf7b36eb3bf3aa40237c9e5be2c7893878578439eb00bc27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e48900050e0303100004040000000f00090380969800000000000f000502f82401001104120c000e098579b3e88abc5343fe110d120005020806010b0a0904070d08a5663d01b94dbd79").to_vec(); + let expected_serialized_tx = hex_literal::hex!("013ce4a7169ecb011374e4cea953491bf340bd8144f7c97b7ceb930310cda703b4e7f8296a987623c00879ddffc8dff71e3b9db2da8ef6895d50a58e92a6bf020f8001000410f79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb05a557a331e51b8bf444d3bacdf6f48d8fd583aa79f9b956dd68f13a67ad096417e5cc1f4d51a40626e11c783b75a45a4922615ecd7f5320b9d4d46481a196a31c11d80c98e8c11e79fd97b6c10ad733782bdbe25a710b807bbf14dedaa3148657d7f5b3e6c340824caca3b6c34c03e2fe0e636430b2b729ddfe32146ba4b3795c4b1e73c84b8d3f9e006c22fe8b865b9900e296345d88cdaaa7077ef17d9a31665730decf59d4cd6db8437dab77302287431eb7562b5997601851a0eab6946fa7e867ab720f01897e5ede67fc232e41729d0be2a530391619743822ff6d95bea9dff663e1d13345d96daede8066cd30a1474635f2d64052d1a50ac04aed3f99bd9ce2f9674b65bfaefb62c9b8252fd0080357b1cbff44d0dad8568535dbc230c8bb64258728f7a98b57a72fade81639eb845674b3d259b51991a97a1821a319d33096c9d0fa193639345c07abfe81175fc4d153cf0ab7b5668006538f19538200000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea94000001ef91c791d2aa8492c90f12540abd10056ce5dd8d9ab08461476c1dcc1622938c27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e48900050c03100e0004040000000d00090380969800000000000d000502f82401000f04120a000c098579b3e88abc5343fe0f0d1200110206040109080703050b08a5663d01b94dbd79013001afd71da9456a977233960b08eba77d2e3690b8c7259637c8fb8f82cf58a10209080102").to_vec(); test_constructed_transaction(transaction, expected_serialized_tx); } @@ -779,11 +821,12 @@ pub mod test { durable_nonce(), compute_price(), TEST_COMPUTE_LIMIT, + vec![chainflip_alt()], ) .unwrap(); // Serialized tx built in `create_ccm_native_transfer` test - let expected_serialized_tx = hex_literal::hex!("01f38ab7045a32761b6438c5e29a29f53685508de759f51e683b490a2927d9fe88c412fb87f2ababf85d9df74e5e46dd8f974ea44dcf2e1e1fb63955f0ae3077070100070bf79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb17eb2b10d3377bda2bc7bea65bec6b8372f4fc3463ec2cd6f9fde4b2c633d19231e9528aae784fecbbd0bee129d9539c57be0e90061af6b6f4a5e274654e5bd47417da8b99d7748127a76b03d61fee69c80dfef73ad2d5503737beedc5a9ed4800000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517187bd16635dad40455fdc2c0c124c68f215675a5dbbacb5f0800000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea940000072b5d2051d300b10b74314b7e25ace9998ca66eb2c7fbc10ef130dd67028293ca1e031c8bc9bec3b610cf7b36eb3bf3aa40237c9e5be2c7893878578439eb00ba73bdf31e341218a693b8772c43ecfcecd4cf35fada09a87ea0f860d028168e5c27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e48900050403010700040400000005000903809698000000000005000502e0930400040200020c0200000000ca9a3b0000000008070900020304060a347d050be38042e0b20100000014000000ffffffffffffffffffffffffffffffffffffffff040000007c1d0f0700ca9a3b00000000").to_vec(); + let expected_serialized_tx = hex_literal::hex!("0102281baf609788e68ce97ba072a021a6c9788bb08b6f69546b713ffa6faabf5e925c5396ea66e8dd7f2cffe0c66fa7268c63019720b752ee073e3f4bd8fac0058001000609f79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb31e9528aae784fecbbd0bee129d9539c57be0e90061af6b6f4a5e274654e5bd47417da8b99d7748127a76b03d61fee69c80dfef73ad2d5503737beedc5a9ed4800000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517187bd16635dad40455fdc2c0c124c68f215675a5dbbacb5f0800000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea940000072b5d2051d300b10b74314b7e25ace9998ca66eb2c7fbc10ef130dd67028293ca73bdf31e341218a693b8772c43ecfcecd4cf35fada09a87ea0f860d028168e5c27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e48900050303090600040400000004000903809698000000000004000502e0930400030200010c0200000000ca9a3b0000000007070a000102030508347d050be38042e0b20100000014000000ffffffffffffffffffffffffffffffffffffffff040000007c1d0f0700ca9a3b00000000013001afd71da9456a977233960b08eba77d2e3690b8c7259637c8fb8f82cf58a101090102").to_vec(); test_constructed_transaction(transaction, expected_serialized_tx); } @@ -817,11 +860,12 @@ pub mod test { compute_price(), SOL_USDC_DECIMAL, TEST_COMPUTE_LIMIT, + vec![chainflip_alt()], ) .unwrap(); // Serialized tx built in `create_ccm_token_transfer` test - let expected_serialized_tx = hex_literal::hex!("011007091828e8a0357a6e4827daaa2d6e44f79d2daf5ac45e26d409f8d7baadf8b8df231ffde59d9f581754178a695b89d7a42e197781912aa8653dac2a9e390d01000c11f79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb17eb2b10d3377bda2bc7bea65bec6b8372f4fc3463ec2cd6f9fde4b2c633d1925ec7baaea7200eb2a66ccd361ee73bc87a7e5222ecedcbc946e97afb59ec46167417da8b99d7748127a76b03d61fee69c80dfef73ad2d5503737beedc5a9ed48e91372b3d301c202a633da0a92365a736e462131aecfad1fac47322cf8863ada00000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517187bd16635dad40455fdc2c0c124c68f215675a5dbbacb5f0800000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea940000006ddf6e1d765a193d9cbe146ceeb79ac1cb485ed5f5b37913a8cf5857eff00a90fb9ba52b1f09445f1e3a7508d59f0797923acf744fbe2da303fb06da859ee8731e9528aae784fecbbd0bee129d9539c57be0e90061af6b6f4a5e274654e5bd472b5d2051d300b10b74314b7e25ace9998ca66eb2c7fbc10ef130dd67028293c8c97258f4e2489f1bb3d1029148e0d830b5a1399daff1084048e7bd8dbe9f859a1e031c8bc9bec3b610cf7b36eb3bf3aa40237c9e5be2c7893878578439eb00ba73bdf31e341218a693b8772c43ecfcecd4cf35fada09a87ea0f860d028168e5ab1d2a644046552e73f4d05b5a6ef53848973a9ee9febba42ddefb034b5f5130c27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e48900060503010800040400000006000903809698000000000006000502e09304000d0600020b0a050901010c070e001004020a091136b4eeaf4a557ebc00ca9a3b00000000060c080e000203090a070f346cb8a27b9fdeaa230100000014000000ffffffffffffffffffffffffffffffffffffffff040000007c1d0f0700ca9a3b00000000").to_vec(); + let expected_serialized_tx = hex_literal::hex!("016f23b283e6b171c042d714ad6d24c6ab09fcbb22fcd977a2fb9b2ab53a3bf36418a2b7f8814672c10c7be41272e64d585e5fc7e913ad455d4e8d9d797ecdbb0e800100090cf79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb5ec7baaea7200eb2a66ccd361ee73bc87a7e5222ecedcbc946e97afb59ec46167417da8b99d7748127a76b03d61fee69c80dfef73ad2d5503737beedc5a9ed4800000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517187bd16635dad40455fdc2c0c124c68f215675a5dbbacb5f0800000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea940000006ddf6e1d765a193d9cbe146ceeb79ac1cb485ed5f5b37913a8cf5857eff00a931e9528aae784fecbbd0bee129d9539c57be0e90061af6b6f4a5e274654e5bd472b5d2051d300b10b74314b7e25ace9998ca66eb2c7fbc10ef130dd67028293c8c97258f4e2489f1bb3d1029148e0d830b5a1399daff1084048e7bd8dbe9f859a73bdf31e341218a693b8772c43ecfcecd4cf35fada09a87ea0f860d028168e5c27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e489000603030c0600040400000004000903809698000000000004000502e09304000a060001080e0307010109070f00100d010e071136b4eeaf4a557ebc00ca9a3b000000000609080f000102070e050b346cb8a27b9fdeaa230100000014000000ffffffffffffffffffffffffffffffffffffffff040000007c1d0f0700ca9a3b00000000013001afd71da9456a977233960b08eba77d2e3690b8c7259637c8fb8f82cf58a102090503030204").to_vec(); test_constructed_transaction(transaction, expected_serialized_tx); } @@ -837,35 +881,39 @@ pub mod test { agg_key(), durable_nonce(), compute_price(), + vec![chainflip_alt()], ) .unwrap(); // Serialized tx built in `set_gov_key_with_agg_key` test - let expected_serialized_tx = hex_literal::hex!("01b6b605651cd375e812a7d47eeb2f20e204b16544a1a12f32fd97cdfb18d36ffa2179abb5fcac6fe677a5c21651c26ab41e3a84c1b2c2bc8ab4bcbb3e438c670d01000407f79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb17eb2b10d3377bda2bc7bea65bec6b8372f4fc3463ec2cd6f9fde4b2c633d192a1e031c8bc9bec3b610cf7b36eb3bf3aa40237c9e5be2c7893878578439eb00b00000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea940000072b5d2051d300b10b74314b7e25ace9998ca66eb2c7fbc10ef130dd67028293cc27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e48900040303010500040400000004000903809698000000000004000502e4570000060202002842403a280f4bd7a26744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be543990044").to_vec(); + let expected_serialized_tx = hex_literal::hex!("01b08fe749db9efd9ce87fa0c45c816cc395b344bf5e0acdb172c7f6549c50651a1965b52a7a2150cdd579d40b9a6b07dbd734e59d59130b4f62f990a2fd28d8048001000405f79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb00000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea940000072b5d2051d300b10b74314b7e25ace9998ca66eb2c7fbc10ef130dd67028293cc27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e48900040103050300040400000002000903809698000000000002000502e4570000040206002842403a280f4bd7a26744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be543990044013001afd71da9456a977233960b08eba77d2e3690b8c7259637c8fb8f82cf58a102090200").to_vec(); test_constructed_transaction(transaction, expected_serialized_tx); } #[test] fn transactions_above_max_lengths_will_fail() { - // with 28 Fetches, the length is 1232 <= 1232 + let limit = 9; + assert_ok!(SolanaTransactionBuilder::fetch_from( - [get_fetch_params(None, SOL); 28].to_vec(), + (0..limit).map(|i| get_fetch_params(Some(i), SOL)).collect(), api_env(), agg_key(), durable_nonce(), compute_price(), + vec![chainflip_alt()], )); assert_err!( SolanaTransactionBuilder::fetch_from( - [get_fetch_params(None, SOL); 29].to_vec(), + (0..=limit).map(|i| get_fetch_params(Some(i), SOL)).collect(), api_env(), agg_key(), durable_nonce(), compute_price(), + vec![chainflip_alt()], ), - SolanaTransactionBuildingError::FinalTransactionExceededMaxLength(1261) + SolanaTransactionBuildingError::FinalTransactionExceededMaxLength(1260) ); } } diff --git a/state-chain/pallets/cf-environment/src/mock.rs b/state-chain/pallets/cf-environment/src/mock.rs index 3c88f174650..4036b3dc247 100644 --- a/state-chain/pallets/cf-environment/src/mock.rs +++ b/state-chain/pallets/cf-environment/src/mock.rs @@ -7,11 +7,11 @@ use cf_chains::{ eth, sol::{ api::{ - AllNonceAccounts, ApiEnvironment, ComputePrice, CurrentAggKey, CurrentOnChainKey, - DurableNonce, DurableNonceAndAccount, RecoverDurableNonce, SolanaApi, - SolanaEnvironment, + AllNonceAccounts, ApiEnvironment, ChainflipAddressLookupTable, ComputePrice, + CurrentAggKey, CurrentOnChainKey, DurableNonce, DurableNonceAndAccount, + RecoverDurableNonce, SolanaAddressLookupTables, SolanaApi, SolanaEnvironment, }, - SolAddress, SolAmount, SolApiEnvironment, SolHash, + SolAddress, SolAddressLookupTableAccount, SolAmount, SolApiEnvironment, SolHash, }, ApiCall, Arbitrum, Bitcoin, Chain, ChainCrypto, ChainEnvironment, Polkadot, Solana, }; @@ -183,6 +183,22 @@ impl RecoverDurableNonce for MockSolEnvironment { unimplemented!(); } } + +impl ChainEnvironment> + for MockSolEnvironment +{ + fn lookup(_s: SolanaAddressLookupTables) -> Option> { + None + } +} +impl ChainEnvironment + for MockSolEnvironment +{ + fn lookup(_s: ChainflipAddressLookupTable) -> Option { + None + } +} + impl SolanaEnvironment for MockSolEnvironment {} pub struct MockSolanaBroadcaster; diff --git a/state-chain/pallets/cf-ingress-egress/src/lib.rs b/state-chain/pallets/cf-ingress-egress/src/lib.rs index 44a54393b26..d7cef8e46df 100644 --- a/state-chain/pallets/cf-ingress-egress/src/lib.rs +++ b/state-chain/pallets/cf-ingress-egress/src/lib.rs @@ -258,6 +258,7 @@ pub struct CrossChainMessage { // Where funds might be returned to if the message fails. pub ccm_additional_data: CcmAdditionalData, pub gas_budget: GasAmount, + pub swap_request_id: SwapRequestId, } impl CrossChainMessage { @@ -1747,6 +1748,7 @@ impl, I: 'static> Pallet { ccm.gas_budget, ccm.message.to_vec(), ccm.ccm_additional_data.to_vec(), + ccm.swap_request_id, ) { Ok(api_call) => { let broadcast_id = T::Broadcaster::threshold_sign_and_broadcast_with_callback( @@ -2866,6 +2868,8 @@ impl, I: 'static> EgressApi for Pallet { source_chain, source_address, gas_budget, + swap_request_id: Default::default(), /* TODO Ramiz: Pass this in as a + * parameter */ }); Ok(egress_details) diff --git a/state-chain/pallets/cf-ingress-egress/src/tests.rs b/state-chain/pallets/cf-ingress-egress/src/tests.rs index 94175a5e4d8..32f328210d7 100644 --- a/state-chain/pallets/cf-ingress-egress/src/tests.rs +++ b/state-chain/pallets/cf-ingress-egress/src/tests.rs @@ -164,6 +164,7 @@ fn blacklisted_asset_will_not_egress_via_ccm() { source_address: ccm.source_address.clone(), ccm_additional_data: ccm.channel_metadata.ccm_additional_data, gas_budget, + swap_request_id: Default::default(), }] ); @@ -523,6 +524,7 @@ fn can_egress_ccm() { source_chain: ForeignChain::Ethereum, source_address: Some(ForeignChainAddress::Eth([0xcf; 20].into())), gas_budget: GAS_BUDGET, + swap_request_id: Default::default(), } ]); @@ -541,6 +543,7 @@ fn can_egress_ccm() { GAS_BUDGET, ccm.channel_metadata.message.to_vec(), vec![], + Default::default(), ).unwrap()]); // Storage should be cleared diff --git a/state-chain/runtime/src/chainflip.rs b/state-chain/runtime/src/chainflip.rs index b22900ee305..1b714cc6b48 100644 --- a/state-chain/runtime/src/chainflip.rs +++ b/state-chain/runtime/src/chainflip.rs @@ -50,12 +50,12 @@ use cf_chains::{ }, sol::{ api::{ - AllNonceAccounts, ApiEnvironment, ComputePrice, CurrentAggKey, CurrentOnChainKey, - DurableNonce, DurableNonceAndAccount, RecoverDurableNonce, SolanaApi, - SolanaEnvironment, + AllNonceAccounts, ApiEnvironment, ChainflipAddressLookupTable, ComputePrice, + CurrentAggKey, CurrentOnChainKey, DurableNonce, DurableNonceAndAccount, + RecoverDurableNonce, SolanaAddressLookupTables, SolanaApi, SolanaEnvironment, }, - SolAddress, SolAmount, SolApiEnvironment, SolanaCrypto, SolanaTransactionData, - NONCE_AVAILABILITY_THRESHOLD_FOR_INITIATING_TRANSFER, + SolAddress, SolAddressLookupTableAccount, SolAmount, SolApiEnvironment, SolanaCrypto, + SolanaTransactionData, NONCE_AVAILABILITY_THRESHOLD_FOR_INITIATING_TRANSFER, }, AnyChain, ApiCall, Arbitrum, CcmChannelMetadata, CcmDepositMetadata, Chain, ChainCrypto, ChainEnvironment, ChainState, ChannelRefundParametersDecoded, ForeignChain, @@ -371,11 +371,14 @@ impl TransactionBuilder> for SolanaTransaction RequiresSignatureRefresh::False, |active_epoch_key| { let current_aggkey = active_epoch_key.key; - for key in modified_call.transaction.message.account_keys.iter_mut() { - if *key == signer.into() { - *key = current_aggkey.into() + modified_call.transaction.message.map_static_account_keys(|key| { + if key == signer.into() { + current_aggkey.into() + } else { + key } - } + }); + for sig in modified_call.transaction.signatures.iter_mut() { *sig = Default::default() } @@ -593,6 +596,24 @@ impl RecoverDurableNonce for SolEnvironment { } } +impl ChainEnvironment> + for SolEnvironment +{ + fn lookup(_s: SolanaAddressLookupTables) -> Option> { + // TODO Ramiz: Lookup SolanaElection pallet for the ALTS using the given SwapRequestId + None + } +} + +impl ChainEnvironment + for SolEnvironment +{ + fn lookup(_s: ChainflipAddressLookupTable) -> Option { + // TODO Roy: Read Chainflip's ALT from the Environment pallet. + None + } +} + impl SolanaEnvironment for SolEnvironment {} pub struct TokenholderGovernanceBroadcaster; diff --git a/state-chain/runtime/src/lib.rs b/state-chain/runtime/src/lib.rs index 1a7d364eff8..6a0f1684a6f 100644 --- a/state-chain/runtime/src/lib.rs +++ b/state-chain/runtime/src/lib.rs @@ -48,7 +48,7 @@ use cf_chains::{ btc::{api::BitcoinApi, BitcoinCrypto, BitcoinRetryPolicy, ScriptPubkey}, ccm_checker::{ check_ccm_for_blacklisted_accounts, CcmValidityCheck, CcmValidityChecker, - DecodedCcmAdditionalData, VersionedSolanaCcmAdditionalData, + DecodedCcmAdditionalData, }, dot::{self, PolkadotAccountId, PolkadotCrypto}, eth::{self, api::EthereumApi, Address as EthereumAddress, Ethereum}, @@ -2230,7 +2230,9 @@ impl_runtime_apis! { // Ensure CCM message is valid match CcmValidityChecker::check_and_decode(ccm, destination_asset, destination_address.clone()) { - Ok(DecodedCcmAdditionalData::Solana(VersionedSolanaCcmAdditionalData::V0(ccm_accounts))) => { + Ok(DecodedCcmAdditionalData::Solana(decoded)) => { + let ccm_accounts = decoded.ccm_accounts(); + // Ensure the CCM parameters do not contain blacklisted accounts. // Load up environment variables. let api_environment = diff --git a/state-chain/traits/src/mocks/api_call.rs b/state-chain/traits/src/mocks/api_call.rs index 2c20bd96559..43d1ea58b1f 100644 --- a/state-chain/traits/src/mocks/api_call.rs +++ b/state-chain/traits/src/mocks/api_call.rs @@ -6,7 +6,7 @@ use cf_chains::{ ExecutexSwapAndCallError, FetchAssetParams, ForeignChainAddress, RejectCall, RejectError, TransferAssetParams, TransferFallback, TransferFallbackError, }; -use cf_primitives::{chains::assets, EgressId, ForeignChain, GasAmount}; +use cf_primitives::{chains::assets, EgressId, ForeignChain, GasAmount, SwapRequestId}; use codec::{Decode, Encode}; use frame_support::{sp_runtime::DispatchError, CloneNoBound, DebugNoBound, PartialEqNoBound}; use scale_info::TypeInfo; @@ -151,6 +151,7 @@ impl ExecutexSwapAndCall for MockEthereumApiCall { gas_budget: GasAmount, message: Vec, _ccm_additional_data: Vec, + _swap_request_id: SwapRequestId, ) -> Result { if MockEvmEnvironment::lookup(transfer_param.asset).is_none() { Err(ExecutexSwapAndCallError::DispatchError(DispatchError::CannotLookup)) @@ -288,6 +289,7 @@ impl ExecutexSwapAndCall for MockBitcoinApiCall { gas_budget: GasAmount, message: Vec, _ccm_additional_data: Vec, + _swap_request_id: SwapRequestId, ) -> Result { if MockBtcEnvironment::lookup(transfer_param.asset).is_none() { Err(ExecutexSwapAndCallError::DispatchError(DispatchError::CannotLookup)) From 0dd6b084ee7c87c29c55290b9e7e91956cc65981 Mon Sep 17 00:00:00 2001 From: Albert Llimos <53186777+albert-llimos@users.noreply.github.com> Date: Wed, 19 Feb 2025 06:04:07 +0100 Subject: [PATCH 3/4] feat: add image with ALT Manager, additional nonces and ALT witnessing. (#5638) * Added versioned transaction and versioned message support * Added unit test for Versioned transactions with Address lookup table * Moved (almost) everything in sol_tx_core into sol-prim Moved ALT related stuff to its own file. * Initial commit for changing Solana Transaction to VersionedTransaction * Make solana api calls more consistent with the use of ALT * feat: update image with alt and add logic and migrations * chore: rebase and update * chore: run ci * chore: fix clippy and try removing symlink * chore: try running anza * chore: upgrade to 2.1.13 * chore: update bouncer expected number of nonces * chore: update compute units * chore: restore ci# * chore: fix ci * chore: nit * chore: update test * chore: fix tests and nit * chore: define MAX_CCM_USER_ALTS * Minor improvements. Fix build and tests --------- Co-authored-by: Roy Yang Co-authored-by: Daniel --- .cargo/config.toml | 2 +- .github/workflows/_40_post_check.yml | 5 +- .github/workflows/ci-development.yml | 2 +- .github/workflows/upgrade-test.yml | 18 +- bouncer/commands/setup_vaults.ts | 1 - bouncer/shared/contract_interfaces.ts | 2 +- bouncer/shared/force_sol_nonces.ts | 180 +++++- bouncer/shared/initialize_new_chains.ts | 49 +- bouncer/shared/sol_vault_swap.ts | 2 +- bouncer/shared/utils.ts | 12 +- .../tests/solana_vault_settings_governance.ts | 2 +- .../download-sol-program-idls.sh | 1 + .../v0.1.1-alt-test/alt_manager.json | 371 ++++++++++++ .../cf_tester.json | 0 .../cf_tester.ts | 0 .../swap_endpoint.json | 0 .../swap_endpoint.ts | 0 .../vault.json | 0 .../vault.ts | 0 engine/src/witness/sol.rs | 5 +- engine/src/witness/sol/egress_witnessing.rs | 5 +- .../witness/sol/lookup_table_witnessing.rs | 226 ++++++++ ...itnessing.rs => vault_swaps_witnessing.rs} | 2 +- foreign-chains/solana/sol-prim/src/alt.rs | 4 +- foreign-chains/solana/sol-prim/src/consts.rs | 4 +- .../src/instructions/program_instructions.rs | 23 + foreign-chains/solana/sol-prim/src/lib.rs | 1 + localnet/common.sh | 3 - localnet/docker-compose.yml | 2 +- .../cf-integration-tests/src/solana.rs | 17 +- state-chain/chains/src/sol.rs | 14 +- state-chain/chains/src/sol/api.rs | 44 +- state-chain/chains/src/sol/sol_tx_core.rs | 11 +- .../chains/src/sol/transaction_builder.rs | 77 +-- state-chain/node/src/chain_spec.rs | 43 +- state-chain/node/src/chain_spec/berghain.rs | 234 ++++++++ .../node/src/chain_spec/perseverance.rs | 234 ++++++++ state-chain/node/src/chain_spec/sisyphos.rs | 234 ++++++++ state-chain/node/src/chain_spec/testnet.rs | 251 ++++++++- state-chain/pallets/cf-environment/src/lib.rs | 4 +- .../pallets/cf-environment/src/migrations.rs | 13 +- .../src/migrations/sol_api_environment.rs | 532 +++++++++++++++++- .../pallets/cf-environment/src/mock.rs | 18 +- state-chain/runtime/src/chainflip.rs | 15 +- 44 files changed, 2458 insertions(+), 205 deletions(-) create mode 100644 contract-interfaces/sol-program-idls/v0.1.1-alt-test/alt_manager.json rename contract-interfaces/sol-program-idls/{v1.0.1-swap-endpoint => v0.1.1-alt-test}/cf_tester.json (100%) rename contract-interfaces/sol-program-idls/{v1.0.1-swap-endpoint => v0.1.1-alt-test}/cf_tester.ts (100%) rename contract-interfaces/sol-program-idls/{v1.0.1-swap-endpoint => v0.1.1-alt-test}/swap_endpoint.json (100%) rename contract-interfaces/sol-program-idls/{v1.0.1-swap-endpoint => v0.1.1-alt-test}/swap_endpoint.ts (100%) rename contract-interfaces/sol-program-idls/{v1.0.1-swap-endpoint => v0.1.1-alt-test}/vault.json (100%) rename contract-interfaces/sol-program-idls/{v1.0.1-swap-endpoint => v0.1.1-alt-test}/vault.ts (100%) create mode 100644 engine/src/witness/sol/lookup_table_witnessing.rs rename engine/src/witness/sol/{program_swaps_witnessing.rs => vault_swaps_witnessing.rs} (99%) diff --git a/.cargo/config.toml b/.cargo/config.toml index b5365753225..030f30bd8bb 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -2,7 +2,7 @@ CF_ETH_CONTRACT_ABI_ROOT = { value = "contract-interfaces/eth-contract-abis", relative = true } CF_ETH_CONTRACT_ABI_TAG = "v1.1.2" CF_SOL_PROGRAM_IDL_ROOT = { value = "contract-interfaces/sol-program-idls", relative = true } -CF_SOL_PROGRAM_IDL_TAG = "v1.0.1-swap-endpoint" +CF_SOL_PROGRAM_IDL_TAG = "v0.1.1-alt-test" CF_ARB_CONTRACT_ABI_ROOT = { value = "contract-interfaces/arb-contract-abis", relative = true } CF_TEST_CONFIG_ROOT = { value = "engine/config/testing", relative = true } diff --git a/.github/workflows/_40_post_check.yml b/.github/workflows/_40_post_check.yml index a69d3390f3d..9e532f6e3e9 100644 --- a/.github/workflows/_40_post_check.yml +++ b/.github/workflows/_40_post_check.yml @@ -18,7 +18,7 @@ on: env: FORCE_COLOR: 1 - SOLANA_VERSION: v1.18.17 + SOLANA_VERSION: v2.1.13 NODE_COUNT: "${{ inputs.node-count }}-node" permissions: @@ -81,8 +81,7 @@ jobs: - name: Install solana ☀️ run: | - sh -c "$(curl -sSfL https://release.solana.com/$SOLANA_VERSION/install)" - + sh -c "$(curl -sSfL https://release.anza.xyz/$SOLANA_VERSION/install)" - name: Start a localnet 🚀 env: BINARY_ROOT_PATH: . diff --git a/.github/workflows/ci-development.yml b/.github/workflows/ci-development.yml index eb20a5c53d7..78e24feaf83 100644 --- a/.github/workflows/ci-development.yml +++ b/.github/workflows/ci-development.yml @@ -5,7 +5,7 @@ on: branches: - main - "release/*" - - "feat/solana-versioned-transaction-base-branch" + - "feat/solana-versioned-transaction*" concurrency: group: ${{ github.ref }}-release-development cancel-in-progress: true diff --git a/.github/workflows/upgrade-test.yml b/.github/workflows/upgrade-test.yml index f9ee64339ec..afe24ba61dc 100644 --- a/.github/workflows/upgrade-test.yml +++ b/.github/workflows/upgrade-test.yml @@ -22,8 +22,8 @@ on: default: true env: FORCE_COLOR: 1 - SOLANA_VERSION: v1.18.17 - SOLANA_PROGRAMS_VERSION: v1.0.1-swap-endpoint + SOLANA_VERSION: v2.1.13 + SOLANA_PROGRAMS_VERSION: v0.1.1-alt-test NODE_COUNT: "1-node" permissions: @@ -149,7 +149,7 @@ jobs: - name: Install solana ☀️ if: inputs.run-job run: | - sh -c "$(curl -sSfL https://release.solana.com/$SOLANA_VERSION/install)" + sh -c "$(curl -sSfL https://release.anza.xyz/$SOLANA_VERSION/install)" - name: Start a localnet from upgrade-from version 🚀 if: inputs.run-job @@ -173,9 +173,21 @@ jobs: echo "/usr/lib after copy of .so files" ls -l /usr/lib touch ./localnet/.setup_complete + # TODO: This is a temporary fix to allow the localnet docker-compose.yml from an older commit to run the latest solana programs version. + sed -i 's|ghcr.io/chainflip-io/solana-localnet-ledger:v[0-9.]*|ghcr.io/chainflip-io/solana-localnet-ledger:${{ env.SOLANA_PROGRAMS_VERSION }}|g' localnet/docker-compose.yml ./localnet/manage.sh git reset --hard + # TODO: This is a temporary workaround to insert the image nonces for versioned transactions. Remove after it's is released. + - name: Nonce workaround + if: inputs.run-job + run: | + git checkout ${{ github.sha }} + git rev-parse HEAD + cd bouncer + pnpm install --frozen-lockfile + ./shared/force_sol_nonces.ts + - name: Run bouncer on upgrade-from version 🙅‍♂️ if: inputs.run-job id: pre-upgrade-bouncer diff --git a/bouncer/commands/setup_vaults.ts b/bouncer/commands/setup_vaults.ts index 6febfdd4ed7..b4685aa32d5 100755 --- a/bouncer/commands/setup_vaults.ts +++ b/bouncer/commands/setup_vaults.ts @@ -71,7 +71,6 @@ async function main(): Promise { } if (result.isInBlock) { console.log('Polkadot Vault created'); - // TODO: figure out type inference so we don't have to coerce using `any` const pureCreated = result.findRecord('proxy', 'PureCreated')!; resolve({ vaultAddress: pureCreated.event.data[0] as AddressOrPair, diff --git a/bouncer/shared/contract_interfaces.ts b/bouncer/shared/contract_interfaces.ts index e9e081a97fc..4003ba4bb18 100644 --- a/bouncer/shared/contract_interfaces.ts +++ b/bouncer/shared/contract_interfaces.ts @@ -13,7 +13,7 @@ function loadContractCached(abiPath: string) { }; } const CF_ETH_CONTRACT_ABI_TAG = 'v1.1.2'; -const CF_SOL_PROGRAM_IDL_TAG = 'v1.0.1-swap-endpoint'; +const CF_SOL_PROGRAM_IDL_TAG = 'v0.1.1-alt-test'; export const getErc20abi = loadContractCached( '../contract-interfaces/eth-contract-abis/IERC20.json', ); diff --git a/bouncer/shared/force_sol_nonces.ts b/bouncer/shared/force_sol_nonces.ts index 9067796539b..7127406e684 100755 --- a/bouncer/shared/force_sol_nonces.ts +++ b/bouncer/shared/force_sol_nonces.ts @@ -16,43 +16,203 @@ async function forceRecoverSolNonce(nonceAddress: string, nonceValue: string) { async function main() { await forceRecoverSolNonce( '2cNMwUCF51djw2xAiiU54wz1WrU8uG4Q8Kp8nfEuwghw', - '2qVz58R5aPmF5Q61VaKXnpWQtngdh4Jgbeko32fEcECu', + 'A6PxZEnTwTrLQG8pVBwytG8YLRqPUeEdsXHJP2UQ5RSF', ); await forceRecoverSolNonce( 'HVG21SovGzMBJDB9AQNuWb6XYq4dDZ6yUwCbRUuFnYDo', - '6fxCujPRyyTPzcZWpkDRhvDC4NXf4GB5tCTbQRDnz2iw', + 'EtK5bRt2pDX3CJyDzsdDtzjRf7v15NPR8JVpMikh6sNh', ); await forceRecoverSolNonce( 'HDYArziNzyuNMrK89igisLrXFe78ti8cvkcxfx4qdU2p', - '2VUnNMpXzohc4284EyuhT7PEuUdqy9E7AfxAP8nrm9cv', + '3PkYapCizvyiFPBEg2pkiBAxnVYfpR2VWs7H6FQcD7rc', ); await forceRecoverSolNonce( 'HLPsNyxBqfq2tLE31v6RiViLp2dTXtJRgHgsWgNDRPs2', - '7bNgRtjaTgCiXwEagFv2cndco5aTzW1dEXGTZp9EDHgE', + 'HqPcXp31mYG1G4DP3c9F262pjXKeMzb4hbAwqsdLKrmM', ); await forceRecoverSolNonce( 'GKMP63TqzbueWTrFYjRwMNkAyTHpQ54notRbAbMDmePM', - 'DSSpXCVb6LU4a91TAkqyUHGXB1bspfLUxKzb5VhGUvyf', + '2cMqnuCCnGWm56LFPe9mZuGHdhzpFpwwv2io9Q99EMjE', ); await forceRecoverSolNonce( 'EpmHm2aSPsB5ZZcDjqDhQ86h1BV32GFCbGSMuC58Y2tn', - 'DEwmxJ6xUTXVMnZjvSsRBb9knA1JG3ETT1CQXz5q3yzY', + '7ZZpMge82HiNhhyv1LDzfwq7Ak9sF943TmLkQNuR7ZZh', ); await forceRecoverSolNonce( '9yBZNMrLrtspj4M7bEf2X6tqbqHxD2vNETw8qSdvJHMa', - 'ERJZ2GKvYB2f7MroWy8qEA3xdvMNHg2DUqjBJ6KVzXYE', + 'Ee2tKBQguV5Rfsa738jBTRCU7vczXkZYnddiqwSRz2Dz', ); await forceRecoverSolNonce( 'J9dT7asYJFGS68NdgDCYjzU2Wi8uBoBusSHN1Z6JLWna', - 'Ecqa1ZZwjS6Lz74k2kXvVKcrWXJNiVGzLqfe1ftBcCYj', + 'BhW9y8kkdBFiWnwzrYihhjhreovZd3TfZE7uaQnKz8ea', ); await forceRecoverSolNonce( 'GUMpVpQFNYJvSbyTtUarZVL7UDUgErKzDTSVJhekUX55', - 'HuksgAnauQ9wTextjMhHVB6oVSCT3GKGb6j1DniSS8eL', + '5CGa6yRJsVStdMR4PkUNGW5F13UeHBuqyurkmNByrgxj', ); await forceRecoverSolNonce( 'AUiHYbzH7qLZSkb3u7nAqtvqC7e41sEzgWjBEvXrpfGv', - '2TR5QRLhPzPzB6Gvs4iZsq6Dp8v5w2LamrE9BFrsNkzW', + 'DCrChXBpKFjq61yYdULyYEnfqtcYkf1ACQqDNkgfwhF9', + ); + await forceRecoverSolNonce( + 'BN2vyodNYQQTrx3gtaDAL2UGGVtZwFeF5M8krE5aYYES', + '4fjG6oYKadvnsbzAzomF5k2Zdc4DuuUyT71nueAeykMW', + ); + await forceRecoverSolNonce( + 'Gwq9TAQCjbJtdnmtxQa3PbHFfbr6YTUBMDjEP9x2uXnH', + 'GK29hbKjKWNwdF4KT11MzkrmQPsYPwE41qZMnLVcQPaS', + ); + await forceRecoverSolNonce( + '3pGbKatko2ckoLEy139McfKiirNgy9brYxieNqFGdN1W', + '5cinXdpw2KAGzmiXXegWJRdDDboXbDHaQaT3WFsH3txb', + ); + await forceRecoverSolNonce( + '9Mcd8BTievK2yTvyiqG9Ft4HfDFf6mjGFBWMnCSRQP8S', + 'DRoAyPDtsg9CCMBSN6egFsWsP2zsQBAxCzN6fAdtQxJU', + ); + await forceRecoverSolNonce( + 'AEZG74RoqM6sxf79eTizq5ShB4JTuCkMVwUgtnC8H94z', + 'G8ZKHMsWFSoKJAtVbm1xgv8VjT5F6YBeiZbbzpVHuuyM', + ); + await forceRecoverSolNonce( + 'APLkgyCWi8DFAMF4KikjTu8YnUG1r7sMjVEfDiaBRZnS', + 'BMUqNXhMoB6VWsR7jHgRcv7yio8L5vjHdGby7gEJ4Pd2', + ); + await forceRecoverSolNonce( + '4ShNXTTHvpVt6bQdZTRdyW6yWXDzrPupdMuxajbEoGE4', + '52yamKJdMiQ5tEUyhkngvjR3XFXp7dmJzYsVsLbPs9JX', + ); + await forceRecoverSolNonce( + 'FgZp6NJYWw15U51ynfXCfU9vq3eVgDDAHMSfJ8fFBZZ8', + 'AX3qKNMBRKZimeCsBEhtp7heeduKekj85a4UpdN34HFe', + ); + await forceRecoverSolNonce( + 'ENQ9Mmg87KFLX8ncXRPDBSd7jhKCtPBi8QzAh4rkREgP', + 'GGFme2ydkkbDzq7LhVDMX5SsFf2yGLf7uKNSLLhvrGMd', + ); + await forceRecoverSolNonce( + 'Hhay1UwkzkFUgrGUYuiCvUwv7kErNzAcZnVRQ2fetT7K', + 'HMN14axscHALAuknuwSpVkEmAJkZWeJoNAjJuXUjRQbN', + ); + await forceRecoverSolNonce( + '2fUVR42opcHgGLrY1eguDXLYfQPHQe9ReJNmRorVt9v8', + 'RWoH6shzxCS9dmW2mg37cujXxARBRBunbHEtZwUz1Gj', + ); + await forceRecoverSolNonce( + 'HfKr1wJASkW5UHs8yNWAqMeaYJdp8K2mdYwkbdVRdVrm', + '2dhBBWYQE2Fvm4ShUQjno8ydJb5H6rUmBZ1e6TJHDupL', + ); + await forceRecoverSolNonce( + 'DrpYkMpJWkpNqX9yYgQfc3uZrCVYobJ3RbTABcSkHJkM', + '6VCThFyLtFCKk35wihyrRUa6dubBU7skhJdRRDBfH4Md', + ); + await forceRecoverSolNonce( + 'HCXc3o2go1Y2KhfnykLYXEvofLifXTb7GT13w4GsFmGw', + 'EggsCqUiKJVxmN7a9s7RScXUAJRjekjwCAaeQvK9TcJ4', + ); + await forceRecoverSolNonce( + 'FFKYhae4HSnMmA6JJfe8NNtZeySA9yRWLaHzE2jqfhBr', + '2E8BayMrqL3on6bhcMms6dsm3PwKcxttFSuHDNe6vZ4B', + ); + await forceRecoverSolNonce( + 'AaRrJovR9Npna4fuCJ17AB3cJAMzoNDaZymRTbGGzUZm', + 'D5bhT4vxhrtkfPeyZbvCtwzAnHSwBaa287CZZU8F6fye', + ); + await forceRecoverSolNonce( + '5S8DzBBLvJUeyJccV4DekAK8KJA5PDcjwxRxCvgdyBEi', + '8o7RkbTeV9r1yMgXaTzjcPys2FEkqieHER6Z5Fdc8hbw', + ); + await forceRecoverSolNonce( + 'Cot1DQZpm859brrre7swrDhTYLj2NJbg3hdMKCHk5zSk', + 'Gd86jHRKKSxrho3WKni5HYe6runTFX4cyFUQtcmJeiuk', + ); + await forceRecoverSolNonce( + '4mfDv7PisvtMhiyGmvD6vxRdVpB842XbUhimAZYxMEn9', + '4YQLN6N7G9nFwT8UVdFE2ZniW1gf89Qjob16wxMThxqN', + ); + await forceRecoverSolNonce( + 'BHW7qFCNHTX5QD5yJpT1hn1VM817Ji5ksZqiXMfqGrsj', + 'Ft3vnX4KQBa22CVpPkmvk5QNMGwL2xhQVxQtFJwK5MvJ', + ); + await forceRecoverSolNonce( + 'EJqZLeaxi2gVsJgQW4nbmxyWJukK25n7jB8qWKoDgWUN', + '5tZeUYorHfdh9FYsA9yKjanFRwxjGxM9YLzNAfiwhZUf', + ); + await forceRecoverSolNonce( + 'BJqTPWyoqqgzhkLh1pbPh4KWBqg8kCUNzJ81avitSQrm', + '5ggDcExaPfgjsmrhBS3D2UnRaEPsCGKGDkJqzF7gr92A', + ); + await forceRecoverSolNonce( + 'EkmPmEmSbwm8EDDYtLtaDgcfuLNtW7MbKx5w3FUpaGjv', + '3G7D13ckfLCfDFC3VusXdittLHp6z6dZeUJBHTqcc2iR', + ); + await forceRecoverSolNonce( + 'CgwtCv8HQ67imnHEkz24TfXfyA2H5jurxcLGxAgDmNQj', + 'Gikpdfo6SwRqi3nTmQKuCmap3cGwupZd2poiYkUop4Sn', + ); + await forceRecoverSolNonce( + 'zfKsXSxJ4cTpKS7S6aHL1Hy3m1CEjQuySKSwkWvukQX', + '43Kn8Kevfy2cy2fpJEhEZSpmPNwFurL2ERG5FqdSeTsq', + ); + await forceRecoverSolNonce( + '2VvN1s6txNYyBdKpaC8b6AZKVqUQiQT2Exrpa7ffCgV6', + 'FVZKFoZ8WRdsFBp64LpTF1MrH36dHym2XZv7cJ2oYU5', + ); + await forceRecoverSolNonce( + 'A2DT1dc4rA1uMry7WCLwoUEQQNjCAsAMkB4X9Lgo88zd', + 'HjtHG8XRKyGiN8VXWmMh9oEviURAv5o2VygKTvsZjAPz', + ); + await forceRecoverSolNonce( + '9mNBRGfTMLsSsQUn4YZfRDBVXfQ6juEWbNUTwv2ir9gC', + '2S1aHds5wqUSyY4BmAK9YyBNGwzsQSsqGa2iyisF8t6h', + ); + await forceRecoverSolNonce( + '3jXiydxPx1P7Ggdja5yt384ryLJAW2c8LRGV8PPRT54C', + 'Hgu6wkD6aE3uuESdW9fCWoXX4sN3eLnxYJsM7QCtrZMk', + ); + await forceRecoverSolNonce( + '7ztGR1z28NpYjUaXyrGBzBGu62u1f9H9Pj9UVSKnT3yu', + '9wic99ejEMQubHea9KKZZk27EU7r4LL8672D5GNrpXRG', + ); + await forceRecoverSolNonce( + '4GdnDTr5X4eJFHuzTEBLrz3tsREo8rQro7S9YDqrbMZ9', + 'FCsgGf33ueodTVhLgQtTriNL5ZGfoaWoBkDwXSbDmLFd', + ); + await forceRecoverSolNonce( + 'ALxnH6TBKJPBFRfFZspQkxDjb9nGLUP5oxFFdZNRFgUu', + 'QkBgGAKFPtQzRj1v7sFECr8D2LMPb99AEy3w1RtKX5j', + ); + await forceRecoverSolNonce( + 'Bu3sdWtBh5TJishgK3vneh2zJg1rjLqWN5mFTHxWspwJ', + 'GWvckQW231Safveswww1GBSu4SzP5h5SgE6gugBn8upC', + ); + await forceRecoverSolNonce( + 'GvBbUTE312RXU5iXAcNWt6CuVbfsPs5Nk28D6qvU6NF3', + 'BnFsZdujQde7FnHGVcZTmvidRHBr5H87XRDDB6A5dn8D', + ); + await forceRecoverSolNonce( + '2LLct8SsnkW3sD9Gu8CfxmDEjKAWtFXqLvA8ymMyuq8u', + 'Bnt1CWn8SEwpNqFbNxby6ysoW49wmL95Ed28pbS9v4Nx', + ); + await forceRecoverSolNonce( + 'CQ9vUhC3dSa4LyZCpWVpNbXhSn6f7J3NQXWDDvMMk6aW', + '2yVSXvwXjtA5tqqWUKjxBuYjME6pKwJGA12NUc31x9VS', + ); + await forceRecoverSolNonce( + 'Cw8GqRmKzCbp7UFfafECC9sf9f936Chgx3BkbSgnXfmU', + 'FDPW3e2qPvNrmi1dqxsMaYAXLq9vMQYda5fKsVzNBUCv', + ); + await forceRecoverSolNonce( + 'GFJ6m6YdNT1tUfAxyD2BiPSx8gwt3xe4jVAKdtdSUt8W', + '4tUTcUePrDUu48ZyH584aYv8JAbPrc9aDcH6bjxhEJon', + ); + await forceRecoverSolNonce( + '7bphTuo5BKs4JJw5WPusCevmnoRk9ocFiB8EGgfwnh4c', + 'SyhFE8iYH9ZsZNBDWLvTDTBFBoEjxs12msF3xprikgf', + ); + await forceRecoverSolNonce( + 'EFbUq18Mcdi2gGauRzmbNeD5ixaB7EYVk5JZgAF34LoS', + '53EBQYjZ7yH3Zy6KCWjSGAUGTki2YjxsHkrfXnvsj9vT', ); } diff --git a/bouncer/shared/initialize_new_chains.ts b/bouncer/shared/initialize_new_chains.ts index 88d308fb5f3..d5af2c45eb9 100644 --- a/bouncer/shared/initialize_new_chains.ts +++ b/bouncer/shared/initialize_new_chains.ts @@ -12,6 +12,7 @@ import { getSolWhaleKeyPair, encodeSolAddress, solanaNumberOfNonces, + solanaNumberOfAdditionalNonces, } from '../shared/utils'; import { sendSol, signAndSendTxSol } from '../shared/send_sol'; import { getSolanaVaultIdl, getKeyManagerAbi } from '../shared/contract_interfaces'; @@ -156,31 +157,31 @@ export async function initializeSolanaPrograms(solClient: Connection, solKey: st programId: solanaVaultProgramId, }), ); - await signAndSendTxSol(tx); + await signAndSendTxSol(tx, false); // Set nonce authority to the new AggKey - tx = new Transaction(); - for (let i = 0; i < solanaNumberOfNonces; i++) { - // Using the index stringified as the seed ('0', '1', '2' ...) - const seed = i.toString(); - - // Deriving the nonceAccounts with index seeds to find the nonce accounts - const nonceAccountPubKey = await PublicKey.createWithSeed( - whaleKeypair.publicKey, - seed, - SystemProgram.programId, - ); - - // Set nonce authority to the new AggKey - tx.add( - SystemProgram.nonceAuthorize({ - noncePubkey: new PublicKey(nonceAccountPubKey), - authorizedPubkey: whaleKeypair.publicKey, - newAuthorizedPubkey: newAggKey, - }), - ); + for (const [nonceNumber, prefix] of [ + [solanaNumberOfNonces, ''], + [solanaNumberOfAdditionalNonces, '-add-nonce'], + ]) { + for (let i = 0; i < Number(nonceNumber); i++) { + const seed = prefix + i.toString(); + const nonceAccountPubKey = await PublicKey.createWithSeed( + whaleKeypair.publicKey, + seed, + SystemProgram.programId, + ); + + tx = new Transaction().add( + SystemProgram.nonceAuthorize({ + noncePubkey: new PublicKey(nonceAccountPubKey), + authorizedPubkey: whaleKeypair.publicKey, + newAuthorizedPubkey: newAggKey, + }), + ); + await signAndSendTxSol(tx, false); + } } - await signAndSendTxSol(tx); // Set Vault's upgrade authority to upgradeSignerPda and enable token support tx = new Transaction().add( @@ -219,7 +220,7 @@ export async function initializeSolanaPrograms(solClient: Connection, solKey: st programId: solanaVaultProgramId, }), ); - await signAndSendTxSol(tx); + await signAndSendTxSol(tx, false); // Set Governance authority to the new AggKey (State Chain) const setGovKeyWithGovKeyDiscriminatorString = vaultIdl.instructions.find( @@ -241,5 +242,5 @@ export async function initializeSolanaPrograms(solClient: Connection, solKey: st programId: solanaVaultProgramId, }), ); - await signAndSendTxSol(tx); + await signAndSendTxSol(tx, false); } diff --git a/bouncer/shared/sol_vault_swap.ts b/bouncer/shared/sol_vault_swap.ts index 2e5501c0b08..b64b04304d4 100644 --- a/bouncer/shared/sol_vault_swap.ts +++ b/bouncer/shared/sol_vault_swap.ts @@ -26,7 +26,7 @@ import { } from './utils'; import { CcmDepositMetadata, DcaParams, FillOrKillParamsX128 } from './new_swap'; -import { SwapEndpoint } from '../../contract-interfaces/sol-program-idls/v1.0.1-swap-endpoint/swap_endpoint'; +import { SwapEndpoint } from '../../contract-interfaces/sol-program-idls/v0.1.1-alt-test/swap_endpoint'; import { getSolanaSwapEndpointIdl } from './contract_interfaces'; import { getChainflipApi } from './utils/substrate'; import { getBalance } from './get_balance'; diff --git a/bouncer/shared/utils.ts b/bouncer/shared/utils.ts index 6cdc39b13b9..4166a8ecd62 100644 --- a/bouncer/shared/utils.ts +++ b/bouncer/shared/utils.ts @@ -62,7 +62,9 @@ export type VaultSwapParams = { const isSDKAsset = (asset: Asset): asset is SDKAsset => asset in assetConstants; const isSDKChain = (chain: Chain): chain is SDKChain => chain in chainConstants; -export const solanaNumberOfNonces = 10; +// Nonces deployed in two stages +export const solanaNumberOfNonces: number = 10; +export const solanaNumberOfAdditionalNonces: number = 40; const solCcmAccountsCodec = Struct({ cf_receiver: Struct({ @@ -150,6 +152,8 @@ export function getContractAddress(chain: Chain, contract: string): string { return '2tmtGLQcBd11BMiE9B1tAkQXwmPNgR79Meki2Eme4Ec9'; case 'SWAP_ENDPOINT_NATIVE_VAULT_ACCOUNT': return 'EWaGcrFXhf9Zq8yxSdpAa75kZmDXkRxaP17sYiL6UpZN'; + case 'USER_ADDRESS_LOOKUP_TABLE': + return '4eUGPyr3krnw8tD3rL3UBXXdy1cx8Sf9HKVESZUAatqv'; default: throw new Error(`Unsupported contract: ${contract}`); } @@ -1175,16 +1179,16 @@ export async function checkAvailabilityAllSolanaNonces(testContext: TestContext) // Check that all Solana nonces are available await using chainflip = await getChainflipApi(); - const maxRetries = 7; // 42 seconds + const maxRetries = 10; // 60 seconds for (let attempt = 0; attempt < maxRetries; attempt++) { const availableNonces = (await chainflip.query.environment.solanaAvailableNonceAccounts()) // eslint-disable-next-line @typescript-eslint/no-explicit-any .toJSON() as any[]; - if (availableNonces.length === solanaNumberOfNonces) { + if (availableNonces.length === solanaNumberOfNonces + solanaNumberOfAdditionalNonces) { break; } else if (attempt === maxRetries - 1) { throw new Error( - `Unexpected number of available nonces: ${availableNonces.length}, expected ${solanaNumberOfNonces}`, + `Unexpected number of available nonces: ${availableNonces.length}, expected ${solanaNumberOfNonces + solanaNumberOfAdditionalNonces}`, ); } else { await sleep(6000); diff --git a/bouncer/tests/solana_vault_settings_governance.ts b/bouncer/tests/solana_vault_settings_governance.ts index 857ef15a3bc..847fefcbba6 100755 --- a/bouncer/tests/solana_vault_settings_governance.ts +++ b/bouncer/tests/solana_vault_settings_governance.ts @@ -8,7 +8,7 @@ import { } from '../shared/utils'; import { submitGovernanceExtrinsic } from '../shared/cf_governance'; import { getSolanaVaultIdl } from '../shared/contract_interfaces'; -import { Vault } from '../../contract-interfaces/sol-program-idls/v1.0.1-swap-endpoint/vault'; +import { Vault } from '../../contract-interfaces/sol-program-idls/v0.1.1-alt-test/vault'; import { TestContext } from '../shared/utils/test_context'; import { Logger } from '../shared/utils/logger'; diff --git a/contract-interfaces/sol-program-idls/download-sol-program-idls.sh b/contract-interfaces/sol-program-idls/download-sol-program-idls.sh index 6bcd10b839c..6f0c5c18fc8 100755 --- a/contract-interfaces/sol-program-idls/download-sol-program-idls.sh +++ b/contract-interfaces/sol-program-idls/download-sol-program-idls.sh @@ -35,6 +35,7 @@ unzip -u ${ZIP_FILE} \ 'cf_tester.ts' \ 'swap_endpoint.json' \ 'swap_endpoint.ts' \ + 'alt_manager.json' \ -d $TARGET_DIR rm ${ZIP_FILE} \ No newline at end of file diff --git a/contract-interfaces/sol-program-idls/v0.1.1-alt-test/alt_manager.json b/contract-interfaces/sol-program-idls/v0.1.1-alt-test/alt_manager.json new file mode 100644 index 00000000000..7c50cb05293 --- /dev/null +++ b/contract-interfaces/sol-program-idls/v0.1.1-alt-test/alt_manager.json @@ -0,0 +1,371 @@ +{ + "address": "49XegQyykAXwzigc6u7gXbaLjhKfNadWMZwFiovzjwUw", + "metadata": { + "name": "alt_manager", + "version": "0.1.0", + "spec": "0.1.0", + "description": "Created with Anchor" + }, + "instructions": [ + { + "name": "check_remaining_accounts_ix", + "discriminator": [ + 59, + 191, + 203, + 214, + 176, + 149, + 65, + 76 + ], + "accounts": [ + { + "name": "data_account" + } + ], + "args": [] + }, + { + "name": "create_lookup_table", + "discriminator": [ + 74, + 26, + 45, + 214, + 23, + 155, + 143, + 153 + ], + "accounts": [ + { + "name": "data_account" + }, + { + "name": "agg_key", + "signer": true + }, + { + "name": "address_lookup_table_account", + "writable": true + }, + { + "name": "signer_pda", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 108, + 116, + 95, + 115, + 105, + 103, + 110, + 101, + 114 + ] + } + ] + } + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + }, + { + "name": "address_lookup_table_program", + "address": "AddressLookupTab1e1111111111111111111111111" + } + ], + "args": [ + { + "name": "recent_slot", + "type": "u64" + } + ] + }, + { + "name": "extend_protocol_lookup_table", + "discriminator": [ + 7, + 227, + 198, + 1, + 107, + 113, + 31, + 88 + ], + "accounts": [ + { + "name": "data_account" + }, + { + "name": "agg_key", + "signer": true + }, + { + "name": "address_lookup_table_account", + "writable": true + }, + { + "name": "signer_pda", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 108, + 116, + 95, + 115, + 105, + 103, + 110, + 101, + 114 + ] + } + ] + } + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + }, + { + "name": "address_lookup_table_program", + "address": "AddressLookupTab1e1111111111111111111111111" + } + ], + "args": [ + { + "name": "bump", + "type": "u8" + }, + { + "name": "new_addresses", + "type": { + "vec": "pubkey" + } + } + ] + }, + { + "name": "initialize_lookup_table", + "discriminator": [ + 149, + 120, + 10, + 249, + 212, + 185, + 177, + 216 + ], + "accounts": [ + { + "name": "signer", + "signer": true, + "address": "HfasueN6RNPjSM6rKGH5dga6kS2oUF8siGH3m4MXPURp" + }, + { + "name": "address_lookup_table_account", + "writable": true + }, + { + "name": "signer_pda", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 108, + 116, + 95, + 115, + 105, + 103, + 110, + 101, + 114 + ] + } + ] + } + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + }, + { + "name": "address_lookup_table_program", + "address": "AddressLookupTab1e1111111111111111111111111" + } + ], + "args": [ + { + "name": "bump", + "type": "u8" + }, + { + "name": "new_addresses", + "type": { + "vec": "pubkey" + } + } + ] + }, + { + "name": "rotate_nonces", + "discriminator": [ + 98, + 245, + 73, + 119, + 165, + 90, + 57, + 203 + ], + "accounts": [ + { + "name": "data_account" + }, + { + "name": "agg_key", + "signer": true + }, + { + "name": "new_agg_key", + "docs": [ + "NonceAuthorize instruction. However, we pass it as an account to save bytes so only", + "the reference is needed compared to it's address for every instruction." + ] + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + } + ], + "args": [] + } + ], + "accounts": [ + { + "name": "DataAccount", + "discriminator": [ + 85, + 240, + 182, + 158, + 76, + 7, + 18, + 233 + ] + } + ], + "errors": [ + { + "code": 6000, + "name": "CreateAltKeyMissmatch", + "msg": "Address lookup table doesn't match" + }, + { + "code": 6001, + "name": "ExtendAltInvalidKey", + "msg": "Address lookup table cant be extended with aggKey" + }, + { + "code": 6002, + "name": "CannotDeserializeAlt", + "msg": "Cant deserialize lookip table account" + }, + { + "code": 6003, + "name": "AddressExtensionLimitReached", + "msg": "Reached the maximum number of addresses that can be initialized" + }, + { + "code": 6004, + "name": "InvalidRemainingAccount", + "msg": "Invalid remaining accounts" + } + ], + "types": [ + { + "name": "DataAccount", + "docs": [ + "* ****************************************************************************\n * *************************** IMPORTANT NOTE *********************************\n * ****************************************************************************\n * If the vault is upgraded and the DataAccount struct is modified we need to\n * check the compatibility and ensure there is a proper migration process, given\n * that the Vault bytecode is the only thing being upgraded, not the data account.\n *\n * The easiest approach on upgrade is keeping the DataAccount unchanged and use\n * a new account struct for any new data that is required.\n *\n * DO NOT MODIFY THIS WITHOUT UNDERSTANDING THE CONSEQUENCES!\n * ****************************************************************************\n * ****************************************************************************" + ], + "type": { + "kind": "struct", + "fields": [ + { + "name": "agg_key", + "type": "pubkey" + }, + { + "name": "gov_key", + "type": "pubkey" + }, + { + "name": "token_vault_pda", + "type": "pubkey" + }, + { + "name": "token_vault_bump", + "type": "u8" + }, + { + "name": "upgrade_signer_pda", + "type": "pubkey" + }, + { + "name": "upgrade_signer_pda_bump", + "type": "u8" + }, + { + "name": "suspended", + "type": "bool" + }, + { + "name": "suspended_legacy_swaps", + "type": "bool" + }, + { + "name": "suspended_event_swaps", + "type": "bool" + }, + { + "name": "min_native_swap_amount", + "type": "u64" + }, + { + "name": "max_dst_address_len", + "type": "u16" + }, + { + "name": "max_ccm_message_len", + "type": "u32" + }, + { + "name": "max_cf_parameters_len", + "type": "u32" + }, + { + "name": "max_event_accounts", + "type": "u32" + } + ] + } + } + ] +} \ No newline at end of file diff --git a/contract-interfaces/sol-program-idls/v1.0.1-swap-endpoint/cf_tester.json b/contract-interfaces/sol-program-idls/v0.1.1-alt-test/cf_tester.json similarity index 100% rename from contract-interfaces/sol-program-idls/v1.0.1-swap-endpoint/cf_tester.json rename to contract-interfaces/sol-program-idls/v0.1.1-alt-test/cf_tester.json diff --git a/contract-interfaces/sol-program-idls/v1.0.1-swap-endpoint/cf_tester.ts b/contract-interfaces/sol-program-idls/v0.1.1-alt-test/cf_tester.ts similarity index 100% rename from contract-interfaces/sol-program-idls/v1.0.1-swap-endpoint/cf_tester.ts rename to contract-interfaces/sol-program-idls/v0.1.1-alt-test/cf_tester.ts diff --git a/contract-interfaces/sol-program-idls/v1.0.1-swap-endpoint/swap_endpoint.json b/contract-interfaces/sol-program-idls/v0.1.1-alt-test/swap_endpoint.json similarity index 100% rename from contract-interfaces/sol-program-idls/v1.0.1-swap-endpoint/swap_endpoint.json rename to contract-interfaces/sol-program-idls/v0.1.1-alt-test/swap_endpoint.json diff --git a/contract-interfaces/sol-program-idls/v1.0.1-swap-endpoint/swap_endpoint.ts b/contract-interfaces/sol-program-idls/v0.1.1-alt-test/swap_endpoint.ts similarity index 100% rename from contract-interfaces/sol-program-idls/v1.0.1-swap-endpoint/swap_endpoint.ts rename to contract-interfaces/sol-program-idls/v0.1.1-alt-test/swap_endpoint.ts diff --git a/contract-interfaces/sol-program-idls/v1.0.1-swap-endpoint/vault.json b/contract-interfaces/sol-program-idls/v0.1.1-alt-test/vault.json similarity index 100% rename from contract-interfaces/sol-program-idls/v1.0.1-swap-endpoint/vault.json rename to contract-interfaces/sol-program-idls/v0.1.1-alt-test/vault.json diff --git a/contract-interfaces/sol-program-idls/v1.0.1-swap-endpoint/vault.ts b/contract-interfaces/sol-program-idls/v0.1.1-alt-test/vault.ts similarity index 100% rename from contract-interfaces/sol-program-idls/v1.0.1-swap-endpoint/vault.ts rename to contract-interfaces/sol-program-idls/v0.1.1-alt-test/vault.ts diff --git a/engine/src/witness/sol.rs b/engine/src/witness/sol.rs index d2f718e63d0..a987fe8cf66 100644 --- a/engine/src/witness/sol.rs +++ b/engine/src/witness/sol.rs @@ -1,7 +1,8 @@ mod egress_witnessing; +mod lookup_table_witnessing; mod nonce_witnessing; -mod program_swaps_witnessing; mod sol_deposits; +mod vault_swaps_witnessing; use crate::{ elections::voter_api::{CompositeVoter, VoterApi}, @@ -180,7 +181,7 @@ impl VoterApi for SolanaVaultSwapsVoter { settings: ::ElectoralSettings, properties: ::ElectionProperties, ) -> Result>, anyhow::Error> { - program_swaps_witnessing::get_program_swaps( + vault_swaps_witnessing::get_vault_swaps( &self.client, settings.swap_endpoint_data_account_address, properties diff --git a/engine/src/witness/sol/egress_witnessing.rs b/engine/src/witness/sol/egress_witnessing.rs index 67ff1517139..2148e1d9d9c 100644 --- a/engine/src/witness/sol/egress_witnessing.rs +++ b/engine/src/witness/sol/egress_witnessing.rs @@ -35,9 +35,8 @@ pub async fn get_finalized_fee_and_success_status( // doesn't get the tx. But "Processed" is timing out so we better // retry with finalized. commitment: Some(CommitmentConfig::finalized()), - // Using 0 as max_supported_transaction_version to ensure we query all - // transactions regardless of version. This is not strictly necessary, but - // ensures we don't miss anything. + // Query for both Legacy and Versioned transactions since we can + // build both types. max_supported_transaction_version: Some(0), }, ) diff --git a/engine/src/witness/sol/lookup_table_witnessing.rs b/engine/src/witness/sol/lookup_table_witnessing.rs new file mode 100644 index 00000000000..5e779eaad38 --- /dev/null +++ b/engine/src/witness/sol/lookup_table_witnessing.rs @@ -0,0 +1,226 @@ +use cf_chains::sol::SolAddress; +use itertools::Itertools; + +use crate::sol::{ + commitment_config::CommitmentConfig, + retry_rpc::SolRetryRpcApi, + rpc_client_api::{ + ParsedAccount, RpcAccountInfoConfig, UiAccount, UiAccountData, UiAccountEncoding, + }, +}; +use anyhow::{anyhow, Result}; +use serde_json::Value; +use sol_prim::Slot; +use std::str::FromStr; + +// We want to return None if the account is not found or there is any error. It should +// only error if the rpc call fails or returns an unrecognized format respons. That is +// because this address will be provided by the user (user alts) and in case of the address +// not being a valid ALT we still want to reach consensus. +#[allow(dead_code)] +pub async fn get_lookup_table_state( + sol_rpc: &SolRetryRpcClient, + lookup_table_address: SolAddress, +) -> Result>, anyhow::Error> +where + SolRetryRpcClient: SolRetryRpcApi + Send + Sync + Clone, +{ + let account_info = sol_rpc + .get_multiple_accounts( + &[lookup_table_address], + RpcAccountInfoConfig { + encoding: Some(UiAccountEncoding::JsonParsed), + data_slice: None, + commitment: Some(CommitmentConfig::finalized()), + min_context_slot: None, + }, + ) + .await + .value + .into_iter() + .exactly_one() + .expect("We queried for exactly one account."); + + match account_info { + Some(UiAccount { + data: UiAccountData::Json(ParsedAccount { program, space: _, parsed }), + owner, + .. + }) => { + if program != "address-lookup-table" { + tracing::info!("Program is not an address lookup table: {}", program); + return Ok(None); + } + + let owner_address = SolAddress::from_str(owner.as_str()).unwrap(); + + if owner_address != sol_prim::consts::ADDRESS_LOOKUP_TABLE_PROGRAM { + tracing::info!("Owner is not address lookup table program: {}", owner); + return Ok(None); + } + + let info = match parsed.get("info").and_then(Value::as_object) { + Some(value) => value, + None => { + tracing::info!("Failed to parse the info: {}", parsed); + return Ok(None); + }, + }; + + let deactivation_slot: Slot = Slot::from_str( + info.get("deactivationSlot").and_then(Value::as_str).ok_or(anyhow!( + "Deactivation slot not found in address lookup table account info: {:?}", + info + ))?, + )?; + + // Address lookup table is being deactivated + if deactivation_slot != Slot::MAX { + return Ok(None); + } + let addresses = info.get("addresses").and_then(Value::as_array).ok_or(anyhow!( + "Addresses not found in address lookup table account info: {:?}", + info + ))?; + + let addresses_vector: Vec = addresses + .iter() + .filter_map(|address| address.as_str()) + .map(|address| SolAddress::from_str(address).unwrap()) + .collect(); + + // We might want to return an AddressLookupTable Account type, it depends on how the + // elections are setup. + Ok(Some(addresses_vector)) + }, + // If the account is not JsonParsed as a Lookup Table we assume it's either empty or another + // account. We can also consider not returning an Option and instead return an empty + // vector if the ALT is not found. + Some(_) => { + tracing::info!( + "Address lookup table account encoding is not JsonParsed for account {:?}: {:?}", + lookup_table_address, + account_info + ); + Ok(None) + }, + None => Ok(None), + } +} + +#[cfg(test)] +mod tests { + use crate::{ + settings::{HttpEndpoint, NodeContainer}, + sol::retry_rpc::SolRetryRpcClient, + }; + + use cf_chains::{Chain, Solana}; + use cf_utilities::task_scope; + use futures_util::FutureExt; + use std::str::FromStr; + + use super::*; + + #[tokio::test] + #[ignore = "requires an external endpoint"] + async fn test_get_lookup_table_state() { + task_scope::task_scope(|scope| { + async { + let client = SolRetryRpcClient::new( + scope, + NodeContainer { + primary: HttpEndpoint { + // http_endpoint: "http://0.0.0.0:8899".into(), + http_endpoint: "https://api.mainnet-beta.solana.com".into(), + }, + backup: None, + }, + None, + Solana::WITNESS_PERIOD, + ) + .await + .unwrap(); + + // Mainnet-beta deployed address lookup table account + let mainnet_alt_address: SolAddress = + SolAddress::from_str("2immgwYNHBbyVQKVGCEkgWpi53bLwWNRMB5G2nbgYV17").unwrap(); + + let addresses = + get_lookup_table_state(&client, mainnet_alt_address).await.unwrap().unwrap(); + + // Check the first one just to make sure it's working + assert_eq!( + addresses.first().unwrap(), + &SolAddress::from_str("11111111111111111111111111111111").unwrap() + ); + + // Test that a program will return None and not error + let addresses = get_lookup_table_state( + &client, + SolAddress::from_str("JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4").unwrap(), + ) + .await + .unwrap(); + assert_eq!(addresses, None); + + // Test a non existing address + let addresses = get_lookup_table_state( + &client, + SolAddress::from_str("6UzppnNP2baug3BisB9Mb1J5t43hV1YcawUtPXHchoHS").unwrap(), + ) + .await + .unwrap(); + assert_eq!(addresses, None); + + Ok(()) + } + .boxed() + }) + .await + .unwrap(); + } + + #[tokio::test] + #[ignore = "requires an external endpoint"] + async fn test_get_non_lookup_table() { + task_scope::task_scope(|scope| { + async { + let client = SolRetryRpcClient::new( + scope, + NodeContainer { + primary: HttpEndpoint { + http_endpoint: "https://api.mainnet-beta.solana.com".into(), + }, + backup: None, + }, + None, + Solana::WITNESS_PERIOD, + ) + .await + .unwrap(); + + let mainnet_empty_address: SolAddress = + SolAddress::from_str("ASriuNGwqUosyrUYNrpjMNUsGYAKFAVB4e3bVpeaRC7Y").unwrap(); + + let addresses = + get_lookup_table_state(&client, mainnet_empty_address).await.unwrap(); + + assert_eq!(addresses, None); + + let mainnet_nonce_account: SolAddress = + SolAddress::from_str("3bVqyf58hQHsxbjnqnSkopnoyEHB9v9KQwhZj7h1DucW").unwrap(); + + let addresses = + get_lookup_table_state(&client, mainnet_nonce_account).await.unwrap(); + + assert_eq!(addresses, None); + + Ok(()) + } + .boxed() + }) + .await + .unwrap(); + } +} diff --git a/engine/src/witness/sol/program_swaps_witnessing.rs b/engine/src/witness/sol/vault_swaps_witnessing.rs similarity index 99% rename from engine/src/witness/sol/program_swaps_witnessing.rs rename to engine/src/witness/sol/vault_swaps_witnessing.rs index c8a19d909a1..feca8db0f37 100644 --- a/engine/src/witness/sol/program_swaps_witnessing.rs +++ b/engine/src/witness/sol/vault_swaps_witnessing.rs @@ -39,7 +39,7 @@ const MAX_MULTIPLE_EVENT_ACCOUNTS_QUERY: usize = 10; // 5. If they are not seen in the SC we query the account data. Then we parse the account data and // ensure it's a valid a program swap. The new program swap needs to be reported to the SC. -pub async fn get_program_swaps( +pub async fn get_vault_swaps( sol_rpc: &SolRetryRpcClient, swap_endpoint_data_account_address: SolAddress, sc_open_accounts: HashSet, diff --git a/foreign-chains/solana/sol-prim/src/alt.rs b/foreign-chains/solana/sol-prim/src/alt.rs index a834961f376..197d9d7a19c 100644 --- a/foreign-chains/solana/sol-prim/src/alt.rs +++ b/foreign-chains/solana/sol-prim/src/alt.rs @@ -26,7 +26,9 @@ pub struct MessageAddressTableLookup { /// The definition of address lookup table accounts. /// /// As used by the `crate::message::v0` message format. -#[derive(Debug, PartialEq, Eq, Clone)] +#[derive( + Debug, PartialEq, Eq, Clone, Encode, Decode, Serialize, Deserialize, TypeInfo, Default, +)] pub struct AddressLookupTableAccount { pub key: Pubkey, pub addresses: Vec, diff --git a/foreign-chains/solana/sol-prim/src/consts.rs b/foreign-chains/solana/sol-prim/src/consts.rs index b52e02624ba..42bde45a112 100644 --- a/foreign-chains/solana/sol-prim/src/consts.rs +++ b/foreign-chains/solana/sol-prim/src/consts.rs @@ -44,6 +44,8 @@ pub const BPF_LOADER_UPGRADEABLE_ID: Address = const_address("BPFLoaderUpgradeab1e11111111111111111111111"); pub const COMPUTE_BUDGET_PROGRAM: Address = const_address("ComputeBudget111111111111111111111111111111"); +pub const ADDRESS_LOOKUP_TABLE_PROGRAM: Address = + const_address("AddressLookupTab1e1111111111111111111111111"); pub const MAX_TRANSACTION_LENGTH: usize = 1_232usize; pub const MAX_COMPUTE_UNITS_PER_TRANSACTION: u32 = 1_400_000u32; @@ -57,4 +59,4 @@ pub const SOL_USDC_DECIMAL: u8 = 6u8; pub const ACCOUNT_KEY_LENGTH_IN_TRANSACTION: usize = 32usize; pub const ACCOUNT_REFERENCE_LENGTH_IN_TRANSACTION: usize = 1usize; -pub const MAX_CCM_USER_ALTS: u8 = 5u8; // TODO: Albert come up with a good number for this +pub const MAX_CCM_USER_ALTS: u8 = 3u8; diff --git a/foreign-chains/solana/sol-prim/src/instructions/program_instructions.rs b/foreign-chains/solana/sol-prim/src/instructions/program_instructions.rs index f4663d77d61..8a89f994867 100644 --- a/foreign-chains/solana/sol-prim/src/instructions/program_instructions.rs +++ b/foreign-chains/solana/sol-prim/src/instructions/program_instructions.rs @@ -900,6 +900,29 @@ pub mod swap_endpoints { pub type SwapTokenParams = types::SwapTokenParams; } +pub mod alt_managers { + use super::*; + + solana_program!( + idl_path: concat!( + env!("CF_SOL_PROGRAM_IDL_ROOT"), "/", + env!("CF_SOL_PROGRAM_IDL_TAG"), "/" , + "alt_manager.json" + ), + AltManagerProgram { + rotate_nonces => RotateNonces { + args: [], + account_metas: [ + data_account: { signer: false, writable: false }, + agg_key: { signer: true, writable: false }, + new_agg_key: { signer: false, writable: false }, + system_program: { signer: false, writable: false }, + ] + }, + } + ); +} + #[cfg(test)] mod idl { use serde::{Deserialize, Serialize}; diff --git a/foreign-chains/solana/sol-prim/src/lib.rs b/foreign-chains/solana/sol-prim/src/lib.rs index b01db1bc012..8a1fcc86817 100644 --- a/foreign-chains/solana/sol-prim/src/lib.rs +++ b/foreign-chains/solana/sol-prim/src/lib.rs @@ -39,6 +39,7 @@ pub type Amount = u64; pub type SlotNumber = u64; pub type ComputeLimit = u32; pub type AccountBump = u8; +pub type Slot = u64; use crate::consts::{HASH_BYTES, MAX_BASE58_LEN, SOLANA_SIGNATURE_LEN}; diff --git a/localnet/common.sh b/localnet/common.sh index 53f4b137ffb..c54c674365c 100644 --- a/localnet/common.sh +++ b/localnet/common.sh @@ -102,9 +102,6 @@ build-localnet() { REPLY=$(check_endpoint_health -H "Content-Type: application/json" -s -d '{"id":1, "jsonrpc":"2.0", "method": "chain_getBlockHash", "params":[0]}' 'http://localhost:9947') || [ -z $(echo $REPLY | grep -o '\"result\":\"0x[^"]*' | grep -o '0x.*') ] DOT_GENESIS_HASH=$(echo $REPLY | grep -o '\"result\":\"0x[^"]*' | grep -o '0x.*') - echo "🐛 Fix solana symlink issue ..." - ln -sf $SOLANA_BASE_PATH/test-ledger/accounts/snapshot/100 $SOLANA_BASE_PATH/test-ledger/snapshot/100/accounts_hardlinks/account_path_0 - if which solana-test-validator >>$DEBUG_OUTPUT_DESTINATION 2>&1; then echo "☀️ Waiting for Solana node to start" ./localnet/init/scripts/start-solana.sh diff --git a/localnet/docker-compose.yml b/localnet/docker-compose.yml index 3e5ec0f5022..c03293f0ffa 100644 --- a/localnet/docker-compose.yml +++ b/localnet/docker-compose.yml @@ -9,7 +9,7 @@ services: command: /bin/sh -c "cp -R /initial-state/* /localnet-initial-state" solana-init: - image: ghcr.io/chainflip-io/solana-localnet-ledger:v1.0.1-swap-endpoint + image: ghcr.io/chainflip-io/solana-localnet-ledger:v0.1.1-alt-test pull_policy: if_not_present container_name: init-solana platform: linux/amd64 diff --git a/state-chain/cf-integration-tests/src/solana.rs b/state-chain/cf-integration-tests/src/solana.rs index a0f0749603a..3eb75f0fe46 100644 --- a/state-chain/cf-integration-tests/src/solana.rs +++ b/state-chain/cf-integration-tests/src/solana.rs @@ -11,8 +11,7 @@ use cf_chains::{ api::{SolanaApi, SolanaEnvironment, SolanaTransactionBuildingError}, sol_tx_core::sol_test_values, transaction_builder::SolanaTransactionBuilder, - SolAddress, SolApiEnvironment, SolCcmAccounts, SolCcmAddress, SolHash, SolPubkey, - SolanaCrypto, + SolAddress, SolCcmAccounts, SolCcmAddress, SolHash, SolPubkey, SolanaCrypto, }, CcmChannelMetadata, CcmDepositMetadata, Chain, ChannelRefundParameters, ExecutexSwapAndCallError, ForeignChainAddress, RequiresSignatureRefresh, SetAggKeyWithAggKey, @@ -76,15 +75,7 @@ type SolanaElectionVote = BoundedBTreeMap< fn setup_sol_environments() { // Environment::SolanaApiEnvironment - pallet_cf_environment::SolanaApiEnvironment::::set(SolApiEnvironment { - vault_program: sol_test_values::VAULT_PROGRAM, - vault_program_data_account: sol_test_values::VAULT_PROGRAM_DATA_ACCOUNT, - token_vault_pda_account: sol_test_values::TOKEN_VAULT_PDA_ACCOUNT, - usdc_token_mint_pubkey: sol_test_values::USDC_TOKEN_MINT_PUB_KEY, - usdc_token_vault_ata: sol_test_values::USDC_TOKEN_VAULT_ASSOCIATED_TOKEN_ACCOUNT, - swap_endpoint_program: sol_test_values::SWAP_ENDPOINT_PROGRAM, - swap_endpoint_program_data_account: sol_test_values::SWAP_ENDPOINT_PROGRAM_DATA_ACCOUNT, - }); + pallet_cf_environment::SolanaApiEnvironment::::set(sol_test_values::api_env()); // Environment::AvailableDurableNonces pallet_cf_environment::SolanaAvailableNonceAccounts::::set( @@ -536,7 +527,7 @@ fn solana_ccm_fails_with_invalid_input() { } #[test] -fn failed_ccm_does_not_consume_durable_nonce() { +fn failed_rotation_does_not_consume_durable_nonce() { const EPOCH_BLOCKS: u32 = 100; const MAX_AUTHORITIES: AuthorityCount = 10; super::genesis::with_test_defaults() @@ -569,7 +560,7 @@ fn failed_ccm_does_not_consume_durable_nonce() { // Failed Rotate Key message does not consume DurableNonce // Add extra Durable nonces to make RotateAggkey too long - let available_nonces = (0..20) + let available_nonces = (0..100) .map(|x| (SolAddress([x as u8; 32]), SolHash::default())) .collect::>(); pallet_cf_environment::SolanaAvailableNonceAccounts::::set( diff --git a/state-chain/chains/src/sol.rs b/state-chain/chains/src/sol.rs index 607f41513b7..93ecfc91905 100644 --- a/state-chain/chains/src/sol.rs +++ b/state-chain/chains/src/sol.rs @@ -37,9 +37,10 @@ pub use sol_prim::{ VersionedTransaction as SolVersionedTransaction, }, Address as SolAddress, AddressLookupTableAccount as SolAddressLookupTableAccount, - Amount as SolAmount, ComputeLimit as SolComputeLimit, Digest as SolHash, Hash as RawSolHash, - Instruction as SolInstruction, InstructionRpc as SolInstructionRpc, Pubkey as SolPubkey, - Signature as SolSignature, SlotNumber as SolBlockNumber, + AddressLookupTableAccount, Amount as SolAmount, ComputeLimit as SolComputeLimit, + Digest as SolHash, Hash as RawSolHash, Instruction as SolInstruction, + InstructionRpc as SolInstructionRpc, Pubkey as SolPubkey, Signature as SolSignature, + SlotNumber as SolBlockNumber, }; pub use sol_tx_core::{ rpc_types, AccountMeta as SolAccountMeta, CcmAccounts as SolCcmAccounts, @@ -167,7 +168,8 @@ pub mod compute_units_costs { pub const COMPUTE_UNITS_PER_TRANSFER_NATIVE: SolComputeLimit = 150u32; pub const COMPUTE_UNITS_PER_FETCH_TOKEN: SolComputeLimit = 45_000u32; pub const COMPUTE_UNITS_PER_TRANSFER_TOKEN: SolComputeLimit = 50_000u32; - pub const COMPUTE_UNITS_PER_ROTATION: SolComputeLimit = 8_000u32; + pub const COMPUTE_UNITS_PER_ROTATION: SolComputeLimit = 5_000u32; + pub const COMPUTE_UNITS_PER_NONCE_ROTATION: SolComputeLimit = 4_000u32; pub const COMPUTE_UNITS_PER_SET_GOV_KEY: SolComputeLimit = 15_000u32; pub const COMPUTE_UNITS_PER_BUMP_DERIVATION: SolComputeLimit = 2_000u32; pub const COMPUTE_UNITS_PER_FETCH_AND_CLOSE_VAULT_SWAP_ACCOUNTS: SolComputeLimit = 20_000u32; @@ -451,7 +453,7 @@ pub mod signing_key { /// Solana Environment variables used when building the base API call. #[derive( - Encode, Decode, TypeInfo, Default, Copy, Clone, PartialEq, Eq, Debug, Serialize, Deserialize, + Encode, Decode, TypeInfo, Default, Clone, PartialEq, Eq, Debug, Serialize, Deserialize, )] pub struct SolApiEnvironment { // For native Sol API calls. @@ -468,6 +470,8 @@ pub struct SolApiEnvironment { // For program swaps API calls. pub swap_endpoint_program: SolAddress, pub swap_endpoint_program_data_account: SolAddress, + pub alt_manager_program: SolAddress, + pub address_lookup_table_account: AddressLookupTableAccount, } impl DepositDetailsToTransactionInId for () {} diff --git a/state-chain/chains/src/sol/api.rs b/state-chain/chains/src/sol/api.rs index de1085de940..016d83c2175 100644 --- a/state-chain/chains/src/sol/api.rs +++ b/state-chain/chains/src/sol/api.rs @@ -44,8 +44,6 @@ pub struct CurrentAggKey; pub struct CurrentOnChainKey; #[derive(Clone, Encode, Decode, PartialEq, Debug, TypeInfo)] pub struct SolanaAddressLookupTables(pub SwapRequestId); -#[derive(Clone, Encode, Decode, PartialEq, Debug, TypeInfo)] -pub struct ChainflipAddressLookupTable; pub type DurableNonceAndAccount = (SolAddress, SolHash); @@ -78,7 +76,6 @@ pub trait SolanaEnvironment: + ChainEnvironment + ChainEnvironment> + ChainEnvironment> - + ChainEnvironment + RecoverDurableNonce { fn compute_price() -> Result { @@ -110,18 +107,9 @@ pub trait SolanaEnvironment: .ok_or(SolanaTransactionBuildingError::NoNonceAccountsSet) } - /// Get all relevant Address lookup tables from the Environment. - /// Returns Chainflip's ALT proceeded with user's ALTs. - fn get_address_lookup_tables(id: Option) -> Vec { - let mut alts = Self::get_cf_address_lookup_table().map(|alt| vec![alt]).unwrap_or_default(); - if let Some(id) = id { - alts.extend(Self::lookup(SolanaAddressLookupTables(id)).unwrap_or_default()); - } - alts - } - - fn get_cf_address_lookup_table() -> Option { - Self::lookup(ChainflipAddressLookupTable) + /// Get any user-defined Address lookup tables from the Environment. + fn get_address_lookup_tables(id: SwapRequestId) -> Vec { + Self::lookup(SolanaAddressLookupTables(id)).unwrap_or_default() } } @@ -248,7 +236,6 @@ impl SolanaApi { let sol_api_environment = Environment::api_environment()?; let compute_price = Environment::compute_price()?; let durable_nonce = Environment::nonce_account()?; - let address_lookup_tables = Environment::get_address_lookup_tables(None); // Build the transaction let transaction = SolanaTransactionBuilder::fetch_from( @@ -257,7 +244,6 @@ impl SolanaApi { agg_key, durable_nonce, compute_price, - address_lookup_tables, )?; Ok(Self { @@ -275,7 +261,6 @@ impl SolanaApi { let agg_key = Environment::current_agg_key()?; let sol_api_environment = Environment::api_environment()?; let compute_price = Environment::compute_price()?; - let address_lookup_tables = Environment::get_address_lookup_tables(None); transfer_params .into_iter() @@ -308,7 +293,7 @@ impl SolanaApi { durable_nonce, compute_price, SOL_USDC_DECIMAL, - address_lookup_tables.clone(), + vec![sol_api_environment.address_lookup_table_account.clone()], ) }, }?; @@ -333,7 +318,6 @@ impl SolanaApi { let nonce_accounts = Environment::all_nonce_accounts()?; let compute_price = Environment::compute_price()?; let durable_nonce = Environment::nonce_account()?; - let address_lookup_tables = Environment::get_address_lookup_tables(None); // Build the transaction let transaction = SolanaTransactionBuilder::rotate_agg_key( @@ -342,9 +326,10 @@ impl SolanaApi { sol_api_environment.vault_program, sol_api_environment.vault_program_data_account, agg_key, + sol_api_environment.alt_manager_program, durable_nonce, compute_price, - address_lookup_tables, + vec![sol_api_environment.address_lookup_table_account], ) .inspect_err(|e| { // Vault Rotation call building NOT transactional - meaning when this fails, @@ -411,8 +396,11 @@ impl SolanaApi { let sol_api_environment = Environment::api_environment()?; let agg_key = Environment::current_agg_key()?; + + // Get the Address lookup tables. Chainflip's ALT is proceeded with the User's. // TODO roy: Coordinate with Ramiz on the interface for getting ALTS - let address_lookup_tables = Environment::get_address_lookup_tables(Some(swap_request_id)); + let mut address_lookup_tables = vec![sol_api_environment.address_lookup_table_account]; + address_lookup_tables.extend(Environment::get_address_lookup_tables(swap_request_id)); // Ensure the CCM parameters do not contain blacklisted accounts. check_ccm_for_blacklisted_accounts( @@ -510,7 +498,6 @@ impl SolanaApi { let sol_api_environment = Environment::api_environment()?; let compute_price = Environment::compute_price()?; let durable_nonce = Environment::nonce_account()?; - let address_lookup_tables = Environment::get_address_lookup_tables(None); // Build the transaction let transaction = SolanaTransactionBuilder::fetch_and_close_vault_swap_accounts( @@ -521,7 +508,7 @@ impl SolanaApi { agg_key, durable_nonce, compute_price, - address_lookup_tables, + vec![sol_api_environment.address_lookup_table_account], )?; Ok(Self { @@ -544,7 +531,6 @@ impl SolanaApi { let sol_api_environment = Environment::api_environment()?; let compute_price = Environment::compute_price()?; let durable_nonce = Environment::nonce_account()?; - let address_lookup_tables = Environment::get_address_lookup_tables(None); // Build the transaction let transaction = SolanaTransactionBuilder::set_program_swaps_parameters( @@ -560,7 +546,7 @@ impl SolanaApi { agg_key, durable_nonce, compute_price, - address_lookup_tables, + vec![sol_api_environment.address_lookup_table_account], )?; Ok(Self { @@ -579,7 +565,6 @@ impl SolanaApi { let sol_api_environment = Environment::api_environment()?; let compute_price = Environment::compute_price()?; let durable_nonce = Environment::nonce_account()?; - let address_lookup_tables = Environment::get_address_lookup_tables(None); // Build the transaction let transaction = SolanaTransactionBuilder::enable_token_support( @@ -592,7 +577,7 @@ impl SolanaApi { agg_key, durable_nonce, compute_price, - address_lookup_tables, + vec![sol_api_environment.address_lookup_table_account], )?; Ok(Self { @@ -734,7 +719,6 @@ impl SetGovKeyWithAggKey for Solan let sol_api_environment = Environment::api_environment().map_err(|_e| ())?; let compute_price = Environment::compute_price().map_err(|_e| ())?; let durable_nonce = Environment::nonce_account().map_err(|_e| ())?; - let address_lookup_tables = Environment::get_address_lookup_tables(None); // Build the transaction let transaction = SolanaTransactionBuilder::set_gov_key_with_agg_key( @@ -744,7 +728,7 @@ impl SetGovKeyWithAggKey for Solan agg_key, durable_nonce, compute_price, - address_lookup_tables, + vec![sol_api_environment.address_lookup_table_account], ) .map_err(|e| { // SetGovKeyWithAggKey call building NOT transactional - meaning when this fails, diff --git a/state-chain/chains/src/sol/sol_tx_core.rs b/state-chain/chains/src/sol/sol_tx_core.rs index d9a7132d64e..7fa6df23d69 100644 --- a/state-chain/chains/src/sol/sol_tx_core.rs +++ b/state-chain/chains/src/sol/sol_tx_core.rs @@ -166,6 +166,10 @@ pub mod sol_test_values { const_address("35uYgHdfZQT4kHkaaXQ6ZdCkK5LFrsk43btTLbGCRCNT"); pub const SWAP_ENDPOINT_PROGRAM_DATA_ACCOUNT: SolAddress = const_address("2tmtGLQcBd11BMiE9B1tAkQXwmPNgR79Meki2Eme4Ec9"); + pub const ALT_MANAGER_PROGRAM: SolAddress = + const_address("49XegQyykAXwzigc6u7gXbaLjhKfNadWMZwFiovzjwUw"); + pub const ADDRESS_LOOKUP_TABLE_ACCOUNT: SolAddress = + const_address("7drVSq2ymJLNnXyCciHbNqHyzuSt1SL4iQSEThiESN2c"); pub const EVENT_AND_SENDER_ACCOUNTS: [VaultSwapAccountAndSender; 11] = [ VaultSwapAccountAndSender { vault_swap_account: const_address("2cHcSNtikMpjxJfwwoYL3udpy7hedRExyhakk2eZ6cYA"), @@ -248,6 +252,8 @@ pub mod sol_test_values { usdc_token_vault_ata: USDC_TOKEN_VAULT_ASSOCIATED_TOKEN_ACCOUNT, swap_endpoint_program: SWAP_ENDPOINT_PROGRAM, swap_endpoint_program_data_account: SWAP_ENDPOINT_PROGRAM_DATA_ACCOUNT, + alt_manager_program: ALT_MANAGER_PROGRAM, + address_lookup_table_account: user_alt(), } } @@ -331,10 +337,7 @@ pub mod sol_test_values { } pub fn user_alt() -> SolAddressLookupTableAccount { - SolAddressLookupTableAccount { - key: const_address("3VBLeVu7rZciyk19M9V7VbHBM2uFm9YbnKKPB33mGRW8").into(), - addresses: vec![TRANSFER_TO_ACCOUNT.into()], - } + SolAddressLookupTableAccount { key: ADDRESS_LOOKUP_TABLE_ACCOUNT.into(), addresses: vec![] } } #[track_caller] diff --git a/state-chain/chains/src/sol/transaction_builder.rs b/state-chain/chains/src/sol/transaction_builder.rs index fed9c8aa220..0231fea6ca5 100644 --- a/state-chain/chains/src/sol/transaction_builder.rs +++ b/state-chain/chains/src/sol/transaction_builder.rs @@ -12,9 +12,10 @@ use crate::{ COMPUTE_UNITS_PER_BUMP_DERIVATION, COMPUTE_UNITS_PER_CLOSE_ACCOUNT, COMPUTE_UNITS_PER_ENABLE_TOKEN_SUPPORT, COMPUTE_UNITS_PER_FETCH_AND_CLOSE_VAULT_SWAP_ACCOUNTS, COMPUTE_UNITS_PER_FETCH_NATIVE, - COMPUTE_UNITS_PER_FETCH_TOKEN, COMPUTE_UNITS_PER_ROTATION, - COMPUTE_UNITS_PER_SET_GOV_KEY, COMPUTE_UNITS_PER_SET_PROGRAM_SWAPS_PARAMS, - COMPUTE_UNITS_PER_TRANSFER_NATIVE, COMPUTE_UNITS_PER_TRANSFER_TOKEN, + COMPUTE_UNITS_PER_FETCH_TOKEN, COMPUTE_UNITS_PER_NONCE_ROTATION, + COMPUTE_UNITS_PER_ROTATION, COMPUTE_UNITS_PER_SET_GOV_KEY, + COMPUTE_UNITS_PER_SET_PROGRAM_SWAPS_PARAMS, COMPUTE_UNITS_PER_TRANSFER_NATIVE, + COMPUTE_UNITS_PER_TRANSFER_TOKEN, }, sol_tx_core::{ address_derivation::{ @@ -27,8 +28,8 @@ use crate::{ TOKEN_PROGRAM_ID, }, program_instructions::{ - swap_endpoints::SwapEndpointProgram, InstructionExt, SystemProgramInstruction, - VaultProgram, + alt_managers::AltManagerProgram, swap_endpoints::SwapEndpointProgram, + InstructionExt, SystemProgramInstruction, VaultProgram, }, token_instructions::AssociatedTokenAccountInstruction, AccountMeta, @@ -119,7 +120,6 @@ impl SolanaTransactionBuilder { agg_key: SolAddress, durable_nonce: DurableNonceAndAccount, compute_price: SolAmount, - address_lookup_tables: Vec, ) -> Result { let mut compute_limit: SolComputeLimit = BASE_COMPUTE_UNITS_PER_TX; let instructions = fetch_params @@ -190,7 +190,7 @@ impl SolanaTransactionBuilder { agg_key.into(), compute_price, compute_limit_with_buffer(compute_limit), - address_lookup_tables, + vec![sol_api_environment.address_lookup_table_account], ) } @@ -271,31 +271,45 @@ impl SolanaTransactionBuilder { vault_program: SolAddress, vault_program_data_account: SolAddress, agg_key: SolAddress, + alt_manager: SolAddress, durable_nonce: DurableNonceAndAccount, compute_price: SolAmount, address_lookup_tables: Vec, ) -> Result { - let mut instructions = vec![VaultProgram::with_id(vault_program).rotate_agg_key( - false, - vault_program_data_account, - agg_key, - new_agg_key, - system_program_id(), - )]; - instructions.extend(all_nonce_accounts.into_iter().map(|nonce_account| { - SystemProgramInstruction::nonce_authorize( - &nonce_account.into(), - &agg_key.into(), - &new_agg_key.into(), - ) - })); + let number_of_nonces = all_nonce_accounts.len() as u32; + let all_nonce_accounts_meta: Vec = all_nonce_accounts + .into_iter() + .map(|nonce_account| AccountMeta::new(nonce_account.into(), false)) + .collect(); + + // Rotate nonces must come before the agg Key rotation, otherwise the aggKey + // validation will fail on the rotate nonces instruction. + let instructions = vec![ + AltManagerProgram::with_id(alt_manager) + .rotate_nonces( + vault_program_data_account, + agg_key, + new_agg_key, + system_program_id(), + ) + .with_additional_accounts(all_nonce_accounts_meta), + VaultProgram::with_id(vault_program).rotate_agg_key( + false, + vault_program_data_account, + agg_key, + new_agg_key, + system_program_id(), + ), + ]; Self::build( instructions, durable_nonce, agg_key.into(), compute_price, - compute_limit_with_buffer(COMPUTE_UNITS_PER_ROTATION), + compute_limit_with_buffer( + COMPUTE_UNITS_PER_ROTATION + COMPUTE_UNITS_PER_NONCE_ROTATION * number_of_nonces, + ), address_lookup_tables, ) } @@ -599,12 +613,11 @@ pub mod test { agg_key(), durable_nonce(), compute_price(), - vec![chainflip_alt()], ) .unwrap(); // Serialized tx built in `create_fetch_native` test - let expected_serialized_tx = hex_literal::hex!("014c9e86bf4a01223aaad71560605c3bf8925aebaec28dad02ae7008290cf3682e649ab82d087c387d5ae72d362852737ce5802d48b17e054500bf8ad40787890e8001000407f79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb3a4539fbb757256442c16343f639b15db95c39a6d35721439f7f94f5c8776b7bfd35d0bf8686de2e369c3d97a8033b31e6bc33518629f59314bc3d9050956c8d00000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea940000072b5d2051d300b10b74314b7e25ace9998ca66eb2c7fbc10ef130dd67028293cc27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e489000403030705000404000000040009038096980000000000040005021f95000006050800020103158e24658f6c59298c080000000b0c0d3700000000fc013001afd71da9456a977233960b08eba77d2e3690b8c7259637c8fb8f82cf58a101090102").to_vec(); + let expected_serialized_tx = hex_literal::hex!("0183f284c4160d449a41f0a7b30c3710a7e1876d514ef6d87b89a35ae203d50c6928b1dcd2f821496ac4027bfd84e07f921a912537e3d3f3cd4530935b0cae36028001000509f79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb17eb2b10d3377bda2bc7bea65bec6b8372f4fc3463ec2cd6f9fde4b2c633d1923a4539fbb757256442c16343f639b15db95c39a6d35721439f7f94f5c8776b7bfd35d0bf8686de2e369c3d97a8033b31e6bc33518629f59314bc3d9050956c8d00000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea940000072b5d2051d300b10b74314b7e25ace9998ca66eb2c7fbc10ef130dd67028293ca1e031c8bc9bec3b610cf7b36eb3bf3aa40237c9e5be2c7893878578439eb00bc27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e489000404030106000404000000050009038096980000000000050005021f95000007050800030204158e24658f6c59298c080000000b0c0d3700000000fc00").to_vec(); test_constructed_transaction(transaction, expected_serialized_tx); } @@ -622,12 +635,11 @@ pub mod test { agg_key(), durable_nonce(), compute_price(), - vec![chainflip_alt()], ) .unwrap(); // Serialized tx built in `create_fetch_native_in_batch` test - let expected_serialized_tx = hex_literal::hex!("012a95015c2c1a08af3013fd2575a7f61bf3a4faca1a010f7ec29f017ff10b52c49b9b8113e1adc89a9248c9537bff2eb3b2ca5bfafe9abbe4fbea753fccc139008001000409f79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb38861d2f0bf5cd80031b701a6c25d13b4c812dd92f9d6301fafd9a58fb9e438646cd507258c10454d484e64ba59d3e7570658001c5f854b6b3ebb57be90e7a708d9871ed5fb2ee05765af23b7cabcc0d6b08ed370bb9f616a0d4dea40a25f870b5b9d633289c8fd72fb05f33349bf4cc44e82add5d865311ae346d7c9a67b7dd00000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea940000072b5d2051d300b10b74314b7e25ace9998ca66eb2c7fbc10ef130dd67028293cc27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e48900050503090700040400000006000903809698000000000006000502c34a010008050a00020105158e24658f6c59298c080000000000000000000000ff08050a00030405158e24658f6c59298c080000000100000000000000ff013001afd71da9456a977233960b08eba77d2e3690b8c7259637c8fb8f82cf58a101090102").to_vec(); + let expected_serialized_tx = hex_literal::hex!("01f6a40d02eb553db89f9be4a37bfccd9c9a18ea6687c6e092cec5935863f8b4416c2a290cc474be118a404dc3035866e714dd70d4c77a6549b59a21a6bdb6bf06800100050bf79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb17eb2b10d3377bda2bc7bea65bec6b8372f4fc3463ec2cd6f9fde4b2c633d19238861d2f0bf5cd80031b701a6c25d13b4c812dd92f9d6301fafd9a58fb9e438646cd507258c10454d484e64ba59d3e7570658001c5f854b6b3ebb57be90e7a708d9871ed5fb2ee05765af23b7cabcc0d6b08ed370bb9f616a0d4dea40a25f870b5b9d633289c8fd72fb05f33349bf4cc44e82add5d865311ae346d7c9a67b7dd00000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea940000072b5d2051d300b10b74314b7e25ace9998ca66eb2c7fbc10ef130dd67028293ca1e031c8bc9bec3b610cf7b36eb3bf3aa40237c9e5be2c7893878578439eb00bc27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e48900050603010800040400000007000903809698000000000007000502c34a010009050a00030206158e24658f6c59298c080000000000000000000000ff09050a00040506158e24658f6c59298c080000000100000000000000ff00").to_vec(); test_constructed_transaction(transaction, expected_serialized_tx); } @@ -641,12 +653,11 @@ pub mod test { agg_key(), durable_nonce(), compute_price(), - vec![chainflip_alt()], ) .unwrap(); // Serialized tx built in `create_fetch_tokens` test - let expected_serialized_tx = hex_literal::hex!("0171e6c4881666cb11c8ab4402a1b0b5728c5a18acd668b0ffb524d913ff5bb717597564d05880a8e693ea3c6fd329750e88a0b6de6f97fa62a0c428b020cbea0e8001000609f79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb42ff6863b52c3f8faf95739e6541bda5d0ac593f00c6c07d9ab37096bf26d910ae85f2fb6289c70bfe37df150dddb17dd84f403fd0b1aa1bfee85795159de21f00000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea940000006ddf6e1d765a193d9cbe146ceeb79ac1cb485ed5f5b37913a8cf5857eff00a946cd507258c10454d484e64ba59d3e7570658001c5f854b6b3ebb57be90e7a7072b5d2051d300b10b74314b7e25ace9998ca66eb2c7fbc10ef130dd67028293cc27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e489000403030905000404000000040009038096980000000000040005024f0a010008090c0007010a0b06020316494710642cb0c646080000000000000000000000ff06013001afd71da9456a977233960b08eba77d2e3690b8c7259637c8fb8f82cf58a1020905020302").to_vec(); + let expected_serialized_tx = hex_literal::hex!("013f38d2f1a1669aabbc375de98a7030310f36e4482732ad92adc2fff31c1e63cf5713c92dd41f56b11fe2edf0679f3e095d88a5bb96055c1c84d5bfe0779e3606800100080df79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb17eb2b10d3377bda2bc7bea65bec6b8372f4fc3463ec2cd6f9fde4b2c633d19242ff6863b52c3f8faf95739e6541bda5d0ac593f00c6c07d9ab37096bf26d910ae85f2fb6289c70bfe37df150dddb17dd84f403fd0b1aa1bfee85795159de21fe91372b3d301c202a633da0a92365a736e462131aecfad1fac47322cf8863ada00000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea940000006ddf6e1d765a193d9cbe146ceeb79ac1cb485ed5f5b37913a8cf5857eff00a90fb9ba52b1f09445f1e3a7508d59f0797923acf744fbe2da303fb06da859ee8746cd507258c10454d484e64ba59d3e7570658001c5f854b6b3ebb57be90e7a7072b5d2051d300b10b74314b7e25ace9998ca66eb2c7fbc10ef130dd67028293ca1e031c8bc9bec3b610cf7b36eb3bf3aa40237c9e5be2c7893878578439eb00bc27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e489000405030107000404000000060009038096980000000000060005024f0a01000b090c000a02040908030516494710642cb0c646080000000000000000000000ff0600").to_vec(); test_constructed_transaction(transaction, expected_serialized_tx); } @@ -663,12 +674,11 @@ pub mod test { agg_key(), durable_nonce(), compute_price(), - vec![chainflip_alt()], ) .unwrap(); // Serialized tx built in `create_batch_fetch` test - let expected_serialized_tx = hex_literal::hex!("015eab79254444f6f235494a180b8c0c11fe4ee73c85656eda36b4dccf717ace5d0613540e9d3febb4b439f86b45bfdb26ba4810e17d224efd8ad13c2f34f09f0a800100070ef79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb1ad0968d57ee79348476716f9b2cd44ec4284b8f52c36648d560949e41589a5540de1c0451cccb6edd1fda9b4a48c282b279350b55a7a9716800cc0132b6f0b042ff6863b52c3f8faf95739e6541bda5d0ac593f00c6c07d9ab37096bf26d910a140fd3d05766f0087d57bf99df05731e894392ffcc8e8d7e960ba73c09824aaae85f2fb6289c70bfe37df150dddb17dd84f403fd0b1aa1bfee85795159de21fb4baefcd4965beb1c71311a2ffe76419d4b8f8d35fbc4cf514b1bd02da2df2e300000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea940000006ddf6e1d765a193d9cbe146ceeb79ac1cb485ed5f5b37913a8cf5857eff00a946cd507258c10454d484e64ba59d3e7570658001c5f854b6b3ebb57be90e7a7072b5d2051d300b10b74314b7e25ace9998ca66eb2c7fbc10ef130dd67028293c8d9871ed5fb2ee05765af23b7cabcc0d6b08ed370bb9f616a0d4dea40a25f870c27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e489000607030e0900040400000008000903809698000000000008000502e7bb02000c0911000b030f100a050716494710642cb0c646080000000000000000000000ff060c0911000d010f100a020716494710642cb0c646080000000100000000000000ff060c051100040607158e24658f6c59298c080000000200000000000000ff013001afd71da9456a977233960b08eba77d2e3690b8c7259637c8fb8f82cf58a1020905020302").to_vec(); + let expected_serialized_tx = hex_literal::hex!("01815a9e25f301f6877feb533c18b7ecaec40b2164ccffada07a0a228a7d67beb339b77a0146c5c44f18030ddadcce4ab6c18e9033d1b89ac7dcd0814d9ba7d6078001000912f79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb17eb2b10d3377bda2bc7bea65bec6b8372f4fc3463ec2cd6f9fde4b2c633d1921ad0968d57ee79348476716f9b2cd44ec4284b8f52c36648d560949e41589a5540de1c0451cccb6edd1fda9b4a48c282b279350b55a7a9716800cc0132b6f0b042ff6863b52c3f8faf95739e6541bda5d0ac593f00c6c07d9ab37096bf26d910a140fd3d05766f0087d57bf99df05731e894392ffcc8e8d7e960ba73c09824aaae85f2fb6289c70bfe37df150dddb17dd84f403fd0b1aa1bfee85795159de21fb4baefcd4965beb1c71311a2ffe76419d4b8f8d35fbc4cf514b1bd02da2df2e3e91372b3d301c202a633da0a92365a736e462131aecfad1fac47322cf8863ada00000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea940000006ddf6e1d765a193d9cbe146ceeb79ac1cb485ed5f5b37913a8cf5857eff00a90fb9ba52b1f09445f1e3a7508d59f0797923acf744fbe2da303fb06da859ee8746cd507258c10454d484e64ba59d3e7570658001c5f854b6b3ebb57be90e7a7072b5d2051d300b10b74314b7e25ace9998ca66eb2c7fbc10ef130dd67028293c8d9871ed5fb2ee05765af23b7cabcc0d6b08ed370bb9f616a0d4dea40a25f870a1e031c8bc9bec3b610cf7b36eb3bf3aa40237c9e5be2c7893878578439eb00bc27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e48900060903010b0004040000000a00090380969800000000000a000502e7bb02000f0911000e04080d0c060916494710642cb0c646080000000000000000000000ff060f0911001002080d0c030916494710642cb0c646080000000100000000000000ff060f051100050709158e24658f6c59298c080000000200000000000000ff00").to_vec(); test_constructed_transaction(transaction, expected_serialized_tx); } @@ -734,6 +744,7 @@ pub mod test { env.vault_program, env.vault_program_data_account, agg_key(), + env.alt_manager_program, durable_nonce(), compute_price(), vec![chainflip_alt()], @@ -741,7 +752,7 @@ pub mod test { .unwrap(); // Serialized tx built in `rotate_agg_key` test - let expected_serialized_tx = hex_literal::hex!("01ab37f60681ba0afe0aeda3c39f5021f49332695e63243af28769b59de314f4b62445271f2155e4d49c83153b63a9c64ddeb2feda66acf2ad6058f411c95cf7038001000406f79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb6744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be54399004400000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea940000072b5d2051d300b10b74314b7e25ace9998ca66eb2c7fbc10ef130dd67028293cc27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e489000e0203060400040400000003000903809698000000000003000502e02e0000050409000102094e518fabdda5d68b000202060024070000006744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be54399004402020f0024070000006744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be54399004402020d0024070000006744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be54399004402020e0024070000006744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be54399004402020b0024070000006744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be54399004402020a0024070000006744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be5439900440202070024070000006744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be5439900440202100024070000006744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be54399004402020c0024070000006744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be5439900440202080024070000006744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be543990044013001afd71da9456a977233960b08eba77d2e3690b8c7259637c8fb8f82cf58a10b090f12020e0d110b0c0a1000").to_vec(); + let expected_serialized_tx = hex_literal::hex!("01906e22a60124f3bef2c1d1a3a597540cd92dd8ffb7c2b76490b172e3280172907693a54c12d3ffd760cd47e009794304bc24cca25fbb67ad35e098778f0796088001000507f79d5e026f12edc6443a534b2cdd5072233989b415d7596573e743f3e5b386fb6744e9d9790761c45a800a074687b5ff47b449a90c722a3852543be54399004400000000000000000000000000000000000000000000000000000000000000000306466fe5211732ffecadba72c39be7bc8ce5bbc5f7126b2c439b3a4000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea94000002ec25ce83748eb28232064bd8f41d4f0e7e0cc1186b8704eabdb2461ef50e12c72b5d2051d300b10b74314b7e25ace9998ca66eb2c7fbc10ef130dd67028293cc27e9074fac5e8d36cf04f94a0606fdd8ddbb420e99a489c7915ce5699e48900050203070400040400000003000903809698000000000003000502ac070100050e0a00010207100e0f0c0b08110d090862f54977a55a39cb06040a000102094e518fabdda5d68b00013001afd71da9456a977233960b08eba77d2e3690b8c7259637c8fb8f82cf58a10b090f12020e0d110b0c0a1000").to_vec(); test_constructed_transaction(transaction, expected_serialized_tx); } @@ -901,7 +912,6 @@ pub mod test { agg_key(), durable_nonce(), compute_price(), - vec![chainflip_alt()], )); assert_err!( @@ -911,9 +921,8 @@ pub mod test { agg_key(), durable_nonce(), compute_price(), - vec![chainflip_alt()], ), - SolanaTransactionBuildingError::FinalTransactionExceededMaxLength(1260) + SolanaTransactionBuildingError::FinalTransactionExceededMaxLength(1288) ); } } diff --git a/state-chain/node/src/chain_spec.rs b/state-chain/node/src/chain_spec.rs index 8be4a6a87c4..1b1d3d4434b 100644 --- a/state-chain/node/src/chain_spec.rs +++ b/state-chain/node/src/chain_spec.rs @@ -4,7 +4,10 @@ use cf_chains::{ btc::{BitcoinFeeInfo, BitcoinTrackedData, BITCOIN_DUST_LIMIT}, dot::{PolkadotAccountId, PolkadotHash, PolkadotTrackedData, RuntimeVersion}, eth::EthereumTrackedData, - sol::{api::DurableNonceAndAccount, SolAddress, SolApiEnvironment, SolHash, SolTrackedData}, + sol::{ + api::DurableNonceAndAccount, AddressLookupTableAccount, SolAddress, SolApiEnvironment, + SolHash, SolTrackedData, + }, Arbitrum, Bitcoin, ChainState, Ethereum, Polkadot, }; use cf_primitives::{ @@ -108,11 +111,13 @@ pub struct StateChainEnvironment { sol_usdc_token_mint_pubkey: SolAddress, sol_token_vault_pda_account: SolAddress, sol_usdc_token_vault_ata: SolAddress, - sol_durable_nonces_and_accounts: [DurableNonceAndAccount; 10], /* we inject 10 nonce - * accounts - * at genesis */ + // We injected 10 nonce accounts at genesis and 40 more on an upgrade + sol_durable_nonces_and_accounts: [DurableNonceAndAccount; 50], sol_swap_endpoint_program: SolAddress, sol_swap_endpoint_program_data_account: SolAddress, + sol_alt_manager_program: SolAddress, + // Initialized with 65 accounts (50 of them nonces) + sol_address_lookup_table_account: (SolAddress, [SolAddress; 65]), } /// Get the values from the State Chain's environment variables. Else set them via the defaults @@ -164,6 +169,7 @@ pub fn get_environment_or_defaults(defaults: StateChainEnvironment) -> StateChai SOL_SWAP_ENDPOINT_PROGRAM_DATA_ACCOUNT, sol_swap_endpoint_program_data_account ); + from_env_var!(FromStr::from_str, SOL_ALT_MANAGER_PROGRAM, sol_alt_manager_program); let dot_genesis_hash = match env::var("DOT_GENESIS_HASH") { Ok(s) => hex_decode::<32>(&s).unwrap().into(), @@ -193,6 +199,11 @@ pub fn get_environment_or_defaults(defaults: StateChainEnvironment) -> StateChai Err(_) => defaults.sol_durable_nonces_and_accounts, }; + let sol_address_lookup_table_account = match env::var("SOL_ADDRESS_LOOKUP_TABLE_ACCOUNT") { + Ok(_) => unimplemented!("Solana address lookup table account should not be supplied via environment variables since its a complex type"), + Err(_) => defaults.sol_address_lookup_table_account, + }; + StateChainEnvironment { flip_token_address, eth_usdc_address, @@ -226,6 +237,8 @@ pub fn get_environment_or_defaults(defaults: StateChainEnvironment) -> StateChai sol_durable_nonces_and_accounts, sol_swap_endpoint_program, sol_swap_endpoint_program_data_account, + sol_alt_manager_program, + sol_address_lookup_table_account, } } @@ -295,6 +308,8 @@ pub fn inner_cf_development_config( sol_durable_nonces_and_accounts, sol_swap_endpoint_program, sol_swap_endpoint_program_data_account, + sol_alt_manager_program, + sol_address_lookup_table_account, } = get_environment_or_defaults(testnet::ENV); Ok(ChainSpec::builder(wasm_binary, Default::default()) .with_name("CF Develop") @@ -334,6 +349,15 @@ pub fn inner_cf_development_config( usdc_token_vault_ata: sol_usdc_token_vault_ata, swap_endpoint_program: sol_swap_endpoint_program, swap_endpoint_program_data_account: sol_swap_endpoint_program_data_account, + alt_manager_program: sol_alt_manager_program, + address_lookup_table_account: AddressLookupTableAccount { + key: sol_address_lookup_table_account.0.into(), + addresses: sol_address_lookup_table_account + .1 + .into_iter() + .map(|addr| addr.into()) + .collect(), + }, }, sol_durable_nonces_and_accounts: sol_durable_nonces_and_accounts.to_vec(), network_environment: NetworkEnvironment::Development, @@ -425,6 +449,8 @@ macro_rules! network_spec { sol_durable_nonces_and_accounts, sol_swap_endpoint_program, sol_swap_endpoint_program_data_account, + sol_alt_manager_program, + sol_address_lookup_table_account, } = env_override.unwrap_or(ENV); let protocol_id = format!( "{}-{}", @@ -497,6 +523,15 @@ macro_rules! network_spec { swap_endpoint_program: sol_swap_endpoint_program, swap_endpoint_program_data_account: sol_swap_endpoint_program_data_account, + alt_manager_program: sol_alt_manager_program, + address_lookup_table_account: AddressLookupTableAccount { + key: sol_address_lookup_table_account.0.into(), + addresses: sol_address_lookup_table_account + .1 + .into_iter() + .map(|addr| addr.into()) + .collect(), + }, }, network_environment: NETWORK_ENVIRONMENT, ..Default::default() diff --git a/state-chain/node/src/chain_spec/berghain.rs b/state-chain/node/src/chain_spec/berghain.rs index 1c46213256b..ef1a8807713 100644 --- a/state-chain/node/src/chain_spec/berghain.rs +++ b/state-chain/node/src/chain_spec/berghain.rs @@ -105,6 +105,168 @@ pub const ENV: StateChainEnvironment = StateChainEnvironment { const_address("14AwUr3FG75E66aaLy7jCbVGaxGCGLdqtpVyBNAFwKac"), const_hash("AEzmj9wq8jp7wF46Lrr3Jc2K7xRP58V5Y3cYRVEqtE5J"), ), + // TODO: Update with the real nonces even if we'll actually insert + // then via migration + ( + const_address("11111111111111111111111111111111"), + const_hash("3pMDqkhnibuv2ARQzjq4K1jn58EvCzC6uF28kiMCUoW2"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("5rJzAL24yzaqPNE14xFuhdLtLLmUDF3JAfVbZHoBWAUB"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("6ChBdxfZ4ZPLZ7zhVavtjXZrNojg1MdT3Du4VnSnhQ6u"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("6FtBFnt4P25xUnATE6c6XeicKn1ZB6Q5MiGZq4xqqD2D"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("8UZPPjjKVVjb7TRDx3ZVBnMqrdqYpp6HP2vQVUrxEhn1"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("FtLgEitvpnSrcj4adHKcvbYG9SF1C7NLZCk2priDTA6e"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("2xYo9Gv76GGgZs2ikCi8gSgkriEugv5wFhERowyvDx3H"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("79NHKfzzZZ4Fmm5mK7D6E16KvwJKWWZpuqyHHiD1xdQ3"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("CTyzyX8K9Wwo5zGEZmWxtGpYYwHpGv6YTsFRpi6syLJ4"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("AEzmj9wq8jp7wF46Lrr3Jc2K7xRP58V5Y3cYRVEqtE5J"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("3pMDqkhnibuv2ARQzjq4K1jn58EvCzC6uF28kiMCUoW2"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("5rJzAL24yzaqPNE14xFuhdLtLLmUDF3JAfVbZHoBWAUB"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("6ChBdxfZ4ZPLZ7zhVavtjXZrNojg1MdT3Du4VnSnhQ6u"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("6FtBFnt4P25xUnATE6c6XeicKn1ZB6Q5MiGZq4xqqD2D"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("8UZPPjjKVVjb7TRDx3ZVBnMqrdqYpp6HP2vQVUrxEhn1"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("FtLgEitvpnSrcj4adHKcvbYG9SF1C7NLZCk2priDTA6e"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("2xYo9Gv76GGgZs2ikCi8gSgkriEugv5wFhERowyvDx3H"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("79NHKfzzZZ4Fmm5mK7D6E16KvwJKWWZpuqyHHiD1xdQ3"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("CTyzyX8K9Wwo5zGEZmWxtGpYYwHpGv6YTsFRpi6syLJ4"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("AEzmj9wq8jp7wF46Lrr3Jc2K7xRP58V5Y3cYRVEqtE5J"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("3pMDqkhnibuv2ARQzjq4K1jn58EvCzC6uF28kiMCUoW2"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("5rJzAL24yzaqPNE14xFuhdLtLLmUDF3JAfVbZHoBWAUB"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("6ChBdxfZ4ZPLZ7zhVavtjXZrNojg1MdT3Du4VnSnhQ6u"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("6FtBFnt4P25xUnATE6c6XeicKn1ZB6Q5MiGZq4xqqD2D"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("8UZPPjjKVVjb7TRDx3ZVBnMqrdqYpp6HP2vQVUrxEhn1"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("FtLgEitvpnSrcj4adHKcvbYG9SF1C7NLZCk2priDTA6e"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("2xYo9Gv76GGgZs2ikCi8gSgkriEugv5wFhERowyvDx3H"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("79NHKfzzZZ4Fmm5mK7D6E16KvwJKWWZpuqyHHiD1xdQ3"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("CTyzyX8K9Wwo5zGEZmWxtGpYYwHpGv6YTsFRpi6syLJ4"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("AEzmj9wq8jp7wF46Lrr3Jc2K7xRP58V5Y3cYRVEqtE5J"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("3pMDqkhnibuv2ARQzjq4K1jn58EvCzC6uF28kiMCUoW2"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("5rJzAL24yzaqPNE14xFuhdLtLLmUDF3JAfVbZHoBWAUB"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("6ChBdxfZ4ZPLZ7zhVavtjXZrNojg1MdT3Du4VnSnhQ6u"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("6FtBFnt4P25xUnATE6c6XeicKn1ZB6Q5MiGZq4xqqD2D"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("8UZPPjjKVVjb7TRDx3ZVBnMqrdqYpp6HP2vQVUrxEhn1"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("FtLgEitvpnSrcj4adHKcvbYG9SF1C7NLZCk2priDTA6e"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("2xYo9Gv76GGgZs2ikCi8gSgkriEugv5wFhERowyvDx3H"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("79NHKfzzZZ4Fmm5mK7D6E16KvwJKWWZpuqyHHiD1xdQ3"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("CTyzyX8K9Wwo5zGEZmWxtGpYYwHpGv6YTsFRpi6syLJ4"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("AEzmj9wq8jp7wF46Lrr3Jc2K7xRP58V5Y3cYRVEqtE5J"), + ), ], sol_swap_endpoint_program: SolAddress(bs58_array( "J88B7gmadHzTNGiy54c9Ms8BsEXNdB2fntFyhKpk3qoT", @@ -112,6 +274,78 @@ pub const ENV: StateChainEnvironment = StateChainEnvironment { sol_swap_endpoint_program_data_account: SolAddress(bs58_array( "FmAcjWaRFUxGWBfGT7G3CzcFeJFsewQ4KPJVG4f6fcob", )), + // TODO: To update with the right values + sol_alt_manager_program: SolAddress(bs58_array("11111111111111111111111111111111")), + sol_address_lookup_table_account: ( + SolAddress(bs58_array("11111111111111111111111111111111")), + [ + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + ], + ), }; pub const EPOCH_DURATION_BLOCKS: BlockNumber = 24 * HOURS; diff --git a/state-chain/node/src/chain_spec/perseverance.rs b/state-chain/node/src/chain_spec/perseverance.rs index d4d71cab1a5..dfea9c794fa 100644 --- a/state-chain/node/src/chain_spec/perseverance.rs +++ b/state-chain/node/src/chain_spec/perseverance.rs @@ -105,6 +105,168 @@ pub const ENV: StateChainEnvironment = StateChainEnvironment { const_address("6WcamLU38f1asFanFXYugVJuHN4TXHZicmJgPz9Xr6U7"), const_hash("FS1PdTqsDSEa9xUrLAS5k471MQsT28H2FW5CpUHiTmGF"), ), + // TODO: Update with the real nonces even if we'll actually insert + // then via migration + ( + const_address("11111111111111111111111111111111"), + const_hash("4DEDrSVk4FRKFQkU1p9Zywi5MK64AGxC16RQZvhyFngq"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("5s1V7bXByHPquC1AYD94w4f8SgEhDjEnGeBtiPsuzXYU"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("7Y1PvrW65rZp3RqmJksix3XxQ9MrFdQ62NNbhdB97qwc"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("F1fe16vREumonQurbFAfmbKytfEE9khjy9UPjjgbGnG9"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("D6osW2CyHmpLqg8ymDAeNEjZZETqHGWdQBekh3cVjAUQ"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("7qDGqASPR3VannmDosTXUVMd5ZWbqDnawCA3auEHsq6r"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("4TFDiBqjU5istaaAovdgKBNDKJFdZ318W6XuC9MZiDBC"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("7ua7UjY1Csouw7K1nMDyWhL7Lx5PE9ernETcKciWALFH"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("742EN3zJUt6Xcrs1KAH4jfyLLVp8BYV2bSmjEpsFpMFo"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("FS1PdTqsDSEa9xUrLAS5k471MQsT28H2FW5CpUHiTmGF"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("4DEDrSVk4FRKFQkU1p9Zywi5MK64AGxC16RQZvhyFngq"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("5s1V7bXByHPquC1AYD94w4f8SgEhDjEnGeBtiPsuzXYU"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("7Y1PvrW65rZp3RqmJksix3XxQ9MrFdQ62NNbhdB97qwc"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("F1fe16vREumonQurbFAfmbKytfEE9khjy9UPjjgbGnG9"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("D6osW2CyHmpLqg8ymDAeNEjZZETqHGWdQBekh3cVjAUQ"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("7qDGqASPR3VannmDosTXUVMd5ZWbqDnawCA3auEHsq6r"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("4TFDiBqjU5istaaAovdgKBNDKJFdZ318W6XuC9MZiDBC"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("7ua7UjY1Csouw7K1nMDyWhL7Lx5PE9ernETcKciWALFH"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("742EN3zJUt6Xcrs1KAH4jfyLLVp8BYV2bSmjEpsFpMFo"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("FS1PdTqsDSEa9xUrLAS5k471MQsT28H2FW5CpUHiTmGF"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("4DEDrSVk4FRKFQkU1p9Zywi5MK64AGxC16RQZvhyFngq"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("5s1V7bXByHPquC1AYD94w4f8SgEhDjEnGeBtiPsuzXYU"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("7Y1PvrW65rZp3RqmJksix3XxQ9MrFdQ62NNbhdB97qwc"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("F1fe16vREumonQurbFAfmbKytfEE9khjy9UPjjgbGnG9"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("D6osW2CyHmpLqg8ymDAeNEjZZETqHGWdQBekh3cVjAUQ"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("7qDGqASPR3VannmDosTXUVMd5ZWbqDnawCA3auEHsq6r"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("4TFDiBqjU5istaaAovdgKBNDKJFdZ318W6XuC9MZiDBC"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("7ua7UjY1Csouw7K1nMDyWhL7Lx5PE9ernETcKciWALFH"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("742EN3zJUt6Xcrs1KAH4jfyLLVp8BYV2bSmjEpsFpMFo"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("FS1PdTqsDSEa9xUrLAS5k471MQsT28H2FW5CpUHiTmGF"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("4DEDrSVk4FRKFQkU1p9Zywi5MK64AGxC16RQZvhyFngq"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("5s1V7bXByHPquC1AYD94w4f8SgEhDjEnGeBtiPsuzXYU"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("7Y1PvrW65rZp3RqmJksix3XxQ9MrFdQ62NNbhdB97qwc"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("F1fe16vREumonQurbFAfmbKytfEE9khjy9UPjjgbGnG9"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("D6osW2CyHmpLqg8ymDAeNEjZZETqHGWdQBekh3cVjAUQ"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("7qDGqASPR3VannmDosTXUVMd5ZWbqDnawCA3auEHsq6r"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("4TFDiBqjU5istaaAovdgKBNDKJFdZ318W6XuC9MZiDBC"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("7ua7UjY1Csouw7K1nMDyWhL7Lx5PE9ernETcKciWALFH"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("742EN3zJUt6Xcrs1KAH4jfyLLVp8BYV2bSmjEpsFpMFo"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("FS1PdTqsDSEa9xUrLAS5k471MQsT28H2FW5CpUHiTmGF"), + ), ], sol_swap_endpoint_program: SolAddress(bs58_array( "DeL6iGV5RWrWh7cPoEa7tRHM8XURAaB4vPjfX5qVyuWE", @@ -112,6 +274,78 @@ pub const ENV: StateChainEnvironment = StateChainEnvironment { sol_swap_endpoint_program_data_account: SolAddress(bs58_array( "12MYcNumSQCn81yKRfrk5P5ThM5ivkLiZda979hhKJDR", )), + // TODO: To update with the right values + sol_alt_manager_program: SolAddress(bs58_array("11111111111111111111111111111111")), + sol_address_lookup_table_account: ( + SolAddress(bs58_array("11111111111111111111111111111111")), + [ + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + ], + ), }; pub const EPOCH_DURATION_BLOCKS: BlockNumber = 24 * HOURS; diff --git a/state-chain/node/src/chain_spec/sisyphos.rs b/state-chain/node/src/chain_spec/sisyphos.rs index 61d3aece7d0..1382559fea8 100644 --- a/state-chain/node/src/chain_spec/sisyphos.rs +++ b/state-chain/node/src/chain_spec/sisyphos.rs @@ -106,6 +106,168 @@ pub const ENV: StateChainEnvironment = StateChainEnvironment { const_address("DcEmNXySnth2FNhsHmt64oB15pjtakKhfG3nez7qB52w"), const_hash("3iiniRfNTFmBn6Y9ZhovefUDaGaJ7buB2vYemnbFoHN3"), ), + // TODO: Update with the real nonces even if we'll actually insert + // then via migration + ( + const_address("11111111111111111111111111111111"), + const_hash("9QVwTXtwGTbq4U3KPN9THdnxQ38bVFu6P15cwhURJqNC"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("DkYbyJ5P576ekMQYUuWizejxoWHUUZN3nLrQzVFe2mjd"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("FWUwBbVbRFtaWhpptZ9vsUtiZtc8c6MKKsAnQfRn6uRV"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("3niQmTX5qKD69gdNRLwxRm1o4d65Vkw1QxQH27GLiDCD"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("5ngBYFzxZ2sTFetLY92LiQVzjXZTYbqTjc58ShVZC19d"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("9C1RDEeKLFT2txok1zvqZ3Fu5K1dxCqDCJc3KPfuBqTn"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("B8PDaqM9TUjyuKwT8K2C4tiF2p5jTiBX7r1B9gogVen6"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("Dne5GaxYgG2KzgpC7aD7XX3pFQp3qvj3vfCFy3kfjaJw"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("FKU1qKCydv3TjE1ZDimvevA4khGakkJFRmyVorZvYR7D"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("3iiniRfNTFmBn6Y9ZhovefUDaGaJ7buB2vYemnbFoHN3"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("9QVwTXtwGTbq4U3KPN9THdnxQ38bVFu6P15cwhURJqNC"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("DkYbyJ5P576ekMQYUuWizejxoWHUUZN3nLrQzVFe2mjd"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("FWUwBbVbRFtaWhpptZ9vsUtiZtc8c6MKKsAnQfRn6uRV"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("3niQmTX5qKD69gdNRLwxRm1o4d65Vkw1QxQH27GLiDCD"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("5ngBYFzxZ2sTFetLY92LiQVzjXZTYbqTjc58ShVZC19d"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("9C1RDEeKLFT2txok1zvqZ3Fu5K1dxCqDCJc3KPfuBqTn"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("B8PDaqM9TUjyuKwT8K2C4tiF2p5jTiBX7r1B9gogVen6"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("Dne5GaxYgG2KzgpC7aD7XX3pFQp3qvj3vfCFy3kfjaJw"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("FKU1qKCydv3TjE1ZDimvevA4khGakkJFRmyVorZvYR7D"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("3iiniRfNTFmBn6Y9ZhovefUDaGaJ7buB2vYemnbFoHN3"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("9QVwTXtwGTbq4U3KPN9THdnxQ38bVFu6P15cwhURJqNC"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("DkYbyJ5P576ekMQYUuWizejxoWHUUZN3nLrQzVFe2mjd"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("FWUwBbVbRFtaWhpptZ9vsUtiZtc8c6MKKsAnQfRn6uRV"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("3niQmTX5qKD69gdNRLwxRm1o4d65Vkw1QxQH27GLiDCD"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("5ngBYFzxZ2sTFetLY92LiQVzjXZTYbqTjc58ShVZC19d"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("9C1RDEeKLFT2txok1zvqZ3Fu5K1dxCqDCJc3KPfuBqTn"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("B8PDaqM9TUjyuKwT8K2C4tiF2p5jTiBX7r1B9gogVen6"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("Dne5GaxYgG2KzgpC7aD7XX3pFQp3qvj3vfCFy3kfjaJw"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("FKU1qKCydv3TjE1ZDimvevA4khGakkJFRmyVorZvYR7D"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("3iiniRfNTFmBn6Y9ZhovefUDaGaJ7buB2vYemnbFoHN3"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("9QVwTXtwGTbq4U3KPN9THdnxQ38bVFu6P15cwhURJqNC"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("DkYbyJ5P576ekMQYUuWizejxoWHUUZN3nLrQzVFe2mjd"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("FWUwBbVbRFtaWhpptZ9vsUtiZtc8c6MKKsAnQfRn6uRV"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("3niQmTX5qKD69gdNRLwxRm1o4d65Vkw1QxQH27GLiDCD"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("5ngBYFzxZ2sTFetLY92LiQVzjXZTYbqTjc58ShVZC19d"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("9C1RDEeKLFT2txok1zvqZ3Fu5K1dxCqDCJc3KPfuBqTn"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("B8PDaqM9TUjyuKwT8K2C4tiF2p5jTiBX7r1B9gogVen6"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("Dne5GaxYgG2KzgpC7aD7XX3pFQp3qvj3vfCFy3kfjaJw"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("FKU1qKCydv3TjE1ZDimvevA4khGakkJFRmyVorZvYR7D"), + ), + ( + const_address("11111111111111111111111111111111"), + const_hash("3iiniRfNTFmBn6Y9ZhovefUDaGaJ7buB2vYemnbFoHN3"), + ), ], sol_swap_endpoint_program: SolAddress(bs58_array( "FtK6TR2ZqhChxXeDFoVzM9gYDPA18tGrKoBb3hX7nPwt", @@ -113,6 +275,78 @@ pub const ENV: StateChainEnvironment = StateChainEnvironment { sol_swap_endpoint_program_data_account: SolAddress(bs58_array( "EXeku7Q9AiAXBdH7cUHw2ue3okhrofvDZR7EBE1BVQZu", )), + // TODO: To update with the right values + sol_alt_manager_program: SolAddress(bs58_array("11111111111111111111111111111111")), + sol_address_lookup_table_account: ( + SolAddress(bs58_array("11111111111111111111111111111111")), + [ + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + const_address("11111111111111111111111111111111"), + ], + ), }; pub const BASHFUL_ACCOUNT_ID: &str = "cFLbasoV5juCGacy9LvvwSgkupFiFmwt8RmAuA3xcaY5YmkBe"; diff --git a/state-chain/node/src/chain_spec/testnet.rs b/state-chain/node/src/chain_spec/testnet.rs index a24e8953b3b..161c7f6c036 100644 --- a/state-chain/node/src/chain_spec/testnet.rs +++ b/state-chain/node/src/chain_spec/testnet.rs @@ -63,43 +63,203 @@ pub const ENV: StateChainEnvironment = StateChainEnvironment { sol_durable_nonces_and_accounts: [ ( const_address("2cNMwUCF51djw2xAiiU54wz1WrU8uG4Q8Kp8nfEuwghw"), - const_hash("2qVz58R5aPmF5Q61VaKXnpWQtngdh4Jgbeko32fEcECu"), + const_hash("A6PxZEnTwTrLQG8pVBwytG8YLRqPUeEdsXHJP2UQ5RSF"), ), ( const_address("HVG21SovGzMBJDB9AQNuWb6XYq4dDZ6yUwCbRUuFnYDo"), - const_hash("6fxCujPRyyTPzcZWpkDRhvDC4NXf4GB5tCTbQRDnz2iw"), + const_hash("EtK5bRt2pDX3CJyDzsdDtzjRf7v15NPR8JVpMikh6sNh"), ), ( const_address("HDYArziNzyuNMrK89igisLrXFe78ti8cvkcxfx4qdU2p"), - const_hash("2VUnNMpXzohc4284EyuhT7PEuUdqy9E7AfxAP8nrm9cv"), + const_hash("3PkYapCizvyiFPBEg2pkiBAxnVYfpR2VWs7H6FQcD7rc"), ), ( const_address("HLPsNyxBqfq2tLE31v6RiViLp2dTXtJRgHgsWgNDRPs2"), - const_hash("7bNgRtjaTgCiXwEagFv2cndco5aTzW1dEXGTZp9EDHgE"), + const_hash("HqPcXp31mYG1G4DP3c9F262pjXKeMzb4hbAwqsdLKrmM"), ), ( const_address("GKMP63TqzbueWTrFYjRwMNkAyTHpQ54notRbAbMDmePM"), - const_hash("DSSpXCVb6LU4a91TAkqyUHGXB1bspfLUxKzb5VhGUvyf"), + const_hash("2cMqnuCCnGWm56LFPe9mZuGHdhzpFpwwv2io9Q99EMjE"), ), ( const_address("EpmHm2aSPsB5ZZcDjqDhQ86h1BV32GFCbGSMuC58Y2tn"), - const_hash("DEwmxJ6xUTXVMnZjvSsRBb9knA1JG3ETT1CQXz5q3yzY"), + const_hash("7ZZpMge82HiNhhyv1LDzfwq7Ak9sF943TmLkQNuR7ZZh"), ), ( const_address("9yBZNMrLrtspj4M7bEf2X6tqbqHxD2vNETw8qSdvJHMa"), - const_hash("ERJZ2GKvYB2f7MroWy8qEA3xdvMNHg2DUqjBJ6KVzXYE"), + const_hash("Ee2tKBQguV5Rfsa738jBTRCU7vczXkZYnddiqwSRz2Dz"), ), ( const_address("J9dT7asYJFGS68NdgDCYjzU2Wi8uBoBusSHN1Z6JLWna"), - const_hash("Ecqa1ZZwjS6Lz74k2kXvVKcrWXJNiVGzLqfe1ftBcCYj"), + const_hash("BhW9y8kkdBFiWnwzrYihhjhreovZd3TfZE7uaQnKz8ea"), ), ( const_address("GUMpVpQFNYJvSbyTtUarZVL7UDUgErKzDTSVJhekUX55"), - const_hash("HuksgAnauQ9wTextjMhHVB6oVSCT3GKGb6j1DniSS8eL"), + const_hash("5CGa6yRJsVStdMR4PkUNGW5F13UeHBuqyurkmNByrgxj"), ), ( const_address("AUiHYbzH7qLZSkb3u7nAqtvqC7e41sEzgWjBEvXrpfGv"), - const_hash("2TR5QRLhPzPzB6Gvs4iZsq6Dp8v5w2LamrE9BFrsNkzW"), + const_hash("DCrChXBpKFjq61yYdULyYEnfqtcYkf1ACQqDNkgfwhF9"), + ), + ( + const_address("BN2vyodNYQQTrx3gtaDAL2UGGVtZwFeF5M8krE5aYYES"), + const_hash("4fjG6oYKadvnsbzAzomF5k2Zdc4DuuUyT71nueAeykMW"), + ), + ( + const_address("Gwq9TAQCjbJtdnmtxQa3PbHFfbr6YTUBMDjEP9x2uXnH"), + const_hash("GK29hbKjKWNwdF4KT11MzkrmQPsYPwE41qZMnLVcQPaS"), + ), + ( + const_address("3pGbKatko2ckoLEy139McfKiirNgy9brYxieNqFGdN1W"), + const_hash("5cinXdpw2KAGzmiXXegWJRdDDboXbDHaQaT3WFsH3txb"), + ), + ( + const_address("9Mcd8BTievK2yTvyiqG9Ft4HfDFf6mjGFBWMnCSRQP8S"), + const_hash("DRoAyPDtsg9CCMBSN6egFsWsP2zsQBAxCzN6fAdtQxJU"), + ), + ( + const_address("AEZG74RoqM6sxf79eTizq5ShB4JTuCkMVwUgtnC8H94z"), + const_hash("G8ZKHMsWFSoKJAtVbm1xgv8VjT5F6YBeiZbbzpVHuuyM"), + ), + ( + const_address("APLkgyCWi8DFAMF4KikjTu8YnUG1r7sMjVEfDiaBRZnS"), + const_hash("BMUqNXhMoB6VWsR7jHgRcv7yio8L5vjHdGby7gEJ4Pd2"), + ), + ( + const_address("4ShNXTTHvpVt6bQdZTRdyW6yWXDzrPupdMuxajbEoGE4"), + const_hash("52yamKJdMiQ5tEUyhkngvjR3XFXp7dmJzYsVsLbPs9JX"), + ), + ( + const_address("FgZp6NJYWw15U51ynfXCfU9vq3eVgDDAHMSfJ8fFBZZ8"), + const_hash("AX3qKNMBRKZimeCsBEhtp7heeduKekj85a4UpdN34HFe"), + ), + ( + const_address("ENQ9Mmg87KFLX8ncXRPDBSd7jhKCtPBi8QzAh4rkREgP"), + const_hash("GGFme2ydkkbDzq7LhVDMX5SsFf2yGLf7uKNSLLhvrGMd"), + ), + ( + const_address("Hhay1UwkzkFUgrGUYuiCvUwv7kErNzAcZnVRQ2fetT7K"), + const_hash("HMN14axscHALAuknuwSpVkEmAJkZWeJoNAjJuXUjRQbN"), + ), + ( + const_address("2fUVR42opcHgGLrY1eguDXLYfQPHQe9ReJNmRorVt9v8"), + const_hash("RWoH6shzxCS9dmW2mg37cujXxARBRBunbHEtZwUz1Gj"), + ), + ( + const_address("HfKr1wJASkW5UHs8yNWAqMeaYJdp8K2mdYwkbdVRdVrm"), + const_hash("2dhBBWYQE2Fvm4ShUQjno8ydJb5H6rUmBZ1e6TJHDupL"), + ), + ( + const_address("DrpYkMpJWkpNqX9yYgQfc3uZrCVYobJ3RbTABcSkHJkM"), + const_hash("6VCThFyLtFCKk35wihyrRUa6dubBU7skhJdRRDBfH4Md"), + ), + ( + const_address("HCXc3o2go1Y2KhfnykLYXEvofLifXTb7GT13w4GsFmGw"), + const_hash("EggsCqUiKJVxmN7a9s7RScXUAJRjekjwCAaeQvK9TcJ4"), + ), + ( + const_address("FFKYhae4HSnMmA6JJfe8NNtZeySA9yRWLaHzE2jqfhBr"), + const_hash("2E8BayMrqL3on6bhcMms6dsm3PwKcxttFSuHDNe6vZ4B"), + ), + ( + const_address("AaRrJovR9Npna4fuCJ17AB3cJAMzoNDaZymRTbGGzUZm"), + const_hash("D5bhT4vxhrtkfPeyZbvCtwzAnHSwBaa287CZZU8F6fye"), + ), + ( + const_address("5S8DzBBLvJUeyJccV4DekAK8KJA5PDcjwxRxCvgdyBEi"), + const_hash("8o7RkbTeV9r1yMgXaTzjcPys2FEkqieHER6Z5Fdc8hbw"), + ), + ( + const_address("Cot1DQZpm859brrre7swrDhTYLj2NJbg3hdMKCHk5zSk"), + const_hash("Gd86jHRKKSxrho3WKni5HYe6runTFX4cyFUQtcmJeiuk"), + ), + ( + const_address("4mfDv7PisvtMhiyGmvD6vxRdVpB842XbUhimAZYxMEn9"), + const_hash("4YQLN6N7G9nFwT8UVdFE2ZniW1gf89Qjob16wxMThxqN"), + ), + ( + const_address("BHW7qFCNHTX5QD5yJpT1hn1VM817Ji5ksZqiXMfqGrsj"), + const_hash("Ft3vnX4KQBa22CVpPkmvk5QNMGwL2xhQVxQtFJwK5MvJ"), + ), + ( + const_address("EJqZLeaxi2gVsJgQW4nbmxyWJukK25n7jB8qWKoDgWUN"), + const_hash("5tZeUYorHfdh9FYsA9yKjanFRwxjGxM9YLzNAfiwhZUf"), + ), + ( + const_address("BJqTPWyoqqgzhkLh1pbPh4KWBqg8kCUNzJ81avitSQrm"), + const_hash("5ggDcExaPfgjsmrhBS3D2UnRaEPsCGKGDkJqzF7gr92A"), + ), + ( + const_address("EkmPmEmSbwm8EDDYtLtaDgcfuLNtW7MbKx5w3FUpaGjv"), + const_hash("3G7D13ckfLCfDFC3VusXdittLHp6z6dZeUJBHTqcc2iR"), + ), + ( + const_address("CgwtCv8HQ67imnHEkz24TfXfyA2H5jurxcLGxAgDmNQj"), + const_hash("Gikpdfo6SwRqi3nTmQKuCmap3cGwupZd2poiYkUop4Sn"), + ), + ( + const_address("zfKsXSxJ4cTpKS7S6aHL1Hy3m1CEjQuySKSwkWvukQX"), + const_hash("43Kn8Kevfy2cy2fpJEhEZSpmPNwFurL2ERG5FqdSeTsq"), + ), + ( + const_address("2VvN1s6txNYyBdKpaC8b6AZKVqUQiQT2Exrpa7ffCgV6"), + const_hash("FVZKFoZ8WRdsFBp64LpTF1MrH36dHym2XZv7cJ2oYU5"), + ), + ( + const_address("A2DT1dc4rA1uMry7WCLwoUEQQNjCAsAMkB4X9Lgo88zd"), + const_hash("HjtHG8XRKyGiN8VXWmMh9oEviURAv5o2VygKTvsZjAPz"), + ), + ( + const_address("9mNBRGfTMLsSsQUn4YZfRDBVXfQ6juEWbNUTwv2ir9gC"), + const_hash("2S1aHds5wqUSyY4BmAK9YyBNGwzsQSsqGa2iyisF8t6h"), + ), + ( + const_address("3jXiydxPx1P7Ggdja5yt384ryLJAW2c8LRGV8PPRT54C"), + const_hash("Hgu6wkD6aE3uuESdW9fCWoXX4sN3eLnxYJsM7QCtrZMk"), + ), + ( + const_address("7ztGR1z28NpYjUaXyrGBzBGu62u1f9H9Pj9UVSKnT3yu"), + const_hash("9wic99ejEMQubHea9KKZZk27EU7r4LL8672D5GNrpXRG"), + ), + ( + const_address("4GdnDTr5X4eJFHuzTEBLrz3tsREo8rQro7S9YDqrbMZ9"), + const_hash("FCsgGf33ueodTVhLgQtTriNL5ZGfoaWoBkDwXSbDmLFd"), + ), + ( + const_address("ALxnH6TBKJPBFRfFZspQkxDjb9nGLUP5oxFFdZNRFgUu"), + const_hash("QkBgGAKFPtQzRj1v7sFECr8D2LMPb99AEy3w1RtKX5j"), + ), + ( + const_address("Bu3sdWtBh5TJishgK3vneh2zJg1rjLqWN5mFTHxWspwJ"), + const_hash("GWvckQW231Safveswww1GBSu4SzP5h5SgE6gugBn8upC"), + ), + ( + const_address("GvBbUTE312RXU5iXAcNWt6CuVbfsPs5Nk28D6qvU6NF3"), + const_hash("BnFsZdujQde7FnHGVcZTmvidRHBr5H87XRDDB6A5dn8D"), + ), + ( + const_address("2LLct8SsnkW3sD9Gu8CfxmDEjKAWtFXqLvA8ymMyuq8u"), + const_hash("Bnt1CWn8SEwpNqFbNxby6ysoW49wmL95Ed28pbS9v4Nx"), + ), + ( + const_address("CQ9vUhC3dSa4LyZCpWVpNbXhSn6f7J3NQXWDDvMMk6aW"), + const_hash("2yVSXvwXjtA5tqqWUKjxBuYjME6pKwJGA12NUc31x9VS"), + ), + ( + const_address("Cw8GqRmKzCbp7UFfafECC9sf9f936Chgx3BkbSgnXfmU"), + const_hash("FDPW3e2qPvNrmi1dqxsMaYAXLq9vMQYda5fKsVzNBUCv"), + ), + ( + const_address("GFJ6m6YdNT1tUfAxyD2BiPSx8gwt3xe4jVAKdtdSUt8W"), + const_hash("4tUTcUePrDUu48ZyH584aYv8JAbPrc9aDcH6bjxhEJon"), + ), + ( + const_address("7bphTuo5BKs4JJw5WPusCevmnoRk9ocFiB8EGgfwnh4c"), + const_hash("SyhFE8iYH9ZsZNBDWLvTDTBFBoEjxs12msF3xprikgf"), + ), + ( + const_address("EFbUq18Mcdi2gGauRzmbNeD5ixaB7EYVk5JZgAF34LoS"), + const_hash("53EBQYjZ7yH3Zy6KCWjSGAUGTki2YjxsHkrfXnvsj9vT"), ), ], sol_swap_endpoint_program: SolAddress(bs58_array( @@ -108,6 +268,77 @@ pub const ENV: StateChainEnvironment = StateChainEnvironment { sol_swap_endpoint_program_data_account: SolAddress(bs58_array( "2tmtGLQcBd11BMiE9B1tAkQXwmPNgR79Meki2Eme4Ec9", )), + sol_alt_manager_program: SolAddress(bs58_array("49XegQyykAXwzigc6u7gXbaLjhKfNadWMZwFiovzjwUw")), + sol_address_lookup_table_account: ( + SolAddress(bs58_array("7drVSq2ymJLNnXyCciHbNqHyzuSt1SL4iQSEThiESN2c")), + [ + const_address("BttvFNSRKrkHugwDP6SpnBejCKKskHowJif1HGgBtTfG"), + const_address("SysvarRecentB1ockHashes11111111111111111111"), + const_address("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"), + const_address("7B13iu7bUbBX88eVBqTZkQqrErnTMazPmGLdE5RqdyKZ"), + const_address("9CGLwcPknpYs3atgwtjMX7RhgvBgaqK8wwCvXnmjEoL9"), + const_address("24PNhTaNtomHhoy3fTRaMhAFCRj4uHqhZEEoWrKDbR5p"), + const_address("Sysvar1nstructions1111111111111111111111111"), + const_address("2tmtGLQcBd11BMiE9B1tAkQXwmPNgR79Meki2Eme4Ec9"), + const_address("EWaGcrFXhf9Zq8yxSdpAa75kZmDXkRxaP17sYiL6UpZN"), + const_address("So11111111111111111111111111111111111111112"), + const_address("ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL"), + const_address("11111111111111111111111111111111"), + const_address("8inHGLHXegST3EPLcpisQe9D1hDT9r7DJjS395L3yuYf"), + const_address("35uYgHdfZQT4kHkaaXQ6ZdCkK5LFrsk43btTLbGCRCNT"), + const_address("49XegQyykAXwzigc6u7gXbaLjhKfNadWMZwFiovzjwUw"), + const_address("2cNMwUCF51djw2xAiiU54wz1WrU8uG4Q8Kp8nfEuwghw"), + const_address("HVG21SovGzMBJDB9AQNuWb6XYq4dDZ6yUwCbRUuFnYDo"), + const_address("HDYArziNzyuNMrK89igisLrXFe78ti8cvkcxfx4qdU2p"), + const_address("HLPsNyxBqfq2tLE31v6RiViLp2dTXtJRgHgsWgNDRPs2"), + const_address("GKMP63TqzbueWTrFYjRwMNkAyTHpQ54notRbAbMDmePM"), + const_address("EpmHm2aSPsB5ZZcDjqDhQ86h1BV32GFCbGSMuC58Y2tn"), + const_address("9yBZNMrLrtspj4M7bEf2X6tqbqHxD2vNETw8qSdvJHMa"), + const_address("J9dT7asYJFGS68NdgDCYjzU2Wi8uBoBusSHN1Z6JLWna"), + const_address("GUMpVpQFNYJvSbyTtUarZVL7UDUgErKzDTSVJhekUX55"), + const_address("AUiHYbzH7qLZSkb3u7nAqtvqC7e41sEzgWjBEvXrpfGv"), + const_address("BN2vyodNYQQTrx3gtaDAL2UGGVtZwFeF5M8krE5aYYES"), + const_address("Gwq9TAQCjbJtdnmtxQa3PbHFfbr6YTUBMDjEP9x2uXnH"), + const_address("3pGbKatko2ckoLEy139McfKiirNgy9brYxieNqFGdN1W"), + const_address("9Mcd8BTievK2yTvyiqG9Ft4HfDFf6mjGFBWMnCSRQP8S"), + const_address("AEZG74RoqM6sxf79eTizq5ShB4JTuCkMVwUgtnC8H94z"), + const_address("APLkgyCWi8DFAMF4KikjTu8YnUG1r7sMjVEfDiaBRZnS"), + const_address("4ShNXTTHvpVt6bQdZTRdyW6yWXDzrPupdMuxajbEoGE4"), + const_address("FgZp6NJYWw15U51ynfXCfU9vq3eVgDDAHMSfJ8fFBZZ8"), + const_address("ENQ9Mmg87KFLX8ncXRPDBSd7jhKCtPBi8QzAh4rkREgP"), + const_address("Hhay1UwkzkFUgrGUYuiCvUwv7kErNzAcZnVRQ2fetT7K"), + const_address("2fUVR42opcHgGLrY1eguDXLYfQPHQe9ReJNmRorVt9v8"), + const_address("HfKr1wJASkW5UHs8yNWAqMeaYJdp8K2mdYwkbdVRdVrm"), + const_address("DrpYkMpJWkpNqX9yYgQfc3uZrCVYobJ3RbTABcSkHJkM"), + const_address("HCXc3o2go1Y2KhfnykLYXEvofLifXTb7GT13w4GsFmGw"), + const_address("FFKYhae4HSnMmA6JJfe8NNtZeySA9yRWLaHzE2jqfhBr"), + const_address("AaRrJovR9Npna4fuCJ17AB3cJAMzoNDaZymRTbGGzUZm"), + const_address("5S8DzBBLvJUeyJccV4DekAK8KJA5PDcjwxRxCvgdyBEi"), + const_address("Cot1DQZpm859brrre7swrDhTYLj2NJbg3hdMKCHk5zSk"), + const_address("4mfDv7PisvtMhiyGmvD6vxRdVpB842XbUhimAZYxMEn9"), + const_address("BHW7qFCNHTX5QD5yJpT1hn1VM817Ji5ksZqiXMfqGrsj"), + const_address("EJqZLeaxi2gVsJgQW4nbmxyWJukK25n7jB8qWKoDgWUN"), + const_address("BJqTPWyoqqgzhkLh1pbPh4KWBqg8kCUNzJ81avitSQrm"), + const_address("EkmPmEmSbwm8EDDYtLtaDgcfuLNtW7MbKx5w3FUpaGjv"), + const_address("CgwtCv8HQ67imnHEkz24TfXfyA2H5jurxcLGxAgDmNQj"), + const_address("zfKsXSxJ4cTpKS7S6aHL1Hy3m1CEjQuySKSwkWvukQX"), + const_address("2VvN1s6txNYyBdKpaC8b6AZKVqUQiQT2Exrpa7ffCgV6"), + const_address("A2DT1dc4rA1uMry7WCLwoUEQQNjCAsAMkB4X9Lgo88zd"), + const_address("9mNBRGfTMLsSsQUn4YZfRDBVXfQ6juEWbNUTwv2ir9gC"), + const_address("3jXiydxPx1P7Ggdja5yt384ryLJAW2c8LRGV8PPRT54C"), + const_address("7ztGR1z28NpYjUaXyrGBzBGu62u1f9H9Pj9UVSKnT3yu"), + const_address("4GdnDTr5X4eJFHuzTEBLrz3tsREo8rQro7S9YDqrbMZ9"), + const_address("ALxnH6TBKJPBFRfFZspQkxDjb9nGLUP5oxFFdZNRFgUu"), + const_address("Bu3sdWtBh5TJishgK3vneh2zJg1rjLqWN5mFTHxWspwJ"), + const_address("GvBbUTE312RXU5iXAcNWt6CuVbfsPs5Nk28D6qvU6NF3"), + const_address("2LLct8SsnkW3sD9Gu8CfxmDEjKAWtFXqLvA8ymMyuq8u"), + const_address("CQ9vUhC3dSa4LyZCpWVpNbXhSn6f7J3NQXWDDvMMk6aW"), + const_address("Cw8GqRmKzCbp7UFfafECC9sf9f936Chgx3BkbSgnXfmU"), + const_address("GFJ6m6YdNT1tUfAxyD2BiPSx8gwt3xe4jVAKdtdSUt8W"), + const_address("7bphTuo5BKs4JJw5WPusCevmnoRk9ocFiB8EGgfwnh4c"), + const_address("EFbUq18Mcdi2gGauRzmbNeD5ixaB7EYVk5JZgAF34LoS"), + ], + ), }; pub const EPOCH_DURATION_BLOCKS: BlockNumber = 3 * HOURS; diff --git a/state-chain/pallets/cf-environment/src/lib.rs b/state-chain/pallets/cf-environment/src/lib.rs index 3dd391b9bf8..3c0fd634dfe 100644 --- a/state-chain/pallets/cf-environment/src/lib.rs +++ b/state-chain/pallets/cf-environment/src/lib.rs @@ -39,7 +39,7 @@ pub mod weights; pub use weights::WeightInfo; pub mod migrations; -pub const PALLET_VERSION: StorageVersion = StorageVersion::new(13); +pub const PALLET_VERSION: StorageVersion = StorageVersion::new(14); const INITIAL_CONSOLIDATION_PARAMETERS: utxo_selection::ConsolidationParameters = utxo_selection::ConsolidationParameters { @@ -596,7 +596,7 @@ pub mod pallet { ArbitrumAddressCheckerAddress::::set(self.arb_address_checker_address); SolanaGenesisHash::::set(self.sol_genesis_hash); - SolanaApiEnvironment::::set(self.sol_api_env); + SolanaApiEnvironment::::set(self.sol_api_env.clone()); SolanaAvailableNonceAccounts::::set(self.sol_durable_nonces_and_accounts.clone()); ChainflipNetworkEnvironment::::set(self.network_environment); diff --git a/state-chain/pallets/cf-environment/src/migrations.rs b/state-chain/pallets/cf-environment/src/migrations.rs index 9ecc856b6e2..31a4aab96da 100644 --- a/state-chain/pallets/cf-environment/src/migrations.rs +++ b/state-chain/pallets/cf-environment/src/migrations.rs @@ -2,7 +2,7 @@ use crate::{Config, Pallet}; #[cfg(feature = "try-runtime")] use crate::{CurrentReleaseVersion, Get}; use cf_runtime_utilities::PlaceholderMigration; -use frame_support::traits::OnRuntimeUpgrade; +use frame_support::{migrations::VersionedMigration, traits::OnRuntimeUpgrade}; #[cfg(feature = "try-runtime")] use frame_support::{pallet_prelude::DispatchError, sp_runtime}; #[cfg(feature = "try-runtime")] @@ -38,7 +38,16 @@ impl OnRuntimeUpgrade for VersionUpdate { } // Migration for Updating Solana's Api Environments. -pub type PalletMigration = (PlaceholderMigration<13, Pallet>,); +pub type PalletMigration = ( + VersionedMigration< + 13, + 14, + SolApiEnvironmentMigration, + Pallet, + ::DbWeight, + >, + PlaceholderMigration<14, Pallet>, +); #[cfg(test)] mod tests { diff --git a/state-chain/pallets/cf-environment/src/migrations/sol_api_environment.rs b/state-chain/pallets/cf-environment/src/migrations/sol_api_environment.rs index bee2d75ac54..9b85636453c 100644 --- a/state-chain/pallets/cf-environment/src/migrations/sol_api_environment.rs +++ b/state-chain/pallets/cf-environment/src/migrations/sol_api_environment.rs @@ -2,7 +2,13 @@ use crate::*; use frame_support::{pallet_prelude::Weight, traits::UncheckedOnRuntimeUpgrade}; -use cf_chains::{evm::H256, sol::SolAddress}; +use cf_chains::{ + evm::H256, + sol::{ + sol_tx_core::consts::{const_address, const_hash}, + AddressLookupTableAccount, SolAddress, + }, +}; use cf_utilities::bs58_array; use codec::{Decode, Encode}; use scale_info::TypeInfo; @@ -18,6 +24,8 @@ pub mod old { pub token_vault_pda_account: SolAddress, pub usdc_token_mint_pubkey: SolAddress, pub usdc_token_vault_ata: SolAddress, + pub swap_endpoint_program: SolAddress, + pub swap_endpoint_program_data_account: SolAddress, } } @@ -34,40 +42,315 @@ impl> UncheckedOnRuntimeUpgrade for SolApiEnvironmentMigr token_vault_pda_account, usdc_token_mint_pubkey, usdc_token_vault_ata, + swap_endpoint_program, + swap_endpoint_program_data_account, }| { - let (swap_endpoint_program, swap_endpoint_program_data_account) = + let (alt_manager_program, address_lookup_table_account) = match cf_runtime_utilities::genesis_hashes::genesis_hash::() { + // TODO: To update with real values cf_runtime_utilities::genesis_hashes::BERGHAIN => ( SolAddress(bs58_array( "J88B7gmadHzTNGiy54c9Ms8BsEXNdB2fntFyhKpk3qoT", )), - SolAddress(bs58_array( - "FmAcjWaRFUxGWBfGT7G3CzcFeJFsewQ4KPJVG4f6fcob", - )), + ( + SolAddress(bs58_array( + "FmAcjWaRFUxGWBfGT7G3CzcFeJFsewQ4KPJVG4f6fcob", + )), + vec![], + ), ), + // TODO: To update with the right values cf_runtime_utilities::genesis_hashes::PERSEVERANCE => ( SolAddress(bs58_array( "DeL6iGV5RWrWh7cPoEa7tRHM8XURAaB4vPjfX5qVyuWE", )), - SolAddress(bs58_array( - "12MYcNumSQCn81yKRfrk5P5ThM5ivkLiZda979hhKJDR", - )), + ( + SolAddress(bs58_array( + "12MYcNumSQCn81yKRfrk5P5ThM5ivkLiZda979hhKJDR", + )), + vec![], + ), ), + // TODO: To update with the right values cf_runtime_utilities::genesis_hashes::SISYPHOS => ( SolAddress(bs58_array( "FtK6TR2ZqhChxXeDFoVzM9gYDPA18tGrKoBb3hX7nPwt", )), - SolAddress(bs58_array( - "EXeku7Q9AiAXBdH7cUHw2ue3okhrofvDZR7EBE1BVQZu", - )), + ( + SolAddress(bs58_array( + "EXeku7Q9AiAXBdH7cUHw2ue3okhrofvDZR7EBE1BVQZu", + )), + vec![], + ), ), _ => ( SolAddress(bs58_array( - "35uYgHdfZQT4kHkaaXQ6ZdCkK5LFrsk43btTLbGCRCNT", - )), - SolAddress(bs58_array( - "2tmtGLQcBd11BMiE9B1tAkQXwmPNgR79Meki2Eme4Ec9", + "49XegQyykAXwzigc6u7gXbaLjhKfNadWMZwFiovzjwUw", )), + ( + SolAddress(bs58_array( + "7drVSq2ymJLNnXyCciHbNqHyzuSt1SL4iQSEThiESN2c", + )), + vec![ + const_address( + "BttvFNSRKrkHugwDP6SpnBejCKKskHowJif1HGgBtTfG", + ) + .into(), + const_address( + "SysvarRecentB1ockHashes11111111111111111111", + ) + .into(), + const_address( + "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", + ) + .into(), + const_address( + "7B13iu7bUbBX88eVBqTZkQqrErnTMazPmGLdE5RqdyKZ", + ) + .into(), + const_address( + "9CGLwcPknpYs3atgwtjMX7RhgvBgaqK8wwCvXnmjEoL9", + ) + .into(), + const_address( + "24PNhTaNtomHhoy3fTRaMhAFCRj4uHqhZEEoWrKDbR5p", + ) + .into(), + const_address( + "Sysvar1nstructions1111111111111111111111111", + ) + .into(), + const_address( + "2tmtGLQcBd11BMiE9B1tAkQXwmPNgR79Meki2Eme4Ec9", + ) + .into(), + const_address( + "EWaGcrFXhf9Zq8yxSdpAa75kZmDXkRxaP17sYiL6UpZN", + ) + .into(), + const_address( + "So11111111111111111111111111111111111111112", + ) + .into(), + const_address( + "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL", + ) + .into(), + const_address("11111111111111111111111111111111").into(), + const_address( + "8inHGLHXegST3EPLcpisQe9D1hDT9r7DJjS395L3yuYf", + ) + .into(), + const_address( + "35uYgHdfZQT4kHkaaXQ6ZdCkK5LFrsk43btTLbGCRCNT", + ) + .into(), + const_address( + "49XegQyykAXwzigc6u7gXbaLjhKfNadWMZwFiovzjwUw", + ) + .into(), + const_address( + "2cNMwUCF51djw2xAiiU54wz1WrU8uG4Q8Kp8nfEuwghw", + ) + .into(), + const_address( + "HVG21SovGzMBJDB9AQNuWb6XYq4dDZ6yUwCbRUuFnYDo", + ) + .into(), + const_address( + "HDYArziNzyuNMrK89igisLrXFe78ti8cvkcxfx4qdU2p", + ) + .into(), + const_address( + "HLPsNyxBqfq2tLE31v6RiViLp2dTXtJRgHgsWgNDRPs2", + ) + .into(), + const_address( + "GKMP63TqzbueWTrFYjRwMNkAyTHpQ54notRbAbMDmePM", + ) + .into(), + const_address( + "EpmHm2aSPsB5ZZcDjqDhQ86h1BV32GFCbGSMuC58Y2tn", + ) + .into(), + const_address( + "9yBZNMrLrtspj4M7bEf2X6tqbqHxD2vNETw8qSdvJHMa", + ) + .into(), + const_address( + "J9dT7asYJFGS68NdgDCYjzU2Wi8uBoBusSHN1Z6JLWna", + ) + .into(), + const_address( + "GUMpVpQFNYJvSbyTtUarZVL7UDUgErKzDTSVJhekUX55", + ) + .into(), + const_address( + "AUiHYbzH7qLZSkb3u7nAqtvqC7e41sEzgWjBEvXrpfGv", + ) + .into(), + const_address( + "BN2vyodNYQQTrx3gtaDAL2UGGVtZwFeF5M8krE5aYYES", + ) + .into(), + const_address( + "Gwq9TAQCjbJtdnmtxQa3PbHFfbr6YTUBMDjEP9x2uXnH", + ) + .into(), + const_address( + "3pGbKatko2ckoLEy139McfKiirNgy9brYxieNqFGdN1W", + ) + .into(), + const_address( + "9Mcd8BTievK2yTvyiqG9Ft4HfDFf6mjGFBWMnCSRQP8S", + ) + .into(), + const_address( + "AEZG74RoqM6sxf79eTizq5ShB4JTuCkMVwUgtnC8H94z", + ) + .into(), + const_address( + "APLkgyCWi8DFAMF4KikjTu8YnUG1r7sMjVEfDiaBRZnS", + ) + .into(), + const_address( + "4ShNXTTHvpVt6bQdZTRdyW6yWXDzrPupdMuxajbEoGE4", + ) + .into(), + const_address( + "FgZp6NJYWw15U51ynfXCfU9vq3eVgDDAHMSfJ8fFBZZ8", + ) + .into(), + const_address( + "ENQ9Mmg87KFLX8ncXRPDBSd7jhKCtPBi8QzAh4rkREgP", + ) + .into(), + const_address( + "Hhay1UwkzkFUgrGUYuiCvUwv7kErNzAcZnVRQ2fetT7K", + ) + .into(), + const_address( + "2fUVR42opcHgGLrY1eguDXLYfQPHQe9ReJNmRorVt9v8", + ) + .into(), + const_address( + "HfKr1wJASkW5UHs8yNWAqMeaYJdp8K2mdYwkbdVRdVrm", + ) + .into(), + const_address( + "DrpYkMpJWkpNqX9yYgQfc3uZrCVYobJ3RbTABcSkHJkM", + ) + .into(), + const_address( + "HCXc3o2go1Y2KhfnykLYXEvofLifXTb7GT13w4GsFmGw", + ) + .into(), + const_address( + "FFKYhae4HSnMmA6JJfe8NNtZeySA9yRWLaHzE2jqfhBr", + ) + .into(), + const_address( + "AaRrJovR9Npna4fuCJ17AB3cJAMzoNDaZymRTbGGzUZm", + ) + .into(), + const_address( + "5S8DzBBLvJUeyJccV4DekAK8KJA5PDcjwxRxCvgdyBEi", + ) + .into(), + const_address( + "Cot1DQZpm859brrre7swrDhTYLj2NJbg3hdMKCHk5zSk", + ) + .into(), + const_address( + "4mfDv7PisvtMhiyGmvD6vxRdVpB842XbUhimAZYxMEn9", + ) + .into(), + const_address( + "BHW7qFCNHTX5QD5yJpT1hn1VM817Ji5ksZqiXMfqGrsj", + ) + .into(), + const_address( + "EJqZLeaxi2gVsJgQW4nbmxyWJukK25n7jB8qWKoDgWUN", + ) + .into(), + const_address( + "BJqTPWyoqqgzhkLh1pbPh4KWBqg8kCUNzJ81avitSQrm", + ) + .into(), + const_address( + "EkmPmEmSbwm8EDDYtLtaDgcfuLNtW7MbKx5w3FUpaGjv", + ) + .into(), + const_address( + "CgwtCv8HQ67imnHEkz24TfXfyA2H5jurxcLGxAgDmNQj", + ) + .into(), + const_address( + "zfKsXSxJ4cTpKS7S6aHL1Hy3m1CEjQuySKSwkWvukQX", + ) + .into(), + const_address( + "2VvN1s6txNYyBdKpaC8b6AZKVqUQiQT2Exrpa7ffCgV6", + ) + .into(), + const_address( + "A2DT1dc4rA1uMry7WCLwoUEQQNjCAsAMkB4X9Lgo88zd", + ) + .into(), + const_address( + "9mNBRGfTMLsSsQUn4YZfRDBVXfQ6juEWbNUTwv2ir9gC", + ) + .into(), + const_address( + "3jXiydxPx1P7Ggdja5yt384ryLJAW2c8LRGV8PPRT54C", + ) + .into(), + const_address( + "7ztGR1z28NpYjUaXyrGBzBGu62u1f9H9Pj9UVSKnT3yu", + ) + .into(), + const_address( + "4GdnDTr5X4eJFHuzTEBLrz3tsREo8rQro7S9YDqrbMZ9", + ) + .into(), + const_address( + "ALxnH6TBKJPBFRfFZspQkxDjb9nGLUP5oxFFdZNRFgUu", + ) + .into(), + const_address( + "Bu3sdWtBh5TJishgK3vneh2zJg1rjLqWN5mFTHxWspwJ", + ) + .into(), + const_address( + "GvBbUTE312RXU5iXAcNWt6CuVbfsPs5Nk28D6qvU6NF3", + ) + .into(), + const_address( + "2LLct8SsnkW3sD9Gu8CfxmDEjKAWtFXqLvA8ymMyuq8u", + ) + .into(), + const_address( + "CQ9vUhC3dSa4LyZCpWVpNbXhSn6f7J3NQXWDDvMMk6aW", + ) + .into(), + const_address( + "Cw8GqRmKzCbp7UFfafECC9sf9f936Chgx3BkbSgnXfmU", + ) + .into(), + const_address( + "GFJ6m6YdNT1tUfAxyD2BiPSx8gwt3xe4jVAKdtdSUt8W", + ) + .into(), + const_address( + "7bphTuo5BKs4JJw5WPusCevmnoRk9ocFiB8EGgfwnh4c", + ) + .into(), + const_address( + "EFbUq18Mcdi2gGauRzmbNeD5ixaB7EYVk5JZgAF34LoS", + ) + .into(), + ], + ), ), }; @@ -77,15 +360,230 @@ impl> UncheckedOnRuntimeUpgrade for SolApiEnvironmentMigr token_vault_pda_account, usdc_token_mint_pubkey, usdc_token_vault_ata, - - // Newly inserted values swap_endpoint_program, swap_endpoint_program_data_account, + + // Newly inserted values + alt_manager_program, + address_lookup_table_account: AddressLookupTableAccount { + key: address_lookup_table_account.0.into(), + addresses: address_lookup_table_account.1, + }, } }, ) }); + // Insert new nonces into storage + match cf_runtime_utilities::genesis_hashes::genesis_hash::() { + cf_runtime_utilities::genesis_hashes::BERGHAIN => (), + // TODO: To add the right values + cf_runtime_utilities::genesis_hashes::PERSEVERANCE => (), + // TODO: To add the right values + cf_runtime_utilities::genesis_hashes::SISYPHOS => (), + _ => { + SolanaAvailableNonceAccounts::::append(( + const_address("BN2vyodNYQQTrx3gtaDAL2UGGVtZwFeF5M8krE5aYYES"), + const_hash("4fjG6oYKadvnsbzAzomF5k2Zdc4DuuUyT71nueAeykMW"), + )); + + SolanaAvailableNonceAccounts::::append(( + const_address("Gwq9TAQCjbJtdnmtxQa3PbHFfbr6YTUBMDjEP9x2uXnH"), + const_hash("GK29hbKjKWNwdF4KT11MzkrmQPsYPwE41qZMnLVcQPaS"), + )); + + SolanaAvailableNonceAccounts::::append(( + const_address("3pGbKatko2ckoLEy139McfKiirNgy9brYxieNqFGdN1W"), + const_hash("5cinXdpw2KAGzmiXXegWJRdDDboXbDHaQaT3WFsH3txb"), + )); + + SolanaAvailableNonceAccounts::::append(( + const_address("9Mcd8BTievK2yTvyiqG9Ft4HfDFf6mjGFBWMnCSRQP8S"), + const_hash("DRoAyPDtsg9CCMBSN6egFsWsP2zsQBAxCzN6fAdtQxJU"), + )); + + SolanaAvailableNonceAccounts::::append(( + const_address("AEZG74RoqM6sxf79eTizq5ShB4JTuCkMVwUgtnC8H94z"), + const_hash("G8ZKHMsWFSoKJAtVbm1xgv8VjT5F6YBeiZbbzpVHuuyM"), + )); + + SolanaAvailableNonceAccounts::::append(( + const_address("APLkgyCWi8DFAMF4KikjTu8YnUG1r7sMjVEfDiaBRZnS"), + const_hash("BMUqNXhMoB6VWsR7jHgRcv7yio8L5vjHdGby7gEJ4Pd2"), + )); + + SolanaAvailableNonceAccounts::::append(( + const_address("4ShNXTTHvpVt6bQdZTRdyW6yWXDzrPupdMuxajbEoGE4"), + const_hash("52yamKJdMiQ5tEUyhkngvjR3XFXp7dmJzYsVsLbPs9JX"), + )); + + SolanaAvailableNonceAccounts::::append(( + const_address("FgZp6NJYWw15U51ynfXCfU9vq3eVgDDAHMSfJ8fFBZZ8"), + const_hash("AX3qKNMBRKZimeCsBEhtp7heeduKekj85a4UpdN34HFe"), + )); + + SolanaAvailableNonceAccounts::::append(( + const_address("ENQ9Mmg87KFLX8ncXRPDBSd7jhKCtPBi8QzAh4rkREgP"), + const_hash("GGFme2ydkkbDzq7LhVDMX5SsFf2yGLf7uKNSLLhvrGMd"), + )); + + SolanaAvailableNonceAccounts::::append(( + const_address("Hhay1UwkzkFUgrGUYuiCvUwv7kErNzAcZnVRQ2fetT7K"), + const_hash("HMN14axscHALAuknuwSpVkEmAJkZWeJoNAjJuXUjRQbN"), + )); + + SolanaAvailableNonceAccounts::::append(( + const_address("2fUVR42opcHgGLrY1eguDXLYfQPHQe9ReJNmRorVt9v8"), + const_hash("RWoH6shzxCS9dmW2mg37cujXxARBRBunbHEtZwUz1Gj"), + )); + + SolanaAvailableNonceAccounts::::append(( + const_address("HfKr1wJASkW5UHs8yNWAqMeaYJdp8K2mdYwkbdVRdVrm"), + const_hash("2dhBBWYQE2Fvm4ShUQjno8ydJb5H6rUmBZ1e6TJHDupL"), + )); + + SolanaAvailableNonceAccounts::::append(( + const_address("DrpYkMpJWkpNqX9yYgQfc3uZrCVYobJ3RbTABcSkHJkM"), + const_hash("6VCThFyLtFCKk35wihyrRUa6dubBU7skhJdRRDBfH4Md"), + )); + + SolanaAvailableNonceAccounts::::append(( + const_address("HCXc3o2go1Y2KhfnykLYXEvofLifXTb7GT13w4GsFmGw"), + const_hash("EggsCqUiKJVxmN7a9s7RScXUAJRjekjwCAaeQvK9TcJ4"), + )); + + SolanaAvailableNonceAccounts::::append(( + const_address("FFKYhae4HSnMmA6JJfe8NNtZeySA9yRWLaHzE2jqfhBr"), + const_hash("2E8BayMrqL3on6bhcMms6dsm3PwKcxttFSuHDNe6vZ4B"), + )); + + SolanaAvailableNonceAccounts::::append(( + const_address("AaRrJovR9Npna4fuCJ17AB3cJAMzoNDaZymRTbGGzUZm"), + const_hash("D5bhT4vxhrtkfPeyZbvCtwzAnHSwBaa287CZZU8F6fye"), + )); + + SolanaAvailableNonceAccounts::::append(( + const_address("5S8DzBBLvJUeyJccV4DekAK8KJA5PDcjwxRxCvgdyBEi"), + const_hash("8o7RkbTeV9r1yMgXaTzjcPys2FEkqieHER6Z5Fdc8hbw"), + )); + + SolanaAvailableNonceAccounts::::append(( + const_address("Cot1DQZpm859brrre7swrDhTYLj2NJbg3hdMKCHk5zSk"), + const_hash("Gd86jHRKKSxrho3WKni5HYe6runTFX4cyFUQtcmJeiuk"), + )); + + SolanaAvailableNonceAccounts::::append(( + const_address("4mfDv7PisvtMhiyGmvD6vxRdVpB842XbUhimAZYxMEn9"), + const_hash("4YQLN6N7G9nFwT8UVdFE2ZniW1gf89Qjob16wxMThxqN"), + )); + + SolanaAvailableNonceAccounts::::append(( + const_address("BHW7qFCNHTX5QD5yJpT1hn1VM817Ji5ksZqiXMfqGrsj"), + const_hash("Ft3vnX4KQBa22CVpPkmvk5QNMGwL2xhQVxQtFJwK5MvJ"), + )); + + SolanaAvailableNonceAccounts::::append(( + const_address("EJqZLeaxi2gVsJgQW4nbmxyWJukK25n7jB8qWKoDgWUN"), + const_hash("5tZeUYorHfdh9FYsA9yKjanFRwxjGxM9YLzNAfiwhZUf"), + )); + + SolanaAvailableNonceAccounts::::append(( + const_address("BJqTPWyoqqgzhkLh1pbPh4KWBqg8kCUNzJ81avitSQrm"), + const_hash("5ggDcExaPfgjsmrhBS3D2UnRaEPsCGKGDkJqzF7gr92A"), + )); + + SolanaAvailableNonceAccounts::::append(( + const_address("EkmPmEmSbwm8EDDYtLtaDgcfuLNtW7MbKx5w3FUpaGjv"), + const_hash("3G7D13ckfLCfDFC3VusXdittLHp6z6dZeUJBHTqcc2iR"), + )); + + SolanaAvailableNonceAccounts::::append(( + const_address("CgwtCv8HQ67imnHEkz24TfXfyA2H5jurxcLGxAgDmNQj"), + const_hash("Gikpdfo6SwRqi3nTmQKuCmap3cGwupZd2poiYkUop4Sn"), + )); + + SolanaAvailableNonceAccounts::::append(( + const_address("zfKsXSxJ4cTpKS7S6aHL1Hy3m1CEjQuySKSwkWvukQX"), + const_hash("43Kn8Kevfy2cy2fpJEhEZSpmPNwFurL2ERG5FqdSeTsq"), + )); + + SolanaAvailableNonceAccounts::::append(( + const_address("2VvN1s6txNYyBdKpaC8b6AZKVqUQiQT2Exrpa7ffCgV6"), + const_hash("FVZKFoZ8WRdsFBp64LpTF1MrH36dHym2XZv7cJ2oYU5"), + )); + + SolanaAvailableNonceAccounts::::append(( + const_address("A2DT1dc4rA1uMry7WCLwoUEQQNjCAsAMkB4X9Lgo88zd"), + const_hash("HjtHG8XRKyGiN8VXWmMh9oEviURAv5o2VygKTvsZjAPz"), + )); + + SolanaAvailableNonceAccounts::::append(( + const_address("9mNBRGfTMLsSsQUn4YZfRDBVXfQ6juEWbNUTwv2ir9gC"), + const_hash("2S1aHds5wqUSyY4BmAK9YyBNGwzsQSsqGa2iyisF8t6h"), + )); + + SolanaAvailableNonceAccounts::::append(( + const_address("3jXiydxPx1P7Ggdja5yt384ryLJAW2c8LRGV8PPRT54C"), + const_hash("Hgu6wkD6aE3uuESdW9fCWoXX4sN3eLnxYJsM7QCtrZMk"), + )); + + SolanaAvailableNonceAccounts::::append(( + const_address("7ztGR1z28NpYjUaXyrGBzBGu62u1f9H9Pj9UVSKnT3yu"), + const_hash("9wic99ejEMQubHea9KKZZk27EU7r4LL8672D5GNrpXRG"), + )); + + SolanaAvailableNonceAccounts::::append(( + const_address("4GdnDTr5X4eJFHuzTEBLrz3tsREo8rQro7S9YDqrbMZ9"), + const_hash("FCsgGf33ueodTVhLgQtTriNL5ZGfoaWoBkDwXSbDmLFd"), + )); + + SolanaAvailableNonceAccounts::::append(( + const_address("ALxnH6TBKJPBFRfFZspQkxDjb9nGLUP5oxFFdZNRFgUu"), + const_hash("QkBgGAKFPtQzRj1v7sFECr8D2LMPb99AEy3w1RtKX5j"), + )); + + SolanaAvailableNonceAccounts::::append(( + const_address("Bu3sdWtBh5TJishgK3vneh2zJg1rjLqWN5mFTHxWspwJ"), + const_hash("GWvckQW231Safveswww1GBSu4SzP5h5SgE6gugBn8upC"), + )); + + SolanaAvailableNonceAccounts::::append(( + const_address("GvBbUTE312RXU5iXAcNWt6CuVbfsPs5Nk28D6qvU6NF3"), + const_hash("BnFsZdujQde7FnHGVcZTmvidRHBr5H87XRDDB6A5dn8D"), + )); + + SolanaAvailableNonceAccounts::::append(( + const_address("2LLct8SsnkW3sD9Gu8CfxmDEjKAWtFXqLvA8ymMyuq8u"), + const_hash("Bnt1CWn8SEwpNqFbNxby6ysoW49wmL95Ed28pbS9v4Nx"), + )); + + SolanaAvailableNonceAccounts::::append(( + const_address("CQ9vUhC3dSa4LyZCpWVpNbXhSn6f7J3NQXWDDvMMk6aW"), + const_hash("2yVSXvwXjtA5tqqWUKjxBuYjME6pKwJGA12NUc31x9VS"), + )); + + SolanaAvailableNonceAccounts::::append(( + const_address("Cw8GqRmKzCbp7UFfafECC9sf9f936Chgx3BkbSgnXfmU"), + const_hash("FDPW3e2qPvNrmi1dqxsMaYAXLq9vMQYda5fKsVzNBUCv"), + )); + + SolanaAvailableNonceAccounts::::append(( + const_address("GFJ6m6YdNT1tUfAxyD2BiPSx8gwt3xe4jVAKdtdSUt8W"), + const_hash("4tUTcUePrDUu48ZyH584aYv8JAbPrc9aDcH6bjxhEJon"), + )); + + SolanaAvailableNonceAccounts::::append(( + const_address("7bphTuo5BKs4JJw5WPusCevmnoRk9ocFiB8EGgfwnh4c"), + const_hash("SyhFE8iYH9ZsZNBDWLvTDTBFBoEjxs12msF3xprikgf"), + )); + + SolanaAvailableNonceAccounts::::append(( + const_address("EFbUq18Mcdi2gGauRzmbNeD5ixaB7EYVk5JZgAF34LoS"), + const_hash("53EBQYjZ7yH3Zy6KCWjSGAUGTki2YjxsHkrfXnvsj9vT"), + )); + }, + }; + Weight::zero() } } diff --git a/state-chain/pallets/cf-environment/src/mock.rs b/state-chain/pallets/cf-environment/src/mock.rs index 4036b3dc247..27b3d7da30f 100644 --- a/state-chain/pallets/cf-environment/src/mock.rs +++ b/state-chain/pallets/cf-environment/src/mock.rs @@ -7,9 +7,9 @@ use cf_chains::{ eth, sol::{ api::{ - AllNonceAccounts, ApiEnvironment, ChainflipAddressLookupTable, ComputePrice, - CurrentAggKey, CurrentOnChainKey, DurableNonce, DurableNonceAndAccount, - RecoverDurableNonce, SolanaAddressLookupTables, SolanaApi, SolanaEnvironment, + AllNonceAccounts, ApiEnvironment, ComputePrice, CurrentAggKey, CurrentOnChainKey, + DurableNonce, DurableNonceAndAccount, RecoverDurableNonce, SolanaAddressLookupTables, + SolanaApi, SolanaEnvironment, }, SolAddress, SolAddressLookupTableAccount, SolAmount, SolApiEnvironment, SolHash, }, @@ -150,6 +150,11 @@ impl ChainEnvironment for MockSolEnvironment usdc_token_vault_ata: SolAddress([0x00; 32]), swap_endpoint_program: SolAddress([0x00; 32]), swap_endpoint_program_data_account: SolAddress([0x00; 32]), + alt_manager_program: SolAddress([0x00; 32]), + address_lookup_table_account: SolAddressLookupTableAccount { + key: SolAddress([0x00; 32]).into(), + addresses: vec![], + }, }) } } @@ -191,13 +196,6 @@ impl ChainEnvironment - for MockSolEnvironment -{ - fn lookup(_s: ChainflipAddressLookupTable) -> Option { - None - } -} impl SolanaEnvironment for MockSolEnvironment {} diff --git a/state-chain/runtime/src/chainflip.rs b/state-chain/runtime/src/chainflip.rs index 1b714cc6b48..37e1a7fbce3 100644 --- a/state-chain/runtime/src/chainflip.rs +++ b/state-chain/runtime/src/chainflip.rs @@ -50,9 +50,9 @@ use cf_chains::{ }, sol::{ api::{ - AllNonceAccounts, ApiEnvironment, ChainflipAddressLookupTable, ComputePrice, - CurrentAggKey, CurrentOnChainKey, DurableNonce, DurableNonceAndAccount, - RecoverDurableNonce, SolanaAddressLookupTables, SolanaApi, SolanaEnvironment, + AllNonceAccounts, ApiEnvironment, ComputePrice, CurrentAggKey, CurrentOnChainKey, + DurableNonce, DurableNonceAndAccount, RecoverDurableNonce, SolanaAddressLookupTables, + SolanaApi, SolanaEnvironment, }, SolAddress, SolAddressLookupTableAccount, SolAmount, SolApiEnvironment, SolanaCrypto, SolanaTransactionData, NONCE_AVAILABILITY_THRESHOLD_FOR_INITIATING_TRANSFER, @@ -605,15 +605,6 @@ impl ChainEnvironment - for SolEnvironment -{ - fn lookup(_s: ChainflipAddressLookupTable) -> Option { - // TODO Roy: Read Chainflip's ALT from the Environment pallet. - None - } -} - impl SolanaEnvironment for SolEnvironment {} pub struct TokenholderGovernanceBroadcaster; From cb41ac52610923e0339f650d088d868fbc5c8749 Mon Sep 17 00:00:00 2001 From: Roy Yang Date: Wed, 19 Feb 2025 20:45:34 +1300 Subject: [PATCH 4/4] feat: add fallback logic to refund failed CCM transaction (#5650) * chore: add ci when PR against base branch * feat: use Solana versioned transaction to build api calls (#5633) * Added versioned transaction and versioned message support * Added unit test for Versioned transactions with Address lookup table * Moved (almost) everything in sol_tx_core into sol-prim Moved ALT related stuff to its own file. * Initial commit for changing Solana Transaction to VersionedTransaction * chore: update bouncer to get versioned transactions * Updated unit tests for transaction building Removed all uses of Legacy message and Transaction. * Fix broken unit test * Make solana api calls more consistent with the use of ALT --------- Co-authored-by: Daniel Co-authored-by: albert * Added versioned transaction and versioned message support * Added unit test for Versioned transactions with Address lookup table * Moved (almost) everything in sol_tx_core into sol-prim Moved ALT related stuff to its own file. * Initial commit for changing Solana Transaction to VersionedTransaction * Make solana api calls more consistent with the use of ALT * feat: update image with alt and add logic and migrations * chore: rebase and update * chore: run ci * chore: fix clippy and try removing symlink * chore: try running anza * chore: upgrade to 2.1.13 * chore: update bouncer expected number of nonces * chore: update compute units * chore: restore ci# * chore: fix ci * chore: nit * chore: update test * chore: fix tests and nit * chore: define MAX_CCM_USER_ALTS * Minor improvements. Fix build and tests * Add a fallback mechanism where if CCM failed to build (for any reason) the fund is returned to the "refund" address via a "Transfer" transaction. * chore: nit * chore: fix * chore: revert source_address * chore: clippy --------- Co-authored-by: albert Co-authored-by: Daniel --- .../cf-integration-tests/src/solana.rs | 99 ++++++++++++++++++- state-chain/chains/src/ccm_checker.rs | 48 +++++++-- state-chain/chains/src/sol/api.rs | 4 +- .../pallets/cf-ingress-egress/src/lib.rs | 42 +++++++- 4 files changed, 176 insertions(+), 17 deletions(-) diff --git a/state-chain/cf-integration-tests/src/solana.rs b/state-chain/cf-integration-tests/src/solana.rs index 3eb75f0fe46..85b99bfe28f 100644 --- a/state-chain/cf-integration-tests/src/solana.rs +++ b/state-chain/cf-integration-tests/src/solana.rs @@ -8,14 +8,16 @@ use cf_chains::{ assets::{any::Asset, sol::Asset as SolAsset}, ccm_checker::{CcmValidityError, VersionedSolanaCcmAdditionalData}, sol::{ - api::{SolanaApi, SolanaEnvironment, SolanaTransactionBuildingError}, + api::{ + SolanaApi, SolanaEnvironment, SolanaTransactionBuildingError, SolanaTransactionType, + }, sol_tx_core::sol_test_values, transaction_builder::SolanaTransactionBuilder, SolAddress, SolCcmAccounts, SolCcmAddress, SolHash, SolPubkey, SolanaCrypto, }, CcmChannelMetadata, CcmDepositMetadata, Chain, ChannelRefundParameters, ExecutexSwapAndCallError, ForeignChainAddress, RequiresSignatureRefresh, SetAggKeyWithAggKey, - SetAggKeyWithAggKeyError, Solana, SwapOrigin, TransactionBuilder, + SetAggKeyWithAggKeyError, Solana, SwapOrigin, TransactionBuilder, TransferAssetParams, }; use cf_primitives::{AccountRole, AuthorityCount, ForeignChain, SwapRequestId}; use cf_test_utilities::{assert_events_match, assert_has_matching_event}; @@ -771,3 +773,96 @@ fn solana_ccm_execution_error_can_trigger_fallback() { assert!(!pallet_cf_broadcast::PendingApiCalls::::contains_key(ccm_broadcast_id)); }); } + +#[test] +fn solana_failed_ccm_can_trigger_refund_transfer() { + const EPOCH_BLOCKS: u32 = 100; + const MAX_AUTHORITIES: AuthorityCount = 10; + super::genesis::with_test_defaults() + .epoch_duration(EPOCH_BLOCKS) + .max_authorities(MAX_AUTHORITIES) + .with_additional_accounts(&[ + (DORIS, AccountRole::LiquidityProvider, 5 * FLIPPERINOS_PER_FLIP), + (ZION, AccountRole::Broker, 5 * FLIPPERINOS_PER_FLIP), + ]) + .build() + .execute_with(|| { + setup_sol_environments(); + + let (mut testnet, _, _) = network::fund_authorities_and_join_auction(MAX_AUTHORITIES); + assert_ok!(RuntimeCall::SolanaVault( + pallet_cf_vaults::Call::::initialize_chain {} + ) + .dispatch_bypass_filter(pallet_cf_governance::RawOrigin::GovernanceApproval.into())); + setup_pool_and_accounts(vec![Asset::Sol, Asset::SolUsdc], OrderType::LimitOrder); + testnet.move_to_the_next_epoch(); + + let destination_address = SolAddress([0xcf; 32]); + let asset = SolAsset::Sol; + let amount = 1_000_000_000_000u64; + + // Construct a Ccm that when built will exceed the maximum length. + const NUM_ACCOUNTS: u8 = 40u8; + let ccm = CcmChannelMetadata { + message: vec![0u8, 1u8, 2u8, 3u8].try_into().unwrap(), + gas_budget: 1_000_000_000u128, + ccm_additional_data: VersionedSolanaCcmAdditionalData::V1{ccm_accounts: SolCcmAccounts { + cf_receiver: SolCcmAddress { pubkey: SolPubkey([0x10; 32]), is_writable: true }, + additional_accounts: (0..NUM_ACCOUNTS).map(|i|SolCcmAddress { pubkey: SolPubkey([i; 32]), is_writable: false }).collect::>(), + fallback_address: FALLBACK_ADDRESS.into(), + }, alts: vec![]} + .encode() + .try_into() + .unwrap(), + }; + + // This Ccm will exceed maximum size when built, triggering the fallback refund mechanism. + assert_eq!(cf_chains::sol::api::SolanaApi::::ccm_transfer( + TransferAssetParams { + asset, + amount, + to: destination_address, + }, + ForeignChain::Ethereum, + None, + ccm.gas_budget, + ccm.message.clone().to_vec(), + ccm.ccm_additional_data.clone().to_vec(), + Default::default(), + ), Err(SolanaTransactionBuildingError::InvalidCcm(CcmValidityError::CcmIsTooLong))); + + // Directly insert a CCM to be ingressed. + pallet_cf_ingress_egress::ScheduledEgressCcm::::append(pallet_cf_ingress_egress::CrossChainMessage { + egress_id: (ForeignChain::Solana, 1u64), + asset: SolAsset::Sol, + amount: 1_000_000_000_000u64, + destination_address, + message: ccm.message, + source_chain: ForeignChain::Ethereum, + source_address: None, + ccm_additional_data: ccm.ccm_additional_data, + gas_budget: ccm.gas_budget, + swap_request_id: SwapRequestId(1u64), + }); + + testnet.move_forward_blocks(1); + + // When CCM transaction building failed, fallback to refund the asset via Transfer instead. + assert!(assert_events_match!(Runtime, RuntimeEvent::SolanaIngressEgress(pallet_cf_ingress_egress::Event::::InvalidCcmRefunded { + asset, + destination_address, + .. + }) if asset == SolAsset::Sol && destination_address == FALLBACK_ADDRESS => true)); + + // Give enough time to schedule, egress and threshold-sign the transfer transaction. + testnet.move_forward_blocks(4); + let broadcast_id = pallet_cf_broadcast::BroadcastIdCounter::::get(); + + // Transfer transaction should be created against the refund address. + assert!(pallet_cf_broadcast::PendingBroadcasts::::get().contains(&broadcast_id)); + assert!(matches!(pallet_cf_broadcast::PendingApiCalls::::get(broadcast_id), Some(SolanaApi { + call_type: SolanaTransactionType::Transfer, + .. + }))); + }); +} diff --git a/state-chain/chains/src/ccm_checker.rs b/state-chain/chains/src/ccm_checker.rs index 86cdcd7e03b..b8cbf5be3b3 100644 --- a/state-chain/chains/src/ccm_checker.rs +++ b/state-chain/chains/src/ccm_checker.rs @@ -7,7 +7,7 @@ use crate::{ }, SolAddress, SolAsset, SolCcmAccounts, SolPubkey, MAX_CCM_BYTES_SOL, MAX_CCM_BYTES_USDC, }, - CcmChannelMetadata, + CcmAdditionalData, CcmChannelMetadata, Chain, ForeignChainAddress, }; use cf_primitives::{Asset, ForeignChain}; use codec::{Decode, Encode}; @@ -52,19 +52,34 @@ pub trait CcmValidityCheck { } fn decode_unchecked( - _ccm: &CcmChannelMetadata, + _ccm: CcmAdditionalData, _chain: ForeignChain, ) -> Result { Ok(DecodedCcmAdditionalData::NotRequired) } } -#[derive(Clone, Debug, Decode, PartialEq, Eq)] +#[derive(Clone, Debug, Encode, Decode, PartialEq, Eq)] pub enum DecodedCcmAdditionalData { NotRequired, Solana(VersionedSolanaCcmAdditionalData), } +impl DecodedCcmAdditionalData { + /// Attempt to extract the fallback address from the decoded ccm additional data. + /// Will only return Some(addr) if fallback address exists and matches the target `Chain`. + pub fn refund_address(&self) -> Option { + match self { + DecodedCcmAdditionalData::Solana(additional_data) => ForeignChainAddress::from( + SolAddress::from(additional_data.ccm_accounts().fallback_address), + ) + .try_into() + .ok(), + _ => None, + } + } +} + #[derive(Clone, Debug, Encode, Decode, PartialEq, Eq)] pub enum VersionedSolanaCcmAdditionalData { V0(SolCcmAccounts), @@ -141,6 +156,7 @@ impl CcmValidityCheck for CcmValidityChecker { let mut accounts_length = ccm_accounts.additional_accounts.len() * ACCOUNT_REFERENCE_LENGTH_IN_TRANSACTION; + // TODO PRO-2046: we should not check the length here? for ccm_address in &ccm_accounts.additional_accounts { if seen_addresses.insert(ccm_address.pubkey.into()) { accounts_length += ACCOUNT_KEY_LENGTH_IN_TRANSACTION; @@ -169,12 +185,14 @@ impl CcmValidityCheck for CcmValidityChecker { } } + /// Decodes the `ccm_additional_data` without any additional checks. + /// Only fail if given bytes cannot be decoded into `VersionedSolanaCcmAdditionalData`. fn decode_unchecked( - ccm: &CcmChannelMetadata, + ccm_additional_data: CcmAdditionalData, chain: ForeignChain, ) -> Result { if chain == ForeignChain::Solana { - VersionedSolanaCcmAdditionalData::decode(&mut &ccm.ccm_additional_data.clone()[..]) + VersionedSolanaCcmAdditionalData::decode(&mut &ccm_additional_data[..]) .map(DecodedCcmAdditionalData::Solana) .map_err(|_| CcmValidityError::CannotDecodeCcmAdditionalData) } else { @@ -596,9 +614,15 @@ mod test { #[test] fn can_decode_unchecked() { let ccm = sol_test_values::ccm_parameter().channel_metadata; - assert_ok!(CcmValidityChecker::decode_unchecked(&ccm, ForeignChain::Solana)); + assert_ok!(CcmValidityChecker::decode_unchecked( + ccm.ccm_additional_data.clone(), + ForeignChain::Solana + )); assert_eq!( - CcmValidityChecker::decode_unchecked(&ccm, ForeignChain::Ethereum), + CcmValidityChecker::decode_unchecked( + ccm.ccm_additional_data.clone(), + ForeignChain::Ethereum + ), Ok(DecodedCcmAdditionalData::NotRequired) ); } @@ -606,9 +630,15 @@ mod test { #[test] fn can_decode_unchecked_ccm_v1() { let ccm = sol_test_values::ccm_parameter_v1().channel_metadata; - assert_ok!(CcmValidityChecker::decode_unchecked(&ccm, ForeignChain::Solana)); + assert_ok!(CcmValidityChecker::decode_unchecked( + ccm.ccm_additional_data.clone(), + ForeignChain::Solana + )); assert_eq!( - CcmValidityChecker::decode_unchecked(&ccm, ForeignChain::Ethereum), + CcmValidityChecker::decode_unchecked( + ccm.ccm_additional_data.clone(), + ForeignChain::Ethereum + ), Ok(DecodedCcmAdditionalData::NotRequired) ); } diff --git a/state-chain/chains/src/sol/api.rs b/state-chain/chains/src/sol/api.rs index 016d83c2175..e59460b722e 100644 --- a/state-chain/chains/src/sol/api.rs +++ b/state-chain/chains/src/sol/api.rs @@ -663,8 +663,8 @@ impl ExecutexSwapAndCall for SolanaApi Self::ccm_transfer( transfer_param, source_chain, - // Hardcoding this to None to gain extra bytes in Solana. - // Revert this when we implement versioned Transactions. + // Hardcoding this to None to gain extra bytes in Solana. Consider + // reverting this when we implement versioned Transactions. PRO-2046. None, gas_budget, message, diff --git a/state-chain/pallets/cf-ingress-egress/src/lib.rs b/state-chain/pallets/cf-ingress-egress/src/lib.rs index d7cef8e46df..603d231c689 100644 --- a/state-chain/pallets/cf-ingress-egress/src/lib.rs +++ b/state-chain/pallets/cf-ingress-egress/src/lib.rs @@ -924,6 +924,11 @@ pub mod pallet { NetworkFeeDeductionFromBoostSet { deduction_percent: Percent, }, + InvalidCcmRefunded { + asset: TargetChainAsset, + amount: TargetChainAmount, + destination_address: TargetChainAccount, + }, } #[derive(CloneNoBound, PartialEqNoBound, EqNoBound)] @@ -1761,10 +1766,39 @@ impl, I: 'static> Pallet { egress_id: ccm.egress_id, }); }, - Err(error) => Self::deposit_event(Event::::CcmEgressInvalid { - egress_id: ccm.egress_id, - error, - }), + Err(error) => { + log::warn!("Failed to construct CCM. Fund will be refunded to the fallback refund address. swap_request_id: {:?}, Error: {:?}", ccm.swap_request_id, error); + + Self::deposit_event(Event::::CcmEgressInvalid { + egress_id: ccm.egress_id, + error, + }); + + if let Ok(decoded_data) = T::CcmValidityChecker::decode_unchecked( + ccm.ccm_additional_data.clone(), + T::TargetChain::get(), + ) { + if let Some(fallback_address) = + decoded_data.refund_address::() + { + match Self::schedule_egress( + ccm.asset, + ccm.amount, + fallback_address.clone(), + None, + ) { + Ok(egress_details) => Self::deposit_event(Event::::InvalidCcmRefunded { + asset: ccm.asset, + amount: egress_details.egress_amount, + destination_address: fallback_address, + }), + Err(e) => log::warn!("Cannot refund failed Ccm: failed to Egress. swap_request_id: {:?}, Error: {:?}", ccm.swap_request_id, e), + }; + } + } else { + log::warn!("Cannot refund failed Ccm: failed to decode `ccm_additional_data`. swap_request_id: {:?}", ccm.swap_request_id); + } + }, }; } }