diff --git a/client/src/mock_rpc_client_request.rs b/client/src/mock_rpc_client_request.rs index 787f845ac..141aa678a 100644 --- a/client/src/mock_rpc_client_request.rs +++ b/client/src/mock_rpc_client_request.rs @@ -116,10 +116,12 @@ impl GenericRpcClientRequest for MockRpcClientRequest { let status = if self.url == "sig_not_found" { None } else { + let err = status.clone().err(); Some(TransactionStatus { status, slot: 1, confirmations: Some(0), + err, }) }; serde_json::to_value(Response { diff --git a/client/src/rpc_response.rs b/client/src/rpc_response.rs index 389cee91f..95cef7e01 100644 --- a/client/src/rpc_response.rs +++ b/client/src/rpc_response.rs @@ -4,7 +4,7 @@ use solana_sdk::{ clock::{Epoch, Slot}, fee_calculator::{FeeCalculator, FeeRateGovernor}, pubkey::Pubkey, - transaction::Result, + transaction::{Result, TransactionError}, }; use std::{collections::HashMap, net::SocketAddr, str::FromStr}; @@ -54,6 +54,12 @@ pub struct RpcKeyedAccount { pub account: RpcAccount, } +#[derive(Serialize, Deserialize, Clone, Debug)] +#[serde(rename_all = "camelCase")] +pub struct RpcSignatureResult { + pub err: Option, +} + /// A duplicate representation of a Message for pretty JSON serialization #[derive(Serialize, Deserialize, Clone, Debug)] #[serde(rename_all = "camelCase")] diff --git a/core/src/banking_stage.rs b/core/src/banking_stage.rs index 58990b4ce..99a1a75ff 100644 --- a/core/src/banking_stage.rs +++ b/core/src/banking_stage.rs @@ -1982,10 +1982,20 @@ mod tests { { if let EncodedTransaction::Json(transaction) = transaction { if transaction.signatures[0] == success_signature.to_string() { - assert_eq!(meta.unwrap().status, Ok(())); + let meta = meta.unwrap(); + assert_eq!(meta.err, None); + assert_eq!(meta.status, Ok(())); } else if transaction.signatures[0] == ix_error_signature.to_string() { + let meta = meta.unwrap(); assert_eq!( - meta.unwrap().status, + meta.err, + Some(TransactionError::InstructionError( + 0, + InstructionError::Custom(1) + )) + ); + assert_eq!( + meta.status, Err(TransactionError::InstructionError( 0, InstructionError::Custom(1) diff --git a/core/src/replay_stage.rs b/core/src/replay_stage.rs index f4a1d0872..101a3e078 100644 --- a/core/src/replay_stage.rs +++ b/core/src/replay_stage.rs @@ -2530,10 +2530,20 @@ pub(crate) mod tests { { if let EncodedTransaction::Json(transaction) = transaction { if transaction.signatures[0] == signatures[0].to_string() { - assert_eq!(meta.unwrap().status, Ok(())); + let meta = meta.unwrap(); + assert_eq!(meta.err, None); + assert_eq!(meta.status, Ok(())); } else if transaction.signatures[0] == signatures[1].to_string() { + let meta = meta.unwrap(); assert_eq!( - meta.unwrap().status, + meta.err, + Some(TransactionError::InstructionError( + 0, + InstructionError::Custom(1) + )) + ); + assert_eq!( + meta.status, Err(TransactionError::InstructionError( 0, InstructionError::Custom(1) diff --git a/core/src/rpc.rs b/core/src/rpc.rs index d61d2a5b0..ca052d297 100644 --- a/core/src/rpc.rs +++ b/core/src/rpc.rs @@ -460,10 +460,12 @@ impl JsonRpcRequestProcessor { .get_confirmation_count(slot) .or(Some(0)) }; + let err = status.clone().err(); TransactionStatus { slot, status, confirmations, + err, } }) } @@ -2416,11 +2418,21 @@ pub mod tests { { if let EncodedTransaction::Json(transaction) = transaction { if transaction.signatures[0] == confirmed_block_signatures[0].to_string() { + let meta = meta.unwrap(); assert_eq!(transaction.message.recent_blockhash, blockhash.to_string()); - assert_eq!(meta.unwrap().status, Ok(())); + assert_eq!(meta.status, Ok(())); + assert_eq!(meta.err, None); } else if transaction.signatures[0] == confirmed_block_signatures[1].to_string() { + let meta = meta.unwrap(); assert_eq!( - meta.unwrap().status, + meta.err, + Some(TransactionError::InstructionError( + 0, + InstructionError::Custom(1) + )) + ); + assert_eq!( + meta.status, Err(TransactionError::InstructionError( 0, InstructionError::Custom(1) @@ -2450,11 +2462,21 @@ pub mod tests { let decoded_transaction: Transaction = deserialize(&bs58::decode(&transaction).into_vec().unwrap()).unwrap(); if decoded_transaction.signatures[0] == confirmed_block_signatures[0] { + let meta = meta.unwrap(); assert_eq!(decoded_transaction.message.recent_blockhash, blockhash); - assert_eq!(meta.unwrap().status, Ok(())); + assert_eq!(meta.status, Ok(())); + assert_eq!(meta.err, None); } else if decoded_transaction.signatures[0] == confirmed_block_signatures[1] { + let meta = meta.unwrap(); assert_eq!( - meta.unwrap().status, + meta.err, + Some(TransactionError::InstructionError( + 0, + InstructionError::Custom(1) + )) + ); + assert_eq!( + meta.status, Err(TransactionError::InstructionError( 0, InstructionError::Custom(1) diff --git a/core/src/rpc_pubsub.rs b/core/src/rpc_pubsub.rs index 79b31a2c5..e363f8a3f 100644 --- a/core/src/rpc_pubsub.rs +++ b/core/src/rpc_pubsub.rs @@ -4,8 +4,10 @@ use crate::rpc_subscriptions::{Confirmations, RpcSubscriptions, SlotInfo}; use jsonrpc_core::{Error, ErrorCode, Result}; use jsonrpc_derive::rpc; use jsonrpc_pubsub::{typed::Subscriber, Session, SubscriptionId}; -use solana_client::rpc_response::{Response as RpcResponse, RpcAccount, RpcKeyedAccount}; -use solana_sdk::{clock::Slot, pubkey::Pubkey, signature::Signature, transaction}; +use solana_client::rpc_response::{ + Response as RpcResponse, RpcAccount, RpcKeyedAccount, RpcSignatureResult, +}; +use solana_sdk::{clock::Slot, pubkey::Pubkey, signature::Signature}; use std::sync::{atomic, Arc}; // Suppress needless_return due to @@ -74,7 +76,7 @@ pub trait RpcSolPubSub { fn signature_subscribe( &self, meta: Self::Metadata, - subscriber: Subscriber>>, + subscriber: Subscriber>, signature_str: String, confirmations: Option, ); @@ -225,7 +227,7 @@ impl RpcSolPubSub for RpcSolPubSubImpl { fn signature_subscribe( &self, _meta: Self::Metadata, - subscriber: Subscriber>>, + subscriber: Subscriber>, signature_str: String, confirmations: Option, ) { @@ -385,7 +387,7 @@ mod tests { // Test signature confirmation notification let (response, _) = robust_poll_or_panic(receiver); - let expected_res: Option> = Some(Ok(())); + let expected_res = RpcSignatureResult { err: None }; let expected = json!({ "jsonrpc": "2.0", "method": "signatureNotification", diff --git a/core/src/rpc_subscriptions.rs b/core/src/rpc_subscriptions.rs index 889630a95..510b0a5b3 100644 --- a/core/src/rpc_subscriptions.rs +++ b/core/src/rpc_subscriptions.rs @@ -8,7 +8,9 @@ use jsonrpc_pubsub::{ SubscriptionId, }; use serde::Serialize; -use solana_client::rpc_response::{Response, RpcAccount, RpcKeyedAccount, RpcResponseContext}; +use solana_client::rpc_response::{ + Response, RpcAccount, RpcKeyedAccount, RpcResponseContext, RpcSignatureResult, +}; use solana_ledger::bank_forks::BankForks; use solana_runtime::bank::Bank; use solana_sdk::{ @@ -66,7 +68,7 @@ type RpcProgramSubscriptions = RwLock< type RpcSignatureSubscriptions = RwLock< HashMap< Signature, - HashMap>>, Confirmations)>, + HashMap>, Confirmations)>, >, >; type RpcSlotSubscriptions = RwLock>>; @@ -207,11 +209,15 @@ fn filter_account_result( Box::new(iter::empty()) } -fn filter_signature_result(result: Option, _root: Slot) -> Box> -where - S: 'static + Clone + Serialize, -{ - Box::new(result.into_iter()) +fn filter_signature_result( + result: Option>, + _root: Slot, +) -> Box> { + Box::new( + result + .into_iter() + .map(|result| RpcSignatureResult { err: result.err() }), + ) } fn filter_program_results( @@ -430,7 +436,7 @@ impl RpcSubscriptions { signature: Signature, confirmations: Option, sub_id: SubscriptionId, - subscriber: Subscriber>>, + subscriber: Subscriber>, ) { let mut subscriptions = self.signature_subscriptions.write().unwrap(); add_subscription( @@ -890,7 +896,7 @@ pub(crate) mod tests { } subscriptions.notify_subscribers(1, &bank_forks); - let expected_res: Option> = Some(Ok(())); + let expected_res = RpcSignatureResult { err: None }; struct Notification { slot: Slot, diff --git a/core/tests/rpc.rs b/core/tests/rpc.rs index 8dd6d8d01..d1e3baf5b 100644 --- a/core/tests/rpc.rs +++ b/core/tests/rpc.rs @@ -9,16 +9,12 @@ use reqwest::{self, header::CONTENT_TYPE}; use serde_json::{json, Value}; use solana_client::{ rpc_client::{get_rpc_request_str, RpcClient}, - rpc_response::Response, + rpc_response::{Response, RpcSignatureResult}, }; use solana_core::{rpc_pubsub::gen_client::Client as PubsubClient, validator::TestValidator}; use solana_sdk::{ - commitment_config::CommitmentConfig, - hash::Hash, - pubkey::Pubkey, - signature::Signer, - system_transaction, - transaction::{self, Transaction}, + commitment_config::CommitmentConfig, hash::Hash, pubkey::Pubkey, signature::Signer, + system_transaction, transaction::Transaction, }; use std::{ collections::HashSet, @@ -225,7 +221,7 @@ fn test_rpc_subscriptions() { // Track when subscriptions are ready let (ready_sender, ready_receiver) = channel::<()>(); // Track when status notifications are received - let (status_sender, status_receiver) = channel::<(String, Response>)>(); + let (status_sender, status_receiver) = channel::<(String, Response)>(); // Create the pub sub runtime let mut rt = Runtime::new().unwrap(); @@ -305,7 +301,7 @@ fn test_rpc_subscriptions() { let timeout = deadline.saturating_duration_since(Instant::now()); match status_receiver.recv_timeout(timeout) { Ok((sig, result)) => { - assert!(result.value.is_ok()); + assert!(result.value.err.is_none()); assert!(signature_set.remove(&sig)); } Err(_err) => { diff --git a/docs/src/apps/jsonrpc-api.md b/docs/src/apps/jsonrpc-api.md index 4ccce41b8..99bbd3cc5 100644 --- a/docs/src/apps/jsonrpc-api.md +++ b/docs/src/apps/jsonrpc-api.md @@ -299,12 +299,13 @@ The result field will be an object with the following fields: * `transactions: ` - an array of JSON objects containing: * `transaction: ` - [Transaction](#transaction-structure) object, either in JSON format or base-58 encoded binary data, depending on encoding parameter * `meta: ` - transaction status metadata object, containing `null` or: - * `status: ` - Transaction status: - * `"Ok": null` - Transaction was successful - * `"Err": ` - Transaction failed with TransactionError [TransactionError definitions](https://github.com/solana-labs/solana/blob/master/sdk/src/transaction.rs#L18) - * `fee: ` - fee this transaction was charged, as u64 integer - * `preBalances: ` - array of u64 account balances from before the transaction was processed - * `postBalances: ` - array of u64 account balances after the transaction was processed + * `err: ` - Error if transaction failed, null if transaction succeeded. [TransactionError definitions](https://github.com/solana-labs/solana/blob/master/sdk/src/transaction.rs#L14) + * `fee: ` - fee this transaction was charged, as u64 integer + * `preBalances: ` - array of u64 account balances from before the transaction was processed + * `postBalances: ` - array of u64 account balances after the transaction was processed + * DEPRECATED: `status: ` - Transaction status + * `"Ok": ` - Transaction was successful + * `"Err": ` - Transaction failed with TransactionError * `rewards: ` - an array of JSON objects containing: * `pubkey: ` - The public key, as base-58 encoded string, of the account that received the reward * `lamports: `- number of reward lamports credited or debited by the account, as a i64 @@ -316,13 +317,13 @@ The result field will be an object with the following fields: curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc": "2.0","id":1,"method":"getConfirmedBlock","params":[430, "json"]}' localhost:8899 // Result -{"jsonrpc":"2.0","result":{"blockhash":"Gp3t5bfDsJv1ovP8cB1SuRhXVuoTqDv7p3tymyubYg5","parentSlot":429,"previousBlockhash":"EFejToxii1L5aUF2NrK9dsbAEmZSNyN5nsipmZHQR1eA","transactions":[{"transaction":{"message":{"accountKeys":["6H94zdiaYfRfPfKjYLjyr2VFBg6JHXygy84r3qhc3NsC","39UAy8hsoYPywGPGdmun747omSr79zLSjqvPJN3zetoH","SysvarS1otHashes111111111111111111111111111","SysvarC1ock11111111111111111111111111111111","Vote111111111111111111111111111111111111111"],"header":{"numReadonlySignedAccounts":0,"numReadonlyUnsignedAccounts":3,"numRequiredSignatures":2},"instructions":[{"accounts":[1,2,3],"data":"29z5mr1JoRmJYQ6ynmk3pf31cGFRziAF1M3mT3L6sFXf5cKLdkEaMXMT8AqLpD4CpcupHmuMEmtZHpomrwfdZetSomNy3d","programIdIndex":4}],"recentBlockhash":"EFejToxii1L5aUF2NrK9dsbAEmZSNyN5nsipmZHQR1eA"},"signatures":["35YGay1Lwjwgxe9zaH6APSHbt9gYQUCtBWTNL3aVwVGn9xTFw2fgds7qK5AL29mP63A9j3rh8KpN1TgSR62XCaby","4vANMjSKiwEchGSXwVrQkwHnmsbKQmy9vdrsYxWdCup1bLsFzX8gKrFTSVDCZCae2dbxJB9mPNhqB2sD1vvr4sAD"]},"meta":{"fee":18000,"postBalances":[499999972500,15298080,1,1,1],"preBalances":[499999990500,15298080,1,1,1],"status":{"Ok":null}}}]},"id":1} +{"jsonrpc":"2.0","result":{"blockhash":"Gp3t5bfDsJv1ovP8cB1SuRhXVuoTqDv7p3tymyubYg5","parentSlot":429,"previousBlockhash":"EFejToxii1L5aUF2NrK9dsbAEmZSNyN5nsipmZHQR1eA","transactions":[{"transaction":{"message":{"accountKeys":["6H94zdiaYfRfPfKjYLjyr2VFBg6JHXygy84r3qhc3NsC","39UAy8hsoYPywGPGdmun747omSr79zLSjqvPJN3zetoH","SysvarS1otHashes111111111111111111111111111","SysvarC1ock11111111111111111111111111111111","Vote111111111111111111111111111111111111111"],"header":{"numReadonlySignedAccounts":0,"numReadonlyUnsignedAccounts":3,"numRequiredSignatures":2},"instructions":[{"accounts":[1,2,3],"data":"29z5mr1JoRmJYQ6ynmk3pf31cGFRziAF1M3mT3L6sFXf5cKLdkEaMXMT8AqLpD4CpcupHmuMEmtZHpomrwfdZetSomNy3d","programIdIndex":4}],"recentBlockhash":"EFejToxii1L5aUF2NrK9dsbAEmZSNyN5nsipmZHQR1eA"},"signatures":["35YGay1Lwjwgxe9zaH6APSHbt9gYQUCtBWTNL3aVwVGn9xTFw2fgds7qK5AL29mP63A9j3rh8KpN1TgSR62XCaby","4vANMjSKiwEchGSXwVrQkwHnmsbKQmy9vdrsYxWdCup1bLsFzX8gKrFTSVDCZCae2dbxJB9mPNhqB2sD1vvr4sAD"]},"meta":{"err":null,"fee":18000,"postBalances":[499999972500,15298080,1,1,1],"preBalances":[499999990500,15298080,1,1,1],"status":{"Ok":null}}}]},"id":1} // Request curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc": "2.0","id":1,"method":"getConfirmedBlock","params":[430, "binary"]}' localhost:8899 // Result -{"jsonrpc":"2.0","result":{"blockhash":"Gp3t5bfDsJv1ovP8cB1SuRhXVuoTqDv7p3tymyubYg5","parentSlot":429,"previousBlockhash":"EFejToxii1L5aUF2NrK9dsbAEmZSNyN5nsipmZHQR1eA","transactions":[{"transaction":"81UZJt4dh4Do66jDhrgkQudS8J2N6iG3jaVav7gJrqJSFY4Ug53iA9JFJZh2gxKWcaFdLJwhHx9mRdg9JwDAWB4ywiu5154CRwXV4FMdnPLg7bhxRLwhhYaLsVgMF5AyNRcTzjCVoBvqFgDU7P8VEKDEiMvD3qxzm1pLZVxDG1LTQpT3Dz4Uviv4KQbFQNuC22KupBoyHFB7Zh6KFdMqux4M9PvhoqcoJsJKwXjWpKu7xmEKnnrSbfLadkgjBmmjhW3fdTrFvnhQdTkhtdJxUL1xS9GMuJQer8YgSKNtUXB1eXZQwXU8bU2BjYkZE6Q5Xww8hu9Z4E4Mo4QsooVtHoP6BM3NKw8zjVbWfoCQqxTrwuSzrNCWCWt58C24LHecH67CTt2uXbYSviixvrYkK7A3t68BxTJcF1dXJitEPTFe2ceTkauLJqrJgnER4iUrsjr26T8YgWvpY9wkkWFSviQW6wV5RASTCUasVEcrDiaKj8EQMkgyDoe9HyKitSVg67vMWJFpUXpQobseWJUs5FTWWzmfHmFp8FZ","meta":{"fee":18000,"postBalances":[499999972500,15298080,1,1,1],"preBalances":[499999990500,15298080,1,1,1],"status":{"Ok":null}}}]},"id":1} +{"jsonrpc":"2.0","result":{"blockhash":"Gp3t5bfDsJv1ovP8cB1SuRhXVuoTqDv7p3tymyubYg5","parentSlot":429,"previousBlockhash":"EFejToxii1L5aUF2NrK9dsbAEmZSNyN5nsipmZHQR1eA","transactions":[{"transaction":"81UZJt4dh4Do66jDhrgkQudS8J2N6iG3jaVav7gJrqJSFY4Ug53iA9JFJZh2gxKWcaFdLJwhHx9mRdg9JwDAWB4ywiu5154CRwXV4FMdnPLg7bhxRLwhhYaLsVgMF5AyNRcTzjCVoBvqFgDU7P8VEKDEiMvD3qxzm1pLZVxDG1LTQpT3Dz4Uviv4KQbFQNuC22KupBoyHFB7Zh6KFdMqux4M9PvhoqcoJsJKwXjWpKu7xmEKnnrSbfLadkgjBmmjhW3fdTrFvnhQdTkhtdJxUL1xS9GMuJQer8YgSKNtUXB1eXZQwXU8bU2BjYkZE6Q5Xww8hu9Z4E4Mo4QsooVtHoP6BM3NKw8zjVbWfoCQqxTrwuSzrNCWCWt58C24LHecH67CTt2uXbYSviixvrYkK7A3t68BxTJcF1dXJitEPTFe2ceTkauLJqrJgnER4iUrsjr26T8YgWvpY9wkkWFSviQW6wV5RASTCUasVEcrDiaKj8EQMkgyDoe9HyKitSVg67vMWJFpUXpQobseWJUs5FTWWzmfHmFp8FZ","meta":{"err":null,"fee":18000,"postBalances":[499999972500,15298080,1,1,1],"preBalances":[499999990500,15298080,1,1,1],"status":{"Ok":null}}}]},"id":1} ``` #### Transaction Structure @@ -703,9 +704,10 @@ An array of: * `` * `slot: ` - The slot the transaction was processed * `confirmations: ` - Number of blocks since signature confirmation, null if rooted - * `status: ` - Transaction status + * `err: ` - Error if transaction failed, null if transaction succeeded. [TransactionError definitions](https://github.com/solana-labs/solana/blob/master/sdk/src/transaction.rs#L14) + * DEPRECATED: `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) + * `"Err": ` - Transaction failed with TransactionError #### Example: @@ -714,10 +716,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":{"context":{"slot":82},"value":[{"slot": 72, "confirmations": 10, "status": {"Ok": null}}, null]},"id":1} +{"jsonrpc":"2.0","result":{"context":{"slot":82},"value":[{"slot": 72, "confirmations": 10, "err": null, "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} +{"jsonrpc":"2.0","result":{"context":{"slot":82},"value":[{"slot": 48, "confirmations": null, "err": null, "status": {"Ok": null}}, null]},"id":1} ``` ### getSlot @@ -1226,7 +1228,7 @@ Subscribe to a transaction signature to receive notification when the transactio #### Notification Format: ```bash -{"jsonrpc": "2.0","method": "signatureNotification", "params": {"result": "Confirmed","subscription":0}} +{"jsonrpc": "2.0","method": "signatureNotification", "params": {"result": {"err": null}, "subscription":0}} ``` ### signatureUnsubscribe diff --git a/ledger/src/blockstore.rs b/ledger/src/blockstore.rs index 0ae05b3b8..1d533b522 100644 --- a/ledger/src/blockstore.rs +++ b/ledger/src/blockstore.rs @@ -37,8 +37,8 @@ use solana_sdk::{ transaction::Transaction, }; use solana_transaction_status::{ - ConfirmedBlock, EncodedTransaction, Rewards, TransactionEncoding, TransactionStatusMeta, - TransactionWithStatusMeta, + ConfirmedBlock, EncodedTransaction, Rewards, RpcTransactionStatusMeta, TransactionEncoding, + TransactionStatusMeta, TransactionWithStatusMeta, }; use solana_vote_program::{vote_instruction::VoteInstruction, vote_state::TIMESTAMP_SLOT_INTERVAL}; use std::{ @@ -1500,7 +1500,8 @@ impl Blockstore { meta: self .transaction_status_cf .get((slot, signature)) - .expect("Expect database get to succeed"), + .expect("Expect database get to succeed") + .map(RpcTransactionStatusMeta::from), } }) .collect() @@ -4848,7 +4849,7 @@ pub mod tests { .put_meta_bytes(slot - 1, &serialize(&parent_meta).unwrap()) .unwrap(); - let expected_transactions: Vec<(Transaction, Option)> = entries + let expected_transactions: Vec<(Transaction, Option)> = entries .iter() .cloned() .filter(|entry| !entry.is_tick()) @@ -4887,12 +4888,15 @@ pub mod tests { .unwrap(); ( transaction, - Some(TransactionStatusMeta { - status: Ok(()), - fee: 42, - pre_balances, - post_balances, - }), + Some( + TransactionStatusMeta { + status: Ok(()), + fee: 42, + pre_balances, + post_balances, + } + .into(), + ), ) }) .collect(); diff --git a/stake-monitor/src/lib.rs b/stake-monitor/src/lib.rs index 30b877013..a7fa8dd1f 100644 --- a/stake-monitor/src/lib.rs +++ b/stake-monitor/src/lib.rs @@ -4,7 +4,7 @@ use solana_client::{client_error::Result as ClientResult, rpc_client::RpcClient} use solana_metrics::{datapoint_error, datapoint_info}; use solana_sdk::{clock::Slot, program_utils::limited_deserialize, transaction::Transaction}; use solana_stake_program::{stake_instruction::StakeInstruction, stake_state::Lockup}; -use solana_transaction_status::{ConfirmedBlock, TransactionEncoding, TransactionStatusMeta}; +use solana_transaction_status::{ConfirmedBlock, RpcTransactionStatusMeta, TransactionEncoding}; use std::{collections::HashMap, thread::sleep, time::Duration}; pub type PubkeyString = String; @@ -41,7 +41,7 @@ pub struct StakeAccountsInfo { fn process_transaction( slot: Slot, transaction: &Transaction, - meta: &TransactionStatusMeta, + meta: &RpcTransactionStatusMeta, stake_accounts: &mut HashMap, ) { let mut last_instruction = true; @@ -194,7 +194,7 @@ fn process_confirmed_block( ); } Some(meta) => { - if meta.status.is_ok() { + if meta.err.is_none() { if let Some(transaction) = rpc_transaction.transaction.decode() { if transaction.verify().is_ok() { process_transaction(slot, &transaction, &meta, stake_accounts); diff --git a/transaction-status/src/lib.rs b/transaction-status/src/lib.rs index ecabe07ce..c1573a0cf 100644 --- a/transaction-status/src/lib.rs +++ b/transaction-status/src/lib.rs @@ -5,7 +5,7 @@ use bincode; use solana_sdk::{ clock::Slot, message::MessageHeader, - transaction::{Result, Transaction}, + transaction::{Result, Transaction, TransactionError}, }; /// A duplicate representation of a Message for pretty JSON serialization @@ -26,12 +26,35 @@ pub struct TransactionStatusMeta { pub post_balances: Vec, } +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct RpcTransactionStatusMeta { + pub err: Option, + pub status: Result<()>, // This field is deprecated. See https://github.com/solana-labs/solana/issues/9302 + pub fee: u64, + pub pre_balances: Vec, + pub post_balances: Vec, +} + +impl From for RpcTransactionStatusMeta { + fn from(meta: TransactionStatusMeta) -> Self { + Self { + err: meta.status.clone().err(), + status: meta.status, + fee: meta.fee, + pre_balances: meta.pre_balances, + post_balances: meta.post_balances, + } + } +} + #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct TransactionStatus { pub slot: Slot, pub confirmations: Option, pub status: Result<()>, + pub err: Option, } #[derive(Debug, PartialEq, Serialize, Deserialize)] @@ -74,7 +97,7 @@ pub struct RpcMessage { #[serde(rename_all = "camelCase")] pub struct TransactionWithStatusMeta { pub transaction: EncodedTransaction, - pub meta: Option, + pub meta: Option, } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]