What is Type Id
Type Id is a digest of a unique type script.
The unique type script consists of three parts:
1 | code_hash: type id contract code hash |
The uniqueness of the generated type script is guaranteed by the type id contract
and hash(this_transaction.input[0]) | output_index_of_this_cell
since
No man ever steps in the same river twice, for it’s not the same river and he’s not the same man.
The type id contract
checks if the unique_type_script.args
matches the deployment_transaction.inputs[0]
. Once it’s deployed on the chain successfully, the deployment_transaction.inputs[0]
cannot be used to deploy the same unique type script
again since it’s comsumed, like the water gone, i.e. the unique_type_script.args
cannot be used to deploy again and the uniqueness of the unique type script
is promised.
Why Type Id is Important
The contract cell, i.e. the cell dep referenced in a transaction, is upgradable when it’s located via its type script. By deploying a new cell with new contract code but having the same type script as the deprecated one, it can be indexed by the same [code_hash, hash_type]
conditions.
graph LR id1[code_hash: hash_a, hash_type: type]-->|OutPoint of Deprecated Cell|id2[Deprecated Contract] id1[code_hash: hash_a, hash_type: type]-->|OutPoint of Latest Deployed Cell|id3[Latest Deploayed Contract]
By this way, an attacker can deploy a malicious contract with the same type script of the targeted contract to bypass script validation and confuse users.
graph LR id1[code_hash: hash_a, hash_type: type]-->|OutPoint of Deprecated Cell|id2[Deprecated Contract] id1[code_hash: hash_a, hash_type: type]-->|OutPoint of Latest Deployed Cell|id3[Latest Deploayed Contract] id1[code_hash: hash_a, hash_type: type]-->|OutPoint of Malicious Cell|id3[Malicious Contract]
An exclusive type script is necessary in this mode.
How to Create a Unique Type Script
There are 4 rules to deploy an unique type script(with unique args
)
Count how many output cells use current type script, if there’re more than one cell with current type script, throw an error since an attacker is trying to create more than one cells with the same type script, which is not expected.
Count how many input cells use current type script, if there’s only one input cell with the current type script, return success.
Use CKB Syscall to read the first input’s OutPoint in the current transaction and if it matches the
args
field of the type script, return success.- Since the first input can only be comsumed once, its unique OutPoint guarantees the uniqueness of the type script.
- An attacker cannot use the same
args
to deploy the type script since the unique cell has been consumed.
Otherwise throw an error.
Get Unique Type Id
Simply hash the type script
1 | hash([codeHash, hashType, args]) | output_index |
Resolve Scripts in CKB Transaction via Type Id
Since Type Script is used, the contract depends on it has hash type = type
.
In this case, the ckb vm loops all cell deps and try to find a dep whose type script has the corresponding hash(type script)
.
Once a cell dep meeting the condition is found, it’s used as the dependency of the contract.
Appendix
The type id contract
can be implemented in CKB VM, but now it exists in CKB node as a system script and can be referenced by a special code hash, ascii code in hex of the text TYPE_ID
1 | 0x00000000000000000000000000000000000000000000000000545950455f4944 |