feat: add TransactionStatus column family and test (#6958)
This commit is contained in:
parent
c1b06817a2
commit
086e5da8d0
|
@ -68,6 +68,7 @@ pub struct Blocktree {
|
|||
index_cf: LedgerColumn<cf::Index>,
|
||||
data_shred_cf: LedgerColumn<cf::ShredData>,
|
||||
code_shred_cf: LedgerColumn<cf::ShredCode>,
|
||||
transaction_status_cf: LedgerColumn<cf::TransactionStatus>,
|
||||
last_root: Arc<RwLock<u64>>,
|
||||
insert_shreds_lock: Arc<Mutex<()>>,
|
||||
pub new_shreds_signals: Vec<SyncSender<bool>>,
|
||||
|
@ -171,6 +172,7 @@ impl Blocktree {
|
|||
|
||||
let data_shred_cf = db.column();
|
||||
let code_shred_cf = db.column();
|
||||
let transaction_status_cf = db.column();
|
||||
|
||||
let db = Arc::new(db);
|
||||
|
||||
|
@ -192,6 +194,7 @@ impl Blocktree {
|
|||
index_cf,
|
||||
data_shred_cf,
|
||||
code_shred_cf,
|
||||
transaction_status_cf,
|
||||
new_shreds_signals: vec![],
|
||||
completed_slots_senders: vec![],
|
||||
insert_shreds_lock: Arc::new(Mutex::new(())),
|
||||
|
@ -283,6 +286,10 @@ impl Blocktree {
|
|||
.code_shred_cf
|
||||
.delete_slot(&mut write_batch, from_slot, batch_end)
|
||||
.unwrap_or(false)
|
||||
&& self
|
||||
.transaction_status_cf
|
||||
.delete_slot(&mut write_batch, from_slot, batch_end)
|
||||
.unwrap_or(false)
|
||||
&& self
|
||||
.orphans_cf
|
||||
.delete_slot(&mut write_batch, from_slot, batch_end)
|
||||
|
@ -1985,6 +1992,7 @@ pub mod tests {
|
|||
use rand::{seq::SliceRandom, thread_rng};
|
||||
use solana_sdk::{
|
||||
hash::Hash, instruction::CompiledInstruction, packet::PACKET_DATA_SIZE, pubkey::Pubkey,
|
||||
signature::Signature, transaction::TransactionError,
|
||||
};
|
||||
use std::{iter::FromIterator, time::Duration};
|
||||
|
||||
|
@ -4071,4 +4079,59 @@ pub mod tests {
|
|||
drop(ledger);
|
||||
Blocktree::destroy(&ledger_path).expect("Expected successful database destruction");
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_persist_transaction_status() {
|
||||
let blocktree_path = get_tmp_ledger_path!();
|
||||
{
|
||||
let blocktree = Blocktree::open(&blocktree_path).unwrap();
|
||||
let transaction_status_cf = blocktree.db.column::<cf::TransactionStatus>();
|
||||
|
||||
// result not found
|
||||
assert!(transaction_status_cf
|
||||
.get((0, Signature::default()))
|
||||
.unwrap()
|
||||
.is_none());
|
||||
|
||||
// insert value
|
||||
assert!(transaction_status_cf
|
||||
.put(
|
||||
(0, Signature::default()),
|
||||
&(
|
||||
solana_sdk::transaction::Result::<()>::Err(
|
||||
TransactionError::AccountNotFound
|
||||
),
|
||||
5u64
|
||||
)
|
||||
)
|
||||
.is_ok());
|
||||
|
||||
// result found
|
||||
let (status, fee) = transaction_status_cf
|
||||
.get((0, Signature::default()))
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
assert_eq!(status, Err(TransactionError::AccountNotFound));
|
||||
assert_eq!(fee, 5u64);
|
||||
|
||||
// insert value
|
||||
assert!(transaction_status_cf
|
||||
.put(
|
||||
(9, Signature::default()),
|
||||
&(solana_sdk::transaction::Result::<()>::Ok(()), 9u64)
|
||||
)
|
||||
.is_ok());
|
||||
|
||||
// result found
|
||||
let (status, fee) = transaction_status_cf
|
||||
.get((9, Signature::default()))
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
||||
// deserialize
|
||||
assert_eq!(status, Ok(()));
|
||||
assert_eq!(fee, 9u64);
|
||||
}
|
||||
Blocktree::destroy(&blocktree_path).expect("Expected successful database destruction");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ use rocksdb::{
|
|||
};
|
||||
use serde::de::DeserializeOwned;
|
||||
use serde::Serialize;
|
||||
use solana_sdk::clock::Slot;
|
||||
use solana_sdk::{clock::Slot, signature::Signature};
|
||||
use std::collections::HashMap;
|
||||
use std::fs;
|
||||
use std::marker::PhantomData;
|
||||
|
@ -35,6 +35,8 @@ const INDEX_CF: &str = "index";
|
|||
const DATA_SHRED_CF: &str = "data_shred";
|
||||
/// Column family for Code Shreds
|
||||
const CODE_SHRED_CF: &str = "code_shred";
|
||||
/// Column family for Transaction Status
|
||||
const TRANSACTION_STATUS_CF: &str = "transaction_status";
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum BlocktreeError {
|
||||
|
@ -111,6 +113,10 @@ pub mod columns {
|
|||
#[derive(Debug)]
|
||||
/// The shred erasure code column
|
||||
pub struct ShredCode;
|
||||
|
||||
#[derive(Debug)]
|
||||
/// The transaction status column
|
||||
pub struct TransactionStatus;
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -120,6 +126,7 @@ impl Rocks {
|
|||
fn open(path: &Path) -> Result<Rocks> {
|
||||
use columns::{
|
||||
DeadSlots, ErasureMeta, Index, Orphans, Root, ShredCode, ShredData, SlotMeta,
|
||||
TransactionStatus,
|
||||
};
|
||||
|
||||
fs::create_dir_all(&path)?;
|
||||
|
@ -140,6 +147,8 @@ impl Rocks {
|
|||
ColumnFamilyDescriptor::new(ShredData::NAME, get_cf_options());
|
||||
let shred_code_cf_descriptor =
|
||||
ColumnFamilyDescriptor::new(ShredCode::NAME, get_cf_options());
|
||||
let transaction_status_cf_descriptor =
|
||||
ColumnFamilyDescriptor::new(TransactionStatus::NAME, get_cf_options());
|
||||
|
||||
let cfs = vec![
|
||||
meta_cf_descriptor,
|
||||
|
@ -150,6 +159,7 @@ impl Rocks {
|
|||
index_cf_descriptor,
|
||||
shred_data_cf_descriptor,
|
||||
shred_code_cf_descriptor,
|
||||
transaction_status_cf_descriptor,
|
||||
];
|
||||
|
||||
// Open the database
|
||||
|
@ -161,6 +171,7 @@ impl Rocks {
|
|||
fn columns(&self) -> Vec<&'static str> {
|
||||
use columns::{
|
||||
DeadSlots, ErasureMeta, Index, Orphans, Root, ShredCode, ShredData, SlotMeta,
|
||||
TransactionStatus,
|
||||
};
|
||||
|
||||
vec![
|
||||
|
@ -172,6 +183,7 @@ impl Rocks {
|
|||
SlotMeta::NAME,
|
||||
ShredData::NAME,
|
||||
ShredCode::NAME,
|
||||
TransactionStatus::NAME,
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -248,6 +260,36 @@ pub trait TypedColumn: Column {
|
|||
type Type: Serialize + DeserializeOwned;
|
||||
}
|
||||
|
||||
impl TypedColumn for columns::TransactionStatus {
|
||||
type Type = (solana_sdk::transaction::Result<()>, u64);
|
||||
}
|
||||
|
||||
impl Column for columns::TransactionStatus {
|
||||
const NAME: &'static str = TRANSACTION_STATUS_CF;
|
||||
type Index = (Slot, Signature);
|
||||
|
||||
fn key((slot, index): (Slot, Signature)) -> Vec<u8> {
|
||||
let mut key = vec![0; 8 + 64];
|
||||
BigEndian::write_u64(&mut key[..8], slot);
|
||||
key[8..72].clone_from_slice(&index.as_ref()[0..64]);
|
||||
key
|
||||
}
|
||||
|
||||
fn index<'a>(key: &[u8]) -> (Slot, Signature) {
|
||||
let slot = BigEndian::read_u64(&key[..8]);
|
||||
let index = Signature::new(&key[8..72]);
|
||||
(slot, index)
|
||||
}
|
||||
|
||||
fn slot(index: Self::Index) -> Slot {
|
||||
index.0
|
||||
}
|
||||
|
||||
fn as_index(slot: Slot) -> Self::Index {
|
||||
(slot, Signature::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl Column for columns::ShredCode {
|
||||
const NAME: &'static str = CODE_SHRED_CF;
|
||||
type Index = (u64, u64);
|
||||
|
|
Loading…
Reference in New Issue