Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.

Do not call initialize_block before any runtime api #8953

Merged
8 commits merged into from
Jul 1, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion bin/node-template/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -365,8 +365,9 @@ impl_runtime_apis! {
fn validate_transaction(
source: TransactionSource,
tx: <Block as BlockT>::Extrinsic,
block_hash: <Block as BlockT>::Hash,
) -> TransactionValidity {
Executive::validate_transaction(source, tx)
Executive::validate_transaction(source, tx, block_hash)
}
}

Expand Down
8 changes: 6 additions & 2 deletions bin/node/executor/tests/submit_transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -256,12 +256,16 @@ fn submitted_transaction_should_be_valid() {
<frame_system::Account<Runtime>>::insert(&address, account);

// check validity
let res = Executive::validate_transaction(source, extrinsic).unwrap();
let res = Executive::validate_transaction(
source,
extrinsic,
frame_system::BlockHash::<Runtime>::get(0),
).unwrap();

// We ignore res.priority since this number can change based on updates to weights and such.
assert_eq!(res.requires, Vec::<TransactionTag>::new());
assert_eq!(res.provides, vec![(address, 0).encode()]);
assert_eq!(res.longevity, 2048);
assert_eq!(res.longevity, 2047);
assert_eq!(res.propagate, true);
});
}
3 changes: 2 additions & 1 deletion bin/node/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1292,8 +1292,9 @@ impl_runtime_apis! {
fn validate_transaction(
source: TransactionSource,
tx: <Block as BlockT>::Extrinsic,
block_hash: <Block as BlockT>::Hash,
) -> TransactionValidity {
Executive::validate_transaction(source, tx)
Executive::validate_transaction(source, tx, block_hash)
}
}

Expand Down
6 changes: 1 addition & 5 deletions client/api/src/call_executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ use sc_executor::{RuntimeVersion, NativeVersion};
use sp_externalities::Extensions;
use sp_core::NativeOrEncoded;

use sp_api::{ProofRecorder, InitializeBlock, StorageTransactionCache};
use sp_api::{ProofRecorder, StorageTransactionCache};
use crate::execution_extensions::ExecutionExtensions;

