Protocol
In theory, you are correct, the one dispute chunk could potentially be a generic design. In fact it was not a new one, I remembered hearing it first from @jjy when working on godwoken / polyjuice, where instead of bisecting, we use one CKB transaction to run EVM and validate a whole L2 transaction. I’m merely dusting up the old idea and reuse it for the games.
In practice, though, I really don’t want to build another generic protocol on CKB again. There are just too many protocol-designing experiences where we debated and (exhaustively) agreed to prioritize A, and live with B as a tradeoff. Later when we approach different teams building products in the ecosystem, they really just wanted C, and confronted us why B was given up. Eventually, protocols got de-prioritized or abandoned.
This happened a lot. I settled with myself that I just don’t have the superpower.. These days I only just build complete products first, maybe, when a few products are used, a common core can be extracted. But I’m not worried about it just yet.
Memory
First of all, I didn’t run into any memory issue porting Teeworlds, I have another game I’m working on that requires a re-design of data structures to fit in the 4MB limit, but still, the game design does not need more than 4MB, only the current implementation does. All the fixed-math / alpha-beta / libc tricks are utilized for cycle reduction, not for memory saving.
This might be counter-intuitive: 4MB is actually a lot. Notice the design requires a replayer that only contains the game core, stripping all of the graphics, sounding, networking states. When this is done and optimizations are applied, you’d be surprised that many games actually fit in the 4MB limit.
One thing worth calling out, is by default the templates used by CKB contract, is a little bit careless on memory layout. These days, the CKB contracts I built, almost exclusively used the following rules:
- Reorder stack & heap, so stack starts from 0 - 512K, code lives at 512K - 1M, then you have almost 3M memory for the heap. For a comparison, by default CKB’s template put code at the lower address, heap next, then stack starts from the highest address. Old convention is there is 1.2MB heap, and 1MB stack. Due to CKB having no MMU structure, you have to leave enough room so heap and stack do not overlap. The reorder design, on the other hand, signals error immediately when stack is all used up(due to overflow), allowing you to utilize all the 4MB memory as you need. I once tried pushing the stack reorder design to be the default, but I failed to get a consensus. Luckily, the flexibility of CKB enables me to do it without anyone’s approval. I can use up all the 3.5MB memory for game logics.
- I use musl-libc’s memory allocator. As I typically code in C / C++, this one is easier for me. The default buddy-alloc algorithm used in
ckb-std, while simple enough and fit normal use cases, can waste quite some memory. We are really better served with a two-level segregated fit allocator. I had my try but didn’t manage to make it the default in CKB.
I guess my use case is really rare enough in CKB, so my choices won’t yet be defaults, the point I want to make is, 4MB is not really that small, it’s still far from CKB being pushed to the limits.
That being said, there are indeed plans when 4MB is really not enough:
- When I initially designed CKB-VM, 4MB is only one choice made then, the plan was when memory is really an issue, there could be bigger VM instances such as 16MB, etc. You should pay higher cycles for bigger VMs, but such VM instances should be available. I don’t know current progress, though. The decision is now out of my hands.
- There is always a ZK path, verifiers are out, if you want bigger memory, you can just run a similar RISC-V program on SP1, and have the proof verified on CKB.
- There is always a different VM, I designed the games for a multi-VM multi-chain future, but let’s not expand this too far in CKB’s forum.