From 1821e72812934567424764960bd586a9ce6db365 Mon Sep 17 00:00:00 2001 From: Michael Vines Date: Wed, 26 Sep 2018 17:12:40 -0700 Subject: [PATCH] Add getSignatureStatus --- doc/json-rpc.md | 26 +++++++++++++++++++++++++ src/rpc.rs | 50 +++++++++++++++++++++++++++++++++---------------- 2 files changed, 60 insertions(+), 16 deletions(-) diff --git a/doc/json-rpc.md b/doc/json-rpc.md index f011675259..03dda356be 100644 --- a/doc/json-rpc.md +++ b/doc/json-rpc.md @@ -19,6 +19,7 @@ Methods * [getBalance](#getbalance) * [getAccountInfo](#getaccountinfo) * [getLastId](#getlastid) +* [getSignatureStatus](#getsignaturestatus) * [getTransactionCount](#gettransactioncount) * [requestAirdrop](#requestairdrop) * [sendTransaction](#sendtransaction) @@ -141,6 +142,31 @@ curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1, "m --- +### getSignatureStatus +Returns the status of a given signature. This method is similar to +[confirmTransaction](#confirmtransaction) but provides more resolution for error +events. + +##### Parameters: +* `string` - Signature of Transaction to confirm, as base-58 encoded string + +##### Results: +* `string` - Transaction status: + * `Confirmed` - Transaction was successful + * `SignatureNotFound` - Unknown transaction + * `ProgramRuntimeError` - An error occurred in the program that processed this Transaction + * `GenericFailure` - Some other error occurred. **Note**: In the future new Transaction statuses may be added to this list. It's safe to assume that all new statuses will be more specific error conditions that previously presented as `GenericFailure` + +##### Example: +```bash +// Request +curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0", "id":1, "method":"getSignatureStatus", "params":["5VERv8NMvzbJMEkV8xnrLkEaWRtSz9CosKDYjCJjBRnbJLgp8uirBgmQpjKhoR4tjF3ZpRzrFmBV6UjKdiSZkQUW"]}' http://localhost:8899 + +// Result +{"jsonrpc":"2.0","result":"SignatureNotFound","id":1} +``` + +--- ### getTransactionCount Returns the current Transaction count from the ledger diff --git a/src/rpc.rs b/src/rpc.rs index 1e55da3b36..4eea85785f 100644 --- a/src/rpc.rs +++ b/src/rpc.rs @@ -84,6 +84,14 @@ pub struct Meta { } impl Metadata for Meta {} +#[derive(PartialEq, Serialize)] +pub enum RpcSignatureStatus { + Confirmed, + SignatureNotFound, + ProgramRuntimeError, + GenericFailure, +} + build_rpc_trait! { pub trait RpcSol { type Metadata; @@ -103,6 +111,9 @@ build_rpc_trait! { #[rpc(meta, name = "getLastId")] fn get_last_id(&self, Self::Metadata) -> Result; + #[rpc(meta, name = "getSignatureStatus")] + fn get_signature_status(&self, Self::Metadata, String) -> Result; + #[rpc(meta, name = "getTransactionCount")] fn get_transaction_count(&self, Self::Metadata) -> Result; @@ -119,17 +130,10 @@ impl RpcSol for RpcSolImpl { type Metadata = Meta; fn confirm_transaction(&self, meta: Self::Metadata, id: String) -> Result { - let signature_vec = bs58::decode(id) - .into_vec() - .map_err(|_| Error::invalid_request())?; - if signature_vec.len() != mem::size_of::() { - return Err(Error::invalid_request()); - } - let signature = Signature::new(&signature_vec); - meta.request_processor - .get_signature_status(signature) - .map(|res| res.is_ok()) + self.get_signature_status(meta, id) + .map(|status| status == RpcSignatureStatus::Confirmed) } + fn get_account_info(&self, meta: Self::Metadata, id: String) -> Result { let pubkey_vec = bs58::decode(id) .into_vec() @@ -156,6 +160,23 @@ impl RpcSol for RpcSolImpl { fn get_last_id(&self, meta: Self::Metadata) -> Result { meta.request_processor.get_last_id() } + fn get_signature_status(&self, meta: Self::Metadata, id: String) -> Result { + let signature_vec = bs58::decode(id) + .into_vec() + .map_err(|_| Error::invalid_request())?; + if signature_vec.len() != mem::size_of::() { + return Err(Error::invalid_request()); + } + let signature = Signature::new(&signature_vec); + Ok( + match meta.request_processor.get_signature_status(signature) { + Ok(_) => RpcSignatureStatus::Confirmed, + Err(BankError::ProgramRuntimeError) => RpcSignatureStatus::ProgramRuntimeError, + Err(BankError::SignatureNotFound) => RpcSignatureStatus::SignatureNotFound, + Err(_) => RpcSignatureStatus::GenericFailure, + }, + ) + } fn get_transaction_count(&self, meta: Self::Metadata) -> Result { meta.request_processor.get_transaction_count() } @@ -172,10 +193,7 @@ impl RpcSol for RpcSolImpl { let now = Instant::now(); let mut signature_status; loop { - signature_status = meta - .request_processor - .get_signature_status(signature) - .map_err(|_| Error::internal_error())?; + signature_status = meta.request_processor.get_signature_status(signature); if signature_status.is_ok() { return Ok(bs58::encode(signature).into_string()); @@ -227,8 +245,8 @@ impl JsonRpcRequestProcessor { let id = self.bank.last_id(); Ok(bs58::encode(id).into_string()) } - fn get_signature_status(&self, signature: Signature) -> Result> { - Ok(self.bank.get_signature_status(&signature)) + fn get_signature_status(&self, signature: Signature) -> result::Result<(), BankError> { + self.bank.get_signature_status(&signature) } fn get_transaction_count(&self) -> Result { Ok(self.bank.transaction_count() as u64)