Skip to content

Commit

Permalink
fix stateless proof
Browse files Browse the repository at this point in the history
  • Loading branch information
weiihann committed Jan 3, 2025
1 parent fe3e25c commit dd87e7f
Show file tree
Hide file tree
Showing 14 changed files with 306 additions and 161 deletions.
6 changes: 3 additions & 3 deletions empty.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func (Empty) Get([]byte, StatePeriod, NodeResolverFn) ([]byte, error) {
return nil, nil
}

func (Empty) Revive(Stem, [][]byte, StatePeriod, StatePeriod, NodeResolverFn) error {
func (Empty) Revive(Stem, [][]byte, StatePeriod, StatePeriod, bool, NodeResolverFn) error {
return errors.New("cannot revive an empty node")
}

Expand All @@ -57,8 +57,8 @@ func (Empty) Commitment() *Point {
return &id
}

func (Empty) GetProofItems(keylist, NodeResolverFn) (*ProofElements, []byte, []Stem, error) {
return nil, nil, nil, errors.New("trying to produce a commitment for an empty subtree")
func (Empty) GetProofItems(keylist, NodeResolverFn, StatePeriod) (*ProofElements, []byte, []Stem, []StatePeriod, error) {
return nil, nil, nil, nil, errors.New("trying to produce a commitment for an empty subtree")
}

func (Empty) Serialize() ([]byte, error) {
Expand Down
2 changes: 1 addition & 1 deletion empty_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func TestEmptyFuncs(t *testing.T) {
t.Fatal("commitment and commit mismatch")
}

if _, _, _, err := e.GetProofItems(nil, nil); err == nil {
if _, _, _, _, err := e.GetProofItems(nil, nil, period0); err == nil {
t.Fatal("get proof items should error")
}

Expand Down
6 changes: 3 additions & 3 deletions expired_leaf.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ func (n *ExpiredLeafNode) Get([]byte, StatePeriod, NodeResolverFn) ([]byte, erro
return nil, errExpired
}

func (n *ExpiredLeafNode) Revive(Stem, [][]byte, StatePeriod, StatePeriod, NodeResolverFn) error {
func (n *ExpiredLeafNode) Revive(Stem, [][]byte, StatePeriod, StatePeriod, bool, NodeResolverFn) error {
return errors.New("cannot revive an expired leaf node directly")
}

Expand All @@ -69,7 +69,7 @@ func (n *ExpiredLeafNode) Commitment() *Point {
return n.commitment
}

func (n *ExpiredLeafNode) GetProofItems(keys keylist, resolver NodeResolverFn) (*ProofElements, []byte, []Stem, error) {
func (n *ExpiredLeafNode) GetProofItems(keys keylist, resolver NodeResolverFn, _ StatePeriod) (*ProofElements, []byte, []Stem, []StatePeriod, error) {
var (
pe = &ProofElements{
Vals: make([][]byte, len(keys)),
Expand All @@ -87,7 +87,7 @@ func (n *ExpiredLeafNode) GetProofItems(keys keylist, resolver NodeResolverFn) (
poass = append(poass, n.stem)
}

return pe, esses, poass, nil
return pe, esses, poass, []StatePeriod{n.lastPeriod}, nil
}

func (n *ExpiredLeafNode) Serialize() ([]byte, error) {
Expand Down
151 changes: 127 additions & 24 deletions expired_tree_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ func TestInsertSameLeafNoExpired(t *testing.T) {
t.Parallel()

root := New()
if err := root.Insert(zeroKeyTest, testValue, 0, nil); err != nil {
if err := root.Insert(zeroKeyTest, testValue, period0, nil); err != nil {
t.Fatalf("error inserting: %v", err)
}

if err := root.Insert(oneKeyTest, testValue, 1, nil); err != nil {
if err := root.Insert(oneKeyTest, testValue, period1, nil); err != nil {
t.Fatalf("error inserting: %v", err)
}

Expand All @@ -31,7 +31,7 @@ func TestInsertSameLeafNoExpired(t *testing.T) {
t.Fatalf("expected value %x, got %x", testValue, leaf.values[oneKeyTest[StemSize]])
}

if leaf.lastPeriod != 1 {
if leaf.lastPeriod != period1 {
t.Fatalf("expected last accessed to be 1, got %d", leaf.lastPeriod)
}
}
Expand All @@ -40,11 +40,11 @@ func TestInsertSameLeafExpired(t *testing.T) {
t.Parallel()

root := New()
if err := root.Insert(zeroKeyTest, testValue, 0, nil); err != nil {
if err := root.Insert(zeroKeyTest, testValue, period0, nil); err != nil {
t.Fatalf("error inserting: %v", err)
}

err := root.Insert(oneKeyTest, testValue, 2, nil)
err := root.Insert(oneKeyTest, testValue, period2, nil)
if !errors.Is(err, errExpired) {
t.Fatalf("expected period expired error when inserting, got %v", err)
}
Expand All @@ -58,7 +58,7 @@ func TestInsertSameLeafExpired(t *testing.T) {
t.Fatalf("expected value %x, got %x", testValue, leaf.values[zeroKeyTest[StemSize]])
}

if leaf.lastPeriod != 0 {
if leaf.lastPeriod != period0 {
t.Fatalf("expected last accessed to be 0, got %d", leaf.lastPeriod)
}
}
Expand All @@ -67,11 +67,11 @@ func TestInsertDiffLeaf(t *testing.T) {
t.Parallel()

root := New()
if err := root.Insert(zeroKeyTest, testValue, 0, nil); err != nil {
if err := root.Insert(zeroKeyTest, testValue, period0, nil); err != nil {
t.Fatalf("error inserting: %v", err)
}

if err := root.Insert(ffx32KeyTest, testValue, 2, nil); err != nil {
if err := root.Insert(ffx32KeyTest, testValue, period2, nil); err != nil {
t.Fatalf("error inserting: %v", err)
}

Expand All @@ -93,24 +93,63 @@ func TestInsertDiffLeaf(t *testing.T) {
t.Fatalf("expected value %x, got %x", testValue, leaff.values[ffx32KeyTest[StemSize]])
}

if leaf0.lastPeriod != 0 {
if leaf0.lastPeriod != period0 {
t.Fatalf("expected last accessed to be 0, got %d", leaf0.lastPeriod)
}

if leaff.lastPeriod != 2 {
if leaff.lastPeriod != period2 {
t.Fatalf("expected last accessed to be 2, got %d", leaff.lastPeriod)
}
}

func TestInsertExpiredLeafSibling(t *testing.T) {
t.Parallel()

root := New()
if err := root.Insert(zeroKeyTest, testValue, period0, nil); err != nil {
t.Fatalf("error inserting: %v", err)
}

leaf, ok := root.(*InternalNode).children[0].(*LeafNode)
if !ok {
t.Fatalf("expected leaf node, got %T", root.(*InternalNode).children[0])
}

root.(*InternalNode).children[0] = NewExpiredLeafNode(leaf.stem, leaf.lastPeriod, leaf.commitment)

if err := root.Insert(forkOneKeyTest, testValue, period2, nil); err != nil {
t.Fatalf("error inserting: %v", err)
}

c1 := root.Commit()

// Reconstruct a new tree with the same key-values but without the expired leaf node
root2 := New()
if err := root2.Insert(zeroKeyTest, testValue, period0, nil); err != nil {
t.Fatalf("error inserting: %v", err)
}

if err := root2.Insert(forkOneKeyTest, testValue, period2, nil); err != nil {
t.Fatalf("error inserting: %v", err)
}

c2 := root2.Commit()

// The two trees should have the same commitment
if !c1.Equal(c2) {
t.Fatalf("expected commitment to be %x, got %x", c1, c2)
}
}

func TestGetNoExpired(t *testing.T) {
t.Parallel()

root := New()
if err := root.Insert(zeroKeyTest, testValue, 0, nil); err != nil {
if err := root.Insert(zeroKeyTest, testValue, period0, nil); err != nil {
t.Fatalf("error inserting: %v", err)
}

val, err := root.Get(zeroKeyTest, 1, nil)
val, err := root.Get(zeroKeyTest, period1, nil)
if err != nil {
t.Fatalf("error getting: %v", err)
}
Expand All @@ -124,7 +163,7 @@ func TestGetNoExpired(t *testing.T) {
t.Fatalf("expected value %x, got %x", testValue, val)
}

if leaf.lastPeriod != 0 {
if leaf.lastPeriod != period0 {
t.Fatalf("expected last accessed to be 0, got %d", leaf.lastPeriod)
}
}
Expand All @@ -133,11 +172,11 @@ func TestGetExpired(t *testing.T) {
t.Parallel()

root := New()
if err := root.Insert(zeroKeyTest, testValue, 0, nil); err != nil {
if err := root.Insert(zeroKeyTest, testValue, period0, nil); err != nil {
t.Fatalf("error inserting: %v", err)
}

val, err := root.Get(zeroKeyTest, 2, nil)
val, err := root.Get(zeroKeyTest, period2, nil)
if !errors.Is(err, errExpired) {
t.Fatalf("expected period expired error when getting, got %v", err)
}
Expand All @@ -151,7 +190,7 @@ func TestGetExpired(t *testing.T) {
t.Fatalf("expected leaf node, got %T", root.(*InternalNode).children[0])
}

if leaf.lastPeriod != 0 {
if leaf.lastPeriod != period0 {
t.Fatalf("expected last accessed to be 0, got %d", leaf.lastPeriod)
}
}
Expand All @@ -160,11 +199,11 @@ func TestDelLeafNoExpired(t *testing.T) {
t.Parallel()

root := New()
if err := root.Insert(zeroKeyTest, testValue, 0, nil); err != nil {
if err := root.Insert(zeroKeyTest, testValue, period0, nil); err != nil {
t.Fatalf("error inserting: %v", err)
}

if _, err := root.Delete(zeroKeyTest, 1, nil); err != nil {
if _, err := root.Delete(zeroKeyTest, period1, nil); err != nil {
t.Fatalf("error deleting: %v", err)
}

Expand All @@ -178,11 +217,11 @@ func TestDelLeafExpired(t *testing.T) {
t.Parallel()

root := New()
if err := root.Insert(zeroKeyTest, testValue, 0, nil); err != nil {
if err := root.Insert(zeroKeyTest, testValue, period0, nil); err != nil {
t.Fatalf("error inserting: %v", err)
}

_, err := root.Delete(zeroKeyTest, 2, nil)
_, err := root.Delete(zeroKeyTest, period2, nil)
if !errors.Is(err, errExpired) {
t.Fatalf("expected period expired error when deleting, got %v", err)
}
Expand All @@ -192,16 +231,80 @@ func TestDelLeafExpired(t *testing.T) {
t.Fatalf("expected empty node, got %T", root.(*InternalNode).children[0])
}

if leaf.lastPeriod != 0 {
if leaf.lastPeriod != period0 {
t.Fatalf("expected last accessed to be 0, got %d", leaf.lastPeriod)
}
}

func TestReviveExpired(t *testing.T) {
t.Parallel()

root := New()
if err := root.Insert(zeroKeyTest, testValue, period0, nil); err != nil {
t.Fatalf("error inserting: %v", err)
}

leaf, ok := root.(*InternalNode).children[0].(*LeafNode)
if !ok {
t.Fatalf("expected leaf node, got %T", root.(*InternalNode).children[0])
}

expiredLeaf := NewExpiredLeafNode(leaf.stem, leaf.lastPeriod, leaf.commitment)
root.(*InternalNode).children[0] = expiredLeaf

if err := root.Revive(leaf.stem, leaf.values, leaf.lastPeriod, period2, false, nil); err != nil {
t.Fatalf("error reviving: %v", err)
}

rLeaf, ok := root.(*InternalNode).children[0].(*LeafNode)
if !ok {
t.Fatalf("expected leaf node, got %T", root.(*InternalNode).children[0])
}

if rLeaf.lastPeriod != period2 {
t.Fatalf("expected last accessed to be 2, got %d", rLeaf.lastPeriod)
}
}

func TestReviveNoExpired(t *testing.T) {
t.Parallel()

root := New()
if err := root.Insert(zeroKeyTest, testValue, period0, nil); err != nil {
t.Fatalf("error inserting: %v", err)
}

leaf, ok := root.(*InternalNode).children[0].(*LeafNode)
if !ok {
t.Fatalf("expected leaf node, got %T", root.(*InternalNode).children[0])
}

comm := root.Commit()

if err := root.Revive(leaf.stem, leaf.values, leaf.lastPeriod, period0, false, nil); err != nil {
t.Fatalf("error reviving: %v", err)
}

rLeaf, ok := root.(*InternalNode).children[0].(*LeafNode)
if !ok {
t.Fatalf("expected leaf node, got %T", root.(*InternalNode).children[0])
}

if rLeaf.lastPeriod != period0 {
t.Fatalf("expected last accessed to be 0, got %d", rLeaf.lastPeriod)
}

rComm := root.Commit()
if !rComm.Equal(comm) {
t.Fatalf("expected commitment to be %x, got %x", comm, rComm)
}
}

func TestRootCommitExpired(t *testing.T) {
t.Parallel()

root := New()
if err := root.Insert(zeroKeyTest, testValue, 0, nil); err != nil {
if err := root.Insert(zeroKeyTest, testValue, period0, nil); err != nil {
t.Fatalf("error inserting: %v", err)
}

Expand All @@ -226,13 +329,13 @@ func TestRootCommitDiffEpoch(t *testing.T) {
t.Parallel()

root1 := New()
if err := root1.Insert(zeroKeyTest, testValue, 0, nil); err != nil {
if err := root1.Insert(zeroKeyTest, testValue, period0, nil); err != nil {
t.Fatalf("error inserting: %v", err)
}
comm1 := root1.Commit()

root2 := New()
if err := root2.Insert(zeroKeyTest, testValue, 2, nil); err != nil {
if err := root2.Insert(zeroKeyTest, testValue, period2, nil); err != nil {
t.Fatalf("error inserting: %v", err)
}
comm2 := root2.Commit()
Expand Down
6 changes: 3 additions & 3 deletions hashednode.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func (HashedNode) Get([]byte, StatePeriod, NodeResolverFn) ([]byte, error) {
return nil, errors.New("can not read from a hash node")
}

func (HashedNode) Revive(Stem, [][]byte, StatePeriod, StatePeriod, NodeResolverFn) error {
func (HashedNode) Revive(Stem, [][]byte, StatePeriod, StatePeriod, bool, NodeResolverFn) error {
return errors.New("cannot revive a hashed node")
}

Expand All @@ -62,8 +62,8 @@ func (HashedNode) Commitment() *Point {
panic("can not get commitment of a hash node")
}

func (HashedNode) GetProofItems(keylist, NodeResolverFn) (*ProofElements, []byte, []Stem, error) {
return nil, nil, nil, errors.New("can not get the full path, and there is no proof of absence")
func (HashedNode) GetProofItems(keylist, NodeResolverFn, StatePeriod) (*ProofElements, []byte, []Stem, []StatePeriod, error) {
return nil, nil, nil, nil, errors.New("can not get the full path, and there is no proof of absence")
}

func (HashedNode) Serialize() ([]byte, error) {
Expand Down
2 changes: 1 addition & 1 deletion hashednode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func TestHashedNodeFuncs(t *testing.T) {
if v != nil {
t.Fatal("non-nil get from a hashed node")
}
if _, _, _, err := e.GetProofItems(nil, nil); err == nil {
if _, _, _, _, err := e.GetProofItems(nil, nil, period0); err == nil {
t.Fatal("got nil error when getting proof items from a hashed node")
}
if _, err := e.Serialize(); err != errSerializeHashedNode {
Expand Down
4 changes: 3 additions & 1 deletion period.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ type StatePeriod uint16

const (
NumActiveEpochs = 2
period0 = 0
period0 = StatePeriod(0)
period1 = StatePeriod(1)
period2 = StatePeriod(2)
)

func IsExpired(prev, cur StatePeriod) bool {
Expand Down
Loading

0 comments on commit dd87e7f

Please sign in to comment.