ceremonyclient/node/crypto/proof_tree_test.go
2025-01-21 16:15:35 -06:00

323 lines
7.6 KiB
Go

package crypto
import (
"bytes"
"crypto/rand"
"fmt"
"testing"
"go.uber.org/zap"
"source.quilibrium.com/quilibrium/monorepo/bls48581/generated/bls48581"
"source.quilibrium.com/quilibrium/monorepo/node/config"
)
func BenchmarkVectorCommitmentTreeInsert(b *testing.B) {
tree := &VectorCommitmentTree{}
addresses := [][]byte{}
for i := range b.N {
d := make([]byte, 32)
rand.Read(d)
addresses = append(addresses, d)
err := tree.Insert(d, d)
if err != nil {
b.Errorf("Failed to insert item %d: %v", i, err)
}
}
}
func BenchmarkVectorCommitmentTreeCommit(b *testing.B) {
tree := &VectorCommitmentTree{}
addresses := [][]byte{}
log, _ := zap.NewProduction()
prover := NewKZGInclusionProver(log, &config.EngineConfig{PendingCommitWorkers: 1})
for i := range b.N {
d := make([]byte, 32)
rand.Read(d)
addresses = append(addresses, d)
err := tree.Insert(d, d)
if err != nil {
b.Errorf("Failed to insert item %d: %v", i, err)
}
tree.Commit(prover)
}
}
func BenchmarkVectorCommitmentTreeProve(b *testing.B) {
tree := &VectorCommitmentTree{}
addresses := [][]byte{}
log, _ := zap.NewProduction()
prover := NewKZGInclusionProver(log, &config.EngineConfig{PendingCommitWorkers: 1})
for i := range b.N {
d := make([]byte, 32)
rand.Read(d)
addresses = append(addresses, d)
err := tree.Insert(d, d)
if err != nil {
b.Errorf("Failed to insert item %d: %v", i, err)
}
tree.Prove(prover, d)
}
}
func BenchmarkVectorCommitmentTreeVerify(b *testing.B) {
tree := &VectorCommitmentTree{}
addresses := [][]byte{}
log, _ := zap.NewProduction()
prover := NewKZGInclusionProver(log, &config.EngineConfig{PendingCommitWorkers: 1})
for i := range b.N {
d := make([]byte, 32)
rand.Read(d)
addresses = append(addresses, d)
err := tree.Insert(d, d)
if err != nil {
b.Errorf("Failed to insert item %d: %v", i, err)
}
p := tree.Prove(prover, d)
if !tree.Verify(prover, d, p) {
b.Errorf("bad proof")
}
}
}
func TestVectorCommitmentTrees(t *testing.T) {
bls48581.Init()
tree := &VectorCommitmentTree{}
log, _ := zap.NewProduction()
prover := NewKZGInclusionProver(log, &config.EngineConfig{PendingCommitWorkers: 1})
// Test single insert
err := tree.Insert([]byte("key1"), []byte("value1"))
if err != nil {
t.Errorf("Failed to insert: %v", err)
}
// Test duplicate key
err = tree.Insert([]byte("key1"), []byte("value2"))
if err != nil {
t.Errorf("Failed to update existing key: %v", err)
}
value, err := tree.Get([]byte("key1"))
if err != nil {
t.Errorf("Failed to get value: %v", err)
}
if !bytes.Equal(value, []byte("value2")) {
t.Errorf("Expected value2, got %s", string(value))
}
// Test empty key
err = tree.Insert([]byte{}, []byte("value"))
if err == nil {
t.Error("Expected error for empty key, got none")
}
tree = &VectorCommitmentTree{}
// Test get on empty tree
_, err = tree.Get([]byte("nonexistent"))
if err == nil {
t.Error("Expected error for nonexistent key, got none")
}
// Insert and get
tree.Insert([]byte("key1"), []byte("value1"))
value, err = tree.Get([]byte("key1"))
if err != nil {
t.Errorf("Failed to get value: %v", err)
}
if !bytes.Equal(value, []byte("value1")) {
t.Errorf("Expected value1, got %s", string(value))
}
// Test empty key
_, err = tree.Get([]byte{})
if err == nil {
t.Error("Expected error for empty key, got none")
}
tree = &VectorCommitmentTree{}
// Test delete on empty tree
err = tree.Delete([]byte("nonexistent"))
if err != nil {
t.Errorf("Delete on empty tree should not return error: %v", err)
}
// Insert and delete
tree.Insert([]byte("key1"), []byte("value1"))
err = tree.Delete([]byte("key1"))
if err != nil {
t.Errorf("Failed to delete: %v", err)
}
// Verify deletion
_, err = tree.Get([]byte("key1"))
if err == nil {
t.Error("Expected error for deleted key, got none")
}
// Test empty key
err = tree.Delete([]byte{})
if err == nil {
t.Error("Expected error for empty key, got none")
}
tree = &VectorCommitmentTree{}
// Insert keys that share common prefix
keys := []string{
"key1",
"key2",
"key3",
"completely_different",
}
for i, key := range keys {
err := tree.Insert([]byte(key), []byte("value"+string(rune('1'+i))))
if err != nil {
t.Errorf("Failed to insert key %s: %v", key, err)
}
}
// Verify all values
for i, key := range keys {
value, err := tree.Get([]byte(key))
if err != nil {
t.Errorf("Failed to get key %s: %v", key, err)
}
expected := []byte("value" + string(rune('1'+i)))
if !bytes.Equal(value, expected) {
t.Errorf("Expected %s, got %s", string(expected), string(value))
}
}
// Delete middle key
err = tree.Delete([]byte("key2"))
if err != nil {
t.Errorf("Failed to delete key2: %v", err)
}
// Verify key2 is gone but others remain
_, err = tree.Get([]byte("key2"))
if err == nil {
t.Error("Expected error for deleted key2, got none")
}
// Check remaining keys
remainingKeys := []string{"key1", "key3", "completely_different"}
remainingValues := []string{"value1", "value3", "value4"}
for i, key := range remainingKeys {
value, err := tree.Get([]byte(key))
if err != nil {
t.Errorf("Failed to get key %s after deletion: %v", key, err)
}
expected := []byte(remainingValues[i])
if !bytes.Equal(value, expected) {
t.Errorf("Expected %s, got %s", string(expected), string(value))
}
}
tree = &VectorCommitmentTree{}
// Empty tree should be empty
emptyRoot := tree.Root
if emptyRoot != nil {
t.Errorf("Expected empty root")
}
// Root should change after insert
tree.Insert([]byte("key1"), []byte("value1"))
firstRoot := tree.Root.Commit(prover)
if bytes.Equal(firstRoot, bytes.Repeat([]byte{0x00}, 64)) {
t.Error("Root hash should change after insert")
}
// Root should change after update
tree.Insert([]byte("key1"), []byte("value2"))
secondRoot := tree.Root.Commit(prover)
if bytes.Equal(secondRoot, firstRoot) {
t.Error("Root hash should change after update")
}
// Root should change after delete
tree.Delete([]byte("key1"))
thirdRoot := tree.Root
if thirdRoot != nil {
t.Error("Root hash should match empty tree after deleting all entries")
}
tree = &VectorCommitmentTree{}
cmptree := &VectorCommitmentTree{}
addresses := [][]byte{}
for i := 0; i < 1000; i++ {
d := make([]byte, 32)
rand.Read(d)
addresses = append(addresses, d)
}
// Insert 1000 items
for i := 0; i < 1000; i++ {
key := addresses[i]
value := addresses[i]
err := tree.Insert(key, value)
if err != nil {
t.Errorf("Failed to insert item %d: %v", i, err)
}
}
// Insert 1000 items in reverse
for i := 999; i >= 0; i-- {
key := addresses[i]
value := addresses[i]
err := cmptree.Insert(key, value)
if err != nil {
t.Errorf("Failed to insert item %d: %v", i, err)
}
}
// Verify all items
for i := 0; i < 1000; i++ {
key := addresses[i]
expected := addresses[i]
value, err := tree.Get(key)
if err != nil {
t.Errorf("Failed to get item %d: %v", i, err)
}
cmpvalue, err := cmptree.Get(key)
if err != nil {
t.Errorf("Failed to get item %d: %v", i, err)
}
if !bytes.Equal(value, expected) {
t.Errorf("Item %d: expected %x, got %x", i, string(expected), string(value))
}
if !bytes.Equal(value, cmpvalue) {
t.Errorf("Item %d: expected %x, got %x", i, string(value), string(cmpvalue))
}
}
tcommit := tree.Root.Commit(prover)
cmptcommit := cmptree.Root.Commit(prover)
if !bytes.Equal(tcommit, cmptcommit) {
t.Errorf("tree mismatch, %x, %x", tcommit, cmptcommit)
}
proofs := tree.Prove(prover, addresses[500])
if !tree.Verify(prover, addresses[500], proofs) {
t.Errorf("proof failed")
}
for _, p := range proofs {
fmt.Printf("%x\n", p)
}
}