链下功能
总览
很多时候我们需要先对链下的数据作查询或处理,然后才将其提交到链上。 常规的做法是通过预言机(Oracles)。 预言机是一种外部服务,通常用于监听区块链事件,并根据条件触发任务。 当这些任务执行完毕,执行结果会以交易的形式提交至区块链上。 虽然这种方法可行,但在安全性、可扩展性,和基本效率方面仍然存在一些缺陷。
To make the off-chain data integration secure and more efficient, Substrate provides off-chain features:
Off-Chain Worker (OCW) subsystem allows execution of long-running and possibly non- deterministic tasks (e.g. web requests, encryption/decryption and signing of data, random number generation, CPU-intensive computations, enumeration/aggregation of on-chain data, etc.) that could otherwise require longer than the block execution time.
Off-Chain Storage offers storage that is local to a Substrate node that can be accessed both by off-chain workers (both read and write access) and on-chain logic (write access via off-chain indexing but not read access). This is great for different worker threads to communicate to each others and for storing user- / node-specific data that does not require consensus over the whole network.
Off-Chain Indexing allows the runtime, if opted-in, to write directly to the off-chain storage independently from OCWs. This serves as a local/temporary storage for on-chain logic and complement to its on-chain state.
Off-chain features run in their own Wasm execution environment outside of the Substrate runtime. This separation of concerns makes sure that block production is not impacted by long-running off-chain tasks. However, as the off-chain features are declared in the same code as the runtime, they can easily access on-chain state for their computations.
链下工作机
Off-chain workers have access to extended APIs for communicating with the external world:
- Ability to submit transactions (either signed or unsigned) to the chain to publish computation results.
- 一个功能齐全的 HTTP 客户端,使链下工作机可访问和获取到外部数据。
- 访问本地密钥库以签署和验证声明(statements)或交易。
- An additional, local key-value database shared between all off-chain workers.
- 一个安全的本地熵源(entropy),用于生成随机数。
- Access to the node's precise local time.
- The ability to sleep and resume work.
OCWs can be initiated from within a special function in your runtime implementation, fn offchain_worker(block: T::BlockNumber)
. communicate results back to the chain, off-chain workers can submit signed or unsigned transactions to be included in subsequent blocks.
值得注意的是,链下工作机的交易不会受到常规交易验证的约束。 所以需要另外实现一套交易验证机制 (例如投票,取平均值,检查提交人签名或简单地 "信任"),以确定哪些信息能够记录在链上。
想要了解更多如何在你下一个 runtime 开发项目中使用到链下工作机,请参考我们的 开发指南。
Off-Chain Storage
As its name indicated, the storage is not stored on-chain. It can be accessed by off-chain worker threads (both read and write access) and on-chain logic (write only, refer to off-chain indexing below). This storage is not populated among the blockchain network and does not need to have consensus computation over it.
As an off-chain worker thread is being spawned off during each block import, there could be more than one off-chain worker thread running at any given time. So, similar to any multi-threaded programming environment, there are also utilities to mutex lock the storage when accessing them for data consistency.
Off-chain storage serves as a bridge for various off-chain worker threads to communicate to each others and between off-chain and on-chain logics. It can also be read using remote procedure calls (RPC) so it fits the use case of storing indefinitely growing data without over-consuming the on-chain storage.
Off-Chain Indexing
Storage in the context of blockchain is mostly about on-chain state. But it is expensive (as it is populated to each node in the network) and not recommended for historical or user-generated data which grow indefinitely over time.
We have off-chain storage for this purpose. In addition of being accessible by OCWs, Substrate also includes a feature called "off-chain indexing" allowing the runtime to write directly to the off-chain storage independently from OCWs. Nodes have to opt-in for persistency of this data via --enable-offchain-indexing
flag when starting up the Substrate node.
Unlike OCWs, which are not executed during initial blockchain synchronization, off-chain indexing is populating the storage every time a block is processed, so the data is always consistent and will be exactly the same for every node with indexing enabled.