Runtime
Runtime is the first modular component of the app-chain, containing all the business logic of the application itself. Business logic is implemented as runtime modules, defining the runtime state and runtime methods of each module. Runtime modules can be composed together to create a runtime that suits the needs of the application.
Runtime methods are functions callable by user’s transactions, responsible for reading and writing to the state - with accordance to their inner business logic implementation. Each runtime module can define it’s own state (storage), which can be of two types: state and state map.
Runtime module
Protokit provides runtime modules out of the box via the
@proto-kit/librarypackage. For example, if your chain needs to work with balances, you can extend theBalancesclass provided by the library, or implement your own runtime module from scratch.
The Balances runtime module from @proto-kit/library defines its storage as a ledger of type state map, storing key-value pairings between public keys and balances.
It provides methods callable by users via transactions, such as transfer, mint, and burn. The transfer method reads the ledger,
checks if the sender has sufficient balance, and if so, updates the ledger accordingly.
Behind the scenes every interaction with the state produces a state transition. Runtime does not apply any state transitions to the merkle tree itself, this allows us to keep the runtime circuits as simple as possible. As a result we can achieve adequate proof parallelization between business logic and state transition circuits.
Soft-failing runtime methods
In order to ensure provability of both successful and failing transactions, we can’t fail the proof generation forcefully using built in O1JS assertions (e.g. assertEquals).
As an alternative way to soft-fail runtime method execution, we provide a custom assert function that keeps track of the assertion failures and returns them as a part of the runtime method result - as a boolean status.
Runtime module interoperability
Runtime modules within the same runtime are aware of each other, allowing them to call each other’s methods and reach each other’s state.
Calling a method of runtime module B, from within a runtime module A would result in the appropriate state transitions within each respective module. This allows for a modular approach to building your runtime, where each module can be developed and tested in isolation.