/// Executor Provider
Expand Down Expand Up @@ -71,8 +71,6 @@ pub trait CallExecutor<B: BlockT> {
/// Before executing the method, passed header is installed as the current header
/// of the execution context.
fn contextual_call<
'a,
IB: Fn() -> sp_blockchain::Result<()>,
EM: Fn(
Result<NativeOrEncoded<R>, Self::Error>,
Result<NativeOrEncoded<R>, Self::Error>
Expand All @@ -81,15 +79,13 @@ pub trait CallExecutor<B: BlockT> {
NC: FnOnce() -> result::Result<R, sp_api::ApiError> + UnwindSafe,
>(
&self,
initialize_block_fn: IB,
at: &BlockId<B>,
method: &str,
call_data: &[u8],
changes: &RefCell<OverlayedChanges>,
storage_transaction_cache: Option<&RefCell<
StorageTransactionCache<B, <Self::Backend as crate::backend::Backend<B>>::State>,
>>,
initialize_block: InitializeBlock<'a, B>,
execution_manager: ExecutionManager<EM>,
native_call: Option<NC>,
proof_recorder: &Option<ProofRecorder<B>>,
Expand Down
75 changes: 6 additions & 69 deletions client/light/src/call_executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use sp_core::{
convert_hash, NativeOrEncoded, traits::{CodeExecutor, SpawnNamed},
};
use sp_runtime::{
generic::BlockId, traits::{One, Block as BlockT, Header as HeaderT, HashFor},
generic::BlockId, traits::{Block as BlockT, Header as HeaderT, HashFor},
};
use sp_externalities::Extensions;
use sp_state_machine::{
Expand All @@ -36,7 +36,7 @@ use sp_state_machine::{
};
use hash_db::Hasher;

use sp_api::{ProofRecorder, InitializeBlock, StorageTransactionCache};
use sp_api::{ProofRecorder, StorageTransactionCache};

use sp_blockchain::{Error as ClientError, Result as ClientResult};

Expand Down Expand Up @@ -97,8 +97,6 @@ impl<Block, B, Local> CallExecutor<Block> for
}

fn contextual_call<
'a,
IB: Fn() -> ClientResult<()>,
EM: Fn(
Result<NativeOrEncoded<R>, Self::Error>,
Result<NativeOrEncoded<R>, Self::Error>
Expand All @@ -107,13 +105,11 @@ impl<Block, B, Local> CallExecutor<Block> for
NC: FnOnce() -> result::Result<R, sp_api::ApiError> + UnwindSafe,
>(
&self,
initialize_block_fn: IB,
at: &BlockId<Block>,
method: &str,
call_data: &[u8],
changes: &RefCell<OverlayedChanges>,
_: Option<&RefCell<StorageTransactionCache<Block, B::State>>>,
initialize_block: InitializeBlock<'a, Block>,
_manager: ExecutionManager<EM>,
native_call: Option<NC>,
recorder: &Option<ProofRecorder<Block>>,
Expand All @@ -124,7 +120,6 @@ impl<Block, B, Local> CallExecutor<Block> for

match self.backend.is_local_state_available(at) {
true => CallExecutor::contextual_call::<
_,
fn(
Result<NativeOrEncoded<R>, Local::Error>,
Result<NativeOrEncoded<R>, Local::Error>,
Expand All @@ -133,13 +128,11 @@ impl<Block, B, Local> CallExecutor<Block> for
NC
>(
&self.local,
initialize_block_fn,
at,
method,
call_data,
changes,
None,
initialize_block,
ExecutionManager::NativeWhenPossible,
native_call,
recorder,
Expand Down Expand Up @@ -177,7 +170,6 @@ impl<Block, B, Local> CallExecutor<Block> for
/// Proof includes both environment preparation proof and method execution proof.
pub fn prove_execution<Block, S, E>(
mut state: S,
header: Block::Header,
executor: &E,
method: &str,
call_data: &[u8],
Expand All @@ -193,31 +185,20 @@ pub fn prove_execution<Block, S, E>(
Box<dyn sp_state_machine::Error>
)?;

// prepare execution environment + record preparation proof
let mut changes = Default::default();
let (_, init_proof) = executor.prove_at_trie_state(
trie_state,
&mut changes,
"Core_initialize_block",
&header.encode(),
)?;

// execute method + record execution proof
let (result, exec_proof) = executor.prove_at_trie_state(
&trie_state,
&mut changes,
&mut Default::default(),
method,
call_data,
)?;
let total_proof = StorageProof::merge(vec![init_proof, exec_proof]);

Ok((result, total_proof))
Ok((result, exec_proof))
}

/// Check remote contextual execution proof using given backend.
///
/// Method is executed using passed header as environment' current block.
/// Proof should include both environment preparation proof and method execution proof.
/// Proof should include the method execution proof.
pub fn check_execution_proof<Header, E, H>(
executor: &E,
spawn_handle: Box<dyn SpawnNamed>,
Expand All @@ -229,63 +210,19 @@ pub fn check_execution_proof<Header, E, H>(
E: CodeExecutor + Clone + 'static,
H: Hasher,
H::Out: Ord + codec::Codec + 'static,
{
check_execution_proof_with_make_header::<Header, E, H, _>(
executor,
spawn_handle,
request,
remote_proof,
|header| <Header as HeaderT>::new(
*header.number() + One::one(),
Default::default(),
Default::default(),
header.hash(),
Default::default(),
),
)
}

/// Check remote contextual execution proof using given backend and header factory.
///
/// Method is executed using passed header as environment' current block.
/// Proof should include both environment preparation proof and method execution proof.
pub fn check_execution_proof_with_make_header<Header, E, H, MakeNextHeader>(
executor: &E,
spawn_handle: Box<dyn SpawnNamed>,
request: &RemoteCallRequest<Header>,
remote_proof: StorageProof,
make_next_header: MakeNextHeader,
) -> ClientResult<Vec<u8>>
where
E: CodeExecutor + Clone + 'static,
H: Hasher,
Header: HeaderT,
H::Out: Ord + codec::Codec + 'static,
MakeNextHeader: Fn(&Header) -> Header,
{
let local_state_root = request.header.state_root();
let root: H::Out = convert_hash(&local_state_root);

// prepare execution environment + check preparation proof
// prepare execution environment
let mut changes = OverlayedChanges::default();
let trie_backend = create_proof_check_backend(root, remote_proof)?;
let next_header = make_next_header(&request.header);

// TODO: Remove when solved: https://github.com/paritytech/substrate/issues/5047
let backend_runtime_code = sp_state_machine::backend::BackendRuntimeCode::new(&trie_backend);
let runtime_code = backend_runtime_code.runtime_code()
.map_err(|_e| ClientError::RuntimeCodeMissing)?;

execution_proof_check_on_trie_backend::<H, Header::Number, _, _>(
&trie_backend,
&mut changes,
executor,
spawn_handle.clone(),
"Core_initialize_block",
&next_header.encode(),
&runtime_code,
)?;

// execute method
execution_proof_check_on_trie_backend::<H, Header::Number, _, _>(
&trie_backend,
Expand Down
2 changes: 1 addition & 1 deletion client/rpc/src/state/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,7 @@ fn should_return_runtime_version() {

let result = "{\"specName\":\"test\",\"implName\":\"parity-test\",\"authoringVersion\":1,\
\"specVersion\":2,\"implVersion\":2,\"apis\":[[\"0xdf6acb689907609b\",3],\
[\"0x37e397fc7c91f5e4\",1],[\"0xd2bc9897eed08f15\",2],[\"0x40fe3ad401f8959a\",5],\
[\"0x37e397fc7c91f5e4\",1],[\"0xd2bc9897eed08f15\",3],[\"0x40fe3ad401f8959a\",5],\
[\"0xc6e9a76309f39b09\",1],[\"0xdd718d5cc53262d4\",1],[\"0xcbca25e39f142387\",2],\
[\"0xf78b278be53f454c\",2],[\"0xab3c0572291feb8b\",1],[\"0xbc9d89904f5b923f\",1]],\
\"transactionVersion\":1}";
Expand Down
15 changes: 1 addition & 14 deletions client/service/src/client/call_executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ use sp_externalities::Extensions;
use sp_core::{
NativeOrEncoded, NeverNativeValue, traits::{CodeExecutor, SpawnNamed, RuntimeCode},
};
use sp_api::{ProofRecorder, InitializeBlock, StorageTransactionCache};
use sp_api::{ProofRecorder, StorageTransactionCache};
use sc_client_api::{backend, call_executor::CallExecutor};
use super::{client::ClientConfig, wasm_override::WasmOverride, wasm_substitutes::WasmSubstitutes};

Expand Down Expand Up @@ -173,8 +173,6 @@ where
}

fn contextual_call<
'a,
IB: Fn() -> sp_blockchain::Result<()>,
EM: Fn(
Result<NativeOrEncoded<R>, Self::Error>,
Result<NativeOrEncoded<R>, Self::Error>
Expand All @@ -183,29 +181,18 @@ where
NC: FnOnce() -> result::Result<R, sp_api::ApiError> + UnwindSafe,
>(
&self,
initialize_block_fn: IB,
at: &BlockId<Block>,
method: &str,
call_data: &[u8],
changes: &RefCell<OverlayedChanges>,
storage_transaction_cache: Option<&RefCell<
StorageTransactionCache<Block, B::State>
>>,
initialize_block: InitializeBlock<'a, Block>,
execution_manager: ExecutionManager<EM>,
native_call: Option<NC>,
recorder: &Option<ProofRecorder<Block>>,
extensions: Option<Extensions>,
) -> Result<NativeOrEncoded<R>, sp_blockchain::Error> where ExecutionManager<EM>: Clone {
match initialize_block {
InitializeBlock::Do(ref init_block)
if init_block.borrow().as_ref().map(|id| id != at).unwrap_or(true) => {
initialize_block_fn()?;
},
// We don't need to initialize the runtime at a block.
_ => {},
}

let changes_trie_state = backend::changes_tries_state_at_block(at, self.backend.changes_trie_storage())?;
let mut storage_transaction_cache = storage_transaction_cache.map(|c| c.borrow_mut());

Expand Down
24 changes: 2 additions & 22 deletions client/service/src/client/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1243,18 +1243,6 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
trace!("Collected {} uncles", uncles.len());
Ok(uncles)
}

/// Prepare in-memory header that is used in execution environment.
fn prepare_environment_block(&self, parent: &BlockId<Block>) -> sp_blockchain::Result<Block::Header> {
let parent_hash = self.backend.blockchain().expect_block_hash_from_id(parent)?;
Ok(<<Block as BlockT>::Header as HeaderT>::new(
self.backend.blockchain().expect_block_number_from_id(parent)? + One::one(),
Default::default(),
Default::default(),
parent_hash,
Default::default(),
))
}
}

impl<B, E, Block, RA> UsageProvider<Block> for Client<B, E, Block, RA> where
Expand Down Expand Up @@ -1313,10 +1301,8 @@ impl<B, E, Block, RA> ProofProvider<Block> for Client<B, E, Block, RA> where
)?;

let state = self.state_at(id)?;
let header = self.prepare_environment_block(id)?;
prove_execution(
state,
header,
&self.executor,
method,
call_data,
Expand Down Expand Up @@ -1782,29 +1768,23 @@ impl<B, E, Block, RA> CallApiAt<Block> for Client<B, E, Block, RA> where
'a,
R: Encode + Decode + PartialEq,
NC: FnOnce() -> result::Result<R, sp_api::ApiError> + UnwindSafe,
C: CoreApi<Block>,
>(
&self,
params: CallApiAtParams<'a, Block, C, NC, B::State>,
params: CallApiAtParams<'a, Block, NC, B::State>,
) -> Result<NativeOrEncoded<R>, sp_api::ApiError> {
let core_api = params.core_api;
let at = params.at;

let (manager, extensions) = self.execution_extensions.manager_and_extensions(
at,
params.context,
);

self.executor.contextual_call::<_, fn(_,_) -> _,_,_>(
|| core_api
.initialize_block(at, &self.prepare_environment_block(at)?)
.map_err(Error::RuntimeApiError),
self.executor.contextual_call::<fn(_,_) -> _, _, _>(
at,
params.function,
&params.arguments,
params.overlayed_changes,
Some(params.storage_transaction_cache),
params.initialize_block,
manager,
params.native_call,
params.recorder,
Expand Down
Loading