Another concern around using 350K Bitcoin's snapshot. As you're going to use Proof-of-Stake, and majority of Bitcoin holders will no participate in the Qeditas consensus from day 1, so generating balance will be low during early days. In this case, system could be overtaken by a big holder, history attack is also possible(you'll need to introduce checkpoints) etc.
I agree with the concern. I think if a single large bitcoin holder wants to overtake the network in the first few days, they are likely to succeed. The hope is that there are enough participants at different balance levels to prevent this, but it's a real danger.
As for checkpoints, I like the solution Nxt uses of not allowing reorganizations beyond N blocks and plan to use this in Qeditas. This makes the criteria "weakly subjective" in Vitalik Buterin's terminology, but realistically I think this is good enough. To be honest, I think even in a POW network like Bitcoin, if there were a reorganization beyond 24 hours there would likely be some kind of social (human) consensus very quickly to deny the reorganization. If I'm right about that, the criteria Bitcoin uses is not truly "objective."
How do you want to solve compact Merkle tree problems?
I'm still experimenting, but the idea is simple. The "real" tree is a sparsely populated binary tree of depth 162 with account assets at the leaves. Instead of holding the full compact tree in memory, I break it into several parts and save the different parts into files. (I could use a database, but I don't think I need one.) I can describe these "parts" as follows:
The top of the tree: from the root through the first 6 levels.
The midsections of the tree: from level 6 to level 14.
The bottom parts: the rest of the way to the leaves.
The numbers are a bit arbitrary, and there's actually a general data type that can be used to choose multiple ways of breaking the tree into parts. For simplicity, let's assume it's broken up as above.
A transaction mentions certain addresses. The leaves corresponding to those addresses are to be transformed. For this reason we need each "bottom part" that contains one of these leaves. We also need the particular midsections above those selected bottom parts. The top part is always needed. All these parts are loaded into memory to do the transformation. This should be a very small part of the tree in practice.
After the transformation in order to save the new (transformed) tree, only the new versions of the selected bottom parts, midsections and top part must be saved. The unselected parts are unchanged and we already have them saved in files.
Another side effect is that to calculate the hashroot of the full tree is very easy since it can start hashing from the tops of the midsections.
There are, of course, tradeoffs. On one extreme is not to break up the tree at all. In that case too much RAM is consumed and the operation of computing the hashroot takes too long (since every intermediate hash needs to be computed). On another extreme, every single node in the tree could be saved in files. I haven't tried this, but I think it would require too many file operations.
Does this sound reasonable? Do you know of some better techniques to handle this?
What's new in the 'qeditastheory' in comparison with the 'ledgertheory'?
I will answer this in another reply since it will be a bit longer.