Add block_time to getConfirmedSignaturesForAddress2 and getConfirmedTransaction (#14572)
* add block_time to get_confirmed_signatures_for_address2 and protobuf implementation for tx_by_addr * add tests for convert * update cargo lock * run cargo format after rebase * introduce legacy TransactionByAddrInfo * move LegacyTransactionByAddrInfo back to storage-bigtable
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -5017,6 +5017,7 @@ name = "solana-storage-proto"
|
|||||||
version = "1.6.0"
|
version = "1.6.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bincode",
|
"bincode",
|
||||||
|
"bs58",
|
||||||
"prost",
|
"prost",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::client_error;
|
use crate::client_error;
|
||||||
use solana_account_decoder::{parse_token::UiTokenAmount, UiAccount};
|
use solana_account_decoder::{parse_token::UiTokenAmount, UiAccount};
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
clock::{Epoch, Slot},
|
clock::{Epoch, Slot, UnixTimestamp},
|
||||||
fee_calculator::{FeeCalculator, FeeRateGovernor},
|
fee_calculator::{FeeCalculator, FeeRateGovernor},
|
||||||
inflation::Inflation,
|
inflation::Inflation,
|
||||||
transaction::{Result, TransactionError},
|
transaction::{Result, TransactionError},
|
||||||
@ -286,6 +286,7 @@ pub struct RpcConfirmedTransactionStatusWithSignature {
|
|||||||
pub slot: Slot,
|
pub slot: Slot,
|
||||||
pub err: Option<TransactionError>,
|
pub err: Option<TransactionError>,
|
||||||
pub memo: Option<String>,
|
pub memo: Option<String>,
|
||||||
|
pub block_time: Option<UnixTimestamp>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
@ -304,12 +305,14 @@ impl From<ConfirmedTransactionStatusWithSignature> for RpcConfirmedTransactionSt
|
|||||||
slot,
|
slot,
|
||||||
err,
|
err,
|
||||||
memo,
|
memo,
|
||||||
|
block_time,
|
||||||
} = value;
|
} = value;
|
||||||
Self {
|
Self {
|
||||||
signature: signature.to_string(),
|
signature: signature.to_string(),
|
||||||
slot,
|
slot,
|
||||||
err,
|
err,
|
||||||
memo,
|
memo,
|
||||||
|
block_time,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2023,12 +2023,14 @@ impl Blockstore {
|
|||||||
let transaction = self
|
let transaction = self
|
||||||
.find_transaction_in_slot(slot, signature)?
|
.find_transaction_in_slot(slot, signature)?
|
||||||
.ok_or(BlockstoreError::TransactionStatusSlotMismatch)?; // Should not happen
|
.ok_or(BlockstoreError::TransactionStatusSlotMismatch)?; // Should not happen
|
||||||
|
let block_time = self.get_block_time(slot)?;
|
||||||
Ok(Some(ConfirmedTransaction {
|
Ok(Some(ConfirmedTransaction {
|
||||||
slot,
|
slot,
|
||||||
transaction: TransactionWithStatusMeta {
|
transaction: TransactionWithStatusMeta {
|
||||||
transaction,
|
transaction,
|
||||||
meta: Some(status),
|
meta: Some(status),
|
||||||
},
|
},
|
||||||
|
block_time,
|
||||||
}))
|
}))
|
||||||
} else {
|
} else {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
@ -2323,11 +2325,13 @@ impl Blockstore {
|
|||||||
None => None,
|
None => None,
|
||||||
Some((_slot, status)) => status.status.err(),
|
Some((_slot, status)) => status.status.err(),
|
||||||
};
|
};
|
||||||
|
let block_time = self.get_block_time(slot)?;
|
||||||
infos.push(ConfirmedTransactionStatusWithSignature {
|
infos.push(ConfirmedTransactionStatusWithSignature {
|
||||||
signature,
|
signature,
|
||||||
slot,
|
slot,
|
||||||
err,
|
err,
|
||||||
memo: None,
|
memo: None,
|
||||||
|
block_time,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
get_status_info_timer.stop();
|
get_status_info_timer.stop();
|
||||||
@ -6590,7 +6594,11 @@ pub mod tests {
|
|||||||
let signature = transaction.transaction.signatures[0];
|
let signature = transaction.transaction.signatures[0];
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
blockstore.get_confirmed_transaction(signature).unwrap(),
|
blockstore.get_confirmed_transaction(signature).unwrap(),
|
||||||
Some(ConfirmedTransaction { slot, transaction })
|
Some(ConfirmedTransaction {
|
||||||
|
slot,
|
||||||
|
transaction,
|
||||||
|
block_time: None
|
||||||
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,9 +8,10 @@ use solana_sdk::{
|
|||||||
transaction::{Transaction, TransactionError},
|
transaction::{Transaction, TransactionError},
|
||||||
};
|
};
|
||||||
use solana_storage_proto::convert::generated;
|
use solana_storage_proto::convert::generated;
|
||||||
|
use solana_storage_proto::convert::tx_by_addr;
|
||||||
use solana_transaction_status::{
|
use solana_transaction_status::{
|
||||||
ConfirmedBlock, ConfirmedTransaction, ConfirmedTransactionStatusWithSignature, Reward,
|
ConfirmedBlock, ConfirmedTransaction, ConfirmedTransactionStatusWithSignature, Reward,
|
||||||
TransactionConfirmationStatus, TransactionStatus, TransactionStatusMeta,
|
TransactionByAddrInfo, TransactionConfirmationStatus, TransactionStatus, TransactionStatusMeta,
|
||||||
TransactionWithStatusMeta,
|
TransactionWithStatusMeta,
|
||||||
};
|
};
|
||||||
use std::{collections::HashMap, convert::TryInto};
|
use std::{collections::HashMap, convert::TryInto};
|
||||||
@ -263,14 +264,31 @@ impl From<TransactionInfo> for TransactionStatus {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// A serialized `Vec<TransactionByAddrInfo>` is stored in the `tx-by-addr` table. The row keys are
|
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
// the one's compliment of the slot so that rows may be listed in reverse order
|
struct LegacyTransactionByAddrInfo {
|
||||||
#[derive(Serialize, Deserialize)]
|
pub signature: Signature, // The transaction signature
|
||||||
struct TransactionByAddrInfo {
|
pub err: Option<TransactionError>, // None if the transaction executed successfully
|
||||||
signature: Signature, // The transaction signature
|
pub index: u32, // Where the transaction is located in the block
|
||||||
err: Option<TransactionError>, // None if the transaction executed successfully
|
pub memo: Option<String>, // Transaction memo
|
||||||
index: u32, // Where the transaction is located in the block
|
}
|
||||||
memo: Option<String>, // Transaction memo
|
|
||||||
|
impl From<LegacyTransactionByAddrInfo> for TransactionByAddrInfo {
|
||||||
|
fn from(legacy: LegacyTransactionByAddrInfo) -> Self {
|
||||||
|
let LegacyTransactionByAddrInfo {
|
||||||
|
signature,
|
||||||
|
err,
|
||||||
|
index,
|
||||||
|
memo,
|
||||||
|
} = legacy;
|
||||||
|
|
||||||
|
Self {
|
||||||
|
signature,
|
||||||
|
err,
|
||||||
|
index,
|
||||||
|
memo,
|
||||||
|
block_time: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@ -363,6 +381,7 @@ impl LedgerStorage {
|
|||||||
Ok(Some(ConfirmedTransaction {
|
Ok(Some(ConfirmedTransaction {
|
||||||
slot,
|
slot,
|
||||||
transaction: bucket_block_transaction,
|
transaction: bucket_block_transaction,
|
||||||
|
block_time: block.block_time,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -417,12 +436,17 @@ impl LedgerStorage {
|
|||||||
let mut infos = vec![];
|
let mut infos = vec![];
|
||||||
|
|
||||||
let starting_slot_tx_len = bigtable
|
let starting_slot_tx_len = bigtable
|
||||||
.get_bincode_cell::<Vec<TransactionByAddrInfo>>(
|
.get_protobuf_or_bincode_cell::<Vec<LegacyTransactionByAddrInfo>, tx_by_addr::TransactionByAddr>(
|
||||||
"tx-by-addr",
|
"tx-by-addr",
|
||||||
format!("{}{}", address_prefix, slot_to_key(!first_slot)),
|
format!("{}{}", address_prefix, slot_to_key(!first_slot)),
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.map(|txs| txs.len())
|
.map(|cell_data| {
|
||||||
|
match cell_data {
|
||||||
|
bigtable::CellData::Bincode(tx_by_addr) => tx_by_addr.len(),
|
||||||
|
bigtable::CellData::Protobuf(tx_by_addr) => tx_by_addr.tx_by_addrs.len(),
|
||||||
|
}
|
||||||
|
})
|
||||||
.unwrap_or(0);
|
.unwrap_or(0);
|
||||||
|
|
||||||
// Return the next tx-by-addr data of amount `limit` plus extra to account for the largest
|
// Return the next tx-by-addr data of amount `limit` plus extra to account for the largest
|
||||||
@ -443,8 +467,27 @@ impl LedgerStorage {
|
|||||||
row_key
|
row_key
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
let mut cell_data: Vec<TransactionByAddrInfo> =
|
|
||||||
bigtable::deserialize_bincode_cell_data(&data, "tx-by-addr", row_key)?;
|
let deserialized_cell_data = bigtable::deserialize_protobuf_or_bincode_cell_data::<
|
||||||
|
Vec<LegacyTransactionByAddrInfo>,
|
||||||
|
tx_by_addr::TransactionByAddr,
|
||||||
|
>(&data, "tx-by-addr", row_key.clone())?;
|
||||||
|
|
||||||
|
let mut cell_data: Vec<TransactionByAddrInfo> = match deserialized_cell_data {
|
||||||
|
bigtable::CellData::Bincode(tx_by_addr) => {
|
||||||
|
tx_by_addr.into_iter().map(|legacy| legacy.into()).collect()
|
||||||
|
}
|
||||||
|
bigtable::CellData::Protobuf(tx_by_addr) => {
|
||||||
|
tx_by_addr.try_into().map_err(|error| {
|
||||||
|
bigtable::Error::ObjectCorrupt(format!(
|
||||||
|
"Failed to deserialize: {}: tx-by-addr/{}",
|
||||||
|
error,
|
||||||
|
row_key.clone()
|
||||||
|
))
|
||||||
|
})?
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
cell_data.reverse();
|
cell_data.reverse();
|
||||||
for tx_by_addr_info in cell_data.into_iter() {
|
for tx_by_addr_info in cell_data.into_iter() {
|
||||||
// Filter out records before `before_transaction_index`
|
// Filter out records before `before_transaction_index`
|
||||||
@ -461,6 +504,7 @@ impl LedgerStorage {
|
|||||||
slot,
|
slot,
|
||||||
err: tx_by_addr_info.err,
|
err: tx_by_addr_info.err,
|
||||||
memo: tx_by_addr_info.memo,
|
memo: tx_by_addr_info.memo,
|
||||||
|
block_time: tx_by_addr_info.block_time,
|
||||||
},
|
},
|
||||||
tx_by_addr_info.index,
|
tx_by_addr_info.index,
|
||||||
));
|
));
|
||||||
@ -500,6 +544,7 @@ impl LedgerStorage {
|
|||||||
err: err.clone(),
|
err: err.clone(),
|
||||||
index,
|
index,
|
||||||
memo: None, // TODO
|
memo: None, // TODO
|
||||||
|
block_time: confirmed_block.block_time,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -520,7 +565,12 @@ impl LedgerStorage {
|
|||||||
.map(|(address, transaction_info_by_addr)| {
|
.map(|(address, transaction_info_by_addr)| {
|
||||||
(
|
(
|
||||||
format!("{}/{}", address, slot_to_key(!slot)),
|
format!("{}/{}", address, slot_to_key(!slot)),
|
||||||
transaction_info_by_addr,
|
tx_by_addr::TransactionByAddr {
|
||||||
|
tx_by_addrs: transaction_info_by_addr
|
||||||
|
.into_iter()
|
||||||
|
.map(|by_addr| by_addr.into())
|
||||||
|
.collect(),
|
||||||
|
},
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
@ -535,7 +585,7 @@ impl LedgerStorage {
|
|||||||
if !tx_by_addr_cells.is_empty() {
|
if !tx_by_addr_cells.is_empty() {
|
||||||
bytes_written += self
|
bytes_written += self
|
||||||
.connection
|
.connection
|
||||||
.put_bincode_cells_with_retry::<Vec<TransactionByAddrInfo>>(
|
.put_protobuf_cells_with_retry::<tx_by_addr::TransactionByAddr>(
|
||||||
"tx-by-addr",
|
"tx-by-addr",
|
||||||
&tx_by_addr_cells,
|
&tx_by_addr_cells,
|
||||||
)
|
)
|
||||||
|
@ -10,6 +10,7 @@ edition = "2018"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bincode = "1.2.1"
|
bincode = "1.2.1"
|
||||||
|
bs58 = "0.3.1"
|
||||||
prost = "0.6.1"
|
prost = "0.6.1"
|
||||||
serde = "1.0.112"
|
serde = "1.0.112"
|
||||||
serde_derive = "1.0.103"
|
serde_derive = "1.0.103"
|
||||||
|
@ -12,5 +12,11 @@ fn main() -> Result<(), std::io::Error> {
|
|||||||
.build_server(false)
|
.build_server(false)
|
||||||
.format(true)
|
.format(true)
|
||||||
.out_dir(&out_dir)
|
.out_dir(&out_dir)
|
||||||
.compile(&[proto_files.join("confirmed_block.proto")], &[proto_files])
|
.compile(
|
||||||
|
&[
|
||||||
|
proto_files.join("confirmed_block.proto"),
|
||||||
|
proto_files.join("transaction_by_addr.proto"),
|
||||||
|
],
|
||||||
|
&[proto_files],
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
117
storage-proto/proto/solana.storage.transaction_by_addr.rs
Normal file
117
storage-proto/proto/solana.storage.transaction_by_addr.rs
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||||
|
pub struct TransactionByAddr {
|
||||||
|
#[prost(message, repeated, tag = "1")]
|
||||||
|
pub tx_by_addrs: ::std::vec::Vec<TransactionByAddrInfo>,
|
||||||
|
}
|
||||||
|
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||||
|
pub struct TransactionByAddrInfo {
|
||||||
|
#[prost(bytes, tag = "1")]
|
||||||
|
pub signature: std::vec::Vec<u8>,
|
||||||
|
#[prost(message, optional, tag = "2")]
|
||||||
|
pub err: ::std::option::Option<TransactionError>,
|
||||||
|
#[prost(uint32, tag = "3")]
|
||||||
|
pub index: u32,
|
||||||
|
#[prost(message, optional, tag = "4")]
|
||||||
|
pub memo: ::std::option::Option<Memo>,
|
||||||
|
#[prost(message, optional, tag = "5")]
|
||||||
|
pub block_time: ::std::option::Option<UnixTimestamp>,
|
||||||
|
}
|
||||||
|
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||||
|
pub struct Memo {
|
||||||
|
#[prost(string, tag = "1")]
|
||||||
|
pub memo: std::string::String,
|
||||||
|
}
|
||||||
|
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||||
|
pub struct TransactionError {
|
||||||
|
#[prost(enumeration = "TransactionErrorType", tag = "1")]
|
||||||
|
pub transaction_error: i32,
|
||||||
|
#[prost(message, optional, tag = "2")]
|
||||||
|
pub instruction_error: ::std::option::Option<InstructionError>,
|
||||||
|
}
|
||||||
|
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||||
|
pub struct InstructionError {
|
||||||
|
#[prost(uint32, tag = "1")]
|
||||||
|
pub index: u32,
|
||||||
|
#[prost(enumeration = "InstructionErrorType", tag = "2")]
|
||||||
|
pub error: i32,
|
||||||
|
#[prost(message, optional, tag = "3")]
|
||||||
|
pub custom: ::std::option::Option<CustomError>,
|
||||||
|
}
|
||||||
|
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||||
|
pub struct UnixTimestamp {
|
||||||
|
#[prost(int64, tag = "1")]
|
||||||
|
pub timestamp: i64,
|
||||||
|
}
|
||||||
|
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||||
|
pub struct CustomError {
|
||||||
|
#[prost(uint32, tag = "1")]
|
||||||
|
pub custom: u32,
|
||||||
|
}
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
|
||||||
|
#[repr(i32)]
|
||||||
|
pub enum TransactionErrorType {
|
||||||
|
AccountInUse = 0,
|
||||||
|
AccountLoadedTwice = 1,
|
||||||
|
AccountNotFound = 2,
|
||||||
|
ProgramAccountNotFound = 3,
|
||||||
|
InsufficientFundsForFee = 4,
|
||||||
|
InvalidAccountForFee = 5,
|
||||||
|
DuplicateSignature = 6,
|
||||||
|
BlockhashNotFound = 7,
|
||||||
|
InstructionError = 8,
|
||||||
|
CallChainTooDeep = 9,
|
||||||
|
MissingSignatureForFee = 10,
|
||||||
|
InvalidAccountIndex = 11,
|
||||||
|
SignatureFailure = 12,
|
||||||
|
InvalidProgramForExecution = 13,
|
||||||
|
SanitizeFailure = 14,
|
||||||
|
ClusterMaintenance = 15,
|
||||||
|
}
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
|
||||||
|
#[repr(i32)]
|
||||||
|
pub enum InstructionErrorType {
|
||||||
|
GenericError = 0,
|
||||||
|
InvalidArgument = 1,
|
||||||
|
InvalidInstructionData = 2,
|
||||||
|
InvalidAccountData = 3,
|
||||||
|
AccountDataTooSmall = 4,
|
||||||
|
InsufficientFunds = 5,
|
||||||
|
IncorrectProgramId = 6,
|
||||||
|
MissingRequiredSignature = 7,
|
||||||
|
AccountAlreadyInitialized = 8,
|
||||||
|
UninitializedAccount = 9,
|
||||||
|
UnbalancedInstruction = 10,
|
||||||
|
ModifiedProgramId = 11,
|
||||||
|
ExternalAccountLamportSpend = 12,
|
||||||
|
ExternalAccountDataModified = 13,
|
||||||
|
ReadonlyLamportChange = 14,
|
||||||
|
ReadonlyDataModified = 15,
|
||||||
|
DuplicateAccountIndex = 16,
|
||||||
|
ExecutableModified = 17,
|
||||||
|
RentEpochModified = 18,
|
||||||
|
NotEnoughAccountKeys = 19,
|
||||||
|
AccountDataSizeChanged = 20,
|
||||||
|
AccountNotExecutable = 21,
|
||||||
|
AccountBorrowFailed = 22,
|
||||||
|
AccountBorrowOutstanding = 23,
|
||||||
|
DuplicateAccountOutOfSync = 24,
|
||||||
|
Custom = 25,
|
||||||
|
InvalidError = 26,
|
||||||
|
ExecutableDataModified = 27,
|
||||||
|
ExecutableLamportChange = 28,
|
||||||
|
ExecutableAccountNotRentExempt = 29,
|
||||||
|
UnsupportedProgramId = 30,
|
||||||
|
CallDepth = 31,
|
||||||
|
MissingAccount = 32,
|
||||||
|
ReentrancyNotAllowed = 33,
|
||||||
|
MaxSeedLengthExceeded = 34,
|
||||||
|
InvalidSeeds = 35,
|
||||||
|
InvalidRealloc = 36,
|
||||||
|
ComputationalBudgetExceeded = 37,
|
||||||
|
PrivilegeEscalation = 38,
|
||||||
|
ProgramEnvironmentSetupFailure = 39,
|
||||||
|
ProgramFailedToComplete = 40,
|
||||||
|
ProgramFailedToCompile = 41,
|
||||||
|
Immutable = 42,
|
||||||
|
IncorrectAuthority = 43,
|
||||||
|
}
|
@ -3,14 +3,16 @@ use solana_account_decoder::parse_token::UiTokenAmount;
|
|||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
hash::Hash,
|
hash::Hash,
|
||||||
instruction::CompiledInstruction,
|
instruction::CompiledInstruction,
|
||||||
|
instruction::InstructionError,
|
||||||
message::{Message, MessageHeader},
|
message::{Message, MessageHeader},
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
signature::Signature,
|
signature::Signature,
|
||||||
transaction::Transaction,
|
transaction::Transaction,
|
||||||
|
transaction::TransactionError,
|
||||||
};
|
};
|
||||||
use solana_transaction_status::{
|
use solana_transaction_status::{
|
||||||
ConfirmedBlock, InnerInstructions, Reward, RewardType, TransactionStatusMeta,
|
ConfirmedBlock, InnerInstructions, Reward, RewardType, TransactionByAddrInfo,
|
||||||
TransactionTokenBalance, TransactionWithStatusMeta,
|
TransactionStatusMeta, TransactionTokenBalance, TransactionWithStatusMeta,
|
||||||
};
|
};
|
||||||
use std::convert::{TryFrom, TryInto};
|
use std::convert::{TryFrom, TryInto};
|
||||||
|
|
||||||
@ -21,6 +23,13 @@ pub mod generated {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub mod tx_by_addr {
|
||||||
|
include!(concat!(
|
||||||
|
env!("CARGO_MANIFEST_DIR"),
|
||||||
|
concat!("/proto/solana.storage.transaction_by_addr.rs")
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
impl From<Vec<Reward>> for generated::Rewards {
|
impl From<Vec<Reward>> for generated::Rewards {
|
||||||
fn from(rewards: Vec<Reward>) -> Self {
|
fn from(rewards: Vec<Reward>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@ -417,6 +426,356 @@ impl From<generated::CompiledInstruction> for CompiledInstruction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl TryFrom<tx_by_addr::TransactionError> for TransactionError {
|
||||||
|
type Error = &'static str;
|
||||||
|
|
||||||
|
fn try_from(transaction_error: tx_by_addr::TransactionError) -> Result<Self, Self::Error> {
|
||||||
|
if transaction_error.transaction_error == 8 {
|
||||||
|
if let Some(instruction_error) = transaction_error.instruction_error {
|
||||||
|
if let Some(custom) = instruction_error.custom {
|
||||||
|
return Ok(TransactionError::InstructionError(
|
||||||
|
instruction_error.index as u8,
|
||||||
|
InstructionError::Custom(custom.custom),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
let ie = match instruction_error.error {
|
||||||
|
0 => InstructionError::GenericError,
|
||||||
|
1 => InstructionError::InvalidArgument,
|
||||||
|
2 => InstructionError::InvalidInstructionData,
|
||||||
|
3 => InstructionError::InvalidAccountData,
|
||||||
|
4 => InstructionError::AccountDataTooSmall,
|
||||||
|
5 => InstructionError::InsufficientFunds,
|
||||||
|
6 => InstructionError::IncorrectProgramId,
|
||||||
|
7 => InstructionError::MissingRequiredSignature,
|
||||||
|
8 => InstructionError::AccountAlreadyInitialized,
|
||||||
|
9 => InstructionError::UninitializedAccount,
|
||||||
|
10 => InstructionError::UnbalancedInstruction,
|
||||||
|
11 => InstructionError::ModifiedProgramId,
|
||||||
|
12 => InstructionError::ExternalAccountLamportSpend,
|
||||||
|
13 => InstructionError::ExternalAccountDataModified,
|
||||||
|
14 => InstructionError::ReadonlyLamportChange,
|
||||||
|
15 => InstructionError::ReadonlyDataModified,
|
||||||
|
16 => InstructionError::DuplicateAccountIndex,
|
||||||
|
17 => InstructionError::ExecutableModified,
|
||||||
|
18 => InstructionError::RentEpochModified,
|
||||||
|
19 => InstructionError::NotEnoughAccountKeys,
|
||||||
|
20 => InstructionError::AccountDataSizeChanged,
|
||||||
|
21 => InstructionError::AccountNotExecutable,
|
||||||
|
22 => InstructionError::AccountBorrowFailed,
|
||||||
|
23 => InstructionError::AccountBorrowOutstanding,
|
||||||
|
24 => InstructionError::DuplicateAccountOutOfSync,
|
||||||
|
26 => InstructionError::InvalidError,
|
||||||
|
27 => InstructionError::ExecutableDataModified,
|
||||||
|
28 => InstructionError::ExecutableLamportChange,
|
||||||
|
29 => InstructionError::ExecutableAccountNotRentExempt,
|
||||||
|
30 => InstructionError::UnsupportedProgramId,
|
||||||
|
31 => InstructionError::CallDepth,
|
||||||
|
32 => InstructionError::MissingAccount,
|
||||||
|
33 => InstructionError::ReentrancyNotAllowed,
|
||||||
|
34 => InstructionError::MaxSeedLengthExceeded,
|
||||||
|
35 => InstructionError::InvalidSeeds,
|
||||||
|
36 => InstructionError::InvalidRealloc,
|
||||||
|
37 => InstructionError::ComputationalBudgetExceeded,
|
||||||
|
38 => InstructionError::PrivilegeEscalation,
|
||||||
|
39 => InstructionError::ProgramEnvironmentSetupFailure,
|
||||||
|
40 => InstructionError::ProgramFailedToComplete,
|
||||||
|
41 => InstructionError::ProgramFailedToCompile,
|
||||||
|
42 => InstructionError::Immutable,
|
||||||
|
43 => InstructionError::IncorrectAuthority,
|
||||||
|
_ => return Err("Invalid InstructionError"),
|
||||||
|
};
|
||||||
|
|
||||||
|
return Ok(TransactionError::InstructionError(
|
||||||
|
instruction_error.index as u8,
|
||||||
|
ie,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(match transaction_error.transaction_error {
|
||||||
|
0 => TransactionError::AccountInUse,
|
||||||
|
1 => TransactionError::AccountLoadedTwice,
|
||||||
|
2 => TransactionError::AccountNotFound,
|
||||||
|
3 => TransactionError::ProgramAccountNotFound,
|
||||||
|
4 => TransactionError::InsufficientFundsForFee,
|
||||||
|
5 => TransactionError::InvalidAccountForFee,
|
||||||
|
6 => TransactionError::DuplicateSignature,
|
||||||
|
7 => TransactionError::BlockhashNotFound,
|
||||||
|
9 => TransactionError::CallChainTooDeep,
|
||||||
|
10 => TransactionError::MissingSignatureForFee,
|
||||||
|
11 => TransactionError::InvalidAccountIndex,
|
||||||
|
12 => TransactionError::SignatureFailure,
|
||||||
|
13 => TransactionError::InvalidProgramForExecution,
|
||||||
|
14 => TransactionError::SanitizeFailure,
|
||||||
|
15 => TransactionError::ClusterMaintenance,
|
||||||
|
_ => return Err("Invalid TransactionError"),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<TransactionError> for tx_by_addr::TransactionError {
|
||||||
|
fn from(transaction_error: TransactionError) -> Self {
|
||||||
|
Self {
|
||||||
|
transaction_error: match transaction_error {
|
||||||
|
TransactionError::AccountInUse => tx_by_addr::TransactionErrorType::AccountInUse,
|
||||||
|
TransactionError::AccountLoadedTwice => {
|
||||||
|
tx_by_addr::TransactionErrorType::AccountLoadedTwice
|
||||||
|
}
|
||||||
|
TransactionError::AccountNotFound => {
|
||||||
|
tx_by_addr::TransactionErrorType::AccountNotFound
|
||||||
|
}
|
||||||
|
TransactionError::ProgramAccountNotFound => {
|
||||||
|
tx_by_addr::TransactionErrorType::ProgramAccountNotFound
|
||||||
|
}
|
||||||
|
TransactionError::InsufficientFundsForFee => {
|
||||||
|
tx_by_addr::TransactionErrorType::InsufficientFundsForFee
|
||||||
|
}
|
||||||
|
TransactionError::InvalidAccountForFee => {
|
||||||
|
tx_by_addr::TransactionErrorType::InvalidAccountForFee
|
||||||
|
}
|
||||||
|
TransactionError::DuplicateSignature => {
|
||||||
|
tx_by_addr::TransactionErrorType::DuplicateSignature
|
||||||
|
}
|
||||||
|
TransactionError::BlockhashNotFound => {
|
||||||
|
tx_by_addr::TransactionErrorType::BlockhashNotFound
|
||||||
|
}
|
||||||
|
TransactionError::CallChainTooDeep => {
|
||||||
|
tx_by_addr::TransactionErrorType::CallChainTooDeep
|
||||||
|
}
|
||||||
|
TransactionError::MissingSignatureForFee => {
|
||||||
|
tx_by_addr::TransactionErrorType::MissingSignatureForFee
|
||||||
|
}
|
||||||
|
TransactionError::InvalidAccountIndex => {
|
||||||
|
tx_by_addr::TransactionErrorType::InvalidAccountIndex
|
||||||
|
}
|
||||||
|
TransactionError::SignatureFailure => {
|
||||||
|
tx_by_addr::TransactionErrorType::SignatureFailure
|
||||||
|
}
|
||||||
|
TransactionError::InvalidProgramForExecution => {
|
||||||
|
tx_by_addr::TransactionErrorType::InvalidProgramForExecution
|
||||||
|
}
|
||||||
|
TransactionError::SanitizeFailure => {
|
||||||
|
tx_by_addr::TransactionErrorType::SanitizeFailure
|
||||||
|
}
|
||||||
|
TransactionError::ClusterMaintenance => {
|
||||||
|
tx_by_addr::TransactionErrorType::ClusterMaintenance
|
||||||
|
}
|
||||||
|
TransactionError::InstructionError(_, _) => {
|
||||||
|
tx_by_addr::TransactionErrorType::InstructionError
|
||||||
|
}
|
||||||
|
} as i32,
|
||||||
|
instruction_error: match transaction_error {
|
||||||
|
TransactionError::InstructionError(index, ref instruction_error) => {
|
||||||
|
Some(tx_by_addr::InstructionError {
|
||||||
|
index: index as u32,
|
||||||
|
error: match instruction_error {
|
||||||
|
InstructionError::GenericError => {
|
||||||
|
tx_by_addr::InstructionErrorType::GenericError
|
||||||
|
}
|
||||||
|
InstructionError::InvalidArgument => {
|
||||||
|
tx_by_addr::InstructionErrorType::InvalidArgument
|
||||||
|
}
|
||||||
|
InstructionError::InvalidInstructionData => {
|
||||||
|
tx_by_addr::InstructionErrorType::InvalidInstructionData
|
||||||
|
}
|
||||||
|
InstructionError::InvalidAccountData => {
|
||||||
|
tx_by_addr::InstructionErrorType::InvalidAccountData
|
||||||
|
}
|
||||||
|
InstructionError::AccountDataTooSmall => {
|
||||||
|
tx_by_addr::InstructionErrorType::AccountDataTooSmall
|
||||||
|
}
|
||||||
|
InstructionError::InsufficientFunds => {
|
||||||
|
tx_by_addr::InstructionErrorType::InsufficientFunds
|
||||||
|
}
|
||||||
|
InstructionError::IncorrectProgramId => {
|
||||||
|
tx_by_addr::InstructionErrorType::IncorrectProgramId
|
||||||
|
}
|
||||||
|
InstructionError::MissingRequiredSignature => {
|
||||||
|
tx_by_addr::InstructionErrorType::MissingRequiredSignature
|
||||||
|
}
|
||||||
|
InstructionError::AccountAlreadyInitialized => {
|
||||||
|
tx_by_addr::InstructionErrorType::AccountAlreadyInitialized
|
||||||
|
}
|
||||||
|
InstructionError::UninitializedAccount => {
|
||||||
|
tx_by_addr::InstructionErrorType::UninitializedAccount
|
||||||
|
}
|
||||||
|
InstructionError::UnbalancedInstruction => {
|
||||||
|
tx_by_addr::InstructionErrorType::UnbalancedInstruction
|
||||||
|
}
|
||||||
|
InstructionError::ModifiedProgramId => {
|
||||||
|
tx_by_addr::InstructionErrorType::ModifiedProgramId
|
||||||
|
}
|
||||||
|
InstructionError::ExternalAccountLamportSpend => {
|
||||||
|
tx_by_addr::InstructionErrorType::ExternalAccountLamportSpend
|
||||||
|
}
|
||||||
|
InstructionError::ExternalAccountDataModified => {
|
||||||
|
tx_by_addr::InstructionErrorType::ExternalAccountDataModified
|
||||||
|
}
|
||||||
|
InstructionError::ReadonlyLamportChange => {
|
||||||
|
tx_by_addr::InstructionErrorType::ReadonlyLamportChange
|
||||||
|
}
|
||||||
|
InstructionError::ReadonlyDataModified => {
|
||||||
|
tx_by_addr::InstructionErrorType::ReadonlyDataModified
|
||||||
|
}
|
||||||
|
InstructionError::DuplicateAccountIndex => {
|
||||||
|
tx_by_addr::InstructionErrorType::DuplicateAccountIndex
|
||||||
|
}
|
||||||
|
InstructionError::ExecutableModified => {
|
||||||
|
tx_by_addr::InstructionErrorType::ExecutableModified
|
||||||
|
}
|
||||||
|
InstructionError::RentEpochModified => {
|
||||||
|
tx_by_addr::InstructionErrorType::RentEpochModified
|
||||||
|
}
|
||||||
|
InstructionError::NotEnoughAccountKeys => {
|
||||||
|
tx_by_addr::InstructionErrorType::NotEnoughAccountKeys
|
||||||
|
}
|
||||||
|
InstructionError::AccountDataSizeChanged => {
|
||||||
|
tx_by_addr::InstructionErrorType::AccountDataSizeChanged
|
||||||
|
}
|
||||||
|
InstructionError::AccountNotExecutable => {
|
||||||
|
tx_by_addr::InstructionErrorType::AccountNotExecutable
|
||||||
|
}
|
||||||
|
InstructionError::AccountBorrowFailed => {
|
||||||
|
tx_by_addr::InstructionErrorType::AccountBorrowFailed
|
||||||
|
}
|
||||||
|
InstructionError::AccountBorrowOutstanding => {
|
||||||
|
tx_by_addr::InstructionErrorType::AccountBorrowOutstanding
|
||||||
|
}
|
||||||
|
InstructionError::DuplicateAccountOutOfSync => {
|
||||||
|
tx_by_addr::InstructionErrorType::DuplicateAccountOutOfSync
|
||||||
|
}
|
||||||
|
InstructionError::Custom(_) => tx_by_addr::InstructionErrorType::Custom,
|
||||||
|
InstructionError::InvalidError => {
|
||||||
|
tx_by_addr::InstructionErrorType::InvalidError
|
||||||
|
}
|
||||||
|
InstructionError::ExecutableDataModified => {
|
||||||
|
tx_by_addr::InstructionErrorType::ExecutableDataModified
|
||||||
|
}
|
||||||
|
InstructionError::ExecutableLamportChange => {
|
||||||
|
tx_by_addr::InstructionErrorType::ExecutableLamportChange
|
||||||
|
}
|
||||||
|
InstructionError::ExecutableAccountNotRentExempt => {
|
||||||
|
tx_by_addr::InstructionErrorType::ExecutableAccountNotRentExempt
|
||||||
|
}
|
||||||
|
InstructionError::UnsupportedProgramId => {
|
||||||
|
tx_by_addr::InstructionErrorType::UnsupportedProgramId
|
||||||
|
}
|
||||||
|
InstructionError::CallDepth => {
|
||||||
|
tx_by_addr::InstructionErrorType::CallDepth
|
||||||
|
}
|
||||||
|
InstructionError::MissingAccount => {
|
||||||
|
tx_by_addr::InstructionErrorType::MissingAccount
|
||||||
|
}
|
||||||
|
InstructionError::ReentrancyNotAllowed => {
|
||||||
|
tx_by_addr::InstructionErrorType::ReentrancyNotAllowed
|
||||||
|
}
|
||||||
|
InstructionError::MaxSeedLengthExceeded => {
|
||||||
|
tx_by_addr::InstructionErrorType::MaxSeedLengthExceeded
|
||||||
|
}
|
||||||
|
InstructionError::InvalidSeeds => {
|
||||||
|
tx_by_addr::InstructionErrorType::InvalidSeeds
|
||||||
|
}
|
||||||
|
InstructionError::InvalidRealloc => {
|
||||||
|
tx_by_addr::InstructionErrorType::InvalidRealloc
|
||||||
|
}
|
||||||
|
InstructionError::ComputationalBudgetExceeded => {
|
||||||
|
tx_by_addr::InstructionErrorType::ComputationalBudgetExceeded
|
||||||
|
}
|
||||||
|
InstructionError::PrivilegeEscalation => {
|
||||||
|
tx_by_addr::InstructionErrorType::PrivilegeEscalation
|
||||||
|
}
|
||||||
|
InstructionError::ProgramEnvironmentSetupFailure => {
|
||||||
|
tx_by_addr::InstructionErrorType::ProgramEnvironmentSetupFailure
|
||||||
|
}
|
||||||
|
InstructionError::ProgramFailedToComplete => {
|
||||||
|
tx_by_addr::InstructionErrorType::ProgramFailedToComplete
|
||||||
|
}
|
||||||
|
InstructionError::ProgramFailedToCompile => {
|
||||||
|
tx_by_addr::InstructionErrorType::ProgramFailedToCompile
|
||||||
|
}
|
||||||
|
InstructionError::Immutable => {
|
||||||
|
tx_by_addr::InstructionErrorType::Immutable
|
||||||
|
}
|
||||||
|
InstructionError::IncorrectAuthority => {
|
||||||
|
tx_by_addr::InstructionErrorType::IncorrectAuthority
|
||||||
|
}
|
||||||
|
} as i32,
|
||||||
|
custom: match instruction_error {
|
||||||
|
InstructionError::Custom(custom) => {
|
||||||
|
Some(tx_by_addr::CustomError { custom: *custom })
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<TransactionByAddrInfo> for tx_by_addr::TransactionByAddrInfo {
|
||||||
|
fn from(by_addr: TransactionByAddrInfo) -> Self {
|
||||||
|
let TransactionByAddrInfo {
|
||||||
|
signature,
|
||||||
|
err,
|
||||||
|
index,
|
||||||
|
memo,
|
||||||
|
block_time,
|
||||||
|
} = by_addr;
|
||||||
|
|
||||||
|
Self {
|
||||||
|
signature: <Signature as AsRef<[u8]>>::as_ref(&signature).into(),
|
||||||
|
err: match err {
|
||||||
|
None => None,
|
||||||
|
Some(e) => Some(e.into()),
|
||||||
|
},
|
||||||
|
index,
|
||||||
|
memo: memo.map(|memo| tx_by_addr::Memo { memo }),
|
||||||
|
block_time: block_time.map(|timestamp| tx_by_addr::UnixTimestamp { timestamp }),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<tx_by_addr::TransactionByAddrInfo> for TransactionByAddrInfo {
|
||||||
|
type Error = &'static str;
|
||||||
|
|
||||||
|
fn try_from(
|
||||||
|
transaction_by_addr: tx_by_addr::TransactionByAddrInfo,
|
||||||
|
) -> Result<Self, Self::Error> {
|
||||||
|
let err = if let Some(err) = transaction_by_addr.err {
|
||||||
|
Some(err.try_into()?)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
signature: Signature::new(&transaction_by_addr.signature),
|
||||||
|
err,
|
||||||
|
index: transaction_by_addr.index,
|
||||||
|
memo: transaction_by_addr
|
||||||
|
.memo
|
||||||
|
.map(|tx_by_addr::Memo { memo }| memo),
|
||||||
|
block_time: transaction_by_addr
|
||||||
|
.block_time
|
||||||
|
.map(|tx_by_addr::UnixTimestamp { timestamp }| timestamp),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<tx_by_addr::TransactionByAddr> for Vec<TransactionByAddrInfo> {
|
||||||
|
type Error = &'static str;
|
||||||
|
|
||||||
|
fn try_from(collection: tx_by_addr::TransactionByAddr) -> Result<Self, Self::Error> {
|
||||||
|
Ok(collection
|
||||||
|
.tx_by_addrs
|
||||||
|
.into_iter()
|
||||||
|
.map(|tx_by_addr| tx_by_addr.try_into())
|
||||||
|
.collect::<Result<Vec<TransactionByAddrInfo>, Self::Error>>()?)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -448,4 +807,539 @@ mod test {
|
|||||||
let gen_reward: generated::Reward = reward.clone().into();
|
let gen_reward: generated::Reward = reward.clone().into();
|
||||||
assert_eq!(reward, gen_reward.into());
|
assert_eq!(reward, gen_reward.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_transaction_by_addr_encode() {
|
||||||
|
let info = TransactionByAddrInfo {
|
||||||
|
signature: Signature::new(&bs58::decode("Nfo6rgemG1KLbk1xuNwfrQTsdxaGfLuWURHNRy9LYnDrubG7LFQZaA5obPNas9LQ6DdorJqxh2LxA3PsnWdkSrL").into_vec().unwrap()),
|
||||||
|
err: None,
|
||||||
|
index: 5,
|
||||||
|
memo: Some("string".to_string()),
|
||||||
|
block_time: Some(1610674861)
|
||||||
|
};
|
||||||
|
|
||||||
|
let tx_by_addr_transaction_info: tx_by_addr::TransactionByAddrInfo = info.clone().into();
|
||||||
|
assert_eq!(info, tx_by_addr_transaction_info.try_into().unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_transaction_error_encode() {
|
||||||
|
let transaction_error = TransactionError::AccountInUse;
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error = TransactionError::AccountLoadedTwice;
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error = TransactionError::AccountNotFound;
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error = TransactionError::BlockhashNotFound;
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error = TransactionError::CallChainTooDeep;
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error = TransactionError::ClusterMaintenance;
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error = TransactionError::DuplicateSignature;
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error = TransactionError::InsufficientFundsForFee;
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error = TransactionError::InvalidAccountForFee;
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error = TransactionError::InvalidAccountIndex;
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error = TransactionError::InvalidProgramForExecution;
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error = TransactionError::MissingSignatureForFee;
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error = TransactionError::ProgramAccountNotFound;
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error = TransactionError::SanitizeFailure;
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error = TransactionError::SignatureFailure;
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error =
|
||||||
|
TransactionError::InstructionError(10, InstructionError::AccountAlreadyInitialized);
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error =
|
||||||
|
TransactionError::InstructionError(10, InstructionError::AccountBorrowFailed);
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error =
|
||||||
|
TransactionError::InstructionError(10, InstructionError::AccountBorrowOutstanding);
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error =
|
||||||
|
TransactionError::InstructionError(10, InstructionError::AccountDataSizeChanged);
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error =
|
||||||
|
TransactionError::InstructionError(10, InstructionError::AccountDataTooSmall);
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error =
|
||||||
|
TransactionError::InstructionError(10, InstructionError::AccountNotExecutable);
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error = TransactionError::InstructionError(10, InstructionError::CallDepth);
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error =
|
||||||
|
TransactionError::InstructionError(10, InstructionError::ComputationalBudgetExceeded);
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error =
|
||||||
|
TransactionError::InstructionError(10, InstructionError::DuplicateAccountIndex);
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error =
|
||||||
|
TransactionError::InstructionError(10, InstructionError::DuplicateAccountOutOfSync);
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error = TransactionError::InstructionError(
|
||||||
|
10,
|
||||||
|
InstructionError::ExecutableAccountNotRentExempt,
|
||||||
|
);
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error =
|
||||||
|
TransactionError::InstructionError(10, InstructionError::ExecutableDataModified);
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error =
|
||||||
|
TransactionError::InstructionError(10, InstructionError::ExecutableLamportChange);
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error =
|
||||||
|
TransactionError::InstructionError(10, InstructionError::ExecutableModified);
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error =
|
||||||
|
TransactionError::InstructionError(10, InstructionError::ExternalAccountDataModified);
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error =
|
||||||
|
TransactionError::InstructionError(10, InstructionError::ExternalAccountLamportSpend);
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error =
|
||||||
|
TransactionError::InstructionError(10, InstructionError::GenericError);
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error = TransactionError::InstructionError(10, InstructionError::Immutable);
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error =
|
||||||
|
TransactionError::InstructionError(10, InstructionError::IncorrectAuthority);
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error =
|
||||||
|
TransactionError::InstructionError(10, InstructionError::IncorrectProgramId);
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error =
|
||||||
|
TransactionError::InstructionError(10, InstructionError::InsufficientFunds);
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error =
|
||||||
|
TransactionError::InstructionError(10, InstructionError::InvalidAccountData);
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error =
|
||||||
|
TransactionError::InstructionError(10, InstructionError::InvalidArgument);
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error =
|
||||||
|
TransactionError::InstructionError(10, InstructionError::InvalidError);
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error =
|
||||||
|
TransactionError::InstructionError(10, InstructionError::InvalidInstructionData);
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error =
|
||||||
|
TransactionError::InstructionError(10, InstructionError::InvalidRealloc);
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error =
|
||||||
|
TransactionError::InstructionError(10, InstructionError::InvalidSeeds);
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error =
|
||||||
|
TransactionError::InstructionError(10, InstructionError::MaxSeedLengthExceeded);
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error =
|
||||||
|
TransactionError::InstructionError(10, InstructionError::MissingAccount);
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error =
|
||||||
|
TransactionError::InstructionError(10, InstructionError::MissingRequiredSignature);
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error =
|
||||||
|
TransactionError::InstructionError(10, InstructionError::ModifiedProgramId);
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error =
|
||||||
|
TransactionError::InstructionError(10, InstructionError::NotEnoughAccountKeys);
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error =
|
||||||
|
TransactionError::InstructionError(10, InstructionError::PrivilegeEscalation);
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error = TransactionError::InstructionError(
|
||||||
|
10,
|
||||||
|
InstructionError::ProgramEnvironmentSetupFailure,
|
||||||
|
);
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error =
|
||||||
|
TransactionError::InstructionError(10, InstructionError::ProgramFailedToCompile);
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error =
|
||||||
|
TransactionError::InstructionError(10, InstructionError::ProgramFailedToComplete);
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error =
|
||||||
|
TransactionError::InstructionError(10, InstructionError::ReadonlyDataModified);
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error =
|
||||||
|
TransactionError::InstructionError(10, InstructionError::ReadonlyLamportChange);
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error =
|
||||||
|
TransactionError::InstructionError(10, InstructionError::ReentrancyNotAllowed);
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error =
|
||||||
|
TransactionError::InstructionError(10, InstructionError::RentEpochModified);
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error =
|
||||||
|
TransactionError::InstructionError(10, InstructionError::UnbalancedInstruction);
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error =
|
||||||
|
TransactionError::InstructionError(10, InstructionError::UninitializedAccount);
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error =
|
||||||
|
TransactionError::InstructionError(10, InstructionError::UnsupportedProgramId);
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let transaction_error =
|
||||||
|
TransactionError::InstructionError(10, InstructionError::Custom(10));
|
||||||
|
let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
|
||||||
|
transaction_error.clone().into();
|
||||||
|
assert_eq!(
|
||||||
|
transaction_error,
|
||||||
|
tx_by_addr_transaction_error.try_into().unwrap()
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
104
storage-proto/src/transaction_by_addr.proto
Normal file
104
storage-proto/src/transaction_by_addr.proto
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package solana.storage.TransactionByAddr;
|
||||||
|
|
||||||
|
message TransactionByAddr {
|
||||||
|
repeated TransactionByAddrInfo tx_by_addrs = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message TransactionByAddrInfo {
|
||||||
|
bytes signature = 1;
|
||||||
|
TransactionError err = 2;
|
||||||
|
uint32 index = 3;
|
||||||
|
Memo memo = 4;
|
||||||
|
UnixTimestamp block_time = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Memo {
|
||||||
|
string memo = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message TransactionError {
|
||||||
|
TransactionErrorType transaction_error = 1;
|
||||||
|
InstructionError instruction_error = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum TransactionErrorType {
|
||||||
|
ACCOUNT_IN_USE = 0;
|
||||||
|
ACCOUNT_LOADED_TWICE = 1;
|
||||||
|
ACCOUNT_NOT_FOUND = 2;
|
||||||
|
PROGRAM_ACCOUNT_NOT_FOUND = 3;
|
||||||
|
INSUFFICIENT_FUNDS_FOR_FEE = 4;
|
||||||
|
INVALID_ACCOUNT_FOR_FEE = 5;
|
||||||
|
DUPLICATE_SIGNATURE = 6;
|
||||||
|
BLOCKHASH_NOT_FOUND = 7;
|
||||||
|
INSTRUCTION_ERROR = 8;
|
||||||
|
CALL_CHAIN_TOO_DEEP = 9;
|
||||||
|
MISSING_SIGNATURE_FOR_FEE = 10;
|
||||||
|
INVALID_ACCOUNT_INDEX = 11;
|
||||||
|
SIGNATURE_FAILURE = 12;
|
||||||
|
INVALID_PROGRAM_FOR_EXECUTION = 13;
|
||||||
|
SANITIZE_FAILURE = 14;
|
||||||
|
CLUSTER_MAINTENANCE = 15;
|
||||||
|
}
|
||||||
|
|
||||||
|
message InstructionError {
|
||||||
|
uint32 index = 1;
|
||||||
|
InstructionErrorType error = 2;
|
||||||
|
CustomError custom = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum InstructionErrorType {
|
||||||
|
GENERIC_ERROR = 0;
|
||||||
|
INVALID_ARGUMENT = 1;
|
||||||
|
INVALID_INSTRUCTION_DATA = 2;
|
||||||
|
INVALID_ACCOUNT_DATA = 3;
|
||||||
|
ACCOUNT_DATA_TOO_SMALL = 4;
|
||||||
|
INSUFFICIENT_FUNDS = 5;
|
||||||
|
INCORRECT_PROGRAM_ID = 6;
|
||||||
|
MISSING_REQUIRED_SIGNATURE = 7;
|
||||||
|
ACCOUNT_ALREADY_INITIALIZED = 8;
|
||||||
|
UNINITIALIZED_ACCOUNT = 9;
|
||||||
|
UNBALANCED_INSTRUCTION = 10;
|
||||||
|
MODIFIED_PROGRAM_ID = 11;
|
||||||
|
EXTERNAL_ACCOUNT_LAMPORT_SPEND = 12;
|
||||||
|
EXTERNAL_ACCOUNT_DATA_MODIFIED = 13;
|
||||||
|
READONLY_LAMPORT_CHANGE = 14;
|
||||||
|
READONLY_DATA_MODIFIED = 15;
|
||||||
|
DUPLICATE_ACCOUNT_INDEX = 16;
|
||||||
|
EXECUTABLE_MODIFIED = 17;
|
||||||
|
RENT_EPOCH_MODIFIED = 18;
|
||||||
|
NOT_ENOUGH_ACCOUNT_KEYS = 19;
|
||||||
|
ACCOUNT_DATA_SIZE_CHANGED = 20;
|
||||||
|
ACCOUNT_NOT_EXECUTABLE = 21;
|
||||||
|
ACCOUNT_BORROW_FAILED = 22;
|
||||||
|
ACCOUNT_BORROW_OUTSTANDING = 23;
|
||||||
|
DUPLICATE_ACCOUNT_OUT_OF_SYNC = 24;
|
||||||
|
CUSTOM = 25;
|
||||||
|
INVALID_ERROR = 26;
|
||||||
|
EXECUTABLE_DATA_MODIFIED = 27;
|
||||||
|
EXECUTABLE_LAMPORT_CHANGE = 28;
|
||||||
|
EXECUTABLE_ACCOUNT_NOT_RENT_EXEMPT = 29;
|
||||||
|
UNSUPPORTED_PROGRAM_ID = 30;
|
||||||
|
CALL_DEPTH = 31;
|
||||||
|
MISSING_ACCOUNT = 32;
|
||||||
|
REENTRANCY_NOT_ALLOWED = 33;
|
||||||
|
MAX_SEED_LENGTH_EXCEEDED = 34;
|
||||||
|
INVALID_SEEDS = 35;
|
||||||
|
INVALID_REALLOC = 36;
|
||||||
|
COMPUTATIONAL_BUDGET_EXCEEDED = 37;
|
||||||
|
PRIVILEGE_ESCALATION = 38;
|
||||||
|
PROGRAM_ENVIRONMENT_SETUP_FAILURE = 39;
|
||||||
|
PROGRAM_FAILED_TO_COMPLETE = 40;
|
||||||
|
PROGRAM_FAILED_TO_COMPILE = 41;
|
||||||
|
IMMUTABLE = 42;
|
||||||
|
INCORRECT_AUTHORITY = 43;
|
||||||
|
}
|
||||||
|
|
||||||
|
message UnixTimestamp {
|
||||||
|
int64 timestamp = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CustomError {
|
||||||
|
uint32 custom = 1;
|
||||||
|
}
|
@ -324,6 +324,7 @@ pub struct ConfirmedTransactionStatusWithSignature {
|
|||||||
pub slot: Slot,
|
pub slot: Slot,
|
||||||
pub err: Option<TransactionError>,
|
pub err: Option<TransactionError>,
|
||||||
pub memo: Option<String>,
|
pub memo: Option<String>,
|
||||||
|
pub block_time: Option<UnixTimestamp>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
@ -382,6 +383,7 @@ pub struct ConfirmedTransaction {
|
|||||||
pub slot: Slot,
|
pub slot: Slot,
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub transaction: TransactionWithStatusMeta,
|
pub transaction: TransactionWithStatusMeta,
|
||||||
|
pub block_time: Option<UnixTimestamp>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ConfirmedTransaction {
|
impl ConfirmedTransaction {
|
||||||
@ -389,6 +391,7 @@ impl ConfirmedTransaction {
|
|||||||
EncodedConfirmedTransaction {
|
EncodedConfirmedTransaction {
|
||||||
slot: self.slot,
|
slot: self.slot,
|
||||||
transaction: self.transaction.encode(encoding),
|
transaction: self.transaction.encode(encoding),
|
||||||
|
block_time: self.block_time,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -399,6 +402,7 @@ pub struct EncodedConfirmedTransaction {
|
|||||||
pub slot: Slot,
|
pub slot: Slot,
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub transaction: EncodedTransactionWithStatusMeta,
|
pub transaction: EncodedTransactionWithStatusMeta,
|
||||||
|
pub block_time: Option<UnixTimestamp>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A duplicate representation of a Transaction for pretty JSON serialization
|
/// A duplicate representation of a Transaction for pretty JSON serialization
|
||||||
@ -575,6 +579,17 @@ impl EncodedTransaction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A serialized `Vec<TransactionByAddrInfo>` is stored in the `tx-by-addr` table. The row keys are
|
||||||
|
// the one's compliment of the slot so that rows may be listed in reverse order
|
||||||
|
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub struct TransactionByAddrInfo {
|
||||||
|
pub signature: Signature, // The transaction signature
|
||||||
|
pub err: Option<TransactionError>, // None if the transaction executed successfully
|
||||||
|
pub index: u32, // Where the transaction is located in the block
|
||||||
|
pub memo: Option<String>, // Transaction memo
|
||||||
|
pub block_time: Option<UnixTimestamp>,
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
Reference in New Issue
Block a user