Custom runtime module errors (#3433)

* srml-system checks

* wip

* more modules compiles

* node-runtime checks

* build.sh passes

* include dispatch error in failed event

* revert some unnecessary changes

* refactor based on comments

* more compile error fixes

* avoid unnecessary into

* reorder code

* fixes some tests

* manually implement encode & decode to avoid i8 workaround

* more test fixes

* more fixes

* more error fixes

* Apply suggestions from code review

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* address comments

* test for DispatchError encoding

* tyep alias for democracy

* make error printable

* line width

* fix balances tests

* fix executive test

* fix system tests

* bump version

* ensure consistent method signature

* Apply suggestions from code review

Co-Authored-By: Gavin Wood <github@gavwood.com>

* changes based on review

* Add issue number for TODOs

* fix

* line width

* fix test

* Update core/sr-primitives/src/lib.rs

Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com>

* Update core/sr-primitives/src/traits.rs

Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com>

* Update srml/council/src/motions.rs

Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com>

* Update srml/council/src/motions.rs

Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com>

* update based on review

* More concrete macro matching

* fix test build issue

* Update hex-literal dependency version. (#3141)

* Update hex-literal dep version.

* Update lock file.

* Start to rework the new error handling

* More work to get it back compiling

* Start to fix after master merge

* The great transaction error handling refactoring

* Make `decl_error` errors convertible to `&'static str`

* Make srml-executive build again

* Fix `sr-primitives` tests

* More fixes

* Last round of fix ups

* Fix build

* Fix build

* Apply suggestions from code review

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Rename some stuff

* Fixes after master merge

* Adds `CheckBlockGasLimit` signed extension

* Remove debug stuff

* Fix srml-balances test

* Rename `InvalidIndex` to `CannotLookup`

* Remove weird generic parameters

* Rename function again

* Fix import

* Document the signed extension

* Change from `Into` to `From`

* Update srml/contracts/src/lib.rs

Co-Authored-By: Sergei Pepyakin <sergei@parity.io>

* Fix compilation

* Update srml/contracts/src/lib.rs

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Update core/sr-primitives/src/transaction_validity.rs

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Remove unused code

* Fix compilation

* Some cleanups

* Fix compile errors

* Make `TransactionValidity` a `Result`

* Apply suggestions from code review

Co-Authored-By: Gavin Wood <gavin@parity.io>

* Beautify the code a little bit and fix test

* Make `CannotLookup` an inherent error declared by `decl_error!`

* Adds some documentation

* Make `ApplyOutcome` a result

* Up the spec_version

* Apply suggestions from code review

Co-Authored-By: Gavin Wood <gavin@parity.io>
Co-Authored-By: DemiMarie-parity <48690212+DemiMarie-parity@users.noreply.github.com>
This commit is contained in:
Bastian Köcher
2019-09-04 16:21:42 +02:00
committed by GitHub
parent 5e4bc7c9b6
commit c6f3798078
46 changed files with 1259 additions and 630 deletions
+8 -6
View File
@@ -38,7 +38,9 @@ use substrate_client::{
};
use sr_primitives::{
ApplyResult, create_runtime_str, Perbill, impl_opaque_keys,
transaction_validity::{TransactionValidity, ValidTransaction},
transaction_validity::{
TransactionValidity, ValidTransaction, TransactionValidityError, InvalidTransaction,
},
traits::{
BlindCheckable, BlakeTwo256, Block as BlockT, Extrinsic as ExtrinsicT,
GetNodeBlockType, GetRuntimeBlockType, Verify, IdentityLookup,
@@ -123,17 +125,17 @@ impl serde::Serialize for Extrinsic {
impl BlindCheckable for Extrinsic {
type Checked = Self;
fn check(self) -> Result<Self, &'static str> {
fn check(self) -> Result<Self, TransactionValidityError> {
match self {
Extrinsic::AuthoritiesChange(new_auth) => Ok(Extrinsic::AuthoritiesChange(new_auth)),
Extrinsic::Transfer(transfer, signature) => {
if sr_primitives::verify_encoded_lazy(&signature, &transfer, &transfer.from) {
Ok(Extrinsic::Transfer(transfer, signature))
} else {
Err(sr_primitives::BAD_SIGNATURE)
Err(InvalidTransaction::BadProof.into())
}
},
Extrinsic::IncludeData(_) => Err(sr_primitives::BAD_SIGNATURE),
Extrinsic::IncludeData(_) => Err(InvalidTransaction::BadProof.into()),
Extrinsic::StorageChange(key, value) => Ok(Extrinsic::StorageChange(key, value)),
}
}
@@ -478,7 +480,7 @@ cfg_if! {
impl client_api::TaggedTransactionQueue<Block> for Runtime {
fn validate_transaction(utx: <Block as BlockT>::Extrinsic) -> TransactionValidity {
if let Extrinsic::IncludeData(data) = utx {
return TransactionValidity::Valid(ValidTransaction {
return Ok(ValidTransaction {
priority: data.len() as u64,
requires: vec![],
provides: vec![data],
@@ -662,7 +664,7 @@ cfg_if! {
impl client_api::TaggedTransactionQueue<Block> for Runtime {
fn validate_transaction(utx: <Block as BlockT>::Extrinsic) -> TransactionValidity {
if let Extrinsic::IncludeData(data) = utx {
return TransactionValidity::Valid(ValidTransaction{
return Ok(ValidTransaction{
priority: data.len() as u64,
requires: vec![],
provides: vec![data],
+21 -22
View File
@@ -21,12 +21,12 @@ use rstd::prelude::*;
use runtime_io::{storage_root, ordered_trie_root, storage_changes_root, twox_128, blake2_256};
use runtime_support::storage::{self, StorageValue, StorageMap};
use runtime_support::storage_items;
use sr_primitives::traits::{Hash as HashT, BlakeTwo256, Header as _};
use sr_primitives::generic;
use sr_primitives::{ApplyError, ApplyOutcome, ApplyResult};
use sr_primitives::transaction_validity::{TransactionValidity, ValidTransaction};
use sr_primitives::{
traits::{Hash as HashT, BlakeTwo256, Header as _}, generic, ApplyError, ApplyResult,
transaction_validity::{TransactionValidity, ValidTransaction, InvalidTransaction},
};
use codec::{KeyedVec, Encode};
use super::{
use crate::{
AccountId, BlockNumber, Extrinsic, Transfer, H256 as Hash, Block, Header, Digest, AuthorityId
};
use primitives::{Blake2Hasher, storage::well_known_keys};
@@ -119,7 +119,7 @@ fn execute_block_with_state_root_handler(
// execute transactions
block.extrinsics.iter().enumerate().for_each(|(i, e)| {
storage::unhashed::put(well_known_keys::EXTRINSIC_INDEX, &(i as u32));
execute_transaction_backend(e).unwrap_or_else(|_| panic!("Invalid transaction"));
let _ = execute_transaction_backend(e).unwrap_or_else(|_| panic!("Invalid transaction"));
storage::unhashed::kill(well_known_keys::EXTRINSIC_INDEX);
});
@@ -158,17 +158,17 @@ impl executive::ExecuteBlock<Block> for BlockExecutor {
/// This doesn't attempt to validate anything regarding the block.
pub fn validate_transaction(utx: Extrinsic) -> TransactionValidity {
if check_signature(&utx).is_err() {
return TransactionValidity::Invalid(ApplyError::BadSignature as i8);
return InvalidTransaction::BadProof.into();
}
let tx = utx.transfer();
let nonce_key = tx.from.to_keyed_vec(NONCE_OF);
let expected_nonce: u64 = storage::hashed::get_or(&blake2_256, &nonce_key, 0);
if tx.nonce < expected_nonce {
return TransactionValidity::Invalid(ApplyError::Stale as i8);
return InvalidTransaction::Stale.into();
}
if tx.nonce > expected_nonce + 64 {
return TransactionValidity::Unknown(ApplyError::Future as i8);
return InvalidTransaction::Future.into();
}
let hash = |from: &AccountId, nonce: u64| {
@@ -188,7 +188,7 @@ pub fn validate_transaction(utx: Extrinsic) -> TransactionValidity {
p
};
TransactionValidity::Valid(ValidTransaction {
Ok(ValidTransaction {
priority: tx.amount,
requires,
provides,
@@ -244,8 +244,7 @@ pub fn finalize_block() -> Header {
#[inline(always)]
fn check_signature(utx: &Extrinsic) -> Result<(), ApplyError> {
use sr_primitives::traits::BlindCheckable;
utx.clone().check().map_err(|_| ApplyError::BadSignature)?;
Ok(())
utx.clone().check().map_err(|_| InvalidTransaction::BadProof.into()).map(|_| ())
}
fn execute_transaction_backend(utx: &Extrinsic) -> ApplyResult {
@@ -253,7 +252,7 @@ fn execute_transaction_backend(utx: &Extrinsic) -> ApplyResult {
match utx {
Extrinsic::Transfer(ref transfer, _) => execute_transfer_backend(transfer),
Extrinsic::AuthoritiesChange(ref new_auth) => execute_new_authorities_backend(new_auth),
Extrinsic::IncludeData(_) => Ok(ApplyOutcome::Success),
Extrinsic::IncludeData(_) => Ok(Ok(())),
Extrinsic::StorageChange(key, value) => execute_storage_change(key, value.as_ref().map(|v| &**v)),
}
}
@@ -263,7 +262,7 @@ fn execute_transfer_backend(tx: &Transfer) -> ApplyResult {
let nonce_key = tx.from.to_keyed_vec(NONCE_OF);
let expected_nonce: u64 = storage::hashed::get_or(&blake2_256, &nonce_key, 0);
if !(tx.nonce == expected_nonce) {
return Err(ApplyError::Stale)
return Err(InvalidTransaction::Stale.into());
}
// increment nonce in storage
@@ -275,18 +274,18 @@ fn execute_transfer_backend(tx: &Transfer) -> ApplyResult {
// enact transfer
if !(tx.amount <= from_balance) {
return Err(ApplyError::CantPay)
return Err(InvalidTransaction::Payment.into());
}
let to_balance_key = tx.to.to_keyed_vec(BALANCE_OF);
let to_balance: u64 = storage::hashed::get_or(&blake2_256, &to_balance_key, 0);
storage::hashed::put(&blake2_256, &from_balance_key, &(from_balance - tx.amount));
storage::hashed::put(&blake2_256, &to_balance_key, &(to_balance + tx.amount));
Ok(ApplyOutcome::Success)
Ok(Ok(()))
}
fn execute_new_authorities_backend(new_authorities: &[AuthorityId]) -> ApplyResult {
NewAuthorities::put(new_authorities.to_vec());
Ok(ApplyOutcome::Success)
Ok(Ok(()))
}
fn execute_storage_change(key: &[u8], value: Option<&[u8]>) -> ApplyResult {
@@ -294,7 +293,7 @@ fn execute_storage_change(key: &[u8], value: Option<&[u8]>) -> ApplyResult {
Some(value) => storage::unhashed::put_raw(key, value),
None => storage::unhashed::kill(key),
}
Ok(ApplyOutcome::Success)
Ok(Ok(()))
}
#[cfg(feature = "std")]
@@ -304,7 +303,7 @@ fn info_expect_equal_hash(given: &Hash, expected: &Hash) {
println!(
"Hash: given={}, expected={}",
HexDisplay::from(given.as_fixed_bytes()),
HexDisplay::from(expected.as_fixed_bytes())
HexDisplay::from(expected.as_fixed_bytes()),
);
}
}
@@ -312,9 +311,9 @@ fn info_expect_equal_hash(given: &Hash, expected: &Hash) {
#[cfg(not(feature = "std"))]
fn info_expect_equal_hash(given: &Hash, expected: &Hash) {
if given != expected {
::runtime_io::print("Hash not equal");
::runtime_io::print(given.as_bytes());
::runtime_io::print(expected.as_bytes());
runtime_io::print("Hash not equal");
runtime_io::print(given.as_bytes());
runtime_io::print(expected.as_bytes());
}
}