Recently, I am working on the prototype of the generic payment channel (GPC). But I find the current model is not completely generic. For example, if the implementation of the payment channel contract in ethereum follows the ERC20 standard, any token that complies with the ERC20 standard can create channel each other. But it is impossible in current GPC implementation because one cell can only store one typescript. To achieve perfect composability, I have two ways to go.
- Multiple gpc outputs.
- A brand new typescript can store many typescripts.
For me, the first one is ugly, because the transaction about gpc will be swollen. If you have 100 types of assets, you need 100 outputs. So I try to explore the possibility to fuse different typescripts into one. One possible solution is creating another special typescript called collector.
The structure of the output_data of collector is shown above. In a cell, only output_data and typescript is related to type, so we only need to record them. With such a structure, we can merge different typescripts into one single output_data. Then, collector should guarantee the data keep consistent until these types are return to their typescripts correspondingly. That all it needs to do. Let me explain it more precisely. There are three cases.
- collector is only in outputs: It checks whether the aggregate of input type is equal to the output_data of collector.
- collector are both in inputs and outputs: It should check the output_data in inputs and outputs are consistent.
- collector is only in the inputs: It checks all the hashes in output_data of collector appear in the output. This rule ensures no asset will burn out. The typescript about assets in outputs will take the responsibility of validating the output_data by their ways.
Nevertheless, we can easily see there are two drawbacks.
Firstly, we need to persuade all contract developers to treat collector as an exception. More specifically, they should believe the output_data from collector about their typescripts are legal. So collector is allowed to “burn” (store) and “create” (release) their tokens (output_data).
Secondly, the collector is exclusive, in outputs at least. That is, if there is a collector in outputs, the existence of any other typescript in outputs should cause failure during the validation of collector. The rationale is simple. For example, I have 100 UDT1 and 50 UDT2, and I want to fuse 50 UDT1 and 50 UDT2. So I will have a change with 50 UDT1. In this case, if we want collector to recognize the change output and calculate 50 + 50 = 100. We should update its code to teach it how to parse and calculate UDT1. However, it will cause a huge body of code because every time you create a new type, we should update the code. Also, frequent updates will undoubtedly reduce users’ trust in the security of the contract.
That is my idea about the composability of type in ckb, I hope it can become something like TYPEID in current ckb. Of course, it is still naive and may have some errors. I would appreciate it if you have any comments.