This repository has been archived by the owner on Jan 22, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 4.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
create separate structs for runtime in different state, add corespond…
…ing traits for transacion_meta
- Loading branch information
1 parent
e38adf7
commit 294382c
Showing
4 changed files
with
135 additions
and
56 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,72 +1,130 @@ | ||
use { | ||
crate::{ | ||
simple_vote_transaction_checker::is_simple_vote_transaction, transaction_meta::TransactionMeta, | ||
simple_vote_transaction_checker::is_simple_vote_transaction, | ||
transaction_meta::{DynamicMeta, StaticMeta, TransactionMeta}, | ||
}, | ||
solana_sdk::{ | ||
hash::Hash, | ||
message::{ | ||
v0::{self}, | ||
AddressLoader, LegacyMessage, SanitizedMessage, SanitizedVersionedMessage, | ||
VersionedMessage, | ||
}, | ||
message::{AddressLoader, SanitizedMessage, SanitizedVersionedMessage}, | ||
signature::Signature, | ||
transaction::{MessageHash, Result, SanitizedVersionedTransaction}, | ||
transaction::{Result, SanitizedVersionedTransaction}, | ||
}, | ||
}; | ||
|
||
/// RuntimeTransaction is runtime face representation of transaction, as | ||
/// SanitizedTransaction is client facing rep. | ||
/// RuntimeTransaction is `runtime` facing representation of transaction, while | ||
/// solana_sdk::SanitizedTransaction is client facing representation. | ||
/// | ||
/// 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. | ||
/// 2. Dynamically Loaded: after successfully loaded account addresses from onchain | ||
/// ALT, RuntimeTransaction transits into Dynamically Loaded state, with | ||
/// its dynamic metadata loaded. | ||
#[derive(Debug, Clone, Eq, PartialEq)] | ||
pub struct RuntimeTransaction { | ||
message: SanitizedMessage, | ||
message_hash: Hash, | ||
pub struct RuntimeTransactionStatic { | ||
// sanitized signatures | ||
signatures: Vec<Signature>, | ||
transaction_meta: TransactionMeta, | ||
|
||
// sanitized message | ||
message: SanitizedVersionedMessage, | ||
|
||
// transaction meta is a collection of fields, it is updated | ||
// during message state transition | ||
meta: TransactionMeta, | ||
} | ||
|
||
impl RuntimeTransaction { | ||
/// Create a runtime transaction from a sanitized versioend transaction, | ||
/// then load account addresses from address-lookup-table if apply, and | ||
/// populate transaction metadata. | ||
pub fn try_new( | ||
// Note: transaction sanitization is a function of `sdk` that is shared | ||
// by both runtime and client. | ||
impl StaticMeta for RuntimeTransactionStatic { | ||
fn message_hash(&self) -> &Hash { | ||
&self.meta.message_hash | ||
} | ||
fn is_simple_vote_tx(&self) -> bool { | ||
self.meta.is_simple_vote_tx | ||
} | ||
} | ||
|
||
impl RuntimeTransactionStatic { | ||
pub fn try_from( | ||
sanitized_versioned_tx: SanitizedVersionedTransaction, | ||
message_hash: impl Into<MessageHash>, | ||
message_hash: Option<Hash>, | ||
is_simple_vote_tx: Option<bool>, | ||
address_loader: impl AddressLoader, | ||
) -> Result<Self> { | ||
// metadata can be lazily updated alone transaction's execution path | ||
let mut transaction_meta = TransactionMeta::default(); | ||
transaction_meta.set_is_simple_vote_tx(is_simple_vote_tx.unwrap_or_else(|| { | ||
is_simple_vote_transaction(&sanitized_versioned_tx) | ||
})); | ||
let meta = | ||
Self::load_static_metadata(&sanitized_versioned_tx, message_hash, is_simple_vote_tx)?; | ||
|
||
let signatures = sanitized_versioned_tx.signatures; | ||
Ok(Self { | ||
signatures: sanitized_versioned_tx.signatures, | ||
message: sanitized_versioned_tx.message, | ||
meta, | ||
}) | ||
} | ||
|
||
// private helpers | ||
fn load_static_metadata( | ||
sanitized_versioned_tx: &SanitizedVersionedTransaction, | ||
message_hash: Option<Hash>, | ||
is_simple_vote_tx: Option<bool>, | ||
) -> Result<TransactionMeta> { | ||
let mut meta = TransactionMeta::default(); | ||
meta.set_is_simple_vote_tx( | ||
is_simple_vote_tx.unwrap_or_else(|| is_simple_vote_transaction(sanitized_versioned_tx)), | ||
); | ||
meta.set_message_hash( | ||
message_hash.unwrap_or_else(|| sanitized_versioned_tx.message.message.hash()), | ||
); | ||
|
||
let SanitizedVersionedMessage { message } = sanitized_versioned_tx.message; | ||
Ok(meta) | ||
} | ||
} | ||
|
||
let message_hash = match message_hash.into() { | ||
MessageHash::Compute => message.hash(), | ||
MessageHash::Precomputed(hash) => hash, | ||
}; | ||
/// 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 { | ||
// sanitized signatures | ||
signatures: Vec<Signature>, | ||
|
||
let message = match message { | ||
VersionedMessage::Legacy(message) => { | ||
SanitizedMessage::Legacy(LegacyMessage::new(message)) | ||
} | ||
VersionedMessage::V0(message) => { | ||
let loaded_addresses = | ||
address_loader.load_addresses(&message.address_table_lookups)?; | ||
SanitizedMessage::V0(v0::LoadedMessage::new(message, loaded_addresses)) | ||
} | ||
// sanitized message | ||
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 { | ||
pub fn try_from( | ||
statically_loaded_runtime_tx: RuntimeTransactionStatic, | ||
address_loader: impl AddressLoader, | ||
) -> Result<Self> { | ||
let mut tx = Self { | ||
signatures: statically_loaded_runtime_tx.signatures, | ||
message: SanitizedMessage::try_new( | ||
statically_loaded_runtime_tx.message, | ||
address_loader, | ||
)?, | ||
meta: statically_loaded_runtime_tx.meta, | ||
}; | ||
tx.load_dynamic_metadata()?; | ||
|
||
Ok(Self { | ||
message, | ||
message_hash, | ||
signatures, | ||
transaction_meta, | ||
}) | ||
Ok(tx) | ||
} | ||
|
||
// private helpers | ||
fn load_dynamic_metadata(&mut self) -> Result<()> { | ||
Ok(()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters