Here’s the change in construction that allows replacing 2-bit counters by single-bit counters:
Instead of adjacent edges sharing an endpoint in the Cuckoo Graph, we require the two endpoints to differ in the last bit only.
This is a minimal change in the verification function, we replace
line 66 of cuckoo.c
if (uvs[k] == uvs[i]) { // find other edge endpoint identical to one at i
by
if (uvs[k]>>1 == uvs[i]>>1) { // find other edge endpoint matching one at i
and line 72
if (j == i) return POW_DEAD_END; // no matching endpoint
by
if (j == i || uvs[j] == uvs[i]) return POW_DEAD_END; // no matching endpoint
We also need to replace line 52
node_t xor0 = 0, xor1 =0;
by
node_t xor0, xor1;
xor0 = xor1 = (PROOFSIZE/2) & 1;
to fix early detection of bogus solutions. This has no effect on the distribution of cycle lengths in random graphs; a random endpoint is as likely to match another as it is to differ in the last bit only.
With this change, lean mining only needs a node bitmap to record whether it has any edge adjacent to it.
An edge then survives if the bit for its endpoint^1 is set.
Thus, a graph with 2^n edges will require 2^n bits of SRAM for full speed. It makes more sense to use this n in the name of the PoW.
Let’s call this new version Cuckatoo Cycle.
)/_
<' \
/) )
/'-""
We will then denote by cuckatoo32 the problem with 2^32 edges
needing 2^32 bits of SRAM for full speed.
Compare with cuckoo32 that only has 2^31 edges but similarly needed 2^32 bits of SRAM (or 4/5 of that with trit packing).
So I propose that Grin uses cuckatoo32+ as main PoW instead of cuckoo32+.