@ -538,7 +538,7 @@ impl CliConfig<'_> {
|
|||||||
if !self.signers.is_empty() {
|
if !self.signers.is_empty() {
|
||||||
self.signers[0].try_pubkey()
|
self.signers[0].try_pubkey()
|
||||||
} else {
|
} else {
|
||||||
Err(SignerError::CustomError(
|
Err(SignerError::Custom(
|
||||||
"Default keypair must be set if pubkey arg not provided".to_string(),
|
"Default keypair must be set if pubkey arg not provided".to_string(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@ -2183,7 +2183,7 @@ where
|
|||||||
Err(err) => {
|
Err(err) => {
|
||||||
if let ClientErrorKind::TransactionError(TransactionError::InstructionError(
|
if let ClientErrorKind::TransactionError(TransactionError::InstructionError(
|
||||||
_,
|
_,
|
||||||
InstructionError::CustomError(code),
|
InstructionError::Custom(code),
|
||||||
)) = err.kind()
|
)) = err.kind()
|
||||||
{
|
{
|
||||||
if let Some(specific_error) = E::decode_custom_error_to_enum(*code) {
|
if let Some(specific_error) = E::decode_custom_error_to_enum(*code) {
|
||||||
|
@ -1989,14 +1989,14 @@ mod tests {
|
|||||||
meta.err,
|
meta.err,
|
||||||
Some(TransactionError::InstructionError(
|
Some(TransactionError::InstructionError(
|
||||||
0,
|
0,
|
||||||
InstructionError::CustomError(1)
|
InstructionError::Custom(1)
|
||||||
))
|
))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
meta.status,
|
meta.status,
|
||||||
Err(TransactionError::InstructionError(
|
Err(TransactionError::InstructionError(
|
||||||
0,
|
0,
|
||||||
InstructionError::CustomError(1)
|
InstructionError::Custom(1)
|
||||||
))
|
))
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
@ -2024,14 +2024,14 @@ pub(crate) mod tests {
|
|||||||
meta.err,
|
meta.err,
|
||||||
Some(TransactionError::InstructionError(
|
Some(TransactionError::InstructionError(
|
||||||
0,
|
0,
|
||||||
InstructionError::CustomError(1)
|
InstructionError::Custom(1)
|
||||||
))
|
))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
meta.status,
|
meta.status,
|
||||||
Err(TransactionError::InstructionError(
|
Err(TransactionError::InstructionError(
|
||||||
0,
|
0,
|
||||||
InstructionError::CustomError(1)
|
InstructionError::Custom(1)
|
||||||
))
|
))
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
@ -2074,7 +2074,7 @@ pub mod tests {
|
|||||||
);
|
);
|
||||||
let res = io.handle_request_sync(&req, meta);
|
let res = io.handle_request_sync(&req, meta);
|
||||||
let expected_res: Option<transaction::Result<()>> = Some(Err(
|
let expected_res: Option<transaction::Result<()>> = Some(Err(
|
||||||
TransactionError::InstructionError(0, InstructionError::CustomError(1)),
|
TransactionError::InstructionError(0, InstructionError::Custom(1)),
|
||||||
));
|
));
|
||||||
let expected = json!({
|
let expected = json!({
|
||||||
"jsonrpc": "2.0",
|
"jsonrpc": "2.0",
|
||||||
@ -2135,7 +2135,7 @@ pub mod tests {
|
|||||||
let res = io.handle_request_sync(&req, meta.clone());
|
let res = io.handle_request_sync(&req, meta.clone());
|
||||||
let expected_res: transaction::Result<()> = Err(TransactionError::InstructionError(
|
let expected_res: transaction::Result<()> = Err(TransactionError::InstructionError(
|
||||||
0,
|
0,
|
||||||
InstructionError::CustomError(1),
|
InstructionError::Custom(1),
|
||||||
));
|
));
|
||||||
let json: Value = serde_json::from_str(&res.unwrap()).unwrap();
|
let json: Value = serde_json::from_str(&res.unwrap()).unwrap();
|
||||||
let result: Option<TransactionStatus> =
|
let result: Option<TransactionStatus> =
|
||||||
@ -2614,14 +2614,14 @@ pub mod tests {
|
|||||||
meta.err,
|
meta.err,
|
||||||
Some(TransactionError::InstructionError(
|
Some(TransactionError::InstructionError(
|
||||||
0,
|
0,
|
||||||
InstructionError::CustomError(1)
|
InstructionError::Custom(1)
|
||||||
))
|
))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
meta.status,
|
meta.status,
|
||||||
Err(TransactionError::InstructionError(
|
Err(TransactionError::InstructionError(
|
||||||
0,
|
0,
|
||||||
InstructionError::CustomError(1)
|
InstructionError::Custom(1)
|
||||||
))
|
))
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
@ -2658,14 +2658,14 @@ pub mod tests {
|
|||||||
meta.err,
|
meta.err,
|
||||||
Some(TransactionError::InstructionError(
|
Some(TransactionError::InstructionError(
|
||||||
0,
|
0,
|
||||||
InstructionError::CustomError(1)
|
InstructionError::Custom(1)
|
||||||
))
|
))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
meta.status,
|
meta.status,
|
||||||
Err(TransactionError::InstructionError(
|
Err(TransactionError::InstructionError(
|
||||||
0,
|
0,
|
||||||
InstructionError::CustomError(1)
|
InstructionError::Custom(1)
|
||||||
))
|
))
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
@ -25,7 +25,7 @@ pub enum MyError {
|
|||||||
}
|
}
|
||||||
impl From<MyError> for ProgramError {
|
impl From<MyError> for ProgramError {
|
||||||
fn from(e: MyError) -> Self {
|
fn from(e: MyError) -> Self {
|
||||||
ProgramError::CustomError(e as u32)
|
ProgramError::Custom(e as u32)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<T> DecodeError<T> for MyError {
|
impl<T> DecodeError<T> for MyError {
|
||||||
|
@ -189,7 +189,7 @@ mod bpf {
|
|||||||
let result = bank_client.send_instruction(&mint_keypair, instruction);
|
let result = bank_client.send_instruction(&mint_keypair, instruction);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
result.unwrap_err().unwrap(),
|
result.unwrap_err().unwrap(),
|
||||||
TransactionError::InstructionError(0, InstructionError::CustomError(42))
|
TransactionError::InstructionError(0, InstructionError::Custom(42))
|
||||||
);
|
);
|
||||||
|
|
||||||
let instruction = Instruction::new(program_id, &4u8, account_metas.clone());
|
let instruction = Instruction::new(program_id, &4u8, account_metas.clone());
|
||||||
@ -398,14 +398,14 @@ mod bpf {
|
|||||||
let result = bank_client.send_instruction(&mint_keypair, instruction);
|
let result = bank_client.send_instruction(&mint_keypair, instruction);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
result.unwrap_err().unwrap(),
|
result.unwrap_err().unwrap(),
|
||||||
TransactionError::InstructionError(0, InstructionError::CustomError(0))
|
TransactionError::InstructionError(0, InstructionError::Custom(0))
|
||||||
);
|
);
|
||||||
|
|
||||||
let instruction = Instruction::new(program_id, &4u8, account_metas.clone());
|
let instruction = Instruction::new(program_id, &4u8, account_metas.clone());
|
||||||
let result = bank_client.send_instruction(&mint_keypair, instruction);
|
let result = bank_client.send_instruction(&mint_keypair, instruction);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
result.unwrap_err().unwrap(),
|
result.unwrap_err().unwrap(),
|
||||||
TransactionError::InstructionError(0, InstructionError::CustomError(42))
|
TransactionError::InstructionError(0, InstructionError::Custom(42))
|
||||||
);
|
);
|
||||||
|
|
||||||
let instruction = Instruction::new(program_id, &6u8, account_metas.clone());
|
let instruction = Instruction::new(program_id, &6u8, account_metas.clone());
|
||||||
|
@ -426,7 +426,7 @@ mod tests {
|
|||||||
.unwrap(),
|
.unwrap(),
|
||||||
TransactionError::InstructionError(
|
TransactionError::InstructionError(
|
||||||
0,
|
0,
|
||||||
InstructionError::CustomError(BudgetError::DestinationMissing as u32)
|
InstructionError::Custom(BudgetError::DestinationMissing as u32)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
assert_eq!(bank_client.get_balance(&alice_pubkey).unwrap(), 1);
|
assert_eq!(bank_client.get_balance(&alice_pubkey).unwrap(), 1);
|
||||||
|
@ -13,5 +13,5 @@ fn process_instruction(
|
|||||||
_keyed_accounts: &[KeyedAccount],
|
_keyed_accounts: &[KeyedAccount],
|
||||||
_data: &[u8],
|
_data: &[u8],
|
||||||
) -> Result<(), InstructionError> {
|
) -> Result<(), InstructionError> {
|
||||||
Err(InstructionError::CustomError(0))
|
Err(InstructionError::Custom(0))
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,6 @@ fn test_program_native_failure() {
|
|||||||
.send_instruction(&alice_keypair, instruction)
|
.send_instruction(&alice_keypair, instruction)
|
||||||
.unwrap_err()
|
.unwrap_err()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
TransactionError::InstructionError(0, InstructionError::CustomError(0))
|
TransactionError::InstructionError(0, InstructionError::Custom(0))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
4
programs/librapay/Cargo.lock
generated
4
programs/librapay/Cargo.lock
generated
@ -2616,7 +2616,6 @@ dependencies = [
|
|||||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"solana-logger 1.0.0",
|
|
||||||
"solana-sdk 1.0.0",
|
"solana-sdk 1.0.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -2745,7 +2744,7 @@ dependencies = [
|
|||||||
"rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"solana-bpf-loader-program 1.0.0",
|
"solana-config-program 1.0.0",
|
||||||
"solana-logger 1.0.0",
|
"solana-logger 1.0.0",
|
||||||
"solana-measure 1.0.0",
|
"solana-measure 1.0.0",
|
||||||
"solana-metrics 1.0.0",
|
"solana-metrics 1.0.0",
|
||||||
@ -2844,7 +2843,6 @@ dependencies = [
|
|||||||
"num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"solana-logger 1.0.0",
|
|
||||||
"solana-metrics 1.0.0",
|
"solana-metrics 1.0.0",
|
||||||
"solana-sdk 1.0.0",
|
"solana-sdk 1.0.0",
|
||||||
"thiserror 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"thiserror 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -38,10 +38,10 @@ pub fn map_failure_error(err: failure::Error) -> InstructionError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn map_err_vm_status(status: VMStatus) -> InstructionError {
|
pub fn map_err_vm_status(status: VMStatus) -> InstructionError {
|
||||||
// Attempt to map the StatusCode (repr(u64)) to a u32 for CustomError.
|
// Attempt to map the StatusCode (repr(u64)) to a u32 for Custom.
|
||||||
// The only defined StatusCode that fails is StatusCode::UNKNOWN_ERROR
|
// The only defined StatusCode that fails is StatusCode::UNKNOWN_ERROR
|
||||||
match <StatusCode as Into<u64>>::into(status.major_status).try_into() {
|
match <StatusCode as Into<u64>>::into(status.major_status).try_into() {
|
||||||
Ok(u) => InstructionError::CustomError(u),
|
Ok(u) => InstructionError::Custom(u),
|
||||||
Err(_) => InstructionError::InvalidError,
|
Err(_) => InstructionError::InvalidError,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -641,7 +641,7 @@ mod tests {
|
|||||||
"main".to_string(),
|
"main".to_string(),
|
||||||
vec![],
|
vec![],
|
||||||
),
|
),
|
||||||
Err(InstructionError::CustomError(4002))
|
Err(InstructionError::Custom(4002))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -760,7 +760,7 @@ mod tests {
|
|||||||
where
|
where
|
||||||
T: 'static + std::error::Error + DecodeError<T> + FromPrimitive,
|
T: 'static + std::error::Error + DecodeError<T> + FromPrimitive,
|
||||||
{
|
{
|
||||||
if let InstructionError::CustomError(code) = err {
|
if let InstructionError::Custom(code) = err {
|
||||||
let specific_error: T = T::decode_custom_error_to_enum(code).unwrap();
|
let specific_error: T = T::decode_custom_error_to_enum(code).unwrap();
|
||||||
format!(
|
format!(
|
||||||
"{:?}: {}::{:?} - {}",
|
"{:?}: {}::{:?} - {}",
|
||||||
@ -774,7 +774,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
"CustomError(0): StakeError::NoCreditsToRedeem - not enough credits to redeem",
|
"Custom(0): StakeError::NoCreditsToRedeem - not enough credits to redeem",
|
||||||
pretty_err::<StakeError>(StakeError::NoCreditsToRedeem.into())
|
pretty_err::<StakeError>(StakeError::NoCreditsToRedeem.into())
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -194,7 +194,7 @@ impl<'a> StorageAccount<'a> {
|
|||||||
|
|
||||||
if segment_index >= current_segment {
|
if segment_index >= current_segment {
|
||||||
// attempt to submit proof for unconfirmed segment
|
// attempt to submit proof for unconfirmed segment
|
||||||
return Err(InstructionError::CustomError(
|
return Err(InstructionError::Custom(
|
||||||
StorageError::InvalidSegment as u32,
|
StorageError::InvalidSegment as u32,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@ -207,7 +207,7 @@ impl<'a> StorageAccount<'a> {
|
|||||||
// TODO check that this blockhash is valid and recent
|
// TODO check that this blockhash is valid and recent
|
||||||
// if !is_valid(&blockhash) {
|
// if !is_valid(&blockhash) {
|
||||||
// // proof isn't using a recent blockhash
|
// // proof isn't using a recent blockhash
|
||||||
// return Err(InstructionError::CustomError(InvalidBlockhash as u32));
|
// return Err(InstructionError::Custom(InvalidBlockhash as u32));
|
||||||
// }
|
// }
|
||||||
|
|
||||||
let proof = Proof {
|
let proof = Proof {
|
||||||
@ -220,13 +220,13 @@ impl<'a> StorageAccount<'a> {
|
|||||||
let segment_proofs = proofs.entry(current_segment).or_default();
|
let segment_proofs = proofs.entry(current_segment).or_default();
|
||||||
if segment_proofs.contains(&proof) {
|
if segment_proofs.contains(&proof) {
|
||||||
// do not accept duplicate proofs
|
// do not accept duplicate proofs
|
||||||
return Err(InstructionError::CustomError(
|
return Err(InstructionError::Custom(
|
||||||
StorageError::DuplicateProof as u32,
|
StorageError::DuplicateProof as u32,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
if segment_proofs.len() >= MAX_PROOFS_PER_SEGMENT {
|
if segment_proofs.len() >= MAX_PROOFS_PER_SEGMENT {
|
||||||
// do not accept more than MAX_PROOFS_PER_SEGMENT
|
// do not accept more than MAX_PROOFS_PER_SEGMENT
|
||||||
return Err(InstructionError::CustomError(
|
return Err(InstructionError::Custom(
|
||||||
StorageError::ProofLimitReached as u32,
|
StorageError::ProofLimitReached as u32,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@ -255,7 +255,7 @@ impl<'a> StorageAccount<'a> {
|
|||||||
{
|
{
|
||||||
debug!("advertise new segment: {} orig: {}", segment, clock.segment);
|
debug!("advertise new segment: {} orig: {}", segment, clock.segment);
|
||||||
if segment < *state_segment || segment > clock.segment {
|
if segment < *state_segment || segment > clock.segment {
|
||||||
return Err(InstructionError::CustomError(
|
return Err(InstructionError::Custom(
|
||||||
StorageError::InvalidSegment as u32,
|
StorageError::InvalidSegment as u32,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@ -290,7 +290,7 @@ impl<'a> StorageAccount<'a> {
|
|||||||
} = &mut storage_contract
|
} = &mut storage_contract
|
||||||
{
|
{
|
||||||
if segment_index > *state_segment {
|
if segment_index > *state_segment {
|
||||||
return Err(InstructionError::CustomError(
|
return Err(InstructionError::Custom(
|
||||||
StorageError::InvalidSegment as u32,
|
StorageError::InvalidSegment as u32,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@ -329,7 +329,7 @@ impl<'a> StorageAccount<'a> {
|
|||||||
|
|
||||||
if accounts.len() != proofs_per_account.len() {
|
if accounts.len() != proofs_per_account.len() {
|
||||||
// don't have all the accounts to validate the proofs_per_account against
|
// don't have all the accounts to validate the proofs_per_account against
|
||||||
return Err(InstructionError::CustomError(
|
return Err(InstructionError::Custom(
|
||||||
StorageError::InvalidProofMask as u32,
|
StorageError::InvalidProofMask as u32,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@ -380,9 +380,7 @@ impl<'a> StorageAccount<'a> {
|
|||||||
} = &mut storage_contract
|
} = &mut storage_contract
|
||||||
{
|
{
|
||||||
if owner.id != *account_owner {
|
if owner.id != *account_owner {
|
||||||
return Err(InstructionError::CustomError(
|
return Err(InstructionError::Custom(StorageError::InvalidOwner as u32));
|
||||||
StorageError::InvalidOwner as u32,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
credits.update_epoch(clock.epoch);
|
credits.update_epoch(clock.epoch);
|
||||||
@ -397,9 +395,7 @@ impl<'a> StorageAccount<'a> {
|
|||||||
} = &mut storage_contract
|
} = &mut storage_contract
|
||||||
{
|
{
|
||||||
if owner.id != *account_owner {
|
if owner.id != *account_owner {
|
||||||
return Err(InstructionError::CustomError(
|
return Err(InstructionError::Custom(StorageError::InvalidOwner as u32));
|
||||||
StorageError::InvalidOwner as u32,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
credits.update_epoch(clock.epoch);
|
credits.update_epoch(clock.epoch);
|
||||||
let (num_validations, _total_proofs) = count_valid_proofs(&validations);
|
let (num_validations, _total_proofs) = count_valid_proofs(&validations);
|
||||||
@ -422,7 +418,7 @@ fn check_redeemable(
|
|||||||
) -> Result<(), InstructionError> {
|
) -> Result<(), InstructionError> {
|
||||||
let rewards = (credits.redeemable as f64 * storage_point_value) as u64;
|
let rewards = (credits.redeemable as f64 * storage_point_value) as u64;
|
||||||
if rewards_pool.lamports()? < rewards {
|
if rewards_pool.lamports()? < rewards {
|
||||||
Err(InstructionError::CustomError(
|
Err(InstructionError::Custom(
|
||||||
StorageError::RewardPoolDepleted as u32,
|
StorageError::RewardPoolDepleted as u32,
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
@ -629,7 +625,7 @@ mod tests {
|
|||||||
keyed_pool_account.account.borrow_mut().lamports = 0;
|
keyed_pool_account.account.borrow_mut().lamports = 0;
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
check_redeemable(&mut credits, 1.0, &keyed_pool_account, &mut owner),
|
check_redeemable(&mut credits, 1.0, &keyed_pool_account, &mut owner),
|
||||||
Err(InstructionError::CustomError(
|
Err(InstructionError::Custom(
|
||||||
StorageError::RewardPoolDepleted as u32,
|
StorageError::RewardPoolDepleted as u32,
|
||||||
))
|
))
|
||||||
);
|
);
|
||||||
|
@ -22,7 +22,7 @@ pub enum VestError {
|
|||||||
|
|
||||||
impl From<VestError> for InstructionError {
|
impl From<VestError> for InstructionError {
|
||||||
fn from(e: VestError) -> Self {
|
fn from(e: VestError) -> Self {
|
||||||
InstructionError::CustomError(e as u32)
|
InstructionError::Custom(e as u32)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -370,7 +370,7 @@ mod tests {
|
|||||||
where
|
where
|
||||||
T: 'static + std::error::Error + DecodeError<T> + FromPrimitive,
|
T: 'static + std::error::Error + DecodeError<T> + FromPrimitive,
|
||||||
{
|
{
|
||||||
if let InstructionError::CustomError(code) = err {
|
if let InstructionError::Custom(code) = err {
|
||||||
let specific_error: T = T::decode_custom_error_to_enum(code).unwrap();
|
let specific_error: T = T::decode_custom_error_to_enum(code).unwrap();
|
||||||
format!(
|
format!(
|
||||||
"{:?}: {}::{:?} - {}",
|
"{:?}: {}::{:?} - {}",
|
||||||
@ -384,7 +384,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
"CustomError(0): VoteError::VoteTooOld - vote already recorded or not in slot hashes history",
|
"Custom(0): VoteError::VoteTooOld - vote already recorded or not in slot hashes history",
|
||||||
pretty_err::<VoteError>(VoteError::VoteTooOld.into())
|
pretty_err::<VoteError>(VoteError::VoteTooOld.into())
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -60,16 +60,16 @@ impl From<hidapi::HidError> for RemoteWalletError {
|
|||||||
impl From<RemoteWalletError> for SignerError {
|
impl From<RemoteWalletError> for SignerError {
|
||||||
fn from(err: RemoteWalletError) -> SignerError {
|
fn from(err: RemoteWalletError) -> SignerError {
|
||||||
match err {
|
match err {
|
||||||
RemoteWalletError::Hid(hid_error) => SignerError::ConnectionError(hid_error),
|
RemoteWalletError::Hid(hid_error) => SignerError::Connection(hid_error),
|
||||||
RemoteWalletError::DeviceTypeMismatch => SignerError::ConnectionError(err.to_string()),
|
RemoteWalletError::DeviceTypeMismatch => SignerError::Connection(err.to_string()),
|
||||||
RemoteWalletError::InvalidDevice => SignerError::ConnectionError(err.to_string()),
|
RemoteWalletError::InvalidDevice => SignerError::Connection(err.to_string()),
|
||||||
RemoteWalletError::InvalidInput(input) => SignerError::InvalidInput(input),
|
RemoteWalletError::InvalidInput(input) => SignerError::InvalidInput(input),
|
||||||
RemoteWalletError::NoDeviceFound => SignerError::NoDeviceFound,
|
RemoteWalletError::NoDeviceFound => SignerError::NoDeviceFound,
|
||||||
RemoteWalletError::Protocol(e) => SignerError::Protocol(e.to_string()),
|
RemoteWalletError::Protocol(e) => SignerError::Protocol(e.to_string()),
|
||||||
RemoteWalletError::UserCancel => {
|
RemoteWalletError::UserCancel => {
|
||||||
SignerError::UserCancel("remote wallet operation rejected by the user".to_string())
|
SignerError::UserCancel("remote wallet operation rejected by the user".to_string())
|
||||||
}
|
}
|
||||||
_ => SignerError::CustomError(err.to_string()),
|
_ => SignerError::Custom(err.to_string()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5004,7 +5004,7 @@ mod tests {
|
|||||||
_ka: &[KeyedAccount],
|
_ka: &[KeyedAccount],
|
||||||
_data: &[u8],
|
_data: &[u8],
|
||||||
) -> std::result::Result<(), InstructionError> {
|
) -> std::result::Result<(), InstructionError> {
|
||||||
Err(InstructionError::CustomError(42))
|
Err(InstructionError::Custom(42))
|
||||||
}
|
}
|
||||||
|
|
||||||
assert!(bank.get_account(&solana_vote_program::id()).is_none());
|
assert!(bank.get_account(&solana_vote_program::id()).is_none());
|
||||||
@ -5033,7 +5033,7 @@ mod tests {
|
|||||||
bank.process_transaction(&transaction),
|
bank.process_transaction(&transaction),
|
||||||
Err(TransactionError::InstructionError(
|
Err(TransactionError::InstructionError(
|
||||||
1,
|
1,
|
||||||
InstructionError::CustomError(42)
|
InstructionError::Custom(42)
|
||||||
))
|
))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -5053,7 +5053,7 @@ mod tests {
|
|||||||
_ka: &[KeyedAccount],
|
_ka: &[KeyedAccount],
|
||||||
_data: &[u8],
|
_data: &[u8],
|
||||||
) -> std::result::Result<(), InstructionError> {
|
) -> std::result::Result<(), InstructionError> {
|
||||||
Err(InstructionError::CustomError(42))
|
Err(InstructionError::Custom(42))
|
||||||
}
|
}
|
||||||
|
|
||||||
let mock_account = Keypair::new();
|
let mock_account = Keypair::new();
|
||||||
@ -5083,7 +5083,7 @@ mod tests {
|
|||||||
bank.process_transaction(&transaction),
|
bank.process_transaction(&transaction),
|
||||||
Err(TransactionError::InstructionError(
|
Err(TransactionError::InstructionError(
|
||||||
1,
|
1,
|
||||||
InstructionError::CustomError(42)
|
InstructionError::Custom(42)
|
||||||
))
|
))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -5099,7 +5099,7 @@ mod tests {
|
|||||||
_ka: &[KeyedAccount],
|
_ka: &[KeyedAccount],
|
||||||
_data: &[u8],
|
_data: &[u8],
|
||||||
) -> std::result::Result<(), InstructionError> {
|
) -> std::result::Result<(), InstructionError> {
|
||||||
Err(InstructionError::CustomError(42))
|
Err(InstructionError::Custom(42))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Non-native loader accounts can not be used for instruction processing
|
// Non-native loader accounts can not be used for instruction processing
|
||||||
|
@ -116,8 +116,8 @@ pub enum InstructionError {
|
|||||||
/// Allows on-chain programs to implement program-specific error types and see them returned
|
/// Allows on-chain programs to implement program-specific error types and see them returned
|
||||||
/// by the Solana runtime. A program-specific error may be any type that is represented as
|
/// by the Solana runtime. A program-specific error may be any type that is represented as
|
||||||
/// or serialized to a u32 integer.
|
/// or serialized to a u32 integer.
|
||||||
#[error("program error: {0}")]
|
#[error("custom program error: {0:#x}")]
|
||||||
CustomError(u32),
|
Custom(u32),
|
||||||
|
|
||||||
/// The return value from the program was invalid. Valid errors are either a defined builtin
|
/// The return value from the program was invalid. Valid errors are either a defined builtin
|
||||||
/// error value or a user-defined error in the lower 32 bits.
|
/// error value or a user-defined error in the lower 32 bits.
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use crate::{instruction::InstructionError, program_utils::DecodeError};
|
use crate::{instruction::InstructionError, program_utils::DecodeError};
|
||||||
use num_traits::{FromPrimitive, ToPrimitive};
|
use num_traits::{FromPrimitive, ToPrimitive};
|
||||||
|
use std::convert::TryFrom;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
#[cfg(feature = "program")]
|
#[cfg(feature = "program")]
|
||||||
@ -14,7 +15,7 @@ pub enum ProgramError {
|
|||||||
/// by the Solana runtime. A program-specific error may be any type that is represented as
|
/// by the Solana runtime. A program-specific error may be any type that is represented as
|
||||||
/// or serialized to a u32 integer.
|
/// or serialized to a u32 integer.
|
||||||
#[error("Custom program error: {0}")]
|
#[error("Custom program error: {0}")]
|
||||||
CustomError(u32),
|
Custom(u32),
|
||||||
#[error("The arguments provided to a program instruction where invalid")]
|
#[error("The arguments provided to a program instruction where invalid")]
|
||||||
InvalidArgument,
|
InvalidArgument,
|
||||||
#[error("An instruction's data contents was invalid")]
|
#[error("An instruction's data contents was invalid")]
|
||||||
@ -51,24 +52,24 @@ impl PrintProgramError for ProgramError {
|
|||||||
E: 'static + std::error::Error + DecodeError<E> + PrintProgramError + FromPrimitive,
|
E: 'static + std::error::Error + DecodeError<E> + PrintProgramError + FromPrimitive,
|
||||||
{
|
{
|
||||||
match self {
|
match self {
|
||||||
ProgramError::CustomError(error) => {
|
ProgramError::Custom(error) => {
|
||||||
if let Some(custom_error) = E::decode_custom_error_to_enum(*error) {
|
if let Some(custom_error) = E::decode_custom_error_to_enum(*error) {
|
||||||
custom_error.print::<E>();
|
custom_error.print::<E>();
|
||||||
} else {
|
} else {
|
||||||
info!("Error: Unknown");
|
info!("Error: Unknown");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ProgramError::InvalidArgument => info!("Error: InvalidArgument"),
|
Self::InvalidArgument => info!("Error: InvalidArgument"),
|
||||||
ProgramError::InvalidInstructionData => info!("Error: InvalidInstructionData"),
|
Self::InvalidInstructionData => info!("Error: InvalidInstructionData"),
|
||||||
ProgramError::InvalidAccountData => info!("Error: InvalidAccountData"),
|
Self::InvalidAccountData => info!("Error: InvalidAccountData"),
|
||||||
ProgramError::AccountDataTooSmall => info!("Error: AccountDataTooSmall"),
|
Self::AccountDataTooSmall => info!("Error: AccountDataTooSmall"),
|
||||||
ProgramError::InsufficientFunds => info!("Error: InsufficientFunds"),
|
Self::InsufficientFunds => info!("Error: InsufficientFunds"),
|
||||||
ProgramError::IncorrectProgramId => info!("Error: IncorrectProgramId"),
|
Self::IncorrectProgramId => info!("Error: IncorrectProgramId"),
|
||||||
ProgramError::MissingRequiredSignature => info!("Error: MissingRequiredSignature"),
|
Self::MissingRequiredSignature => info!("Error: MissingRequiredSignature"),
|
||||||
ProgramError::AccountAlreadyInitialized => info!("Error: AccountAlreadyInitialized"),
|
Self::AccountAlreadyInitialized => info!("Error: AccountAlreadyInitialized"),
|
||||||
ProgramError::UninitializedAccount => info!("Error: UninitializedAccount"),
|
Self::UninitializedAccount => info!("Error: UninitializedAccount"),
|
||||||
ProgramError::NotEnoughAccountKeys => info!("Error: NotEnoughAccountKeys"),
|
Self::NotEnoughAccountKeys => info!("Error: NotEnoughAccountKeys"),
|
||||||
ProgramError::AccountBorrowFailed => info!("Error: AccountBorrowFailed"),
|
Self::AccountBorrowFailed => info!("Error: AccountBorrowFailed"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -108,7 +109,7 @@ impl From<ProgramError> for u64 {
|
|||||||
ProgramError::UninitializedAccount => UNINITIALIZED_ACCOUNT,
|
ProgramError::UninitializedAccount => UNINITIALIZED_ACCOUNT,
|
||||||
ProgramError::NotEnoughAccountKeys => NOT_ENOUGH_ACCOUNT_KEYS,
|
ProgramError::NotEnoughAccountKeys => NOT_ENOUGH_ACCOUNT_KEYS,
|
||||||
ProgramError::AccountBorrowFailed => ACCOUNT_BORROW_FAILED,
|
ProgramError::AccountBorrowFailed => ACCOUNT_BORROW_FAILED,
|
||||||
ProgramError::CustomError(error) => {
|
ProgramError::Custom(error) => {
|
||||||
if error == 0 {
|
if error == 0 {
|
||||||
CUSTOM_ZERO
|
CUSTOM_ZERO
|
||||||
} else {
|
} else {
|
||||||
@ -119,6 +120,48 @@ impl From<ProgramError> for u64 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<u64> for ProgramError {
|
||||||
|
fn from(error: u64) -> Self {
|
||||||
|
match error {
|
||||||
|
INVALID_ARGUMENT => ProgramError::InvalidArgument,
|
||||||
|
INVALID_INSTRUCTION_DATA => ProgramError::InvalidInstructionData,
|
||||||
|
INVALID_ACCOUNT_DATA => ProgramError::InvalidAccountData,
|
||||||
|
ACCOUNT_DATA_TOO_SMALL => ProgramError::AccountDataTooSmall,
|
||||||
|
INSUFFICIENT_FUNDS => ProgramError::InsufficientFunds,
|
||||||
|
INCORRECT_PROGRAM_ID => ProgramError::IncorrectProgramId,
|
||||||
|
MISSING_REQUIRED_SIGNATURES => ProgramError::MissingRequiredSignature,
|
||||||
|
ACCOUNT_ALREADY_INITIALIZED => ProgramError::AccountAlreadyInitialized,
|
||||||
|
UNINITIALIZED_ACCOUNT => ProgramError::UninitializedAccount,
|
||||||
|
NOT_ENOUGH_ACCOUNT_KEYS => ProgramError::NotEnoughAccountKeys,
|
||||||
|
ACCOUNT_BORROW_FAILED => ProgramError::AccountBorrowFailed,
|
||||||
|
CUSTOM_ZERO => ProgramError::Custom(0),
|
||||||
|
_ => ProgramError::Custom(error as u32),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<InstructionError> for ProgramError {
|
||||||
|
type Error = InstructionError;
|
||||||
|
|
||||||
|
fn try_from(error: InstructionError) -> Result<Self, Self::Error> {
|
||||||
|
match error {
|
||||||
|
Self::Error::Custom(err) => Ok(Self::Custom(err)),
|
||||||
|
Self::Error::InvalidArgument => Ok(Self::InvalidArgument),
|
||||||
|
Self::Error::InvalidInstructionData => Ok(Self::InvalidInstructionData),
|
||||||
|
Self::Error::InvalidAccountData => Ok(Self::InvalidAccountData),
|
||||||
|
Self::Error::AccountDataTooSmall => Ok(Self::AccountDataTooSmall),
|
||||||
|
Self::Error::InsufficientFunds => Ok(Self::InsufficientFunds),
|
||||||
|
Self::Error::IncorrectProgramId => Ok(Self::IncorrectProgramId),
|
||||||
|
Self::Error::MissingRequiredSignature => Ok(Self::MissingRequiredSignature),
|
||||||
|
Self::Error::AccountAlreadyInitialized => Ok(Self::AccountAlreadyInitialized),
|
||||||
|
Self::Error::UninitializedAccount => Ok(Self::UninitializedAccount),
|
||||||
|
Self::Error::NotEnoughAccountKeys => Ok(Self::NotEnoughAccountKeys),
|
||||||
|
Self::Error::AccountBorrowFailed => Ok(Self::AccountBorrowFailed),
|
||||||
|
_ => Err(error),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T> From<T> for InstructionError
|
impl<T> From<T> for InstructionError
|
||||||
where
|
where
|
||||||
T: ToPrimitive,
|
T: ToPrimitive,
|
||||||
@ -126,7 +169,7 @@ where
|
|||||||
fn from(error: T) -> Self {
|
fn from(error: T) -> Self {
|
||||||
let error = error.to_u64().unwrap_or(0xbad_c0de);
|
let error = error.to_u64().unwrap_or(0xbad_c0de);
|
||||||
match error {
|
match error {
|
||||||
CUSTOM_ZERO => InstructionError::CustomError(0),
|
CUSTOM_ZERO => InstructionError::Custom(0),
|
||||||
INVALID_ARGUMENT => InstructionError::InvalidArgument,
|
INVALID_ARGUMENT => InstructionError::InvalidArgument,
|
||||||
INVALID_INSTRUCTION_DATA => InstructionError::InvalidInstructionData,
|
INVALID_INSTRUCTION_DATA => InstructionError::InvalidInstructionData,
|
||||||
INVALID_ACCOUNT_DATA => InstructionError::InvalidAccountData,
|
INVALID_ACCOUNT_DATA => InstructionError::InvalidAccountData,
|
||||||
@ -141,7 +184,7 @@ where
|
|||||||
_ => {
|
_ => {
|
||||||
// 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 {
|
||||||
InstructionError::CustomError(error as u32)
|
InstructionError::Custom(error as u32)
|
||||||
} else {
|
} else {
|
||||||
InstructionError::InvalidError
|
InstructionError::InvalidError
|
||||||
}
|
}
|
||||||
|
@ -204,7 +204,7 @@ pub enum SignerError {
|
|||||||
TransactionError(#[from] TransactionError),
|
TransactionError(#[from] TransactionError),
|
||||||
|
|
||||||
#[error("custom error: {0}")]
|
#[error("custom error: {0}")]
|
||||||
CustomError(String),
|
Custom(String),
|
||||||
|
|
||||||
// Presigner-specific Errors
|
// Presigner-specific Errors
|
||||||
#[error("presigner error")]
|
#[error("presigner error")]
|
||||||
@ -212,7 +212,7 @@ pub enum SignerError {
|
|||||||
|
|
||||||
// Remote Keypair-specific Errors
|
// Remote Keypair-specific Errors
|
||||||
#[error("connection error: {0}")]
|
#[error("connection error: {0}")]
|
||||||
ConnectionError(String),
|
Connection(String),
|
||||||
|
|
||||||
#[error("invalid input: {0}")]
|
#[error("invalid input: {0}")]
|
||||||
InvalidInput(String),
|
InvalidInput(String),
|
||||||
|
@ -504,7 +504,7 @@ mod tests {
|
|||||||
where
|
where
|
||||||
T: 'static + std::error::Error + DecodeError<T> + FromPrimitive,
|
T: 'static + std::error::Error + DecodeError<T> + FromPrimitive,
|
||||||
{
|
{
|
||||||
if let InstructionError::CustomError(code) = err {
|
if let InstructionError::Custom(code) = err {
|
||||||
let specific_error: T = T::decode_custom_error_to_enum(code).unwrap();
|
let specific_error: T = T::decode_custom_error_to_enum(code).unwrap();
|
||||||
format!(
|
format!(
|
||||||
"{:?}: {}::{:?} - {}",
|
"{:?}: {}::{:?} - {}",
|
||||||
@ -518,19 +518,19 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
"CustomError(0): NonceError::NoRecentBlockhashes - recent blockhash list is empty",
|
"Custom(0): NonceError::NoRecentBlockhashes - recent blockhash list is empty",
|
||||||
pretty_err::<NonceError>(NonceError::NoRecentBlockhashes.into())
|
pretty_err::<NonceError>(NonceError::NoRecentBlockhashes.into())
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
"CustomError(1): NonceError::NotExpired - stored nonce is still in recent_blockhashes",
|
"Custom(1): NonceError::NotExpired - stored nonce is still in recent_blockhashes",
|
||||||
pretty_err::<NonceError>(NonceError::NotExpired.into())
|
pretty_err::<NonceError>(NonceError::NotExpired.into())
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
"CustomError(2): NonceError::UnexpectedValue - specified nonce does not match stored nonce",
|
"Custom(2): NonceError::UnexpectedValue - specified nonce does not match stored nonce",
|
||||||
pretty_err::<NonceError>(NonceError::UnexpectedValue.into())
|
pretty_err::<NonceError>(NonceError::UnexpectedValue.into())
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
"CustomError(3): NonceError::BadAccountState - cannot handle request in current account state",
|
"Custom(3): NonceError::BadAccountState - cannot handle request in current account state",
|
||||||
pretty_err::<NonceError>(NonceError::BadAccountState.into())
|
pretty_err::<NonceError>(NonceError::BadAccountState.into())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user