ceremonyclient/node/tests/factories.go
Cassandra Heart 2acc979ccf
v2.1.0.13
2025-11-29 15:04:37 -06:00

1428 lines
34 KiB
Go

package tests
import (
"bytes"
"context"
"crypto/rand"
"encoding/binary"
"math/big"
"slices"
"github.com/iden3/go-iden3-crypto/poseidon"
"github.com/libp2p/go-libp2p/core/peer"
"github.com/stretchr/testify/mock"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/credentials/insecure"
"source.quilibrium.com/quilibrium/monorepo/node/execution/intrinsics/global"
"source.quilibrium.com/quilibrium/monorepo/node/execution/intrinsics/token"
qgrpc "source.quilibrium.com/quilibrium/monorepo/node/internal/grpc"
"source.quilibrium.com/quilibrium/monorepo/protobufs"
"source.quilibrium.com/quilibrium/monorepo/types/channel"
"source.quilibrium.com/quilibrium/monorepo/types/crypto"
"source.quilibrium.com/quilibrium/monorepo/types/execution/intrinsics"
"source.quilibrium.com/quilibrium/monorepo/types/mocks"
"source.quilibrium.com/quilibrium/monorepo/types/schema"
"source.quilibrium.com/quilibrium/monorepo/types/store"
qcrypto "source.quilibrium.com/quilibrium/monorepo/types/tries"
)
// CreateHypergraphWithInclusionProver sets up the mock hypergraph to return the
// provided prover instance
func CreateHypergraphWithInclusionProver(
inclusionProver crypto.InclusionProver,
) *mocks.MockHypergraph {
mockHG := new(mocks.MockHypergraph)
mockHG.On("GetProver").Return(inclusionProver)
return mockHG
}
// CreateTestRDFMultiprover creates a RDFMultiprover for test usage
func CreateTestRDFMultiprover(
inclusionProver crypto.InclusionProver,
) *schema.RDFMultiprover {
parser := &schema.TurtleRDFParser{}
return schema.NewRDFMultiprover(parser, inclusionProver)
}
// SetHypergraphProverData sets mock hypergraph responses for prover data
func SetHypergraphProverData(
mockHG *mocks.MockHypergraph,
proverAddress []byte,
publicKey []byte,
status byte,
availableStorage uint64,
seniority uint64,
delegateAddress []byte,
kickFrameNumber uint64,
) error {
rdfProver := CreateTestRDFMultiprover(mockHG.GetProver())
tree := &qcrypto.VectorCommitmentTree{}
// Set prover fields in tree using RDF schema
if err := rdfProver.Set(
global.GLOBAL_RDF_SCHEMA,
intrinsics.GLOBAL_INTRINSIC_ADDRESS[:],
"prover:Prover",
"PublicKey",
publicKey,
tree,
); err != nil {
return err
}
statusBytes := []byte{status}
if err := rdfProver.Set(
global.GLOBAL_RDF_SCHEMA,
intrinsics.GLOBAL_INTRINSIC_ADDRESS[:],
"prover:Prover",
"Status",
statusBytes,
tree,
); err != nil {
return err
}
availableStorageBytes := make([]byte, 8)
binary.BigEndian.PutUint64(availableStorageBytes, availableStorage)
if err := rdfProver.Set(
global.GLOBAL_RDF_SCHEMA,
intrinsics.GLOBAL_INTRINSIC_ADDRESS[:],
"prover:Prover",
"AvailableStorage",
availableStorageBytes,
tree,
); err != nil {
return err
}
seniorityBytes := make([]byte, 8)
binary.BigEndian.PutUint64(seniorityBytes, seniority)
if err := rdfProver.Set(
global.GLOBAL_RDF_SCHEMA,
intrinsics.GLOBAL_INTRINSIC_ADDRESS[:],
"prover:Prover",
"Seniority",
seniorityBytes,
tree,
); err != nil {
return err
}
kickFrameBytes := make([]byte, 8)
binary.BigEndian.PutUint64(kickFrameBytes, kickFrameNumber)
if err := rdfProver.Set(
global.GLOBAL_RDF_SCHEMA,
intrinsics.GLOBAL_INTRINSIC_ADDRESS[:],
"prover:Prover",
"KickFrameNumber",
kickFrameBytes,
tree,
); err != nil {
return err
}
// Create mock vertex
mockVertex := &mocks.MockVertex{}
mockVertex.On("GetAddress").Return(proverAddress)
mockVertex.On("GetData").Return(tree, nil)
// Set expectations on mock hypergraph
mockHG.On("GetVertex", proverAddress).Return(mockVertex, nil)
mockHG.On("GetVertexData", proverAddress).Return(tree, nil)
return nil
}
// SetHypergraphAllocationData sets mock hypergraph responses for allocation
// data
func SetHypergraphAllocationData(
mockHG *mocks.MockHypergraph,
allocationAddress []byte,
proverRef []byte,
status byte,
confirmationFilter []byte,
rejectionFilter []byte,
joinFrameNumber uint64,
leaveFrameNumber uint64,
pauseFrameNumber uint64,
resumeFrameNumber uint64,
kickFrameNumber uint64,
joinConfirmFrameNumber uint64,
joinRejectFrameNumber uint64,
leaveConfirmFrameNumber uint64,
leaveRejectFrameNumber uint64,
lastActiveFrameNumber uint64,
) error {
rdfProver := CreateTestRDFMultiprover(mockHG.GetProver())
tree := &qcrypto.VectorCommitmentTree{}
// Set allocation fields in tree
if err := rdfProver.Set(
global.GLOBAL_RDF_SCHEMA,
intrinsics.GLOBAL_INTRINSIC_ADDRESS[:],
"allocation:ProverAllocation",
"Prover",
proverRef,
tree,
); err != nil {
return err
}
statusBytes := []byte{status}
if err := rdfProver.Set(
global.GLOBAL_RDF_SCHEMA,
intrinsics.GLOBAL_INTRINSIC_ADDRESS[:],
"allocation:ProverAllocation",
"Status",
statusBytes,
tree,
); err != nil {
return err
}
if err := rdfProver.Set(
global.GLOBAL_RDF_SCHEMA,
intrinsics.GLOBAL_INTRINSIC_ADDRESS[:],
"allocation:ProverAllocation",
"ConfirmationFilter",
confirmationFilter,
tree,
); err != nil {
return err
}
if err := rdfProver.Set(
global.GLOBAL_RDF_SCHEMA,
intrinsics.GLOBAL_INTRINSIC_ADDRESS[:],
"allocation:ProverAllocation",
"RejectionFilter",
rejectionFilter,
tree,
); err != nil {
return err
}
joinFrameBytes := make([]byte, 8)
binary.BigEndian.PutUint64(joinFrameBytes, joinFrameNumber)
if err := rdfProver.Set(
global.GLOBAL_RDF_SCHEMA,
intrinsics.GLOBAL_INTRINSIC_ADDRESS[:],
"allocation:ProverAllocation",
"JoinFrameNumber",
joinFrameBytes,
tree,
); err != nil {
return err
}
leaveFrameBytes := make([]byte, 8)
binary.BigEndian.PutUint64(leaveFrameBytes, leaveFrameNumber)
if err := rdfProver.Set(
global.GLOBAL_RDF_SCHEMA,
intrinsics.GLOBAL_INTRINSIC_ADDRESS[:],
"allocation:ProverAllocation",
"LeaveFrameNumber",
leaveFrameBytes,
tree,
); err != nil {
return err
}
pauseFrameBytes := make([]byte, 8)
binary.BigEndian.PutUint64(pauseFrameBytes, pauseFrameNumber)
if err := rdfProver.Set(
global.GLOBAL_RDF_SCHEMA,
intrinsics.GLOBAL_INTRINSIC_ADDRESS[:],
"allocation:ProverAllocation",
"PauseFrameNumber",
pauseFrameBytes,
tree,
); err != nil {
return err
}
resumeFrameBytes := make([]byte, 8)
binary.BigEndian.PutUint64(resumeFrameBytes, resumeFrameNumber)
if err := rdfProver.Set(
global.GLOBAL_RDF_SCHEMA,
intrinsics.GLOBAL_INTRINSIC_ADDRESS[:],
"allocation:ProverAllocation",
"ResumeFrameNumber",
resumeFrameBytes,
tree,
); err != nil {
return err
}
kickFrameBytes := make([]byte, 8)
binary.BigEndian.PutUint64(kickFrameBytes, kickFrameNumber)
if err := rdfProver.Set(
global.GLOBAL_RDF_SCHEMA,
intrinsics.GLOBAL_INTRINSIC_ADDRESS[:],
"allocation:ProverAllocation",
"KickFrameNumber",
kickFrameBytes,
tree,
); err != nil {
return err
}
joinConfirmFrameBytes := make([]byte, 8)
binary.BigEndian.PutUint64(joinConfirmFrameBytes, joinConfirmFrameNumber)
if err := rdfProver.Set(
global.GLOBAL_RDF_SCHEMA,
intrinsics.GLOBAL_INTRINSIC_ADDRESS[:],
"allocation:ProverAllocation",
"JoinConfirmFrameNumber",
joinConfirmFrameBytes,
tree,
); err != nil {
return err
}
joinRejectFrameBytes := make([]byte, 8)
binary.BigEndian.PutUint64(joinRejectFrameBytes, joinRejectFrameNumber)
if err := rdfProver.Set(
global.GLOBAL_RDF_SCHEMA,
intrinsics.GLOBAL_INTRINSIC_ADDRESS[:],
"allocation:ProverAllocation",
"JoinRejectFrameNumber",
joinRejectFrameBytes,
tree,
); err != nil {
return err
}
leaveConfirmFrameBytes := make([]byte, 8)
binary.BigEndian.PutUint64(leaveConfirmFrameBytes, leaveConfirmFrameNumber)
if err := rdfProver.Set(
global.GLOBAL_RDF_SCHEMA,
intrinsics.GLOBAL_INTRINSIC_ADDRESS[:],
"allocation:ProverAllocation",
"LeaveConfirmFrameNumber",
leaveConfirmFrameBytes,
tree,
); err != nil {
return err
}
leaveRejectFrameBytes := make([]byte, 8)
binary.BigEndian.PutUint64(leaveRejectFrameBytes, leaveRejectFrameNumber)
if err := rdfProver.Set(
global.GLOBAL_RDF_SCHEMA,
intrinsics.GLOBAL_INTRINSIC_ADDRESS[:],
"allocation:ProverAllocation",
"LeaveRejectFrameNumber",
leaveRejectFrameBytes,
tree,
); err != nil {
return err
}
lastActiveFrameBytes := make([]byte, 8)
binary.BigEndian.PutUint64(lastActiveFrameBytes, lastActiveFrameNumber)
if err := rdfProver.Set(
global.GLOBAL_RDF_SCHEMA,
intrinsics.GLOBAL_INTRINSIC_ADDRESS[:],
"allocation:ProverAllocation",
"LastActiveFrameNumber",
lastActiveFrameBytes,
tree,
); err != nil {
return err
}
// Create mock vertex
mockVertex := &mocks.MockVertex{}
mockVertex.On("GetAddress").Return(allocationAddress)
mockVertex.On("GetData").Return(tree, nil)
// Set expectations on mock hypergraph
mockHG.On("GetVertex", allocationAddress).Return(mockVertex, nil)
mockHG.On("GetVertexData", allocationAddress).Return(tree, nil)
return nil
}
// SetHypergraphRewardData sets mock hypergraph responses for reward data
func SetHypergraphRewardData(
mockHG *mocks.MockHypergraph,
rewardAddress []byte,
delegateAddress []byte,
balance *big.Int,
) error {
rdfProver := CreateTestRDFMultiprover(mockHG.GetProver())
tree := &qcrypto.VectorCommitmentTree{}
// Set reward fields in tree
if err := rdfProver.Set(
global.GLOBAL_RDF_SCHEMA,
token.QUIL_TOKEN_ADDRESS[:],
"reward:ProverReward",
"DelegateAddress",
delegateAddress,
tree,
); err != nil {
return err
}
balanceBytes := balance.FillBytes(make([]byte, 32))
if err := rdfProver.Set(
global.GLOBAL_RDF_SCHEMA,
token.QUIL_TOKEN_ADDRESS[:],
"reward:ProverReward",
"Balance",
balanceBytes,
tree,
); err != nil {
return err
}
// Create mock vertex
mockVertex := &mocks.MockVertex{}
mockVertex.On("GetAddress").Return(rewardAddress)
mockVertex.On("GetData").Return(tree, nil)
// Set expectations on mock hypergraph
mockHG.On("GetVertex", rewardAddress).Return(mockVertex, nil)
mockHG.On("GetVertexData", rewardAddress).Return(tree, nil)
return nil
}
// SetHypergraphTokenMetadataData sets mock hypergraph responses for token
// metadata
func SetHypergraphTokenMetadataData(
mockHG *mocks.MockHypergraph,
config *token.TokenIntrinsicConfiguration,
) error {
rdfProver := CreateTestRDFMultiprover(mockHG.GetProver())
tree, err := token.NewTokenConfigurationMetadata(config, rdfProver)
if err != nil {
return err
}
tokenDomainBI, err := poseidon.HashBytes(
slices.Concat(
token.TOKEN_PREFIX,
tree.Commit(mockHG.GetProver(), false),
),
)
if err != nil {
return err
}
metadataAddress := slices.Concat(
tokenDomainBI.FillBytes(make([]byte, 32)),
bytes.Repeat([]byte{0xff}, 32),
)
emptyTree := &qcrypto.VectorCommitmentTree{}
emptyTreeBytes, _ := qcrypto.SerializeNonLazyTree(emptyTree)
configTreeBytes, _ := qcrypto.SerializeNonLazyTree(tree)
metadataTree := &qcrypto.VectorCommitmentTree{}
metadataTree.Insert(
[]byte{0},
emptyTreeBytes,
nil,
big.NewInt(int64(len(emptyTreeBytes))),
)
metadataTree.Insert(
[]byte{1 << 2},
emptyTreeBytes,
nil,
big.NewInt(int64(len(emptyTreeBytes))),
)
metadataTree.Insert(
[]byte{16 << 2},
configTreeBytes,
nil,
big.NewInt(int64(len(configTreeBytes))),
)
// Create mock vertex
mockVertex := &mocks.MockVertex{}
mockVertex.On("GetAddress").Return(metadataAddress)
mockVertex.On("GetData").Return(tree, nil)
// Set expectations on mock hypergraph
mockHG.On("GetVertex", metadataAddress).Return(mockVertex, nil)
mockHG.On("GetVertexData", metadataAddress).Return(tree, nil)
return nil
}
// SetHypergraphPendingTransactionData sets mock hypergraph responses for
// pending transaction data
func SetHypergraphPendingTransactionData(
mockHG *mocks.MockHypergraph,
config *token.TokenIntrinsicConfiguration,
transactionAddress []byte,
commitment []byte,
toOneTimeKey []byte,
toVerificationKey []byte,
toCoinBalance []byte,
toMask []byte,
refundOneTimeKey []byte,
refundVerificationKey []byte,
refundCoinBalance []byte,
refundMask []byte,
expiration uint64,
) error {
rdfProver := CreateTestRDFMultiprover(mockHG.GetProver())
tree := &qcrypto.VectorCommitmentTree{}
schema, err := token.PrepareRDFSchemaFromConfig(
transactionAddress[:32],
config,
)
if err != nil {
return err
}
if err := rdfProver.Set(
schema,
transactionAddress[:32],
"pending:PendingTransaction",
"Commitment",
commitment,
tree,
); err != nil {
return err
}
// Set pending transaction fields - To output
if err := rdfProver.Set(
schema,
transactionAddress[:32],
"pending:PendingTransaction",
"ToOneTimeKey",
toOneTimeKey,
tree,
); err != nil {
return err
}
if err := rdfProver.Set(
schema,
transactionAddress[:32],
"pending:PendingTransaction",
"ToVerificationKey",
toVerificationKey,
tree,
); err != nil {
return err
}
if err := rdfProver.Set(
schema,
transactionAddress[:32],
"pending:PendingTransaction",
"ToCoinBalance",
toCoinBalance,
tree,
); err != nil {
return err
}
if err := rdfProver.Set(
schema,
transactionAddress[:32],
"pending:PendingTransaction",
"ToMask",
toMask,
tree,
); err != nil {
return err
}
// Set pending transaction fields - Refund output
if err := rdfProver.Set(
schema,
transactionAddress[:32],
"pending:PendingTransaction",
"RefundOneTimeKey",
refundOneTimeKey,
tree,
); err != nil {
return err
}
if err := rdfProver.Set(
schema,
transactionAddress[:32],
"pending:PendingTransaction",
"RefundVerificationKey",
refundVerificationKey,
tree,
); err != nil {
return err
}
if err := rdfProver.Set(
schema,
transactionAddress[:32],
"pending:PendingTransaction",
"RefundCoinBalance",
refundCoinBalance,
tree,
); err != nil {
return err
}
if err := rdfProver.Set(
schema,
transactionAddress[:32],
"pending:PendingTransaction",
"RefundMask",
refundMask,
tree,
); err != nil {
return err
}
// Set expiration if non-zero
if expiration > 0 {
expirationBytes := make([]byte, 8)
binary.BigEndian.PutUint64(expirationBytes, expiration)
if err := rdfProver.Set(
schema,
transactionAddress[:32],
"pending:PendingTransaction",
"Expiration",
expirationBytes,
tree,
); err != nil {
return err
}
}
// Create mock vertex
mockVertex := &mocks.MockVertex{}
mockVertex.On("GetAddress").Return(transactionAddress)
mockVertex.On("GetData").Return(tree, nil)
// Set expectations on mock hypergraph
mockHG.On("GetVertex", transactionAddress).Return(mockVertex, nil)
mockHG.On("GetVertexData", transactionAddress).Return(tree, nil)
return nil
}
// SetHypergraphCoinData sets mock hypergraph responses for coin data
func SetHypergraphCoinData(
mockHG *mocks.MockHypergraph,
config *token.TokenIntrinsicConfiguration,
coinAddress []byte,
frameNumber uint64,
commitment []byte,
oneTimeKey []byte,
verificationKey []byte,
coinBalance []byte,
mask []byte,
additionalReference []byte,
additionalReferenceKey []byte,
) error {
rdfProver := CreateTestRDFMultiprover(mockHG.GetProver())
tree := &qcrypto.VectorCommitmentTree{}
schema, err := token.PrepareRDFSchemaFromConfig(coinAddress[:32], config)
if err != nil {
return err
}
// Set coin fields
frameNumberBytes := make([]byte, 8)
binary.BigEndian.PutUint64(frameNumberBytes, frameNumber)
if err := rdfProver.Set(
schema,
coinAddress[:32],
"coin:Coin",
"FrameNumber",
frameNumberBytes,
tree,
); err != nil {
return err
}
if err := rdfProver.Set(
schema,
coinAddress[:32],
"coin:Coin",
"Commitment",
commitment,
tree,
); err != nil {
return err
}
if err := rdfProver.Set(
schema,
coinAddress[:32],
"coin:Coin",
"OneTimeKey",
oneTimeKey,
tree,
); err != nil {
return err
}
if err := rdfProver.Set(
schema,
coinAddress[:32],
"coin:Coin",
"VerificationKey",
verificationKey,
tree,
); err != nil {
return err
}
if err := rdfProver.Set(
schema,
coinAddress[:32],
"coin:Coin",
"CoinBalance",
coinBalance,
tree,
); err != nil {
return err
}
if err := rdfProver.Set(
schema,
coinAddress[:32],
"coin:Coin",
"Mask",
mask,
tree,
); err != nil {
return err
}
// Set optional additional reference fields
if additionalReference != nil {
if err := rdfProver.Set(
schema,
coinAddress[:32],
"coin:Coin",
"AdditionalReference",
additionalReference,
tree,
); err != nil {
return err
}
}
if additionalReferenceKey != nil {
if err := rdfProver.Set(
schema,
coinAddress[:32],
"coin:Coin",
"AdditionalReferenceKey",
additionalReferenceKey,
tree,
); err != nil {
return err
}
}
// Create mock vertex
mockVertex := &mocks.MockVertex{}
mockVertex.On("GetAddress").Return(coinAddress)
mockVertex.On("GetData").Return(tree, nil)
// Set expectations on mock hypergraph
mockHG.On("GetVertex", coinAddress).Return(mockVertex, nil)
mockHG.On("GetVertexData", coinAddress).Return(tree, nil)
return nil
}
// SetHypergraphComputeMetadataData sets mock hypergraph responses for compute
// metadata
func SetHypergraphComputeMetadataData(
mockHG *mocks.MockHypergraph,
computeAddress []byte,
schema string,
creator []byte,
readPublicKey []byte,
writePublicKey []byte,
) error {
tree := &qcrypto.VectorCommitmentTree{}
// Index 0: Consensus metadata (empty for tests)
consensusMetadata := &qcrypto.VectorCommitmentTree{}
consensusMetadataBytes, err := qcrypto.SerializeNonLazyTree(consensusMetadata)
if err != nil {
return err
}
if err := tree.Insert(
[]byte{0 << 2},
consensusMetadataBytes,
nil,
big.NewInt(int64(len(consensusMetadataBytes))),
); err != nil {
return err
}
// Index 1: Sumcheck info (empty for tests)
sumcheckInfo := &qcrypto.VectorCommitmentTree{}
sumcheckInfoBytes, err := qcrypto.SerializeNonLazyTree(sumcheckInfo)
if err != nil {
return err
}
if err := tree.Insert(
[]byte{1 << 2},
sumcheckInfoBytes,
nil,
big.NewInt(int64(len(sumcheckInfoBytes))),
); err != nil {
return err
}
// Index 2: RDF schema
schemaBytes := []byte(schema)
if err := tree.Insert(
[]byte{2 << 2},
schemaBytes,
nil,
big.NewInt(int64(len(schemaBytes))),
); err != nil {
return err
}
// Index 16: Compute configuration metadata (same as index 13 in
// additionalData array)
configTree := &qcrypto.VectorCommitmentTree{}
// Store Read key (byte 0)
if err := configTree.Insert(
[]byte{0 << 2},
readPublicKey,
nil,
big.NewInt(57),
); err != nil {
return err
}
// Store Write key (byte 1)
if err := configTree.Insert(
[]byte{1 << 2},
writePublicKey,
nil,
big.NewInt(57),
); err != nil {
return err
}
configBytes, err := qcrypto.SerializeNonLazyTree(configTree)
if err != nil {
return err
}
if err := tree.Insert(
[]byte{16 << 2},
configBytes,
nil,
big.NewInt(int64(len(configBytes))),
); err != nil {
return err
}
// Create mock vertex
mockVertex := &mocks.MockVertex{}
mockVertex.On("GetAddress").Return(computeAddress)
mockVertex.On("GetData").Return(tree, nil)
// Set expectations on mock hypergraph - handle both []byte and [64]byte
mockHG.On("GetVertex", computeAddress).Return(mockVertex, nil)
mockHG.On("GetVertexData", computeAddress).Return(tree, nil)
// Also set up for [64]byte if address is 64 bytes
if len(computeAddress) == 64 {
var addr64 [64]byte
copy(addr64[:], computeAddress)
mockHG.On("GetVertex", addr64).Return(mockVertex, nil).Maybe()
mockHG.On("GetVertexData", addr64).Return(tree, nil).Maybe()
}
return nil
}
// SetHypergraphCodeData sets mock hypergraph responses for code deployment data
func SetHypergraphCodeData(
mockHG *mocks.MockHypergraph,
codeAddress []byte,
code []byte,
) error {
tree := &qcrypto.VectorCommitmentTree{}
// Store the code content at index 0 (same as CodeDeployment.Materialize)
if err := tree.Insert(
[]byte{0 << 2},
code,
nil,
big.NewInt(int64(len(code))),
); err != nil {
return err
}
// Create mock vertex
mockVertex := &mocks.MockVertex{}
mockVertex.On("GetAddress").Return(codeAddress)
mockVertex.On("GetData").Return(tree, nil)
// Set expectations on mock hypergraph
mockHG.On("GetVertex", codeAddress).Return(mockVertex, nil)
mockHG.On("GetVertexData", codeAddress).Return(tree, nil)
return nil
}
// SetHypergraphExecutionData sets mock hypergraph responses for code execution
// data
func SetHypergraphExecutionData(
mockHG *mocks.MockHypergraph,
executionAddress []byte,
codeRef []byte,
inputData []byte,
outputData []byte,
status byte,
) error {
tree := &qcrypto.VectorCommitmentTree{}
// Store execution data following compute execution structure
// Index 0: Code reference
if err := tree.Insert(
[]byte{0 << 2},
codeRef,
nil,
big.NewInt(int64(len(codeRef))),
); err != nil {
return err
}
// Index 1: Input data
if err := tree.Insert(
[]byte{1 << 2},
inputData,
nil,
big.NewInt(int64(len(inputData))),
); err != nil {
return err
}
// Index 2: Output data
if err := tree.Insert(
[]byte{2 << 2},
outputData,
nil,
big.NewInt(int64(len(outputData))),
); err != nil {
return err
}
// Index 3: Status
statusBytes := []byte{status}
if err := tree.Insert(
[]byte{3 << 2},
statusBytes,
nil,
big.NewInt(1),
); err != nil {
return err
}
// Create mock vertex
mockVertex := &mocks.MockVertex{}
mockVertex.On("GetAddress").Return(executionAddress)
mockVertex.On("GetData").Return(tree, nil)
// Set expectations on mock hypergraph
mockHG.On("GetVertex", executionAddress).Return(mockVertex, nil)
mockHG.On("GetVertexData", executionAddress).Return(tree, nil)
return nil
}
// SetHypergraphFinalizedData sets mock hypergraph responses for finalized
// execution data
func SetHypergraphFinalizedData(
mockHG *mocks.MockHypergraph,
finalizedAddress []byte,
executionRef []byte,
finalizedOutput []byte,
proofs []byte,
) error {
tree := &qcrypto.VectorCommitmentTree{}
// Store finalized data following compute finalization structure
// Index 0: Execution reference
if err := tree.Insert(
[]byte{0 << 2},
executionRef,
nil,
big.NewInt(int64(len(executionRef))),
); err != nil {
return err
}
// Index 1: Finalized output
if err := tree.Insert(
[]byte{1 << 2},
finalizedOutput,
nil,
big.NewInt(int64(len(finalizedOutput))),
); err != nil {
return err
}
// Index 2: Proofs (if provided)
if proofs != nil {
if err := tree.Insert(
[]byte{2 << 2},
proofs,
nil,
big.NewInt(int64(len(proofs))),
); err != nil {
return err
}
}
// Create mock vertex
mockVertex := &mocks.MockVertex{}
mockVertex.On("GetAddress").Return(finalizedAddress)
mockVertex.On("GetData").Return(tree, nil)
// Set expectations on mock hypergraph
mockHG.On("GetVertex", finalizedAddress).Return(mockVertex, nil)
mockHG.On("GetVertexData", finalizedAddress).Return(tree, nil)
return nil
}
// SetHypergraphHypergraphMetadataData sets mock hypergraph responses for
// hypergraph metadata
func SetHypergraphHypergraphMetadataData(
mockHG *mocks.MockHypergraph,
metadataAddress []byte,
schema string,
readPublicKey []byte,
writePublicKey []byte,
) error {
tree := &qcrypto.VectorCommitmentTree{}
// Index 0: Consensus metadata (empty for tests)
consensusMetadata := &qcrypto.VectorCommitmentTree{}
consensusMetadataBytes, err := qcrypto.SerializeNonLazyTree(consensusMetadata)
if err != nil {
return err
}
if err := tree.Insert(
[]byte{0 << 2},
consensusMetadataBytes,
nil,
big.NewInt(int64(len(consensusMetadataBytes))),
); err != nil {
return err
}
// Index 1: Sumcheck info (empty for tests)
sumcheckInfo := &qcrypto.VectorCommitmentTree{}
sumcheckInfoBytes, err := qcrypto.SerializeNonLazyTree(sumcheckInfo)
if err != nil {
return err
}
if err := tree.Insert(
[]byte{1 << 2},
sumcheckInfoBytes,
nil,
big.NewInt(int64(len(sumcheckInfoBytes))),
); err != nil {
return err
}
// Index 2: RDF schema
schemaBytes := []byte(schema)
if err := tree.Insert(
[]byte{2 << 2},
schemaBytes,
nil,
big.NewInt(int64(len(schemaBytes))),
); err != nil {
return err
}
// Index 16: Hypergraph configuration metadata (same as index 13 in
// additionalData array)
configTree := &qcrypto.VectorCommitmentTree{}
// Store Read key (byte 0)
if err := configTree.Insert(
[]byte{0 << 2},
readPublicKey,
nil,
big.NewInt(57),
); err != nil {
return err
}
// Store Write key (byte 1)
if err := configTree.Insert(
[]byte{1 << 2},
writePublicKey,
nil,
big.NewInt(57),
); err != nil {
return err
}
configBytes, err := qcrypto.SerializeNonLazyTree(configTree)
if err != nil {
return err
}
if err := tree.Insert(
[]byte{16 << 2},
configBytes,
nil,
big.NewInt(int64(len(configBytes))),
); err != nil {
return err
}
// Create mock vertex
mockVertex := &mocks.MockVertex{}
mockVertex.On("GetAddress").Return(metadataAddress)
mockVertex.On("GetData").Return(tree, nil)
// Set expectations on mock hypergraph
mockHG.On("GetVertex", metadataAddress).Return(mockVertex, nil)
mockHG.On("GetVertexData", metadataAddress).Return(tree, nil)
return nil
}
// SetHypergraphVertexAddData sets mock hypergraph responses for vertex add
// operations
func SetHypergraphVertexAddData(
mockHG *mocks.MockHypergraph,
vertexAddress []byte,
data []byte,
timestamp uint64,
) error {
tree := &qcrypto.VectorCommitmentTree{}
// Store vertex data
if err := tree.Insert(
[]byte("data"),
data,
nil,
big.NewInt(int64(len(data))),
); err != nil {
return err
}
timestampBytes := make([]byte, 8)
binary.BigEndian.PutUint64(timestampBytes, timestamp)
if err := tree.Insert(
[]byte("timestamp"),
timestampBytes,
nil,
big.NewInt(8),
); err != nil {
return err
}
// Create mock vertex
mockVertex := &mocks.MockVertex{}
mockVertex.On("GetAddress").Return(vertexAddress)
mockVertex.On("GetData").Return(tree, nil)
// Set expectations on mock hypergraph
mockHG.On("GetVertex", vertexAddress).Return(mockVertex, nil)
mockHG.On("GetVertexData", vertexAddress).Return(tree, nil)
return nil
}
// SetHypergraphVertexRemoveData sets mock hypergraph responses for vertex
// remove operations
func SetHypergraphVertexRemoveData(
mockHG *mocks.MockHypergraph,
vertexAddress []byte,
removalTimestamp uint64,
) error {
// For removal, we typically return nil or an error indicating vertex doesn't
// exist
mockHG.On("GetVertex", vertexAddress).Return(nil, store.ErrNotFound)
mockHG.On("GetVertexData", vertexAddress).Return(nil, store.ErrNotFound)
return nil
}
// SetHypergraphHyperedgeAddData sets mock hypergraph responses for hyperedge
// add operations
func SetHypergraphHyperedgeAddData(
mockHG *mocks.MockHypergraph,
hyperedgeAddress []byte,
sourceVertices [][]byte,
targetVertices [][]byte,
data []byte,
) error {
tree := &qcrypto.VectorCommitmentTree{}
// Store hyperedge data
if err := tree.Insert(
[]byte("data"),
data,
nil,
big.NewInt(int64(len(data))),
); err != nil {
return err
}
// Store source vertex references
for i, source := range sourceVertices {
key := append([]byte("source_"), byte(i))
if err := tree.Insert(
key,
source,
nil,
big.NewInt(int64(len(source))),
); err != nil {
return err
}
}
// Store target vertex references
for i, target := range targetVertices {
key := append([]byte("target_"), byte(i))
if err := tree.Insert(
key,
target,
nil,
big.NewInt(int64(len(target))),
); err != nil {
return err
}
}
// Create mock hyperedge
mockHyperedge := &mocks.MockHyperedge{}
mockHyperedge.On("GetAddress").Return(hyperedgeAddress)
mockHyperedge.On("GetData").Return(tree, nil)
mockHyperedge.On("GetSourceVertices").Return(sourceVertices)
mockHyperedge.On("GetTargetVertices").Return(targetVertices)
// Set expectations on mock hypergraph for hyperedge
mockHG.On("GetHyperedge", hyperedgeAddress).Return(mockHyperedge, nil)
return nil
}
// SetHypergraphHyperedgeRemoveData sets mock hypergraph responses for hyperedge
// remove operations
func SetHypergraphHyperedgeRemoveData(
mockHG *mocks.MockHypergraph,
hyperedgeAddress []byte,
) error {
// For removal, we typically return nil or an error indicating hyperedge
// doesn't exist
mockHG.On("GetHyperedge", hyperedgeAddress).Return(nil, store.ErrNotFound)
return nil
}
// Helper to set up a chain of vertex lookups for following references
func SetHypergraphVertexChain(
mockHG *mocks.MockHypergraph,
addresses [][]byte,
trees []*qcrypto.VectorCommitmentTree,
) {
if len(addresses) != len(trees) {
panic("addresses and trees must have same length")
}
for i := range addresses {
mockVertex := &mocks.MockVertex{}
mockVertex.On("GetAddress").Return(addresses[i])
mockVertex.On("GetData").Return(trees[i], nil)
mockHG.On("GetVertex", addresses[i]).Return(mockVertex, nil)
mockHG.On("GetVertexData", addresses[i]).Return(trees[i], nil)
}
}
func CreateValidQUILPendingTransactionPayload(
mockHG *mocks.MockHypergraph,
frameNumber uint64,
toSpendKeys [][]byte,
toViewKeys [][]byte,
refundSpendKeys [][]byte,
refundViewKeys [][]byte,
inputAmounts []*big.Int,
outputAmounts []*big.Int,
outputFees []*big.Int,
expiration uint64,
) (*protobufs.MessageRequest, error) {
if len(toSpendKeys) != len(toViewKeys) ||
len(refundSpendKeys) != len(refundViewKeys) ||
len(toSpendKeys) != len(refundSpendKeys) ||
len(toSpendKeys) != len(outputAmounts) || frameNumber == 0 {
panic("incorrect parameters")
}
mp := &mocks.MockMultiproof{}
mp.On("FromBytes", mock.Anything).Return(nil)
mp.On("GetMulticommitment").Return(make([]byte, 74))
mp.On("GetProof").Return(make([]byte, 74))
mockHG.GetProver().(*mocks.MockInclusionProver).On("NewMultiproof").Return(mp)
mockHG.GetProver().(*mocks.MockInclusionProver).On("VerifyMultiple", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(true)
mockHG.On("VerifyTraversalProof", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(true, nil)
mockHG.On("GetVertex", mock.Anything).Return(nil, nil)
pendingInputs := []*protobufs.PendingTransactionInput{}
for _, input := range inputAmounts {
address := []byte{0x0f, 0x63, 0xcd, 0x0c, 0x9f, 0xbe, 0x67, 0x9a, 0x56, 0x24, 0x69, 0x83, 0x1d, 0x8e, 0x81, 0x0c, 0x9d, 0x33, 0xcc, 0x24, 0x09, 0x69, 0x5b, 0x8e, 0x6a, 0x89, 0x3e, 0x62, 0x7e, 0xa9, 0x52, 0xd1}
err := SetHypergraphCoinData(
mockHG,
token.QUIL_TOKEN_CONFIGURATION,
slices.Concat(token.QUIL_TOKEN_ADDRESS, address),
frameNumber-1,
make([]byte, 56),
make([]byte, 56),
make([]byte, 56),
input.FillBytes(make([]byte, 56)),
make([]byte, 56),
nil,
nil,
)
if err != nil {
return nil, err
}
pendingInputs = append(pendingInputs, &protobufs.PendingTransactionInput{
Commitment: make([]byte, 56),
Signature: make([]byte, 336),
Proofs: make([][]byte, 1),
})
}
// Create verification key for consistency
verKey := make([]byte, 56)
rand.Read(verKey)
pendingOutputs := []*protobufs.PendingTransactionOutput{}
for _, output := range outputAmounts {
pendingOutputs = append(pendingOutputs, &protobufs.PendingTransactionOutput{
FrameNumber: big.NewInt(int64(frameNumber)).FillBytes(make([]byte, 8)),
Commitment: make([]byte, 56),
To: &protobufs.RecipientBundle{
OneTimeKey: make([]byte, 56),
VerificationKey: verKey,
CoinBalance: output.FillBytes(make([]byte, 56)),
Mask: make([]byte, 56),
AdditionalReference: []byte{},
AdditionalReferenceKey: []byte{},
},
Refund: &protobufs.RecipientBundle{
OneTimeKey: make([]byte, 56),
VerificationKey: verKey,
CoinBalance: output.FillBytes(make([]byte, 56)),
Mask: make([]byte, 56),
AdditionalReference: []byte{},
AdditionalReferenceKey: []byte{},
},
Expiration: expiration,
})
}
fees := [][]byte{}
for _, fee := range outputFees {
fees = append(fees, fee.FillBytes(make([]byte, 32)))
}
// Create PendingTransaction using protobuf
pbTx := &protobufs.PendingTransaction{
Domain: token.QUIL_TOKEN_ADDRESS[:],
Inputs: pendingInputs,
Outputs: pendingOutputs,
Fees: fees,
RangeProof: make([]byte, 100),
TraversalProof: &protobufs.TraversalProof{
Multiproof: nil,
SubProofs: []*protobufs.TraversalSubProof{
{
Commits: [][]byte{make([]byte, 74)},
Ys: [][]byte{make([]byte, 64)},
Paths: []*protobufs.Path{
{
Indices: []uint64{0},
},
},
},
},
},
}
return &protobufs.MessageRequest{
Request: &protobufs.MessageRequest_PendingTransaction{
PendingTransaction: pbTx,
},
}, nil
}
type Nopthenticator struct{}
// CreateClientTLSCredentials implements channel.AuthenticationProvider.
func (n *Nopthenticator) CreateClientTLSCredentials(expectedPeerId []byte) (
credentials.TransportCredentials,
error,
) {
return insecure.NewCredentials(), nil
}
// CreateServerTLSCredentials implements channel.AuthenticationProvider.
func (n *Nopthenticator) CreateServerTLSCredentials() (
credentials.TransportCredentials,
error,
) {
return insecure.NewCredentials(), nil
}
type authenticatedStream struct {
grpc.ServerStream
ctx context.Context
}
func (w *authenticatedStream) Context() context.Context { return w.ctx }
// StreamInterceptor implements channel.AuthenticationProvider.
func (n *Nopthenticator) StreamInterceptor(
srv any,
ss grpc.ServerStream,
info *grpc.StreamServerInfo,
handler grpc.StreamHandler,
) error {
bytes := make([]byte, 20)
rand.Read(bytes)
ss = &authenticatedStream{
ServerStream: ss,
ctx: qgrpc.NewContextWithPeerID(ss.Context(), peer.ID(bytes)),
}
return handler(srv, ss)
}
// UnaryInterceptor implements channel.AuthenticationProvider.
func (n *Nopthenticator) UnaryInterceptor(
ctx context.Context,
req any,
info *grpc.UnaryServerInfo,
handler grpc.UnaryHandler,
) (any, error) {
bytes := make([]byte, 20)
rand.Read(bytes)
return handler(qgrpc.NewContextWithPeerID(ctx, peer.ID(bytes)), req)
}
// Identify implements channel.AuthenticationProvider.
func (n *Nopthenticator) Identify(ctx context.Context) (peer.ID, error) {
bytes := make([]byte, 20)
rand.Read(bytes)
return peer.ID(bytes), nil
}
var _ channel.AuthenticationProvider = (*Nopthenticator)(nil)