refactor storage approach for proof trees due to pebble limitations

This commit is contained in:
Cassandra Heart 2025-02-17 05:52:45 -06:00
parent 7188f828a6
commit 1e63348a61
No known key found for this signature in database
GPG Key ID: 6352152859385958
15 changed files with 1282 additions and 280 deletions

View File

@ -24,8 +24,6 @@ replace source.quilibrium.com/quilibrium/monorepo/go-libp2p-blossomsub => ../go-
replace source.quilibrium.com/quilibrium/monorepo/node => ../node
replace github.com/cockroachdb/pebble => ../pebble
require (
github.com/iden3/go-iden3-crypto v0.0.16
github.com/multiformats/go-multiaddr v0.12.4
@ -44,9 +42,10 @@ require (
github.com/btcsuite/btcd v0.21.0-beta.0.20201114000516-e9c7a5ac6401 // indirect
github.com/bwesterb/go-ristretto v1.2.3 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/cockroachdb/errors v1.11.1 // indirect
github.com/cockroachdb/errors v1.11.3 // indirect
github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce // indirect
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect
github.com/cockroachdb/pebble v0.0.0-20231210175920-b4d301aeb46a // indirect
github.com/cockroachdb/pebble v1.1.4 // indirect
github.com/cockroachdb/redact v1.1.5 // indirect
github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect
github.com/consensys/gnark-crypto v0.5.3 // indirect
@ -58,7 +57,7 @@ require (
github.com/elastic/gosigar v0.14.2 // indirect
github.com/flynn/noise v1.1.0 // indirect
github.com/francoispqt/gojay v1.2.13 // indirect
github.com/getsentry/sentry-go v0.18.0 // indirect
github.com/getsentry/sentry-go v0.27.0 // indirect
github.com/go-logr/logr v1.3.0 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect

View File

@ -50,12 +50,14 @@ github.com/cloudflare/circl v1.3.9/go.mod h1:PDRU+oXvdD7KCtgKxW95M5Z8BpSCJXQORiZ
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f h1:otljaYPt5hWxV3MUfO5dFPFiOXg9CyG5/kCfayTqsJ4=
github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU=
github.com/cockroachdb/errors v1.11.1 h1:xSEW75zKaKCWzR3OfxXUxgrk/NtT4G1MiOv5lWZazG8=
github.com/cockroachdb/errors v1.11.1/go.mod h1:8MUxA3Gi6b25tYlFEBGLf+D8aISL+M4MIpiWMSNRfxw=
github.com/cockroachdb/errors v1.11.3 h1:5bA+k2Y6r+oz/6Z/RFlNeVCesGARKuC6YymtcDrbC/I=
github.com/cockroachdb/errors v1.11.3/go.mod h1:m4UIW4CDjx+R5cybPsNrRbreomiFqt8o1h1wUVazSd8=
github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce h1:giXvy4KSc/6g/esnpM7Geqxka4WSqI1SZc7sMJFd3y4=
github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce/go.mod h1:9/y3cnZ5GKakj/H4y9r9GTjCvAFta7KLgSHPJJYc52M=
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE=
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs=
github.com/cockroachdb/metamorphic v0.0.0-20231108215700-4ba948b56895 h1:XANOgPYtvELQ/h4IrmPAohXqe2pWA8Bwhejr3VQoZsA=
github.com/cockroachdb/metamorphic v0.0.0-20231108215700-4ba948b56895/go.mod h1:aPd7gM9ov9M8v32Yy5NJrDyOcD8z642dqs+F0CeNXfA=
github.com/cockroachdb/pebble v1.1.4 h1:5II1uEP4MyHLDnsrbv/EZ36arcb9Mxg3n+owhZ3GrG8=
github.com/cockroachdb/pebble v1.1.4/go.mod h1:4exszw1r40423ZsmkG/09AFEG83I0uDgfujJdbL6kYU=
github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30=
github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg=
github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo=
@ -104,8 +106,8 @@ github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiD
github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/getsentry/sentry-go v0.18.0 h1:MtBW5H9QgdcJabtZcuJG80BMOwaBpkRDZkxRkNC1sN0=
github.com/getsentry/sentry-go v0.18.0/go.mod h1:Kgon4Mby+FJ7ZWHFUAZgVaIa8sxHtnRJRLTXZr51aKQ=
github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps=
github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=

View File

@ -18,11 +18,22 @@ func init() {
}
const (
BranchNodes = 64
BranchBits = 6 // log2(64)
BranchMask = BranchNodes - 1
NodesPerBranch = 64
BranchBits = 6 // log2(64)
BranchMask = NodesPerBranch - 1
)
type VectorCommitmentTree interface {
Commit(recalculate bool) []byte
Delete(key []byte) error
Get(key []byte) ([]byte, error)
GetMetadata() (leafCount int, longestBranch int)
GetSize() *big.Int
Insert(key []byte, value []byte, hashTarget []byte, size *big.Int) error
Prove(key []byte) [][]byte
Verify(key []byte, proofs [][]byte) bool
}
type VectorCommitmentNode interface {
Commit(recalculate bool) []byte
GetSize() *big.Int
@ -38,7 +49,7 @@ type VectorCommitmentLeafNode struct {
type VectorCommitmentBranchNode struct {
Prefix []int
Children [BranchNodes]VectorCommitmentNode
Children [NodesPerBranch]VectorCommitmentNode
Commitment []byte
Size *big.Int
LeafCount int
@ -175,12 +186,12 @@ func (n *VectorCommitmentBranchNode) Prove(index int) []byte {
return rbls48581.ProveRaw(data, uint64(index), 64)
}
type VectorCommitmentTree struct {
type RawVectorCommitmentTree struct {
Root VectorCommitmentNode
}
// getNextNibble returns the next BranchBits bits from the key starting at pos
func getNextNibble(key []byte, pos int) int {
// GetNextNibble returns the next BranchBits bits from the key starting at pos
func GetNextNibble(key []byte, pos int) int {
startByte := pos / 8
if startByte >= len(key) {
return 0
@ -208,13 +219,13 @@ func getNextNibble(key []byte, pos int) int {
return result & BranchMask
}
func getNibblesUntilDiverge(key1, key2 []byte, startDepth int) ([]int, int) {
func GetNibblesUntilDiverge(key1, key2 []byte, startDepth int) ([]int, int) {
var nibbles []int
depth := startDepth
for {
n1 := getNextNibble(key1, depth)
n2 := getNextNibble(key2, depth)
n1 := GetNextNibble(key1, depth)
n2 := GetNextNibble(key2, depth)
if n1 != n2 {
return nibbles, depth
}
@ -224,7 +235,7 @@ func getNibblesUntilDiverge(key1, key2 []byte, startDepth int) ([]int, int) {
}
// Insert adds or updates a key-value pair in the tree
func (t *VectorCommitmentTree) Insert(
func (t *RawVectorCommitmentTree) Insert(
key, value, hashTarget []byte,
size *big.Int,
) error {
@ -253,7 +264,7 @@ func (t *VectorCommitmentTree) Insert(
}
// 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{
@ -264,8 +275,8 @@ func (t *VectorCommitmentTree) Insert(
}
// Add both leaves at their final positions
finalOldNibble := getNextNibble(n.Key, divergeDepth)
finalNewNibble := getNextNibble(key, divergeDepth)
finalOldNibble := GetNextNibble(n.Key, divergeDepth)
finalNewNibble := GetNextNibble(key, divergeDepth)
branch.Children[finalOldNibble] = n
branch.Children[finalNewNibble] = &VectorCommitmentLeafNode{
Key: key,
@ -280,7 +291,7 @@ func (t *VectorCommitmentTree) Insert(
if len(n.Prefix) > 0 {
// Check if the new key matches the prefix
for i, expectedNibble := range n.Prefix {
actualNibble := getNextNibble(key, depth+i*BranchBits)
actualNibble := GetNextNibble(key, depth+i*BranchBits)
if actualNibble != expectedNibble {
// Create new branch with shared prefix subset
newBranch := &VectorCommitmentBranchNode{
@ -303,7 +314,7 @@ func (t *VectorCommitmentTree) Insert(
}
// Key matches prefix, continue with final nibble
finalNibble := getNextNibble(key, depth+len(n.Prefix)*BranchBits)
finalNibble := GetNextNibble(key, depth+len(n.Prefix)*BranchBits)
inserted := insert(
n.Children[finalNibble],
depth+len(n.Prefix)*BranchBits+BranchBits,
@ -323,7 +334,7 @@ func (t *VectorCommitmentTree) Insert(
return n
} else {
// Simple branch without prefix
nibble := getNextNibble(key, depth)
nibble := GetNextNibble(key, depth)
inserted := insert(n.Children[nibble], depth+BranchBits)
n.Children[nibble] = inserted
n.Commitment = nil
@ -348,7 +359,7 @@ func (t *VectorCommitmentTree) Insert(
return nil
}
func (t *VectorCommitmentTree) Verify(key []byte, proofs [][]byte) bool {
func (t *RawVectorCommitmentTree) Verify(key []byte, proofs [][]byte) bool {
if len(key) == 0 {
return false
}
@ -373,13 +384,13 @@ func (t *VectorCommitmentTree) Verify(key []byte, proofs [][]byte) bool {
case *VectorCommitmentBranchNode:
// Check prefix match
for i, expectedNibble := range n.Prefix {
if getNextNibble(key, depth+i*BranchBits) != expectedNibble {
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
@ -394,7 +405,7 @@ func (t *VectorCommitmentTree) Verify(key []byte, proofs [][]byte) bool {
return verify(t.Root, proofs, 0)
}
func (t *VectorCommitmentTree) Prove(key []byte) [][]byte {
func (t *RawVectorCommitmentTree) Prove(key []byte) [][]byte {
if len(key) == 0 {
return nil
}
@ -415,13 +426,13 @@ func (t *VectorCommitmentTree) Prove(key []byte) [][]byte {
case *VectorCommitmentBranchNode:
// Check prefix match
for i, expectedNibble := range n.Prefix {
if getNextNibble(key, depth+i*BranchBits) != expectedNibble {
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)}
@ -435,7 +446,7 @@ func (t *VectorCommitmentTree) Prove(key []byte) [][]byte {
}
// Get retrieves a value from the tree by key
func (t *VectorCommitmentTree) Get(key []byte) ([]byte, error) {
func (t *RawVectorCommitmentTree) Get(key []byte) ([]byte, error) {
if len(key) == 0 {
return nil, errors.New("empty key not allowed")
}
@ -456,12 +467,12 @@ func (t *VectorCommitmentTree) Get(key []byte) ([]byte, error) {
case *VectorCommitmentBranchNode:
// Check prefix match
for i, expectedNibble := range n.Prefix {
if getNextNibble(key, depth+i*BranchBits) != expectedNibble {
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)
return get(n.Children[finalNibble], depth+len(n.Prefix)*BranchBits+BranchBits)
}
@ -476,7 +487,7 @@ func (t *VectorCommitmentTree) Get(key []byte) ([]byte, error) {
}
// Delete removes a key-value pair from the tree
func (t *VectorCommitmentTree) Delete(key []byte) error {
func (t *RawVectorCommitmentTree) Delete(key []byte) error {
if len(key) == 0 {
return errors.New("empty key not allowed")
}
@ -497,13 +508,13 @@ func (t *VectorCommitmentTree) Delete(key []byte) error {
case *VectorCommitmentBranchNode:
for i, expectedNibble := range n.Prefix {
currentNibble := getNextNibble(key, depth+i*BranchBits)
currentNibble := GetNextNibble(key, depth+i*BranchBits)
if currentNibble != expectedNibble {
return big.NewInt(0), n
}
}
finalNibble := getNextNibble(key, depth+len(n.Prefix)*BranchBits)
finalNibble := GetNextNibble(key, depth+len(n.Prefix)*BranchBits)
var size *big.Int
size, n.Children[finalNibble] =
remove(n.Children[finalNibble], depth+len(n.Prefix)*BranchBits+BranchBits)
@ -568,7 +579,10 @@ func (t *VectorCommitmentTree) Delete(key []byte) error {
return nil
}
func (t *VectorCommitmentTree) GetMetadata() (leafCount int, longestBranch int) {
func (t *RawVectorCommitmentTree) GetMetadata() (
leafCount int,
longestBranch int,
) {
switch root := t.Root.(type) {
case nil:
return 0, 0
@ -581,14 +595,14 @@ func (t *VectorCommitmentTree) GetMetadata() (leafCount int, longestBranch int)
}
// Commit returns the root of the tree
func (t *VectorCommitmentTree) Commit(recalculate bool) []byte {
func (t *RawVectorCommitmentTree) Commit(recalculate bool) []byte {
if t.Root == nil {
return make([]byte, 64)
}
return t.Root.Commit(recalculate)
}
func (t *VectorCommitmentTree) GetSize() *big.Int {
func (t *RawVectorCommitmentTree) GetSize() *big.Int {
return t.Root.GetSize()
}

View File

@ -11,7 +11,7 @@ import (
)
func BenchmarkVectorCommitmentTreeInsert(b *testing.B) {
tree := &VectorCommitmentTree{}
tree := &RawVectorCommitmentTree{}
addresses := [][]byte{}
for i := range b.N {
@ -26,7 +26,7 @@ func BenchmarkVectorCommitmentTreeInsert(b *testing.B) {
}
func BenchmarkVectorCommitmentTreeCommit(b *testing.B) {
tree := &VectorCommitmentTree{}
tree := &RawVectorCommitmentTree{}
addresses := [][]byte{}
for i := range b.N {
@ -42,7 +42,7 @@ func BenchmarkVectorCommitmentTreeCommit(b *testing.B) {
}
func BenchmarkVectorCommitmentTreeProve(b *testing.B) {
tree := &VectorCommitmentTree{}
tree := &RawVectorCommitmentTree{}
addresses := [][]byte{}
for i := range b.N {
@ -58,7 +58,7 @@ func BenchmarkVectorCommitmentTreeProve(b *testing.B) {
}
func BenchmarkVectorCommitmentTreeVerify(b *testing.B) {
tree := &VectorCommitmentTree{}
tree := &RawVectorCommitmentTree{}
addresses := [][]byte{}
for i := range b.N {
@ -78,7 +78,7 @@ func BenchmarkVectorCommitmentTreeVerify(b *testing.B) {
func TestVectorCommitmentTrees(t *testing.T) {
bls48581.Init()
tree := &VectorCommitmentTree{}
tree := &RawVectorCommitmentTree{}
// Test single insert
err := tree.Insert([]byte("key1"), []byte("value1"), nil, big.NewInt(1))
@ -106,7 +106,7 @@ func TestVectorCommitmentTrees(t *testing.T) {
t.Error("Expected error for empty key, got none")
}
tree = &VectorCommitmentTree{}
tree = &RawVectorCommitmentTree{}
// Test get on empty tree
_, err = tree.Get([]byte("nonexistent"))
@ -130,7 +130,7 @@ func TestVectorCommitmentTrees(t *testing.T) {
t.Error("Expected error for empty key, got none")
}
tree = &VectorCommitmentTree{}
tree = &RawVectorCommitmentTree{}
// Test delete on empty tree
err = tree.Delete([]byte("nonexistent"))
@ -157,7 +157,7 @@ func TestVectorCommitmentTrees(t *testing.T) {
t.Error("Expected error for empty key, got none")
}
tree = &VectorCommitmentTree{}
tree = &RawVectorCommitmentTree{}
// Insert keys that share common prefix
keys := []string{
@ -212,7 +212,7 @@ func TestVectorCommitmentTrees(t *testing.T) {
}
}
tree = &VectorCommitmentTree{}
tree = &RawVectorCommitmentTree{}
// Empty tree should be empty
emptyRoot := tree.Root
@ -244,8 +244,8 @@ func TestVectorCommitmentTrees(t *testing.T) {
t.Error("Root hash should match empty tree after deleting all entries")
}
tree = &VectorCommitmentTree{}
cmptree := &VectorCommitmentTree{}
tree = &RawVectorCommitmentTree{}
cmptree := &RawVectorCommitmentTree{}
addresses := [][]byte{}
@ -332,7 +332,7 @@ func TestVectorCommitmentTrees(t *testing.T) {
t.Errorf("invalid tree size: %s", tree.GetSize().String())
}
cmptree = &VectorCommitmentTree{}
cmptree = &RawVectorCommitmentTree{}
for i := 0; i < 10000; i++ {
cmptree.Insert(kept[i], kept[i], nil, big.NewInt(1))

View File

@ -6,7 +6,7 @@ import (
)
// CompareTreesAtHeight compares two vector commitment trees at each level
func CompareTreesAtHeight(tree1, tree2 *VectorCommitmentTree) [][]ComparisonResult {
func CompareTreesAtHeight(tree1, tree2 *RawVectorCommitmentTree) [][]ComparisonResult {
if tree1 == nil || tree2 == nil {
return nil
}
@ -104,7 +104,7 @@ func compareLevelCommits(node1, node2 VectorCommitmentNode, targetHeight, curren
// If we're still below target height after prefix, traverse children
if nextHeight < targetHeight {
for i := 0; i < BranchNodes; i++ {
for i := 0; i < NodesPerBranch; i++ {
childResults := compareLevelCommits(n1.Children[i], n2.Children[i], targetHeight, nextHeight+1)
results = append(results, childResults...)
}
@ -115,7 +115,7 @@ func compareLevelCommits(node1, node2 VectorCommitmentNode, targetHeight, curren
}
// TraverseAndCompare provides a channel-based iterator for comparing trees
func TraverseAndCompare(tree1, tree2 *VectorCommitmentTree) chan ComparisonResult {
func TraverseAndCompare(tree1, tree2 *RawVectorCommitmentTree) chan ComparisonResult {
resultChan := make(chan ComparisonResult)
go func() {
@ -150,7 +150,7 @@ type LeafDifference struct {
}
// CompareLeaves returns all leaves that differ between the two trees
func CompareLeaves(tree1, tree2 *VectorCommitmentTree) []LeafDifference {
func CompareLeaves(tree1, tree2 *RawVectorCommitmentTree) []LeafDifference {
// Get all leaves from both trees
leaves1 := GetAllLeaves(tree1.Root)
leaves2 := GetAllLeaves(tree2.Root)
@ -231,8 +231,8 @@ func GetAllLeaves(node VectorCommitmentNode) []*VectorCommitmentLeafNode {
func ExampleComparison() {
// Create and populate two trees
tree1 := &VectorCommitmentTree{}
tree2 := &VectorCommitmentTree{}
tree1 := &RawVectorCommitmentTree{}
tree2 := &RawVectorCommitmentTree{}
// Compare trees using channel-based iterator
for result := range TraverseAndCompare(tree1, tree2) {

View File

@ -148,7 +148,18 @@ func NewTokenExecutionEngine(
var inclusionProof *qcrypto.InclusionAggregateProof
var proverKeys [][]byte
var peerSeniority map[string]uint64
hg := hypergraph.NewHypergraph()
hg := hypergraph.NewHypergraph(
func(
shardKey hypergraph.ShardKey,
phaseSet protobufs.HypergraphPhaseSet,
) qcrypto.VectorCommitmentTree {
return store.NewPersistentVectorTree(
hypergraphStore,
shardKey,
phaseSet,
)
},
)
mpcithVerEnc := qcrypto.NewMPCitHVerifiableEncryptor(
runtime.NumCPU(),
)
@ -484,7 +495,7 @@ func (e *TokenExecutionEngine) addBatchToHypergraph(batchKey [][]byte, batchValu
var wg sync.WaitGroup
throttle := make(chan struct{}, runtime.NumCPU())
batchCompressed := make([]hypergraph.Vertex, len(batchKey))
batchTrees := make([]*qcrypto.VectorCommitmentTree, len(batchKey))
batchTrees := make([]*qcrypto.RawVectorCommitmentTree, len(batchKey))
txn, err := e.hypergraphStore.NewTransaction(false)
if err != nil {
panic(err)
@ -639,7 +650,18 @@ func (e *TokenExecutionEngine) hyperSync() {
func (e *TokenExecutionEngine) rebuildHypergraph() {
e.logger.Info("rebuilding hypergraph")
e.hypergraph = hypergraph.NewHypergraph()
e.hypergraph = hypergraph.NewHypergraph(
func(
shardKey hypergraph.ShardKey,
phaseSet protobufs.HypergraphPhaseSet,
) qcrypto.VectorCommitmentTree {
return store.NewPersistentVectorTree(
e.hypergraphStore,
shardKey,
phaseSet,
)
},
)
if e.engineConfig.RebuildStart == "" {
e.engineConfig.RebuildStart = "0000000000000000000000000000000000000000000000000000000000000000"
}

View File

@ -23,10 +23,8 @@ replace github.com/libp2p/go-libp2p-kad-dht => ../go-libp2p-kad-dht
replace source.quilibrium.com/quilibrium/monorepo/go-libp2p-blossomsub => ../go-libp2p-blossomsub
replace github.com/cockroachdb/pebble => ../pebble
require (
github.com/cockroachdb/pebble v0.0.0-20231210175920-b4d301aeb46a
github.com/cockroachdb/pebble v1.1.4
github.com/deiu/rdf2go v0.0.0-20240619132609-81222e324bb9
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1
github.com/klauspost/reedsolomon v1.12.4
@ -45,8 +43,8 @@ require (
require (
filippo.io/edwards25519 v1.0.0-rc.1 // indirect
github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce // indirect
github.com/deiu/gon3 v0.0.0-20230411081920-f0f8f879f597 // indirect
github.com/google/subcommands v1.0.1 // indirect
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 // indirect
github.com/libp2p/go-libp2p-routing-helpers v0.7.2 // indirect
github.com/linkeddata/gojsonld v0.0.0-20170418210642-4f5db6791326 // indirect
@ -80,14 +78,14 @@ require (
github.com/bwesterb/go-ristretto v1.2.3 // indirect
github.com/charmbracelet/bubbletea v0.24.2
github.com/charmbracelet/lipgloss v0.9.1
github.com/cockroachdb/errors v1.11.1 // indirect
github.com/cockroachdb/errors v1.11.3 // indirect
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect
github.com/cockroachdb/redact v1.1.5 // indirect
github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect
github.com/consensys/gnark-crypto v0.5.3 // indirect
github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/getsentry/sentry-go v0.18.0 // indirect
github.com/getsentry/sentry-go v0.27.0 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/gorilla/websocket v1.5.3 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0
@ -112,7 +110,6 @@ require (
require (
github.com/benbjohnson/clock v1.3.5 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cbergoon/merkletree v0.2.0
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/cloudflare/circl v1.3.9
github.com/containerd/cgroups v1.1.0 // indirect

View File

@ -42,8 +42,6 @@ github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46f
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
github.com/bwesterb/go-ristretto v1.2.3 h1:1w53tCkGhCQ5djbat3+MH0BAQ5Kfgbt56UZQ/JMzngw=
github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
github.com/cbergoon/merkletree v0.2.0 h1:Bttqr3OuoiZEo4ed1L7fTasHka9II+BF9fhBfbNEEoQ=
github.com/cbergoon/merkletree v0.2.0/go.mod h1:5c15eckUgiucMGDOCanvalj/yJnD+KAZj1qyJtRW5aM=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@ -58,12 +56,14 @@ github.com/cloudflare/circl v1.3.9/go.mod h1:PDRU+oXvdD7KCtgKxW95M5Z8BpSCJXQORiZ
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f h1:otljaYPt5hWxV3MUfO5dFPFiOXg9CyG5/kCfayTqsJ4=
github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU=
github.com/cockroachdb/errors v1.11.1 h1:xSEW75zKaKCWzR3OfxXUxgrk/NtT4G1MiOv5lWZazG8=
github.com/cockroachdb/errors v1.11.1/go.mod h1:8MUxA3Gi6b25tYlFEBGLf+D8aISL+M4MIpiWMSNRfxw=
github.com/cockroachdb/errors v1.11.3 h1:5bA+k2Y6r+oz/6Z/RFlNeVCesGARKuC6YymtcDrbC/I=
github.com/cockroachdb/errors v1.11.3/go.mod h1:m4UIW4CDjx+R5cybPsNrRbreomiFqt8o1h1wUVazSd8=
github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce h1:giXvy4KSc/6g/esnpM7Geqxka4WSqI1SZc7sMJFd3y4=
github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce/go.mod h1:9/y3cnZ5GKakj/H4y9r9GTjCvAFta7KLgSHPJJYc52M=
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE=
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs=
github.com/cockroachdb/metamorphic v0.0.0-20231108215700-4ba948b56895 h1:XANOgPYtvELQ/h4IrmPAohXqe2pWA8Bwhejr3VQoZsA=
github.com/cockroachdb/metamorphic v0.0.0-20231108215700-4ba948b56895/go.mod h1:aPd7gM9ov9M8v32Yy5NJrDyOcD8z642dqs+F0CeNXfA=
github.com/cockroachdb/pebble v1.1.4 h1:5II1uEP4MyHLDnsrbv/EZ36arcb9Mxg3n+owhZ3GrG8=
github.com/cockroachdb/pebble v1.1.4/go.mod h1:4exszw1r40423ZsmkG/09AFEG83I0uDgfujJdbL6kYU=
github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30=
github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg=
github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo=
@ -117,8 +117,8 @@ github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiD
github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/getsentry/sentry-go v0.18.0 h1:MtBW5H9QgdcJabtZcuJG80BMOwaBpkRDZkxRkNC1sN0=
github.com/getsentry/sentry-go v0.18.0/go.mod h1:Kgon4Mby+FJ7ZWHFUAZgVaIa8sxHtnRJRLTXZr51aKQ=
github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps=
github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
@ -183,7 +183,6 @@ github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OI
github.com/google/pprof v0.0.0-20240207164012-fb44976bdcd5 h1:E/LAvt58di64hlYjx7AsNS6C/ysHWYo+2qPCZKTQhRo=
github.com/google/pprof v0.0.0-20240207164012-fb44976bdcd5/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/subcommands v1.0.1 h1:/eqq+otEXm5vhfBrbREPCSVQbvofip6kIz+mX5TUH7k=
github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=

View File

@ -9,6 +9,7 @@ import (
"github.com/pkg/errors"
"source.quilibrium.com/quilibrium/monorepo/node/crypto"
"source.quilibrium.com/quilibrium/monorepo/node/p2p"
"source.quilibrium.com/quilibrium/monorepo/node/protobufs"
)
type AtomType string
@ -72,7 +73,7 @@ type hyperedge struct {
appAddress [32]byte
dataAddress [32]byte
extrinsics map[[64]byte]Atom
extTree *crypto.VectorCommitmentTree
extTree *crypto.RawVectorCommitmentTree
}
var _ Vertex = (*vertex)(nil)
@ -89,8 +90,8 @@ type Atom interface {
Commit() []byte
}
func EncryptedToVertexTree(encrypted []Encrypted) *crypto.VectorCommitmentTree {
dataTree := &crypto.VectorCommitmentTree{}
func EncryptedToVertexTree(encrypted []Encrypted) *crypto.RawVectorCommitmentTree {
dataTree := &crypto.RawVectorCommitmentTree{}
for _, d := range encrypted {
dataBytes := d.ToBytes()
id := sha512.Sum512(dataBytes)
@ -118,7 +119,7 @@ func AtomFromBytes(data []byte) Atom {
size: new(big.Int).SetBytes(data[len(data)-32:]),
}
} else {
tree := &crypto.VectorCommitmentTree{}
tree := &crypto.RawVectorCommitmentTree{}
var b bytes.Buffer
b.Write(data[65:])
dec := gob.NewDecoder(&b)
@ -162,7 +163,7 @@ func NewHyperedge(
appAddress: appAddress,
dataAddress: dataAddress,
extrinsics: make(map[[64]byte]Atom),
extTree: &crypto.VectorCommitmentTree{},
extTree: &crypto.RawVectorCommitmentTree{},
}
}
@ -330,48 +331,38 @@ type IdSet struct {
dirty bool
atomType AtomType
atoms map[[64]byte]Atom
tree *crypto.VectorCommitmentTree
tree crypto.VectorCommitmentTree
}
func NewIdSet(atomType AtomType) *IdSet {
func NewIdSet(
shardKey ShardKey,
phaseSet protobufs.HypergraphPhaseSet,
tree crypto.VectorCommitmentTree,
) *IdSet {
atomType := VertexAtomType
switch phaseSet {
case protobufs.HypergraphPhaseSet_HYPERGRAPH_PHASE_SET_VERTEX_ADDS:
fallthrough
case protobufs.HypergraphPhaseSet_HYPERGRAPH_PHASE_SET_VERTEX_REMOVES:
atomType = VertexAtomType
case protobufs.HypergraphPhaseSet_HYPERGRAPH_PHASE_SET_HYPEREDGE_ADDS:
fallthrough
case protobufs.HypergraphPhaseSet_HYPERGRAPH_PHASE_SET_HYPEREDGE_REMOVES:
atomType = HyperedgeAtomType
}
return &IdSet{
dirty: false,
atomType: atomType,
atoms: make(map[[64]byte]Atom),
tree: &crypto.VectorCommitmentTree{},
tree: tree,
}
}
func (set *IdSet) FromBytes(treeData []byte) error {
set.tree = &crypto.VectorCommitmentTree{}
var b bytes.Buffer
b.Write(treeData)
dec := gob.NewDecoder(&b)
if err := dec.Decode(set.tree); err != nil {
return errors.Wrap(err, "load set")
}
for _, leaf := range crypto.GetAllLeaves(set.tree.Root) {
set.atoms[[64]byte(leaf.Key)] = AtomFromBytes(leaf.Value)
}
return nil
}
func (set *IdSet) IsDirty() bool {
return set.dirty
}
func (set *IdSet) ToBytes() []byte {
var buf bytes.Buffer
enc := gob.NewEncoder(&buf)
if err := enc.Encode(set.tree); err != nil {
return nil
}
return buf.Bytes()
}
func (set *IdSet) Add(atom Atom) error {
if atom.GetAtomType() != set.atomType {
return ErrInvalidAtomType
@ -412,21 +403,31 @@ func (set *IdSet) Has(key [64]byte) bool {
return ok
}
func (set *IdSet) GetTree() *crypto.VectorCommitmentTree {
func (set *IdSet) GetTree() crypto.VectorCommitmentTree {
return set.tree
}
type Hypergraph struct {
size *big.Int
size *big.Int
treeConstructor func(
shardKey ShardKey,
phaseSet protobufs.HypergraphPhaseSet,
) crypto.VectorCommitmentTree
vertexAdds map[ShardKey]*IdSet
vertexRemoves map[ShardKey]*IdSet
hyperedgeAdds map[ShardKey]*IdSet
hyperedgeRemoves map[ShardKey]*IdSet
}
func NewHypergraph() *Hypergraph {
func NewHypergraph(
treeConstructor func(
shardKey ShardKey,
phaseSet protobufs.HypergraphPhaseSet,
) crypto.VectorCommitmentTree,
) *Hypergraph {
return &Hypergraph{
size: big.NewInt(0),
treeConstructor: treeConstructor,
vertexAdds: make(map[ShardKey]*IdSet),
vertexRemoves: make(map[ShardKey]*IdSet),
hyperedgeAdds: make(map[ShardKey]*IdSet),
@ -467,36 +468,26 @@ func (hg *Hypergraph) Commit() [][]byte {
return commits
}
func (hg *Hypergraph) ImportFromBytes(
atomType AtomType,
phaseType PhaseType,
func (hg *Hypergraph) SetIdSet(
shardKey ShardKey,
data []byte,
phaseSet protobufs.HypergraphPhaseSet,
tree crypto.VectorCommitmentTree,
) error {
set := NewIdSet(atomType)
if err := set.FromBytes(data); err != nil {
return errors.Wrap(err, "import from bytes")
}
set := NewIdSet(shardKey, phaseSet, tree)
switch atomType {
case VertexAtomType:
switch phaseType {
case AddsPhaseType:
hg.size.Add(hg.size, set.GetSize())
hg.vertexAdds[shardKey] = set
case RemovesPhaseType:
hg.size.Sub(hg.size, set.GetSize())
hg.vertexRemoves[shardKey] = set
}
case HyperedgeAtomType:
switch phaseType {
case AddsPhaseType:
hg.size.Add(hg.size, set.GetSize())
hg.hyperedgeAdds[shardKey] = set
case RemovesPhaseType:
hg.size.Sub(hg.size, set.GetSize())
hg.hyperedgeRemoves[shardKey] = set
}
switch phaseSet {
case protobufs.HypergraphPhaseSet_HYPERGRAPH_PHASE_SET_VERTEX_ADDS:
hg.size.Add(hg.size, set.GetSize())
hg.vertexAdds[shardKey] = set
case protobufs.HypergraphPhaseSet_HYPERGRAPH_PHASE_SET_VERTEX_REMOVES:
hg.size.Sub(hg.size, set.GetSize())
hg.vertexRemoves[shardKey] = set
case protobufs.HypergraphPhaseSet_HYPERGRAPH_PHASE_SET_HYPEREDGE_ADDS:
hg.size.Add(hg.size, set.GetSize())
hg.hyperedgeAdds[shardKey] = set
case protobufs.HypergraphPhaseSet_HYPERGRAPH_PHASE_SET_HYPEREDGE_REMOVES:
hg.size.Sub(hg.size, set.GetSize())
hg.hyperedgeRemoves[shardKey] = set
}
return nil
@ -507,18 +498,32 @@ func (hg *Hypergraph) GetSize() *big.Int {
}
func (hg *Hypergraph) getOrCreateIdSet(
shardAddr ShardKey,
shardKey ShardKey,
addMap map[ShardKey]*IdSet,
removeMap map[ShardKey]*IdSet,
atomType AtomType,
) (*IdSet, *IdSet) {
if _, ok := addMap[shardAddr]; !ok {
addMap[shardAddr] = NewIdSet(atomType)
if _, ok := addMap[shardKey]; !ok {
phaseSet := protobufs.HypergraphPhaseSet_HYPERGRAPH_PHASE_SET_VERTEX_ADDS
if atomType == HyperedgeAtomType {
phaseSet = protobufs.HypergraphPhaseSet_HYPERGRAPH_PHASE_SET_HYPEREDGE_ADDS
}
addMap[shardKey] = NewIdSet(shardKey, phaseSet, hg.treeConstructor(
shardKey,
phaseSet,
))
}
if _, ok := removeMap[shardAddr]; !ok {
removeMap[shardAddr] = NewIdSet(atomType)
if _, ok := removeMap[shardKey]; !ok {
phaseSet := protobufs.HypergraphPhaseSet_HYPERGRAPH_PHASE_SET_VERTEX_REMOVES
if atomType == HyperedgeAtomType {
phaseSet = protobufs.HypergraphPhaseSet_HYPERGRAPH_PHASE_SET_HYPEREDGE_REMOVES
}
removeMap[shardKey] = NewIdSet(shardKey, phaseSet, hg.treeConstructor(
shardKey,
phaseSet,
))
}
return addMap[shardAddr], removeMap[shardAddr]
return addMap[shardKey], removeMap[shardKey]
}
func (hg *Hypergraph) AddVertex(v Vertex) error {
@ -687,37 +692,3 @@ func (hg *Hypergraph) Within(a, h Atom) bool {
}
return false
}
func (hg *Hypergraph) GetReconciledVertexSetForShard(
shardKey ShardKey,
) *IdSet {
vertices := NewIdSet(VertexAtomType)
if addSet, ok := hg.vertexAdds[shardKey]; ok {
removeSet := hg.vertexRemoves[shardKey]
for id, v := range addSet.atoms {
if !removeSet.Has(id) {
vertices.Add(v)
}
}
}
return vertices
}
func (hg *Hypergraph) GetReconciledHyperedgeSetForShard(
shardKey ShardKey,
) *IdSet {
hyperedges := NewIdSet(HyperedgeAtomType)
if addSet, ok := hg.hyperedgeAdds[shardKey]; ok {
removeSet := hg.hyperedgeRemoves[shardKey]
for _, h := range addSet.atoms {
if !removeSet.Has(h.GetID()) {
hyperedges.Add(h)
}
}
}
return hyperedges
}

View File

@ -10,8 +10,11 @@ import (
"time"
"github.com/cloudflare/circl/sign/ed448"
"go.uber.org/zap"
"source.quilibrium.com/quilibrium/monorepo/node/crypto"
"source.quilibrium.com/quilibrium/monorepo/node/hypergraph/application"
"source.quilibrium.com/quilibrium/monorepo/node/protobufs"
"source.quilibrium.com/quilibrium/monorepo/node/store"
)
type Operation struct {
@ -22,13 +25,13 @@ type Operation struct {
func TestConvergence(t *testing.T) {
numParties := 4
numOperations := 100000
numOperations := 10000
enc := crypto.NewMPCitHVerifiableEncryptor(1)
pub, _, _ := ed448.GenerateKey(crand.Reader)
data := enc.Encrypt(make([]byte, 20), pub)
verenc := data[0].Compress()
vertices := make([]application.Vertex, numOperations)
dataTree := &crypto.VectorCommitmentTree{}
dataTree := &crypto.RawVectorCommitmentTree{}
for _, d := range []application.Encrypted{verenc} {
dataBytes := d.ToBytes()
id := sha512.Sum512(dataBytes)
@ -77,9 +80,19 @@ func TestConvergence(t *testing.T) {
}
}
inmem := store.NewInMemKVDB()
logger, _ := zap.NewProduction()
hgStore := store.NewPebbleHypergraphStore(inmem, logger)
crdts := make([]*application.Hypergraph, numParties)
for i := 0; i < numParties; i++ {
crdts[i] = application.NewHypergraph()
crdts[i] = application.NewHypergraph(func(shardKey application.ShardKey, phaseSet protobufs.HypergraphPhaseSet) crypto.VectorCommitmentTree {
return store.NewPersistentVectorTree(
hgStore,
shardKey,
phaseSet,
)
})
}
for i := 0; i < numParties; i++ {

View File

@ -11,10 +11,13 @@ import (
"github.com/cloudflare/circl/sign/ed448"
"source.quilibrium.com/quilibrium/monorepo/node/crypto"
"source.quilibrium.com/quilibrium/monorepo/node/hypergraph/application"
"source.quilibrium.com/quilibrium/monorepo/node/protobufs"
)
func TestHypergraph(t *testing.T) {
hg := application.NewHypergraph()
hg := application.NewHypergraph(func(shardKey application.ShardKey, phaseSet protobufs.HypergraphPhaseSet) crypto.VectorCommitmentTree {
return &crypto.RawVectorCommitmentTree{}
})
// Test vertex operations
t.Run("Vertex Operations", func(t *testing.T) {
@ -22,7 +25,7 @@ func TestHypergraph(t *testing.T) {
pub, _, _ := ed448.GenerateKey(crand.Reader)
data := enc.Encrypt(make([]byte, 20), pub)
verenc := data[0].Compress()
dataTree := &crypto.VectorCommitmentTree{}
dataTree := &crypto.RawVectorCommitmentTree{}
for _, d := range []application.Encrypted{verenc} {
dataBytes := d.ToBytes()
id := sha512.Sum512(dataBytes)
@ -69,7 +72,7 @@ func TestHypergraph(t *testing.T) {
pub, _, _ := ed448.GenerateKey(crand.Reader)
data := enc.Encrypt(make([]byte, 20), pub)
verenc := data[0].Compress()
dataTree := &crypto.VectorCommitmentTree{}
dataTree := &crypto.RawVectorCommitmentTree{}
for _, d := range []application.Encrypted{verenc} {
dataBytes := d.ToBytes()
id := sha512.Sum512(dataBytes)
@ -113,7 +116,7 @@ func TestHypergraph(t *testing.T) {
pub, _, _ := ed448.GenerateKey(crand.Reader)
data := enc.Encrypt(make([]byte, 20), pub)
verenc := data[0].Compress()
dataTree := &crypto.VectorCommitmentTree{}
dataTree := &crypto.RawVectorCommitmentTree{}
for _, d := range []application.Encrypted{verenc} {
dataBytes := d.ToBytes()
id := sha512.Sum512(dataBytes)
@ -151,7 +154,7 @@ func TestHypergraph(t *testing.T) {
pub, _, _ := ed448.GenerateKey(crand.Reader)
data := enc.Encrypt(make([]byte, 20), pub)
verenc := data[0].Compress()
dataTree := &crypto.VectorCommitmentTree{}
dataTree := &crypto.RawVectorCommitmentTree{}
for _, d := range []application.Encrypted{verenc} {
dataBytes := d.ToBytes()
id := sha512.Sum512(dataBytes)
@ -186,7 +189,7 @@ func TestHypergraph(t *testing.T) {
pub, _, _ := ed448.GenerateKey(crand.Reader)
data := enc.Encrypt(make([]byte, 20), pub)
verenc := data[0].Compress()
dataTree := &crypto.VectorCommitmentTree{}
dataTree := &crypto.RawVectorCommitmentTree{}
for _, d := range []application.Encrypted{verenc} {
dataBytes := d.ToBytes()
id := sha512.Sum512(dataBytes)
@ -222,7 +225,7 @@ func TestHypergraph(t *testing.T) {
pub, _, _ := ed448.GenerateKey(crand.Reader)
data := enc.Encrypt(make([]byte, 20), pub)
verenc := data[0].Compress()
dataTree := &crypto.VectorCommitmentTree{}
dataTree := &crypto.RawVectorCommitmentTree{}
for _, d := range []application.Encrypted{verenc} {
dataBytes := d.ToBytes()
id := sha512.Sum512(dataBytes)

View File

@ -43,7 +43,7 @@ func NewHypergraphComparisonServer(
func sendLeafData(
stream protobufs.HypergraphComparisonService_HyperStreamClient,
hypergraphStore store.HypergraphStore,
localTree *crypto.VectorCommitmentTree,
localTree *crypto.RawVectorCommitmentTree,
path []int32,
metadataOnly bool,
) error {
@ -161,7 +161,7 @@ func getNodeAtPath(
// getBranchInfoFromTree looks up the node at the given path in the local tree,
// computes its commitment, and (if it is a branch) collects its immediate
// children's commitments.
func getBranchInfoFromTree(tree *crypto.VectorCommitmentTree, path []int32) (
func getBranchInfoFromTree(tree *crypto.RawVectorCommitmentTree, path []int32) (
*protobufs.HypergraphComparisonResponse,
error,
) {
@ -207,7 +207,7 @@ func isLeaf(info *protobufs.HypergraphComparisonResponse) bool {
func sendLeafDataServer(
stream protobufs.HypergraphComparisonService_HyperStreamServer,
hypergraphStore store.HypergraphStore,
localTree *crypto.VectorCommitmentTree,
localTree *crypto.RawVectorCommitmentTree,
path []int32,
metadataOnly bool,
) error {
@ -309,7 +309,10 @@ func syncTreeBidirectionallyServer(
// Send our root branch info.
rootPath := []int32{}
rootInfo, err := getBranchInfoFromTree(idSet.GetTree(), rootPath)
rootInfo, err := getBranchInfoFromTree(
idSet.GetTree().(*store.PersistentVectorTree).GetInternalTree(),
rootPath,
)
if err != nil {
return err
}
@ -374,7 +377,7 @@ func syncTreeBidirectionallyServer(
zap.String("path", hex.EncodeToString(packNibbles(remoteInfo.Path))),
)
localInfo, err := getBranchInfoFromTree(
idSet.GetTree(),
idSet.GetTree().(*store.PersistentVectorTree).GetInternalTree(),
remoteInfo.Path,
)
if err != nil {
@ -422,7 +425,7 @@ func syncTreeBidirectionallyServer(
if err := sendLeafDataServer(
stream,
localHypergraphStore,
idSet.GetTree(),
idSet.GetTree().(*store.PersistentVectorTree).GetInternalTree(),
remoteInfo.Path,
metadataOnly,
); err != nil {
@ -477,7 +480,7 @@ func syncTreeBidirectionallyServer(
if err := sendLeafDataServer(
stream,
localHypergraphStore,
idSet.GetTree(),
idSet.GetTree().(*store.PersistentVectorTree).GetInternalTree(),
queryPath,
metadataOnly,
); err != nil {
@ -491,7 +494,10 @@ func syncTreeBidirectionallyServer(
hex.EncodeToString(packNibbles(queryPath)),
),
)
branchInfo, err := getBranchInfoFromTree(idSet.GetTree(), queryPath)
branchInfo, err := getBranchInfoFromTree(
idSet.GetTree().(*store.PersistentVectorTree).GetInternalTree(),
queryPath,
)
if err != nil {
continue
}
@ -518,7 +524,7 @@ func syncTreeBidirectionallyServer(
if err != nil {
return err
}
tree := &crypto.VectorCommitmentTree{}
tree := &crypto.RawVectorCommitmentTree{}
var b bytes.Buffer
b.Write(remoteUpdate.UnderlyingData)
@ -570,7 +576,7 @@ func SyncTreeBidirectionally(
shardKey []byte,
phaseSet protobufs.HypergraphPhaseSet,
hypergraphStore store.HypergraphStore,
localTree *crypto.VectorCommitmentTree,
localTree crypto.VectorCommitmentTree,
metadataOnly bool,
) error {
logger.Info(
@ -593,7 +599,10 @@ func SyncTreeBidirectionally(
}
rootPath := []int32{}
rootInfo, err := getBranchInfoFromTree(localTree, rootPath)
rootInfo, err := getBranchInfoFromTree(
localTree.(*store.PersistentVectorTree).GetInternalTree(),
rootPath,
)
if err != nil {
return err
}
@ -653,7 +662,10 @@ func SyncTreeBidirectionally(
"handling response",
zap.String("path", hex.EncodeToString(packNibbles(remoteInfo.Path))),
)
localInfo, err := getBranchInfoFromTree(localTree, remoteInfo.Path)
localInfo, err := getBranchInfoFromTree(
localTree.(*store.PersistentVectorTree).GetInternalTree(),
remoteInfo.Path,
)
if err != nil {
logger.Info(
"requesting missing node",
@ -695,7 +707,7 @@ func SyncTreeBidirectionally(
if err := sendLeafData(
stream,
hypergraphStore,
localTree,
localTree.(*store.PersistentVectorTree).GetInternalTree(),
remoteInfo.Path,
metadataOnly,
); err != nil {
@ -750,7 +762,7 @@ func SyncTreeBidirectionally(
if err := sendLeafData(
stream,
hypergraphStore,
localTree,
localTree.(*store.PersistentVectorTree).GetInternalTree(),
queryPath,
metadataOnly,
); err != nil {
@ -764,7 +776,10 @@ func SyncTreeBidirectionally(
hex.EncodeToString(packNibbles(queryPath)),
),
)
branchInfo, err := getBranchInfoFromTree(localTree, queryPath)
branchInfo, err := getBranchInfoFromTree(
localTree.(*store.PersistentVectorTree).GetInternalTree(),
queryPath,
)
if err != nil {
continue
}
@ -792,7 +807,7 @@ func SyncTreeBidirectionally(
if err != nil {
return err
}
tree := &crypto.VectorCommitmentTree{}
tree := &crypto.RawVectorCommitmentTree{}
var b bytes.Buffer
b.Write(remoteUpdate.UnderlyingData)

View File

@ -12,6 +12,7 @@ import (
"testing"
"github.com/cloudflare/circl/sign/ed448"
"github.com/stretchr/testify/assert"
"go.uber.org/zap"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
@ -37,7 +38,7 @@ func TestHypergraphSyncServer(t *testing.T) {
data := enc.Encrypt(make([]byte, 20), pub)
verenc := data[0].Compress()
vertices := make([]application.Vertex, numOperations)
dataTree := &crypto.VectorCommitmentTree{}
dataTree := &crypto.RawVectorCommitmentTree{}
for _, d := range []application.Encrypted{verenc} {
dataBytes := d.ToBytes()
id := sha512.Sum512(dataBytes)
@ -88,15 +89,35 @@ func TestHypergraphSyncServer(t *testing.T) {
}
}
clientKvdb := store.NewInMemKVDB()
serverKvdb := store.NewInMemKVDB()
clientKvdb := store.NewInMemKVDB()
controlKvdb := store.NewInMemKVDB()
logger, _ := zap.NewProduction()
clientHypergraphStore := store.NewPebbleHypergraphStore(clientKvdb, logger)
serverHypergraphStore := store.NewPebbleHypergraphStore(serverKvdb, logger)
clientHypergraphStore := store.NewPebbleHypergraphStore(clientKvdb, logger)
controlHypergraphStore := store.NewPebbleHypergraphStore(controlKvdb, logger)
crdts := make([]*application.Hypergraph, numParties)
for i := 0; i < numParties; i++ {
crdts[i] = application.NewHypergraph()
}
crdts[0] = application.NewHypergraph(func(shardKey application.ShardKey, phaseSet protobufs.HypergraphPhaseSet) crypto.VectorCommitmentTree {
return store.NewPersistentVectorTree(
serverHypergraphStore,
shardKey,
phaseSet,
)
})
crdts[1] = application.NewHypergraph(func(shardKey application.ShardKey, phaseSet protobufs.HypergraphPhaseSet) crypto.VectorCommitmentTree {
return store.NewPersistentVectorTree(
clientHypergraphStore,
shardKey,
phaseSet,
)
})
crdts[2] = application.NewHypergraph(func(shardKey application.ShardKey, phaseSet protobufs.HypergraphPhaseSet) crypto.VectorCommitmentTree {
return store.NewPersistentVectorTree(
controlHypergraphStore,
shardKey,
phaseSet,
)
})
txn, _ := serverHypergraphStore.NewTransaction(false)
for _, op := range operations1[:5000] {
@ -114,7 +135,7 @@ func TestHypergraphSyncServer(t *testing.T) {
}
}
txn.Commit()
for _, op := range operations2[:500] {
for _, op := range operations2[:5000] {
switch op.Type {
case "AddVertex":
crdts[0].AddVertex(op.Vertex)
@ -143,7 +164,7 @@ func TestHypergraphSyncServer(t *testing.T) {
}
}
txn.Commit()
for _, op := range operations2[500:] {
for _, op := range operations2[5000:] {
switch op.Type {
case "AddVertex":
crdts[1].AddVertex(op.Vertex)
@ -184,7 +205,31 @@ func TestHypergraphSyncServer(t *testing.T) {
crdts[0].Commit()
crdts[1].Commit()
crdts[2].Commit()
txn, _ = serverHypergraphStore.NewTransaction(false)
serverHypergraphStore.SaveHypergraph(txn, crdts[0])
txn.Commit()
txn, _ = clientHypergraphStore.NewTransaction(false)
clientHypergraphStore.SaveHypergraph(txn, crdts[1])
txn.Commit()
txn, _ = controlHypergraphStore.NewTransaction(false)
controlHypergraphStore.SaveHypergraph(txn, crdts[2])
txn.Commit()
var err error
eval0, err := serverHypergraphStore.LoadHypergraph()
assert.NoError(t, err)
eval1, err := clientHypergraphStore.LoadHypergraph()
assert.NoError(t, err)
log.Printf("Generated data")
leaves0 := crypto.CompareLeaves(
crdts[0].GetVertexAdds()[shardKey].GetTree().(*store.PersistentVectorTree).GetInternalTree(),
eval0.GetVertexAdds()[shardKey].GetTree().(*store.PersistentVectorTree).GetInternalTree(),
)
leaves1 := crypto.CompareLeaves(
crdts[1].GetVertexAdds()[shardKey].GetTree().(*store.PersistentVectorTree).GetInternalTree(),
eval1.GetVertexAdds()[shardKey].GetTree().(*store.PersistentVectorTree).GetInternalTree(),
)
assert.Len(t, leaves0, 0)
assert.Len(t, leaves1, 0)
lis, err := net.Listen("tcp", ":50051")
if err != nil {
@ -212,14 +257,22 @@ func TestHypergraphSyncServer(t *testing.T) {
log.Fatalf("Client: failed to stream: %v", err)
}
err = rpc.SyncTreeBidirectionally(str, logger, append(append([]byte{}, shardKey.L1[:]...), shardKey.L2[:]...), protobufs.HypergraphPhaseSet_HYPERGRAPH_PHASE_SET_VERTEX_ADDS, clientHypergraphStore, crdts[1].GetVertexAdds()[shardKey].GetTree(), false)
err = rpc.SyncTreeBidirectionally(
str,
logger,
append(append([]byte{}, shardKey.L1[:]...), shardKey.L2[:]...),
protobufs.HypergraphPhaseSet_HYPERGRAPH_PHASE_SET_VERTEX_ADDS,
clientHypergraphStore,
crdts[1].GetVertexAdds()[shardKey].GetTree(),
false,
)
if err != nil {
log.Fatalf("Client: failed to sync 1: %v", err)
}
leaves := crypto.CompareLeaves(
crdts[0].GetVertexAdds()[shardKey].GetTree(),
crdts[1].GetVertexAdds()[shardKey].GetTree(),
crdts[0].GetVertexAdds()[shardKey].GetTree().(*store.PersistentVectorTree).GetInternalTree(),
crdts[1].GetVertexAdds()[shardKey].GetTree().(*store.PersistentVectorTree).GetInternalTree(),
)
fmt.Println(len(leaves))
@ -241,8 +294,8 @@ func TestHypergraphSyncServer(t *testing.T) {
crdts[1].GetVertexAdds()[shardKey].GetTree().Commit(false),
) {
leaves := crypto.CompareLeaves(
crdts[0].GetVertexAdds()[shardKey].GetTree(),
crdts[1].GetVertexAdds()[shardKey].GetTree(),
crdts[0].GetVertexAdds()[shardKey].GetTree().(*store.PersistentVectorTree).GetInternalTree(),
crdts[1].GetVertexAdds()[shardKey].GetTree().(*store.PersistentVectorTree).GetInternalTree(),
)
fmt.Println(len(leaves))
log.Fatalf(

View File

@ -104,11 +104,11 @@ type ClockStore interface {
minFrameNumber uint64,
maxFrameNumber uint64,
) error
GetDataStateTree(filter []byte) (*crypto.VectorCommitmentTree, error)
GetDataStateTree(filter []byte) (*crypto.RawVectorCommitmentTree, error)
SetDataStateTree(
txn Transaction,
filter []byte,
tree *crypto.VectorCommitmentTree,
tree *crypto.RawVectorCommitmentTree,
) error
}
@ -1696,7 +1696,7 @@ func (p *PebbleClockStore) SetProverTriesForFrame(
}
func (p *PebbleClockStore) GetDataStateTree(filter []byte) (
*crypto.VectorCommitmentTree,
*crypto.RawVectorCommitmentTree,
error,
) {
data, closer, err := p.db.Get(clockDataStateTreeKey(filter))
@ -1708,7 +1708,7 @@ func (p *PebbleClockStore) GetDataStateTree(filter []byte) (
return nil, errors.Wrap(err, "get data state tree")
}
defer closer.Close()
tree := &crypto.VectorCommitmentTree{}
tree := &crypto.RawVectorCommitmentTree{}
var b bytes.Buffer
b.Write(data)
dec := gob.NewDecoder(&b)
@ -1722,7 +1722,7 @@ func (p *PebbleClockStore) GetDataStateTree(filter []byte) (
func (p *PebbleClockStore) SetDataStateTree(
txn Transaction,
filter []byte,
tree *crypto.VectorCommitmentTree,
tree *crypto.RawVectorCommitmentTree,
) error {
b := new(bytes.Buffer)
enc := gob.NewEncoder(b)

File diff suppressed because it is too large Load Diff