Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding additional GRPC endpoints for block explorer #1922

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 100 additions & 3 deletions applications/tari_base_node/proto/base_node.proto
Original file line number Diff line number Diff line change
Expand Up @@ -26,20 +26,86 @@ package tari.base_node;
import "google/protobuf/wrappers.proto";
import "google/protobuf/timestamp.proto";


// The gRPC interface for interacting with the base node.
service BaseNode {
// Lists headers in the current best chain
rpc ListHeaders(ListHeadersRequest) returns (stream BlockHeader);
// Returns blocks in the current best chain. Currently only supports querying by height
rpc GetBlocks(GetBlocksRequest) returns (stream HistoricalBlock);
// Returns the calc timing for the chain heights
rpc GetCalcTiming(GetCalcTimingRequest) returns (CalcTimingResponse);
rpc GetCalcTiming(HeightRequest) returns (CalcTimingResponse);
// Returns the network Constants
rpc GetConstants(Empty) returns (ConsensusConstants);
// Returns Block Sizes
rpc GetBlockSize (BlockGroupRequest) returns (BlockGroupResponse);
// Returns Block Fees
rpc GetBlockFees (BlockGroupRequest) returns (BlockGroupResponse);
// Get Version
rpc GetVersion(Empty) returns (StringValue);
// Get coins in circulation
rpc GetTokensInCirculation(IntegerValue) returns (IntegerValue);
// Get network difficulties
rpc GetNetworkDifficulty(HeightRequest) returns (stream NetworkDifficultyResponse);
}

/// An Empty placeholder for endpoints without request parameters
message Empty {}

// Network difficulty response
message NetworkDifficultyResponse {
uint64 difficulty = 1;
uint64 estimated_hash_rate = 2;
uint64 height = 3;
}

// A generic single value response for a specific height
message ValueAtHeightResponse {
uint64 value= 1;
uint64 height = 2;
}

// A generic uint value
message IntegerValue {
uint64 value = 1;
}

// A generic String value
message StringValue {
string value = 1;
}

/// GetBlockSize / GetBlockFees Request
/// Either the starting and ending heights OR the from_tip param must be specified
message BlockGroupRequest {
// The height from the chain tip (optional)
uint64 from_tip = 1;
// The starting height (optional)
uint64 start_height = 2;
// The ending height (optional)
uint64 end_height = 3;
/// The type of calculation required (optional)
/// Defaults to median
/// median, mean, quartile, quantile
CalcType calc_type = 4;
}

/// GetBlockSize / GetBlockFees Response
message BlockGroupResponse {
repeated double value = 1;
CalcType calc_type = 2;
}

enum CalcType {
MEAN = 0;
MEDIAN = 1;
QUANTILE = 2;
QUARTILE = 3;
}

