Skip to content

Commit

Permalink
Adding additional GRPC endpoints for block explorer (#1922)
Browse files Browse the repository at this point in the history
Merge pull request #1922

The following endpoints have been added to the GRPC service based on the
core requirements.

GetConstants
GetBlockSize
GetBlockFees
GetVersion
GetTokensInCirculation
GetNetworkDifficulty

* pull/1922/head:
  Moving constants to proto
  • Loading branch information
sdbondi committed May 28, 2020
2 parents 060ab70 + e629046 commit ee06f9e
Show file tree
Hide file tree
Showing 10 changed files with 545 additions and 45 deletions.
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

0 comments on commit ee06f9e

Please sign in to comment.