Add rent estimation rpc (#6109)
* server side new rpc endpoint * client side rpc * take data_len as usize Co-Authored-By: Tyera Eulberg <teulberg@gmail.com> * add test and documentation
This commit is contained in:
parent
74a648accb
commit
67d07254c2
|
@ -30,6 +30,7 @@ To interact with a Solana node inside a JavaScript application, use the [solana-
|
|||
* [getStorageTurn](jsonrpc-api.md#getstorageturn)
|
||||
* [getStorageTurnRate](jsonrpc-api.md#getstorageturnrate)
|
||||
* [getNumBlocksSinceSignatureConfirmation](jsonrpc-api.md#getnumblockssincesignatureconfirmation)
|
||||
* [getMinimumBalanceForRentExemption](jsonrpc-api.md#getminimumbalanceforrentexemption)
|
||||
* [getTransactionCount](jsonrpc-api.md#gettransactioncount)
|
||||
* [getTotalSupply](jsonrpc-api.md#gettotalsupply)
|
||||
* [getVersion](jsonrpc-api.md#getversion)
|
||||
|
@ -455,6 +456,28 @@ curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0", "id":1, "
|
|||
{"jsonrpc":"2.0","result":8,"id":1}
|
||||
```
|
||||
|
||||
### getMinimumBalanceForRentExemption
|
||||
|
||||
Returns minimum balance required to make account rent exempt.
|
||||
|
||||
#### Parameters:
|
||||
|
||||
* `integer` - account data length, as unsigned integer
|
||||
|
||||
#### Results:
|
||||
|
||||
* `integer` - minimum lamports required in account, as unsigned 64-bit integer
|
||||
|
||||
#### Example:
|
||||
|
||||
```bash
|
||||
// Request
|
||||
curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0", "id":1, "method":"getMinimumBalanceForRentExemption", "params":[50]}' http://localhost:8899
|
||||
|
||||
// Result
|
||||
{"jsonrpc":"2.0","result":500,"id":1}
|
||||
```
|
||||
|
||||
### getTransactionCount
|
||||
|
||||
Returns the current Transaction count from the ledger
|
||||
|
|
|
@ -306,6 +306,35 @@ impl RpcClient {
|
|||
self.get_account(pubkey).map(|account| account.data)
|
||||
}
|
||||
|
||||
pub fn get_minimum_balance_for_rent_exemption(&self, data_len: usize) -> io::Result<u64> {
|
||||
let params = json!([data_len]);
|
||||
let minimum_balance_json = self
|
||||
.client
|
||||
.send(
|
||||
&RpcRequest::GetMinimumBalanceForRentExemption,
|
||||
Some(params),
|
||||
0,
|
||||
)
|
||||
.map_err(|err| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!(
|
||||
"GetMinimumBalanceForRentExemption request failure: {:?}",
|
||||
err
|
||||
),
|
||||
)
|
||||
})?;
|
||||
|
||||
let minimum_balance: u64 =
|
||||
serde_json::from_value(minimum_balance_json).expect("deserialize minimum_balance");
|
||||
trace!(
|
||||
"Response minimum balance {:?} {:?}",
|
||||
data_len,
|
||||
minimum_balance
|
||||
);
|
||||
Ok(minimum_balance)
|
||||
}
|
||||
|
||||
/// Request the balance of the user holding `pubkey`. This method blocks
|
||||
/// until the server sends a response. If the response packet is dropped
|
||||
/// by the network, this method will hang indefinitely.
|
||||
|
|
|
@ -28,6 +28,7 @@ pub enum RpcRequest {
|
|||
RequestAirdrop,
|
||||
SendTransaction,
|
||||
SignVote,
|
||||
GetMinimumBalanceForRentExemption,
|
||||
}
|
||||
|
||||
impl RpcRequest {
|
||||
|
@ -61,6 +62,7 @@ impl RpcRequest {
|
|||
RpcRequest::RequestAirdrop => "requestAirdrop",
|
||||
RpcRequest::SendTransaction => "sendTransaction",
|
||||
RpcRequest::SignVote => "signVote",
|
||||
RpcRequest::GetMinimumBalanceForRentExemption => "getMinimumBalanceForRentExemption",
|
||||
};
|
||||
let mut request = json!({
|
||||
"jsonrpc": jsonrpc,
|
||||
|
|
|
@ -73,6 +73,10 @@ impl JsonRpcRequestProcessor {
|
|||
.ok_or_else(Error::invalid_request)
|
||||
}
|
||||
|
||||
pub fn get_minimum_balance_for_rent_exemption(&self, data_len: usize) -> Result<u64> {
|
||||
Ok(self.bank().get_minimum_balance_for_rent_exemption(data_len))
|
||||
}
|
||||
|
||||
pub fn get_program_accounts(&self, program_id: &Pubkey) -> Result<Vec<(String, Account)>> {
|
||||
Ok(self
|
||||
.bank()
|
||||
|
@ -299,6 +303,9 @@ pub trait RpcSol {
|
|||
#[rpc(meta, name = "getProgramAccounts")]
|
||||
fn get_program_accounts(&self, _: Self::Metadata, _: String) -> Result<Vec<(String, Account)>>;
|
||||
|
||||
#[rpc(meta, name = "getMinimumBalanceForRentExemption")]
|
||||
fn get_minimum_balance_for_rent_exemption(&self, _: Self::Metadata, _: usize) -> Result<u64>;
|
||||
|
||||
#[rpc(meta, name = "getInflation")]
|
||||
fn get_inflation(&self, _: Self::Metadata) -> Result<Inflation>;
|
||||
|
||||
|
@ -407,6 +414,21 @@ impl RpcSol for RpcSolImpl {
|
|||
.get_account_info(&pubkey)
|
||||
}
|
||||
|
||||
fn get_minimum_balance_for_rent_exemption(
|
||||
&self,
|
||||
meta: Self::Metadata,
|
||||
data_len: usize,
|
||||
) -> Result<u64> {
|
||||
debug!(
|
||||
"get_minimum_balance_for_rent_exemption rpc request received: {:?}",
|
||||
data_len
|
||||
);
|
||||
meta.request_processor
|
||||
.read()
|
||||
.unwrap()
|
||||
.get_minimum_balance_for_rent_exemption(data_len)
|
||||
}
|
||||
|
||||
fn get_program_accounts(
|
||||
&self,
|
||||
meta: Self::Metadata,
|
||||
|
@ -877,6 +899,39 @@ pub mod tests {
|
|||
assert!(supply >= TEST_MINT_LAMPORTS);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rpc_get_minimum_balance_for_rent_exemption() {
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
let data_len = 50;
|
||||
let (io, meta, bank, _blockhash, _alice, _leader_pubkey) =
|
||||
start_rpc_handler_with_tx(&bob_pubkey);
|
||||
|
||||
let req = format!(
|
||||
r#"{{"jsonrpc":"2.0","id":1,"method":"getMinimumBalanceForRentExemption","params":[{}]}}"#,
|
||||
data_len
|
||||
);
|
||||
let rep = io.handle_request_sync(&req, meta);
|
||||
let res: Response = serde_json::from_str(&rep.expect("actual response"))
|
||||
.expect("actual response deserialization");
|
||||
let minimum_balance: u64 = if let Response::Single(res) = res {
|
||||
if let Output::Success(res) = res {
|
||||
if let Value::Number(num) = res.result {
|
||||
num.as_u64().unwrap()
|
||||
} else {
|
||||
panic!("Expected number");
|
||||
}
|
||||
} else {
|
||||
panic!("Expected success");
|
||||
}
|
||||
} else {
|
||||
panic!("Expected single response");
|
||||
};
|
||||
assert_eq!(
|
||||
minimum_balance,
|
||||
bank.get_minimum_balance_for_rent_exemption(data_len)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rpc_get_inflation() {
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
|
@ -1171,10 +1226,14 @@ pub mod tests {
|
|||
|
||||
fn new_bank_forks() -> (Arc<RwLock<BankForks>>, Keypair) {
|
||||
let GenesisBlockInfo {
|
||||
genesis_block,
|
||||
mut genesis_block,
|
||||
mint_keypair,
|
||||
..
|
||||
} = create_genesis_block(TEST_MINT_LAMPORTS);
|
||||
|
||||
genesis_block.rent_calculator.lamports_per_byte_year = 50;
|
||||
genesis_block.rent_calculator.exemption_threshold = 2.0;
|
||||
|
||||
let bank = Bank::new(&genesis_block);
|
||||
(
|
||||
Arc::new(RwLock::new(BankForks::new(bank.slot(), bank))),
|
||||
|
|
|
@ -679,6 +679,12 @@ impl Bank {
|
|||
self.blockhash_queue.read().unwrap().last_hash()
|
||||
}
|
||||
|
||||
pub fn get_minimum_balance_for_rent_exemption(&self, data_len: usize) -> u64 {
|
||||
self.rent_collector
|
||||
.rent_calculator
|
||||
.minimum_balance(data_len)
|
||||
}
|
||||
|
||||
pub fn last_blockhash_with_fee_calculator(&self) -> (Hash, FeeCalculator) {
|
||||
let blockhash_queue = self.blockhash_queue.read().unwrap();
|
||||
let last_hash = blockhash_queue.last_hash();
|
||||
|
|
Loading…
Reference in New Issue