// The request used for querying the calc timing from the base node.
// The request used for querying a function that requires a height, either between 2 points or from the chain tip
// If start_height and end_height are set and > 0, they take precedence, otherwise from_tip is used
message GetCalcTimingRequest {
message HeightRequest {
// The height from the chain tip (optional)
uint64 from_tip = 1;
// The starting height (optional)
Expand All @@ -48,6 +114,37 @@ message GetCalcTimingRequest {
uint64 end_height = 3;
}

/// Consensus Constants response
message ConsensusConstants {
/// The min height maturity a coinbase utxo must have
uint64 coinbase_lock_height = 1;
/// Current version of the blockchain
uint32 blockchain_version = 2;
/// The Future Time Limit (FTL) of the blockchain in seconds. This is the max allowable timestamp that is excepted.
/// We use TxN/20 where T = target time = 60 seconds, and N = block_window = 150
uint64 future_time_limit = 3;
/// This is the our target time in seconds between blocks
uint64 target_block_interval = 4;
/// When doing difficulty adjustments and FTL calculations this is the amount of blocks we look at
uint64 difficulty_block_window = 5;
/// When doing difficulty adjustments, this is the maximum block time allowed
uint64 difficulty_max_block_interval = 6;
/// Maximum transaction weight used for the construction of new blocks.
uint64 max_block_transaction_weight = 7;
/// The amount of PoW algorithms used by the Tari chain.
uint64 pow_algo_count = 8;
/// This is how many blocks we use to count towards the median timestamp to ensure the block chain moves forward
uint64 median_timestamp_count = 9;
/// This is the initial emission curve amount
uint64 emission_initial = 10;
/// This is the emission curve delay
double emission_decay = 11;
/// This is the emission curve tail amount
uint64 emission_tail = 12;
/// This is the initial min difficulty for the difficulty adjustment
uint64 min_blake_pow_difficulty = 13;
}

// The return type of the rpc GetCalcTiming
message CalcTimingResponse {
uint64 max = 1;
Expand Down
75 changes: 75 additions & 0 deletions applications/tari_base_node/src/grpc/blocks.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// Copyright 2019. The Tari Project
//
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
// following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
// disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
// following disclaimer in the documentation and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
// products derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

use tari_core::{base_node::LocalNodeCommsInterface, blocks::BlockHeader, chain_storage::HistoricalBlock};
use tonic::Status;

// The maximum number of blocks that can be requested at a time. These will be streamed to the
// client, so memory is not really a concern here, but a malicious client could request a large
// number here to keep the node busy
pub const GET_BLOCKS_MAX_HEIGHTS: usize = 1000;

// The number of blocks to request from the base node at a time. This is to reduce the number of
// requests to the base node, but if you'd like to stream directly, this can be set to 1.
pub const GET_BLOCKS_PAGE_SIZE: usize = 10;

/// Magic number for input and output sizes
pub const BLOCK_INPUT_SIZE: u64 = 4;
pub const BLOCK_OUTPUT_SIZE: u64 = 13;

/// Returns the block heights based on the start and end heights or from_tip
pub async fn block_heights(
handler: LocalNodeCommsInterface,
start_height: u64,
end_height: u64,
from_tip: u64,
) -> Result<Vec<u64>, Status>
{
let heights = if start_height > 0 && end_height > 0 {
Ok(BlockHeader::get_height_range(start_height, end_height))
} else if from_tip > 0 {
BlockHeader::get_heights_from_tip(handler, from_tip)
.await
.map_err(|e| Status::internal(e.to_string()))
} else {
return Err(Status::invalid_argument("Invalid arguments provided"));
};
heights
}

pub fn block_size(block: &HistoricalBlock) -> u64 {
let body = block.clone().block.body;

let input_size = body.inputs().len() as u64 * BLOCK_INPUT_SIZE;
let output_size = body.outputs().len() as u64 * BLOCK_OUTPUT_SIZE;
input_size + output_size
}

pub fn block_fees(block: &HistoricalBlock) -> u64 {
let body = block.clone().block.body;
body.kernels()
.iter()
.map(|k| k.fee.into())
.collect::<Vec<u64>>()
.iter()
.sum::<u64>()
}
72 changes: 72 additions & 0 deletions applications/tari_base_node/src/grpc/helpers.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// Copyright 2019. The Tari Project
//
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
// following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
// disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
// following disclaimer in the documentation and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
// products derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

pub fn median(mut list: Vec<u64>) -> Option<f64> {
if list.is_empty() {
return None;
}
list.sort();
let mid_index = list.len() / 2;
let median = if list.len() % 2 == 0 {
(list[mid_index - 1] + list[mid_index]) as f64 / 2.0
} else {
list[mid_index] as f64
};
Some(median)
}

pub fn mean(list: Vec<u64>) -> Option<f64> {
if list.is_empty() {
return None;
}
let mut count = 0;
let total = list.iter().inspect(|_| count += 1).sum::<u64>();
Some(total as f64 / count as f64)
}
/// TODO Implement the function for grpc responsed
pub fn quantile(_list: Vec<u64>) -> Option<f64> {
None
}

/// TODO Implement the function for grpc responsed
pub fn quartile(_list: Vec<u64>) -> Option<f64> {
None
}

#[cfg(test)]
pub mod test {
use super::*;

#[test]
fn median() {
let mut values = vec![1u64, 8u64, 3u64, 9u64];
let median_value = super::median(values);
assert_eq!(median_value, Some(5.5f64))
}

#[test]
fn mean() {
let values = vec![1u64, 8u64, 3u64, 9u64];
let mean_value = super::mean(values);
assert_eq!(mean_value, Some(5.25f64))
}
}
3 changes: 3 additions & 0 deletions applications/tari_base_node/src/grpc/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub mod blocks;
pub mod helpers;
pub mod server;
Loading