ceremonyclient/node/execution/intrinsics/hypergraph/hypergraph_hyperedge_add_test.go
Cassandra Heart dbd95bd9e9
v2.1.0 (#439)
* v2.1.0 [omit consensus and adjacent] - this commit will be amended with the full release after the file copy is complete

* 2.1.0 main node rollup
2025-09-30 02:48:15 -05:00

254 lines
6.6 KiB
Go

package hypergraph_test
import (
"math/big"
"slices"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
"source.quilibrium.com/quilibrium/monorepo/node/execution/intrinsics/hypergraph"
hgstate "source.quilibrium.com/quilibrium/monorepo/node/execution/state/hypergraph"
"source.quilibrium.com/quilibrium/monorepo/node/keys"
qcrypto "source.quilibrium.com/quilibrium/monorepo/types/crypto"
nodehg "source.quilibrium.com/quilibrium/monorepo/types/hypergraph"
"source.quilibrium.com/quilibrium/monorepo/types/mocks"
crypto "source.quilibrium.com/quilibrium/monorepo/types/tries"
)
// Mock implementation of Hyperedge for testing
type mockHyperedge struct {
id [64]byte
connections []nodehg.Atom
}
// GetExtrinsicTree implements hypergraph.Hyperedge.
func (m *mockHyperedge) GetExtrinsicTree() *crypto.VectorCommitmentTree {
return &crypto.VectorCommitmentTree{}
}
func (m *mockHyperedge) GetID() [64]byte {
return [64]byte(m.id)
}
func (m *mockHyperedge) GetSize() *big.Int {
return big.NewInt(int64(len(m.connections) * 64))
}
func (m *mockHyperedge) ToBytes() []byte {
return m.id[:]
}
func (m *mockHyperedge) AddExtrinsic(a nodehg.Atom) {
m.connections = append(m.connections, a)
}
func (m *mockHyperedge) RemoveExtrinsic(a nodehg.Atom) {
i := slices.Index(m.connections, a)
if i < len(m.connections)-1 && i > 0 {
m.connections = slices.Concat(m.connections[:i], m.connections[i+1:])
} else if i == 0 {
m.connections = m.connections[1:]
} else if i == len(m.connections)-1 {
m.connections = m.connections[:len(m.connections)-2]
}
}
func (m *mockHyperedge) Commit(_ qcrypto.InclusionProver) []byte {
return m.id[:]
}
func (m *mockHyperedge) GetAtomType() nodehg.AtomType {
return nodehg.HyperedgeAtomType
}
// Mock implementation of Vertex for testing
type mockVertex struct {
id []byte
}
func (m *mockVertex) GetID() [64]byte {
return [64]byte(m.id)
}
func (m *mockVertex) ToBytes() []byte {
return m.id
}
func (m *mockVertex) GetAtomType() nodehg.AtomType {
return nodehg.VertexAtomType
}
func (m *mockHyperedge) GetAppAddress() [32]byte {
return [32]byte(m.id[:32])
}
func (m *mockHyperedge) GetDataAddress() [32]byte {
return [32]byte(m.id[32:])
}
func (m *mockVertex) GetSize() *big.Int {
return big.NewInt(10)
}
func (m *mockVertex) GetAppAddress() [32]byte {
return [32]byte(m.id[:32])
}
func (m *mockVertex) GetDataAddress() [32]byte {
return [32]byte(m.id[32:])
}
func (m *mockVertex) Commit(_ qcrypto.InclusionProver) []byte {
return m.id
}
func TestHyperedgeAdd_GetCost(t *testing.T) {
// Setup
domain := [32]byte{1, 2, 3}
// Create a mock hyperedge with no atoms
expectedSize := big.NewInt(0)
id := make([]byte, 64)
copy(id[:32], domain[:])
copy(id[32:], []byte{4, 5, 6, 7, 8})
mockEdge := &mockHyperedge{
id: [64]byte(id),
}
// Create mock inclusionProver and signer
mockProver := &mocks.MockInclusionProver{}
signer, err := keys.NewEd448Key()
require.NoError(t, err)
hyperedgeAdd := hypergraph.NewHyperedgeAdd(domain, mockEdge, mockProver, signer)
// Test cost calculation
cost, err := hyperedgeAdd.GetCost()
assert.NoError(t, err)
assert.Equal(t, expectedSize, cost)
}
func TestHyperedgeAdd_Prove(t *testing.T) {
// Setup
domain := [32]byte{1, 2, 3}
// Create mock inclusionProver and signer
mockProver := &mocks.MockInclusionProver{}
signer, err := keys.NewEd448Key()
require.NoError(t, err)
// Test with nil hyperedge
hyperedgeAdd := hypergraph.NewHyperedgeAdd(domain, nil, mockProver, signer)
err = hyperedgeAdd.Prove(1)
assert.Error(t, err)
// Test with hyperedge that has no connections
id := make([]byte, 64)
copy(id[:32], domain[:])
copy(id[32:], []byte{4, 5, 6, 7, 8})
mockEdge := &mockHyperedge{
id: [64]byte(id),
connections: []nodehg.Atom{},
}
hyperedgeAdd = hypergraph.NewHyperedgeAdd(domain, mockEdge, mockProver, signer)
err = hyperedgeAdd.Prove(1)
assert.Error(t, err)
// Test with valid hyperedge
mockEdge.connections = []nodehg.Atom{
&mockVertex{id: []byte{1, 2, 3}},
}
hyperedgeAdd = hypergraph.NewHyperedgeAdd(domain, mockEdge, mockProver, signer)
err = hyperedgeAdd.Prove(1)
assert.NoError(t, err)
}
func TestHyperedgeAdd_Verify(t *testing.T) {
// Setup
domain := [32]byte{1, 2, 3}
// Create mock inclusionProver and signer
mockProver := &mocks.MockInclusionProver{}
signer, err := keys.NewEd448Key()
require.NoError(t, err)
// Test with nil hyperedge
hyperedgeAdd := hypergraph.NewHyperedgeAdd(domain, nil, mockProver, signer)
valid, err := hyperedgeAdd.Verify(1)
assert.False(t, valid)
assert.Error(t, err)
// Test with hyperedge that has no connections
id := make([]byte, 64)
copy(id[:32], domain[:])
copy(id[32:], []byte{4, 5, 6, 7, 8})
mockEdge := &mockHyperedge{
id: [64]byte(id),
connections: []nodehg.Atom{},
}
hyperedgeAdd = hypergraph.NewHyperedgeAdd(domain, mockEdge, mockProver, signer)
valid, err = hyperedgeAdd.Verify(1)
assert.False(t, valid)
assert.Error(t, err)
// Test with domain mismatch
badDomainID := make([]byte, 64)
copy(badDomainID[:32], []byte{9, 9, 9}) // Different domain
copy(badDomainID[32:], []byte{4, 5, 6, 7, 8})
mockEdge.id = [64]byte(badDomainID)
mockEdge.connections = []nodehg.Atom{
&mockVertex{id: []byte{1, 2, 3}},
}
hyperedgeAdd = hypergraph.NewHyperedgeAdd(domain, mockEdge, mockProver, signer)
valid, err = hyperedgeAdd.Verify(1)
assert.False(t, valid)
assert.Error(t, err)
// Test with valid hyperedge
mockEdge.id = [64]byte(id) // Restore correct domain
hyperedgeAdd = hypergraph.NewHyperedgeAdd(domain, mockEdge, mockProver, signer)
// Note: Verify requires keyManager and config to be set, which happens in InvokeStep
// For unit tests, we'll skip this verification as it gets tested in integration tests
}
func TestHyperedgeAdd_Materialize(t *testing.T) {
// Setup
domain := [32]byte{1, 2, 3}
mockHypergraph := &mocks.MockHypergraph{}
hgState := hgstate.NewHypergraphState(mockHypergraph)
mockHypergraph.On("GetHyperedge", mock.Anything).Return(nil, nil)
// Create a mock hyperedge
id := make([]byte, 64)
copy(id[:32], domain[:])
copy(id[32:], []byte{4, 5, 6, 7, 8})
mockEdge := &mockHyperedge{
id: [64]byte(id),
connections: []nodehg.Atom{&mockVertex{id: []byte{1, 2, 3}}},
}
// Create mock inclusionProver and signer
mockProver := &mocks.MockInclusionProver{}
signer, err := keys.NewEd448Key()
require.NoError(t, err)
hyperedgeAdd := hypergraph.NewHyperedgeAdd(domain, mockEdge, mockProver, signer)
// Test materialization
resultState, err := hyperedgeAdd.Materialize(1, hgState)
require.NoError(t, err)
assert.Equal(t, hgState, resultState)
}