Undo getSignatureStatus breaking change, add getSignatureStatuses (#9228)
automerge
This commit is contained in:
parent
9aab0b9388
commit
c7ba1994ac
|
@ -88,6 +88,21 @@ impl GenericRpcClientRequest for MockRpcClientRequest {
|
||||||
value: serde_json::to_value(FeeRateGovernor::default()).unwrap(),
|
value: serde_json::to_value(FeeRateGovernor::default()).unwrap(),
|
||||||
})?,
|
})?,
|
||||||
RpcRequest::GetSignatureStatus => {
|
RpcRequest::GetSignatureStatus => {
|
||||||
|
let response: Option<transaction::Result<()>> = if self.url == "account_in_use" {
|
||||||
|
Some(Err(TransactionError::AccountInUse))
|
||||||
|
} else if self.url == "instruction_error" {
|
||||||
|
Some(Err(TransactionError::InstructionError(
|
||||||
|
0,
|
||||||
|
InstructionError::UninitializedAccount,
|
||||||
|
)))
|
||||||
|
} else if self.url == "sig_not_found" {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(Ok(()))
|
||||||
|
};
|
||||||
|
serde_json::to_value(response).unwrap()
|
||||||
|
}
|
||||||
|
RpcRequest::GetSignatureStatuses => {
|
||||||
let status: transaction::Result<()> = if self.url == "account_in_use" {
|
let status: transaction::Result<()> = if self.url == "account_in_use" {
|
||||||
Err(TransactionError::AccountInUse)
|
Err(TransactionError::AccountInUse)
|
||||||
} else if self.url == "instruction_error" {
|
} else if self.url == "instruction_error" {
|
||||||
|
|
|
@ -119,13 +119,13 @@ impl RpcClient {
|
||||||
commitment_config: CommitmentConfig,
|
commitment_config: CommitmentConfig,
|
||||||
) -> ClientResult<Option<transaction::Result<()>>> {
|
) -> ClientResult<Option<transaction::Result<()>>> {
|
||||||
let signature_status = self.client.send(
|
let signature_status = self.client.send(
|
||||||
&RpcRequest::GetSignatureStatus,
|
&RpcRequest::GetSignatureStatuses,
|
||||||
json!([[signature.to_string()], commitment_config]),
|
json!([[signature.to_string()], commitment_config]),
|
||||||
5,
|
5,
|
||||||
)?;
|
)?;
|
||||||
let result: Response<Vec<Option<TransactionStatus>>> =
|
let result: Response<Vec<Option<TransactionStatus>>> =
|
||||||
serde_json::from_value(signature_status)
|
serde_json::from_value(signature_status)
|
||||||
.map_err(|err| ClientError::new_with_command(err.into(), "GetSignatureStatus"))?;
|
.map_err(|err| ClientError::new_with_command(err.into(), "GetSignatureStatuses"))?;
|
||||||
Ok(result.value[0]
|
Ok(result.value[0]
|
||||||
.clone()
|
.clone()
|
||||||
.map(|status_meta| status_meta.status))
|
.map(|status_meta| status_meta.status))
|
||||||
|
@ -949,20 +949,20 @@ impl RpcClient {
|
||||||
let response = self
|
let response = self
|
||||||
.client
|
.client
|
||||||
.send(
|
.send(
|
||||||
&RpcRequest::GetSignatureStatus,
|
&RpcRequest::GetSignatureStatuses,
|
||||||
json!([[signature.to_string()], CommitmentConfig::recent().ok()]),
|
json!([[signature.to_string()], CommitmentConfig::recent().ok()]),
|
||||||
1,
|
1,
|
||||||
)
|
)
|
||||||
.map_err(|err| err.into_with_command("GetSignatureStatus"))?;
|
.map_err(|err| err.into_with_command("GetSignatureStatuses"))?;
|
||||||
let result: Response<Vec<Option<TransactionStatus>>> = serde_json::from_value(response)
|
let result: Response<Vec<Option<TransactionStatus>>> = serde_json::from_value(response)
|
||||||
.map_err(|err| ClientError::new_with_command(err.into(), "GetSignatureStatus"))?;
|
.map_err(|err| ClientError::new_with_command(err.into(), "GetSignatureStatuses"))?;
|
||||||
|
|
||||||
let confirmations = result.value[0]
|
let confirmations = result.value[0]
|
||||||
.clone()
|
.clone()
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
ClientError::new_with_command(
|
ClientError::new_with_command(
|
||||||
ClientErrorKind::Custom("signature not found".to_string()),
|
ClientErrorKind::Custom("signature not found".to_string()),
|
||||||
"GetSignatureStatus",
|
"GetSignatureStatuses",
|
||||||
)
|
)
|
||||||
})?
|
})?
|
||||||
.confirmations
|
.confirmations
|
||||||
|
|
|
@ -23,6 +23,7 @@ pub enum RpcRequest {
|
||||||
GetFeeCalculatorForBlockhash,
|
GetFeeCalculatorForBlockhash,
|
||||||
GetFeeRateGovernor,
|
GetFeeRateGovernor,
|
||||||
GetSignatureStatus,
|
GetSignatureStatus,
|
||||||
|
GetSignatureStatuses,
|
||||||
GetSlot,
|
GetSlot,
|
||||||
GetSlotLeader,
|
GetSlotLeader,
|
||||||
GetStorageTurn,
|
GetStorageTurn,
|
||||||
|
@ -65,6 +66,7 @@ impl RpcRequest {
|
||||||
RpcRequest::GetFeeCalculatorForBlockhash => "getFeeCalculatorForBlockhash",
|
RpcRequest::GetFeeCalculatorForBlockhash => "getFeeCalculatorForBlockhash",
|
||||||
RpcRequest::GetFeeRateGovernor => "getFeeRateGovernor",
|
RpcRequest::GetFeeRateGovernor => "getFeeRateGovernor",
|
||||||
RpcRequest::GetSignatureStatus => "getSignatureStatus",
|
RpcRequest::GetSignatureStatus => "getSignatureStatus",
|
||||||
|
RpcRequest::GetSignatureStatuses => "getSignatureStatuses",
|
||||||
RpcRequest::GetSlot => "getSlot",
|
RpcRequest::GetSlot => "getSlot",
|
||||||
RpcRequest::GetSlotLeader => "getSlotLeader",
|
RpcRequest::GetSlotLeader => "getSlotLeader",
|
||||||
RpcRequest::GetStorageTurn => "getStorageTurn",
|
RpcRequest::GetStorageTurn => "getStorageTurn",
|
||||||
|
|
114
core/src/rpc.rs
114
core/src/rpc.rs
|
@ -23,7 +23,7 @@ use solana_sdk::{
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
signature::Signature,
|
signature::Signature,
|
||||||
timing::slot_duration_from_slots_per_year,
|
timing::slot_duration_from_slots_per_year,
|
||||||
transaction::Transaction,
|
transaction::{self, Transaction},
|
||||||
};
|
};
|
||||||
use solana_transaction_status::{ConfirmedBlock, TransactionEncoding, TransactionStatus};
|
use solana_transaction_status::{ConfirmedBlock, TransactionEncoding, TransactionStatus};
|
||||||
use solana_vote_program::vote_state::{VoteState, MAX_LOCKOUT_HISTORY};
|
use solana_vote_program::vote_state::{VoteState, MAX_LOCKOUT_HISTORY};
|
||||||
|
@ -398,6 +398,16 @@ impl JsonRpcRequestProcessor {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_signature_status(
|
pub fn get_signature_status(
|
||||||
|
&self,
|
||||||
|
signature: Signature,
|
||||||
|
commitment: Option<CommitmentConfig>,
|
||||||
|
) -> Option<transaction::Result<()>> {
|
||||||
|
self.bank(commitment)
|
||||||
|
.get_signature_status_slot(&signature)
|
||||||
|
.map(|(_, status)| status)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_signature_statuses(
|
||||||
&self,
|
&self,
|
||||||
signatures: Vec<Signature>,
|
signatures: Vec<Signature>,
|
||||||
commitment: Option<CommitmentConfig>,
|
commitment: Option<CommitmentConfig>,
|
||||||
|
@ -556,6 +566,14 @@ pub trait RpcSol {
|
||||||
|
|
||||||
#[rpc(meta, name = "getSignatureStatus")]
|
#[rpc(meta, name = "getSignatureStatus")]
|
||||||
fn get_signature_status(
|
fn get_signature_status(
|
||||||
|
&self,
|
||||||
|
meta: Self::Metadata,
|
||||||
|
signature_str: String,
|
||||||
|
commitment: Option<CommitmentConfig>,
|
||||||
|
) -> Result<Option<transaction::Result<()>>>;
|
||||||
|
|
||||||
|
#[rpc(meta, name = "getSignatureStatuses")]
|
||||||
|
fn get_signature_statuses(
|
||||||
&self,
|
&self,
|
||||||
meta: Self::Metadata,
|
meta: Self::Metadata,
|
||||||
signature_strs: Vec<String>,
|
signature_strs: Vec<String>,
|
||||||
|
@ -886,6 +904,20 @@ impl RpcSol for RpcSolImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_signature_status(
|
fn get_signature_status(
|
||||||
|
&self,
|
||||||
|
meta: Self::Metadata,
|
||||||
|
signature_str: String,
|
||||||
|
commitment: Option<CommitmentConfig>,
|
||||||
|
) -> Result<Option<transaction::Result<()>>> {
|
||||||
|
let signature = verify_signature(&signature_str)?;
|
||||||
|
Ok(meta
|
||||||
|
.request_processor
|
||||||
|
.read()
|
||||||
|
.unwrap()
|
||||||
|
.get_signature_status(signature, commitment))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_signature_statuses(
|
||||||
&self,
|
&self,
|
||||||
meta: Self::Metadata,
|
meta: Self::Metadata,
|
||||||
signature_strs: Vec<String>,
|
signature_strs: Vec<String>,
|
||||||
|
@ -898,7 +930,7 @@ impl RpcSol for RpcSolImpl {
|
||||||
meta.request_processor
|
meta.request_processor
|
||||||
.read()
|
.read()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.get_signature_status(signatures, commitment)
|
.get_signature_statuses(signatures, commitment)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_slot(&self, meta: Self::Metadata, commitment: Option<CommitmentConfig>) -> Result<u64> {
|
fn get_slot(&self, meta: Self::Metadata, commitment: Option<CommitmentConfig>) -> Result<u64> {
|
||||||
|
@ -991,7 +1023,7 @@ impl RpcSol for RpcSolImpl {
|
||||||
.request_processor
|
.request_processor
|
||||||
.read()
|
.read()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.get_signature_status(vec![signature], commitment.clone())?
|
.get_signature_statuses(vec![signature], commitment.clone())?
|
||||||
.value[0]
|
.value[0]
|
||||||
.clone()
|
.clone()
|
||||||
.map(|x| x.status);
|
.map(|x| x.status);
|
||||||
|
@ -1757,6 +1789,76 @@ pub mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_rpc_get_signature_status() {
|
fn test_rpc_get_signature_status() {
|
||||||
|
let bob_pubkey = Pubkey::new_rand();
|
||||||
|
let RpcHandler {
|
||||||
|
io,
|
||||||
|
meta,
|
||||||
|
blockhash,
|
||||||
|
alice,
|
||||||
|
..
|
||||||
|
} = start_rpc_handler_with_tx(&bob_pubkey);
|
||||||
|
|
||||||
|
let tx = system_transaction::transfer(&alice, &bob_pubkey, 20, blockhash);
|
||||||
|
let req = format!(
|
||||||
|
r#"{{"jsonrpc":"2.0","id":1,"method":"getSignatureStatus","params":["{}"]}}"#,
|
||||||
|
tx.signatures[0]
|
||||||
|
);
|
||||||
|
let res = io.handle_request_sync(&req, meta.clone());
|
||||||
|
let expected_res: Option<transaction::Result<()>> = Some(Ok(()));
|
||||||
|
let expected = json!({
|
||||||
|
"jsonrpc": "2.0",
|
||||||
|
"result": expected_res,
|
||||||
|
"id": 1
|
||||||
|
});
|
||||||
|
let expected: Response =
|
||||||
|
serde_json::from_value(expected).expect("expected response deserialization");
|
||||||
|
let result: Response = serde_json::from_str(&res.expect("actual response"))
|
||||||
|
.expect("actual response deserialization");
|
||||||
|
assert_eq!(expected, result);
|
||||||
|
|
||||||
|
// Test getSignatureStatus request on unprocessed tx
|
||||||
|
let tx = system_transaction::transfer(&alice, &bob_pubkey, 10, blockhash);
|
||||||
|
let req = format!(
|
||||||
|
r#"{{"jsonrpc":"2.0","id":1,"method":"getSignatureStatus","params":["{}"]}}"#,
|
||||||
|
tx.signatures[0]
|
||||||
|
);
|
||||||
|
let res = io.handle_request_sync(&req, meta.clone());
|
||||||
|
let expected_res: Option<String> = None;
|
||||||
|
let expected = json!({
|
||||||
|
"jsonrpc": "2.0",
|
||||||
|
"result": expected_res,
|
||||||
|
"id": 1
|
||||||
|
});
|
||||||
|
let expected: Response =
|
||||||
|
serde_json::from_value(expected).expect("expected response deserialization");
|
||||||
|
let result: Response = serde_json::from_str(&res.expect("actual response"))
|
||||||
|
.expect("actual response deserialization");
|
||||||
|
assert_eq!(expected, result);
|
||||||
|
|
||||||
|
// Test getSignatureStatus request on a TransactionError
|
||||||
|
let tx = system_transaction::transfer(&alice, &bob_pubkey, std::u64::MAX, blockhash);
|
||||||
|
let req = format!(
|
||||||
|
r#"{{"jsonrpc":"2.0","id":1,"method":"getSignatureStatus","params":["{}"]}}"#,
|
||||||
|
tx.signatures[0]
|
||||||
|
);
|
||||||
|
let res = io.handle_request_sync(&req, meta);
|
||||||
|
let expected_res: Option<transaction::Result<()>> = Some(Err(
|
||||||
|
TransactionError::InstructionError(0, InstructionError::Custom(1)),
|
||||||
|
));
|
||||||
|
let expected = json!({
|
||||||
|
"jsonrpc": "2.0",
|
||||||
|
"result": expected_res,
|
||||||
|
"id": 1
|
||||||
|
});
|
||||||
|
let expected: Response =
|
||||||
|
serde_json::from_value(expected).expect("expected response deserialization");
|
||||||
|
let result: Response = serde_json::from_str(&res.expect("actual response"))
|
||||||
|
.expect("actual response deserialization");
|
||||||
|
assert_eq!(expected, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_rpc_get_signature_statuses() {
|
||||||
let bob_pubkey = Pubkey::new_rand();
|
let bob_pubkey = Pubkey::new_rand();
|
||||||
let RpcHandler {
|
let RpcHandler {
|
||||||
io,
|
io,
|
||||||
|
@ -1768,7 +1870,7 @@ pub mod tests {
|
||||||
} = start_rpc_handler_with_tx(&bob_pubkey);
|
} = start_rpc_handler_with_tx(&bob_pubkey);
|
||||||
|
|
||||||
let req = format!(
|
let req = format!(
|
||||||
r#"{{"jsonrpc":"2.0","id":1,"method":"getSignatureStatus","params":[["{}"]]}}"#,
|
r#"{{"jsonrpc":"2.0","id":1,"method":"getSignatureStatuses","params":[["{}"]]}}"#,
|
||||||
confirmed_block_signatures[0]
|
confirmed_block_signatures[0]
|
||||||
);
|
);
|
||||||
let res = io.handle_request_sync(&req, meta.clone());
|
let res = io.handle_request_sync(&req, meta.clone());
|
||||||
|
@ -1784,7 +1886,7 @@ pub mod tests {
|
||||||
// Test getSignatureStatus request on unprocessed tx
|
// Test getSignatureStatus request on unprocessed tx
|
||||||
let tx = system_transaction::transfer(&alice, &bob_pubkey, 10, blockhash);
|
let tx = system_transaction::transfer(&alice, &bob_pubkey, 10, blockhash);
|
||||||
let req = format!(
|
let req = format!(
|
||||||
r#"{{"jsonrpc":"2.0","id":1,"method":"getSignatureStatus","params":[["{}"]]}}"#,
|
r#"{{"jsonrpc":"2.0","id":1,"method":"getSignatureStatuses","params":[["{}"]]}}"#,
|
||||||
tx.signatures[0]
|
tx.signatures[0]
|
||||||
);
|
);
|
||||||
let res = io.handle_request_sync(&req, meta.clone());
|
let res = io.handle_request_sync(&req, meta.clone());
|
||||||
|
@ -1796,7 +1898,7 @@ pub mod tests {
|
||||||
|
|
||||||
// Test getSignatureStatus request on a TransactionError
|
// Test getSignatureStatus request on a TransactionError
|
||||||
let req = format!(
|
let req = format!(
|
||||||
r#"{{"jsonrpc":"2.0","id":1,"method":"getSignatureStatus","params":[["{}"]]}}"#,
|
r#"{{"jsonrpc":"2.0","id":1,"method":"getSignatureStatuses","params":[["{}"]]}}"#,
|
||||||
confirmed_block_signatures[1]
|
confirmed_block_signatures[1]
|
||||||
);
|
);
|
||||||
let res = io.handle_request_sync(&req, meta.clone());
|
let res = io.handle_request_sync(&req, meta.clone());
|
||||||
|
|
|
@ -34,6 +34,7 @@ To interact with a Solana node inside a JavaScript application, use the [solana-
|
||||||
* [getProgramAccounts](jsonrpc-api.md#getprogramaccounts)
|
* [getProgramAccounts](jsonrpc-api.md#getprogramaccounts)
|
||||||
* [getRecentBlockhash](jsonrpc-api.md#getrecentblockhash)
|
* [getRecentBlockhash](jsonrpc-api.md#getrecentblockhash)
|
||||||
* [getSignatureStatus](jsonrpc-api.md#getsignaturestatus)
|
* [getSignatureStatus](jsonrpc-api.md#getsignaturestatus)
|
||||||
|
* [getSignatureStatuses](jsonrpc-api.md#getsignaturestatuses)
|
||||||
* [getSlot](jsonrpc-api.md#getslot)
|
* [getSlot](jsonrpc-api.md#getslot)
|
||||||
* [getSlotLeader](jsonrpc-api.md#getslotleader)
|
* [getSlotLeader](jsonrpc-api.md#getslotleader)
|
||||||
* [getSlotsPerSegment](jsonrpc-api.md#getslotspersegment)
|
* [getSlotsPerSegment](jsonrpc-api.md#getslotspersegment)
|
||||||
|
@ -660,6 +661,32 @@ Returns the status of a given signature. This method is similar to [confirmTrans
|
||||||
|
|
||||||
#### Parameters:
|
#### 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 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)
|
||||||
|
|
||||||
|
#### 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":{"Ok": null},"id":1}
|
||||||
|
```
|
||||||
|
|
||||||
|
### getSignatureStatuses
|
||||||
|
|
||||||
|
Returns the statuses of a list of signatures. This method is similar to [confirmTransaction](jsonrpc-api.md#confirmtransaction) but provides more resolution for error events. This method only searches the recent status cache of signatures, which retains all active slots plus `MAX_RECENT_BLOCKHASHES` rooted slots.
|
||||||
|
|
||||||
|
#### Parameters:
|
||||||
|
|
||||||
* `<array>` - An array of transaction signatures to confirm, as base-58 encoded strings
|
* `<array>` - An array of transaction signatures to confirm, as base-58 encoded strings
|
||||||
* `<object>` - (optional) Extended Rpc configuration, containing the following optional fields:
|
* `<object>` - (optional) Extended Rpc configuration, containing the following optional fields:
|
||||||
* `commitment: <string>` - [Commitment](jsonrpc-api.md#configuring-state-commitment)
|
* `commitment: <string>` - [Commitment](jsonrpc-api.md#configuring-state-commitment)
|
||||||
|
|
Loading…
Reference in New Issue