Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,15 @@ var (
errDeleteHash = errors.New("trying to delete from a hashed subtree")
errDeleteMissing = errors.New("trying to delete a missing group")
errDeleteUnknown = errors.New("trying to delete an out-of-view node")
errDeleteEmpty = errors.New("can't delete an empty node")
errReadFromInvalid = errors.New("trying to read from an invalid child")
errSerializeHashedNode = errors.New("trying to serialize a hashed internal node")
errSerializeUnknownNode = errors.New("trying to serialize a subtree missing from the stateless view")
errInsertIntoOtherStem = errors.New("insert splits a stem where it should not happen")
errUnknownNodeType = errors.New("unknown node type detected")
errMissingNodeInStateless = errors.New("trying to access a node that is missing from the stateless view")
errIsPOAStub = errors.New("trying to read/write a proof of absence leaf node")
errGetProofItemsUnknownNode = errors.New("can't generate proof items for unknown node")
)

const (
Expand Down
2 changes: 1 addition & 1 deletion empty.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func (Empty) Insert([]byte, []byte, NodeResolverFn) error {
}

func (Empty) Delete([]byte, NodeResolverFn) (bool, error) {
return false, errors.New("cant delete an empty node")
return false, errDeleteEmpty
}

func (Empty) Get([]byte, NodeResolverFn) ([]byte, error) {
Expand Down
2 changes: 1 addition & 1 deletion hashednode.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func (HashedNode) Insert([]byte, []byte, NodeResolverFn) error {
}

func (HashedNode) Delete([]byte, NodeResolverFn) (bool, error) {
return false, errors.New("cant delete a hashed node in-place")
return false, errDeleteHash
}

func (HashedNode) Get([]byte, NodeResolverFn) ([]byte, error) {
Expand Down
41 changes: 24 additions & 17 deletions proof_ipa.go
Original file line number Diff line number Diff line change
Expand Up @@ -294,22 +294,24 @@ func verifyVerkleProof(proof *Proof, Cs []*Point, indices []uint8, ys []*Fr, tc
// * Multipoint proof
// it also returns the serialized keys and values
func SerializeProof(proof *Proof) (*VerkleProof, StateDiff, error) {
// SerializeProof serializes a proof into a format that can be stored in a block.
// it also returns the serialized keys and values
otherstems := make([][StemSize]byte, len(proof.PoaStems))
for i, stem := range proof.PoaStems {
copy(otherstems[i][:], stem)
for i, poaStem := range proof.PoaStems {
copy(otherstems[i][:], poaStem)
}

cbp := make([][32]byte, len(proof.Cs))
for i, C := range proof.Cs {
serialized := C.Bytes()
copy(cbp[i][:], serialized[:])
for i, c := range proof.Cs {
serializedC := c.Bytes()
copy(cbp[i][:], serializedC[:])
}

var cls, crs [IPA_PROOF_DEPTH][32]byte
for i := 0; i < IPA_PROOF_DEPTH; i++ {

for i := range proof.Multipoint.IPA.L {
l := proof.Multipoint.IPA.L[i].Bytes()
copy(cls[i][:], l[:])

r := proof.Multipoint.IPA.R[i].Bytes()
copy(crs[i][:], r[:])
}
Expand Down Expand Up @@ -492,6 +494,13 @@ func PreStateTreeFromProof(proof *Proof, rootC *Point) (VerkleNode, error) { //
i++
}

// Build an index of keys by stem to avoid O(N²) lookups
keyStemIndex := make(map[string][]int)
for j, k := range proof.Keys {
stem := KeyToStem(k)
keyStemIndex[string(stem)] = append(keyStemIndex[string(stem)], j)
}

// assign one or more stem to each stem info
for i, es := range proof.ExtStatus {
si := stemInfo{
Expand All @@ -503,16 +512,16 @@ func PreStateTreeFromProof(proof *Proof, rootC *Point) (VerkleNode, error) { //
case extStatusAbsentEmpty:
// All keys that are part of a proof of absence, must contain empty
// prestate values. If that isn't the case, the proof is invalid.
for j := range proof.Keys { // TODO: DoS risk, use map or binary search.
if bytes.HasPrefix(proof.Keys[j], stems[i]) && proof.PreValues[j] != nil {
for _, j := range keyStemIndex[string(stems[i])] {
if proof.PreValues[j] != nil {
return nil, fmt.Errorf("proof of absence (empty) stem %x has a value", si.stem)
}
}
case extStatusAbsentOther:
// All keys that are part of a proof of absence, must contain empty
// prestate values. If that isn't the case, the proof is invalid.
for j := range proof.Keys { // TODO: DoS risk, use map or binary search.
if bytes.HasPrefix(proof.Keys[j], stems[i]) && proof.PreValues[j] != nil {
for _, j := range keyStemIndex[string(stems[i])] {
if proof.PreValues[j] != nil {
return nil, fmt.Errorf("proof of absence (other) stem %x has a value", si.stem)
}
}
Expand All @@ -537,12 +546,10 @@ func PreStateTreeFromProof(proof *Proof, rootC *Point) (VerkleNode, error) { //
case extStatusPresent:
si.values = map[byte][]byte{}
si.stem = stems[i]
for j, k := range proof.Keys { // TODO: DoS risk, use map or binary search.
if bytes.Equal(KeyToStem(k), si.stem) {
si.values[k[StemSize]] = proof.PreValues[j]
si.has_c1 = si.has_c1 || (k[StemSize] < 128)
si.has_c2 = si.has_c2 || (k[StemSize] >= 128)
}
for _, j := range keyStemIndex[string(si.stem)] {
si.values[proof.Keys[j][StemSize]] = proof.PreValues[j]
si.has_c1 = si.has_c1 || (proof.Keys[j][StemSize] < 128)
si.has_c2 = si.has_c2 || (proof.Keys[j][StemSize] >= 128)
}
default:
return nil, fmt.Errorf("invalid extension status: %d", si.stemType)
Expand Down
8 changes: 3 additions & 5 deletions unknown.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,14 @@

package verkle

import "errors"

type UnknownNode struct{}

func (UnknownNode) Insert([]byte, []byte, NodeResolverFn) error {
return errMissingNodeInStateless
}

func (UnknownNode) Delete([]byte, NodeResolverFn) (bool, error) {
return false, errors.New("cant delete in a subtree missing form a stateless view")
return false, errDeleteUnknown
}

func (UnknownNode) Get([]byte, NodeResolverFn) ([]byte, error) {
Expand All @@ -52,11 +50,11 @@ func (UnknownNode) Commitment() *Point {
}

func (UnknownNode) GetProofItems(Keylist, NodeResolverFn) (*ProofElements, []byte, []Stem, error) {
return nil, nil, nil, errors.New("can't generate proof items for unknown node")
return nil, nil, nil, errGetProofItemsUnknownNode
}

func (UnknownNode) Serialize() ([]byte, error) {
return nil, errors.New("trying to serialize a subtree missing from the statless view")
return nil, errSerializeUnknownNode
}

func (UnknownNode) Copy() VerkleNode {
Expand Down