Skip to content

Block Hooks

Blocks hooks are functions (Similar to State transition functions) that are automatically executed before or after the execution of all the actions on the block as per configuration. Hooks are executed once per block and a representation of the same is stored in Block Headers for verification later.

Hooks in Stackr

Our SDK provides a way to create execution hooks for the blocks.

A basic hook in Stackr looks like this:

hooks.ts
import { Hook, Hooks } from "@stackr/sdk/machine";
import { CounterState } from "./state";
 
const addTwo = CounterState.Hook({
  handler: ({ state }) => {
    state += 2;
    return state;
  },
});
 
// a hook can also be written in this manner
const minusTwo: Hook<CounterState> = {
  handler: ({ state }) => {
    state -= 2;
    return state;
  },
};
 
export const hooks: Hooks<CounterState> = {
  addTwo,
  minusTwo,
};

In the above example, we have two hooks addTwo and minusTwo. These hooks have a handler, and they take in current state, applies the hook logic & return the new state.

Hooks in Detail

The most important part of the Hooks is the handler function. This function only has access to the current state & the blockInfo height, timestamp & parentHash. Like State Transition Functions, they should be pure functions too & should return the new state after the applying the logic.

Defining the Hooks for MicroRollup

To configure these hooks, hooks has to be passed in StateMachine & then pre & post hooks can be defined as follows on the MircoRollup :

mru.ts
const mru = await MicroRollup({
  config: stackrConfig,
  stateMachines: [machine],
  blockHooks: { 
    pre: ["addTwo"], 
    post: ["minusTwo"], 
  },
});

In this case, we call addTwo before and minusTwo after the block is executed. Mutliple hooks can be added for both of the triggers by just passing the hook name as string in the array.

Variables available inside a block hook

There are 3 special variables which always exist inside the handler of a block hook. These can be used by the developer to write the logic of a block hook:

  1. state
  2. block
    • block.height
    • block.timestamp
    • block.parentHash
  3. emit
hooks.ts
// Without Destructuring
const superCoolBlockHook = CounterState.Hook({
  handler: (props) => {
    const state = props.
block
emit
state
const height = props.block.
height
parentHash
timestamp
}, }); // With Destructuring const anotherSuperCoolBlockHook = CounterState.Hook({ handler: ({ s
state
}) => {
}, });

State

  1. state : The entire current state of the state machine in wrapped format. This is the state that the block hook is supposed to modify.

Block Properties

A block object containing the current block height, timestamp and the parent block's hash is passed as an argument to the hook. These can be used to generate pseudo-random numbers or to implement time-based logic.

  1. block.height : The height of the block.

  2. block.timestamp : The timestamp of the block.

  3. block.parentHash : The hash of the parent block of the block.

Custom Execution Logs

The emit variable passed to a hook is a method that can be used to record custom execution logs (later accessible at block.hooksLogs).

Example usage:

hooks.ts
const checkEven = CounterState.Hook({
  handler: ({ state, emit }) => {
    if (state % 2 === 0) {
      emit({ name: "is_even", value: state });
    }
    return state;
  },
});