Add GetConfirmedBlocksWithLimit RPC method

This commit is contained in:
Michael Vines 2020-09-30 13:47:12 -07:00
parent b2fc7f7caa
commit 75b621160e
4 changed files with 160 additions and 5 deletions

View File

@ -271,6 +271,17 @@ impl RpcClient {
)
}
pub fn get_confirmed_blocks_with_limit(
&self,
start_slot: Slot,
limit: usize,
) -> ClientResult<Vec<Slot>> {
self.send(
RpcRequest::GetConfirmedBlocksWithLimit,
json!([start_slot, limit]),
)
}
pub fn get_confirmed_signatures_for_address(
&self,
address: &Pubkey,

View File

@ -13,6 +13,7 @@ pub enum RpcRequest {
GetClusterNodes,
GetConfirmedBlock,
GetConfirmedBlocks,
GetConfirmedBlocksWithLimit,
GetConfirmedSignaturesForAddress,
GetConfirmedSignaturesForAddress2,
GetConfirmedTransaction,
@ -67,6 +68,7 @@ impl fmt::Display for RpcRequest {
RpcRequest::GetClusterNodes => "getClusterNodes",
RpcRequest::GetConfirmedBlock => "getConfirmedBlock",
RpcRequest::GetConfirmedBlocks => "getConfirmedBlocks",
RpcRequest::GetConfirmedBlocksWithLimit => "getConfirmedBlocksWithLimit",
RpcRequest::GetConfirmedSignaturesForAddress => "getConfirmedSignaturesForAddress",
RpcRequest::GetConfirmedSignaturesForAddress2 => "getConfirmedSignaturesForAddress2",
RpcRequest::GetConfirmedTransaction => "getConfirmedTransaction",

View File

@ -679,8 +679,8 @@ impl JsonRpcRequestProcessor {
)));
}
let lowest_slot = self.blockstore.lowest_slot();
if start_slot < lowest_slot {
let lowest_blockstore_slot = self.blockstore.lowest_slot();
if start_slot < lowest_blockstore_slot {
// If the starting slot is lower than what's available in blockstore assume the entire
// [start_slot..end_slot] can be fetched from BigTable.
if let Some(bigtable_ledger_storage) = &self.bigtable_ledger_storage {
@ -696,12 +696,45 @@ impl JsonRpcRequestProcessor {
Ok(self
.blockstore
.rooted_slot_iterator(max(start_slot, lowest_slot))
.rooted_slot_iterator(max(start_slot, lowest_blockstore_slot))
.map_err(|_| Error::internal_error())?
.filter(|&slot| slot <= end_slot)
.collect())
}
pub fn get_confirmed_blocks_with_limit(
&self,
start_slot: Slot,
limit: usize,
) -> Result<Vec<Slot>> {
if limit > MAX_GET_CONFIRMED_BLOCKS_RANGE as usize {
return Err(Error::invalid_params(format!(
"Limit too large; max {}",
MAX_GET_CONFIRMED_BLOCKS_RANGE
)));
}
let lowest_blockstore_slot = self.blockstore.lowest_slot();
if start_slot < lowest_blockstore_slot {
// If the starting slot is lower than what's available in blockstore assume the entire
// range can be fetched from BigTable.
if let Some(bigtable_ledger_storage) = &self.bigtable_ledger_storage {
return Ok(self
.runtime_handle
.block_on(bigtable_ledger_storage.get_confirmed_blocks(start_slot, limit))
.unwrap_or_else(|_| vec![]));
}
}
Ok(self
.blockstore
.rooted_slot_iterator(max(start_slot, lowest_blockstore_slot))
.map_err(|_| Error::internal_error())?
.take(limit)
.collect())
}
pub fn get_block_time(&self, slot: Slot) -> Result<Option<UnixTimestamp>> {
if slot
<= self
@ -1699,6 +1732,14 @@ pub trait RpcSol {
end_slot: Option<Slot>,
) -> Result<Vec<Slot>>;
#[rpc(meta, name = "getConfirmedBlocksWithLimit")]
fn get_confirmed_blocks_with_limit(
&self,
meta: Self::Metadata,
start_slot: Slot,
limit: usize,
) -> Result<Vec<Slot>>;
#[rpc(meta, name = "getConfirmedTransaction")]
fn get_confirmed_transaction(
&self,
@ -2366,12 +2407,25 @@ impl RpcSol for RpcSolImpl {
end_slot: Option<Slot>,
) -> Result<Vec<Slot>> {
debug!(
"get_confirmed_blocks rpc request received: {:?}-{:?}",
"get_confirmed_blocks rpc request received: {}-{:?}",
start_slot, end_slot
);
meta.get_confirmed_blocks(start_slot, end_slot)
}
fn get_confirmed_blocks_with_limit(
&self,
meta: Self::Metadata,
start_slot: Slot,
limit: usize,
) -> Result<Vec<Slot>> {
debug!(
"get_confirmed_blocks_with_limit rpc request received: {}-{}",
start_slot, limit,
);
meta.get_confirmed_blocks_with_limit(start_slot, limit)
}
fn get_block_time(&self, meta: Self::Metadata, slot: Slot) -> Result<Option<UnixTimestamp>> {
meta.get_block_time(slot)
}
@ -4733,6 +4787,69 @@ pub mod tests {
);
}
#[test]
fn test_get_confirmed_blocks_with_limit() {
let bob_pubkey = Pubkey::new_rand();
let roots = vec![0, 1, 3, 4, 8];
let RpcHandler {
io,
meta,
block_commitment_cache,
..
} = start_rpc_handler_with_tx_and_blockstore(&bob_pubkey, roots, 0);
block_commitment_cache
.write()
.unwrap()
.set_highest_confirmed_root(8);
let req = r#"{"jsonrpc":"2.0","id":1,"method":"getConfirmedBlocksWithLimit","params":[0,500001]}"#;
let res = io.handle_request_sync(&req, meta.clone());
assert_eq!(
res,
Some(
r#"{"jsonrpc":"2.0","error":{"code":-32602,"message":"Limit too large; max 500000"},"id":1}"#.to_string(),
)
);
let req =
r#"{"jsonrpc":"2.0","id":1,"method":"getConfirmedBlocksWithLimit","params":[0,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!(confirmed_blocks.is_empty());
let req =
r#"{"jsonrpc":"2.0","id":1,"method":"getConfirmedBlocksWithLimit","params":[2,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]);
let req =
r#"{"jsonrpc":"2.0","id":1,"method":"getConfirmedBlocksWithLimit","params":[2,3]}"#;
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 = r#"{"jsonrpc":"2.0","id":1,"method":"getConfirmedBlocksWithLimit","params":[2,500000]}"#;
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 = r#"{"jsonrpc":"2.0","id":1,"method":"getConfirmedBlocksWithLimit","params":[9,500000]}"#;
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();

View File

@ -23,6 +23,7 @@ To interact with a Solana node inside a JavaScript application, use the [solana-
- [getClusterNodes](jsonrpc-api.md#getclusternodes)
- [getConfirmedBlock](jsonrpc-api.md#getconfirmedblock)
- [getConfirmedBlocks](jsonrpc-api.md#getconfirmedblocks)
- [getConfirmedBlocksWithLimit](jsonrpc-api.md#getconfirmedblockswithlimit)
- [getConfirmedSignaturesForAddress](jsonrpc-api.md#getconfirmedsignaturesforaddress)
- [getConfirmedSignaturesForAddress2](jsonrpc-api.md#getconfirmedsignaturesforaddress2)
- [getConfirmedTransaction](jsonrpc-api.md#getconfirmedtransaction)
@ -392,7 +393,7 @@ The JSON structure of inner instructions is defined as a list of objects in the
### getConfirmedBlocks
Returns a list of confirmed blocks
Returns a list of confirmed blocks between two slots
#### Parameters:
@ -416,6 +417,30 @@ curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc": "2.0","id":1,"m
{"jsonrpc":"2.0","result":[5,6,7,8,9,10],"id":1}
```
### getConfirmedBlocksWithLimit
Returns a list of confirmed blocks starting at the given slot
#### Parameters:
- `<u64>` - start_slot, as u64 integer
- `<u64>` - limit, as u64 integer
#### Results:
The result field will be an array of u64 integers listing confirmed blocks
starting at `start_slot` for up to `limit` blocks, inclusive.
#### Example:
```bash
// Request
curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc": "2.0","id":1,"method":"getConfirmedBlockWithLimit2","params":[5, 3]}' localhost:8899
// Result
{"jsonrpc":"2.0","result":[5,6,7],"id":1}
```
### getConfirmedSignaturesForAddress
**DEPRECATED: Please use getConfirmedSignaturesForAddress2 instead**