v0.2.9-pre.007
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-onchain-transport-lib/unit_tests/grpc_subscribe.rs
|
||||
// version: 2
|
||||
// version: 3
|
||||
|
||||
fn filter_name(value: &str) -> crate::YellowstoneSubscribeFilterName {
|
||||
return crate::YellowstoneSubscribeFilterName::new(value).expect("fixture filter name must validate");
|
||||
@@ -55,7 +55,7 @@ fn yellowstone_subscribe_empty_and_named_empty_maps_encode_exactly() {
|
||||
assert_eq!(wire.slots.get("slots"), std::option::Option::Some(&yellowstone_grpc_proto::geyser::SubscribeRequestFilterSlots::default()));
|
||||
assert_eq!(
|
||||
wire.transactions.get("transactions"),
|
||||
std::option::Option::Some(&yellowstone_grpc_proto::geyser::SubscribeRequestFilterTransactions::default())
|
||||
std::option::Option::Some(&yellowstone_grpc_proto::geyser::SubscribeRequestFilterTransactions::default()),
|
||||
);
|
||||
assert_eq!(
|
||||
wire.transactions_status.get("transaction-status"),
|
||||
@@ -365,3 +365,191 @@ fn yellowstone_slot_update_preserves_all_current_statuses_and_bounds_dead_error(
|
||||
};
|
||||
assert!(super::decode_slot_update(oversized).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn yellowstone_transaction_filters_encode_complete_current_wire_and_redact_selectors() {
|
||||
let mut filter = crate::YellowstoneSubscribeTransactionFilter::new();
|
||||
filter.set_vote(std::option::Option::Some(false));
|
||||
filter.set_failed(std::option::Option::Some(true));
|
||||
let signature = crate::YellowstoneTransactionSignatureSelector::new("1".repeat(64)).expect("signature selector must validate");
|
||||
filter.set_signature(std::option::Option::Some(signature));
|
||||
assert!(filter.push_account_include(ksp_core_lib::Pubkey::new_from_array([1_u8; 32])).is_ok());
|
||||
assert!(filter.push_account_exclude(ksp_core_lib::Pubkey::new_from_array([2_u8; 32])).is_ok());
|
||||
assert!(filter.push_account_required(ksp_core_lib::Pubkey::new_from_array([3_u8; 32])).is_ok());
|
||||
let cuckoo =
|
||||
crate::YellowstoneCuckooFilter::new(vec![0_u8; 16], 4, 4, 8, 7, crate::YellowstoneCuckooHashAlgorithm::SipHash).expect("cuckoo filter must validate");
|
||||
filter.set_cuckoo_account_include(std::option::Option::Some(cuckoo));
|
||||
filter.set_token_accounts(std::option::Option::Some(crate::YellowstoneTokenAccountExpansion::BalanceChanged));
|
||||
let wire = filter.to_wire();
|
||||
assert_eq!(wire.vote, std::option::Option::Some(false));
|
||||
assert_eq!(wire.failed, std::option::Option::Some(true));
|
||||
assert!(wire.signature.is_some());
|
||||
assert_eq!(wire.account_include.len(), 1);
|
||||
assert_eq!(wire.account_exclude.len(), 1);
|
||||
assert_eq!(wire.account_required.len(), 1);
|
||||
assert!(wire.cuckoo_account_include.is_some());
|
||||
assert_eq!(wire.token_accounts, std::option::Option::Some(yellowstone_grpc_proto::geyser::TokenAccountExpansionControlFlag::BalanceChanged as i32));
|
||||
let debug = format!("{filter:?}");
|
||||
assert!(debug.contains("account_include_count"));
|
||||
assert!(!debug.contains(&"1".repeat(32)));
|
||||
assert!(!debug.contains(&ksp_core_lib::Pubkey::new_from_array([1_u8; 32]).to_string()));
|
||||
assert!(crate::YellowstoneTransactionSignatureSelector::new("contains-0-O-I-l").is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn yellowstone_transaction_update_decodes_current_storage_wire_including_v1_config_and_meta() {
|
||||
let confirmed = yellowstone_grpc_proto::geyser::SubscribeUpdateTransactionInfo {
|
||||
signature: vec![9_u8; 64],
|
||||
is_vote: false,
|
||||
transaction: std::option::Option::Some(yellowstone_grpc_proto::solana::storage::confirmed_block::Transaction {
|
||||
signatures: vec![vec![9_u8; 64], vec![8_u8; 64]],
|
||||
message: std::option::Option::Some(yellowstone_grpc_proto::solana::storage::confirmed_block::Message {
|
||||
header: std::option::Option::Some(yellowstone_grpc_proto::solana::storage::confirmed_block::MessageHeader {
|
||||
num_required_signatures: 2,
|
||||
num_readonly_signed_accounts: 1,
|
||||
num_readonly_unsigned_accounts: 1,
|
||||
}),
|
||||
account_keys: vec![vec![1_u8; 32], vec![2_u8; 32]],
|
||||
recent_blockhash: vec![3_u8; 32],
|
||||
instructions: vec![yellowstone_grpc_proto::solana::storage::confirmed_block::CompiledInstruction {
|
||||
program_id_index: 1,
|
||||
accounts: vec![0_u8, 1],
|
||||
data: vec![4_u8, 5, 6],
|
||||
}],
|
||||
versioned: true,
|
||||
address_table_lookups: vec![yellowstone_grpc_proto::solana::storage::confirmed_block::MessageAddressTableLookup {
|
||||
account_key: vec![4_u8; 32],
|
||||
writable_indexes: vec![1_u8, 2],
|
||||
readonly_indexes: vec![3_u8],
|
||||
}],
|
||||
config: std::option::Option::Some(yellowstone_grpc_proto::solana::storage::confirmed_block::TransactionConfig {
|
||||
priority_fee: std::option::Option::Some(7),
|
||||
compute_unit_limit: std::option::Option::Some(8),
|
||||
loaded_accounts_data_size_limit: std::option::Option::Some(9),
|
||||
heap_size: std::option::Option::Some(10),
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
meta: std::option::Option::Some(yellowstone_grpc_proto::solana::storage::confirmed_block::TransactionStatusMeta {
|
||||
err: std::option::Option::Some(yellowstone_grpc_proto::solana::storage::confirmed_block::TransactionError { err: vec![11_u8, 12] }),
|
||||
fee: 5_000,
|
||||
pre_balances: vec![100, 200],
|
||||
post_balances: vec![90, 210],
|
||||
inner_instructions: vec![yellowstone_grpc_proto::solana::storage::confirmed_block::InnerInstructions {
|
||||
index: 0,
|
||||
instructions: vec![yellowstone_grpc_proto::solana::storage::confirmed_block::InnerInstruction {
|
||||
program_id_index: 1,
|
||||
accounts: vec![0_u8],
|
||||
data: vec![13_u8, 14],
|
||||
stack_height: std::option::Option::Some(2),
|
||||
}],
|
||||
}],
|
||||
inner_instructions_none: false,
|
||||
log_messages: vec!["Program log: fixture".to_owned()],
|
||||
log_messages_none: false,
|
||||
pre_token_balances: vec![yellowstone_grpc_proto::solana::storage::confirmed_block::TokenBalance {
|
||||
account_index: 0,
|
||||
mint: "mint-fixture".to_owned(),
|
||||
ui_token_amount: std::option::Option::Some(yellowstone_grpc_proto::solana::storage::confirmed_block::UiTokenAmount {
|
||||
ui_amount: 1.5,
|
||||
decimals: 6,
|
||||
amount: "1500000".to_owned(),
|
||||
ui_amount_string: "1.5".to_owned(),
|
||||
}),
|
||||
owner: "owner-fixture".to_owned(),
|
||||
program_id: "program-fixture".to_owned(),
|
||||
}],
|
||||
post_token_balances: vec![],
|
||||
rewards: vec![yellowstone_grpc_proto::solana::storage::confirmed_block::Reward {
|
||||
pubkey: ksp_core_lib::Pubkey::new_from_array([5_u8; 32]).to_string(),
|
||||
lamports: 17,
|
||||
post_balance: 18,
|
||||
reward_type: yellowstone_grpc_proto::solana::storage::confirmed_block::RewardType::Staking as i32,
|
||||
commission: "5".to_owned(),
|
||||
commission_bps: "500".to_owned(),
|
||||
}],
|
||||
loaded_writable_addresses: vec![vec![6_u8; 32]],
|
||||
loaded_readonly_addresses: vec![vec![7_u8; 32]],
|
||||
return_data: std::option::Option::Some(yellowstone_grpc_proto::solana::storage::confirmed_block::ReturnData {
|
||||
program_id: vec![8_u8; 32],
|
||||
data: vec![15_u8, 16],
|
||||
}),
|
||||
return_data_none: false,
|
||||
compute_units_consumed: std::option::Option::Some(123),
|
||||
cost_units: std::option::Option::Some(456),
|
||||
}),
|
||||
index: 3,
|
||||
};
|
||||
let wire = yellowstone_grpc_proto::geyser::SubscribeUpdate {
|
||||
filters: vec!["transactions-main".to_owned()],
|
||||
update_oneof: std::option::Option::Some(yellowstone_grpc_proto::geyser::subscribe_update::UpdateOneof::Transaction(
|
||||
yellowstone_grpc_proto::geyser::SubscribeUpdateTransaction { transaction: std::option::Option::Some(confirmed), slot: 42 },
|
||||
)),
|
||||
created_at: std::option::Option::Some(yellowstone_grpc_proto::prost_types::Timestamp { seconds: 100, nanos: 200 }),
|
||||
};
|
||||
let update = super::decode_transaction_update(wire).expect("transaction update fixture must decode");
|
||||
assert_eq!(update.slot(), 42);
|
||||
assert_eq!(update.filters()[0].as_str(), "transactions-main");
|
||||
assert_eq!(update.transaction().signature().as_bytes(), &[9_u8; 64]);
|
||||
assert_eq!(format!("{:?}", update.transaction().signature()), "YellowstoneTransactionSignature(<redacted>)");
|
||||
assert_eq!(update.transaction().index(), 3);
|
||||
assert_eq!(update.transaction().transaction().signatures().len(), 2);
|
||||
assert!(update.transaction().transaction().message().versioned());
|
||||
let config = update.transaction().transaction().message().config().expect("v1 config must be preserved");
|
||||
assert_eq!(config.priority_fee(), std::option::Option::Some(7));
|
||||
assert_eq!(config.heap_size(), std::option::Option::Some(10));
|
||||
assert_eq!(update.transaction().meta().fee(), 5_000);
|
||||
assert_eq!(update.transaction().meta().error().expect("error must be present").as_bytes(), &[11_u8, 12]);
|
||||
assert_eq!(update.transaction().meta().inner_instructions()[0].instructions()[0].stack_height(), std::option::Option::Some(2));
|
||||
assert_eq!(update.transaction().meta().pre_token_balances()[0].ui_token_amount().expect("token amount must be present").amount(), "1500000");
|
||||
let token_debug = format!("{:?}", update.transaction().meta().pre_token_balances()[0]);
|
||||
assert!(!token_debug.contains("mint-fixture"));
|
||||
assert!(!token_debug.contains("owner-fixture"));
|
||||
assert!(!token_debug.contains("program-fixture"));
|
||||
assert_eq!(update.transaction().meta().rewards()[0].reward_type(), crate::YellowstoneRewardType::Staking);
|
||||
assert_eq!(update.transaction().meta().loaded_writable_addresses()[0], ksp_core_lib::Pubkey::new_from_array([6_u8; 32]));
|
||||
assert_eq!(update.transaction().meta().return_data().expect("return data must be present").data(), &[15_u8, 16]);
|
||||
assert_eq!(update.transaction().meta().compute_units_consumed(), std::option::Option::Some(123));
|
||||
assert_eq!(update.transaction().meta().cost_units(), std::option::Option::Some(456));
|
||||
let debug = format!("{update:?}");
|
||||
assert!(!debug.contains("Program log: fixture"));
|
||||
assert!(!debug.contains("11, 12"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn yellowstone_transaction_status_update_preserves_error_and_rejects_malformed_signature() {
|
||||
let wire = yellowstone_grpc_proto::geyser::SubscribeUpdate {
|
||||
filters: vec!["status".to_owned()],
|
||||
update_oneof: std::option::Option::Some(yellowstone_grpc_proto::geyser::subscribe_update::UpdateOneof::TransactionStatus(
|
||||
yellowstone_grpc_proto::geyser::SubscribeUpdateTransactionStatus {
|
||||
slot: 55,
|
||||
signature: vec![2_u8; 64],
|
||||
is_vote: true,
|
||||
index: 4,
|
||||
err: std::option::Option::Some(yellowstone_grpc_proto::solana::storage::confirmed_block::TransactionError { err: vec![99_u8] }),
|
||||
},
|
||||
)),
|
||||
created_at: std::option::Option::None,
|
||||
};
|
||||
let update = super::decode_transaction_status_update(wire).expect("transaction-status update must decode");
|
||||
assert_eq!(update.slot(), 55);
|
||||
assert!(update.is_vote());
|
||||
assert_eq!(update.index(), 4);
|
||||
assert_eq!(update.signature().as_bytes(), &[2_u8; 64]);
|
||||
assert_eq!(update.error().expect("status error must be present").as_bytes(), &[99_u8]);
|
||||
assert!(!format!("{update:?}").contains("99"));
|
||||
let malformed = yellowstone_grpc_proto::geyser::SubscribeUpdate {
|
||||
filters: vec!["status".to_owned()],
|
||||
update_oneof: std::option::Option::Some(yellowstone_grpc_proto::geyser::subscribe_update::UpdateOneof::TransactionStatus(
|
||||
yellowstone_grpc_proto::geyser::SubscribeUpdateTransactionStatus {
|
||||
slot: 1,
|
||||
signature: vec![0_u8; 63],
|
||||
is_vote: false,
|
||||
index: 0,
|
||||
err: std::option::Option::None,
|
||||
},
|
||||
)),
|
||||
created_at: std::option::Option::None,
|
||||
};
|
||||
assert!(super::decode_transaction_status_update(malformed).is_err());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user