Skip to content

Commit 450404f

Browse files
authored
v1.9: Enforce tx metadata upload to bigtable (solana-labs#23212)
* Enforce tx metadata upload with static types (solana-labs#23028) * resolve conflicts * fix test
1 parent 8413700 commit 450404f

File tree

16 files changed

+367
-320
lines changed

16 files changed

+367
-320
lines changed

client-test/tests/client.rs

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use {
88
RpcAccountInfoConfig, RpcBlockSubscribeConfig, RpcBlockSubscribeFilter,
99
RpcProgramAccountsConfig,
1010
},
11-
rpc_response::{RpcBlockUpdate, SlotInfo},
11+
rpc_response::SlotInfo,
1212
},
1313
solana_ledger::{blockstore::Blockstore, get_tmp_ledger_path},
1414
solana_rpc::{
@@ -34,7 +34,9 @@ use {
3434
},
3535
solana_streamer::socket::SocketAddrSpace,
3636
solana_test_validator::TestValidator,
37-
solana_transaction_status::{TransactionDetails, UiTransactionEncoding},
37+
solana_transaction_status::{
38+
ConfirmedBlockWithOptionalMetadata, TransactionDetails, UiTransactionEncoding,
39+
},
3840
std::{
3941
collections::HashSet,
4042
net::{IpAddr, SocketAddr},
@@ -212,6 +214,7 @@ fn test_block_subscription() {
212214
..
213215
} = create_genesis_config(10_000);
214216
let bank = Bank::new_for_tests(&genesis_config);
217+
let rent_exempt_amount = bank.get_minimum_balance_for_rent_exemption(0);
215218
let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
216219

217220
// setup Blockstore
@@ -225,6 +228,8 @@ fn test_block_subscription() {
225228
let keypair2 = Keypair::new();
226229
let keypair3 = Keypair::new();
227230
let max_complete_transaction_status_slot = Arc::new(AtomicU64::new(blockstore.max_root()));
231+
bank.transfer(rent_exempt_amount, &alice, &keypair2.pubkey())
232+
.unwrap();
228233
let _confirmed_block_signatures = create_test_transactions_and_populate_blockstore(
229234
vec![&alice, &keypair1, &keypair2, &keypair3],
230235
0,
@@ -276,22 +281,12 @@ fn test_block_subscription() {
276281
match maybe_actual {
277282
Ok(actual) => {
278283
let complete_block = blockstore.get_complete_block(slot, false).unwrap();
279-
let block = complete_block.clone().configure(
280-
UiTransactionEncoding::Json,
281-
TransactionDetails::Signatures,
282-
false,
283-
);
284-
let expected = RpcBlockUpdate {
285-
slot,
286-
block: Some(block),
287-
err: None,
288-
};
289-
let block = complete_block.configure(
284+
let block = ConfirmedBlockWithOptionalMetadata::from(complete_block).configure(
290285
UiTransactionEncoding::Json,
291286
TransactionDetails::Signatures,
292287
false,
293288
);
294-
assert_eq!(actual.value.slot, expected.slot);
289+
assert_eq!(actual.value.slot, slot);
295290
assert!(block.eq(&actual.value.block.unwrap()));
296291
}
297292
Err(e) => {

core/src/banking_stage.rs

Lines changed: 27 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -2067,7 +2067,7 @@ mod tests {
20672067
transaction::{Transaction, TransactionError},
20682068
},
20692069
solana_streamer::{recvmmsg::recv_mmsg, socket::SocketAddrSpace},
2070-
solana_transaction_status::TransactionWithStatusMeta,
2070+
solana_transaction_status::TransactionWithMetadata,
20712071
solana_vote_program::vote_transaction,
20722072
std::{
20732073
net::SocketAddr,
@@ -3223,39 +3223,23 @@ mod tests {
32233223
genesis_config.rent.lamports_per_byte_year = 50;
32243224
genesis_config.rent.exemption_threshold = 2.0;
32253225
let bank = Arc::new(Bank::new_no_wallclock_throttle_for_tests(&genesis_config));
3226+
let rent_exempt_minimum = bank.get_minimum_balance_for_rent_exemption(0);
32263227
let pubkey = solana_sdk::pubkey::new_rand();
32273228
let pubkey1 = solana_sdk::pubkey::new_rand();
32283229
let keypair1 = Keypair::new();
32293230

3230-
let rent_exempt_amount = bank.get_minimum_balance_for_rent_exemption(0);
3231-
3232-
let success_tx = system_transaction::transfer(
3233-
&mint_keypair,
3234-
&pubkey,
3235-
rent_exempt_amount,
3236-
genesis_config.hash(),
3237-
);
3231+
let success_tx =
3232+
system_transaction::transfer(&mint_keypair, &pubkey, 0, genesis_config.hash());
32383233
let success_signature = success_tx.signatures[0];
32393234
let entry_1 = next_entry(&genesis_config.hash(), 1, vec![success_tx.clone()]);
3240-
let ix_error_tx = system_transaction::transfer(
3241-
&keypair1,
3242-
&pubkey1,
3243-
2 * rent_exempt_amount,
3244-
genesis_config.hash(),
3245-
);
3235+
let ix_error_tx =
3236+
system_transaction::transfer(&keypair1, &pubkey1, std::u64::MAX, genesis_config.hash());
32463237
let ix_error_signature = ix_error_tx.signatures[0];
32473238
let entry_2 = next_entry(&entry_1.hash, 1, vec![ix_error_tx.clone()]);
3248-
let fail_tx = system_transaction::transfer(
3249-
&mint_keypair,
3250-
&pubkey1,
3251-
rent_exempt_amount,
3252-
genesis_config.hash(),
3253-
);
3254-
let entry_3 = next_entry(&entry_2.hash, 1, vec![fail_tx.clone()]);
3255-
let entries = vec![entry_1, entry_2, entry_3];
3239+
let entries = vec![entry_1, entry_2];
32563240

3257-
let transactions = sanitize_transactions(vec![success_tx, ix_error_tx, fail_tx]);
3258-
bank.transfer(rent_exempt_amount, &mint_keypair, &keypair1.pubkey())
3241+
let transactions = sanitize_transactions(vec![success_tx, ix_error_tx]);
3242+
bank.transfer(rent_exempt_minimum, &mint_keypair, &keypair1.pubkey())
32593243
.unwrap();
32603244

32613245
let ledger_path = get_tmp_ledger_path_auto_delete!();
@@ -3314,27 +3298,24 @@ mod tests {
33143298
transaction_status_service.join().unwrap();
33153299

33163300
let confirmed_block = blockstore.get_rooted_block(bank.slot(), false).unwrap();
3317-
assert_eq!(confirmed_block.transactions.len(), 3);
3318-
3319-
for TransactionWithStatusMeta { transaction, meta } in
3320-
confirmed_block.transactions.into_iter()
3321-
{
3322-
if transaction.signatures[0] == success_signature {
3323-
let meta = meta.unwrap();
3324-
assert_eq!(meta.status, Ok(()));
3325-
} else if transaction.signatures[0] == ix_error_signature {
3326-
let meta = meta.unwrap();
3327-
assert_eq!(
3328-
meta.status,
3329-
Err(TransactionError::InstructionError(
3330-
0,
3331-
InstructionError::Custom(1)
3332-
))
3333-
);
3334-
} else {
3335-
assert_eq!(meta, None);
3336-
}
3337-
}
3301+
let actual_tx_results: Vec<_> = confirmed_block
3302+
.transactions
3303+
.into_iter()
3304+
.map(|TransactionWithMetadata { transaction, meta }| {
3305+
(transaction.signatures[0], meta.status)
3306+
})
3307+
.collect();
3308+
let expected_tx_results = vec![
3309+
(success_signature, Ok(())),
3310+
(
3311+
ix_error_signature,
3312+
Err(TransactionError::InstructionError(
3313+
0,
3314+
InstructionError::Custom(1),
3315+
)),
3316+
),
3317+
];
3318+
assert_eq!(actual_tx_results, expected_tx_results);
33383319

33393320
poh_recorder
33403321
.lock()

core/src/replay_stage.rs

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3021,7 +3021,7 @@ pub mod tests {
30213021
transaction::TransactionError,
30223022
},
30233023
solana_streamer::socket::SocketAddrSpace,
3024-
solana_transaction_status::TransactionWithStatusMeta,
3024+
solana_transaction_status::TransactionWithMetadata,
30253025
solana_vote_program::{
30263026
vote_state::{VoteState, VoteStateVersions},
30273027
vote_transaction,
@@ -3871,36 +3871,35 @@ pub mod tests {
38713871
let bank1 = Arc::new(Bank::new_from_parent(&bank0, &Pubkey::default(), 1));
38723872
let slot = bank1.slot();
38733873

3874-
let signatures = create_test_transactions_and_populate_blockstore(
3874+
let mut test_signatures_iter = create_test_transactions_and_populate_blockstore(
38753875
vec![&mint_keypair, &keypair1, &keypair2, &keypair3],
38763876
bank0.slot(),
38773877
bank1,
38783878
blockstore.clone(),
38793879
Arc::new(AtomicU64::default()),
3880-
);
3880+
)
3881+
.into_iter();
38813882

38823883
let confirmed_block = blockstore.get_rooted_block(slot, false).unwrap();
3883-
assert_eq!(confirmed_block.transactions.len(), 3);
3884-
3885-
for TransactionWithStatusMeta { transaction, meta } in
3886-
confirmed_block.transactions.into_iter()
3887-
{
3888-
if transaction.signatures[0] == signatures[0] {
3889-
let meta = meta.unwrap();
3890-
assert_eq!(meta.status, Ok(()));
3891-
} else if transaction.signatures[0] == signatures[1] {
3892-
let meta = meta.unwrap();
3893-
assert_eq!(
3894-
meta.status,
3895-
Err(TransactionError::InstructionError(
3896-
0,
3897-
InstructionError::Custom(1)
3898-
))
3899-
);
3900-
} else {
3901-
assert_eq!(meta, None);
3902-
}
3903-
}
3884+
let actual_tx_results: Vec<_> = confirmed_block
3885+
.transactions
3886+
.into_iter()
3887+
.map(|TransactionWithMetadata { transaction, meta }| {
3888+
(transaction.signatures[0], meta.status)
3889+
})
3890+
.collect();
3891+
let expected_tx_results = vec![
3892+
(test_signatures_iter.next().unwrap(), Ok(())),
3893+
(
3894+
test_signatures_iter.next().unwrap(),
3895+
Err(TransactionError::InstructionError(
3896+
0,
3897+
InstructionError::Custom(1),
3898+
)),
3899+
),
3900+
];
3901+
assert_eq!(actual_tx_results, expected_tx_results);
3902+
assert!(test_signatures_iter.next().is_none());
39043903
}
39053904
Blockstore::destroy(&ledger_path).unwrap();
39063905
}

ledger-tool/src/bigtable.rs

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ use {
1616
},
1717
solana_ledger::{blockstore::Blockstore, blockstore_db::AccessType},
1818
solana_sdk::{clock::Slot, pubkey::Pubkey, signature::Signature},
19-
solana_transaction_status::{ConfirmedBlock, EncodedTransaction, UiTransactionEncoding},
19+
solana_transaction_status::{
20+
ConfirmedBlockWithOptionalMetadata, EncodedTransaction, UiTransactionEncoding,
21+
},
2022
std::{
2123
collections::HashSet,
2224
path::Path,
@@ -30,7 +32,6 @@ async fn upload(
3032
blockstore: Blockstore,
3133
starting_slot: Slot,
3234
ending_slot: Option<Slot>,
33-
allow_missing_metadata: bool,
3435
force_reupload: bool,
3536
) -> Result<(), Box<dyn std::error::Error>> {
3637
let bigtable = solana_storage_bigtable::LedgerStorage::new(false, None, None)
@@ -42,7 +43,6 @@ async fn upload(
4243
bigtable,
4344
starting_slot,
4445
ending_slot,
45-
allow_missing_metadata,
4646
force_reupload,
4747
Arc::new(AtomicBool::new(false)),
4848
)
@@ -194,7 +194,7 @@ pub async fn transaction_history(
194194
) -> Result<(), Box<dyn std::error::Error>> {
195195
let bigtable = solana_storage_bigtable::LedgerStorage::new(true, None, None).await?;
196196

197-
let mut loaded_block: Option<(Slot, ConfirmedBlock)> = None;
197+
let mut loaded_block: Option<(Slot, ConfirmedBlockWithOptionalMetadata)> = None;
198198
while limit > 0 {
199199
let results = bigtable
200200
.get_confirmed_signatures_for_address(
@@ -306,12 +306,6 @@ impl BigTableSubCommand for App<'_, '_> {
306306
.index(2)
307307
.help("Stop uploading at this slot [default: last available slot]"),
308308
)
309-
.arg(
310-
Arg::with_name("allow_missing_metadata")
311-
.long("allow-missing-metadata")
312-
.takes_value(false)
313-
.help("Don't panic if transaction metadata is missing"),
314-
)
315309
.arg(
316310
Arg::with_name("force_reupload")
317311
.long("force")
@@ -506,7 +500,6 @@ pub fn bigtable_process_command(ledger_path: &Path, matches: &ArgMatches<'_>) {
506500
("upload", Some(arg_matches)) => {
507501
let starting_slot = value_t!(arg_matches, "starting_slot", Slot).unwrap_or(0);
508502
let ending_slot = value_t!(arg_matches, "ending_slot", Slot).ok();
509-
let allow_missing_metadata = arg_matches.is_present("allow_missing_metadata");
510503
let force_reupload = arg_matches.is_present("force_reupload");
511504
let blockstore = crate::open_blockstore(
512505
&canonicalize_ledger_path(ledger_path),
@@ -518,7 +511,6 @@ pub fn bigtable_process_command(ledger_path: &Path, matches: &ArgMatches<'_>) {
518511
blockstore,
519512
starting_slot,
520513
ending_slot,
521-
allow_missing_metadata,
522514
force_reupload,
523515
))
524516
}

ledger/src/bigtable_upload.rs

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ pub async fn upload_confirmed_blocks(
2525
bigtable: solana_storage_bigtable::LedgerStorage,
2626
starting_slot: Slot,
2727
ending_slot: Option<Slot>,
28-
allow_missing_metadata: bool,
2928
force_reupload: bool,
3029
exit: Arc<AtomicBool>,
3130
) -> Result<(), Box<dyn std::error::Error>> {
@@ -186,20 +185,7 @@ pub async fn upload_confirmed_blocks(
186185
num_blocks -= 1;
187186
None
188187
}
189-
Some(confirmed_block) => {
190-
if confirmed_block
191-
.transactions
192-
.iter()
193-
.any(|transaction| transaction.meta.is_none())
194-
{
195-
if allow_missing_metadata {
196-
info!("Transaction metadata missing from slot {}", slot);
197-
} else {
198-
panic!("Transaction metadata missing from slot {}", slot);
199-
}
200-
}
201-
Some(bigtable.upload_confirmed_block(slot, confirmed_block))
202-
}
188+
Some(confirmed_block) => Some(bigtable.upload_confirmed_block(slot, confirmed_block)),
203189
});
204190

205191
for result in futures::future::join_all(uploads).await {

ledger/src/bigtable_upload_service.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,6 @@ impl BigTableUploadService {
7272
bigtable_ledger_storage.clone(),
7373
start_slot,
7474
Some(end_slot),
75-
true,
7675
false,
7776
exit.clone(),
7877
));

0 commit comments

Comments
 (0)