mirror of
https://github.com/mimblewimble/grin.git
synced 2025-01-20 19:11:08 +03:00
Foreign API: Bulk block request (#3751)
* remove non-mainnet check for PIBD requests * add first version of get blocks function * .\api\src\foreign.rs * add a max value to get_blocks, documentation * typo * updates based on feedback
This commit is contained in:
parent
0649ba9645
commit
01370d74ff
5 changed files with 370 additions and 3 deletions
|
@ -23,12 +23,12 @@ use crate::handlers::pool_api::PoolHandler;
|
|||
use crate::handlers::transactions_api::TxHashSetHandler;
|
||||
use crate::handlers::version_api::VersionHandler;
|
||||
use crate::pool::{self, BlockChain, PoolAdapter, PoolEntry};
|
||||
use crate::rest::*;
|
||||
use crate::types::{
|
||||
BlockHeaderPrintable, BlockPrintable, LocatedTxKernel, OutputListing, OutputPrintable, Tip,
|
||||
Version,
|
||||
};
|
||||
use crate::util::RwLock;
|
||||
use crate::{rest::*, BlockListing};
|
||||
use std::sync::Weak;
|
||||
|
||||
/// Main interface into all node API functions.
|
||||
|
@ -139,6 +139,36 @@ where
|
|||
block_handler.get_block(&hash, include_proof, include_merkle_proof)
|
||||
}
|
||||
|
||||
/// Returns a [`BlockListing`](types/struct.BlockListing.html) of available blocks
|
||||
/// between `min_height` and `max_height`
|
||||
/// The method will query the database for blocks starting at the block height `min_height`
|
||||
/// and continue until `max_height`, skipping any blocks that aren't available.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `start_height` - starting height to lookup.
|
||||
/// * `end_height` - ending height to to lookup.
|
||||
/// * 'max` - The max number of blocks to return.
|
||||
/// Note this is overriden with BLOCK_TRANSFER_LIMIT if BLOCK_TRANSFER_LIMIT is exceeded
|
||||
///
|
||||
/// # Returns
|
||||
/// * Result Containing:
|
||||
/// * A [`BlockListing`](types/struct.BlockListing.html)
|
||||
/// * or [`Error`](struct.Error.html) if an error is encountered.
|
||||
///
|
||||
|
||||
pub fn get_blocks(
|
||||
&self,
|
||||
start_height: u64,
|
||||
end_height: u64,
|
||||
max: u64,
|
||||
include_proof: Option<bool>,
|
||||
) -> Result<BlockListing, Error> {
|
||||
let block_handler = BlockHandler {
|
||||
chain: self.chain.clone(),
|
||||
};
|
||||
block_handler.get_blocks(start_height, end_height, max, include_proof)
|
||||
}
|
||||
|
||||
/// Returns the node version and block header version (used by grin-wallet).
|
||||
///
|
||||
/// # Returns
|
||||
|
|
|
@ -21,8 +21,8 @@ use crate::pool::PoolEntry;
|
|||
use crate::pool::{BlockChain, PoolAdapter};
|
||||
use crate::rest::Error;
|
||||
use crate::types::{
|
||||
BlockHeaderPrintable, BlockPrintable, LocatedTxKernel, OutputListing, OutputPrintable, Tip,
|
||||
Version,
|
||||
BlockHeaderPrintable, BlockListing, BlockPrintable, LocatedTxKernel, OutputListing,
|
||||
OutputPrintable, Tip, Version,
|
||||
};
|
||||
use crate::util;
|
||||
|
||||
|
@ -246,6 +246,251 @@ pub trait ForeignRpc: Sync + Send {
|
|||
commit: Option<String>,
|
||||
) -> Result<BlockPrintable, Error>;
|
||||
|
||||
/**
|
||||
Networked version of [Foreign::get_blocks](struct.Foreign.html#method.get_blocks).
|
||||
|
||||
# Json rpc example
|
||||
|
||||
```
|
||||
# grin_api::doctest_helper_json_rpc_foreign_assert_response!(
|
||||
# r#"
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"method": "get_blocks",
|
||||
"params": [2299309, 2300309, 2, false],
|
||||
"id": 1
|
||||
}
|
||||
# "#
|
||||
# ,
|
||||
# r#"
|
||||
{
|
||||
"id": 1,
|
||||
"jsonrpc": "2.0",
|
||||
"result": {
|
||||
"Ok": {
|
||||
"blocks": [
|
||||
{
|
||||
"header": {
|
||||
"cuckoo_solution": [
|
||||
20354215,
|
||||
100524565,
|
||||
169529296,
|
||||
259818619,
|
||||
261952555,
|
||||
265003136,
|
||||
290685286,
|
||||
307792709,
|
||||
329993483,
|
||||
331550733,
|
||||
478902211,
|
||||
707186317,
|
||||
717277083,
|
||||
742312701,
|
||||
763869950,
|
||||
785680094,
|
||||
791217416,
|
||||
1156641404,
|
||||
1244452354,
|
||||
1277970471,
|
||||
1405106926,
|
||||
1663783361,
|
||||
1701259732,
|
||||
1795507572,
|
||||
1845900835,
|
||||
2060172013,
|
||||
2067055232,
|
||||
2169213199,
|
||||
2191128830,
|
||||
2253855427,
|
||||
2626425322,
|
||||
2678973678,
|
||||
2815586448,
|
||||
2921010487,
|
||||
3042894274,
|
||||
3103031603,
|
||||
3492595971,
|
||||
3603041347,
|
||||
3853538391,
|
||||
3974438280,
|
||||
4199558832,
|
||||
4262968379
|
||||
],
|
||||
"edge_bits": 32,
|
||||
"hash": "0004331bb122685f12644e40b163e4557951b2b835ad2493502750ea787af7cc",
|
||||
"height": 2299309,
|
||||
"kernel_mmr_size": 8568165,
|
||||
"kernel_root": "6b4adb9ee193ad043910b5a8c1bac0864ab99f57845101a3b422031bcf5c2ce1",
|
||||
"nonce": 4185528505858938389,
|
||||
"output_mmr_size": 13524183,
|
||||
"output_root": "b642891741b56adaf7762813490d161377d0fbf7b47170d235beef33c25a4d77",
|
||||
"prev_root": "a0ba3206b6a8089ef05690d40767c41cc0514eaa5031ebce1960a7cc2edcc211",
|
||||
"previous": "000207548609a9007eacd7dfcdc8006252d6b1ad70864ea8ddebe4ca9e82bd74",
|
||||
"range_proof_root": "d8cefda00f325fd9a1223454f23276b73d8a1d7c72ec74cdfb9bdf5c77a04dee",
|
||||
"secondary_scaling": 0,
|
||||
"timestamp": "2023-06-05T20:18:45+00:00",
|
||||
"total_difficulty": 2072532663425232,
|
||||
"total_kernel_offset": "b0a0c21326532b4a91c18d2355aedca4d8ed68b77db9882feb85da8120b4f533",
|
||||
"version": 5
|
||||
},
|
||||
"inputs": [
|
||||
"092b140b1500812ac58ef68c17a2bbf2ec3531bcf0ce4dc32bbf8a29351d1784d7",
|
||||
"083b72230921abeacd637dae8505233ab035c20dff1bfdab5ff5bb41b2f5238458"
|
||||
],
|
||||
"kernels": [
|
||||
{
|
||||
"excess": "08ab720dc374f099e6726e2dceada508a0331bb1f13b8a4e56afde83ff42f7a351",
|
||||
"excess_sig": "6858120e9758d7587e27fd5dc9c26117a2ce0d5a7d871ce805e03eb494bfa1f86a27991865b3ab709064c43692433fd58f008c3bba2c88ad5f95a0c8ff3cf11f",
|
||||
"features": "Plain",
|
||||
"fee": 23500000,
|
||||
"fee_shift": 0,
|
||||
"lock_height": 0
|
||||
},
|
||||
{
|
||||
"excess": "08d0a44b22952b03b29e3d88391102c281dcab4763def22cab65ed45e35b9078e8",
|
||||
"excess_sig": "32f91d5671e334a87843a8b02c550c9e0fbdfe507ee62417cc123b5078d7884701a42e257357a1bed9dc4a8e07540b1629e9fa95a05c44adb5cb001c8fb777ee",
|
||||
"features": "Coinbase",
|
||||
"fee": 0,
|
||||
"fee_shift": 0,
|
||||
"lock_height": 0
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"block_height": 2299309,
|
||||
"commit": "0857c94df51dd226fa0c5920aae6d73d069603f973b2e06551698c6d39fdc2c192",
|
||||
"merkle_proof": null,
|
||||
"mmr_index": 13524176,
|
||||
"output_type": "Coinbase",
|
||||
"proof": null,
|
||||
"proof_hash": "0937291a8a3c81cea4421fa0d0b291aacb5d46065cfd93747a15f58d99d781b6",
|
||||
"spent": false
|
||||
},
|
||||
{
|
||||
"block_height": 2299309,
|
||||
"commit": "08d4681b904695edee6e183cd40564ea0f5589b35d4d386da2eb980a6a92b1b307",
|
||||
"merkle_proof": null,
|
||||
"mmr_index": 0,
|
||||
"output_type": "Transaction",
|
||||
"proof": null,
|
||||
"proof_hash": "41694ab6dcd9b1664ca28e79c3302144b99a4c1cb45d13c8728604c1d26e37bf",
|
||||
"spent": true
|
||||
},
|
||||
{
|
||||
"block_height": 2299309,
|
||||
"commit": "08255a260a65fc87cfd924780d896eaadb42468b0fe3ba6adeace378793b5d8172",
|
||||
"merkle_proof": null,
|
||||
"mmr_index": 13524182,
|
||||
"output_type": "Transaction",
|
||||
"proof": null,
|
||||
"proof_hash": "58c77a5716ec4806dbddac64a83d6e4351b6eeffca391be1b11ec74aac0514dc",
|
||||
"spent": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"header": {
|
||||
"cuckoo_solution": [
|
||||
898450,
|
||||
353949138,
|
||||
440882514,
|
||||
500154010,
|
||||
555236503,
|
||||
615120852,
|
||||
740100750,
|
||||
754668484,
|
||||
1056458121,
|
||||
1071299788,
|
||||
1130460099,
|
||||
1414281857,
|
||||
1444894533,
|
||||
1481124421,
|
||||
1551877341,
|
||||
1666859923,
|
||||
1682642953,
|
||||
1837365586,
|
||||
1845508478,
|
||||
1872787697,
|
||||
2040619654,
|
||||
2078971700,
|
||||
2104947318,
|
||||
2206501084,
|
||||
2233951742,
|
||||
2360961460,
|
||||
2378988856,
|
||||
2402500295,
|
||||
2438384422,
|
||||
2532261092,
|
||||
2879360933,
|
||||
3011869457,
|
||||
3023365279,
|
||||
3412207020,
|
||||
3509607650,
|
||||
3793770861,
|
||||
3850043972,
|
||||
3873426868,
|
||||
3965579806,
|
||||
4007877324,
|
||||
4090157476,
|
||||
4141650723
|
||||
],
|
||||
"edge_bits": 32,
|
||||
"hash": "00006871e1fb8e7dddcc46343d7fbba14d08946c67b4568f3c2e98ec8c554ae9",
|
||||
"height": 2299310,
|
||||
"kernel_mmr_size": 8568166,
|
||||
"kernel_root": "87184dc2f9efa6467ce797191c5d3ef086403d0103ba0b5adc6a71ed203a053c",
|
||||
"nonce": 13726392224838330049,
|
||||
"output_mmr_size": 13524184,
|
||||
"output_root": "9570fbccef29609c5d3c68b07771bf4e7e80d0b139d9bd0215d1e9d1aaaed813",
|
||||
"prev_root": "df1c67366b9cdd8deea570534a00a320748899e146288be067c0f402038e6aa0",
|
||||
"previous": "0004331bb122685f12644e40b163e4557951b2b835ad2493502750ea787af7cc",
|
||||
"range_proof_root": "987d7aff01e201269d4c6b00e885b9ed9c10f47205edd7727e3490aab953ca80",
|
||||
"secondary_scaling": 0,
|
||||
"timestamp": "2023-06-05T20:19:27+00:00",
|
||||
"total_difficulty": 2072532872584027,
|
||||
"total_kernel_offset": "b0a0c21326532b4a91c18d2355aedca4d8ed68b77db9882feb85da8120b4f533",
|
||||
"version": 5
|
||||
},
|
||||
"inputs": [],
|
||||
"kernels": [
|
||||
{
|
||||
"excess": "08224a7946a75071b127af45496ddd3fc438db325cc35c3e4b0fdf23ed27703dd8",
|
||||
"excess_sig": "d8c81bd8130c30016e38655a32b4c7a1f8fffda34a736dd8cdbcad05d28d09e3708d1f01e21276747eb03f28b9f5a834cb0ef8532330183df2b10d47ae7e68c6",
|
||||
"features": "Coinbase",
|
||||
"fee": 0,
|
||||
"fee_shift": 0,
|
||||
"lock_height": 0
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"block_height": 2299310,
|
||||
"commit": "09997d3c1eff72b7efa7bfb52032d713f5907755838c01a6e178a87a0ac170a279",
|
||||
"merkle_proof": null,
|
||||
"mmr_index": 13524184,
|
||||
"output_type": "Coinbase",
|
||||
"proof": null,
|
||||
"proof_hash": "6c2c10af5c4b6d2bcf71084c2bd9685ae91427f03a8b78736ab27d6c5bc7e4db",
|
||||
"spent": false
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"last_retrieved_height": 2299310
|
||||
}
|
||||
}
|
||||
}
|
||||
# "#
|
||||
# );
|
||||
```
|
||||
*/
|
||||
fn get_blocks(
|
||||
&self,
|
||||
start_height: u64,
|
||||
end_height: u64,
|
||||
max: u64,
|
||||
include_proof: Option<bool>,
|
||||
) -> Result<BlockListing, Error>;
|
||||
|
||||
/**
|
||||
Networked version of [Foreign::get_version](struct.Foreign.html#method.get_version).
|
||||
|
||||
|
@ -760,6 +1005,7 @@ where
|
|||
}
|
||||
Foreign::get_header(self, height, parsed_hash, commit)
|
||||
}
|
||||
|
||||
fn get_block(
|
||||
&self,
|
||||
height: Option<u64>,
|
||||
|
@ -775,6 +1021,16 @@ where
|
|||
Foreign::get_block(self, height, parsed_hash, commit)
|
||||
}
|
||||
|
||||
fn get_blocks(
|
||||
&self,
|
||||
start_height: u64,
|
||||
end_height: u64,
|
||||
max: u64,
|
||||
include_proof: Option<bool>,
|
||||
) -> Result<BlockListing, Error> {
|
||||
Foreign::get_blocks(self, start_height, end_height, max, include_proof)
|
||||
}
|
||||
|
||||
fn get_version(&self) -> Result<Version, Error> {
|
||||
Foreign::get_version(self)
|
||||
}
|
||||
|
|
|
@ -24,6 +24,8 @@ use hyper::{Body, Request, StatusCode};
|
|||
use regex::Regex;
|
||||
use std::sync::Weak;
|
||||
|
||||
pub const BLOCK_TRANSFER_LIMIT: u64 = 1000;
|
||||
|
||||
/// Gets block headers given either a hash or height or an output commit.
|
||||
/// GET /v1/headers/<hash>
|
||||
/// GET /v1/headers/<height>
|
||||
|
@ -138,6 +140,69 @@ impl BlockHandler {
|
|||
.map_err(|_| Error::Internal("chain error".to_owned()))
|
||||
}
|
||||
|
||||
pub fn get_blocks(
|
||||
&self,
|
||||
mut start_height: u64,
|
||||
end_height: u64,
|
||||
mut max: u64,
|
||||
include_proof: Option<bool>,
|
||||
) -> Result<BlockListing, Error> {
|
||||
// set a limit here
|
||||
if max > BLOCK_TRANSFER_LIMIT {
|
||||
max = BLOCK_TRANSFER_LIMIT;
|
||||
}
|
||||
let tail_height = self.get_tail_height()?;
|
||||
|
||||
if start_height < tail_height {
|
||||
start_height = tail_height;
|
||||
}
|
||||
|
||||
let mut result_set = BlockListing {
|
||||
last_retrieved_height: 0,
|
||||
blocks: vec![],
|
||||
};
|
||||
let mut block_count = 0;
|
||||
for h in start_height..=end_height {
|
||||
result_set.last_retrieved_height = h;
|
||||
|
||||
let hash = match self.parse_inputs(Some(h), None, None) {
|
||||
Err(e) => {
|
||||
if let Error::NotFound = e {
|
||||
continue;
|
||||
} else {
|
||||
return Err(e);
|
||||
}
|
||||
}
|
||||
Ok(h) => h,
|
||||
};
|
||||
|
||||
let block_res = self.get_block(&hash, include_proof == Some(true), false);
|
||||
|
||||
match block_res {
|
||||
Err(e) => {
|
||||
if let Error::NotFound = e {
|
||||
continue;
|
||||
} else {
|
||||
return Err(e);
|
||||
}
|
||||
}
|
||||
Ok(b) => {
|
||||
block_count += 1;
|
||||
result_set.blocks.push(b);
|
||||
}
|
||||
}
|
||||
if block_count == max {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Ok(result_set)
|
||||
}
|
||||
|
||||
pub fn get_tail_height(&self) -> Result<u64, Error> {
|
||||
let chain = w(&self.chain)?;
|
||||
Ok(chain.get_tail().map_err(|_| Error::NotFound)?.height)
|
||||
}
|
||||
|
||||
fn get_compact_block(&self, h: &Hash) -> Result<CompactBlockPrintable, Error> {
|
||||
let chain = w(&self.chain)?;
|
||||
let block = chain.get_block(h).map_err(|_| Error::NotFound)?;
|
||||
|
|
|
@ -722,6 +722,15 @@ pub struct OutputListing {
|
|||
pub outputs: Vec<OutputPrintable>,
|
||||
}
|
||||
|
||||
// For traversing a set of all available blocks
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct BlockListing {
|
||||
/// The last height retrieved
|
||||
pub last_retrieved_height: u64,
|
||||
/// A printable version of the retrieved Blocks
|
||||
pub blocks: Vec<BlockPrintable>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct LocatedTxKernel {
|
||||
pub tx_kernel: TxKernel,
|
||||
|
|
|
@ -1445,6 +1445,13 @@ impl Chain {
|
|||
.map_err(|e| Error::StoreErr(e, "chain get block".to_owned()))
|
||||
}
|
||||
|
||||
/// Gets the earliest stored block (tail)
|
||||
pub fn get_tail(&self) -> Result<Tip, Error> {
|
||||
self.store
|
||||
.tail()
|
||||
.map_err(|e| Error::StoreErr(e, "chain get tail".to_owned()))
|
||||
}
|
||||
|
||||
/// Gets a block header by hash
|
||||
pub fn get_block_header(&self, h: &Hash) -> Result<BlockHeader, Error> {
|
||||
self.store
|
||||
|
|
Loading…
Reference in a new issue