Cleanup unsupported sysvars (#16390)
* Cleanup unsupported sysvars * fix ser description
This commit is contained in:
parent
03d3ae1cb9
commit
92f4018b07
|
@ -7,11 +7,12 @@ use solana_program::{
|
||||||
entrypoint,
|
entrypoint,
|
||||||
entrypoint::ProgramResult,
|
entrypoint::ProgramResult,
|
||||||
msg,
|
msg,
|
||||||
|
program_error::ProgramError,
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
rent,
|
rent,
|
||||||
sysvar::{
|
sysvar::{
|
||||||
self, clock::Clock, fees::Fees, rent::Rent, slot_hashes::SlotHashes,
|
self, clock::Clock, fees::Fees, instructions, rent::Rent, slot_hashes::SlotHashes,
|
||||||
stake_history::StakeHistory, Sysvar,
|
slot_history::SlotHistory, stake_history::StakeHistory, Sysvar,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -25,37 +26,54 @@ fn process_instruction(
|
||||||
// Clock
|
// Clock
|
||||||
msg!("Clock identifier:");
|
msg!("Clock identifier:");
|
||||||
sysvar::clock::id().log();
|
sysvar::clock::id().log();
|
||||||
let clock = Clock::from_account_info(&accounts[2]).expect("clock");
|
let clock = Clock::from_account_info(&accounts[2]).unwrap();
|
||||||
assert_eq!(clock.slot, DEFAULT_SLOTS_PER_EPOCH + 1);
|
assert_eq!(clock.slot, DEFAULT_SLOTS_PER_EPOCH + 1);
|
||||||
|
|
||||||
// Fees
|
// Fees
|
||||||
msg!("Fees identifier:");
|
msg!("Fees identifier:");
|
||||||
sysvar::fees::id().log();
|
sysvar::fees::id().log();
|
||||||
let fees = Fees::from_account_info(&accounts[3]).expect("fees");
|
let fees = Fees::from_account_info(&accounts[3]).unwrap();
|
||||||
let fee_calculator = fees.fee_calculator;
|
let fee_calculator = fees.fee_calculator;
|
||||||
assert_eq!(fee_calculator.lamports_per_signature, 0);
|
assert_eq!(fee_calculator.lamports_per_signature, 0);
|
||||||
|
|
||||||
|
// Instructions
|
||||||
|
msg!("Instructions identifier:");
|
||||||
|
sysvar::instructions::id().log();
|
||||||
|
let index = instructions::load_current_index(&accounts[4].try_borrow_data()?);
|
||||||
|
assert_eq!(0, index);
|
||||||
|
msg!(
|
||||||
|
"instruction {:?}",
|
||||||
|
instructions::load_instruction_at(index as usize, &accounts[4].try_borrow_data()?)
|
||||||
|
);
|
||||||
|
|
||||||
|
let due = Rent::from_account_info(&accounts[5]).unwrap().due(
|
||||||
|
rent::DEFAULT_LAMPORTS_PER_BYTE_YEAR * rent::DEFAULT_EXEMPTION_THRESHOLD as u64,
|
||||||
|
1,
|
||||||
|
1.0,
|
||||||
|
);
|
||||||
|
assert_eq!(due, (0, true));
|
||||||
|
|
||||||
// Slot Hashes
|
// Slot Hashes
|
||||||
msg!("SlotHashes identifier:");
|
msg!("SlotHashes identifier:");
|
||||||
sysvar::slot_hashes::id().log();
|
sysvar::slot_hashes::id().log();
|
||||||
let slot_hashes = SlotHashes::from_account_info(&accounts[4]).expect("slot_hashes");
|
assert_eq!(
|
||||||
assert!(slot_hashes.len() >= 1);
|
Err(ProgramError::UnsupportedSysvar),
|
||||||
|
SlotHashes::from_account_info(&accounts[6])
|
||||||
|
);
|
||||||
|
|
||||||
|
// Slot History
|
||||||
|
msg!("SlotHistory identifier:");
|
||||||
|
sysvar::slot_history::id().log();
|
||||||
|
assert_eq!(
|
||||||
|
Err(ProgramError::UnsupportedSysvar),
|
||||||
|
SlotHistory::from_account_info(&accounts[7])
|
||||||
|
);
|
||||||
|
|
||||||
// Stake History
|
// Stake History
|
||||||
msg!("StakeHistory identifier:");
|
msg!("StakeHistory identifier:");
|
||||||
sysvar::stake_history::id().log();
|
sysvar::stake_history::id().log();
|
||||||
let stake_history = StakeHistory::from_account_info(&accounts[5]).expect("stake_history");
|
let stake_history = StakeHistory::from_account_info(&accounts[8]).unwrap();
|
||||||
assert!(stake_history.len() >= 1);
|
assert!(stake_history.len() >= 1);
|
||||||
|
|
||||||
let rent = Rent::from_account_info(&accounts[6]).unwrap();
|
|
||||||
assert_eq!(
|
|
||||||
rent.due(
|
|
||||||
rent::DEFAULT_LAMPORTS_PER_BYTE_YEAR * rent::DEFAULT_EXEMPTION_THRESHOLD as u64,
|
|
||||||
1,
|
|
||||||
1.0
|
|
||||||
),
|
|
||||||
(0, true)
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ use solana_sdk::{
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
signature::{keypair_from_seed, Keypair, Signer},
|
signature::{keypair_from_seed, Keypair, Signer},
|
||||||
system_instruction,
|
system_instruction,
|
||||||
sysvar::{clock, fees, rent, slot_hashes, stake_history},
|
sysvar::{clock, fees, rent, slot_hashes, slot_history, stake_history, instructions},
|
||||||
transaction::{Transaction, TransactionError},
|
transaction::{Transaction, TransactionError},
|
||||||
};
|
};
|
||||||
use solana_transaction_status::{
|
use solana_transaction_status::{
|
||||||
|
@ -465,11 +465,14 @@ fn test_program_bpf_sanity() {
|
||||||
let account_metas = vec![
|
let account_metas = vec![
|
||||||
AccountMeta::new(mint_keypair.pubkey(), true),
|
AccountMeta::new(mint_keypair.pubkey(), true),
|
||||||
AccountMeta::new(Keypair::new().pubkey(), false),
|
AccountMeta::new(Keypair::new().pubkey(), false),
|
||||||
AccountMeta::new(clock::id(), false),
|
AccountMeta::new_readonly(clock::id(), false),
|
||||||
AccountMeta::new(fees::id(), false),
|
AccountMeta::new_readonly(fees::id(), false),
|
||||||
AccountMeta::new(slot_hashes::id(), false),
|
AccountMeta::new_readonly(instructions::id(), false),
|
||||||
AccountMeta::new(stake_history::id(), false),
|
AccountMeta::new_readonly(rent::id(), false),
|
||||||
AccountMeta::new(rent::id(), false),
|
AccountMeta::new_readonly(slot_hashes::id(), false),
|
||||||
|
AccountMeta::new_readonly(slot_history::id(), false),
|
||||||
|
AccountMeta::new_readonly(stake_history::id(), false),
|
||||||
|
|
||||||
];
|
];
|
||||||
let instruction = Instruction::new_with_bytes(program_id, &[1], account_metas);
|
let instruction = Instruction::new_with_bytes(program_id, &[1], account_metas);
|
||||||
let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
|
let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
|
||||||
|
|
|
@ -114,7 +114,7 @@ impl ExecuteTimings {
|
||||||
}
|
}
|
||||||
|
|
||||||
type BankStatusCache = StatusCache<Signature, Result<()>>;
|
type BankStatusCache = StatusCache<Signature, Result<()>>;
|
||||||
#[frozen_abi(digest = "EcB9J7sm37t1R47vLcvGuNeiRciB4Efq1EDWDWL6Bp5h")]
|
#[frozen_abi(digest = "4mSWwHd4RrLjCXH7RFrm6K3wZSsi9DfVJK3Ngz9jKk7D")]
|
||||||
pub type BankSlotDelta = SlotDelta<Result<()>>;
|
pub type BankSlotDelta = SlotDelta<Result<()>>;
|
||||||
type TransactionAccountRefCells = Vec<Rc<RefCell<AccountSharedData>>>;
|
type TransactionAccountRefCells = Vec<Rc<RefCell<AccountSharedData>>>;
|
||||||
type TransactionAccountDepRefCells = Vec<(Pubkey, Rc<RefCell<AccountSharedData>>)>;
|
type TransactionAccountDepRefCells = Vec<(Pubkey, Rc<RefCell<AccountSharedData>>)>;
|
||||||
|
|
|
@ -24,6 +24,7 @@ use solana_sdk::{
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
rent::Rent,
|
rent::Rent,
|
||||||
system_program,
|
system_program,
|
||||||
|
sysvar::instructions,
|
||||||
transaction::TransactionError,
|
transaction::TransactionError,
|
||||||
};
|
};
|
||||||
use std::{
|
use std::{
|
||||||
|
@ -1049,9 +1050,9 @@ impl MessageProcessor {
|
||||||
// before the account pre-values are taken care of
|
// before the account pre-values are taken care of
|
||||||
if feature_set.is_active(&instructions_sysvar_enabled::id()) {
|
if feature_set.is_active(&instructions_sysvar_enabled::id()) {
|
||||||
for (i, key) in message.account_keys.iter().enumerate() {
|
for (i, key) in message.account_keys.iter().enumerate() {
|
||||||
if solana_sdk::sysvar::instructions::check_id(key) {
|
if instructions::check_id(key) {
|
||||||
let mut mut_account_ref = accounts[i].borrow_mut();
|
let mut mut_account_ref = accounts[i].borrow_mut();
|
||||||
solana_sdk::sysvar::instructions::store_current_index(
|
instructions::store_current_index(
|
||||||
mut_account_ref.data_as_mut_slice(),
|
mut_account_ref.data_as_mut_slice(),
|
||||||
instruction_index as u16,
|
instruction_index as u16,
|
||||||
);
|
);
|
||||||
|
|
|
@ -211,6 +211,10 @@ pub enum InstructionError {
|
||||||
/// Program arithmetic overflowed
|
/// Program arithmetic overflowed
|
||||||
#[error("Program arithmetic overflowed")]
|
#[error("Program arithmetic overflowed")]
|
||||||
ArithmeticOverflow,
|
ArithmeticOverflow,
|
||||||
|
|
||||||
|
/// Unsupported sysvar
|
||||||
|
#[error("Unsupported sysvar")]
|
||||||
|
UnsupportedSysvar,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
|
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
|
||||||
|
|
|
@ -384,15 +384,15 @@ impl Message {
|
||||||
// [0..2 - num_instructions
|
// [0..2 - num_instructions
|
||||||
//
|
//
|
||||||
// Then a table of offsets of where to find them in the data
|
// Then a table of offsets of where to find them in the data
|
||||||
// 3..2*num_instructions table of instruction offsets
|
// 3..2 * num_instructions table of instruction offsets
|
||||||
//
|
//
|
||||||
// Each instruction is then encoded as:
|
// Each instruction is then encoded as:
|
||||||
// 0..2 - num_accounts
|
// 0..2 - num_accounts
|
||||||
// 3 - meta_byte -> (bit 0 signer, bit 1 is_writable)
|
// 2 - meta_byte -> (bit 0 signer, bit 1 is_writable)
|
||||||
// 4..36 - pubkey - 32 bytes
|
// 3..35 - pubkey - 32 bytes
|
||||||
// 36..64 - program_id
|
// 35..67 - program_id
|
||||||
// 33..34 - data len - u16
|
// 67..69 - data len - u16
|
||||||
// 35..data_len - data
|
// 69..data_len - data
|
||||||
pub fn serialize_instructions(&self, demote_sysvar_write_locks: bool) -> Vec<u8> {
|
pub fn serialize_instructions(&self, demote_sysvar_write_locks: bool) -> Vec<u8> {
|
||||||
// 64 bytes is a reasonable guess, calculating exactly is slower in benchmarks
|
// 64 bytes is a reasonable guess, calculating exactly is slower in benchmarks
|
||||||
let mut data = Vec::with_capacity(self.instructions.len() * (32 * 2));
|
let mut data = Vec::with_capacity(self.instructions.len() * (32 * 2));
|
||||||
|
|
|
@ -43,6 +43,8 @@ pub enum ProgramError {
|
||||||
BorshIoError(String),
|
BorshIoError(String),
|
||||||
#[error("An account does not have enough lamports to be rent-exempt")]
|
#[error("An account does not have enough lamports to be rent-exempt")]
|
||||||
AccountNotRentExempt,
|
AccountNotRentExempt,
|
||||||
|
#[error("Unsupported sysvar")]
|
||||||
|
UnsupportedSysvar,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait PrintProgramError {
|
pub trait PrintProgramError {
|
||||||
|
@ -79,6 +81,7 @@ impl PrintProgramError for ProgramError {
|
||||||
Self::InvalidSeeds => msg!("Error: InvalidSeeds"),
|
Self::InvalidSeeds => msg!("Error: InvalidSeeds"),
|
||||||
Self::BorshIoError(_) => msg!("Error: BorshIoError"),
|
Self::BorshIoError(_) => msg!("Error: BorshIoError"),
|
||||||
Self::AccountNotRentExempt => msg!("Error: AccountNotRentExempt"),
|
Self::AccountNotRentExempt => msg!("Error: AccountNotRentExempt"),
|
||||||
|
Self::UnsupportedSysvar => msg!("Error: UnsupportedSysvar"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -107,6 +110,7 @@ pub const MAX_SEED_LENGTH_EXCEEDED: u64 = to_builtin!(13);
|
||||||
pub const INVALID_SEEDS: u64 = to_builtin!(14);
|
pub const INVALID_SEEDS: u64 = to_builtin!(14);
|
||||||
pub const BORSH_IO_ERROR: u64 = to_builtin!(15);
|
pub const BORSH_IO_ERROR: u64 = to_builtin!(15);
|
||||||
pub const ACCOUNT_NOT_RENT_EXEMPT: u64 = to_builtin!(16);
|
pub const ACCOUNT_NOT_RENT_EXEMPT: u64 = to_builtin!(16);
|
||||||
|
pub const UNSUPPORTED_SYSVAR: u64 = to_builtin!(17);
|
||||||
|
|
||||||
impl From<ProgramError> for u64 {
|
impl From<ProgramError> for u64 {
|
||||||
fn from(error: ProgramError) -> Self {
|
fn from(error: ProgramError) -> Self {
|
||||||
|
@ -126,6 +130,7 @@ impl From<ProgramError> for u64 {
|
||||||
ProgramError::InvalidSeeds => INVALID_SEEDS,
|
ProgramError::InvalidSeeds => INVALID_SEEDS,
|
||||||
ProgramError::BorshIoError(_) => BORSH_IO_ERROR,
|
ProgramError::BorshIoError(_) => BORSH_IO_ERROR,
|
||||||
ProgramError::AccountNotRentExempt => ACCOUNT_NOT_RENT_EXEMPT,
|
ProgramError::AccountNotRentExempt => ACCOUNT_NOT_RENT_EXEMPT,
|
||||||
|
ProgramError::UnsupportedSysvar => UNSUPPORTED_SYSVAR,
|
||||||
|
|
||||||
ProgramError::Custom(error) => {
|
ProgramError::Custom(error) => {
|
||||||
if error == 0 {
|
if error == 0 {
|
||||||
|
@ -154,6 +159,7 @@ impl From<u64> for ProgramError {
|
||||||
ACCOUNT_BORROW_FAILED => ProgramError::AccountBorrowFailed,
|
ACCOUNT_BORROW_FAILED => ProgramError::AccountBorrowFailed,
|
||||||
MAX_SEED_LENGTH_EXCEEDED => ProgramError::MaxSeedLengthExceeded,
|
MAX_SEED_LENGTH_EXCEEDED => ProgramError::MaxSeedLengthExceeded,
|
||||||
INVALID_SEEDS => ProgramError::InvalidSeeds,
|
INVALID_SEEDS => ProgramError::InvalidSeeds,
|
||||||
|
UNSUPPORTED_SYSVAR => ProgramError::UnsupportedSysvar,
|
||||||
CUSTOM_ZERO => ProgramError::Custom(0),
|
CUSTOM_ZERO => ProgramError::Custom(0),
|
||||||
_ => ProgramError::Custom(error as u32),
|
_ => ProgramError::Custom(error as u32),
|
||||||
}
|
}
|
||||||
|
@ -180,6 +186,7 @@ impl TryFrom<InstructionError> for ProgramError {
|
||||||
Self::Error::MaxSeedLengthExceeded => Ok(Self::MaxSeedLengthExceeded),
|
Self::Error::MaxSeedLengthExceeded => Ok(Self::MaxSeedLengthExceeded),
|
||||||
Self::Error::BorshIoError(err) => Ok(Self::BorshIoError(err)),
|
Self::Error::BorshIoError(err) => Ok(Self::BorshIoError(err)),
|
||||||
Self::Error::AccountNotRentExempt => Ok(Self::AccountNotRentExempt),
|
Self::Error::AccountNotRentExempt => Ok(Self::AccountNotRentExempt),
|
||||||
|
Self::Error::UnsupportedSysvar => Ok(Self::UnsupportedSysvar),
|
||||||
_ => Err(error),
|
_ => Err(error),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -206,6 +213,7 @@ where
|
||||||
ACCOUNT_BORROW_FAILED => InstructionError::AccountBorrowFailed,
|
ACCOUNT_BORROW_FAILED => InstructionError::AccountBorrowFailed,
|
||||||
MAX_SEED_LENGTH_EXCEEDED => InstructionError::MaxSeedLengthExceeded,
|
MAX_SEED_LENGTH_EXCEEDED => InstructionError::MaxSeedLengthExceeded,
|
||||||
INVALID_SEEDS => InstructionError::InvalidSeeds,
|
INVALID_SEEDS => InstructionError::InvalidSeeds,
|
||||||
|
UNSUPPORTED_SYSVAR => InstructionError::UnsupportedSysvar,
|
||||||
_ => {
|
_ => {
|
||||||
// A valid custom error has no bits set in the upper 32
|
// A valid custom error has no bits set in the upper 32
|
||||||
if error >> BUILTIN_BIT_SHIFT == 0 {
|
if error >> BUILTIN_BIT_SHIFT == 0 {
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
#![allow(clippy::integer_arithmetic)]
|
#![allow(clippy::integer_arithmetic)]
|
||||||
//! This account contains the serialized transaction instructions
|
//! This account contains the serialized transaction instructions
|
||||||
|
|
||||||
use crate::{instruction::Instruction, sanitize::SanitizeError, sysvar::Sysvar};
|
use crate::{instruction::Instruction, sanitize::SanitizeError};
|
||||||
|
|
||||||
pub type Instructions = Vec<Instruction>;
|
// Instructions Sysvar, dummy type, use the associated helpers instead of the Sysvar trait
|
||||||
|
pub struct Instructions();
|
||||||
|
|
||||||
crate::declare_sysvar_id!("Sysvar1nstructions1111111111111111111111111", Instructions);
|
crate::declare_sysvar_id!("Sysvar1nstructions1111111111111111111111111", Instructions);
|
||||||
|
|
||||||
impl Sysvar for Instructions {}
|
/// Load the current instruction's index from the Instructions Sysvar data
|
||||||
|
|
||||||
pub fn load_current_index(data: &[u8]) -> u16 {
|
pub fn load_current_index(data: &[u8]) -> u16 {
|
||||||
let mut instr_fixed_data = [0u8; 2];
|
let mut instr_fixed_data = [0u8; 2];
|
||||||
let len = data.len();
|
let len = data.len();
|
||||||
|
@ -16,11 +16,13 @@ pub fn load_current_index(data: &[u8]) -> u16 {
|
||||||
u16::from_le_bytes(instr_fixed_data)
|
u16::from_le_bytes(instr_fixed_data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Store the current instruction's index in the Instructions Sysvar data
|
||||||
pub fn store_current_index(data: &mut [u8], instruction_index: u16) {
|
pub fn store_current_index(data: &mut [u8], instruction_index: u16) {
|
||||||
let last_index = data.len() - 2;
|
let last_index = data.len() - 2;
|
||||||
data[last_index..last_index + 2].copy_from_slice(&instruction_index.to_le_bytes());
|
data[last_index..last_index + 2].copy_from_slice(&instruction_index.to_le_bytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Load an instruction at the specified index
|
||||||
pub fn load_instruction_at(index: usize, data: &[u8]) -> Result<Instruction, SanitizeError> {
|
pub fn load_instruction_at(index: usize, data: &[u8]) -> Result<Instruction, SanitizeError> {
|
||||||
crate::message::Message::deserialize_instruction(index, data)
|
crate::message::Message::deserialize_instruction(index, data)
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
//!
|
//!
|
||||||
pub use crate::slot_hashes::SlotHashes;
|
pub use crate::slot_hashes::SlotHashes;
|
||||||
|
|
||||||
use crate::sysvar::Sysvar;
|
use crate::{account_info::AccountInfo, program_error::ProgramError, sysvar::Sysvar};
|
||||||
|
|
||||||
crate::declare_sysvar_id!("SysvarS1otHashes111111111111111111111111111", SlotHashes);
|
crate::declare_sysvar_id!("SysvarS1otHashes111111111111111111111111111", SlotHashes);
|
||||||
|
|
||||||
|
@ -14,6 +14,10 @@ impl Sysvar for SlotHashes {
|
||||||
// hard-coded so that we don't have to construct an empty
|
// hard-coded so that we don't have to construct an empty
|
||||||
20_488 // golden, update if MAX_ENTRIES changes
|
20_488 // golden, update if MAX_ENTRIES changes
|
||||||
}
|
}
|
||||||
|
fn from_account_info(_account_info: &AccountInfo) -> Result<Self, ProgramError> {
|
||||||
|
// This sysvar is too large to bincode::deserialize in-program
|
||||||
|
Err(ProgramError::UnsupportedSysvar)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
//! named accounts for synthesized data accounts for bank state, etc.
|
//! named accounts for synthesized data accounts for bank state, etc.
|
||||||
//!
|
//!
|
||||||
//! this account carries a bitvector of slots present over the past
|
//! this account carries a bitvector of slots present over the past
|
||||||
//! epoch
|
//! epoch
|
||||||
//!
|
//!
|
||||||
pub use crate::slot_history::SlotHistory;
|
pub use crate::{
|
||||||
|
account_info::AccountInfo, program_error::ProgramError, slot_history::SlotHistory,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::sysvar::Sysvar;
|
use crate::sysvar::Sysvar;
|
||||||
|
|
||||||
|
@ -15,6 +17,10 @@ impl Sysvar for SlotHistory {
|
||||||
// hard-coded so that we don't have to construct an empty
|
// hard-coded so that we don't have to construct an empty
|
||||||
131_097 // golden, update if MAX_ENTRIES changes
|
131_097 // golden, update if MAX_ENTRIES changes
|
||||||
}
|
}
|
||||||
|
fn from_account_info(_account_info: &AccountInfo) -> Result<Self, ProgramError> {
|
||||||
|
// This sysvar is too large to bincode::deserialize in-program
|
||||||
|
Err(ProgramError::UnsupportedSysvar)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -118,4 +118,5 @@ pub enum InstructionErrorType {
|
||||||
AccountNotRentExempt = 45,
|
AccountNotRentExempt = 45,
|
||||||
InvalidAccountOwner = 46,
|
InvalidAccountOwner = 46,
|
||||||
ArithmeticOverflow = 47,
|
ArithmeticOverflow = 47,
|
||||||
|
UnsupportedSysvar = 48,
|
||||||
}
|
}
|
||||||
|
|
|
@ -510,6 +510,7 @@ impl TryFrom<tx_by_addr::TransactionError> for TransactionError {
|
||||||
45 => InstructionError::AccountNotRentExempt,
|
45 => InstructionError::AccountNotRentExempt,
|
||||||
46 => InstructionError::InvalidAccountOwner,
|
46 => InstructionError::InvalidAccountOwner,
|
||||||
47 => InstructionError::ArithmeticOverflow,
|
47 => InstructionError::ArithmeticOverflow,
|
||||||
|
48 => InstructionError::UnsupportedSysvar,
|
||||||
_ => return Err("Invalid InstructionError"),
|
_ => return Err("Invalid InstructionError"),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -739,6 +740,9 @@ impl From<TransactionError> for tx_by_addr::TransactionError {
|
||||||
InstructionError::ArithmeticOverflow => {
|
InstructionError::ArithmeticOverflow => {
|
||||||
tx_by_addr::InstructionErrorType::ArithmeticOverflow
|
tx_by_addr::InstructionErrorType::ArithmeticOverflow
|
||||||
}
|
}
|
||||||
|
InstructionError::UnsupportedSysvar => {
|
||||||
|
tx_by_addr::InstructionErrorType::UnsupportedSysvar
|
||||||
|
}
|
||||||
} as i32,
|
} as i32,
|
||||||
custom: match instruction_error {
|
custom: match instruction_error {
|
||||||
InstructionError::Custom(custom) => {
|
InstructionError::Custom(custom) => {
|
||||||
|
|
Loading…
Reference in New Issue