Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

generalize message type for runtime-transaction #34276

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 53 additions & 34 deletions runtime-transaction/src/runtime_transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<SanitizedMessage> transits into Dynamically Loaded state,
//! with its dynamic metadata loaded.
use {
crate::transaction_meta::{DynamicMeta, StaticMeta, TransactionMeta},
solana_sdk::{
Expand All @@ -21,15 +21,27 @@ use {
};

#[derive(Debug, Clone, Eq, PartialEq)]
pub struct RuntimeTransactionStatic {
pub struct RuntimeTransaction<M> {
signatures: Vec<Signature>,
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<M: StaticMetaAccess> StaticMeta for RuntimeTransaction<M> {
fn message_hash(&self) -> &Hash {
&self.meta.message_hash
}
Expand All @@ -38,7 +50,9 @@ impl StaticMeta for RuntimeTransactionStatic {
}
}

impl RuntimeTransactionStatic {
impl<M: DynamicMetaAccess> DynamicMeta for RuntimeTransaction<M> {}

impl RuntimeTransaction<SanitizedVersionedMessage> {
pub fn try_from(
sanitized_versioned_tx: SanitizedVersionedTransaction,
message_hash: Option<Hash>,
Expand All @@ -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<Signature>,
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<SanitizedMessage> {
pub fn try_from(
statically_loaded_runtime_tx: RuntimeTransactionStatic,
statically_loaded_runtime_tx: RuntimeTransaction<SanitizedVersionedMessage>,
address_loader: impl AddressLoader,
) -> Result<Self> {
let mut tx = Self {
Expand Down Expand Up @@ -119,7 +111,7 @@ mod tests {
compute_budget::ComputeBudgetInstruction,
message::Message,
signer::{keypair::Keypair, Signer},
transaction::{Transaction, VersionedTransaction},
transaction::{SimpleAddressLoader, Transaction, VersionedTransaction},
},
};

Expand Down Expand Up @@ -161,7 +153,7 @@ mod tests {
hash: Option<Hash>,
is_simple_vote: Option<bool>,
) -> TransactionMeta {
RuntimeTransactionStatic::try_from(svt, hash, is_simple_vote)
RuntimeTransaction::<SanitizedVersionedMessage>::try_from(svt, hash, is_simple_vote)
.unwrap()
.meta
}
Expand Down Expand Up @@ -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::<SanitizedVersionedMessage>::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::<SanitizedMessage>::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());
}
}