mirror of
https://github.com/QuilibriumNetwork/ceremonyclient.git
synced 2026-02-21 18:37:26 +08:00
384 lines
9.0 KiB
Go
384 lines
9.0 KiB
Go
package crypto
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/rand"
|
|
"fmt"
|
|
"math/big"
|
|
"testing"
|
|
|
|
"source.quilibrium.com/quilibrium/monorepo/bls48581/generated/bls48581"
|
|
)
|
|
|
|
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, nil, big.NewInt(1))
|
|
if err != nil {
|
|
b.Errorf("Failed to insert item %d: %v", i, err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func BenchmarkVectorCommitmentTreeCommit(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, nil, big.NewInt(1))
|
|
if err != nil {
|
|
b.Errorf("Failed to insert item %d: %v", i, err)
|
|
}
|
|
tree.Commit(false)
|
|
}
|
|
}
|
|
|
|
func BenchmarkVectorCommitmentTreeProve(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, nil, big.NewInt(1))
|
|
if err != nil {
|
|
b.Errorf("Failed to insert item %d: %v", i, err)
|
|
}
|
|
tree.Prove(d)
|
|
}
|
|
}
|
|
|
|
func BenchmarkVectorCommitmentTreeVerify(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, nil, big.NewInt(1))
|
|
if err != nil {
|
|
b.Errorf("Failed to insert item %d: %v", i, err)
|
|
}
|
|
p := tree.Prove(d)
|
|
if !tree.Verify(d, p) {
|
|
b.Errorf("bad proof")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestVectorCommitmentTrees(t *testing.T) {
|
|
bls48581.Init()
|
|
tree := &VectorCommitmentTree{}
|
|
|
|
// Test single insert
|
|
err := tree.Insert([]byte("key1"), []byte("value1"), nil, big.NewInt(1))
|
|
if err != nil {
|
|
t.Errorf("Failed to insert: %v", err)
|
|
}
|
|
|
|
// Test duplicate key
|
|
err = tree.Insert([]byte("key1"), []byte("value2"), nil, big.NewInt(1))
|
|
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"), nil, big.NewInt(1))
|
|
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"), nil, big.NewInt(1))
|
|
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"), nil, big.NewInt(1))
|
|
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))), nil, big.NewInt(1))
|
|
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"), nil, big.NewInt(1))
|
|
firstRoot := tree.Root.Commit(false)
|
|
|
|
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"), nil, big.NewInt(1))
|
|
secondRoot := tree.Root.Commit(false)
|
|
|
|
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 < 10000; i++ {
|
|
d := make([]byte, 32)
|
|
rand.Read(d)
|
|
addresses = append(addresses, d)
|
|
}
|
|
|
|
kept := [][]byte{}
|
|
for i := 0; i < 5000; i++ {
|
|
kept = append(kept, addresses[i])
|
|
}
|
|
|
|
newAdditions := [][]byte{}
|
|
for i := 0; i < 5000; i++ {
|
|
d := make([]byte, 32)
|
|
rand.Read(d)
|
|
newAdditions = append(newAdditions, d)
|
|
kept = append(kept, d)
|
|
}
|
|
|
|
// Insert 10000 items
|
|
for i := 0; i < 10000; i++ {
|
|
key := addresses[i]
|
|
value := addresses[i]
|
|
err := tree.Insert(key, value, nil, big.NewInt(1))
|
|
if err != nil {
|
|
t.Errorf("Failed to insert item %d: %v", i, err)
|
|
}
|
|
}
|
|
|
|
if tree.GetSize().Cmp(big.NewInt(10000)) != 0 {
|
|
t.Errorf("invalid tree size: %s", tree.GetSize().String())
|
|
}
|
|
|
|
// Insert 10000 items in reverse
|
|
for i := 9999; i >= 0; i-- {
|
|
key := addresses[i]
|
|
value := addresses[i]
|
|
err := cmptree.Insert(key, value, nil, big.NewInt(1))
|
|
if err != nil {
|
|
t.Errorf("Failed to insert item %d: %v", i, err)
|
|
}
|
|
}
|
|
|
|
// Verify all items
|
|
for i := 0; i < 10000; 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))
|
|
}
|
|
}
|
|
|
|
// delete keys
|
|
for i := 5000; i < 10000; i++ {
|
|
key := addresses[i]
|
|
fmt.Printf("delete %x\n", key)
|
|
tree.Delete(key)
|
|
}
|
|
|
|
if tree.GetSize().Cmp(big.NewInt(5000)) != 0 {
|
|
t.Errorf("invalid tree size: %s", tree.GetSize().String())
|
|
}
|
|
|
|
// add new
|
|
for i := 0; i < 5000; i++ {
|
|
tree.Insert(newAdditions[i], newAdditions[i], nil, big.NewInt(1))
|
|
}
|
|
|
|
if tree.GetSize().Cmp(big.NewInt(10000)) != 0 {
|
|
t.Errorf("invalid tree size: %s", tree.GetSize().String())
|
|
}
|
|
|
|
cmptree = &VectorCommitmentTree{}
|
|
|
|
for i := 0; i < 10000; i++ {
|
|
cmptree.Insert(kept[i], kept[i], nil, big.NewInt(1))
|
|
}
|
|
// Verify all items
|
|
for i := 0; i < 10000; i++ {
|
|
key := kept[i]
|
|
expected := kept[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(expected, cmpvalue) {
|
|
t.Errorf("Item %d: expected %x, got %x", i, string(value), string(cmpvalue))
|
|
}
|
|
}
|
|
tcommit := tree.Root.Commit(false)
|
|
cmptcommit := cmptree.Root.Commit(false)
|
|
|
|
if !bytes.Equal(tcommit, cmptcommit) {
|
|
t.Errorf("tree mismatch, %x, %x", tcommit, cmptcommit)
|
|
}
|
|
|
|
proofs := tree.Prove(addresses[500])
|
|
if !tree.Verify(addresses[500], proofs) {
|
|
t.Errorf("proof failed")
|
|
}
|
|
|
|
leaves, longestBranch := tree.GetMetadata()
|
|
|
|
if leaves != 10000 {
|
|
t.Errorf("incorrect leaf count, %d, %d,", 10000, leaves)
|
|
}
|
|
|
|
// Statistical assumption, can be flaky
|
|
if longestBranch != 4 {
|
|
t.Errorf("incorrect longest branch count, %d, %d,", 4, longestBranch)
|
|
}
|
|
|
|
DebugNode(tree.Root, 0, "")
|
|
}
|