2

Every Substrate runtime implements several Runtime APIs. Two essential ones are the Core and BlockBuilder APIs.

The Core API is for executing blocks, a task that will be performed by all nodes. A simplification of its definition is as follows:

pub trait Core {
  fn initialize_block(header: &Header);

  fn execute_block(block: Block);

  // Less relevant functions elided
}

The BlockBuilder API is for constructing blocks, a task that only a validator or miner would perform. To summarize its definition:

pub trait BlockBuilder: Core {
  fn apply_extrinsic(extrinsic: Extrinsic) -> ApplyExtrinsicResult;

  fn finalize_block() -> Header;

  // Less relevant functions elided
}

It seems to me that building a block should involve initializing, applying several extrinsics, and then finalizing. It also seems natural that executing an already built block should be a single task with any initialization being part of the execution.

This is the approach taken by the rust-blockchain project

Cumulus also seems to take this approach for validating parachain blocks with its single validate_block function.

Finally, even Substrate hints at this design with its requirement trait BlockBuilder: Core

So why does Substrate include initialize_block along with the Core API?

1 Answer 1

3

These are historical reasons. As I implemented the runtime api in the current form as traits, we always called initialize_block before every runtime api function call. Thus, I moved the call to the Core api. We removed this requirement on calling initialize_block for every runtime api function call and now it would make more sense to move it to the BlockBuilder api.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.