Add getConfirmedBlock test to rpc (#7120)

automerge
This commit is contained in:
Tyera Eulberg 2019-11-25 12:08:03 -07:00 committed by Grimes
parent 686aa3a150
commit 0f66e5e49b
3 changed files with 121 additions and 49 deletions

View File

@ -22,7 +22,7 @@ pub struct Response<T> {
pub value: T, pub value: T,
} }
#[derive(Debug, Default, PartialEq, Serialize)] #[derive(Debug, Default, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct RpcConfirmedBlock { pub struct RpcConfirmedBlock {
pub previous_blockhash: Hash, pub previous_blockhash: Hash,

View File

@ -1124,7 +1124,7 @@ impl ReplayStage {
} }
#[cfg(test)] #[cfg(test)]
mod test { pub(crate) mod tests {
use super::*; use super::*;
use crate::{ use crate::{
commitment::BlockCommitment, commitment::BlockCommitment,
@ -1149,7 +1149,7 @@ mod test {
hash::{hash, Hash}, hash::{hash, Hash},
instruction::InstructionError, instruction::InstructionError,
packet::PACKET_DATA_SIZE, packet::PACKET_DATA_SIZE,
signature::{Keypair, KeypairUtil}, signature::{Keypair, KeypairUtil, Signature},
system_transaction, system_transaction,
transaction::TransactionError, transaction::TransactionError,
}; };
@ -1561,6 +1561,61 @@ mod test {
); );
} }
pub fn create_test_transactions_and_populate_blocktree(
keypairs: Vec<&Keypair>,
previous_slot: Slot,
bank: Arc<Bank>,
blocktree: Arc<Blocktree>,
) -> Vec<Signature> {
let mint_keypair = keypairs[0];
let keypair1 = keypairs[1];
let keypair2 = keypairs[2];
let keypair3 = keypairs[3];
let slot = bank.slot();
let blockhash = bank.confirmed_last_blockhash().0;
// Generate transactions for processing
// Successful transaction
let success_tx =
system_transaction::transfer(&mint_keypair, &keypair1.pubkey(), 2, blockhash);
let success_signature = success_tx.signatures[0];
let entry_1 = next_entry(&blockhash, 1, vec![success_tx]);
// Failed transaction, InstructionError
let ix_error_tx =
system_transaction::transfer(&keypair2, &keypair3.pubkey(), 10, blockhash);
let ix_error_signature = ix_error_tx.signatures[0];
let entry_2 = next_entry(&entry_1.hash, 1, vec![ix_error_tx]);
// Failed transaction
let fail_tx =
system_transaction::transfer(&mint_keypair, &keypair2.pubkey(), 2, Hash::default());
let entry_3 = next_entry(&entry_2.hash, 1, vec![fail_tx]);
let entries = vec![entry_1, entry_2, entry_3];
let shreds = entries_to_test_shreds(entries.clone(), slot, previous_slot, true, 0);
blocktree.insert_shreds(shreds, None, false).unwrap();
blocktree.set_roots(&[slot]).unwrap();
let (transaction_status_sender, transaction_status_receiver) = unbounded();
let transaction_status_service = TransactionStatusService::new(
transaction_status_receiver,
blocktree.clone(),
&Arc::new(AtomicBool::new(false)),
);
// Check that process_entries successfully writes can_commit transactions statuses, and
// that they are matched properly by get_confirmed_block
let _result = blocktree_processor::process_entries(
&bank,
&entries,
true,
Some(transaction_status_sender),
);
transaction_status_service.join().unwrap();
vec![success_signature, ix_error_signature]
}
#[test] #[test]
fn test_write_persist_transaction_status() { fn test_write_persist_transaction_status() {
let GenesisConfigInfo { let GenesisConfigInfo {
@ -1568,7 +1623,7 @@ mod test {
mint_keypair, mint_keypair,
.. ..
} = create_genesis_config(1000); } = create_genesis_config(1000);
let (ledger_path, blockhash) = create_new_tmp_ledger!(&genesis_config); let (ledger_path, _) = create_new_tmp_ledger!(&genesis_config);
{ {
let blocktree = Blocktree::open(&ledger_path) let blocktree = Blocktree::open(&ledger_path)
.expect("Expected to successfully open database ledger"); .expect("Expected to successfully open database ledger");
@ -1586,52 +1641,20 @@ mod test {
let bank1 = Arc::new(Bank::new_from_parent(&bank0, &Pubkey::default(), 1)); let bank1 = Arc::new(Bank::new_from_parent(&bank0, &Pubkey::default(), 1));
let slot = bank1.slot(); let slot = bank1.slot();
// Generate transactions for processing let signatures = create_test_transactions_and_populate_blocktree(
// Successful transaction vec![&mint_keypair, &keypair1, &keypair2, &keypair3],
let success_tx = bank0.slot(),
system_transaction::transfer(&mint_keypair, &keypair1.pubkey(), 2, blockhash); bank1,
let success_signature = success_tx.signatures[0];
let entry_1 = next_entry(&blockhash, 1, vec![success_tx]);
// Failed transaction, InstructionError
let ix_error_tx =
system_transaction::transfer(&keypair2, &keypair3.pubkey(), 10, blockhash);
let ix_error_signature = ix_error_tx.signatures[0];
let entry_2 = next_entry(&entry_1.hash, 1, vec![ix_error_tx]);
// Failed transaction
let fail_tx =
system_transaction::transfer(&mint_keypair, &keypair2.pubkey(), 2, Hash::default());
let entry_3 = next_entry(&entry_2.hash, 1, vec![fail_tx]);
let entries = vec![entry_1, entry_2, entry_3];
let shreds = entries_to_test_shreds(entries.clone(), slot, bank0.slot(), true, 0);
blocktree.insert_shreds(shreds, None, false).unwrap();
blocktree.set_roots(&[slot]).unwrap();
let (transaction_status_sender, transaction_status_receiver) = unbounded();
let transaction_status_service = TransactionStatusService::new(
transaction_status_receiver,
blocktree.clone(), blocktree.clone(),
&Arc::new(AtomicBool::new(false)),
); );
// Check that process_entries successfully writes can_commit transactions statuses, and
// that they are matched properly by get_confirmed_block
let _result = blocktree_processor::process_entries(
&bank1,
&entries,
true,
Some(transaction_status_sender),
);
transaction_status_service.join().unwrap();
let confirmed_block = blocktree.get_confirmed_block(slot).unwrap(); let confirmed_block = blocktree.get_confirmed_block(slot).unwrap();
assert_eq!(confirmed_block.transactions.len(), 3); assert_eq!(confirmed_block.transactions.len(), 3);
for (transaction, result) in confirmed_block.transactions.into_iter() { for (transaction, result) in confirmed_block.transactions.into_iter() {
if transaction.signatures[0] == success_signature { if transaction.signatures[0] == signatures[0] {
assert_eq!(result.unwrap().status, Ok(())); assert_eq!(result.unwrap().status, Ok(()));
} else if transaction.signatures[0] == ix_error_signature { } else if transaction.signatures[0] == signatures[1] {
assert_eq!( assert_eq!(
result.unwrap().status, result.unwrap().status,
Err(TransactionError::InstructionError( Err(TransactionError::InstructionError(

View File

@ -301,11 +301,6 @@ impl JsonRpcRequestProcessor {
} }
} }
// The `get_confirmed_block` method is not fully implemented. It currenlty returns a partially
// complete RpcConfirmedBlock. The `blockhash` and `previous_blockhash` fields are legitimate
// data, while the `transactions` field contains transaction tuples (Transaction,
// transaction::Result), where the Transaction is a legitimate transaction, but the
// Option<RpcTransactionStatus> is always None.
pub fn get_confirmed_block(&self, slot: Slot) -> Result<Option<RpcConfirmedBlock>> { pub fn get_confirmed_block(&self, slot: Slot) -> Result<Option<RpcConfirmedBlock>> {
Ok(self.blocktree.get_confirmed_block(slot).ok()) Ok(self.blocktree.get_confirmed_block(slot).ok())
} }
@ -980,6 +975,7 @@ pub mod tests {
use crate::{ use crate::{
contact_info::ContactInfo, contact_info::ContactInfo,
genesis_utils::{create_genesis_config, GenesisConfigInfo}, genesis_utils::{create_genesis_config, GenesisConfigInfo},
replay_stage::tests::create_test_transactions_and_populate_blocktree,
}; };
use jsonrpc_core::{MetaIoHandler, Output, Response, Value}; use jsonrpc_core::{MetaIoHandler, Output, Response, Value};
use solana_ledger::get_tmp_ledger_path; use solana_ledger::get_tmp_ledger_path;
@ -1007,6 +1003,7 @@ pub mod tests {
alice: Keypair, alice: Keypair,
leader_pubkey: Pubkey, leader_pubkey: Pubkey,
block_commitment_cache: Arc<RwLock<BlockCommitmentCache>>, block_commitment_cache: Arc<RwLock<BlockCommitmentCache>>,
confirmed_block_signatures: Vec<Signature>,
} }
fn start_rpc_handler_with_tx(pubkey: &Pubkey) -> RpcHandler { fn start_rpc_handler_with_tx(pubkey: &Pubkey) -> RpcHandler {
@ -1026,6 +1023,18 @@ pub mod tests {
Arc::new(RwLock::new(BlockCommitmentCache::new(block_commitment, 42))); Arc::new(RwLock::new(BlockCommitmentCache::new(block_commitment, 42)));
let ledger_path = get_tmp_ledger_path!(); let ledger_path = get_tmp_ledger_path!();
let blocktree = Blocktree::open(&ledger_path).unwrap(); let blocktree = Blocktree::open(&ledger_path).unwrap();
let blocktree = Arc::new(blocktree);
let keypair1 = Keypair::new();
let keypair2 = Keypair::new();
let keypair3 = Keypair::new();
bank.transfer(4, &alice, &keypair2.pubkey()).unwrap();
let confirmed_block_signatures = create_test_transactions_and_populate_blocktree(
vec![&alice, &keypair1, &keypair2, &keypair3],
0,
bank.clone(),
blocktree.clone(),
);
let leader_pubkey = *bank.collector_id(); let leader_pubkey = *bank.collector_id();
let exit = Arc::new(AtomicBool::new(false)); let exit = Arc::new(AtomicBool::new(false));
@ -1042,7 +1051,7 @@ pub mod tests {
JsonRpcConfig::default(), JsonRpcConfig::default(),
bank_forks, bank_forks,
block_commitment_cache.clone(), block_commitment_cache.clone(),
Arc::new(blocktree), blocktree,
StorageState::default(), StorageState::default(),
&validator_exit, &validator_exit,
))); )));
@ -1074,6 +1083,7 @@ pub mod tests {
alice, alice,
leader_pubkey, leader_pubkey,
block_commitment_cache, block_commitment_cache,
confirmed_block_signatures,
} }
} }
@ -1180,7 +1190,7 @@ pub mod tests {
let req = format!(r#"{{"jsonrpc":"2.0","id":1,"method":"getTransactionCount"}}"#); let req = format!(r#"{{"jsonrpc":"2.0","id":1,"method":"getTransactionCount"}}"#);
let res = io.handle_request_sync(&req, meta); let res = io.handle_request_sync(&req, meta);
let expected = format!(r#"{{"jsonrpc":"2.0","result":1,"id":1}}"#); let expected = format!(r#"{{"jsonrpc":"2.0","result":3,"id":1}}"#);
let expected: Response = let expected: Response =
serde_json::from_str(&expected).expect("expected response deserialization"); serde_json::from_str(&expected).expect("expected response deserialization");
let result: Response = serde_json::from_str(&res.expect("actual response")) let result: Response = serde_json::from_str(&res.expect("actual response"))
@ -1769,4 +1779,43 @@ pub mod tests {
assert_eq!(commitment, None); assert_eq!(commitment, None);
assert_eq!(total_staked, 42); assert_eq!(total_staked, 42);
} }
#[test]
fn test_get_confirmed_block() {
let bob_pubkey = Pubkey::new_rand();
let RpcHandler {
io,
meta,
confirmed_block_signatures,
blockhash,
..
} = start_rpc_handler_with_tx(&bob_pubkey);
let req =
format!(r#"{{"jsonrpc":"2.0","id":1,"method":"getConfirmedBlock","params":[0]}}"#);
let res = io.handle_request_sync(&req, meta);
let result: Value = serde_json::from_str(&res.expect("actual response"))
.expect("actual response deserialization");
let confirmed_block: Option<RpcConfirmedBlock> =
serde_json::from_value(result["result"].clone()).unwrap();
let confirmed_block = confirmed_block.unwrap();
assert_eq!(confirmed_block.transactions.len(), 3);
for (transaction, result) in confirmed_block.transactions.into_iter() {
if transaction.signatures[0] == confirmed_block_signatures[0] {
assert_eq!(transaction.message.recent_blockhash, blockhash);
assert_eq!(result.unwrap().status, Ok(()));
} else if transaction.signatures[0] == confirmed_block_signatures[1] {
assert_eq!(
result.unwrap().status,
Err(TransactionError::InstructionError(
0,
InstructionError::CustomError(1)
))
);
} else {
assert_eq!(result, None);
}
}
}
} }