Skip to content

Commit

Permalink
Add v0 REST APIs for circulating and total supply (#10102)
Browse files Browse the repository at this point in the history
(cherry picked from commit 324cfd4)
  • Loading branch information
mvines committed May 21, 2020
1 parent 2333468 commit 7f21b03
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 25 deletions.
8 changes: 4 additions & 4 deletions core/src/non_circulating_supply.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ pub struct NonCirculatingSupply {
pub accounts: Vec<Pubkey>,
}

pub fn calculate_non_circulating_supply(bank: Arc<Bank>) -> NonCirculatingSupply {
pub fn calculate_non_circulating_supply(bank: &Arc<Bank>) -> NonCirculatingSupply {
debug!("Updating Bank supply, epoch: {}", bank.epoch());
let mut non_circulating_accounts_set: HashSet<Pubkey> = HashSet::new();

Expand Down Expand Up @@ -149,7 +149,7 @@ mod tests {
(num_genesis_accounts + num_non_circulating_accounts + num_stake_accounts) * balance
);

let non_circulating_supply = calculate_non_circulating_supply(bank.clone());
let non_circulating_supply = calculate_non_circulating_supply(&bank);
assert_eq!(
non_circulating_supply.lamports,
(num_non_circulating_accounts + num_stake_accounts) * balance
Expand All @@ -164,7 +164,7 @@ mod tests {
for key in non_circulating_accounts {
bank.store_account(&key, &Account::new(new_balance, 0, &Pubkey::default()));
}
let non_circulating_supply = calculate_non_circulating_supply(bank.clone());
let non_circulating_supply = calculate_non_circulating_supply(&bank);
assert_eq!(
non_circulating_supply.lamports,
(num_non_circulating_accounts * new_balance) + (num_stake_accounts * balance)
Expand All @@ -179,7 +179,7 @@ mod tests {
bank = Arc::new(new_from_parent(&bank));
}
assert_eq!(bank.epoch(), 1);
let non_circulating_supply = calculate_non_circulating_supply(bank.clone());
let non_circulating_supply = calculate_non_circulating_supply(&bank);
assert_eq!(
non_circulating_supply.lamports,
num_non_circulating_accounts * new_balance
Expand Down
2 changes: 1 addition & 1 deletion core/src/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ impl JsonRpcRequestProcessor {

fn get_supply(&self, commitment: Option<CommitmentConfig>) -> RpcResponse<RpcSupply> {
let bank = self.bank(commitment)?;
let non_circulating_supply = calculate_non_circulating_supply(bank.clone());
let non_circulating_supply = calculate_non_circulating_supply(&bank);
let total_supply = bank.capitalization();
new_response(
&bank,
Expand Down
112 changes: 92 additions & 20 deletions core/src/rpc_service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ struct RpcRequestMiddleware {
snapshot_config: Option<SnapshotConfig>,
cluster_info: Arc<RwLock<ClusterInfo>>,
trusted_validators: Option<HashSet<Pubkey>>,
bank_forks: Arc<RwLock<BankForks>>,
}

impl RpcRequestMiddleware {
Expand All @@ -52,6 +53,7 @@ impl RpcRequestMiddleware {
snapshot_config: Option<SnapshotConfig>,
cluster_info: Arc<RwLock<ClusterInfo>>,
trusted_validators: Option<HashSet<Pubkey>>,
bank_forks: Arc<RwLock<BankForks>>,
) -> Self {
Self {
ledger_path,
Expand All @@ -60,6 +62,7 @@ impl RpcRequestMiddleware {
snapshot_config,
cluster_info,
trusted_validators,
bank_forks,
}
}

Expand All @@ -85,7 +88,7 @@ impl RpcRequestMiddleware {
.unwrap()
}

fn is_get_path(&self, path: &str) -> bool {
fn is_file_get_path(&self, path: &str) -> bool {
match path {
"/genesis.tar.bz2" => true,
_ => {
Expand All @@ -98,7 +101,7 @@ impl RpcRequestMiddleware {
}
}

fn get(&self, path: &str) -> RequestMiddlewareAction {
fn process_file_get(&self, path: &str) -> RequestMiddlewareAction {
let filename = self.ledger_path.join(
path.split_at(1).1, // Drop leading '/' from path
);
Expand Down Expand Up @@ -202,8 +205,19 @@ impl RequestMiddleware for RpcRequestMiddleware {
};
}
}
if self.is_get_path(request.uri().path()) {
self.get(request.uri().path())

if let Some(result) = process_rest(&self.bank_forks, request.uri().path()) {
RequestMiddlewareAction::Respond {
should_validate_hosts: true,
response: Box::new(jsonrpc_core::futures::future::ok(
hyper::Response::builder()
.status(hyper::StatusCode::OK)
.body(hyper::Body::from(result))
.unwrap(),
)),
}
} else if self.is_file_get_path(request.uri().path()) {
self.process_file_get(request.uri().path())
} else if request.uri().path() == "/health" {
RequestMiddlewareAction::Respond {
should_validate_hosts: true,
Expand All @@ -223,6 +237,26 @@ impl RequestMiddleware for RpcRequestMiddleware {
}
}

fn process_rest(bank_forks: &Arc<RwLock<BankForks>>, path: &str) -> Option<String> {
match path {
"/v0/circulating-supply" => {
let r_bank_forks = bank_forks.read().unwrap();
let bank = r_bank_forks.root_bank();
let total_supply = bank.capitalization();
let non_circulating_supply =
crate::non_circulating_supply::calculate_non_circulating_supply(&bank).lamports;
Some(format!("{}", total_supply - non_circulating_supply))
}
"/v0/total-supply" => {
let r_bank_forks = bank_forks.read().unwrap();
let bank = r_bank_forks.root_bank();
let total_supply = bank.capitalization();
Some(format!("{}", total_supply))
}
_ => None,
}
}

impl JsonRpcService {
#[allow(clippy::too_many_arguments)]
pub fn new(
Expand All @@ -243,7 +277,7 @@ impl JsonRpcService {
info!("rpc configuration: {:?}", config);
let request_processor = Arc::new(RwLock::new(JsonRpcRequestProcessor::new(
config,
bank_forks,
bank_forks.clone(),
block_commitment_cache,
blockstore,
storage_state,
Expand All @@ -268,6 +302,7 @@ impl JsonRpcService {
snapshot_config,
cluster_info.clone(),
trusted_validators,
bank_forks.clone(),
);
let server = ServerBuilder::with_meta_extractor(
io,
Expand Down Expand Up @@ -397,13 +432,41 @@ mod tests {
rpc_service.join().unwrap();
}

fn create_bank_forks() -> Arc<RwLock<BankForks>> {
let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
let bank = Bank::new(&genesis_config);
Arc::new(RwLock::new(BankForks::new(bank.slot(), bank)))
}

#[test]
fn test_is_get_path() {
fn test_process_rest_api() {
let bank_forks = create_bank_forks();

assert_eq!(None, process_rest(&bank_forks, "not-a-supported-rest-api"));
assert_eq!(
Some("10127".to_string()),
process_rest(&bank_forks, "/v0/circulating-supply")
);
assert_eq!(
Some("10127".to_string()),
process_rest(&bank_forks, "/v0/total-supply")
);
}

#[test]
fn test_is_file_get_path() {
let cluster_info = Arc::new(RwLock::new(ClusterInfo::new_with_invalid_keypair(
ContactInfo::default(),
)));
let bank_forks = create_bank_forks();

let rrm = RpcRequestMiddleware::new(PathBuf::from("/"), None, cluster_info.clone(), None);
let rrm = RpcRequestMiddleware::new(
PathBuf::from("/"),
None,
cluster_info.clone(),
None,
bank_forks.clone(),
);
let rrm_with_snapshot_config = RpcRequestMiddleware::new(
PathBuf::from("/"),
Some(SnapshotConfig {
Expand All @@ -413,26 +476,28 @@ mod tests {
}),
cluster_info,
None,
bank_forks,
);

assert!(rrm.is_get_path("/genesis.tar.bz2"));
assert!(!rrm.is_get_path("genesis.tar.bz2"));
assert!(rrm.is_file_get_path("/genesis.tar.bz2"));
assert!(!rrm.is_file_get_path("genesis.tar.bz2"));

assert!(!rrm.is_get_path("/snapshot.tar.bz2")); // This is a redirect
assert!(!rrm.is_file_get_path("/snapshot.tar.bz2")); // This is a redirect

assert!(
!rrm.is_get_path("/snapshot-100-AvFf9oS8A8U78HdjT9YG2sTTThLHJZmhaMn2g8vkWYnr.tar.bz2")
);
assert!(rrm_with_snapshot_config
.is_get_path("/snapshot-100-AvFf9oS8A8U78HdjT9YG2sTTThLHJZmhaMn2g8vkWYnr.tar.bz2"));
assert!(!rrm.is_file_get_path(
"/snapshot-100-AvFf9oS8A8U78HdjT9YG2sTTThLHJZmhaMn2g8vkWYnr.tar.bz2"
));
assert!(rrm_with_snapshot_config.is_file_get_path(
"/snapshot-100-AvFf9oS8A8U78HdjT9YG2sTTThLHJZmhaMn2g8vkWYnr.tar.bz2"
));

assert!(!rrm.is_get_path(
assert!(!rrm.is_file_get_path(
"/snapshot-notaslotnumber-AvFf9oS8A8U78HdjT9YG2sTTThLHJZmhaMn2g8vkWYnr.tar.bz2"
));

assert!(!rrm.is_get_path("/"));
assert!(!rrm.is_get_path(".."));
assert!(!rrm.is_get_path("🎣"));
assert!(!rrm.is_file_get_path("/"));
assert!(!rrm.is_file_get_path(".."));
assert!(!rrm.is_file_get_path("🎣"));
}

#[test]
Expand All @@ -441,7 +506,13 @@ mod tests {
ContactInfo::default(),
)));

let rm = RpcRequestMiddleware::new(PathBuf::from("/"), None, cluster_info.clone(), None);
let rm = RpcRequestMiddleware::new(
PathBuf::from("/"),
None,
cluster_info.clone(),
None,
create_bank_forks(),
);
assert_eq!(rm.health_check(), "ok");
}

Expand All @@ -457,6 +528,7 @@ mod tests {
None,
cluster_info.clone(),
Some(trusted_validators.clone().into_iter().collect()),
create_bank_forks(),
);

// No account hashes for this node or any trusted validators == "behind"
Expand Down

0 comments on commit 7f21b03

Please sign in to comment.