From f6403e3595ce5b99141b1ed5c7ccc8dbf9f796c8 Mon Sep 17 00:00:00 2001 From: Tao Zhu <82401714+taozhu-chicago@users.noreply.github.com> Date: Thu, 7 Dec 2023 09:51:14 -0600 Subject: [PATCH] generalize message type for runtime-transaction (#34276) * generalize message type for runtime-transaction * Trait bounds TransactionMeta traits implementation --- .../src/runtime_transaction.rs | 87 +++++++++++-------- 1 file changed, 53 insertions(+), 34 deletions(-) diff --git a/runtime-transaction/src/runtime_transaction.rs b/runtime-transaction/src/runtime_transaction.rs index ef8bbbe1e7..df6acbccdd 100644 --- a/runtime-transaction/src/runtime_transaction.rs +++ b/runtime-transaction/src/runtime_transaction.rs @@ -4,11 +4,11 @@ //! It has two states: //! 1. Statically Loaded: after receiving `packet` from sigverify and deserializing //! it into `solana_sdk::VersionedTransaction`, then sanitizing into -//! `solana_sdk::SanitizedVersionedTransaction`, `RuntimeTransactionStatic` -//! can be created from it with static transaction metadata extracted. +//! `solana_sdk::SanitizedVersionedTransaction`, which can be wrapped into +//! `RuntimeTransaction` with static transaction metadata extracted. //! 2. Dynamically Loaded: after successfully loaded account addresses from onchain -//! ALT, RuntimeTransaction transits into Dynamically Loaded state, with -//! its dynamic metadata loaded. +//! ALT, RuntimeTransaction transits into Dynamically Loaded state, +//! with its dynamic metadata loaded. use { crate::transaction_meta::{DynamicMeta, StaticMeta, TransactionMeta}, solana_sdk::{ @@ -21,15 +21,27 @@ use { }; #[derive(Debug, Clone, Eq, PartialEq)] -pub struct RuntimeTransactionStatic { +pub struct RuntimeTransaction { signatures: Vec, - message: SanitizedVersionedMessage, + message: M, // transaction meta is a collection of fields, it is updated // during message state transition meta: TransactionMeta, } -impl StaticMeta for RuntimeTransactionStatic { +// These traits gate access to static and dynamic metadata +// so that only transactions with supporting message types +// can access them. +trait StaticMetaAccess {} +trait DynamicMetaAccess: StaticMetaAccess {} + +// Implement the gate traits for the message types that should +// have access to the static and dynamic metadata. +impl StaticMetaAccess for SanitizedVersionedMessage {} +impl StaticMetaAccess for SanitizedMessage {} +impl DynamicMetaAccess for SanitizedMessage {} + +impl StaticMeta for RuntimeTransaction { fn message_hash(&self) -> &Hash { &self.meta.message_hash } @@ -38,7 +50,9 @@ impl StaticMeta for RuntimeTransactionStatic { } } -impl RuntimeTransactionStatic { +impl DynamicMeta for RuntimeTransaction {} + +impl RuntimeTransaction { pub fn try_from( sanitized_versioned_tx: SanitizedVersionedTransaction, message_hash: Option, @@ -62,31 +76,9 @@ impl RuntimeTransactionStatic { } } -/// Statically Loaded transaction can transit to Dynamically Loaded with supplied -/// address_loader, to load accounts from on-chain ALT, then resolve dynamic metadata -#[derive(Debug, Clone, Eq, PartialEq)] -pub struct RuntimeTransactionDynamic { - signatures: Vec, - message: SanitizedMessage, - // transaction meta is a collection of fields, it is updated - // during message state transition - meta: TransactionMeta, -} - -impl DynamicMeta for RuntimeTransactionDynamic {} - -impl StaticMeta for RuntimeTransactionDynamic { - fn message_hash(&self) -> &Hash { - &self.meta.message_hash - } - fn is_simple_vote_tx(&self) -> bool { - self.meta.is_simple_vote_tx - } -} - -impl RuntimeTransactionDynamic { +impl RuntimeTransaction { pub fn try_from( - statically_loaded_runtime_tx: RuntimeTransactionStatic, + statically_loaded_runtime_tx: RuntimeTransaction, address_loader: impl AddressLoader, ) -> Result { let mut tx = Self { @@ -119,7 +111,7 @@ mod tests { compute_budget::ComputeBudgetInstruction, message::Message, signer::{keypair::Keypair, Signer}, - transaction::{Transaction, VersionedTransaction}, + transaction::{SimpleAddressLoader, Transaction, VersionedTransaction}, }, }; @@ -161,7 +153,7 @@ mod tests { hash: Option, is_simple_vote: Option, ) -> TransactionMeta { - RuntimeTransactionStatic::try_from(svt, hash, is_simple_vote) + RuntimeTransaction::::try_from(svt, hash, is_simple_vote) .unwrap() .meta } @@ -215,4 +207,31 @@ mod tests { ) ); } + + #[test] + fn test_advance_transaction_type() { + let hash = Hash::new_unique(); + let compute_unit_price = 999; + + let statically_loaded_transaction = + RuntimeTransaction::::try_from( + non_vote_sanitized_versioned_transaction(compute_unit_price), + Some(hash), + None, + ) + .unwrap(); + + assert_eq!(hash, *statically_loaded_transaction.message_hash()); + assert!(!statically_loaded_transaction.is_simple_vote_tx()); + + let dynamically_loaded_transaction = RuntimeTransaction::::try_from( + statically_loaded_transaction, + SimpleAddressLoader::Disabled, + ); + let dynamically_loaded_transaction = + dynamically_loaded_transaction.expect("created from statically loaded tx"); + + assert_eq!(hash, *dynamically_loaded_transaction.message_hash()); + assert!(!dynamically_loaded_transaction.is_simple_vote_tx()); + } }