From 4b97e58cba2b15ea0ba6dc8996518b3bf0d9b7a4 Mon Sep 17 00:00:00 2001 From: Tyera Eulberg Date: Thu, 26 Mar 2020 19:21:01 -0600 Subject: [PATCH] Consolidate signature-status rpcs (#9069) * getSignatureStatus: return confirmations for non-rooted transactions * Remove getNumConfirmations.. rpc * Remove getSignatureConfirmation * Review comments * More review comments --- client/src/mock_rpc_client_request.rs | 11 ++- client/src/rpc_client.rs | 29 +++++-- client/src/rpc_request.rs | 4 - core/src/rpc.rs | 110 ++++++++------------------ docs/src/apps/jsonrpc-api.md | 62 +++------------ transaction-status/src/lib.rs | 1 + 6 files changed, 72 insertions(+), 145 deletions(-) diff --git a/client/src/mock_rpc_client_request.rs b/client/src/mock_rpc_client_request.rs index 91d3b6754..e1ebccb86 100644 --- a/client/src/mock_rpc_client_request.rs +++ b/client/src/mock_rpc_client_request.rs @@ -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)), diff --git a/client/src/rpc_client.rs b/client/src/rpc_client.rs index 7776bbfdb..71b1522a7 100644 --- a/client/src/rpc_client.rs +++ b/client/src/rpc_client.rs @@ -120,9 +120,11 @@ impl RpcClient { json!([[signature.to_string()], commitment_config]), 5, )?; - let result: Vec> = + let result: Response>> = 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 { @@ -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>> = + 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( diff --git a/client/src/rpc_request.rs b/client/src/rpc_request.rs index 147fd764f..fddde675f 100644 --- a/client/src/rpc_request.rs +++ b/client/src/rpc_request.rs @@ -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", diff --git a/core/src/rpc.rs b/core/src/rpc.rs index 24588f291..84f2ca4b7 100644 --- a/core/src/rpc.rs +++ b/core/src/rpc.rs @@ -217,25 +217,6 @@ impl JsonRpcRequestProcessor { } } - pub fn get_signature_confirmation_status( - &self, - signature: Signature, - commitment: Option, - ) -> Option { - self.bank(commitment) - .get_signature_confirmation_status(&signature) - .map( - |SignatureConfirmationStatus { - confirmations, - status, - .. - }| RpcSignatureConfirmation { - confirmations, - status, - }, - ) - } - fn get_slot(&self, commitment: Option) -> Result { Ok(self.bank(commitment).slot()) } @@ -422,21 +403,33 @@ impl JsonRpcRequestProcessor { &self, signatures: Vec, commitment: Option, - ) -> Result>> { + ) -> RpcResponse>> { let mut statuses: Vec> = 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, commitment: Option, - ) -> Result>>; + ) -> RpcResponse>>; #[rpc(meta, name = "getSlot")] fn get_slot(&self, meta: Self::Metadata, commitment: Option) -> Result; @@ -633,22 +626,6 @@ pub trait RpcSol { #[rpc(meta, name = "validatorExit")] fn validator_exit(&self, meta: Self::Metadata) -> Result; - #[rpc(meta, name = "getNumBlocksSinceSignatureConfirmation")] - fn get_num_blocks_since_signature_confirmation( - &self, - meta: Self::Metadata, - signature_str: String, - commitment: Option, - ) -> Result>; - - #[rpc(meta, name = "getSignatureConfirmation")] - fn get_signature_confirmation( - &self, - meta: Self::Metadata, - signature_str: String, - commitment: Option, - ) -> Result>; - #[rpc(meta, name = "getIdentity")] fn get_identity(&self, meta: Self::Metadata) -> Result; @@ -912,7 +889,7 @@ impl RpcSol for RpcSolImpl { meta: Self::Metadata, signature_strs: Vec, commitment: Option, - ) -> Result>> { + ) -> RpcResponse>> { let mut signatures: Vec = 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, - ) -> Result> { - 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, - ) -> Result> { - 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> = serde_json::from_value(json["result"].clone()) - .expect("actual response deserialization"); - assert_eq!(expected_res, result[0].as_ref().unwrap().status); + let result: Option = + 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> = serde_json::from_value(json["result"].clone()) - .expect("actual response deserialization"); - assert!(result[0].is_none()); + let result: Option = + 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> = serde_json::from_value(json["result"].clone()) - .expect("actual response deserialization"); - assert_eq!(expected_res, result[0].as_ref().unwrap().status); + let result: Option = + serde_json::from_value(json["result"]["value"][0].clone()) + .expect("actual response deserialization"); + assert_eq!(expected_res, result.as_ref().unwrap().status); } #[test] diff --git a/docs/src/apps/jsonrpc-api.md b/docs/src/apps/jsonrpc-api.md index 38ca64a5c..23a887637 100644 --- a/docs/src/apps/jsonrpc-api.md +++ b/docs/src/apps/jsonrpc-api.md @@ -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: - -* `` - Signature of Transaction to confirm, as base-58 encoded string -* `` - (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment) - -#### Results: - -* `` - 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: - -* `` - Signature of Transaction to confirm, as base-58 encoded string -* `` - (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment) - -#### Results: - -* `` - Unknown transaction -* `` - Transaction confirmations and status: - * `confirmations: ` - count of confirmations since transaction was processed - * `status: ` - - * `"Ok": ` - Transaction was successful - * `"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` - RpcResponse JSON object with `value` field: + An array of: * `` - Unknown transaction * `` * `slot: ` - The slot the transaction was processed + * `confirmations: ` - Number of blocks since signature confirmation, null if rooted * `status: ` - Transaction status * `"Ok": ` - Transaction was successful * `"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 diff --git a/transaction-status/src/lib.rs b/transaction-status/src/lib.rs index 2bd4faa5b..3a410340d 100644 --- a/transaction-status/src/lib.rs +++ b/transaction-status/src/lib.rs @@ -30,6 +30,7 @@ pub struct TransactionStatusMeta { #[serde(rename_all = "camelCase")] pub struct TransactionStatus { pub slot: Slot, + pub confirmations: Option, pub status: Result<()>, }