Enforce tx metadata upload with static types (#23028)

This commit is contained in:
Justin Starry
2022-02-10 13:28:18 +08:00
committed by GitHub
parent 2ca7ae8e30
commit d5dec989b9
16 changed files with 482 additions and 440 deletions

View File

@ -388,7 +388,7 @@ pub struct Reward {
pub type Rewards = Vec<Reward>;
#[derive(Clone, Debug, Default, PartialEq)]
#[derive(Clone, Debug, PartialEq)]
pub struct ConfirmedBlock {
pub previous_blockhash: String,
pub blockhash: String,
@ -399,7 +399,9 @@ pub struct ConfirmedBlock {
pub block_height: Option<u64>,
}
#[derive(Clone, Debug, Default, PartialEq)]
// Confirmed block with type guarantees that transaction metadata
// is always present. Used for uploading to BigTable.
#[derive(Clone, Debug, PartialEq)]
pub struct VersionedConfirmedBlock {
pub previous_blockhash: String,
pub blockhash: String,
@ -410,11 +412,23 @@ pub struct VersionedConfirmedBlock {
pub block_height: Option<u64>,
}
impl VersionedConfirmedBlock {
// Confirmed block which only supports legacy transactions. Used
// until migration to versioned transactions is completed.
pub struct LegacyConfirmedBlock {
pub previous_blockhash: String,
pub blockhash: String,
pub parent_slot: Slot,
pub transactions: Vec<LegacyTransactionWithStatusMeta>,
pub rewards: Rewards,
pub block_time: Option<UnixTimestamp>,
pub block_height: Option<u64>,
}
impl ConfirmedBlock {
/// Downgrades a versioned block into a legacy block type
/// if it only contains legacy transactions
pub fn into_legacy_block(self) -> Option<ConfirmedBlock> {
Some(ConfirmedBlock {
pub fn into_legacy_block(self) -> Option<LegacyConfirmedBlock> {
Some(LegacyConfirmedBlock {
previous_blockhash: self.previous_blockhash,
blockhash: self.blockhash,
parent_slot: self.parent_slot,
@ -430,13 +444,17 @@ impl VersionedConfirmedBlock {
}
}
impl From<ConfirmedBlock> for VersionedConfirmedBlock {
fn from(block: ConfirmedBlock) -> Self {
VersionedConfirmedBlock {
impl From<VersionedConfirmedBlock> for ConfirmedBlock {
fn from(block: VersionedConfirmedBlock) -> Self {
Self {
previous_blockhash: block.previous_blockhash,
blockhash: block.blockhash,
parent_slot: block.parent_slot,
transactions: block.transactions.into_iter().map(|tx| tx.into()).collect(),
transactions: block
.transactions
.into_iter()
.map(TransactionWithStatusMeta::Complete)
.collect(),
rewards: block.rewards,
block_time: block.block_time,
block_height: block.block_height,
@ -444,7 +462,7 @@ impl From<ConfirmedBlock> for VersionedConfirmedBlock {
}
}
impl Encodable for ConfirmedBlock {
impl Encodable for LegacyConfirmedBlock {
type Encoded = EncodedConfirmedBlock;
fn encode(self, encoding: UiTransactionEncoding) -> Self::Encoded {
Self::Encoded {
@ -463,7 +481,7 @@ impl Encodable for ConfirmedBlock {
}
}
impl ConfirmedBlock {
impl LegacyConfirmedBlock {
pub fn configure(
self,
encoding: UiTransactionEncoding,
@ -565,44 +583,68 @@ impl From<EncodedConfirmedBlock> for UiConfirmedBlock {
}
}
#[derive(Clone, Debug, PartialEq)]
#[allow(clippy::large_enum_variant)]
pub enum TransactionWithStatusMeta {
// Very old transactions may be missing metadata
MissingMetadata(Transaction),
// Versioned stored transaction always have metadata
Complete(VersionedTransactionWithStatusMeta),
}
#[derive(Clone, Debug, PartialEq)]
pub struct VersionedTransactionWithStatusMeta {
pub transaction: VersionedTransaction,
pub meta: TransactionStatusMeta,
}
pub struct LegacyTransactionWithStatusMeta {
pub transaction: Transaction,
pub meta: Option<TransactionStatusMeta>,
}
impl TransactionWithStatusMeta {
pub fn transaction_signature(&self) -> &Signature {
match self {
Self::MissingMetadata(transaction) => &transaction.signatures[0],
Self::Complete(VersionedTransactionWithStatusMeta { transaction, .. }) => {
&transaction.signatures[0]
}
}
}
pub fn into_legacy_transaction_with_meta(self) -> Option<LegacyTransactionWithStatusMeta> {
match self {
TransactionWithStatusMeta::MissingMetadata(transaction) => {
Some(LegacyTransactionWithStatusMeta {
transaction,
meta: None,
})
}
TransactionWithStatusMeta::Complete(tx_with_meta) => {
tx_with_meta.into_legacy_transaction_with_meta()
}
}
}
}
impl VersionedTransactionWithStatusMeta {
pub fn account_keys(&self) -> AccountKeys {
AccountKeys::new(
self.transaction.message.static_account_keys(),
self.meta.as_ref().map(|meta| &meta.loaded_addresses),
Some(&self.meta.loaded_addresses),
)
}
pub fn into_legacy_transaction_with_meta(self) -> Option<TransactionWithStatusMeta> {
Some(TransactionWithStatusMeta {
pub fn into_legacy_transaction_with_meta(self) -> Option<LegacyTransactionWithStatusMeta> {
Some(LegacyTransactionWithStatusMeta {
transaction: self.transaction.into_legacy_transaction()?,
meta: self.meta,
meta: Some(self.meta),
})
}
}
impl From<TransactionWithStatusMeta> for VersionedTransactionWithStatusMeta {
fn from(tx_with_meta: TransactionWithStatusMeta) -> Self {
Self {
transaction: tx_with_meta.transaction.into(),
meta: tx_with_meta.meta,
}
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct TransactionWithStatusMeta {
pub transaction: Transaction,
pub meta: Option<TransactionStatusMeta>,
}
impl Encodable for TransactionWithStatusMeta {
impl Encodable for LegacyTransactionWithStatusMeta {
type Encoded = EncodedTransactionWithStatusMeta;
fn encode(self, encoding: UiTransactionEncoding) -> Self::Encoded {
Self::Encoded {
@ -627,21 +669,10 @@ pub struct EncodedTransactionWithStatusMeta {
#[derive(Debug, Clone, PartialEq)]
pub struct ConfirmedTransactionWithStatusMeta {
pub slot: Slot,
pub transaction: TransactionWithStatusMeta,
pub tx_with_meta: TransactionWithStatusMeta,
pub block_time: Option<UnixTimestamp>,
}
impl Encodable for ConfirmedTransactionWithStatusMeta {
type Encoded = EncodedConfirmedTransactionWithStatusMeta;
fn encode(self, encoding: UiTransactionEncoding) -> Self::Encoded {
Self::Encoded {
slot: self.slot,
transaction: self.transaction.encode(encoding),
block_time: self.block_time,
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct VersionedConfirmedTransactionWithStatusMeta {
pub slot: Slot,
@ -649,15 +680,31 @@ pub struct VersionedConfirmedTransactionWithStatusMeta {
pub block_time: Option<UnixTimestamp>,
}
impl VersionedConfirmedTransactionWithStatusMeta {
pub struct LegacyConfirmedTransactionWithStatusMeta {
pub slot: Slot,
pub tx_with_meta: LegacyTransactionWithStatusMeta,
pub block_time: Option<UnixTimestamp>,
}
impl Encodable for LegacyConfirmedTransactionWithStatusMeta {
type Encoded = EncodedConfirmedTransactionWithStatusMeta;
fn encode(self, encoding: UiTransactionEncoding) -> Self::Encoded {
Self::Encoded {
slot: self.slot,
transaction: self.tx_with_meta.encode(encoding),
block_time: self.block_time,
}
}
}
impl ConfirmedTransactionWithStatusMeta {
/// Downgrades a versioned confirmed transaction into a legacy
/// confirmed transaction if it contains a legacy transaction.
pub fn into_legacy_confirmed_transaction(self) -> Option<ConfirmedTransactionWithStatusMeta> {
Some(ConfirmedTransactionWithStatusMeta {
transaction: TransactionWithStatusMeta {
transaction: self.tx_with_meta.transaction.into_legacy_transaction()?,
meta: self.tx_with_meta.meta,
},
pub fn into_legacy_confirmed_transaction(
self,
) -> Option<LegacyConfirmedTransactionWithStatusMeta> {
Some(LegacyConfirmedTransactionWithStatusMeta {
tx_with_meta: self.tx_with_meta.into_legacy_transaction_with_meta()?,
block_time: self.block_time,
slot: self.slot,
})