Skip to content

Commit

Permalink
some progress on errors
Browse files Browse the repository at this point in the history
  • Loading branch information
lexfrl committed Dec 18, 2019
1 parent 775c141 commit 5f2226f
Show file tree
Hide file tree
Showing 10 changed files with 424 additions and 344 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

331 changes: 176 additions & 155 deletions core/primitives/src/errors.rs

Large diffs are not rendered by default.

136 changes: 64 additions & 72 deletions core/primitives/src/views.rs
Original file line number Diff line number Diff line change
Expand Up @@ -668,92 +668,84 @@ impl Default for FinalExecutionStatus {
}
}

#[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
#[derive(
BorshSerialize, BorshDeserialize, Serialize, Deserialize, Debug, PartialEq, Eq, Clone, Default,
)]
pub struct ExecutionErrorView {
pub error_message: String,
pub error_type: String,
}

impl From<ExecutionError> for ExecutionErrorView {
fn from(error: ExecutionError) -> Self {
ExecutionErrorView {
error_message: format!("{}", error),
error_type: match &error {
ExecutionError::Action(e) => match e {
ActionError::AccountAlreadyExists(_) => {
"ActionError::AccountAlreadyExists".to_string()
}
ActionError::AccountDoesNotExist(_, _) => {
"ActionError::AccountDoesNotExist".to_string()
}
ActionError::CreateAccountNotAllowed(_, _) => {
"ActionError::CreateAccountNotAllowed".to_string()
}
ActionError::ActorNoPermission(_, _, _) => {
"ActionError::ActorNoPermission".to_string()
}
ActionError::DeleteKeyDoesNotExist(_) => {
"ActionError::DeleteKeyDoesNotExist".to_string()
}
ActionError::AddKeyAlreadyExists(_) => {
"ActionError::AddKeyAlreadyExists".to_string()
}
ActionError::DeleteAccountStaking(_) => {
"ActionError::DeleteAccountStaking".to_string()
}
ActionError::DeleteAccountHasRent(_, _) => {
"ActionError::DeleteAccountHasRent".to_string()
}
ActionError::RentUnpaid(_, _) => "ActionError::RentUnpaid".to_string(),
ActionError::TriesToUnstake(_) => "ActionError::TriesToUnstake".to_string(),
ActionError::TriesToStake(_, _, _, _) => {
"ActionError::TriesToStake".to_string()
}
ActionError::FunctionCallError(_) => {
"ActionError::FunctionCallError".to_string()
}
},
ExecutionError::InvalidTx(e) => match e {
InvalidTxError::InvalidSigner(_) => "InvalidTxError::InvalidSigner".to_string(),
InvalidTxError::SignerDoesNotExist(_) => {
"InvalidTxError::SignerDoesNotExist".to_string()
let error_type = match &error {
ExecutionError::Action(e) => match e {
ActionError::AccountAlreadyExists { .. } => {
"ActionError::AccountAlreadyExists".to_string()
}
ActionError::AccountDoesNotExist { .. } => {
"ActionError::AccountDoesNotExist".to_string()
}
ActionError::CreateAccountNotAllowed { .. } => {
"ActionError::CreateAccountNotAllowed".to_string()
}
ActionError::ActorNoPermission { .. } => {
"ActionError::ActorNoPermission".to_string()
}
ActionError::DeleteKeyDoesNotExist { .. } => {
"ActionError::DeleteKeyDoesNotExist".to_string()
}
ActionError::AddKeyAlreadyExists { .. } => {
"ActionError::AddKeyAlreadyExists".to_string()
}
ActionError::DeleteAccountStaking { .. } => {
"ActionError::DeleteAccountStaking".to_string()
}
ActionError::DeleteAccountHasRent { .. } => {
"ActionError::DeleteAccountHasRent".to_string()
}
ActionError::RentUnpaid { .. } => "ActionError::RentUnpaid".to_string(),
ActionError::TriesToUnstake { .. } => "ActionError::TriesToUnstake".to_string(),
ActionError::TriesToStake { .. } => "ActionError::TriesToStake".to_string(),
ActionError::FunctionCall { .. } => "ActionError::FunctionCall".to_string(),
},
ExecutionError::InvalidTx(e) => match e {
InvalidTxError::InvalidSigner { .. } => "InvalidTxError::InvalidSigner".to_string(),
InvalidTxError::SignerDoesNotExist { .. } => {
"InvalidTxError::SignerDoesNotExist".to_string()
}
InvalidTxError::InvalidAccessKey(e) => match e {
InvalidAccessKeyError::AccessKeyNotFound { .. } => {
"InvalidTxError::InvalidAccessKey::AccessKeyNotFound".to_string()
}
InvalidTxError::InvalidAccessKey(e) => match e {
InvalidAccessKeyError::AccessKeyNotFound(_, _) => {
"InvalidTxError::InvalidAccessKey::AccessKeyNotFound".to_string()
}
InvalidAccessKeyError::ReceiverMismatch(_, _) => {
"InvalidTxError::InvalidAccessKey::ReceiverMismatch".to_string()
}
InvalidAccessKeyError::MethodNameMismatch(_) => {
"InvalidTxError::InvalidAccessKey::MethodNameMismatch".to_string()
}
InvalidAccessKeyError::ActionError => {
"InvalidTxError::InvalidAccessKey::ActionError".to_string()
}
InvalidAccessKeyError::NotEnoughAllowance(_, _, _, _) => {
"InvalidTxError::InvalidAccessKey::NotEnoughAllowance".to_string()
}
},
InvalidTxError::InvalidNonce(_, _) => {
"InvalidTxError::InvalidNonce".to_string()
InvalidAccessKeyError::ReceiverMismatch { .. } => {
"InvalidTxError::InvalidAccessKey::ReceiverMismatch".to_string()
}
InvalidTxError::InvalidReceiver(_) => {
"InvalidTxError::InvalidReceiver".to_string()
InvalidAccessKeyError::MethodNameMismatch { .. } => {
"InvalidTxError::InvalidAccessKey::MethodNameMismatch".to_string()
}
InvalidTxError::InvalidSignature => {
"InvalidTxError::InvalidSignature".to_string()
InvalidAccessKeyError::ActionError => {
"InvalidTxError::InvalidAccessKey::ActionError".to_string()
}
InvalidTxError::NotEnoughBalance(_, _, _) => {
"InvalidTxError::NotEnoughBalance".to_string()
InvalidAccessKeyError::NotEnoughAllowance { .. } => {
"InvalidTxError::InvalidAccessKey::NotEnoughAllowance".to_string()
}
InvalidTxError::RentUnpaid(_, _) => "InvalidTxError::RentUnpaid".to_string(),
InvalidTxError::CostOverflow => "InvalidTxError::CostOverflow".to_string(),
InvalidTxError::InvalidChain => "InvalidTxError::InvalidChain".to_string(),
InvalidTxError::Expired => "InvalidTxError::Expired".to_string(),
},
InvalidTxError::InvalidNonce { .. } => "InvalidTxError::InvalidNonce".to_string(),
InvalidTxError::InvalidReceiver { .. } => {
"InvalidTxError::InvalidReceiver".to_string()
}
InvalidTxError::InvalidSignature => "InvalidTxError::InvalidSignature".to_string(),
InvalidTxError::NotEnoughBalance { .. } => {
"InvalidTxError::NotEnoughBalance".to_string()
}
InvalidTxError::RentUnpaid { .. } => "InvalidTxError::RentUnpaid".to_string(),
InvalidTxError::CostOverflow => "InvalidTxError::CostOverflow".to_string(),
InvalidTxError::InvalidChain => "InvalidTxError::InvalidChain".to_string(),
InvalidTxError::Expired => "InvalidTxError::Expired".to_string(),
},
}
};
ExecutionErrorView { error_message: format!("{}", error), error_type }
}
}

Expand Down
1 change: 1 addition & 0 deletions runtime/near-vm-errors/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ Error that can occur inside Near Runtime encapsulated in a separate crate. Might

[dependencies]
borsh = "0.2.10"
serde = { version = "1.0", features = ["derive"] }
22 changes: 15 additions & 7 deletions runtime/near-vm-errors/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
use borsh::{BorshDeserialize, BorshSerialize};
use serde::{Deserialize, Serialize};
use std::fmt;

#[derive(Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize)]
#[derive(Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize, Deserialize, Serialize)]
#[serde(tag = "type", content = "c")]
pub enum VMError {
FunctionExecError(FunctionExecError),
StorageError(Vec<u8>),
}

#[derive(Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize)]
#[derive(Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize, Deserialize, Serialize)]
#[serde(tag = "type")]
pub enum FunctionExecError {
CompilationError(CompilationError),
LinkError(String),
Expand All @@ -16,22 +19,25 @@ pub enum FunctionExecError {
HostError(HostError),
}

#[derive(Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize)]
#[derive(Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize, Deserialize, Serialize)]
#[serde(tag = "type")]
pub enum MethodResolveError {
MethodEmptyName,
MethodUTF8Error,
MethodNotFound,
MethodInvalidSignature,
}

#[derive(Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize)]
#[derive(Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize, Deserialize, Serialize)]
#[serde(tag = "type")]
pub enum CompilationError {
CodeDoesNotExist(String),
PrepareError(PrepareError),
WasmerCompileError(String),
}

#[derive(Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize)]
#[derive(Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize, Deserialize, Serialize)]
#[serde(tag = "type")]
/// Error that can occur while preparing or executing Wasm smart-contract.
pub enum PrepareError {
/// Error happened while serializing the module.
Expand Down Expand Up @@ -63,7 +69,8 @@ pub enum PrepareError {
Memory,
}

#[derive(Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize)]
#[derive(Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize, Deserialize, Serialize)]
#[serde(tag = "type")]
pub enum HostError {
BadUTF16,
BadUTF8,
Expand All @@ -88,7 +95,8 @@ pub enum HostError {
ProhibitedInView(String),
}

#[derive(Debug, Clone, PartialEq, BorshDeserialize, BorshSerialize)]
#[derive(Debug, Clone, PartialEq, BorshDeserialize, BorshSerialize, Deserialize, Serialize)]
#[serde(tag = "type")]
pub enum HostErrorOrStorageError {
HostError(HostError),
/// Error from underlying storage, serialized
Expand Down
67 changes: 36 additions & 31 deletions runtime/runtime/src/actions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ pub(crate) fn action_function_call(
let error = VMError::FunctionExecError(FunctionExecError::CompilationError(
CompilationError::CodeDoesNotExist(account_id.clone()),
));
result.result = Err(ActionError::FunctionCallError(error));
result.result = Err(ActionError::FunctionCall(error));
return Ok(());
}
Err(e) => {
Expand Down Expand Up @@ -179,7 +179,7 @@ pub(crate) fn action_function_call(
borsh::BorshDeserialize::try_from_slice(&storage).expect("Borsh cannot fail");
return Err(err);
}
result.result = Err(ActionError::FunctionCallError(err));
result.result = Err(ActionError::FunctionCall(err));
if let Some(outcome) = outcome {
result.gas_burnt += outcome.burnt_gas;
result.gas_burnt_for_function_call += outcome.burnt_gas;
Expand Down Expand Up @@ -215,7 +215,7 @@ pub(crate) fn action_stake(
if account.amount >= increment {
if account.locked == 0 && stake.stake == 0 {
// if the account hasn't staked, it cannot unstake
result.result = Err(ActionError::TriesToUnstake(account_id.clone()));
result.result = Err(ActionError::TriesToUnstake { receiver_id: account_id.clone() });
return;
}
result.validator_proposals.push(ValidatorStake {
Expand All @@ -228,12 +228,12 @@ pub(crate) fn action_stake(
account.locked = stake.stake;
}
} else {
result.result = Err(ActionError::TriesToStake(
account_id.clone(),
stake.stake,
account.locked,
account.amount,
));
result.result = Err(ActionError::TriesToStake {
receiver_id: account_id.clone(),
stake: stake.stake,
staked: account.locked,
amount: account.amount,
});
}
}

Expand All @@ -253,10 +253,10 @@ pub(crate) fn action_create_account(
if !is_valid_top_level_account_id(account_id)
&& !is_valid_sub_account_id(&receipt.predecessor_id, account_id)
{
result.result = Err(ActionError::CreateAccountNotAllowed(
account_id.clone(),
receipt.predecessor_id.clone(),
));
result.result = Err(ActionError::CreateAccountNotAllowed {
receiver_id: account_id.clone(),
sender_id: receipt.predecessor_id.clone(),
});
return;
}
*actor_id = receipt.receiver_id.clone();
Expand Down Expand Up @@ -317,7 +317,10 @@ pub(crate) fn action_delete_key(
let account = account.as_mut().unwrap();
let access_key = get_access_key(state_update, account_id, &delete_key.public_key)?;
if access_key.is_none() {
result.result = Err(ActionError::DeleteKeyDoesNotExist(account_id.clone()));
result.result = Err(ActionError::DeleteKeyDoesNotExist {
public_key: delete_key.public_key.clone(),
receiver_id: account_id.clone(),
});
return Ok(());
}
// Remove access key
Expand All @@ -343,7 +346,10 @@ pub(crate) fn action_add_key(
) -> Result<(), StorageError> {
let account = account.as_mut().unwrap();
if get_access_key(state_update, account_id, &add_key.public_key)?.is_some() {
result.result = Err(ActionError::AddKeyAlreadyExists(add_key.public_key.clone()));
result.result = Err(ActionError::AddKeyAlreadyExists {
receiver_id: account_id.to_owned(),
public_key: add_key.public_key.clone(),
});
return Ok(());
}
set_access_key(state_update, account_id, &add_key.public_key, &add_key.access_key);
Expand All @@ -369,16 +375,16 @@ pub(crate) fn check_actor_permissions(
match action {
Action::DeployContract(_) | Action::Stake(_) | Action::AddKey(_) | Action::DeleteKey(_) => {
if actor_id != account_id {
return Err(ActionError::ActorNoPermission(
actor_id.clone(),
account_id.clone(),
action_type_as_string(action).to_owned(),
));
return Err(ActionError::ActorNoPermission {
sender_id: actor_id.clone(),
receiver_id: account_id.clone(),
action: action_type_as_string(action).to_owned(),
});
}
}
Action::DeleteAccount(_) => {
if account.as_ref().unwrap().locked != 0 {
return Err(ActionError::DeleteAccountStaking(account_id.clone()));
return Err(ActionError::DeleteAccountStaking { receiver_id: account_id.clone() });
}
if actor_id != account_id
&& check_rent(
Expand All @@ -389,10 +395,10 @@ pub(crate) fn check_actor_permissions(
)
.is_ok()
{
return Err(ActionError::DeleteAccountHasRent(
account_id.clone(),
account.as_ref().unwrap().amount,
));
return Err(ActionError::DeleteAccountHasRent {
receiver_id: account_id.clone(),
amount: account.as_ref().unwrap().amount,
});
}
}
Action::CreateAccount(_) | Action::FunctionCall(_) | Action::Transfer(_) => (),
Expand Down Expand Up @@ -421,7 +427,7 @@ pub(crate) fn check_account_existence(
match action {
Action::CreateAccount(_) => {
if account.is_some() {
return Err(ActionError::AccountAlreadyExists(account_id.clone()));
return Err(ActionError::AccountAlreadyExists { receiver_id: account_id.clone() });
}
}
Action::DeployContract(_)
Expand All @@ -432,12 +438,11 @@ pub(crate) fn check_account_existence(
| Action::DeleteKey(_)
| Action::DeleteAccount(_) => {
if account.is_none() {
return Err(ActionError::AccountDoesNotExist(
action_type_as_string(action).to_owned(),
account_id.clone(),
));
return Err(ActionError::AccountDoesNotExist {
action: action_type_as_string(action).to_owned(),
receiver_id: account_id.clone(),
});
}
//
}
};
Ok(())
Expand Down
Loading

0 comments on commit 5f2226f

Please sign in to comment.