Skip to content
This repository has been archived by the owner on Feb 27, 2023. It is now read-only.

Consider changing key bit traversal order to be prefix-based #20

Closed
adlerjohn opened this issue Feb 24, 2021 · 0 comments · Fixed by #22
Closed

Consider changing key bit traversal order to be prefix-based #20

adlerjohn opened this issue Feb 24, 2021 · 0 comments · Fixed by #22

Comments

@adlerjohn
Copy link
Member

adlerjohn commented Feb 24, 2021

Ref: the secondary change of celestiaorg/celestia-specs#129.

Currently, keys are traversed in a way that jumps between bits when looking at the key:

https://github.com/lazyledger/smt/blob/2b025d36fc57c4f0a008d49bb77fdf13c051b0cc/utils.go#L4

The reason is that arrays are ordered 0 to length-1 (left to right), while bits are ordered length-1 to 0 (left to right). As an example, consider the following 2-byte key. Byte indices are on the top and bit indices are on the bottom.

[     byte 0    ][     byte 1    ]
[7 6 5 4 3 2 1 0][7 6 5 4 3 2 1 0]

Here are the positions of different bit indices:

bit = 0
[     byte 0    ][     byte 1    ]
[7 6 5 4 3 2 1 0][7 6 5 4 3 2 1 0]
               ^
               this one!
bit = 1
[     byte 0    ][     byte 1    ]
[7 6 5 4 3 2 1 0][7 6 5 4 3 2 1 0]
             ^
             this one!
bit = 7
[     byte 0    ][     byte 1    ]
[7 6 5 4 3 2 1 0][7 6 5 4 3 2 1 0]
 ^
 this one!
bit = 8
[     byte 0    ][     byte 1    ]
[7 6 5 4 3 2 1 0][7 6 5 4 3 2 1 0]
                                ^
                                this one!

Now, a tree that traverses keys in this bit order can certainly be consistent with itself, but won't be intuitive to use and require non-standard verification logic. In terms of intuitiveness, consider two keys in binary representation: one starting with 0b0... and the other with 0b1.... You would expect the two keys to be on the left and right subtrees respectively from root. Currently, this is not the case: keys on the left subtree begin with 0bxxxxxxx0... and the right subtree 0bxxxxxxx1.... In other words, currently leaves are not actually ordered by key (if you interpret the 32-byte key as a big endian unsigned integer), which makes things confusing.

I propose we should instead traverse both bits and bytes in the same order, and ideally most-significant-first (i.e. most significant on the left). This change would be backwards incompatible.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant