Skip to content

Commit c120179

Browse files
authored
proof: Allow single child for the ephemeral node (#22)
The ephemeral node is the node that does not yet exist, and is therefore replaced by its "children". It can happen that there is only one "child" node representing the ephemeral node (i.e. when the subtree that it covers is perfect). If this is the case, we still want to expose this signal to the user of Proof type, which can then choose whether to treat this node as ephemeral or not.
1 parent 3d6af79 commit c120179

File tree

2 files changed

+24
-25
lines changed

2 files changed

+24
-25
lines changed

proof/proof.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -127,11 +127,10 @@ func nodes(index uint64, level uint, size uint64) Nodes {
127127
reverse(nodes[len(nodes)-left:])
128128

129129
// nodes[len1:len2] contains the nodes representing the ephemeral node. If
130-
// it's empty or only has one node, make it zero.
131-
//
132-
// TODO(pavelkalinnikov): Don't empty the single node case. It is still a
133-
// valuable info to expose.
134-
if len1+1 >= len2 {
130+
// it's empty, make it zero. Note that it can also contain a single node.
131+
// Depending on the preference of the layer above, it may or may not be
132+
// considered ephemeral.
133+
if len1 >= len2 {
135134
len1, len2 = 0, 0
136135
}
137136

proof/proof_test.go

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,9 @@ func TestInclusion(t *testing.T) {
6767

6868
// Small trees.
6969
{size: 1, index: 0, want: Nodes{IDs: []compact.NodeID{}}},
70-
{size: 2, index: 0, want: nodes(id(0, 1))}, // b
71-
{size: 2, index: 1, want: nodes(id(0, 0))}, // a
72-
{size: 3, index: 1, want: nodes(id(0, 0), id(0, 2))}, // a c
70+
{size: 2, index: 0, want: nodes(id(0, 1))}, // b
71+
{size: 2, index: 1, want: nodes(id(0, 0))}, // a
72+
{size: 3, index: 1, want: rehash(1, 2, id(0, 0), id(0, 2))}, // a c
7373

7474
// Tree of size 7.
7575
{size: 7, index: 0, want: rehash(2, 4, // l=hash(i,j)
@@ -80,15 +80,15 @@ func TestInclusion(t *testing.T) {
8080
id(0, 3), id(1, 0), id(0, 6), id(1, 2))}, // d g j i
8181
{size: 7, index: 3, want: rehash(2, 4, // l=hash(i,j)
8282
id(0, 2), id(1, 0), id(0, 6), id(1, 2))}, // c g j i
83-
{size: 7, index: 4, want: nodes(id(0, 5), id(0, 6), id(2, 0))}, // f j k
84-
{size: 7, index: 5, want: nodes(id(0, 4), id(0, 6), id(2, 0))}, // e j k
85-
{size: 7, index: 6, want: nodes(id(1, 2), id(2, 0))}, // i k
83+
{size: 7, index: 4, want: rehash(1, 2, id(0, 5), id(0, 6), id(2, 0))}, // f j k
84+
{size: 7, index: 5, want: rehash(1, 2, id(0, 4), id(0, 6), id(2, 0))}, // e j k
85+
{size: 7, index: 6, want: nodes(id(1, 2), id(2, 0))}, // i k
8686

8787
// Smaller trees within a bigger stored tree.
88-
{size: 4, index: 2, want: nodes(id(0, 3), id(1, 0))}, // d g
89-
{size: 5, index: 3, want: nodes(id(0, 2), id(1, 0), id(0, 4))}, // c g e
90-
{size: 6, index: 3, want: nodes(id(0, 2), id(1, 0), id(1, 2))}, // c g i
91-
{size: 6, index: 4, want: nodes(id(0, 5), id(2, 0))}, // f k
88+
{size: 4, index: 2, want: nodes(id(0, 3), id(1, 0))}, // d g
89+
{size: 5, index: 3, want: rehash(2, 3, id(0, 2), id(1, 0), id(0, 4))}, // c g e
90+
{size: 6, index: 3, want: rehash(2, 3, id(0, 2), id(1, 0), id(1, 2))}, // c g i
91+
{size: 6, index: 4, want: nodes(id(0, 5), id(2, 0))}, // f k
9292
{size: 7, index: 1, want: rehash(2, 4, // l=hash(i,j)
9393
id(0, 0), id(1, 1), id(0, 6), id(1, 2))}, // a h j i
9494
{size: 7, index: 3, want: rehash(2, 4, // l=hash(i,j)
@@ -169,18 +169,18 @@ func TestConsistency(t *testing.T) {
169169
{size1: 5, size2: 0, wantErr: true},
170170
{size1: 9, size2: 8, wantErr: true},
171171

172-
{size1: 1, size2: 2, want: nodes(id(0, 1))}, // b
173-
{size1: 1, size2: 4, want: nodes(id(0, 1), id(1, 1))}, // b h
174-
{size1: 1, size2: 6, want: nodes(id(0, 1), id(1, 1), id(1, 2))}, // b h i
175-
{size1: 2, size2: 3, want: nodes(id(0, 2))}, // c
176-
{size1: 2, size2: 8, want: nodes(id(1, 1), id(2, 1))}, // h l
172+
{size1: 1, size2: 2, want: nodes(id(0, 1))}, // b
173+
{size1: 1, size2: 4, want: nodes(id(0, 1), id(1, 1))}, // b h
174+
{size1: 1, size2: 6, want: rehash(2, 3, id(0, 1), id(1, 1), id(1, 2))}, // b h i
175+
{size1: 2, size2: 3, want: rehash(0, 1, id(0, 2))}, // c
176+
{size1: 2, size2: 8, want: nodes(id(1, 1), id(2, 1))}, // h l
177177
{size1: 3, size2: 7, want: rehash(3, 5, // l=hash(i,j)
178178
id(0, 2), id(0, 3), id(1, 0), id(0, 6), id(1, 2))}, // c d g j i
179179
{size1: 4, size2: 7, want: rehash(0, 2, // l=hash(i,j)
180180
id(0, 6), id(1, 2))}, // j i
181-
{size1: 5, size2: 7, want: nodes(
181+
{size1: 5, size2: 7, want: rehash(2, 3,
182182
id(0, 4), id(0, 5), id(0, 6), id(2, 0))}, // e f j k
183-
{size1: 6, size2: 7, want: nodes(
183+
{size1: 6, size2: 7, want: rehash(1, 2,
184184
id(1, 2), id(0, 6), id(2, 0))}, // i j k
185185
{size1: 7, size2: 8, want: nodes(
186186
id(0, 6), id(0, 7), id(1, 2), id(2, 0))}, // j leaf#7 i k
@@ -196,11 +196,11 @@ func TestConsistency(t *testing.T) {
196196

197197
// Smaller trees within a bigger stored tree.
198198
{size1: 2, size2: 4, want: nodes(id(1, 1))}, // h
199-
{size1: 3, size2: 5, want: nodes(
199+
{size1: 3, size2: 5, want: rehash(3, 4,
200200
id(0, 2), id(0, 3), id(1, 0), id(0, 4))}, // c d g e
201-
{size1: 3, size2: 6, want: nodes(
201+
{size1: 3, size2: 6, want: rehash(3, 4,
202202
id(0, 2), id(0, 3), id(1, 0), id(1, 2))}, // c d g i
203-
{size1: 4, size2: 6, want: nodes(id(1, 2))}, // i
203+
{size1: 4, size2: 6, want: rehash(0, 1, id(1, 2))}, // i
204204
{size1: 1, size2: 7, want: rehash(2, 4, // l=hash(i,j)
205205
id(0, 1), id(1, 1), id(0, 6), id(1, 2))}, // b h j i
206206

0 commit comments

Comments
 (0)