VM Selection
When writing a Script, it is important to understand how the Script will be executed under a specific CKB-VM version. The CKB network has introduced various CKB-VM versions over time to enhance security, performance, bug fixes and support for new RISC-V extensions. However, the upgrade should not break the old code, and users must have the opt-in option to specify the VM version.
This article explains the general mechanism that determines how a CKB node chooses the appropriate CKB-VM version for a transaction Script group, based on RPC-32.
How It Works
In CKB, each VM version has its bundled instruction set, syscalls and cost model.
During a CKB hard fork, a specific activation epoch is determined through community consensus. Typically, transactions in blocks before the activation epoch are verified using the previous CKB-VM version.
Once the fork is activated, CKB nodes determine the CKB-VM version for each Script group based on the hash_type
field in the Script Structure. The allowed values for hash_type
are 0, 1, 2 and 4. Cells with different hash_type
are grouped separately.
hash_type | JSON Representation | Matched by | VM Version |
---|---|---|---|
0 | “data” | Data hash (blake2b) | 0 |
1 | “type” | Type Script hash | 2 |
2 | “data1” | Data hash (blake2b) | 1 |
4 | “data2” | Data hash (blake2b) | 2 |
The hash_type
encoding pattern ensures that if a Script matches code via type hash
, CKB always uses the latest available VM version at the time the Script is executed. In contrast, if the Script matches code via data hash
, the VM version is determined by the designated value.
Cell callers can trade off between the determination and VM performance boost when calling the Cell. They should use data hash
for determination, and type hash
for the latest VM features.
For a deeper comparison of these two approaches, see Data Hash vs. Type Hash.
Although CKB provides this level of flexibility, each CKB-VM version may have its own known issues.
Before finalizing your choice of VM version, review the VM Known Issues to understand any potential risks.
Rationale
Several solutions were discussed for VM version selection, but the current approach balances flexibility and determinism. Here are some of the alternatives and their drawbacks:
- Always use the latest VM version: While straightforward, this approach would remove user control over version selections, making transaction executions non-deterministic as it will depend on the chain state.
- Depend on the Script code Cell epoch: This approach would use the old VM version for code Cells deployed before the fork and the new one for later deployments. However, anyone could redeploy the Cell and force transactions to use a different VM version using a new code Cell, which reduces determinism.
Backward compatibility
For Scripts referencing code via data hash
, the VM version remains consistent before and after a hard fork. In contrast, Scripts referencing code via type hash
will use different VM versions.
DApps developers must ensure the compatibility of their Scripts and upgrade them if necessary. By carefully selecting the appropriate hash_type
and understanding its implications, developers can build robust dApps on CKB while leveraging the flexibility of VM version management.
Security Measures for VM Issues
When bugs are discovered in specific VM versions that could affect public interests, the Layer 1 maintainer team may implement protective measures at higher layers (such as in the mempool) to intercept potentially problematic transactions.
It's important to note that these measures are not consensus-level modifications and do not violate the principle of VM selection rights. Users retain the ability to construct transactions and include them in blocks themselves, bypassing these protective measures if they choose to do so.
This approach maintains the balance between network security and user autonomy, ensuring that while the network can protect against known vulnerabilities, users still have ultimate control over their transaction execution choices.