Add getConfirmedBlocks rpc method (#7550)

automerge
This commit is contained in:
Tyera Eulberg 2019-12-18 16:51:47 -07:00 committed by Grimes
parent 05cf5a38af
commit c5b076ec7e
2 changed files with 148 additions and 4 deletions

View File

@ -21,6 +21,7 @@ To interact with a Solana node inside a JavaScript application, use the [solana-
* [getBlockTime](jsonrpc-api.md#getblocktime)
* [getClusterNodes](jsonrpc-api.md#getclusternodes)
* [getConfirmedBlock](jsonrpc-api.md#getconfirmedblock)
* [getConfirmedBlocks](jsonrpc-api.md#getconfirmedblocks)
* [getEpochInfo](jsonrpc-api.md#getepochinfo)
* [getEpochSchedule](jsonrpc-api.md#getepochschedule)
* [getGenesisHash](jsonrpc-api.md#getgenesishash)
@ -297,6 +298,31 @@ curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc": "2.0","id":1,"m
{"jsonrpc":"2.0","result":{"blockhash":[165,245,120,183,32,205,89,222,249,114,229,49,250,231,149,122,156,232,181,83,238,194,157,153,7,213,180,54,177,6,25,101],"parentSlot":429,"previousBlockhash":[21,108,181,90,139,241,212,203,45,78,232,29,161,31,159,188,110,82,81,11,250,74,47,140,188,28,23,96,251,164,208,166],"transactions":[[{"message":{"accountKeys":[[5],[219,181,202,40,52,148,34,136,186,59,137,160,250,225,234,17,244,160,88,116,24,176,30,227,68,11,199,38,141,68,131,228],[233,48,179,56,91,40,254,206,53,48,196,176,119,248,158,109,121,77,11,69,108,160,128,27,228,122,146,249,53,184,68,87],[6,167,213,23,25,47,10,175,198,242,101,227,251,119,204,122,218,130,197,41,208,190,59,19,110,45,0,85,32,0,0,0],[6,167,213,23,24,199,116,201,40,86,99,152,105,29,94,182,139,94,184,163,155,75,109,92,115,85,91,33,0,0,0,0],[7,97,72,29,53,116,116,187,124,77,118,36,235,211,189,179,216,53,94,115,209,16,67,252,13,163,83,128,0,0,0,0]],"header":{"numReadonlySignedAccounts":0,"numReadonlyUnsignedAccounts":3,"numRequiredSignatures":2},"instructions":[[1],{"accounts":[[3],1,2,3],"data":[[52],2,0,0,0,1,0,0,0,0,0,0,0,173,1,0,0,0,0,0,0,86,55,9,248,142,238,135,114,103,83,247,124,67,68,163,233,55,41,59,129,64,50,110,221,234,234,27,213,205,193,219,50],"program_id_index":4}],"recentBlockhash":[21,108,181,90,139,241,212,203,45,78,232,29,161,31,159,188,110,82,81,11,250,74,47,140,188,28,23,96,251,164,208,166]},"signatures":[[2],[119,9,95,108,35,95,7,1,69,101,65,45,5,204,61,114,172,88,123,238,32,201,135,229,57,50,13,21,106,216,129,183,238,43,37,101,148,81,56,232,88,136,80,65,46,189,39,106,94,13,238,54,186,48,118,186,0,62,121,122,172,171,66,5],[78,40,77,250,10,93,6,157,48,173,100,40,251,9,7,218,7,184,43,169,76,240,254,34,235,48,41,175,119,126,75,107,106,248,45,161,119,48,174,213,57,69,111,225,245,60,148,73,124,82,53,6,203,126,120,180,111,169,89,64,29,23,237,13]]},{"fee":100000,"status":{"Ok":null},"preBalances":[499998337500,15298080,1,1,1],"postBalances":[499998237500,15298080,1,1,1]}]]},"id":1}
```
### getConfirmedBlocks
Returns a list of confirmed blocks
#### Parameters:
* `integer` - start_slot, as u64 integer
* `integer` - (optional) end_slot, as u64 integer
#### Results:
The result field will be an array of u64 integers listing confirmed blocks
between start_slot and either end_slot, if provided, or latest confirmed block,
inclusive.
#### Example:
```bash
// Request
curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc": "2.0","id":1,"method":"getConfirmedBlocks","params":[5, 10]}' localhost:8899
// Result
{"jsonrpc":"2.0","result":[5,6,7,8,9,10],"id":1}
```
### getEpochInfo
Returns information about the current epoch

View File

@ -16,7 +16,9 @@ use solana_client::rpc_request::{
RpcResponseContext, RpcVersionInfo, RpcVoteAccountInfo, RpcVoteAccountStatus,
};
use solana_faucet::faucet::request_airdrop_transaction;
use solana_ledger::{bank_forks::BankForks, blocktree::Blocktree};
use solana_ledger::{
bank_forks::BankForks, blocktree::Blocktree, rooted_slot_iterator::RootedSlotIterator,
};
use solana_runtime::bank::Bank;
use solana_sdk::{
account::Account,
@ -314,6 +316,29 @@ impl JsonRpcRequestProcessor {
Ok(self.blocktree.get_confirmed_block(slot).ok())
}
pub fn get_confirmed_blocks(
&self,
start_slot: Slot,
end_slot: Option<Slot>,
) -> Result<Vec<Slot>> {
let end_slot = end_slot.unwrap_or_else(|| self.bank(None).slot());
if end_slot < start_slot {
return Ok(vec![]);
}
let start_slot = (start_slot..end_slot).find(|&slot| self.blocktree.is_root(slot));
if let Some(start_slot) = start_slot {
let mut slots: Vec<Slot> = RootedSlotIterator::new(start_slot, &self.blocktree)
.unwrap()
.map(|(slot, _)| slot)
.collect();
slots.retain(|&x| x <= end_slot);
Ok(slots)
} else {
Ok(vec![])
}
}
pub fn get_block_time(&self, slot: Slot) -> Result<Option<UnixTimestamp>> {
// This calculation currently assumes that bank.slots_per_year will remain unchanged after
// genesis (ie. that this bank's slot_per_year will be applicable to any rooted slot being
@ -541,6 +566,14 @@ pub trait RpcSol {
#[rpc(meta, name = "getBlockTime")]
fn get_block_time(&self, meta: Self::Metadata, slot: Slot) -> Result<Option<UnixTimestamp>>;
#[rpc(meta, name = "getConfirmedBlocks")]
fn get_confirmed_blocks(
&self,
meta: Self::Metadata,
start_slot: Slot,
end_slot: Option<Slot>,
) -> Result<Vec<Slot>>;
}
pub struct RpcSolImpl;
@ -1005,6 +1038,18 @@ impl RpcSol for RpcSolImpl {
.get_confirmed_block(slot)
}
fn get_confirmed_blocks(
&self,
meta: Self::Metadata,
start_slot: Slot,
end_slot: Option<Slot>,
) -> Result<Vec<Slot>> {
meta.request_processor
.read()
.unwrap()
.get_confirmed_blocks(start_slot, end_slot)
}
fn get_block_time(&self, meta: Self::Metadata, slot: Slot) -> Result<Option<UnixTimestamp>> {
meta.request_processor.read().unwrap().get_block_time(slot)
}
@ -1020,7 +1065,8 @@ pub mod tests {
};
use jsonrpc_core::{MetaIoHandler, Output, Response, Value};
use solana_ledger::{
blocktree::entries_to_test_shreds, entry::next_entry_mut, get_tmp_ledger_path,
blocktree::entries_to_test_shreds, blocktree_processor::fill_blocktree_slot_with_ticks,
entry::next_entry_mut, get_tmp_ledger_path,
};
use solana_sdk::{
fee_calculator::DEFAULT_BURN_PERCENT,
@ -1057,7 +1103,7 @@ pub mod tests {
}
fn start_rpc_handler_with_tx(pubkey: &Pubkey) -> RpcHandler {
start_rpc_handler_with_tx_and_blocktree(pubkey, vec![1], 0)
start_rpc_handler_with_tx_and_blocktree(pubkey, vec![], 0)
}
fn start_rpc_handler_with_tx_and_blocktree(
@ -1118,7 +1164,31 @@ pub mod tests {
0,
);
blocktree.insert_shreds(shreds, None, false).unwrap();
blocktree.set_roots(&blocktree_roots).unwrap();
blocktree.set_roots(&[1]).unwrap();
let mut roots = blocktree_roots.clone();
if !roots.is_empty() {
roots.retain(|&x| x > 1);
let mut parent_bank = bank;
for (i, root) in roots.iter().enumerate() {
let new_bank =
Bank::new_from_parent(&parent_bank, parent_bank.collector_id(), *root);
parent_bank = bank_forks.write().unwrap().insert(new_bank);
parent_bank.squash();
bank_forks.write().unwrap().set_root(*root, &None);
let parent = if i > 0 { roots[i - 1] } else { 1 };
fill_blocktree_slot_with_ticks(&blocktree, 5, *root, parent, Hash::default());
}
blocktree.set_roots(&roots).unwrap();
let new_bank = Bank::new_from_parent(
&parent_bank,
parent_bank.collector_id(),
roots.iter().max().unwrap() + 1,
);
bank_forks.write().unwrap().insert(new_bank);
}
let bank = bank_forks.read().unwrap().working_bank();
let leader_pubkey = *bank.collector_id();
let exit = Arc::new(AtomicBool::new(false));
@ -1964,6 +2034,54 @@ pub mod tests {
}
}
#[test]
fn test_get_confirmed_blocks() {
let bob_pubkey = Pubkey::new_rand();
let roots = vec![0, 1, 3, 4, 8];
let RpcHandler { io, meta, .. } =
start_rpc_handler_with_tx_and_blocktree(&bob_pubkey, roots.clone(), 0);
let req =
format!(r#"{{"jsonrpc":"2.0","id":1,"method":"getConfirmedBlocks","params":[0]}}"#);
let res = io.handle_request_sync(&req, meta.clone());
let result: Value = serde_json::from_str(&res.expect("actual response"))
.expect("actual response deserialization");
let confirmed_blocks: Vec<Slot> = serde_json::from_value(result["result"].clone()).unwrap();
assert_eq!(confirmed_blocks, roots);
let req =
format!(r#"{{"jsonrpc":"2.0","id":1,"method":"getConfirmedBlocks","params":[2]}}"#);
let res = io.handle_request_sync(&req, meta.clone());
let result: Value = serde_json::from_str(&res.expect("actual response"))
.expect("actual response deserialization");
let confirmed_blocks: Vec<Slot> = serde_json::from_value(result["result"].clone()).unwrap();
assert_eq!(confirmed_blocks, vec![3, 4, 8]);
let req =
format!(r#"{{"jsonrpc":"2.0","id":1,"method":"getConfirmedBlocks","params":[0, 4]}}"#);
let res = io.handle_request_sync(&req, meta.clone());
let result: Value = serde_json::from_str(&res.expect("actual response"))
.expect("actual response deserialization");
let confirmed_blocks: Vec<Slot> = serde_json::from_value(result["result"].clone()).unwrap();
assert_eq!(confirmed_blocks, vec![0, 1, 3, 4]);
let req =
format!(r#"{{"jsonrpc":"2.0","id":1,"method":"getConfirmedBlocks","params":[0, 7]}}"#);
let res = io.handle_request_sync(&req, meta.clone());
let result: Value = serde_json::from_str(&res.expect("actual response"))
.expect("actual response deserialization");
let confirmed_blocks: Vec<Slot> = serde_json::from_value(result["result"].clone()).unwrap();
assert_eq!(confirmed_blocks, vec![0, 1, 3, 4]);
let req =
format!(r#"{{"jsonrpc":"2.0","id":1,"method":"getConfirmedBlocks","params":[9, 11]}}"#);
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_blocks: Vec<Slot> = serde_json::from_value(result["result"].clone()).unwrap();
assert_eq!(confirmed_blocks, Vec::<Slot>::new());
}
#[test]
fn test_get_block_time() {
let bob_pubkey = Pubkey::new_rand();