mirror of
https://github.com/QuilibriumNetwork/ceremonyclient.git
synced 2026-03-10 18:57:32 +08:00
gob export
This commit is contained in:
parent
3891468562
commit
04ebb57fdd
@ -4,12 +4,18 @@ import (
|
||||
"bytes"
|
||||
"crypto/sha512"
|
||||
"encoding/binary"
|
||||
"encoding/gob"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
rbls48581 "source.quilibrium.com/quilibrium/monorepo/bls48581"
|
||||
)
|
||||
|
||||
func init() {
|
||||
gob.Register(&VectorCommitmentLeafNode{})
|
||||
gob.Register(&VectorCommitmentBranchNode{})
|
||||
}
|
||||
|
||||
const (
|
||||
BranchNodes = 1024
|
||||
BranchBits = 10 // log2(1024)
|
||||
@ -21,39 +27,39 @@ type VectorCommitmentNode interface {
|
||||
}
|
||||
|
||||
type VectorCommitmentLeafNode struct {
|
||||
key []byte
|
||||
value []byte
|
||||
commitment []byte
|
||||
Key []byte
|
||||
Value []byte
|
||||
Commitment []byte
|
||||
}
|
||||
|
||||
type VectorCommitmentBranchNode struct {
|
||||
prefix []int
|
||||
children [BranchNodes]VectorCommitmentNode
|
||||
commitment []byte
|
||||
Prefix []int
|
||||
Children [BranchNodes]VectorCommitmentNode
|
||||
Commitment []byte
|
||||
}
|
||||
|
||||
func (n *VectorCommitmentLeafNode) Commit() []byte {
|
||||
if n.commitment == nil {
|
||||
if n.Commitment == nil {
|
||||
h := sha512.New()
|
||||
h.Write([]byte{0})
|
||||
h.Write(n.key)
|
||||
h.Write(n.value)
|
||||
n.commitment = h.Sum(nil)
|
||||
h.Write(n.Key)
|
||||
h.Write(n.Value)
|
||||
n.Commitment = h.Sum(nil)
|
||||
}
|
||||
return n.commitment
|
||||
return n.Commitment
|
||||
}
|
||||
|
||||
func (n *VectorCommitmentBranchNode) Commit() []byte {
|
||||
if n.commitment == nil {
|
||||
if n.Commitment == nil {
|
||||
data := []byte{}
|
||||
for _, child := range n.children {
|
||||
for _, child := range n.Children {
|
||||
if child != nil {
|
||||
out := child.Commit()
|
||||
switch c := child.(type) {
|
||||
case *VectorCommitmentBranchNode:
|
||||
h := sha512.New()
|
||||
h.Write([]byte{1})
|
||||
for _, p := range c.prefix {
|
||||
for _, p := range c.Prefix {
|
||||
h.Write(binary.BigEndian.AppendUint32([]byte{}, uint32(p)))
|
||||
}
|
||||
h.Write(out)
|
||||
@ -67,23 +73,23 @@ func (n *VectorCommitmentBranchNode) Commit() []byte {
|
||||
}
|
||||
}
|
||||
|
||||
n.commitment = rbls48581.CommitRaw(data, 1024)
|
||||
n.Commitment = rbls48581.CommitRaw(data, 1024)
|
||||
}
|
||||
|
||||
return n.commitment
|
||||
return n.Commitment
|
||||
}
|
||||
|
||||
func (n *VectorCommitmentBranchNode) Verify(index int, proof []byte) bool {
|
||||
data := []byte{}
|
||||
if n.commitment == nil {
|
||||
for _, child := range n.children {
|
||||
if n.Commitment == nil {
|
||||
for _, child := range n.Children {
|
||||
if child != nil {
|
||||
out := child.Commit()
|
||||
switch c := child.(type) {
|
||||
case *VectorCommitmentBranchNode:
|
||||
h := sha512.New()
|
||||
h.Write([]byte{1})
|
||||
for _, p := range c.prefix {
|
||||
for _, p := range c.Prefix {
|
||||
h.Write(binary.BigEndian.AppendUint32([]byte{}, uint32(p)))
|
||||
}
|
||||
h.Write(out)
|
||||
@ -97,17 +103,17 @@ func (n *VectorCommitmentBranchNode) Verify(index int, proof []byte) bool {
|
||||
}
|
||||
}
|
||||
|
||||
n.commitment = rbls48581.CommitRaw(data, 1024)
|
||||
n.Commitment = rbls48581.CommitRaw(data, 1024)
|
||||
data = data[64*index : 64*(index+1)]
|
||||
} else {
|
||||
child := n.children[index]
|
||||
child := n.Children[index]
|
||||
if child != nil {
|
||||
out := child.Commit()
|
||||
switch c := child.(type) {
|
||||
case *VectorCommitmentBranchNode:
|
||||
h := sha512.New()
|
||||
h.Write([]byte{1})
|
||||
for _, p := range c.prefix {
|
||||
for _, p := range c.Prefix {
|
||||
h.Write(binary.BigEndian.AppendUint32([]byte{}, uint32(p)))
|
||||
}
|
||||
h.Write(out)
|
||||
@ -121,19 +127,19 @@ func (n *VectorCommitmentBranchNode) Verify(index int, proof []byte) bool {
|
||||
}
|
||||
}
|
||||
|
||||
return rbls48581.VerifyRaw(data, n.commitment, uint64(index), proof, 1024)
|
||||
return rbls48581.VerifyRaw(data, n.Commitment, uint64(index), proof, 1024)
|
||||
}
|
||||
|
||||
func (n *VectorCommitmentBranchNode) Prove(index int) []byte {
|
||||
data := []byte{}
|
||||
for _, child := range n.children {
|
||||
for _, child := range n.Children {
|
||||
if child != nil {
|
||||
out := child.Commit()
|
||||
switch c := child.(type) {
|
||||
case *VectorCommitmentBranchNode:
|
||||
h := sha512.New()
|
||||
h.Write([]byte{1})
|
||||
for _, p := range c.prefix {
|
||||
for _, p := range c.Prefix {
|
||||
h.Write(binary.BigEndian.AppendUint32([]byte{}, uint32(p)))
|
||||
}
|
||||
h.Write(out)
|
||||
@ -151,7 +157,7 @@ func (n *VectorCommitmentBranchNode) Prove(index int) []byte {
|
||||
}
|
||||
|
||||
type VectorCommitmentTree struct {
|
||||
root VectorCommitmentNode
|
||||
Root VectorCommitmentNode
|
||||
}
|
||||
|
||||
// getNextNibble returns the next BranchBits bits from the key starting at pos
|
||||
@ -212,60 +218,60 @@ func (t *VectorCommitmentTree) Insert(key, value []byte) error {
|
||||
var insert func(node VectorCommitmentNode, depth int) VectorCommitmentNode
|
||||
insert = func(node VectorCommitmentNode, depth int) VectorCommitmentNode {
|
||||
if node == nil {
|
||||
return &VectorCommitmentLeafNode{key: key, value: value}
|
||||
return &VectorCommitmentLeafNode{Key: key, Value: value}
|
||||
}
|
||||
|
||||
switch n := node.(type) {
|
||||
case *VectorCommitmentLeafNode:
|
||||
if bytes.Equal(n.key, key) {
|
||||
n.value = value
|
||||
n.commitment = nil
|
||||
if bytes.Equal(n.Key, key) {
|
||||
n.Value = value
|
||||
n.Commitment = nil
|
||||
return n
|
||||
}
|
||||
|
||||
// Get common prefix nibbles and divergence point
|
||||
sharedNibbles, divergeDepth := getNibblesUntilDiverge(n.key, key, depth)
|
||||
sharedNibbles, divergeDepth := getNibblesUntilDiverge(n.Key, key, depth)
|
||||
|
||||
// Create single branch node with shared prefix
|
||||
branch := &VectorCommitmentBranchNode{
|
||||
prefix: sharedNibbles,
|
||||
Prefix: sharedNibbles,
|
||||
}
|
||||
|
||||
// Add both leaves at their final positions
|
||||
finalOldNibble := getNextNibble(n.key, divergeDepth)
|
||||
finalOldNibble := getNextNibble(n.Key, divergeDepth)
|
||||
finalNewNibble := getNextNibble(key, divergeDepth)
|
||||
branch.children[finalOldNibble] = n
|
||||
branch.children[finalNewNibble] = &VectorCommitmentLeafNode{key: key, value: value}
|
||||
branch.Children[finalOldNibble] = n
|
||||
branch.Children[finalNewNibble] = &VectorCommitmentLeafNode{Key: key, Value: value}
|
||||
|
||||
return branch
|
||||
|
||||
case *VectorCommitmentBranchNode:
|
||||
if len(n.prefix) > 0 {
|
||||
if len(n.Prefix) > 0 {
|
||||
// Check if the new key matches the prefix
|
||||
for i, expectedNibble := range n.prefix {
|
||||
for i, expectedNibble := range n.Prefix {
|
||||
actualNibble := getNextNibble(key, depth+i*BranchBits)
|
||||
if actualNibble != expectedNibble {
|
||||
// Create new branch with shared prefix subset
|
||||
newBranch := &VectorCommitmentBranchNode{
|
||||
prefix: n.prefix[:i],
|
||||
Prefix: n.Prefix[:i],
|
||||
}
|
||||
// Position old branch and new leaf
|
||||
newBranch.children[expectedNibble] = n
|
||||
n.prefix = n.prefix[i+1:] // remove shared prefix from old branch
|
||||
newBranch.children[actualNibble] = &VectorCommitmentLeafNode{key: key, value: value}
|
||||
newBranch.Children[expectedNibble] = n
|
||||
n.Prefix = n.Prefix[i+1:] // remove shared prefix from old branch
|
||||
newBranch.Children[actualNibble] = &VectorCommitmentLeafNode{Key: key, Value: value}
|
||||
return newBranch
|
||||
}
|
||||
}
|
||||
// Key matches prefix, continue with final nibble
|
||||
finalNibble := getNextNibble(key, depth+len(n.prefix)*BranchBits)
|
||||
n.children[finalNibble] = insert(n.children[finalNibble], depth+len(n.prefix)*BranchBits+BranchBits)
|
||||
n.commitment = nil
|
||||
finalNibble := getNextNibble(key, depth+len(n.Prefix)*BranchBits)
|
||||
n.Children[finalNibble] = insert(n.Children[finalNibble], depth+len(n.Prefix)*BranchBits+BranchBits)
|
||||
n.Commitment = nil
|
||||
return n
|
||||
} else {
|
||||
// Simple branch without prefix
|
||||
nibble := getNextNibble(key, depth)
|
||||
n.children[nibble] = insert(n.children[nibble], depth+BranchBits)
|
||||
n.commitment = nil
|
||||
n.Children[nibble] = insert(n.Children[nibble], depth+BranchBits)
|
||||
n.Commitment = nil
|
||||
return n
|
||||
}
|
||||
}
|
||||
@ -273,7 +279,7 @@ func (t *VectorCommitmentTree) Insert(key, value []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
t.root = insert(t.root, 0)
|
||||
t.Root = insert(t.Root, 0)
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -294,33 +300,33 @@ func (t *VectorCommitmentTree) Verify(key []byte, proofs [][]byte) bool {
|
||||
|
||||
switch n := node.(type) {
|
||||
case *VectorCommitmentLeafNode:
|
||||
if bytes.Equal(n.key, key) {
|
||||
return bytes.Equal(n.value, proofs[0])
|
||||
if bytes.Equal(n.Key, key) {
|
||||
return bytes.Equal(n.Value, proofs[0])
|
||||
}
|
||||
return false
|
||||
|
||||
case *VectorCommitmentBranchNode:
|
||||
// Check prefix match
|
||||
for i, expectedNibble := range n.prefix {
|
||||
for i, expectedNibble := range n.Prefix {
|
||||
if getNextNibble(key, depth+i*BranchBits) != expectedNibble {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// Get final nibble after prefix
|
||||
finalNibble := getNextNibble(key, depth+len(n.prefix)*BranchBits)
|
||||
finalNibble := getNextNibble(key, depth+len(n.Prefix)*BranchBits)
|
||||
|
||||
if !n.Verify(finalNibble, proofs[0]) {
|
||||
return false
|
||||
}
|
||||
|
||||
return verify(n.children[finalNibble], proofs[1:], depth+len(n.prefix)*BranchBits+BranchBits)
|
||||
return verify(n.Children[finalNibble], proofs[1:], depth+len(n.Prefix)*BranchBits+BranchBits)
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
return verify(t.root, proofs, 0)
|
||||
return verify(t.Root, proofs, 0)
|
||||
}
|
||||
|
||||
func (t *VectorCommitmentTree) Prove(key []byte) [][]byte {
|
||||
@ -336,31 +342,31 @@ func (t *VectorCommitmentTree) Prove(key []byte) [][]byte {
|
||||
|
||||
switch n := node.(type) {
|
||||
case *VectorCommitmentLeafNode:
|
||||
if bytes.Equal(n.key, key) {
|
||||
return [][]byte{n.value}
|
||||
if bytes.Equal(n.Key, key) {
|
||||
return [][]byte{n.Value}
|
||||
}
|
||||
return nil
|
||||
|
||||
case *VectorCommitmentBranchNode:
|
||||
// Check prefix match
|
||||
for i, expectedNibble := range n.prefix {
|
||||
for i, expectedNibble := range n.Prefix {
|
||||
if getNextNibble(key, depth+i*BranchBits) != expectedNibble {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Get final nibble after prefix
|
||||
finalNibble := getNextNibble(key, depth+len(n.prefix)*BranchBits)
|
||||
finalNibble := getNextNibble(key, depth+len(n.Prefix)*BranchBits)
|
||||
|
||||
proofs := [][]byte{n.Prove(finalNibble)}
|
||||
|
||||
return append(proofs, prove(n.children[finalNibble], depth+len(n.prefix)*BranchBits+BranchBits)...)
|
||||
return append(proofs, prove(n.Children[finalNibble], depth+len(n.Prefix)*BranchBits+BranchBits)...)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
return prove(t.root, 0)
|
||||
return prove(t.Root, 0)
|
||||
}
|
||||
|
||||
// Get retrieves a value from the tree by key
|
||||
@ -377,27 +383,27 @@ func (t *VectorCommitmentTree) Get(key []byte) ([]byte, error) {
|
||||
|
||||
switch n := node.(type) {
|
||||
case *VectorCommitmentLeafNode:
|
||||
if bytes.Equal(n.key, key) {
|
||||
return n.value
|
||||
if bytes.Equal(n.Key, key) {
|
||||
return n.Value
|
||||
}
|
||||
return nil
|
||||
|
||||
case *VectorCommitmentBranchNode:
|
||||
// Check prefix match
|
||||
for i, expectedNibble := range n.prefix {
|
||||
for i, expectedNibble := range n.Prefix {
|
||||
if getNextNibble(key, depth+i*BranchBits) != expectedNibble {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
// Get final nibble after prefix
|
||||
finalNibble := getNextNibble(key, depth+len(n.prefix)*BranchBits)
|
||||
return get(n.children[finalNibble], depth+len(n.prefix)*BranchBits+BranchBits)
|
||||
finalNibble := getNextNibble(key, depth+len(n.Prefix)*BranchBits)
|
||||
return get(n.Children[finalNibble], depth+len(n.Prefix)*BranchBits+BranchBits)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
value := get(t.root, 0)
|
||||
value := get(t.Root, 0)
|
||||
if value == nil {
|
||||
return nil, errors.New("key not found")
|
||||
}
|
||||
@ -418,14 +424,14 @@ func (t *VectorCommitmentTree) Delete(key []byte) error {
|
||||
|
||||
switch n := node.(type) {
|
||||
case *VectorCommitmentLeafNode:
|
||||
if bytes.Equal(n.key, key) {
|
||||
if bytes.Equal(n.Key, key) {
|
||||
return nil
|
||||
}
|
||||
return n
|
||||
|
||||
case *VectorCommitmentBranchNode:
|
||||
// Check prefix match
|
||||
for i, expectedNibble := range n.prefix {
|
||||
for i, expectedNibble := range n.Prefix {
|
||||
currentNibble := getNextNibble(key, depth+i*BranchBits)
|
||||
if currentNibble != expectedNibble {
|
||||
return n // Key doesn't match prefix, nothing to delete
|
||||
@ -433,15 +439,15 @@ func (t *VectorCommitmentTree) Delete(key []byte) error {
|
||||
}
|
||||
|
||||
// Delete at final position after prefix
|
||||
finalNibble := getNextNibble(key, depth+len(n.prefix)*BranchBits)
|
||||
n.children[finalNibble] = delete(n.children[finalNibble], depth+len(n.prefix)*BranchBits+BranchBits)
|
||||
n.commitment = nil
|
||||
finalNibble := getNextNibble(key, depth+len(n.Prefix)*BranchBits)
|
||||
n.Children[finalNibble] = delete(n.Children[finalNibble], depth+len(n.Prefix)*BranchBits+BranchBits)
|
||||
n.Commitment = nil
|
||||
|
||||
// Count remaining children
|
||||
childCount := 0
|
||||
var lastChild VectorCommitmentNode
|
||||
var lastIndex int
|
||||
for i, child := range n.children {
|
||||
for i, child := range n.Children {
|
||||
if child != nil {
|
||||
childCount++
|
||||
lastChild = child
|
||||
@ -454,14 +460,14 @@ func (t *VectorCommitmentTree) Delete(key []byte) error {
|
||||
} else if childCount == 1 {
|
||||
// If the only child is a leaf, keep structure if its path matches
|
||||
if leaf, ok := lastChild.(*VectorCommitmentLeafNode); ok {
|
||||
if lastIndex == getLastNibble(leaf.key, len(n.prefix)) {
|
||||
if lastIndex == getLastNibble(leaf.Key, len(n.Prefix)) {
|
||||
return n
|
||||
}
|
||||
return leaf
|
||||
}
|
||||
// If it's a branch, merge the prefixes
|
||||
if branch, ok := lastChild.(*VectorCommitmentBranchNode); ok {
|
||||
branch.prefix = append(n.prefix, branch.prefix...)
|
||||
branch.Prefix = append(n.Prefix, branch.Prefix...)
|
||||
return branch
|
||||
}
|
||||
}
|
||||
@ -471,16 +477,16 @@ func (t *VectorCommitmentTree) Delete(key []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
t.root = delete(t.root, 0)
|
||||
t.Root = delete(t.Root, 0)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Root returns the root hash of the tree
|
||||
func (t *VectorCommitmentTree) Root() []byte {
|
||||
if t.root == nil {
|
||||
// Commit returns the root of the tree
|
||||
func (t *VectorCommitmentTree) Commit() []byte {
|
||||
if t.Root == nil {
|
||||
return make([]byte, 64)
|
||||
}
|
||||
return t.root.Commit()
|
||||
return t.Root.Commit()
|
||||
}
|
||||
|
||||
func debugNode(node VectorCommitmentNode, depth int, prefix string) {
|
||||
@ -490,10 +496,10 @@ func debugNode(node VectorCommitmentNode, depth int, prefix string) {
|
||||
|
||||
switch n := node.(type) {
|
||||
case *VectorCommitmentLeafNode:
|
||||
fmt.Printf("%sLeaf: key=%x value=%x\n", prefix, n.key, n.value)
|
||||
fmt.Printf("%sLeaf: key=%x value=%x\n", prefix, n.Key, n.Value)
|
||||
case *VectorCommitmentBranchNode:
|
||||
fmt.Printf("%sBranch %v:\n", prefix, n.prefix)
|
||||
for i, child := range n.children {
|
||||
fmt.Printf("%sBranch %v:\n", prefix, n.Prefix)
|
||||
for i, child := range n.Children {
|
||||
if child != nil {
|
||||
fmt.Printf("%s [%d]:\n", prefix, i)
|
||||
debugNode(child, depth+1, prefix+" ")
|
||||
|
||||
Loading…
Reference in New Issue
Block a user