Consolidate signature-status rpcs (#9069)

* getSignatureStatus: return confirmations for non-rooted transactions

* Remove getNumConfirmations.. rpc

* Remove getSignatureConfirmation

* Review comments

* More review comments
This commit is contained in:
Tyera Eulberg 2020-03-26 19:21:01 -06:00 committed by GitHub
parent 48031651a0
commit 4b97e58cba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 72 additions and 145 deletions

View File

@ -101,9 +101,16 @@ impl GenericRpcClientRequest for MockRpcClientRequest {
let status = if self.url == "sig_not_found" {
None
} else {
Some(TransactionStatus { status, slot: 1 })
Some(TransactionStatus {
status,
slot: 1,
confirmations: Some(0),
})
};
serde_json::to_value(vec![status])?
serde_json::to_value(Response {
context: RpcResponseContext { slot: 1 },
value: vec![status],
})?
}
RpcRequest::GetTransactionCount => Value::Number(Number::from(1234)),
RpcRequest::GetSlot => Value::Number(Number::from(0)),

View File

@ -120,9 +120,11 @@ impl RpcClient {
json!([[signature.to_string()], commitment_config]),
5,
)?;
let result: Vec<Option<TransactionStatus>> =
let result: Response<Vec<Option<TransactionStatus>>> =
serde_json::from_value(signature_status).unwrap();
Ok(result[0].clone().map(|status_meta| status_meta.status))
Ok(result.value[0]
.clone()
.map(|status_meta| status_meta.status))
}
pub fn get_slot(&self) -> ClientResult<Slot> {
@ -944,14 +946,25 @@ impl RpcClient {
let response = self
.client
.send(
&RpcRequest::GetNumBlocksSinceSignatureConfirmation,
json!([signature.to_string(), CommitmentConfig::recent().ok()]),
&RpcRequest::GetSignatureStatus,
json!([[signature.to_string()], CommitmentConfig::recent().ok()]),
1,
)
.map_err(|err| err.into_with_command("GetNumBlocksSinceSignatureConfirmation"))?;
serde_json::from_value(response).map_err(|err| {
ClientError::new_with_command(err.into(), "GetNumBlocksSinceSignatureConfirmation")
})
.map_err(|err| err.into_with_command("GetSignatureStatus"))?;
let result: Response<Vec<Option<TransactionStatus>>> =
serde_json::from_value(response).unwrap();
let confirmations = result.value[0]
.clone()
.ok_or_else(|| {
ClientError::new_with_command(
ClientErrorKind::Custom("signature not found".to_string()),
"GetSignatureStatus",
)
})?
.confirmations
.unwrap_or(MAX_LOCKOUT_HISTORY + 1);
Ok(confirmations)
}
pub fn send_and_confirm_transaction_with_spinner<T: Signers>(

View File

@ -18,7 +18,6 @@ pub enum RpcRequest {
GetIdentity,
GetInflation,
GetLeaderSchedule,
GetNumBlocksSinceSignatureConfirmation,
GetProgramAccounts,
GetRecentBlockhash,
GetFeeCalculatorForBlockhash,
@ -61,9 +60,6 @@ impl RpcRequest {
RpcRequest::GetIdentity => "getIdentity",
RpcRequest::GetInflation => "getInflation",
RpcRequest::GetLeaderSchedule => "getLeaderSchedule",
RpcRequest::GetNumBlocksSinceSignatureConfirmation => {
"getNumBlocksSinceSignatureConfirmation"
}
RpcRequest::GetProgramAccounts => "getProgramAccounts",
RpcRequest::GetRecentBlockhash => "getRecentBlockhash",
RpcRequest::GetFeeCalculatorForBlockhash => "getFeeCalculatorForBlockhash",

View File

@ -217,25 +217,6 @@ impl JsonRpcRequestProcessor {
}
}
pub fn get_signature_confirmation_status(
&self,
signature: Signature,
commitment: Option<CommitmentConfig>,
) -> Option<RpcSignatureConfirmation> {
self.bank(commitment)
.get_signature_confirmation_status(&signature)
.map(
|SignatureConfirmationStatus {
confirmations,
status,
..
}| RpcSignatureConfirmation {
confirmations,
status,
},
)
}
fn get_slot(&self, commitment: Option<CommitmentConfig>) -> Result<u64> {
Ok(self.bank(commitment).slot())
}
@ -422,21 +403,33 @@ impl JsonRpcRequestProcessor {
&self,
signatures: Vec<Signature>,
commitment: Option<CommitmentConfig>,
) -> Result<Vec<Option<TransactionStatus>>> {
) -> RpcResponse<Vec<Option<TransactionStatus>>> {
let mut statuses: Vec<Option<TransactionStatus>> = vec![];
let bank = self.bank(commitment);
for signature in signatures {
let status = bank.get_signature_confirmation_status(&signature).map(
|SignatureConfirmationStatus { slot, status, .. }| TransactionStatus {
|SignatureConfirmationStatus {
slot,
status,
confirmations,
}| TransactionStatus {
slot,
status,
confirmations: if confirmations <= MAX_LOCKOUT_HISTORY {
Some(confirmations)
} else {
None
},
},
);
statuses.push(status);
}
Ok(statuses)
Ok(Response {
context: RpcResponseContext { slot: bank.slot() },
value: statuses,
})
}
}
@ -566,7 +559,7 @@ pub trait RpcSol {
meta: Self::Metadata,
signature_strs: Vec<String>,
commitment: Option<CommitmentConfig>,
) -> Result<Vec<Option<TransactionStatus>>>;
) -> RpcResponse<Vec<Option<TransactionStatus>>>;
#[rpc(meta, name = "getSlot")]
fn get_slot(&self, meta: Self::Metadata, commitment: Option<CommitmentConfig>) -> Result<u64>;
@ -633,22 +626,6 @@ pub trait RpcSol {
#[rpc(meta, name = "validatorExit")]
fn validator_exit(&self, meta: Self::Metadata) -> Result<bool>;
#[rpc(meta, name = "getNumBlocksSinceSignatureConfirmation")]
fn get_num_blocks_since_signature_confirmation(
&self,
meta: Self::Metadata,
signature_str: String,
commitment: Option<CommitmentConfig>,
) -> Result<Option<usize>>;
#[rpc(meta, name = "getSignatureConfirmation")]
fn get_signature_confirmation(
&self,
meta: Self::Metadata,
signature_str: String,
commitment: Option<CommitmentConfig>,
) -> Result<Option<RpcSignatureConfirmation>>;
#[rpc(meta, name = "getIdentity")]
fn get_identity(&self, meta: Self::Metadata) -> Result<RpcIdentity>;
@ -912,7 +889,7 @@ impl RpcSol for RpcSolImpl {
meta: Self::Metadata,
signature_strs: Vec<String>,
commitment: Option<CommitmentConfig>,
) -> Result<Vec<Option<TransactionStatus>>> {
) -> RpcResponse<Vec<Option<TransactionStatus>>> {
let mut signatures: Vec<Signature> = vec![];
for signature_str in signature_strs {
signatures.push(verify_signature(&signature_str)?);
@ -927,34 +904,6 @@ impl RpcSol for RpcSolImpl {
meta.request_processor.read().unwrap().get_slot(commitment)
}
fn get_num_blocks_since_signature_confirmation(
&self,
meta: Self::Metadata,
signature_str: String,
commitment: Option<CommitmentConfig>,
) -> Result<Option<usize>> {
self.get_signature_confirmation(meta, signature_str, commitment)
.map(|res| res.map(|x| x.confirmations))
}
fn get_signature_confirmation(
&self,
meta: Self::Metadata,
signature_str: String,
commitment: Option<CommitmentConfig>,
) -> Result<Option<RpcSignatureConfirmation>> {
debug!(
"get_signature_confirmation rpc request received: {:?}",
signature_str
);
let signature = verify_signature(&signature_str)?;
Ok(meta
.request_processor
.read()
.unwrap()
.get_signature_confirmation_status(signature, commitment))
}
fn get_transaction_count(
&self,
meta: Self::Metadata,
@ -1041,7 +990,9 @@ impl RpcSol for RpcSolImpl {
.request_processor
.read()
.unwrap()
.get_signature_confirmation_status(signature, commitment.clone())
.get_signature_status(vec![signature], commitment.clone())?
.value[0]
.clone()
.map(|x| x.status);
if signature_status == Some(Ok(())) {
@ -1816,9 +1767,10 @@ pub mod tests {
let res = io.handle_request_sync(&req, meta.clone());
let expected_res: transaction::Result<()> = Ok(());
let json: Value = serde_json::from_str(&res.unwrap()).unwrap();
let result: Vec<Option<TransactionStatus>> = serde_json::from_value(json["result"].clone())
.expect("actual response deserialization");
assert_eq!(expected_res, result[0].as_ref().unwrap().status);
let result: Option<TransactionStatus> =
serde_json::from_value(json["result"]["value"][0].clone())
.expect("actual response deserialization");
assert_eq!(expected_res, result.as_ref().unwrap().status);
// Test getSignatureStatus request on unprocessed tx
let tx = system_transaction::transfer(&alice, &bob_pubkey, 10, blockhash);
@ -1828,9 +1780,10 @@ pub mod tests {
);
let res = io.handle_request_sync(&req, meta.clone());
let json: Value = serde_json::from_str(&res.unwrap()).unwrap();
let result: Vec<Option<TransactionStatus>> = serde_json::from_value(json["result"].clone())
.expect("actual response deserialization");
assert!(result[0].is_none());
let result: Option<TransactionStatus> =
serde_json::from_value(json["result"]["value"][0].clone())
.expect("actual response deserialization");
assert!(result.is_none());
// Test getSignatureStatus request on a TransactionError
let req = format!(
@ -1843,9 +1796,10 @@ pub mod tests {
InstructionError::CustomError(1),
));
let json: Value = serde_json::from_str(&res.unwrap()).unwrap();
let result: Vec<Option<TransactionStatus>> = serde_json::from_value(json["result"].clone())
.expect("actual response deserialization");
assert_eq!(expected_res, result[0].as_ref().unwrap().status);
let result: Option<TransactionStatus> =
serde_json::from_value(json["result"]["value"][0].clone())
.expect("actual response deserialization");
assert_eq!(expected_res, result.as_ref().unwrap().status);
}
#[test]

View File

@ -31,10 +31,8 @@ To interact with a Solana node inside a JavaScript application, use the [solana-
* [getInflation](jsonrpc-api.md#getinflation)
* [getLeaderSchedule](jsonrpc-api.md#getleaderschedule)
* [getMinimumBalanceForRentExemption](jsonrpc-api.md#getminimumbalanceforrentexemption)
* [getNumBlocksSinceSignatureConfirmation](jsonrpc-api.md#getnumblockssincesignatureconfirmation)
* [getProgramAccounts](jsonrpc-api.md#getprogramaccounts)
* [getRecentBlockhash](jsonrpc-api.md#getrecentblockhash)
* [getSignatureConfirmation](jsonrpc-api.md#getsignatureconfirmation)
* [getSignatureStatus](jsonrpc-api.md#getsignaturestatus)
* [getSlot](jsonrpc-api.md#getslot)
* [getSlotLeader](jsonrpc-api.md#getslotleader)
@ -580,29 +578,6 @@ curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0", "id":1, "
{"jsonrpc":"2.0","result":500,"id":1}
```
### getNumBlocksSinceSignatureConfirmation
Returns the current number of blocks since signature has been confirmed.
#### Parameters:
* `<string>` - Signature of Transaction to confirm, as base-58 encoded string
* `<object>` - (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment)
#### Results:
* `<u64>` - count, or null if signature not found
#### Example:
```bash
// Request
curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0", "id":1, "method":"getNumBlocksSinceSignatureConfirmation", "params":["5VERv8NMvzbJMEkV8xnrLkEaWRtSz9CosKDYjCJjBRnbJLgp8uirBgmQpjKhoR4tjF3ZpRzrFmBV6UjKdiSZkQUW"]}' http://localhost:8899
// Result
{"jsonrpc":"2.0","result":8,"id":1}
```
### getProgramAccounts
Returns all accounts owned by the provided program Pubkey
@ -660,33 +635,6 @@ curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1, "m
{"jsonrpc":"2.0","result":{"context":{"slot":1},"value":{"blockhash":"CSymwgTNX1j3E4qhKfJAUE41nBWEwXufoYryPbkde5RR","feeCalculator":{"burnPercent":50,"lamportsPerSignature":5000,"maxLamportsPerSignature":100000,"minLamportsPerSignature":5000,"targetLamportsPerSignature":10000,"targetSignaturesPerSlot":20000}}},"id":1}
```
### getSignatureConfirmation
Returns the status and number of confirmations of a given signature.
#### Parameters:
* `<string>` - Signature of Transaction to confirm, as base-58 encoded string
* `<object>` - (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment)
#### Results:
* `<null>` - Unknown transaction
* `<object>` - Transaction confirmations and status:
* `confirmations: <u64>` - count of confirmations since transaction was processed
* `status: <object>` -
* `"Ok": <null>` - Transaction was successful
* `"Err": <ERR>` - Transaction failed with TransactionError [TransactionError definitions](https://github.com/solana-labs/solana/blob/master/sdk/src/transaction.rs#L14)
#### Example:
```bash
// Request
curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0", "id":1, "method":"getSignatureConfirmation", "params":["5VERv8NMvzbJMEkV8xnrLkEaWRtSz9CosKDYjCJjBRnbJLgp8uirBgmQpjKhoR4tjF3ZpRzrFmBV6UjKdiSZkQUW"]}' http://localhost:8899
// Result
{"jsonrpc":"2.0","result":{"confirmations":12,"status":{"Ok": null}},"id":1}
```
### getSignatureStatus
Returns the status of a given signature. This method is similar to [confirmTransaction](jsonrpc-api.md#confirmtransaction) but provides more resolution for error events.
@ -700,11 +648,16 @@ Returns the status of a given signature. This method is similar to [confirmTrans
#### Results:
An RpcResponse containing a JSON object consisting of an array of TransactionStatus objects.
* `RpcResponse<object>` - RpcResponse JSON object with `value` field:
An array of:
* `<null>` - Unknown transaction
* `<object>`
* `slot: <u64>` - The slot the transaction was processed
* `confirmations: <usize | null>` - Number of blocks since signature confirmation, null if rooted
* `status: <object>` - Transaction status
* `"Ok": <null>` - Transaction was successful
* `"Err": <ERR>` - Transaction failed with TransactionError [TransactionError definitions](https://github.com/solana-labs/solana/blob/master/sdk/src/transaction.rs#L14)
@ -716,7 +669,10 @@ An array of:
curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0", "id":1, "method":"getSignatureStatus", "params":[["5VERv8NMvzbJMEkV8xnrLkEaWRtSz9CosKDYjCJjBRnbJLgp8uirBgmQpjKhoR4tjF3ZpRzrFmBV6UjKdiSZkQUW", "5j7s6NiJS3JAkvgkoc18WVAsiSaci2pxB2A6ueCJP4tprA2TFg9wSyTLeYouxPBJEMzJinENTkpA52YStRW5Dia7"]]]}' http://localhost:8899
// Result
{"jsonrpc":"2.0","result":[{"slot": 72, "status": {"Ok": null}}, null],"id":1}
{"jsonrpc":"2.0","result":{"context":{"slot":82},"value":[{"slot": 72, "confirmations": 10, "status": {"Ok": null}}, null]},"id":1}
// Result, first transaction rooted
{"jsonrpc":"2.0","result":{"context":{"slot":82},"value":[{"slot": 48, "confirmations": null, "status": {"Ok": null}}, null]},"id":1}
```
### getSlot

View File

@ -30,6 +30,7 @@ pub struct TransactionStatusMeta {
#[serde(rename_all = "camelCase")]
pub struct TransactionStatus {
pub slot: Slot,
pub confirmations: Option<usize>,
pub status: Result<()>,
}