Skip to content

Commit

Permalink
Remove expiry and add period in stateless proof
Browse files Browse the repository at this point in the history
  • Loading branch information
weiihann committed Jan 5, 2025
1 parent dd87e7f commit 93b1fb4
Show file tree
Hide file tree
Showing 18 changed files with 229 additions and 377 deletions.
3 changes: 1 addition & 2 deletions debug.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,11 @@ type (
C [32]byte `json:"commitment"`
C1 [32]byte `json:"c1"`
C2 [32]byte `json:"c2"`
LastPeriod StatePeriod `json:"last_period"`
Period StatePeriod `json:"period"`
}

ExportableExpiredLeafNode struct {
Stem Stem `json:"stem"`
LastPeriod StatePeriod `json:"last_period"`
Commitment [32]byte `json:"commitment"`
}
)
2 changes: 1 addition & 1 deletion doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,12 @@ var (
errReviveValuesMismatch = errors.New("values mismatch in revive")
errReviveStemMismatch = errors.New("stem mismatch in revive")
errRevivePeriodMismatch = errors.New("period mismatch in revive")
errRevivePeriodOlderThanNew = errors.New("revive old period is older than the new period")
)

const (
// Extension status
extStatusAbsentEmpty = byte(iota) // missing child node along the path
extStatusAbsentOther // path led to a node with a different stem
extStatusPresent // stem was present
extStatusExpired // stem was present but expired
)
2 changes: 1 addition & 1 deletion empty.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ func (Empty) Commitment() *Point {
return &id
}

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

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, period0); err == nil {
if _, _, _, _, err := e.GetProofItems(nil, nil); err == nil {
t.Fatal("get proof items should error")
}

Expand Down
11 changes: 5 additions & 6 deletions encoding.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ const (
leafValueIndexSize = 1
singleSlotLeafSize = nodeTypeSize + StemSize + 2*banderwagon.UncompressedSize + leafValueIndexSize + leafSlotSize + periodSize
eoaLeafSize = nodeTypeSize + StemSize + 2*banderwagon.UncompressedSize + leafBasicDataSize + periodSize
expiredLeafSize = nodeTypeSize + StemSize + periodSize + banderwagon.UncompressedSize
expiredLeafSize = nodeTypeSize + StemSize + banderwagon.UncompressedSize
)

func bit(bitlist []byte, nr int) bool {
Expand All @@ -77,9 +77,9 @@ var errSerializedPayloadTooShort = errors.New("verkle payload is too short")
// ParseNode deserializes a node into its proper VerkleNode instance.
// The serialized bytes have the format:
// - Internal nodes: <nodeType><bitlist><commitment>
// - Leaf nodes: <nodeType><stem><bitlist><comm><c1comm><c2comm><lastPeriod><children...>
// - EoA nodes: <nodeType><stem><comm><c1comm><lastPeriod><balance><nonce>
// - single slot node: <nodeType><stem><comm><cncomm><lastPeriod><leaf index><slot>
// - Leaf nodes: <nodeType><stem><bitlist><comm><c1comm><c2comm><period><children...>
// - EoA nodes: <nodeType><stem><comm><c1comm><period><balance><nonce>
// - single slot node: <nodeType><stem><comm><cncomm><period><leaf index><slot>
// - Expired leaf nodes: <nodeType><stem><commitment>
func ParseNode(serializedNode []byte, depth byte) (VerkleNode, error) {
// Check that the length of the serialized node is at least the smallest possible serialized node.
Expand Down Expand Up @@ -200,9 +200,8 @@ func parseExpiredLeafNode(serialized []byte, depth byte) (VerkleNode, error) {
l := &ExpiredLeafNode{}
l.setDepth(depth)
l.stem = serialized[leafStemOffset : leafStemOffset+StemSize]
l.lastPeriod = StatePeriodFromBytes(serialized[leafStemOffset+StemSize:leafStemOffset+StemSize+periodSize])
l.commitment = new(Point)
if err := l.commitment.SetBytesUncompressed(serialized[leafStemOffset+StemSize+periodSize:], true); err != nil {
if err := l.commitment.SetBytesUncompressed(serialized[leafStemOffset+StemSize:], true); err != nil {
return nil, fmt.Errorf("setting commitment: %w", err)
}
return l, nil
Expand Down
6 changes: 1 addition & 5 deletions encoding_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ func TestParseExpiredLeaf(t *testing.T) {

comm := srs[0]
stem := ffx32KeyTest[:StemSize]
el := NewExpiredLeafNode(stem, period2, &comm)
el := NewExpiredLeafNode(stem, &comm)

serialized, err := el.Serialize()
if err != nil {
Expand All @@ -222,8 +222,4 @@ func TestParseExpiredLeaf(t *testing.T) {
if !el2.commitment.Equal(&comm) {
t.Fatalf("invalid commitment, got %x, expected %x", el2.commitment, comm)
}

if el2.lastPeriod != period2 {
t.Fatalf("invalid last period, got %d, expected %d", el2.lastPeriod, period2)
}
}
33 changes: 5 additions & 28 deletions expired_leaf.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,16 @@ package verkle
import (
"fmt"
"errors"
"encoding/binary"
)

type ExpiredLeafNode struct {
stem Stem
lastPeriod StatePeriod
commitment *Point
depth byte // used for proof only, not commitment calculation
}

func NewExpiredLeafNode(stem Stem, lastPeriod StatePeriod, commitment *Point) *ExpiredLeafNode {
return &ExpiredLeafNode{stem: stem, lastPeriod: lastPeriod, commitment: commitment}
func NewExpiredLeafNode(stem Stem, commitment *Point) *ExpiredLeafNode {
return &ExpiredLeafNode{stem: stem, commitment: commitment}
}

func (n *ExpiredLeafNode) Insert([]byte, []byte, StatePeriod, NodeResolverFn) error {
Expand Down Expand Up @@ -69,25 +67,8 @@ func (n *ExpiredLeafNode) Commitment() *Point {
return n.commitment
}

func (n *ExpiredLeafNode) GetProofItems(keys keylist, resolver NodeResolverFn, _ StatePeriod) (*ProofElements, []byte, []Stem, []StatePeriod, error) {
var (
pe = &ProofElements{
Vals: make([][]byte, len(keys)),
ByPath: map[string]*Point{},
}
esses []byte = nil
poass []Stem
)

for i := range keys {
pe.ByPath[string(keys[i][:n.depth])] = n.commitment
pe.Vals[i] = nil

esses = append(esses, extStatusExpired|(n.depth<<3))
poass = append(poass, n.stem)
}

return pe, esses, poass, []StatePeriod{n.lastPeriod}, nil
func (n *ExpiredLeafNode) GetProofItems(keylist, NodeResolverFn) (*ProofElements, []byte, []Stem, []StatePeriod, error) {
return nil, nil, nil, nil, errors.New("cannot get proof items from expired leaf node")
}

func (n *ExpiredLeafNode) Serialize() ([]byte, error) {
Expand All @@ -97,11 +78,7 @@ func (n *ExpiredLeafNode) Serialize() ([]byte, error) {
result := buf[:]
result[0] = expiredLeafType
copy(result[leafStemOffset:], n.stem[:StemSize])

lastPeriod := make([]byte, periodSize)
binary.BigEndian.PutUint16(lastPeriod, uint16(n.lastPeriod))
copy(result[leafStemOffset+StemSize:], lastPeriod)
copy(result[leafStemOffset+StemSize+periodSize:], cBytes[:])
copy(result[leafStemOffset+StemSize:], cBytes[:])

return result, nil
}
Expand Down
2 changes: 1 addition & 1 deletion expired_leaf_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ func TestExpiredLeafBasic(t *testing.T) {
cfg := GetConfig()
srs := cfg.conf.SRS
comm := srs[0]
leaf := NewExpiredLeafNode(zeroKeyTest[:StemSize], period0, &comm)
leaf := NewExpiredLeafNode(zeroKeyTest[:StemSize], &comm)

err := leaf.Insert(zeroKeyTest, zeroKeyTest, 0, nil)
if !errors.Is(err, errExpired) {
Expand Down
89 changes: 57 additions & 32 deletions expired_tree_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ func TestInsertSameLeafNoExpired(t *testing.T) {
t.Fatalf("expected value %x, got %x", testValue, leaf.values[oneKeyTest[StemSize]])
}

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

Expand All @@ -58,8 +58,8 @@ func TestInsertSameLeafExpired(t *testing.T) {
t.Fatalf("expected value %x, got %x", testValue, leaf.values[zeroKeyTest[StemSize]])
}

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

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

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

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

Expand All @@ -115,7 +115,7 @@ func TestInsertExpiredLeafSibling(t *testing.T) {
t.Fatalf("expected leaf node, got %T", root.(*InternalNode).children[0])
}

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

if err := root.Insert(forkOneKeyTest, testValue, period2, nil); err != nil {
t.Fatalf("error inserting: %v", err)
Expand Down Expand Up @@ -163,8 +163,8 @@ func TestGetNoExpired(t *testing.T) {
t.Fatalf("expected value %x, got %x", testValue, val)
}

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

Expand All @@ -190,8 +190,8 @@ func TestGetExpired(t *testing.T) {
t.Fatalf("expected leaf node, got %T", root.(*InternalNode).children[0])
}

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

Expand Down Expand Up @@ -231,8 +231,28 @@ func TestDelLeafExpired(t *testing.T) {
t.Fatalf("expected empty node, got %T", root.(*InternalNode).children[0])
}

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

func TestUpdatePeriod(t *testing.T) {
values := make([][]byte, NodeWidth)
values[0] = testValue
leaf1, err := NewLeafNode(zeroKeyTest, values, period1)
if err != nil {
t.Fatalf("error creating leaf node: %v", err)
}

leaf1.updatePeriod(period2)

leaf2, err := NewLeafNode(zeroKeyTest, values, period2)
if err != nil {
t.Fatalf("error creating leaf node: %v", err)
}

if !leaf1.Commitment().Equal(leaf2.Commitment()) {
t.Fatalf("expected commitment to be %x, got %x", leaf1.Commitment(), leaf2.Commitment())
}
}

Expand All @@ -244,25 +264,30 @@ func TestReviveExpired(t *testing.T) {
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)
leaf := root.(*InternalNode).children[0].(*LeafNode)
expiredLeaf := NewExpiredLeafNode(leaf.stem, new(Point).Set(leaf.commitment))
expiredLeaf.setDepth(1)
root.(*InternalNode).children[0] = expiredLeaf

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

rLeaf, ok := root.(*InternalNode).children[0].(*LeafNode)
if !ok {
t.Fatalf("expected leaf node, got %T", root.(*InternalNode).children[0])
rLeaf := root.(*InternalNode).children[0].(*LeafNode)
if rLeaf.period != period2 {
t.Fatalf("expected last accessed to be 2, got %d", rLeaf.period)
}

// Create a new root and insert the same key-value with the post-revive period
root2 := New()
if err := root2.Insert(zeroKeyTest, testValue, period2, nil); err != nil {
t.Fatalf("error inserting: %v", err)
}
comm2 := root2.Commit()

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

Expand All @@ -281,7 +306,7 @@ func TestReviveNoExpired(t *testing.T) {

comm := root.Commit()

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

Expand All @@ -290,8 +315,8 @@ func TestReviveNoExpired(t *testing.T) {
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)
if rLeaf.period != period0 {
t.Fatalf("expected last accessed to be 0, got %d", rLeaf.period)
}

rComm := root.Commit()
Expand All @@ -316,7 +341,7 @@ func TestRootCommitExpired(t *testing.T) {
var init Point
init.Set(root.Commit())

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

comm := root.Commit()
Expand All @@ -343,4 +368,4 @@ func TestRootCommitDiffEpoch(t *testing.T) {
if comm1.Equal(comm2) {
t.Fatalf("expected different commitments, got %x", comm1)
}
}
}
2 changes: 1 addition & 1 deletion hashednode.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ func (HashedNode) Commitment() *Point {
panic("can not get commitment of a hash node")
}

func (HashedNode) GetProofItems(keylist, NodeResolverFn, StatePeriod) (*ProofElements, []byte, []Stem, []StatePeriod, error) {
func (HashedNode) GetProofItems(keylist, NodeResolverFn) (*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")
}

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, period0); err == nil {
if _, _, _, _, err := e.GetProofItems(nil, nil); err == nil {
t.Fatal("got nil error when getting proof items from a hashed node")
}
if _, err := e.Serialize(); err != errSerializeHashedNode {
Expand Down
Loading

0 comments on commit 93b1fb4

Please sign in to comment.