package engines_test import ( "bytes" "context" "crypto/rand" "encoding/binary" "encoding/hex" "fmt" "io" "math/big" "slices" "strings" "sync" "testing" "time" "github.com/cloudflare/circl/sign/ed448" "github.com/libp2p/go-libp2p/core/peer" "github.com/multiformats/go-multiaddr" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" "go.uber.org/zap" "golang.org/x/crypto/sha3" "google.golang.org/grpc" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/wrapperspb" "source.quilibrium.com/quilibrium/monorepo/config" "source.quilibrium.com/quilibrium/monorepo/go-libp2p-blossomsub/pb" "source.quilibrium.com/quilibrium/monorepo/node/consensus/app" "source.quilibrium.com/quilibrium/monorepo/node/consensus/global" consensustime "source.quilibrium.com/quilibrium/monorepo/node/consensus/time" "source.quilibrium.com/quilibrium/monorepo/node/execution/engines" "source.quilibrium.com/quilibrium/monorepo/node/execution/intrinsics/compute" "source.quilibrium.com/quilibrium/monorepo/node/execution/intrinsics/token" hgstate "source.quilibrium.com/quilibrium/monorepo/node/execution/state/hypergraph" "source.quilibrium.com/quilibrium/monorepo/node/keys" "source.quilibrium.com/quilibrium/monorepo/node/p2p" pstore "source.quilibrium.com/quilibrium/monorepo/node/store" "source.quilibrium.com/quilibrium/monorepo/node/tests" "source.quilibrium.com/quilibrium/monorepo/protobufs" "source.quilibrium.com/quilibrium/monorepo/types/channel" consensustypes "source.quilibrium.com/quilibrium/monorepo/types/consensus" "source.quilibrium.com/quilibrium/monorepo/types/crypto" "source.quilibrium.com/quilibrium/monorepo/types/execution" "source.quilibrium.com/quilibrium/monorepo/types/hypergraph" tkeys "source.quilibrium.com/quilibrium/monorepo/types/keys" "source.quilibrium.com/quilibrium/monorepo/types/mocks" tp2p "source.quilibrium.com/quilibrium/monorepo/types/p2p" "source.quilibrium.com/quilibrium/monorepo/types/schema" "source.quilibrium.com/quilibrium/monorepo/types/store" "source.quilibrium.com/quilibrium/monorepo/types/tries" ) type mockEncryptedChannel struct{} // DecryptTwoPartyMessage implements channel.EncryptedChannel. func (m *mockEncryptedChannel) DecryptTwoPartyMessage(ratchetState string, envelope *channel.P2PChannelEnvelope) (newRatchetState string, message []byte, err error) { panic("unimplemented") } // EncryptTwoPartyMessage implements channel.EncryptedChannel. func (m *mockEncryptedChannel) EncryptTwoPartyMessage(ratchetState string, message []byte) (newRatchetState string, envelope *channel.P2PChannelEnvelope, err error) { panic("unimplemented") } // EstablishTwoPartyChannel implements channel.EncryptedChannel. func (m *mockEncryptedChannel) EstablishTwoPartyChannel(isSender bool, sendingIdentityPrivateKey []byte, sendingSignedPrePrivateKey []byte, receivingIdentityKey []byte, receivingSignedPreKey []byte) (string, error) { panic("unimplemented") } // makeExtrinsicAddress creates a 32-byte address for ExecutionContextExtrinsic testing func makeExtrinsicAddress(name string) []byte { addr := make([]byte, 32) copy(addr, []byte(name)) return addr } func generateRDFPrelude( appAddress []byte, config *token.TokenIntrinsicConfiguration, ) string { appAddressHex := hex.EncodeToString(appAddress) prelude := "BASE \n" + "PREFIX rdf: \n" + "PREFIX rdfs: \n" + "PREFIX qcl: \n" + "PREFIX coin: \n" if config.Behavior&token.Acceptable != 0 { prelude += "PREFIX pending: \n" } prelude += "\n" return prelude } func prepareRDFSchemaFromConfig( appAddress []byte, config *token.TokenIntrinsicConfiguration, ) (string, error) { schema := generateRDFPrelude(appAddress, config) schema += "coin:Coin a rdfs:Class.\n" + "coin:FrameNumber a rdfs:Property;\n" + " rdfs:domain qcl:Uint;\n" + " qcl:size 8;\n" + " qcl:order 0;\n" + " rdfs:range coin:Coin.\n" + "coin:Commitment a rdfs:Property;\n" + " rdfs:domain qcl:ByteArray;\n" + " qcl:size 56;\n" + " qcl:order 1;\n" + " rdfs:range coin:Coin.\n" + "coin:OneTimeKey a rdfs:Property;\n" + " rdfs:domain qcl:ByteArray;\n" + " qcl:size 56;\n" + " qcl:order 2;\n" + " rdfs:range coin:Coin.\n" + "coin:VerificationKey a rdfs:Property;\n" + " rdfs:domain qcl:ByteArray;\n" + " qcl:size 56;\n" + " qcl:order 3;\n" + " rdfs:range coin:Coin.\n" + "coin:CoinBalance a rdfs:Property;\n" + " rdfs:domain qcl:Uint;\n" + " qcl:size 56;\n" + " qcl:order 4;\n" + " rdfs:range coin:Coin.\n" + "coin:Mask a rdfs:Property;\n" + " rdfs:domain qcl:ByteArray;\n" + " qcl:size 56;\n" + " qcl:order 5;\n" + " rdfs:range coin:Coin.\n" if config.Behavior&token.Divisible == 0 { schema += "coin:AdditionalReference a rdfs:Property;\n" + " rdfs:domain qcl:ByteArray;\n" + " qcl:size 64;\n" + " qcl:order 6;\n" + " rdfs:range coin:Coin.\n" schema += "coin:AdditionalReferenceKey a rdfs:Property;\n" + " rdfs:domain qcl:ByteArray;\n" + " qcl:size 56;\n" + " qcl:order 7;\n" + " rdfs:range coin:Coin.\n" } if config.Behavior&token.Acceptable != 0 { schema += "\npending:PendingTransaction a rdfs:Class;\n" + " rdfs:label \"a pending transaction\".\n" + "pending:FrameNumber a rdfs:Property;\n" + " rdfs:domain qcl:Uint;\n" + " qcl:size 8;\n" + " qcl:order 0;\n" + " rdfs:range pending:PendingTransaction.\n" + "pending:Commitment a rdfs:Property;\n" + " rdfs:domain qcl:ByteArray;\n" + " qcl:size 56;\n" + " qcl:order 1;\n" + " rdfs:range pending:PendingTransaction.\n" + "pending:ToOneTimeKey a rdfs:Property;\n" + " rdfs:domain qcl:ByteArray;\n" + " qcl:size 56;\n" + " qcl:order 2;\n" + " rdfs:range pending:PendingTransaction.\n" + "pending:RefundOneTimeKey a rdfs:Property;\n" + " rdfs:domain qcl:ByteArray;\n" + " qcl:size 56;\n" + " qcl:order 3;\n" + " rdfs:range pending:PendingTransaction.\n" + "pending:ToVerificationKey a rdfs:Property;\n" + " rdfs:domain qcl:ByteArray;\n" + " qcl:size 56;\n" + " qcl:order 4;\n" + " rdfs:range pending:PendingTransaction.\n" + "pending:RefundVerificationKey a rdfs:Property;\n" + " rdfs:domain qcl:ByteArray;\n" + " qcl:size 56;\n" + " qcl:order 5;\n" + " rdfs:range pending:PendingTransaction.\n" + "pending:ToCoinBalance a rdfs:Property;\n" + " rdfs:domain qcl:Uint;\n" + " qcl:size 56;\n" + " qcl:order 6;\n" + " rdfs:range pending:PendingTransaction.\n" + "pending:RefundCoinBalance a rdfs:Property;\n" + " rdfs:domain qcl:Uint;\n" + " qcl:size 56;\n" + " qcl:order 7;\n" + " rdfs:range pending:PendingTransaction.\n" + "pending:ToMask a rdfs:Property;\n" + " rdfs:domain qcl:ByteArray;\n" + " qcl:size 56;\n" + " qcl:order 8;\n" + " rdfs:range pending:PendingTransaction.\n" + "pending:RefundMask a rdfs:Property;\n" + " rdfs:domain qcl:ByteArray;\n" + " qcl:size 56;\n" + " qcl:order 9;\n" + " rdfs:range pending:PendingTransaction.\n" if config.Behavior&token.Divisible == 0 { schema += "pending:ToAdditionalReference a rdfs:Property;\n" + " rdfs:domain qcl:ByteArray;\n" + " qcl:size 64;\n" + " qcl:order 10;\n" + " rdfs:range pending:PendingTransaction.\n" + "pending:ToAdditionalReferenceKey a rdfs:Property;\n" + " rdfs:domain qcl:ByteArray;\n" + " qcl:size 56;\n" + " qcl:order 11;\n" + " rdfs:range pending:PendingTransaction.\n" + "pending:RefundAdditionalReference a rdfs:Property;\n" + " rdfs:domain qcl:ByteArray;\n" + " qcl:size 64;\n" + " qcl:order 12;\n" + " rdfs:range pending:PendingTransaction.\n" + "pending:RefundAdditionalReferenceKey a rdfs:Property;\n" + " rdfs:domain qcl:ByteArray;\n" + " qcl:size 56;\n" + " qcl:order 13;\n" + " rdfs:range pending:PendingTransaction.\n" } if config.Behavior&token.Expirable != 0 { schema += "pending:Expiration a rdfs:Property;\n" + " rdfs:domain qcl:Uint;\n" + " qcl:size 8;\n" if config.Behavior&token.Divisible == 0 { schema += " qcl:order 14;\n" } else { schema += " qcl:order 10;\n" } schema += " rdfs:range pending:PendingTransaction.\n" } } schema += "\n" return schema, nil } type mockVertex struct { mock.Mock } // Commit implements hypergraph.Vertex. func (m *mockVertex) Commit(prover crypto.InclusionProver) []byte { panic("unimplemented") } // GetAppAddress implements hypergraph.Vertex. func (m *mockVertex) GetAppAddress() [32]byte { panic("unimplemented") } // GetAtomType implements hypergraph.Vertex. func (m *mockVertex) GetAtomType() hypergraph.AtomType { panic("unimplemented") } // GetDataAddress implements hypergraph.Vertex. func (m *mockVertex) GetDataAddress() [32]byte { panic("unimplemented") } // GetID implements hypergraph.Vertex. func (m *mockVertex) GetID() [64]byte { panic("unimplemented") } // GetSize implements hypergraph.Vertex. func (m *mockVertex) GetSize() *big.Int { panic("unimplemented") } // ToBytes implements hypergraph.Vertex. func (m *mockVertex) ToBytes() []byte { panic("unimplemented") } type mockFrameValidator struct { mock.Mock } func (m *mockFrameValidator) Validate(frame *protobufs.AppShardFrame) (bool, error) { args := m.Called(frame) return args.Bool(0), args.Error(1) } type mockDynamicFeeManager struct { mock.Mock } func (m *mockDynamicFeeManager) AddFrameFeeVote(filter []byte, frameNumber uint64, feeMultiplierVote uint64) error { args := m.Called(filter, frameNumber, feeMultiplierVote) return args.Error(0) } func (m *mockDynamicFeeManager) GetNextFeeMultiplier(filter []byte) (uint64, error) { args := m.Called(filter) return args.Get(0).(uint64), args.Error(1) } func (m *mockDynamicFeeManager) GetVoteHistory(filter []byte) ([]uint64, error) { args := m.Called(filter) return args.Get(0).([]uint64), args.Error(1) } func (m *mockDynamicFeeManager) GetAverageWindowSize(filter []byte) (int, error) { args := m.Called(filter) return args.Int(0), args.Error(1) } func (m *mockDynamicFeeManager) PruneOldData(maxAge uint64) error { args := m.Called(maxAge) return args.Error(0) } func (m *mockDynamicFeeManager) RewindToFrame(filter []byte, frameNumber uint64) (int, error) { args := m.Called(filter, frameNumber) return args.Int(0), args.Error(1) } type mockGlobalFrameValidator struct { mock.Mock } func (m *mockGlobalFrameValidator) Validate(frame *protobufs.GlobalFrame) (bool, error) { args := m.Called(frame) return args.Bool(0), args.Error(1) } func createTestGlobalConsensusEngine(t *testing.T) ( *global.GlobalConsensusEngine, *mockPubSub, *mockGlobalFrameValidator, *mocks.MockDifficultyAdjuster, *mocks.MockEventDistributor, *consensustime.GlobalTimeReel, ) { logger := zap.NewNop() config := &config.Config{ Engine: &config.EngineConfig{ Difficulty: 100, }, P2P: &config.P2PConfig{ Network: 99, }, } // Create mocks pubsub := newMockPubSub([]byte{0x01, 0x02, 0x03, 0x04}) hypergraph := &mocks.MockHypergraph{} keyManager := &mocks.MockKeyManager{} keyStore := &mocks.MockKeyStore{} clockStore := &mocks.MockClockStore{} frameProver := &mocks.MockFrameProver{} inclusionProver := &mocks.MockInclusionProver{} signerRegistry := &mocks.MockSignerRegistry{} proverRegistry := &mocks.MockProverRegistry{} dynamicFeeManager := &mockDynamicFeeManager{} appFrameValidator := new(mockFrameValidator) frameValidator := &mockGlobalFrameValidator{} difficultyAdjuster := &mocks.MockDifficultyAdjuster{} rewardIssuance := &mocks.MockRewardIssuance{} eventDistributor := &mocks.MockEventDistributor{} // Create time reel globalTimeReel, err := consensustime.NewGlobalTimeReel(logger, proverRegistry, clockStore, 99, true) require.NoError(t, err) eventDistributor.On("Start", mock.Anything).Return(nil) eventDistributor.On("Subscribe", mock.Anything).Return(make(<-chan consensustypes.ControlEvent, 10)) eventDistributor.On("Unsubscribe", mock.Anything).Return() eventDistributor.On("Stop").Return(nil) proverRegistry.On("GetOrderedProvers", mock.Anything, mock.Anything).Return([][]byte{}, nil) // Create mock signer with Public method mockSigner := &mocks.MockBLSSigner{} mockSigner.On("Public").Return(make([]byte, 585)) mockSigner.On("SignWithDomain", mock.Anything, mock.Anything).Return(make([]byte, 74), nil) keyManager.On("GetSigningKey", mock.Anything).Return(mockSigner, nil) keyManager.On("GetRawKey", mock.Anything).Return(&tkeys.Key{ Type: crypto.KeyTypeBLS48581G1, PublicKey: make([]byte, 585), }, nil) // Create engine engine, err := global.NewGlobalConsensusEngine( logger, config, 1000, // frameTimeMillis pubsub, hypergraph, keyManager, keyStore, frameProver, inclusionProver, signerRegistry, proverRegistry, dynamicFeeManager, appFrameValidator, frameValidator, difficultyAdjuster, rewardIssuance, eventDistributor, globalTimeReel, nil, nil, nil, nil, nil, nil, &mockEncryptedChannel{}, &mocks.MockBulletproofProver{}, &mocks.MockVerifiableEncryptor{}, &mocks.MockDecafConstructor{}, &mocks.MockCompiler{}, nil, p2p.NewInMemoryPeerInfoManager(logger), ) require.NoError(t, err) return engine, pubsub, frameValidator, difficultyAdjuster, eventDistributor, globalTimeReel } // createTestProverRegistry creates a mock ProverRegistry that returns expected provers func createTestProverRegistry() *mocks.MockProverRegistry { proverRegistry := new(mocks.MockProverRegistry) proverRegistry.On("GetNextProver", mock.Anything, mock.Anything).Return([]byte{0x01, 0x02, 0x03, 0x04}, nil) proverRegistry.On("GetOrderedProvers", mock.Anything, mock.Anything).Return([][]byte{{0x01, 0x02, 0x03, 0x04}}, nil) return proverRegistry } func createTestAppTimeReel( t *testing.T, appAddress []byte, clockStore store.ClockStore, ) *consensustime.AppTimeReel { logger := zap.NewNop() proverRegistry := createTestProverRegistry() appTimeReel, err := consensustime.NewAppTimeReel(logger, appAddress, proverRegistry, clockStore, true) require.NoError(t, err) return appTimeReel } func createTestAppConsensusEngine( t *testing.T, ) ( *app.AppConsensusEngine, *mockPubSub, *mockFrameValidator, *mocks.MockDifficultyAdjuster, *mocks.MockEventDistributor, *consensustime.AppTimeReel, ) { logger := zap.NewNop() config := &config.Config{ Engine: &config.EngineConfig{ Difficulty: 100, }, P2P: &config.P2PConfig{ Network: 99, }, DB: &config.DBConfig{ InMemoryDONOTUSE: true, Path: ".test/test_store", }, } appAddress := []byte{0x01, 0x02, 0x03} mockPubSub := newMockPubSub([]byte{0x01, 0x02, 0x03, 0x04}) mockHypergraph := new(mocks.MockHypergraph) mockKeyManager := new(mocks.MockKeyManager) mockKeyStore := new(mocks.MockKeyStore) mockFrameProver := new(mocks.MockFrameProver) mockInclusionProver := new(mocks.MockInclusionProver) mockSignerRegistry := new(mocks.MockSignerRegistry) mockFrameValidator := new(mockFrameValidator) mockDifficultyAdjuster := new(mocks.MockDifficultyAdjuster) mockRewardIssuance := new(mocks.MockRewardIssuance) mockEventDistributor := new(mocks.MockEventDistributor) pebbleDB := pstore.NewPebbleDB(logger, config.DB, 0) clockStore := pstore.NewPebbleClockStore(pebbleDB, logger) inboxStore := pstore.NewPebbleInboxStore(pebbleDB, logger) shardStore := pstore.NewPebbleShardsStore(pebbleDB, logger) consensusStore := pstore.NewPebbleConsensusStore(pebbleDB, logger) hypergraphStore := pstore.NewPebbleHypergraphStore(config.DB, pebbleDB, logger, &mocks.MockVerifiableEncryptor{}, mockInclusionProver) appTimeReel := createTestAppTimeReel(t, appAddress, clockStore) mockProverRegistry := createTestProverRegistry() mockDynamicFeeManager := new(mockDynamicFeeManager) // Create global time reel globalTimeReel, err := consensustime.NewGlobalTimeReel(logger, mockProverRegistry, clockStore, 99, true) require.NoError(t, err) mockKey := &tkeys.Key{ Id: "q-prover-key", Type: crypto.KeyTypeBLS48581G1, PublicKey: make([]byte, 585), PrivateKey: make([]byte, 74), } mockFrameProver.On("ProveFrameHeaderGenesis", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&protobufs.FrameHeader{ FrameNumber: 0, Address: []byte{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, }, Output: make([]byte, 516), Timestamp: 0, Difficulty: 160000, ParentSelector: make([]byte, 32), RequestsRoot: make([]byte, 64), StateRoots: make([][]byte, 4), Prover: make([]byte, 32), FeeMultiplierVote: 100, }, nil) mockEventDistributor.On("Start", mock.Anything).Return(nil) mockEventDistributor.On("Subscribe", mock.Anything).Return(make(<-chan consensustypes.ControlEvent, 10)) mockEventDistributor.On("Unsubscribe", mock.Anything).Return() mockEventDistributor.On("Stop").Return(nil) mockSigner := new(mocks.MockBLSSigner) mockSigner.On("Public").Return(make([]byte, 585)) mockSigner.On("Private").Return(make([]byte, 74)) mockKeyManager.On("GetSigningKey", "q-prover-key").Return(mockSigner, nil) mockKeyManager.On("GetRawKey", "q-prover-key").Return(mockKey, nil) mockDynamicFeeManager.On("AddFrameFeeVote", mock.Anything, mock.Anything, mock.Anything).Return(nil) engine, err := app.NewAppConsensusEngine( logger, config, 1, appAddress, mockPubSub, mockHypergraph, mockKeyManager, mockKeyStore, clockStore, inboxStore, shardStore, hypergraphStore, consensusStore, mockFrameProver, mockInclusionProver, &mocks.MockBulletproofProver{}, // bulletproofProver &mocks.MockVerifiableEncryptor{}, // verEnc &mocks.MockDecafConstructor{}, // decafConstructor &mocks.MockCompiler{}, // compiler mockSignerRegistry, mockProverRegistry, mockDynamicFeeManager, mockFrameValidator, &mockGlobalFrameValidator{}, mockDifficultyAdjuster, mockRewardIssuance, mockEventDistributor, p2p.NewInMemoryPeerInfoManager(logger), appTimeReel, globalTimeReel, &mocks.MockBlsConstructor{}, &mockEncryptedChannel{}, nil, ) assert.NoError(t, err) return engine, mockPubSub, mockFrameValidator, mockDifficultyAdjuster, mockEventDistributor, appTimeReel } // mockPubSub extends the basic mock with app-specific features type mockPubSub struct { mock.Mock mu sync.RWMutex subscribers map[string][]func(message *pb.Message) error validators map[string]func(peerID peer.ID, message *pb.Message) tp2p.ValidationResult peerID []byte peerCount int networkPeers map[string]*mockPubSub messageLog []messageRecord // Track all messages for debugging globalFrames []*protobufs.GlobalFrame // Store frames for sync appFrames []*protobufs.AppShardFrame // Store frames for sync } // GetOwnMultiaddrs implements tp2p.PubSub. func (m *mockPubSub) GetOwnMultiaddrs() []multiaddr.Multiaddr { panic("unimplemented") } // AddPeerScore implements tp2p.PubSub. func (m *mockPubSub) AddPeerScore(peerId []byte, scoreDelta int64) { panic("unimplemented") } // Bootstrap implements tp2p.PubSub. func (m *mockPubSub) Bootstrap(ctx context.Context) error { panic("unimplemented") } // DiscoverPeers implements tp2p.PubSub. func (m *mockPubSub) DiscoverPeers(ctx context.Context) error { panic("unimplemented") } // GetDirectChannel implements tp2p.PubSub. func (m *mockPubSub) GetDirectChannel(ctx context.Context, peerId []byte, purpose string) (*grpc.ClientConn, error) { panic("unimplemented") } // GetMultiaddrOfPeer implements tp2p.PubSub. func (m *mockPubSub) GetMultiaddrOfPeer(peerId []byte) string { panic("unimplemented") } // GetMultiaddrOfPeerStream implements tp2p.PubSub. func (m *mockPubSub) GetMultiaddrOfPeerStream(ctx context.Context, peerId []byte) <-chan multiaddr.Multiaddr { panic("unimplemented") } // GetNetwork implements tp2p.PubSub. func (m *mockPubSub) GetNetwork() uint { panic("unimplemented") } // GetNetworkPeersCount implements tp2p.PubSub. func (m *mockPubSub) GetNetworkPeersCount() int { panic("unimplemented") } // GetPeerScore implements tp2p.PubSub. func (m *mockPubSub) GetPeerScore(peerId []byte) int64 { panic("unimplemented") } // GetPublicKey implements tp2p.PubSub. func (m *mockPubSub) GetPublicKey() []byte { panic("unimplemented") } // GetRandomPeer implements tp2p.PubSub. func (m *mockPubSub) GetRandomPeer(bitmask []byte) ([]byte, error) { panic("unimplemented") } // IsPeerConnected implements tp2p.PubSub. func (m *mockPubSub) IsPeerConnected(peerId []byte) bool { panic("unimplemented") } // Publish implements tp2p.PubSub. func (m *mockPubSub) Publish(address []byte, data []byte) error { panic("unimplemented") } // Reachability implements tp2p.PubSub. func (m *mockPubSub) Reachability() *wrapperspb.BoolValue { panic("unimplemented") } // Reconnect implements tp2p.PubSub. func (m *mockPubSub) Reconnect(peerId []byte) error { panic("unimplemented") } // SetPeerScore implements tp2p.PubSub. func (m *mockPubSub) SetPeerScore(peerId []byte, score int64) { panic("unimplemented") } // SignMessage implements tp2p.PubSub. func (m *mockPubSub) SignMessage(msg []byte) ([]byte, error) { panic("unimplemented") } // StartDirectChannelListener implements tp2p.PubSub. func (m *mockPubSub) StartDirectChannelListener(key []byte, purpose string, server *grpc.Server) error { panic("unimplemented") } type messageRecord struct { timestamp time.Time from []byte to []byte data []byte } func newMockPubSub(peerID []byte) *mockPubSub { return &mockPubSub{ subscribers: make(map[string][]func(message *pb.Message) error), validators: make(map[string]func(peerID peer.ID, message *pb.Message) tp2p.ValidationResult), peerID: peerID, peerCount: 10, networkPeers: make(map[string]*mockPubSub), messageLog: make([]messageRecord, 0), globalFrames: make([]*protobufs.GlobalFrame, 0), appFrames: make([]*protobufs.AppShardFrame, 0), } } func (m *mockPubSub) Subscribe(bitmask []byte, handler func(message *pb.Message) error) error { m.mu.Lock() defer m.mu.Unlock() key := string(bitmask) m.subscribers[key] = append(m.subscribers[key], handler) return nil } func (m *mockPubSub) PublishToBitmask(bitmask []byte, data []byte) error { m.mu.Lock() m.messageLog = append(m.messageLog, messageRecord{ timestamp: time.Now(), from: m.peerID, to: bitmask, data: data, }) // If this is an app frame, store it for sync if len(bitmask) >= 4 && bitmask[0] != 0x01 { // Not a message bitmask frame := &protobufs.AppShardFrame{} if err := proto.Unmarshal(data, frame); err == nil { m.appFrames = append(m.appFrames, frame) } } m.mu.Unlock() message := &pb.Message{ Data: data, From: m.peerID, } // Deliver to local subscribers m.mu.RLock() handlers := m.subscribers[string(bitmask)] m.mu.RUnlock() for _, handler := range handlers { go handler(message) } // Deliver to network peers m.mu.RLock() peers := make([]*mockPubSub, 0, len(m.networkPeers)) for _, peer := range m.networkPeers { if peer != m { peers = append(peers, peer) } } m.mu.RUnlock() for _, peer := range peers { // Deliver synchronously to ensure proper ordering peer.receiveFromNetwork(bitmask, message) } return nil } func (m *mockPubSub) receiveFromNetwork(bitmask []byte, message *pb.Message) { m.mu.RLock() validator := m.validators[string(bitmask)] m.mu.RUnlock() if validator != nil { result := validator(peer.ID(message.From), message) if result != tp2p.ValidationResultAccept { // Log validation rejection for debugging frame := &protobufs.AppShardFrame{} if err := proto.Unmarshal(message.Data, frame); err == nil && frame.Header != nil { fmt.Printf("DEBUG: Node %x rejected frame %d from %x (validation result: %v)\n", m.peerID[:4], frame.Header.FrameNumber, message.From[:4], result) } return } } m.mu.RLock() handlers := m.subscribers[string(bitmask)] m.mu.RUnlock() for _, handler := range handlers { go handler(message) // Make async to match PublishToBitmask behavior } } func (m *mockPubSub) RegisterValidator(bitmask []byte, validator func(peerID peer.ID, message *pb.Message) tp2p.ValidationResult, sync bool) error { m.mu.Lock() defer m.mu.Unlock() m.validators[string(bitmask)] = validator return nil } func (m *mockPubSub) GetPeerstoreCount() int { return m.peerCount } func (m *mockPubSub) GetPeerID() []byte { return m.peerID } func (m *mockPubSub) Unsubscribe(bitmask []byte, raw bool) { m.mu.Lock() defer m.mu.Unlock() delete(m.subscribers, string(bitmask)) } func (m *mockPubSub) UnregisterValidator(bitmask []byte) error { m.mu.Lock() defer m.mu.Unlock() delete(m.validators, string(bitmask)) return nil } func (m *mockPubSub) GetNetworkInfo() *protobufs.NetworkInfoResponse { return &protobufs.NetworkInfoResponse{} } type mockTransaction struct{} // Abort implements store.Transaction. func (m *mockTransaction) Abort() error { return nil } // Commit implements store.Transaction. func (m *mockTransaction) Commit() error { return nil } // Delete implements store.Transaction. func (m *mockTransaction) Delete(key []byte) error { panic("unimplemented") } // DeleteRange implements store.Transaction. func (m *mockTransaction) DeleteRange(lowerBound []byte, upperBound []byte) error { panic("unimplemented") } // Get implements store.Transaction. func (m *mockTransaction) Get(key []byte) ([]byte, io.Closer, error) { panic("unimplemented") } // NewIter implements store.Transaction. func (m *mockTransaction) NewIter(lowerBound []byte, upperBound []byte) (store.Iterator, error) { panic("unimplemented") } // Set implements store.Transaction. func (m *mockTransaction) Set(key []byte, value []byte) error { return nil } // setupTokenIntrinsicMocks sets up token intrinsic mocks for payment verification func setupTokenIntrinsicMocks( t *testing.T, mockHG *mocks.MockHypergraph, ) { // For payment transactions, we need to use the QUIL token address tokenDomain := token.QUIL_TOKEN_ADDRESS // Set up token intrinsic metadata mock for this specific domain tokenMetadataAddress := slices.Concat(tokenDomain, bytes.Repeat([]byte{0xff}, 32)) tokenMetadataTree := &tries.VectorCommitmentTree{} // Create a mock vertex for token metadata tokenMockVertex := &mockVertex{} tokenMockVertex.On("GetAddress").Return(tokenMetadataAddress) tokenMockVertex.On("GetData").Return(tokenMetadataTree, nil) // Set up the mock expectations mockHG.On("GetVertex", [64]byte(tokenMetadataAddress)).Return(tokenMockVertex, nil).Maybe() mockHG.On("GetVertexData", [64]byte(tokenMetadataAddress)).Return(tokenMetadataTree, nil).Maybe() } // setupComputeMocks sets up the common mocks for compute execution engine tests func setupComputeMocks( t *testing.T, mockHG *mocks.MockHypergraph, mockInclusionProver *mocks.MockInclusionProver, mockBulletproofProver *mocks.MockBulletproofProver, engineMode engines.ExecutionMode, ) { txn := &mockTransaction{} mockHG.On("NewTransaction", false).Return(txn, nil) mockHG.On("GetProver").Return(mockInclusionProver) mockInclusionProver.On("CommitRaw", mock.Anything, mock.Anything).Return(make([]byte, 74), nil) mockHG.On("Commit").Return(map[tries.ShardKey][][]byte{}) mockHG.On("AddVertex", mock.Anything, mock.Anything).Return(nil) mockHG.On("SetVertexData", mock.Anything, mock.Anything, mock.Anything).Return(nil) mockBulletproofProver.On("SimpleVerify", mock.Anything, mock.Anything, mock.Anything).Return(true) // Add mock for multiproof creation mockMultiproof := new(mocks.MockMultiproof) mockMultiproof.On("FromBytes", mock.Anything).Return(nil) mockMultiproof.On("Size").Return(0).Maybe() mockMultiproof.On("ComputeSize").Return(0).Maybe() mockMultiproof.On("Bind", mock.Anything).Return(nil).Maybe() mockMultiproof.On("Prove", mock.Anything).Return(nil).Maybe() mockMultiproof.On("Reset").Return(nil).Maybe() mockMultiproof.On("Commit", mock.Anything).Return([]byte{}, nil).Maybe() mockMultiproof.On("Verify", mock.Anything, mock.Anything).Return(true, nil).Maybe() mockMultiproof.On("ProveMultiple", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return([]byte{}, nil).Maybe() mockInclusionProver.On("NewMultiproof").Return(mockMultiproof) // Don't set up the GlobalMode metadata check here - let each test handle it // based on whether it's before or after deployment // Set up a generic mock for any GetVertex calls (for code deployment addresses) mockHG.On("GetVertex", mock.Anything).Return(nil, nil).Maybe() // Set up a generic mock for code deployment GetVertexData that matches the pattern // Create the tree once to reuse code := []byte("package main\n\nfunc main(a, b int) int { return a + b }") codeTree := &tries.VectorCommitmentTree{} codeTree.Insert([]byte{0 << 2}, code, nil, big.NewInt(int64(len(code)))) // This will match any 64-byte address that has "app" in it after byte 32 mockHG.On("GetVertexData", mock.MatchedBy(func(addr [64]byte) bool { // Check if the address contains "app" starting from byte 32 for i := 32; i < 64-2; i++ { if addr[i] == 'a' && addr[i+1] == 'p' && addr[i+2] == 'p' { return true } } return false })).Return(codeTree, nil).Maybe() } // setupCodeDeploymentData sets up mock data for deployed code func setupCodeDeploymentData( t *testing.T, mockHG *mocks.MockHypergraph, domain []byte, codeAddress []byte, ) { // Create a 64-byte address from the code address var addr64 [64]byte copy(addr64[:], domain) copy(addr64[32:], codeAddress) // Set up code deployment data code := []byte("package main\n\nfunc main(a, b int) int { return a + b }") err := tests.SetHypergraphCodeData(mockHG, addr64[:], code) require.NoError(t, err) } // setupGlobalModePreDeploymentMocks sets up the mock for GlobalMode before deployment func setupGlobalModePreDeploymentMocks( mockHG *mocks.MockHypergraph, domain []byte, ) { metadataAddress := slices.Concat(domain, bytes.Repeat([]byte{0xff}, 32)) // Before deployment, the metadata vertex doesn't exist mockHG.On("GetVertex", [64]byte(metadataAddress)).Return(nil, store.ErrNotFound) } // setupComputeMetadata sets up the compute metadata after deployment func setupComputeMetadata( t *testing.T, mockHG *mocks.MockHypergraph, domain []byte, readKey []byte, writeKey []byte, ) { // Use provided keys for metadata rdfSchema := `BASE PREFIX rdf: PREFIX rdfs: PREFIX qcl: PREFIX req: req:Request a rdfs:Class. req:A a rdfs:Property; rdfs:domain qcl:Uint; qcl:size 1; qcl:order 0; rdfs:range req:Request. ` // After deployment is done, set up the metadata metadataAddress := slices.Concat(domain, bytes.Repeat([]byte{0xff}, 32)) err := tests.SetHypergraphComputeMetadataData( mockHG, metadataAddress, rdfSchema, nil, // creator not needed for test readKey, writeKey, ) require.NoError(t, err) } // Calling this test "just" a test for compute execution engine is a bit of a // misnomer, because it involves a lot of moving pieces that need to occur in a // specific order: The global execution engine needs to handle the deployment, // allocate provers, verify the payment for the fee (for deployment and // execution), and then the app execution engine has to consume the deployment, // settle the metadata for it, process the rdf bundle (for hypergraph // settlement), verify the payment for the execution fee, and handle the close // out of the execution for fee dispatch. It is by far the most integration-y // unit test we have. Like FAA guidelines, this test is written in the blood of // past failures. Heed the failures like hard rules, and if you're questioning // whether the test is wrong, you probably haven't bled enough. func TestComputeExecutionEngine_ProcessMessage_DeployWithPaymentAndExecute( t *testing.T, ) { // Helper function to perform deployment steps with specific keys performDeploymentWithKeys := func(t *testing.T, engine *engines.ComputeExecutionEngine, mockHG *mocks.MockHypergraph, mockCompiler *mocks.MockCompiler, readKey, writeKey []byte, engineMode engines.ExecutionMode) []byte { mockHG.On("GetCoveredPrefix").Return([]int{}, nil) // Use provided keys outFees := []*big.Int{big.NewInt(1)} total := big.NewInt(10000000) outFees = append(outFees, total) payment, err := tests.CreateValidQUILPendingTransactionPayload( mockHG, 1, [][]byte{make([]byte, 56)}, [][]byte{make([]byte, 56)}, [][]byte{make([]byte, 56)}, [][]byte{make([]byte, 56)}, []*big.Int{big.NewInt(10000001)}, []*big.Int{big.NewInt(0)}, outFees, 0, ) if err != nil { panic(err) } // Deploy RDF schema with keys args := compute.ComputeDeploy{ Config: &compute.ComputeIntrinsicConfiguration{ ReadPublicKey: readKey, WritePublicKey: writeKey, }, RDFSchema: []byte(`BASE PREFIX rdf: PREFIX rdfs: PREFIX qcl: PREFIX req: req:Request a rdfs:Class. req:A a rdfs:Property; rdfs:domain qcl:Uint; qcl:size 1; qcl:order 0; rdfs:range req:Request. `), } deploy := &protobufs.MessageRequest{ Request: &protobufs.MessageRequest_ComputeDeploy{ ComputeDeploy: args.ToProtobuf(), }, } bundle := &protobufs.MessageBundle{ Requests: []*protobufs.MessageRequest{ payment, deploy, }, } bundleBytes, err := bundle.ToCanonicalBytes() require.NoError(t, err) deployHash := sha3.Sum256(bundleBytes) msg := &protobufs.Message{ Address: compute.COMPUTE_INTRINSIC_DOMAIN[:], Hash: deployHash[:], Payload: bundleBytes, } state := hgstate.NewHypergraphState(mockHG) result, err := engine.ProcessMessage(0, big.NewInt(0), msg.Address, msg.Payload, state) require.NoError(t, err) ch := state.Changeset() domain := ch[0].Domain require.Len(t, result.Messages, 0) mockCircuit := &mocks.MockCompiledCircuit{} mockCircuit.On("Marshal", mock.Anything).Return(nil) mockCompiler.On("Compile", mock.Anything, mock.Anything).Return(mockCircuit, nil) mockCompiler.On("ValidateCircuit", mock.Anything).Return(nil) // In GlobalMode, code deployment is not allowed after RDF schema deployment if engineMode != engines.GlobalMode { // Deploy code sourceCode := []byte("package main\n\nfunc main(a, b int) int { return a + b }") deployment, err := compute.NewCodeDeployment( [32]byte(domain), sourceCode, [2]string{"qcl:Int", "qcl:Int"}, [2][]int{{4}, {4}}, []string{"qcl:Int"}, mockCompiler, ) require.NoError(t, err) err = deployment.Prove(1) require.NoError(t, err) // Wrap in MessageRequest deploy := &protobufs.MessageRequest{ Request: &protobufs.MessageRequest_CodeDeploy{ CodeDeploy: deployment.ToProtobuf(), }, } outFees := []*big.Int{big.NewInt(1)} total := big.NewInt(10000000) outFees = append(outFees, total) payment, err := tests.CreateValidQUILPendingTransactionPayload( mockHG, 1, [][]byte{make([]byte, 56)}, [][]byte{make([]byte, 56)}, [][]byte{make([]byte, 56)}, [][]byte{make([]byte, 56)}, []*big.Int{big.NewInt(10000001)}, []*big.Int{big.NewInt(0)}, outFees, 0, ) if err != nil { panic(err) } bundle := &protobufs.MessageBundle{ Requests: []*protobufs.MessageRequest{ payment, deploy, }, } bundleBytes, err = bundle.ToCanonicalBytes() require.NoError(t, err) deployHash := sha3.Sum256(bundleBytes) msg = &protobufs.Message{ Address: domain, Hash: deployHash[:], Payload: bundleBytes, } result, err = engine.ProcessMessage(0, big.NewInt(0), msg.Address, msg.Payload, result.State) require.NoError(t, err) err = result.State.Commit() require.NoError(t, err) } return domain } performBundledDeploymentAndExecution := func( t *testing.T, engine *engines.ComputeExecutionEngine, mockHG *mocks.MockHypergraph, domain []byte, mockCompiler *mocks.MockCompiler, readKey, writeKey []byte, operations []*compute.ExecuteOperation, ) ([]*protobufs.Message, error) { // Set up mock circuit for code deployment mockCircuit := &mocks.MockCompiledCircuit{} mockCircuit.On("Marshal", mock.Anything).Return(nil) mockCompiler.On("Compile", mock.Anything, mock.Anything).Return(mockCircuit, nil) mockCompiler.On("ValidateCircuit", mock.Anything).Return(nil) // Create source code for deployment sourceCode := []byte("package main\n\nfunc main(a, b int) int { return a + b }") // Create bundled message with all operations bundledMsg := createCompleteBundleWithPayment( t, mockHG, domain, readKey, writeKey, sourceCode, mockCompiler, operations, ) state := hgstate.NewHypergraphState(mockHG) // Process the bundled message result, err := engine.ProcessMessage(0, big.NewInt(0), bundledMsg.Address, bundledMsg.Payload, state) if err != nil { return nil, err } if err = state.Commit(); err != nil { return nil, err } return result.Messages, nil } performDeployment := func(t *testing.T, engine *engines.ComputeExecutionEngine, mockHG *mocks.MockHypergraph, mockCompiler *mocks.MockCompiler, engineMode engines.ExecutionMode) []byte { // Generate random keys readKey := make([]byte, 57) writeKey := make([]byte, 57) rand.Read(readKey) rand.Read(writeKey) // Perform deployment domain := performDeploymentWithKeys(t, engine, mockHG, mockCompiler, readKey, writeKey, engineMode) // Set up metadata setupComputeMetadata(t, mockHG, domain, readKey, writeKey) return domain } createTestCodeExecuteMessage := func(t *testing.T, mockHG *mocks.MockHypergraph, domain []byte, operations []*compute.ExecuteOperation) (*protobufs.Message, *compute.CodeExecute) { var rendezvous [32]byte rand.Read(rendezvous[:]) // Create valid payment transaction using protobuf outFees := []*big.Int{big.NewInt(1)} total := big.NewInt(10000000) outFees = append(outFees, total) payment, err := tests.CreateValidQUILPendingTransactionPayload( mockHG, 1, [][]byte{make([]byte, 56)}, [][]byte{make([]byte, 56)}, [][]byte{make([]byte, 56)}, [][]byte{make([]byte, 56)}, []*big.Int{big.NewInt(10000001)}, []*big.Int{big.NewInt(0)}, outFees, 0, ) if err != nil { panic(err) } paymentTxBytes, err := payment.GetPendingTransaction().ToCanonicalBytes() secretKey := make([]byte, 32) rand.Read(secretKey) ce := compute.NewCodeExecute( [32]byte(domain), paymentTxBytes, secretKey, rendezvous, operations, nil, nil, nil, nil, nil, nil, // Mock dependencies will be set by the engine ) // Set up proof of payment ce.ProofOfPayment[0] = paymentTxBytes ce.ProofOfPayment[1] = make([]byte, 112) // Ed448 signature size rand.Read(ce.ProofOfPayment[1]) // Wrap in MessageBundle and serialize executeReq := &protobufs.MessageRequest{ Request: &protobufs.MessageRequest_CodeExecute{ CodeExecute: ce.ToProtobuf(), }, } bundle := &protobufs.MessageBundle{ Requests: []*protobufs.MessageRequest{ payment, executeReq, }, } ceBytes, err := bundle.ToCanonicalBytes() require.NoError(t, err) // Create message hash := sha3.Sum256(ceBytes) require.NoError(t, err) msg := &protobufs.Message{ Address: domain, Hash: hash[:], Payload: ceBytes, } return msg, ce } // Helper function to create a test CodeFinalize message createTestCodeFinalizeMessage := func(t *testing.T, domain []byte, writePrivKey []byte, config *compute.ComputeIntrinsicConfiguration, rendezvous [32]byte, results []*compute.ExecutionResult, mockHG *mocks.MockHypergraph, keyManager *mocks.MockKeyManager) (*protobufs.Message, *compute.CodeFinalize) { cf := compute.NewCodeFinalize( rendezvous, [32]byte(domain), results, []*compute.StateTransition{}, []byte("message_output"), writePrivKey, config, nil, nil, nil, nil, nil, keyManager, // Mock dependencies ) err := cf.Prove(1) require.NoError(t, err) // Create valid payment transaction using protobuf outFees := []*big.Int{big.NewInt(1)} total := big.NewInt(10000000) outFees = append(outFees, total) payment, err := tests.CreateValidQUILPendingTransactionPayload( mockHG, 1, [][]byte{make([]byte, 56)}, [][]byte{make([]byte, 56)}, [][]byte{make([]byte, 56)}, [][]byte{make([]byte, 56)}, []*big.Int{big.NewInt(10000001)}, []*big.Int{big.NewInt(0)}, outFees, 0, ) if err != nil { panic(err) } // Wrap in MessageRequest and serialize finalizeReq := &protobufs.MessageRequest{ Request: &protobufs.MessageRequest_CodeFinalize{ CodeFinalize: cf.ToProtobuf(), }, } bundle := &protobufs.MessageBundle{ Requests: []*protobufs.MessageRequest{ payment, finalizeReq, }, } cfBytes, err := bundle.ToCanonicalBytes() require.NoError(t, err) // Create message hash := sha3.Sum256(cfBytes) require.NoError(t, err) msg := &protobufs.Message{ Address: domain, Hash: hash[:], Payload: cfBytes, } return msg, cf } // Test execution modes type TestExecutionMode int const ( TestGlobalMode TestExecutionMode = iota TestApplicationMode TestMixedMode ) // Helper function to run test with all three execution modes runTestWithAllModes := func(t *testing.T, testName string, testFunc func(t *testing.T, mode TestExecutionMode)) { modes := []struct { name string mode TestExecutionMode }{ {"global_must_sequence", TestGlobalMode}, {"app_fully_sequences", TestApplicationMode}, {"global_sequences_payment_and_partial_execute", TestMixedMode}, } for _, mode := range modes { t.Run(mode.name, func(t *testing.T) { testFunc(t, mode.mode) }) } } // Helper function to assert code execution results based on mode assertCodeExecutionResult := func(t *testing.T, mode TestExecutionMode, msgs *execution.ProcessMessageResult, err error, shouldError bool) { // In GlobalMode, after deployment, only deploy messages are allowed if mode == TestGlobalMode { assert.Error(t, err) assert.Contains(t, err.Error(), "non-deploy messages not allowed in global mode") assert.Nil(t, msgs) } else { if shouldError { assert.Error(t, err) } else { assert.NoError(t, err) assert.NotNil(t, msgs) if msgs != nil && msgs.State != nil { err = msgs.State.Commit() assert.NoError(t, err) } } } } // Helper function to assert bundled execution results assertBundledExecutionResult := func(t *testing.T, msgs []*protobufs.Message, err error) { // Bundled operations should work in all modes, including GlobalMode if err != nil { // If there's an error, it should not be the global mode restriction assert.NotContains(t, err.Error(), "non-deploy messages not allowed in global mode", "Bundled operations should bypass global mode restriction") } } // Test 1: Valid single operation no dependencies t.Run("valid_single_operation_no_dependencies", func(t *testing.T) { runTestWithAllModes(t, "valid_single_operation_no_dependencies", func(t *testing.T, mode TestExecutionMode) { // Create test dependencies logger := zap.NewNop() mockInclusionProver := new(mocks.MockInclusionProver) mockInclusionProver.On("CommitRaw", mock.Anything, mock.Anything).Return(make([]byte, 74), nil) mockHG := tests.CreateHypergraphWithInclusionProver(mockInclusionProver) mockHG.On("TrackChange", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil).Maybe() mockHG.On("Commit").Return(map[tries.ShardKey][][]byte{}).Maybe() mockKeyManager := new(mocks.MockKeyManager) mockBulletproofProver := new(mocks.MockBulletproofProver) mockVerEnc := new(mocks.MockVerifiableEncryptor) mockDecaf := new(mocks.MockDecafConstructor) mockCompiler := new(mocks.MockCompiler) // Map test mode to actual engine mode var engineMode engines.ExecutionMode switch mode { case TestGlobalMode: engineMode = engines.GlobalMode case TestApplicationMode: engineMode = engines.ApplicationMode case TestMixedMode: engineMode = engines.ApplicationMode } engine, err := engines.NewComputeExecutionEngine( logger, mockHG, mockKeyManager, mockInclusionProver, mockBulletproofProver, mockVerEnc, mockDecaf, mockCompiler, engineMode, ) require.NoError(t, err) // Set up mocks setupComputeMocks(t, mockHG, mockInclusionProver, mockBulletproofProver, engineMode) setupTokenIntrinsicMocks(t, mockHG) // Generate keys for metadata readKey := make([]byte, 57) writeKey := make([]byte, 57) rand.Read(readKey) rand.Read(writeKey) // Perform deployment with the same keys domain := performDeploymentWithKeys(t, engine, mockHG, mockCompiler, readKey, writeKey, engineMode) // Set up compute metadata setupComputeMetadata(t, mockHG, domain, readKey, writeKey) // Create single operation with no dependencies op := &compute.ExecuteOperation{ Application: compute.Application{ Address: makeExtrinsicAddress("test_app"), ExecutionContext: compute.ExecutionContextExtrinsic, }, Identifier: []byte("op1"), Dependencies: [][]byte{}, } msg, _ := createTestCodeExecuteMessage(t, mockHG, domain, []*compute.ExecuteOperation{op}) // Process message state := hgstate.NewHypergraphState(mockHG) msgs, err := engine.ProcessMessage(1, big.NewInt(0), msg.Address, msg.Payload, state) if engineMode == engines.GlobalMode { assert.Error(t, err) } else { assert.NoError(t, err) assertCodeExecutionResult(t, mode, msgs, err, false) } }) }) // Test 1b: Valid single operation using bundled approach (works in GlobalMode) t.Run("valid_single_operation_bundled", func(t *testing.T) { runTestWithAllModes(t, "valid_single_operation_bundled", func(t *testing.T, mode TestExecutionMode) { // Create test dependencies logger := zap.NewNop() mockInclusionProver := new(mocks.MockInclusionProver) mockInclusionProver.On("CommitRaw", mock.Anything, mock.Anything).Return(make([]byte, 74), nil) mockHG := tests.CreateHypergraphWithInclusionProver(mockInclusionProver) mockHG.On("Commit").Return(map[tries.ShardKey][][]byte{}).Maybe() mockHG.On("TrackChange", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil).Maybe() mockKeyManager := new(mocks.MockKeyManager) mockBulletproofProver := new(mocks.MockBulletproofProver) mockVerEnc := new(mocks.MockVerifiableEncryptor) mockDecaf := new(mocks.MockDecafConstructor) mockCompiler := new(mocks.MockCompiler) // Map test mode to actual engine mode var engineMode engines.ExecutionMode switch mode { case TestGlobalMode: engineMode = engines.GlobalMode case TestApplicationMode: engineMode = engines.ApplicationMode case TestMixedMode: engineMode = engines.ApplicationMode } engine, err := engines.NewComputeExecutionEngine( logger, mockHG, mockKeyManager, mockInclusionProver, mockBulletproofProver, mockVerEnc, mockDecaf, mockCompiler, engineMode, ) require.NoError(t, err) // Set up mocks setupComputeMocks(t, mockHG, mockInclusionProver, mockBulletproofProver, engineMode) setupTokenIntrinsicMocks(t, mockHG) // Generate keys for metadata readKey := make([]byte, 57) writeKey := make([]byte, 57) rand.Read(readKey) rand.Read(writeKey) // Create single operation op := &compute.ExecuteOperation{ Application: compute.Application{ Address: makeExtrinsicAddress("test_app"), ExecutionContext: compute.ExecutionContextExtrinsic, }, Identifier: []byte("op1"), Dependencies: [][]byte{}, } domain := make([]byte, 32) rand.Read(domain) // Use bundled approach msgs, err := performBundledDeploymentAndExecution( t, engine, mockHG, domain, mockCompiler, readKey, writeKey, []*compute.ExecuteOperation{op}, ) // Bundled operations should work in all modes assertBundledExecutionResult(t, msgs, err) // In GlobalMode, this should succeed with bundling if engineMode == engines.GlobalMode && err == nil { assert.NotNil(t, msgs, "Bundled operations should produce responses in GlobalMode") } }) }) // Test 2: Valid multiple operations sequential dependencies t.Run("valid_multiple_operations_sequential_dependencies", func(t *testing.T) { runTestWithAllModes(t, "valid_multiple_operations_sequential_dependencies", func(t *testing.T, mode TestExecutionMode) { logger := zap.NewNop() mockInclusionProver := new(mocks.MockInclusionProver) mockInclusionProver.On("CommitRaw", mock.Anything, mock.Anything).Return(make([]byte, 74), nil) mockHG := tests.CreateHypergraphWithInclusionProver(mockInclusionProver) mockHG.On("Commit").Return(map[tries.ShardKey][][]byte{}).Maybe() mockHG.On("TrackChange", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil).Maybe() mockKeyManager := new(mocks.MockKeyManager) mockBulletproofProver := new(mocks.MockBulletproofProver) mockVerEnc := new(mocks.MockVerifiableEncryptor) mockDecaf := new(mocks.MockDecafConstructor) mockCompiler := new(mocks.MockCompiler) // Map test mode to actual engine mode var engineMode engines.ExecutionMode switch mode { case TestGlobalMode: engineMode = engines.GlobalMode case TestApplicationMode: engineMode = engines.ApplicationMode case TestMixedMode: engineMode = engines.ApplicationMode } engine, err := engines.NewComputeExecutionEngine( logger, mockHG, mockKeyManager, mockInclusionProver, mockBulletproofProver, mockVerEnc, mockDecaf, mockCompiler, engineMode, ) require.NoError(t, err) // Set up mocks setupComputeMocks(t, mockHG, mockInclusionProver, mockBulletproofProver, engineMode) setupTokenIntrinsicMocks(t, mockHG) // Generate keys for metadata readKey := make([]byte, 57) writeKey := make([]byte, 57) rand.Read(readKey) rand.Read(writeKey) domain := performDeploymentWithKeys(t, engine, mockHG, mockCompiler, readKey, writeKey, engineMode) // Create operations with sequential dependencies: op1 -> op2 -> op3 ops := []*compute.ExecuteOperation{ { Application: compute.Application{ Address: makeExtrinsicAddress("test_app"), ExecutionContext: compute.ExecutionContextExtrinsic, }, Identifier: []byte("op3"), Dependencies: [][]byte{[]byte("op2")}, }, { Application: compute.Application{ Address: makeExtrinsicAddress("test_app"), ExecutionContext: compute.ExecutionContextExtrinsic, }, Identifier: []byte("op2"), Dependencies: [][]byte{[]byte("op1")}, }, { Application: compute.Application{ Address: makeExtrinsicAddress("test_app"), ExecutionContext: compute.ExecutionContextExtrinsic, }, Identifier: []byte("op1"), Dependencies: [][]byte{}, }, } msg, _ := createTestCodeExecuteMessage(t, mockHG, domain, ops) // Process message state := hgstate.NewHypergraphState(mockHG) msgs, err := engine.ProcessMessage(1, big.NewInt(0), msg.Address, msg.Payload, state) assertCodeExecutionResult(t, mode, msgs, err, false) }) }) // Test 3: Valid multiple operations parallel execution t.Run("valid_multiple_operations_parallel_execution", func(t *testing.T) { runTestWithAllModes(t, "valid_multiple_operations_parallel_execution", func(t *testing.T, mode TestExecutionMode) { logger := zap.NewNop() mockInclusionProver := new(mocks.MockInclusionProver) mockInclusionProver.On("CommitRaw", mock.Anything, mock.Anything).Return(make([]byte, 74), nil) mockHG := tests.CreateHypergraphWithInclusionProver(mockInclusionProver) mockHG.On("Commit").Return(map[tries.ShardKey][][]byte{}).Maybe() mockHG.On("TrackChange", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil).Maybe() mockKeyManager := new(mocks.MockKeyManager) mockBulletproofProver := new(mocks.MockBulletproofProver) mockVerEnc := new(mocks.MockVerifiableEncryptor) mockDecaf := new(mocks.MockDecafConstructor) mockCompiler := new(mocks.MockCompiler) // Map test mode to actual engine mode var engineMode engines.ExecutionMode switch mode { case TestGlobalMode: engineMode = engines.GlobalMode case TestApplicationMode: engineMode = engines.ApplicationMode case TestMixedMode: engineMode = engines.ApplicationMode } engine, err := engines.NewComputeExecutionEngine( logger, mockHG, mockKeyManager, mockInclusionProver, mockBulletproofProver, mockVerEnc, mockDecaf, mockCompiler, engineMode, ) require.NoError(t, err) // Set up mocks setupComputeMocks(t, mockHG, mockInclusionProver, mockBulletproofProver, engineMode) setupTokenIntrinsicMocks(t, mockHG) // Generate keys for metadata readKey := make([]byte, 57) writeKey := make([]byte, 57) rand.Read(readKey) rand.Read(writeKey) // Perform deployment with the same keys domain := performDeploymentWithKeys(t, engine, mockHG, mockCompiler, readKey, writeKey, engineMode) setupComputeMetadata(t, mockHG, domain, readKey, writeKey) // Create operations with no dependencies (can run in parallel) ops := []*compute.ExecuteOperation{ { Application: compute.Application{ Address: makeExtrinsicAddress("app1"), ExecutionContext: compute.ExecutionContextExtrinsic, }, Identifier: []byte("op1"), Dependencies: [][]byte{}, }, { Application: compute.Application{ Address: makeExtrinsicAddress("app2"), ExecutionContext: compute.ExecutionContextExtrinsic, }, Identifier: []byte("op2"), Dependencies: [][]byte{}, }, { Application: compute.Application{ Address: makeExtrinsicAddress("app3"), ExecutionContext: compute.ExecutionContextExtrinsic, }, Identifier: []byte("op3"), Dependencies: [][]byte{}, }, } msg, _ := createTestCodeExecuteMessage(t, mockHG, domain, ops) // Process message state := hgstate.NewHypergraphState(mockHG) msgs, err := engine.ProcessMessage(1, big.NewInt(0), msg.Address, msg.Payload, state) assertCodeExecutionResult(t, mode, msgs, err, false) }) }) // Test 4: Valid diamond dependency pattern t.Run("valid_diamond_dependency_pattern", func(t *testing.T) { runTestWithAllModes(t, "valid_diamond_dependency_pattern", func(t *testing.T, mode TestExecutionMode) { logger := zap.NewNop() mockInclusionProver := new(mocks.MockInclusionProver) mockInclusionProver.On("CommitRaw", mock.Anything, mock.Anything).Return(make([]byte, 74), nil) mockHG := tests.CreateHypergraphWithInclusionProver(mockInclusionProver) mockHG.On("Commit").Return(map[tries.ShardKey][][]byte{}).Maybe() mockHG.On("TrackChange", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil).Maybe() mockKeyManager := new(mocks.MockKeyManager) mockBulletproofProver := new(mocks.MockBulletproofProver) mockVerEnc := new(mocks.MockVerifiableEncryptor) mockDecaf := new(mocks.MockDecafConstructor) mockCompiler := new(mocks.MockCompiler) // Map test mode to actual engine mode var engineMode engines.ExecutionMode switch mode { case TestGlobalMode: engineMode = engines.GlobalMode case TestApplicationMode: engineMode = engines.ApplicationMode case TestMixedMode: engineMode = engines.ApplicationMode } engine, err := engines.NewComputeExecutionEngine( logger, mockHG, mockKeyManager, mockInclusionProver, mockBulletproofProver, mockVerEnc, mockDecaf, mockCompiler, engineMode, ) require.NoError(t, err) // Set up mocks setupComputeMocks(t, mockHG, mockInclusionProver, mockBulletproofProver, engineMode) setupTokenIntrinsicMocks(t, mockHG) // Generate keys for metadata readKey := make([]byte, 57) writeKey := make([]byte, 57) rand.Read(readKey) rand.Read(writeKey) // Perform deployment with the same keys domain := performDeploymentWithKeys(t, engine, mockHG, mockCompiler, readKey, writeKey, engineMode) // Set up compute metadata setupComputeMetadata(t, mockHG, domain, readKey, writeKey) // Create diamond pattern: op1 -> op2, op3 -> op4 ops := []*compute.ExecuteOperation{ { Application: compute.Application{ Address: makeExtrinsicAddress("app"), ExecutionContext: compute.ExecutionContextExtrinsic, }, Identifier: []byte("op1"), Dependencies: [][]byte{}, }, { Application: compute.Application{ Address: makeExtrinsicAddress("app"), ExecutionContext: compute.ExecutionContextExtrinsic, }, Identifier: []byte("op2"), Dependencies: [][]byte{[]byte("op1")}, }, { Application: compute.Application{ Address: makeExtrinsicAddress("app"), ExecutionContext: compute.ExecutionContextExtrinsic, }, Identifier: []byte("op3"), Dependencies: [][]byte{[]byte("op1")}, }, { Application: compute.Application{ Address: makeExtrinsicAddress("app"), ExecutionContext: compute.ExecutionContextExtrinsic, }, Identifier: []byte("op4"), Dependencies: [][]byte{[]byte("op2"), []byte("op3")}, }, } msg, _ := createTestCodeExecuteMessage(t, mockHG, domain, ops) // Process message state := hgstate.NewHypergraphState(mockHG) msgs, err := engine.ProcessMessage(1, big.NewInt(0), msg.Address, msg.Payload, state) assertCodeExecutionResult(t, mode, msgs, err, false) }) }) // Test 5: Invalid circular dependency detection t.Run("invalid_circular_dependency_detection", func(t *testing.T) { runTestWithAllModes(t, "invalid_circular_dependency_detection", func(t *testing.T, mode TestExecutionMode) { logger := zap.NewNop() mockInclusionProver := new(mocks.MockInclusionProver) mockInclusionProver.On("CommitRaw", mock.Anything, mock.Anything).Return(make([]byte, 74), nil) mockHG := tests.CreateHypergraphWithInclusionProver(mockInclusionProver) mockHG.On("Commit").Return(map[tries.ShardKey][][]byte{}).Maybe() mockHG.On("TrackChange", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil).Maybe() mockKeyManager := new(mocks.MockKeyManager) mockBulletproofProver := new(mocks.MockBulletproofProver) mockVerEnc := new(mocks.MockVerifiableEncryptor) mockDecaf := new(mocks.MockDecafConstructor) mockCompiler := new(mocks.MockCompiler) // Map test mode to actual engine mode var engineMode engines.ExecutionMode switch mode { case TestGlobalMode: engineMode = engines.GlobalMode case TestApplicationMode: engineMode = engines.ApplicationMode case TestMixedMode: engineMode = engines.ApplicationMode } engine, err := engines.NewComputeExecutionEngine( logger, mockHG, mockKeyManager, mockInclusionProver, mockBulletproofProver, mockVerEnc, mockDecaf, mockCompiler, engineMode, ) require.NoError(t, err) domain := make([]byte, 32) rand.Read(domain) // Ensure compute metadata is available setupComputeMetadata(t, mockHG, domain, []byte{}, []byte{}) // Set up mocks mockBulletproofProver.On("SimpleVerify", mock.Anything, mock.Anything, mock.Anything).Return(true) // Create circular dependency: op1 -> op2 -> op3 -> op1 ops := []*compute.ExecuteOperation{ { Application: compute.Application{ Address: makeExtrinsicAddress("app"), ExecutionContext: compute.ExecutionContextExtrinsic, }, Identifier: []byte("op1"), Dependencies: [][]byte{[]byte("op3")}, }, { Application: compute.Application{ Address: makeExtrinsicAddress("app"), ExecutionContext: compute.ExecutionContextExtrinsic, }, Identifier: []byte("op2"), Dependencies: [][]byte{[]byte("op1")}, }, { Application: compute.Application{ Address: makeExtrinsicAddress("app"), ExecutionContext: compute.ExecutionContextExtrinsic, }, Identifier: []byte("op3"), Dependencies: [][]byte{[]byte("op2")}, }, } msg, _ := createTestCodeExecuteMessage(t, mockHG, domain, ops) // Process message should fail state := hgstate.NewHypergraphState(mockHG) msgs, err := engine.ProcessMessage(1, big.NewInt(0), msg.Address, msg.Payload, state) assert.Error(t, err) assert.Nil(t, msgs) }) }) // Test 6: Invalid missing dependency reference t.Run("invalid_missing_dependency_reference", func(t *testing.T) { runTestWithAllModes(t, "invalid_missing_dependency_reference", func(t *testing.T, mode TestExecutionMode) { logger := zap.NewNop() mockInclusionProver := new(mocks.MockInclusionProver) mockInclusionProver.On("CommitRaw", mock.Anything, mock.Anything).Return(make([]byte, 74), nil) mockHG := tests.CreateHypergraphWithInclusionProver(mockInclusionProver) mockHG.On("Commit").Return(map[tries.ShardKey][][]byte{}).Maybe() mockHG.On("TrackChange", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil).Maybe() mockKeyManager := new(mocks.MockKeyManager) mockBulletproofProver := new(mocks.MockBulletproofProver) mockVerEnc := new(mocks.MockVerifiableEncryptor) mockDecaf := new(mocks.MockDecafConstructor) mockCompiler := new(mocks.MockCompiler) // Map test mode to actual engine mode var engineMode engines.ExecutionMode switch mode { case TestGlobalMode: engineMode = engines.GlobalMode case TestApplicationMode: engineMode = engines.ApplicationMode case TestMixedMode: engineMode = engines.ApplicationMode } engine, err := engines.NewComputeExecutionEngine( logger, mockHG, mockKeyManager, mockInclusionProver, mockBulletproofProver, mockVerEnc, mockDecaf, mockCompiler, engineMode, ) require.NoError(t, err) // Set up mocks mockBulletproofProver.On("SimpleVerify", mock.Anything, mock.Anything, mock.Anything).Return(true) // Create operations with missing dependency reference ops := []*compute.ExecuteOperation{ { Application: compute.Application{ Address: makeExtrinsicAddress("app"), ExecutionContext: compute.ExecutionContextExtrinsic, }, Identifier: []byte("op1"), Dependencies: [][]byte{[]byte("missing_op")}, // Reference to non-existent operation }, } domain := make([]byte, 32) rand.Read(domain) // Ensure compute metadata is available setupComputeMetadata(t, mockHG, domain, []byte{}, []byte{}) msg, _ := createTestCodeExecuteMessage(t, mockHG, domain, ops) // Process message should fail because compute intrinsic hasn't been deployed state := hgstate.NewHypergraphState(mockHG) msgs, err := engine.ProcessMessage(1, big.NewInt(0), msg.Address, msg.Payload, state) assert.Error(t, err) assert.Nil(t, msgs) }) }) // Test 7: Invalid payment proof rejected t.Run("invalid_payment_proof_rejected", func(t *testing.T) { runTestWithAllModes(t, "invalid_payment_proof_rejected", func(t *testing.T, mode TestExecutionMode) { logger := zap.NewNop() mockInclusionProver := new(mocks.MockInclusionProver) mockInclusionProver.On("CommitRaw", mock.Anything, mock.Anything).Return(make([]byte, 74), nil) mockHG := tests.CreateHypergraphWithInclusionProver(mockInclusionProver) mockHG.On("Commit").Return(map[tries.ShardKey][][]byte{}).Maybe() mockHG.On("TrackChange", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil).Maybe() mockKeyManager := new(mocks.MockKeyManager) mockBulletproofProver := new(mocks.MockBulletproofProver) mockVerEnc := new(mocks.MockVerifiableEncryptor) mockDecaf := new(mocks.MockDecafConstructor) mockCompiler := new(mocks.MockCompiler) // Map test mode to actual engine mode var engineMode engines.ExecutionMode switch mode { case TestGlobalMode: engineMode = engines.GlobalMode case TestApplicationMode: engineMode = engines.ApplicationMode case TestMixedMode: engineMode = engines.ApplicationMode } engine, err := engines.NewComputeExecutionEngine( logger, mockHG, mockKeyManager, mockInclusionProver, mockBulletproofProver, mockVerEnc, mockDecaf, mockCompiler, engineMode, ) require.NoError(t, err) // Set up mocks - payment validation fails mockBulletproofProver.On("SimpleVerify", mock.Anything, mock.Anything, mock.Anything).Return(false) // Additional mocks for payment transaction verification mockMultiproof := &mocks.MockMultiproof{} mockInclusionProver.On("NewMultiproof").Return(mockMultiproof, nil).Maybe() mockMultiproof.On("Size").Return(0).Maybe() mockMultiproof.On("ComputeSize").Return(0).Maybe() mockMultiproof.On("Bind", mock.Anything).Return(nil).Maybe() mockMultiproof.On("Prove", mock.Anything).Return(nil).Maybe() mockMultiproof.On("Reset").Return(nil).Maybe() mockMultiproof.On("Commit", mock.Anything).Return([]byte{}, nil).Maybe() mockMultiproof.On("Verify", mock.Anything, mock.Anything).Return(true, nil).Maybe() mockMultiproof.On("FromBytes", mock.Anything).Return(nil).Maybe() mockMultiproof.On("ProveMultiple", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return([]byte{}, nil).Maybe() // Setup GetProver mock for deployment mockHG.On("GetProver").Return(mockInclusionProver) mockInclusionProver.On("CommitRaw", mock.Anything, mock.Anything).Return(make([]byte, 74), nil) // Setup transaction mocks for deployment mockTxn := &mockTransaction{} mockHG.On("NewTransaction", false).Return(mockTxn, nil) mockHG.On("AddVertex", mock.Anything, mock.Anything).Return(nil) mockHG.On("SetVertexData", mock.Anything, mock.Anything, mock.Anything).Return(nil) mockHG.On("Commit").Return(map[tries.ShardKey][][]byte{}).Maybe() // Generate keys and set up metadata before deployment readKey := make([]byte, 57) writeKey := make([]byte, 57) rand.Read(readKey) rand.Read(writeKey) // Add catch-all for any other GetVertex calls during deployment mockHG.On("GetVertex", mock.Anything).Return(nil, fmt.Errorf("not found")).Maybe() // Perform deployment domain := performDeploymentWithKeys(t, engine, mockHG, mockCompiler, readKey, writeKey, engineMode) ops := []*compute.ExecuteOperation{ { Application: compute.Application{ Address: makeExtrinsicAddress("app"), ExecutionContext: compute.ExecutionContextExtrinsic, }, Identifier: []byte("op1"), Dependencies: [][]byte{}, }, } msg, _ := createTestCodeExecuteMessage(t, mockHG, domain, ops) // Process message should fail state := hgstate.NewHypergraphState(mockHG) msgs, err := engine.ProcessMessage(1, big.NewInt(0), msg.Address, msg.Payload, state) assert.Error(t, err) // In global mode, the error is different because non-deploy messages are not allowed if engineMode == engines.GlobalMode { assert.Contains(t, err.Error(), "non-deploy messages not allowed in global mode") } else { // Payment validation fails with "invalid signature" error assert.Contains(t, err.Error(), "invalid signature") } assert.Nil(t, msgs) }) }) // Test 8: Invalid payment insufficient amount t.Run("invalid_payment_insufficient_amount", func(t *testing.T) { runTestWithAllModes(t, "invalid_payment_insufficient_amount", func(t *testing.T, mode TestExecutionMode) { logger := zap.NewNop() mockInclusionProver := new(mocks.MockInclusionProver) mockInclusionProver.On("CommitRaw", mock.Anything, mock.Anything).Return(make([]byte, 74), nil) mockHG := tests.CreateHypergraphWithInclusionProver(mockInclusionProver) mockHG.On("Commit").Return(map[tries.ShardKey][][]byte{}).Maybe() mockHG.On("TrackChange", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil).Maybe() mockKeyManager := new(mocks.MockKeyManager) mockBulletproofProver := new(mocks.MockBulletproofProver) mockVerEnc := new(mocks.MockVerifiableEncryptor) mockDecaf := new(mocks.MockDecafConstructor) mockCompiler := new(mocks.MockCompiler) // Map test mode to actual engine mode var engineMode engines.ExecutionMode switch mode { case TestGlobalMode: engineMode = engines.GlobalMode case TestApplicationMode: engineMode = engines.ApplicationMode case TestMixedMode: engineMode = engines.ApplicationMode } engine, err := engines.NewComputeExecutionEngine( logger, mockHG, mockKeyManager, mockInclusionProver, mockBulletproofProver, mockVerEnc, mockDecaf, mockCompiler, engineMode, ) require.NoError(t, err) // Set up mocks setupComputeMocks(t, mockHG, mockInclusionProver, mockBulletproofProver, engineMode) setupTokenIntrinsicMocks(t, mockHG) // Generate keys for metadata readKey := make([]byte, 57) writeKey := make([]byte, 57) rand.Read(readKey) rand.Read(writeKey) // Perform deployment with the same keys domain := performDeploymentWithKeys(t, engine, mockHG, mockCompiler, readKey, writeKey, engineMode) // Set up compute metadata setupComputeMetadata(t, mockHG, domain, readKey, writeKey) // Create mock agreements - the New() method creates with random keys mockDecafConstructor := &mocks.MockDecafConstructor{} vk, _ := mockDecafConstructor.New() sk, _ := mockDecafConstructor.New() out1, err := token.NewPendingTransactionOutput(big.NewInt(9), vk.Public(), sk.Public(), vk.Public(), sk.Public(), 0) if err != nil { t.Fatal(err) } mockKeyManager.On("GetAgreementKey", "q-view-key").Return(&mocks.MockDecafAgreement{}, nil) mockKeyManager.On("GetAgreementKey", "q-spend-key").Return(&mocks.MockDecafAgreement{}, nil) address1 := [64]byte{} copy(address1[:32], token.QUIL_TOKEN_ADDRESS) rand.Read(address1[32:]) address2 := [64]byte{} copy(address2[:32], token.QUIL_TOKEN_ADDRESS) rand.Read(address2[32:]) tree1 := &tries.VectorCommitmentTree{} otk1 := make([]byte, 56) comm1 := make([]byte, 56) mask1 := make([]byte, 56) verifkey1 := make([]byte, 56) rand.Read(otk1) rand.Read(comm1) rand.Read(mask1) rand.Read(verifkey1) maskedCoinBalanceBytes1 := make([]byte, 56) rand.Read(maskedCoinBalanceBytes1) tree1.Insert([]byte{0}, binary.BigEndian.AppendUint64(nil, token.FRAME_2_1_EXTENDED_ENROLL_CONFIRM_END+1), nil, big.NewInt(8)) tree1.Insert([]byte{1 << 2}, comm1, nil, big.NewInt(56)) tree1.Insert([]byte{2 << 2}, otk1, nil, big.NewInt(56)) tree1.Insert([]byte{3 << 2}, verifkey1, nil, big.NewInt(56)) tree1.Insert([]byte{4 << 2}, maskedCoinBalanceBytes1, nil, big.NewInt(56)) tree1.Insert([]byte{5 << 2}, mask1, nil, big.NewInt(56)) typeAddr, _ := hex.DecodeString("096de9a09f693f92cfa9cf3349bab2b3baee09f3e4f9c596514ecb3e8b0dff8f") tree1.Insert(bytes.Repeat([]byte{0xff}, 32), typeAddr, nil, big.NewInt(32)) mockHG.On("GetVertex", [64]byte(slices.Concat(token.QUIL_TOKEN_ADDRESS, address1[32:]))).Return(&mockVertex{}, nil) mockHG.On("GetVertexData", [64]byte(slices.Concat(token.QUIL_TOKEN_ADDRESS, address1[32:]))).Return(tree1, nil) // simulate input as commitment to total input1, _ := token.NewPendingTransactionInput(address1[:]) tokenconfig := &token.TokenIntrinsicConfiguration{ Behavior: token.Mintable | token.Burnable | token.Divisible | token.Acceptable | token.Expirable | token.Tenderable, MintStrategy: &token.TokenMintStrategy{ MintBehavior: token.MintWithProof, ProofBasis: token.ProofOfMeaningfulWork, }, Units: big.NewInt(8000000000), Name: "QUIL", Symbol: "QUIL", } rdfSchema, _ := prepareRDFSchemaFromConfig(token.QUIL_TOKEN_ADDRESS, tokenconfig) parser := &schema.TurtleRDFParser{} rdfMultiprover := schema.NewRDFMultiprover(parser, mockInclusionProver) mockPaymentTx := token.NewPendingTransaction( [32]byte(token.QUIL_TOKEN_ADDRESS), []*token.PendingTransactionInput{input1}, []*token.PendingTransactionOutput{out1}, []*big.Int{}, tokenconfig, mockHG, mockBulletproofProver, mockInclusionProver, mockVerEnc, mockDecaf, keys.ToKeyRing(mockKeyManager, false), rdfSchema, rdfMultiprover, ) // Additional mocks for transaction creation // RangeProof needs to return a properly sized byte array rangeProof := make([]byte, 112) // Typical range proof size mockBulletproofProver.On("RangeProof", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(rangeProof, nil).Maybe() // GenerateRangeProofFromBig needs to return a RangeProofResult struct rangeProofResult := crypto.RangeProofResult{ Proof: rangeProof, Commitment: make([]byte, 56), Blinding: make([]byte, 56), } mockBulletproofProver.On("GenerateRangeProofFromBig", mock.Anything, mock.Anything, mock.Anything).Return(rangeProofResult, nil).Maybe() mockBulletproofProver.On("SignHidden", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return([]byte{}).Maybe() // Add ProveMultiple mock directly to the inclusion prover for this test mockMultiproof := new(mocks.MockMultiproof) mockMultiproof.On("FromBytes", mock.Anything).Return(nil) mockMultiproof.On("ToBytes").Return([]byte{}, nil) mockInclusionProver.On("ProveMultiple", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(mockMultiproof).Maybe() // Add CreateTraversalProof mock for the hypergraph mockTraversalProofMultiproof := new(mocks.MockMultiproof) // Create a properly sized multiproof byte array (74 bytes multicommitment + some proof data) multiproofBytes := make([]byte, 148) // 74 for multicommitment + 74 for proof rand.Read(multiproofBytes) mockTraversalProofMultiproof.On("ToBytes").Return(multiproofBytes, nil) mockTraversalProof := &tries.TraversalProof{ Multiproof: mockTraversalProofMultiproof, SubProofs: []tries.TraversalSubProof{ { Commits: [][]byte{make([]byte, 74)}, // At least one commit Ys: [][]byte{make([]byte, 64)}, // Matching Ys Paths: [][]uint64{{0}}, // At least one path }, }, } mockHG.On("CreateTraversalProof", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(mockTraversalProof, nil).Maybe() // Call Prove to populate the transaction fields err = mockPaymentTx.Prove(0) require.NoError(t, err) paymentTxBytes, err := mockPaymentTx.ToProtobuf().ToCanonicalBytes() require.NoError(t, err) // Create operations ops := []*compute.ExecuteOperation{ { Application: compute.Application{ Address: makeExtrinsicAddress("app"), ExecutionContext: compute.ExecutionContextExtrinsic, }, Identifier: []byte("op1"), Dependencies: [][]byte{}, }, } var rendezvous [32]byte rand.Read(rendezvous[:]) // Create CodeExecute with insufficient payment ce := compute.NewCodeExecute( [32]byte(domain), paymentTxBytes, []byte("mock_secret_key"), rendezvous, ops, mockHG, mockBulletproofProver, mockInclusionProver, mockVerEnc, mockDecaf, mockKeyManager, ) // Set up proof of payment ce.ProofOfPayment[0] = paymentTxBytes ce.ProofOfPayment[1] = []byte("mock_signature") // Wrap in MessageRequest and serialize executeReq := &protobufs.MessageRequest{ Request: &protobufs.MessageRequest_CodeExecute{ CodeExecute: ce.ToProtobuf(), }, } outFees := []*big.Int{big.NewInt(10000000)} total := big.NewInt(1) outFees = append(outFees, total) payment, err := tests.CreateValidQUILPendingTransactionPayload( mockHG, 1, [][]byte{make([]byte, 56)}, [][]byte{make([]byte, 56)}, [][]byte{make([]byte, 56)}, [][]byte{make([]byte, 56)}, []*big.Int{big.NewInt(10000001)}, []*big.Int{big.NewInt(0)}, outFees, 0, ) if err != nil { panic(err) } bundle := &protobufs.MessageBundle{ Requests: []*protobufs.MessageRequest{ payment, executeReq, }, } bundleBytes, err := bundle.ToCanonicalBytes() require.NoError(t, err) // Create message hash := sha3.Sum256(bundleBytes) require.NoError(t, err) msg := &protobufs.Message{ Address: domain, Hash: hash[:], Payload: bundleBytes, } // Process message should fail state := hgstate.NewHypergraphState(mockHG) msgs, err := engine.ProcessMessage(1, big.NewInt(1000), msg.Address, msg.Payload, state) assert.Error(t, err) // Don't let the error check panic if err != nil { // In GlobalMode, it fails with global mode restriction // In other modes, it should fail with insufficient payment if engineMode == engines.GlobalMode { assert.Contains(t, err.Error(), "non-deploy messages not allowed in global mode") } else { assert.True( t, strings.Contains(err.Error(), "insufficient"), "Expected error about insufficient payment, got: %v", err, ) } } assert.Nil(t, msgs) }) }) // Test 9 removed, retaining number for future use // Test 10: Invalid signature on rendezvous t.Run("invalid_signature_on_rendezvous", func(t *testing.T) { runTestWithAllModes(t, "invalid_signature_on_rendezvous", func(t *testing.T, mode TestExecutionMode) { // Create test dependencies logger := zap.NewNop() mockInclusionProver := new(mocks.MockInclusionProver) mockInclusionProver.On("CommitRaw", mock.Anything, mock.Anything).Return(make([]byte, 74), nil) mockHG := tests.CreateHypergraphWithInclusionProver(mockInclusionProver) mockHG.On("Commit").Return(map[tries.ShardKey][][]byte{}).Maybe() mockHG.On("TrackChange", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil).Maybe() mockKeyManager := new(mocks.MockKeyManager) mockBulletproofProver := new(mocks.MockBulletproofProver) mockVerEnc := new(mocks.MockVerifiableEncryptor) mockDecaf := new(mocks.MockDecafConstructor) mockCompiler := new(mocks.MockCompiler) // Map test mode to actual engine mode var engineMode engines.ExecutionMode switch mode { case TestGlobalMode: engineMode = engines.GlobalMode case TestApplicationMode: engineMode = engines.ApplicationMode case TestMixedMode: engineMode = engines.ApplicationMode } engine, err := engines.NewComputeExecutionEngine( logger, mockHG, mockKeyManager, mockInclusionProver, mockBulletproofProver, mockVerEnc, mockDecaf, mockCompiler, engineMode, ) require.NoError(t, err) // Set up mocks - SimpleVerify returns false for invalid signature mockBulletproofProver.On("SimpleVerify", mock.Anything, mock.Anything, mock.Anything).Return(false) // Set up compute mocks to handle the message processing setupComputeMocks(t, mockHG, mockInclusionProver, mockBulletproofProver, engineMode) domain := make([]byte, 32) rand.Read(domain) // Set up compute metadata metadataAddress := slices.Concat(domain, bytes.Repeat([]byte{0xff}, 32)) metadataTree := &tries.VectorCommitmentTree{} // Set up the mock expectations for metadata mockHG.On("GetVertex", [64]byte(metadataAddress)).Return(&mockVertex{}, nil) mockHG.On("GetVertexData", [64]byte(metadataAddress)).Return(metadataTree, nil) ops := []*compute.ExecuteOperation{ { Application: compute.Application{ Address: makeExtrinsicAddress("app"), ExecutionContext: compute.ExecutionContextExtrinsic, }, Identifier: []byte("op1"), Dependencies: [][]byte{}, }, } msg, ce := createTestCodeExecuteMessage(t, mockHG, domain, ops) // Set invalid signature ce.ProofOfPayment[1] = []byte("invalid_signature") // Process message should fail state := hgstate.NewHypergraphState(mockHG) msgs, err := engine.ProcessMessage(1, big.NewInt(0), msg.Address, msg.Payload, state) assert.Error(t, err) assert.Nil(t, msgs) }) }) // Test 11: Intrinsic token operation execution t.Run("intrinsic_token_operation_execution", func(t *testing.T) { runTestWithAllModes(t, "intrinsic_token_operation_execution", func(t *testing.T, mode TestExecutionMode) { t.Skip("When multiphasic locking is added, support this") }) }) // Test 12: Intrinsic hardcoded app execution t.Run("intrinsic_hardcoded_app_execution", func(t *testing.T) { runTestWithAllModes(t, "intrinsic_hardcoded_app_execution", func(t *testing.T, mode TestExecutionMode) { // Create test dependencies logger := zap.NewNop() mockInclusionProver := new(mocks.MockInclusionProver) mockInclusionProver.On("CommitRaw", mock.Anything, mock.Anything).Return(make([]byte, 74), nil) mockHG := tests.CreateHypergraphWithInclusionProver(mockInclusionProver) mockHG.On("Commit").Return(map[tries.ShardKey][][]byte{}).Maybe() mockHG.On("TrackChange", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil).Maybe() mockKeyManager := new(mocks.MockKeyManager) mockBulletproofProver := new(mocks.MockBulletproofProver) mockVerEnc := new(mocks.MockVerifiableEncryptor) mockDecaf := new(mocks.MockDecafConstructor) mockCompiler := new(mocks.MockCompiler) // Map test mode to actual engine mode var engineMode engines.ExecutionMode switch mode { case TestGlobalMode: engineMode = engines.GlobalMode case TestApplicationMode: engineMode = engines.ApplicationMode case TestMixedMode: engineMode = engines.ApplicationMode } engine, err := engines.NewComputeExecutionEngine( logger, mockHG, mockKeyManager, mockInclusionProver, mockBulletproofProver, mockVerEnc, mockDecaf, mockCompiler, engineMode, ) require.NoError(t, err) // Set up mocks setupComputeMocks(t, mockHG, mockInclusionProver, mockBulletproofProver, engineMode) setupTokenIntrinsicMocks(t, mockHG) // Generate keys for metadata readKey := make([]byte, 57) writeKey := make([]byte, 57) rand.Read(readKey) rand.Read(writeKey) // Perform deployment with the same keys domain := performDeploymentWithKeys(t, engine, mockHG, mockCompiler, readKey, writeKey, engineMode) // Set up compute metadata setupComputeMetadata(t, mockHG, domain, readKey, writeKey) ops := []*compute.ExecuteOperation{ { Application: compute.Application{ Address: []byte{0x00, 0x01, 0x07, 0x01}, ExecutionContext: compute.ExecutionContextIntrinsic, }, Identifier: []byte("intrinsic_op"), Dependencies: [][]byte{}, }, } msg, _ := createTestCodeExecuteMessage(t, mockHG, domain, ops) // Process message state := hgstate.NewHypergraphState(mockHG) msgs, err := engine.ProcessMessage(1, big.NewInt(0), msg.Address, msg.Payload, state) assertCodeExecutionResult(t, mode, msgs, err, false) }) }) // Test 13: Hypergraph context state mutation t.Run("hypergraph_context_state_mutation", func(t *testing.T) { runTestWithAllModes(t, "hypergraph_context_state_mutation", func(t *testing.T, mode TestExecutionMode) { // Create test dependencies logger := zap.NewNop() mockInclusionProver := new(mocks.MockInclusionProver) mockInclusionProver.On("CommitRaw", mock.Anything, mock.Anything).Return(make([]byte, 74), nil) mockHG := tests.CreateHypergraphWithInclusionProver(mockInclusionProver) mockHG.On("Commit").Return(map[tries.ShardKey][][]byte{}).Maybe() mockHG.On("TrackChange", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil).Maybe() mockKeyManager := new(mocks.MockKeyManager) mockBulletproofProver := new(mocks.MockBulletproofProver) mockVerEnc := new(mocks.MockVerifiableEncryptor) mockDecaf := new(mocks.MockDecafConstructor) mockCompiler := new(mocks.MockCompiler) // Map test mode to actual engine mode var engineMode engines.ExecutionMode switch mode { case TestGlobalMode: engineMode = engines.GlobalMode case TestApplicationMode: engineMode = engines.ApplicationMode case TestMixedMode: engineMode = engines.ApplicationMode } engine, err := engines.NewComputeExecutionEngine( logger, mockHG, mockKeyManager, mockInclusionProver, mockBulletproofProver, mockVerEnc, mockDecaf, mockCompiler, engineMode, ) require.NoError(t, err) // Set up mocks setupComputeMocks(t, mockHG, mockInclusionProver, mockBulletproofProver, engineMode) setupTokenIntrinsicMocks(t, mockHG) // Generate keys for metadata readKey := make([]byte, 57) writeKey := make([]byte, 57) rand.Read(readKey) rand.Read(writeKey) // Perform deployment with the same keys domain := performDeploymentWithKeys(t, engine, mockHG, mockCompiler, readKey, writeKey, engineMode) // Set up compute metadata setupComputeMetadata(t, mockHG, domain, readKey, writeKey) ops := []*compute.ExecuteOperation{ { Application: compute.Application{ Address: hgstate.VertexAddsDiscriminator, ExecutionContext: compute.ExecutionContextHypergraph, }, Identifier: []byte("add_vertex"), Dependencies: [][]byte{}, }, } msg, _ := createTestCodeExecuteMessage(t, mockHG, domain, ops) // Process message state := hgstate.NewHypergraphState(mockHG) msgs, err := engine.ProcessMessage(1, big.NewInt(0), msg.Address, msg.Payload, state) assertCodeExecutionResult(t, mode, msgs, err, false) }) }) // Test 14: Extrinsic deployed code execution t.Run("extrinsic_deployed_code_execution", func(t *testing.T) { runTestWithAllModes(t, "extrinsic_deployed_code_execution", func(t *testing.T, mode TestExecutionMode) { // Create test dependencies logger := zap.NewNop() mockInclusionProver := new(mocks.MockInclusionProver) mockInclusionProver.On("CommitRaw", mock.Anything, mock.Anything).Return(make([]byte, 74), nil) mockHG := tests.CreateHypergraphWithInclusionProver(mockInclusionProver) mockHG.On("Commit").Return(map[tries.ShardKey][][]byte{}).Maybe() mockHG.On("TrackChange", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil).Maybe() mockHG.On("Commit").Return(map[tries.ShardKey][][]byte{}).Maybe() mockKeyManager := new(mocks.MockKeyManager) mockBulletproofProver := new(mocks.MockBulletproofProver) mockVerEnc := new(mocks.MockVerifiableEncryptor) mockDecaf := new(mocks.MockDecafConstructor) mockCompiler := new(mocks.MockCompiler) // Map test mode to actual engine mode var engineMode engines.ExecutionMode switch mode { case TestGlobalMode: engineMode = engines.GlobalMode case TestApplicationMode: engineMode = engines.ApplicationMode case TestMixedMode: engineMode = engines.ApplicationMode } engine, err := engines.NewComputeExecutionEngine( logger, mockHG, mockKeyManager, mockInclusionProver, mockBulletproofProver, mockVerEnc, mockDecaf, mockCompiler, engineMode, ) require.NoError(t, err) // Set up mocks setupComputeMocks(t, mockHG, mockInclusionProver, mockBulletproofProver, engineMode) setupTokenIntrinsicMocks(t, mockHG) // Perform deployment domain := performDeployment(t, engine, mockHG, mockCompiler, engineMode) // Set up mock for deployed code retrieval // The test is using "deployed_code_addr" as the code address code := &tries.VectorCommitmentTree{} code.Insert([]byte{0}, []byte("circuit"), nil, big.NewInt(7)) mockHG.On("GetVertexData", mock.MatchedBy(func(addr [64]byte) bool { // Check if the address ends with "deployed_code_addr" codeAddrPart := string(bytes.TrimRight(addr[32:], "\x00")) return codeAddrPart == "deployed_code_addr" })).Return(code, nil) ops := []*compute.ExecuteOperation{ { Application: compute.Application{ Address: makeExtrinsicAddress("deployed_code_addr"), ExecutionContext: compute.ExecutionContextExtrinsic, }, Identifier: []byte("execute_circuit"), Dependencies: [][]byte{}, }, } msg, _ := createTestCodeExecuteMessage(t, mockHG, domain, ops) // Process message state := hgstate.NewHypergraphState(mockHG) msgs, err := engine.ProcessMessage(1, big.NewInt(0), msg.Address, msg.Payload, state) assertCodeExecutionResult(t, mode, msgs, err, false) }) }) // Test 15: Conflict detection same address write t.Run("conflict_detection_same_address_write", func(t *testing.T) { runTestWithAllModes(t, "conflict_detection_same_address_write", func(t *testing.T, mode TestExecutionMode) { logger := zap.NewNop() mockInclusionProver := new(mocks.MockInclusionProver) mockInclusionProver.On("CommitRaw", mock.Anything, mock.Anything).Return(make([]byte, 74), nil) mockHG := tests.CreateHypergraphWithInclusionProver(mockInclusionProver) mockHG.On("Commit").Return(map[tries.ShardKey][][]byte{}).Maybe() mockHG.On("TrackChange", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil).Maybe() mockKeyManager := new(mocks.MockKeyManager) mockBulletproofProver := new(mocks.MockBulletproofProver) mockVerEnc := new(mocks.MockVerifiableEncryptor) mockDecaf := new(mocks.MockDecafConstructor) mockCompiler := new(mocks.MockCompiler) // Map test mode to actual engine mode var engineMode engines.ExecutionMode switch mode { case TestGlobalMode: engineMode = engines.GlobalMode case TestApplicationMode: engineMode = engines.ApplicationMode case TestMixedMode: engineMode = engines.ApplicationMode } engine, err := engines.NewComputeExecutionEngine( logger, mockHG, mockKeyManager, mockInclusionProver, mockBulletproofProver, mockVerEnc, mockDecaf, mockCompiler, engineMode, ) require.NoError(t, err) // Set up mocks setupComputeMocks(t, mockHG, mockInclusionProver, mockBulletproofProver, engineMode) setupTokenIntrinsicMocks(t, mockHG) // Generate keys for metadata readKey := make([]byte, 57) writeKey := make([]byte, 57) rand.Read(readKey) rand.Read(writeKey) // Perform deployment with the same keys domain := performDeploymentWithKeys(t, engine, mockHG, mockCompiler, readKey, writeKey, engineMode) // Set up compute metadata setupComputeMetadata(t, mockHG, domain, readKey, writeKey) // Create operations that write to the same address (should be placed in different stages) ops := []*compute.ExecuteOperation{ { Application: compute.Application{ Address: makeExtrinsicAddress("same_app"), ExecutionContext: compute.ExecutionContextExtrinsic, }, Identifier: []byte("op1"), Dependencies: [][]byte{}, }, { Application: compute.Application{ Address: makeExtrinsicAddress("same_app"), // Same address as op1 ExecutionContext: compute.ExecutionContextExtrinsic, }, Identifier: []byte("op2"), Dependencies: [][]byte{}, }, } msg, _ := createTestCodeExecuteMessage(t, mockHG, domain, ops) // Process message state := hgstate.NewHypergraphState(mockHG) msgs, err := engine.ProcessMessage(1, big.NewInt(0), msg.Address, msg.Payload, state) assertCodeExecutionResult(t, mode, msgs, err, false) }) }) // Test 16: Conflict detection read write dependency t.Run("conflict_detection_read_write_dependency", func(t *testing.T) { runTestWithAllModes(t, "conflict_detection_read_write_dependency", func(t *testing.T, mode TestExecutionMode) { logger := zap.NewNop() mockInclusionProver := new(mocks.MockInclusionProver) mockInclusionProver.On("CommitRaw", mock.Anything, mock.Anything).Return(make([]byte, 74), nil) mockHG := tests.CreateHypergraphWithInclusionProver(mockInclusionProver) mockHG.On("Commit").Return(map[tries.ShardKey][][]byte{}).Maybe() mockHG.On("TrackChange", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil).Maybe() mockKeyManager := new(mocks.MockKeyManager) mockBulletproofProver := new(mocks.MockBulletproofProver) mockVerEnc := new(mocks.MockVerifiableEncryptor) mockDecaf := new(mocks.MockDecafConstructor) mockCompiler := new(mocks.MockCompiler) // Map test mode to actual engine mode var engineMode engines.ExecutionMode switch mode { case TestGlobalMode: engineMode = engines.GlobalMode case TestApplicationMode: engineMode = engines.ApplicationMode case TestMixedMode: engineMode = engines.ApplicationMode } engine, err := engines.NewComputeExecutionEngine( logger, mockHG, mockKeyManager, mockInclusionProver, mockBulletproofProver, mockVerEnc, mockDecaf, mockCompiler, engineMode, ) require.NoError(t, err) // Set up mocks setupComputeMocks(t, mockHG, mockInclusionProver, mockBulletproofProver, engineMode) setupTokenIntrinsicMocks(t, mockHG) // Generate keys for metadata readKey := make([]byte, 57) writeKey := make([]byte, 57) rand.Read(readKey) rand.Read(writeKey) // Perform deployment with the same keys domain := performDeploymentWithKeys(t, engine, mockHG, mockCompiler, readKey, writeKey, engineMode) // Set up compute metadata setupComputeMetadata(t, mockHG, domain, readKey, writeKey) // Create operations with read-write dependency // op1 reads from address A, op2 writes to address A ops := []*compute.ExecuteOperation{ { Application: compute.Application{ Address: makeExtrinsicAddress("reader_app"), ExecutionContext: compute.ExecutionContextExtrinsic, }, Identifier: []byte("op1_read"), Dependencies: [][]byte{}, }, { Application: compute.Application{ Address: makeExtrinsicAddress("writer_app"), ExecutionContext: compute.ExecutionContextExtrinsic, }, Identifier: []byte("op2_write"), Dependencies: [][]byte{}, }, } msg, _ := createTestCodeExecuteMessage(t, mockHG, domain, ops) // Process message state := hgstate.NewHypergraphState(mockHG) msgs, err := engine.ProcessMessage(1, big.NewInt(0), msg.Address, msg.Payload, state) assertCodeExecutionResult(t, mode, msgs, err, false) }) }) // Test 17: Conflict detection write write collision t.Run("conflict_detection_write_write_collision", func(t *testing.T) { runTestWithAllModes(t, "conflict_detection_write_write_collision", func(t *testing.T, mode TestExecutionMode) { logger := zap.NewNop() mockInclusionProver := new(mocks.MockInclusionProver) mockInclusionProver.On("CommitRaw", mock.Anything, mock.Anything).Return(make([]byte, 74), nil) mockHG := tests.CreateHypergraphWithInclusionProver(mockInclusionProver) mockHG.On("Commit").Return(map[tries.ShardKey][][]byte{}).Maybe() mockHG.On("TrackChange", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil).Maybe() mockKeyManager := new(mocks.MockKeyManager) mockBulletproofProver := new(mocks.MockBulletproofProver) mockVerEnc := new(mocks.MockVerifiableEncryptor) mockDecaf := new(mocks.MockDecafConstructor) mockCompiler := new(mocks.MockCompiler) // Map test mode to actual engine mode var engineMode engines.ExecutionMode switch mode { case TestGlobalMode: engineMode = engines.GlobalMode case TestApplicationMode: engineMode = engines.ApplicationMode case TestMixedMode: engineMode = engines.ApplicationMode } engine, err := engines.NewComputeExecutionEngine( logger, mockHG, mockKeyManager, mockInclusionProver, mockBulletproofProver, mockVerEnc, mockDecaf, mockCompiler, engineMode, ) require.NoError(t, err) // Set up mocks setupComputeMocks(t, mockHG, mockInclusionProver, mockBulletproofProver, engineMode) setupTokenIntrinsicMocks(t, mockHG) // Generate keys for metadata readKey := make([]byte, 57) writeKey := make([]byte, 57) rand.Read(readKey) rand.Read(writeKey) // Perform deployment with the same keys domain := performDeploymentWithKeys(t, engine, mockHG, mockCompiler, readKey, writeKey, engineMode) // Set up compute metadata setupComputeMetadata(t, mockHG, domain, readKey, writeKey) // Set up mocks for deployed code retrieval // The test is using "state_writer1" and "state_writer2" as code addresses code := &tries.VectorCommitmentTree{} code.Insert([]byte{0}, []byte("circuit"), nil, big.NewInt(7)) mockHG.On("GetVertexData", mock.MatchedBy(func(addr [64]byte) bool { // Check if the address ends with "state_writer1" or "state_writer2" codeAddrPart := string(bytes.TrimRight(addr[32:], "\x00")) return codeAddrPart == "state_writer1" || codeAddrPart == "state_writer2" })).Return(code, nil) // Create operations that both write to same state ops := []*compute.ExecuteOperation{ { Application: compute.Application{ Address: makeExtrinsicAddress("state_writer1"), ExecutionContext: compute.ExecutionContextExtrinsic, }, Identifier: []byte("writer1"), Dependencies: [][]byte{}, }, { Application: compute.Application{ Address: makeExtrinsicAddress("state_writer2"), ExecutionContext: compute.ExecutionContextExtrinsic, }, Identifier: []byte("writer2"), Dependencies: [][]byte{}, }, } msg, _ := createTestCodeExecuteMessage(t, mockHG, domain, ops) // Process message state := hgstate.NewHypergraphState(mockHG) msgs, err := engine.ProcessMessage(1, big.NewInt(0), msg.Address, msg.Payload, state) assertCodeExecutionResult(t, mode, msgs, err, false) }) }) // Test 18: Conflict free parallel stage grouping t.Run("conflict_free_parallel_stage_grouping", func(t *testing.T) { runTestWithAllModes(t, "conflict_free_parallel_stage_grouping", func(t *testing.T, mode TestExecutionMode) { logger := zap.NewNop() mockInclusionProver := new(mocks.MockInclusionProver) mockInclusionProver.On("CommitRaw", mock.Anything, mock.Anything).Return(make([]byte, 74), nil) mockHG := tests.CreateHypergraphWithInclusionProver(mockInclusionProver) mockHG.On("Commit").Return(map[tries.ShardKey][][]byte{}).Maybe() mockHG.On("TrackChange", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil).Maybe() mockKeyManager := new(mocks.MockKeyManager) mockBulletproofProver := new(mocks.MockBulletproofProver) mockVerEnc := new(mocks.MockVerifiableEncryptor) mockDecaf := new(mocks.MockDecafConstructor) mockCompiler := new(mocks.MockCompiler) // Map test mode to actual engine mode var engineMode engines.ExecutionMode switch mode { case TestGlobalMode: engineMode = engines.GlobalMode case TestApplicationMode: engineMode = engines.ApplicationMode case TestMixedMode: engineMode = engines.ApplicationMode } engine, err := engines.NewComputeExecutionEngine( logger, mockHG, mockKeyManager, mockInclusionProver, mockBulletproofProver, mockVerEnc, mockDecaf, mockCompiler, engineMode, ) require.NoError(t, err) // Set up mocks setupComputeMocks(t, mockHG, mockInclusionProver, mockBulletproofProver, engineMode) setupTokenIntrinsicMocks(t, mockHG) // Generate keys for metadata readKey := make([]byte, 57) writeKey := make([]byte, 57) rand.Read(readKey) rand.Read(writeKey) // Perform deployment with the same keys domain := performDeploymentWithKeys(t, engine, mockHG, mockCompiler, readKey, writeKey, engineMode) // Set up compute metadata setupComputeMetadata(t, mockHG, domain, readKey, writeKey) // Create operations that can run in parallel (no conflicts) ops := []*compute.ExecuteOperation{ { Application: compute.Application{ Address: makeExtrinsicAddress("app1"), ExecutionContext: compute.ExecutionContextExtrinsic, }, Identifier: []byte("op1"), Dependencies: [][]byte{}, }, { Application: compute.Application{ Address: makeExtrinsicAddress("app2"), ExecutionContext: compute.ExecutionContextExtrinsic, }, Identifier: []byte("op2"), Dependencies: [][]byte{}, }, { Application: compute.Application{ Address: makeExtrinsicAddress("app3"), ExecutionContext: compute.ExecutionContextExtrinsic, }, Identifier: []byte("op3"), Dependencies: [][]byte{}, }, } msg, _ := createTestCodeExecuteMessage(t, mockHG, domain, ops) // Process message state := hgstate.NewHypergraphState(mockHG) msgs, err := engine.ProcessMessage(1, big.NewInt(0), msg.Address, msg.Payload, state) assertCodeExecutionResult(t, mode, msgs, err, false) // All operations should be in the same stage since there are no conflicts }) }) // Test 19: topological sort ordering t.Run("topological_sort_ordering", func(t *testing.T) { runTestWithAllModes(t, "topological_sort_ordering", func(t *testing.T, mode TestExecutionMode) { logger := zap.NewNop() mockInclusionProver := new(mocks.MockInclusionProver) mockInclusionProver.On("CommitRaw", mock.Anything, mock.Anything).Return(make([]byte, 74), nil) mockHG := tests.CreateHypergraphWithInclusionProver(mockInclusionProver) mockHG.On("Commit").Return(map[tries.ShardKey][][]byte{}).Maybe() mockHG.On("TrackChange", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil).Maybe() mockKeyManager := new(mocks.MockKeyManager) mockBulletproofProver := new(mocks.MockBulletproofProver) mockVerEnc := new(mocks.MockVerifiableEncryptor) mockDecaf := new(mocks.MockDecafConstructor) mockCompiler := new(mocks.MockCompiler) // Map test mode to actual engine mode var engineMode engines.ExecutionMode switch mode { case TestGlobalMode: engineMode = engines.GlobalMode case TestApplicationMode: engineMode = engines.ApplicationMode case TestMixedMode: engineMode = engines.ApplicationMode } engine, err := engines.NewComputeExecutionEngine( logger, mockHG, mockKeyManager, mockInclusionProver, mockBulletproofProver, mockVerEnc, mockDecaf, mockCompiler, engineMode, ) require.NoError(t, err) // Set up mocks setupComputeMocks(t, mockHG, mockInclusionProver, mockBulletproofProver, engineMode) setupTokenIntrinsicMocks(t, mockHG) // Generate keys for metadata readKey := make([]byte, 57) writeKey := make([]byte, 57) rand.Read(readKey) rand.Read(writeKey) // Perform deployment with the same keys domain := performDeploymentWithKeys(t, engine, mockHG, mockCompiler, readKey, writeKey, engineMode) // Set up compute metadata setupComputeMetadata(t, mockHG, domain, readKey, writeKey) // Create complex DAG: op1 -> op2 -> op4, op1 -> op3 -> op4 ops := []*compute.ExecuteOperation{ { Application: compute.Application{ Address: makeExtrinsicAddress("app"), ExecutionContext: compute.ExecutionContextExtrinsic, }, Identifier: []byte("op1"), Dependencies: [][]byte{}, }, { Application: compute.Application{ Address: makeExtrinsicAddress("app"), ExecutionContext: compute.ExecutionContextExtrinsic, }, Identifier: []byte("op2"), Dependencies: [][]byte{[]byte("op1")}, }, { Application: compute.Application{ Address: makeExtrinsicAddress("app"), ExecutionContext: compute.ExecutionContextExtrinsic, }, Identifier: []byte("op3"), Dependencies: [][]byte{[]byte("op1")}, }, { Application: compute.Application{ Address: makeExtrinsicAddress("app"), ExecutionContext: compute.ExecutionContextExtrinsic, }, Identifier: []byte("op4"), Dependencies: [][]byte{[]byte("op2"), []byte("op3")}, }, } msg, _ := createTestCodeExecuteMessage(t, mockHG, domain, ops) // Process message state := hgstate.NewHypergraphState(mockHG) msgs, err := engine.ProcessMessage(1, big.NewInt(0), msg.Address, msg.Payload, state) assertCodeExecutionResult(t, mode, msgs, err, false) // Should produce stages: [op1], [op2, op3], [op4] }) }) // Test 20: Execution stage assignment correctness t.Run("execution_stage_assignment_correctness", func(t *testing.T) { runTestWithAllModes(t, "execution_stage_assignment_correctness", func(t *testing.T, mode TestExecutionMode) { logger := zap.NewNop() mockInclusionProver := new(mocks.MockInclusionProver) mockInclusionProver.On("CommitRaw", mock.Anything, mock.Anything).Return(make([]byte, 74), nil) mockHG := tests.CreateHypergraphWithInclusionProver(mockInclusionProver) mockHG.On("Commit").Return(map[tries.ShardKey][][]byte{}).Maybe() mockHG.On("TrackChange", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil).Maybe() mockKeyManager := new(mocks.MockKeyManager) mockBulletproofProver := new(mocks.MockBulletproofProver) mockVerEnc := new(mocks.MockVerifiableEncryptor) mockDecaf := new(mocks.MockDecafConstructor) mockCompiler := new(mocks.MockCompiler) // Map test mode to actual engine mode var engineMode engines.ExecutionMode switch mode { case TestGlobalMode: engineMode = engines.GlobalMode case TestApplicationMode: engineMode = engines.ApplicationMode case TestMixedMode: engineMode = engines.ApplicationMode } engine, err := engines.NewComputeExecutionEngine( logger, mockHG, mockKeyManager, mockInclusionProver, mockBulletproofProver, mockVerEnc, mockDecaf, mockCompiler, engineMode, ) require.NoError(t, err) // Set up mocks setupComputeMocks(t, mockHG, mockInclusionProver, mockBulletproofProver, engineMode) setupTokenIntrinsicMocks(t, mockHG) // Generate keys for metadata readKey := make([]byte, 57) writeKey := make([]byte, 57) rand.Read(readKey) rand.Read(writeKey) // Perform deployment with the same keys domain := performDeploymentWithKeys(t, engine, mockHG, mockCompiler, readKey, writeKey, engineMode) // Set up compute metadata setupComputeMetadata(t, mockHG, domain, readKey, writeKey) // Create operations with mixed dependencies and conflicts ops := []*compute.ExecuteOperation{ { Application: compute.Application{ Address: makeExtrinsicAddress("app_a"), ExecutionContext: compute.ExecutionContextExtrinsic, }, Identifier: []byte("op1"), Dependencies: [][]byte{}, }, { Application: compute.Application{ Address: makeExtrinsicAddress("app_b"), ExecutionContext: compute.ExecutionContextExtrinsic, }, Identifier: []byte("op2"), Dependencies: [][]byte{}, }, { Application: compute.Application{ Address: makeExtrinsicAddress("app_a"), // Conflict with op1 ExecutionContext: compute.ExecutionContextExtrinsic, }, Identifier: []byte("op3"), Dependencies: [][]byte{}, }, { Application: compute.Application{ Address: makeExtrinsicAddress("app_c"), ExecutionContext: compute.ExecutionContextExtrinsic, }, Identifier: []byte("op4"), Dependencies: [][]byte{[]byte("op1"), []byte("op2")}, }, } msg, _ := createTestCodeExecuteMessage(t, mockHG, domain, ops) // Process message state := hgstate.NewHypergraphState(mockHG) msgs, err := engine.ProcessMessage(1, big.NewInt(0), msg.Address, msg.Payload, state) assertCodeExecutionResult(t, mode, msgs, err, false) // Expected stages considering conflicts and dependencies: // Stage 0: op1, op2 (no dependencies, no conflicts between them) // Stage 1: op3 (conflicts with op1) // Stage 2: op4 (depends on op1 and op2) }) }) // Test 21: Materialize stores dependency structure t.Run("materialize_stores_dependency_structure", func(t *testing.T) { runTestWithAllModes(t, "materialize_stores_dependency_structure", func(t *testing.T, mode TestExecutionMode) { logger := zap.NewNop() mockInclusionProver := new(mocks.MockInclusionProver) mockInclusionProver.On("CommitRaw", mock.Anything, mock.Anything).Return(make([]byte, 74), nil) mockHG := tests.CreateHypergraphWithInclusionProver(mockInclusionProver) mockHG.On("Commit").Return(map[tries.ShardKey][][]byte{}).Maybe() mockHG.On("TrackChange", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil).Maybe() mockKeyManager := new(mocks.MockKeyManager) mockBulletproofProver := new(mocks.MockBulletproofProver) mockVerEnc := new(mocks.MockVerifiableEncryptor) mockDecaf := new(mocks.MockDecafConstructor) mockCompiler := new(mocks.MockCompiler) // Map test mode to actual engine mode var engineMode engines.ExecutionMode switch mode { case TestGlobalMode: engineMode = engines.GlobalMode case TestApplicationMode: engineMode = engines.ApplicationMode case TestMixedMode: engineMode = engines.ApplicationMode } engine, err := engines.NewComputeExecutionEngine( logger, mockHG, mockKeyManager, mockInclusionProver, mockBulletproofProver, mockVerEnc, mockDecaf, mockCompiler, engineMode, ) require.NoError(t, err) // Set up mocks setupComputeMocks(t, mockHG, mockInclusionProver, mockBulletproofProver, engineMode) setupTokenIntrinsicMocks(t, mockHG) // Generate keys for metadata readKey := make([]byte, 57) writeKey := make([]byte, 57) rand.Read(readKey) rand.Read(writeKey) // Perform deployment with the same keys domain := performDeploymentWithKeys(t, engine, mockHG, mockCompiler, readKey, writeKey, engineMode) // Set up compute metadata setupComputeMetadata(t, mockHG, domain, readKey, writeKey) // Create operations with dependencies ops := []*compute.ExecuteOperation{ { Application: compute.Application{ Address: makeExtrinsicAddress("app"), ExecutionContext: compute.ExecutionContextExtrinsic, }, Identifier: []byte("op1"), Dependencies: [][]byte{}, }, { Application: compute.Application{ Address: makeExtrinsicAddress("app"), ExecutionContext: compute.ExecutionContextExtrinsic, }, Identifier: []byte("op2"), Dependencies: [][]byte{[]byte("op1")}, }, } msg, ce := createTestCodeExecuteMessage(t, mockHG, domain, ops) // Process message state := hgstate.NewHypergraphState(mockHG) msgs, err := engine.ProcessMessage(1, big.NewInt(0), msg.Address, msg.Payload, state) assertCodeExecutionResult(t, mode, msgs, err, false) // Verify DAG structure is preserved in the materialized CodeExecute assert.Equal(t, 2, len(ce.ExecuteOperations)) assert.Equal(t, []byte("op1"), ce.ExecuteOperations[0].Identifier) assert.Equal(t, []byte("op2"), ce.ExecuteOperations[1].Identifier) assert.Equal(t, [][]byte{[]byte("op1")}, ce.ExecuteOperations[1].Dependencies) }) }) // Test 22: Materialize stores execution stages t.Run("materialize_stores_execution_stages", func(t *testing.T) { runTestWithAllModes(t, "materialize_stores_execution_stages", func(t *testing.T, mode TestExecutionMode) { logger := zap.NewNop() mockInclusionProver := new(mocks.MockInclusionProver) mockInclusionProver.On("CommitRaw", mock.Anything, mock.Anything).Return(make([]byte, 74), nil) mockHG := tests.CreateHypergraphWithInclusionProver(mockInclusionProver) mockHG.On("Commit").Return(map[tries.ShardKey][][]byte{}).Maybe() mockHG.On("TrackChange", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil).Maybe() mockKeyManager := new(mocks.MockKeyManager) mockBulletproofProver := new(mocks.MockBulletproofProver) mockVerEnc := new(mocks.MockVerifiableEncryptor) mockDecaf := new(mocks.MockDecafConstructor) mockCompiler := new(mocks.MockCompiler) // Map test mode to actual engine mode var engineMode engines.ExecutionMode switch mode { case TestGlobalMode: engineMode = engines.GlobalMode case TestApplicationMode: engineMode = engines.ApplicationMode case TestMixedMode: engineMode = engines.ApplicationMode } engine, err := engines.NewComputeExecutionEngine( logger, mockHG, mockKeyManager, mockInclusionProver, mockBulletproofProver, mockVerEnc, mockDecaf, mockCompiler, engineMode, ) require.NoError(t, err) // Set up mocks setupComputeMocks(t, mockHG, mockInclusionProver, mockBulletproofProver, engineMode) setupTokenIntrinsicMocks(t, mockHG) // Generate keys for metadata readKey := make([]byte, 57) writeKey := make([]byte, 57) rand.Read(readKey) rand.Read(writeKey) // Perform deployment with the same keys domain := performDeploymentWithKeys(t, engine, mockHG, mockCompiler, readKey, writeKey, engineMode) // Set up compute metadata setupComputeMetadata(t, mockHG, domain, readKey, writeKey) // Create operations that will be in different stages ops := []*compute.ExecuteOperation{ { Application: compute.Application{ Address: makeExtrinsicAddress("app1"), ExecutionContext: compute.ExecutionContextExtrinsic, }, Identifier: []byte("op1"), Dependencies: [][]byte{}, }, { Application: compute.Application{ Address: makeExtrinsicAddress("app2"), ExecutionContext: compute.ExecutionContextExtrinsic, }, Identifier: []byte("op2"), Dependencies: [][]byte{}, }, { Application: compute.Application{ Address: makeExtrinsicAddress("app3"), ExecutionContext: compute.ExecutionContextExtrinsic, }, Identifier: []byte("op3"), Dependencies: [][]byte{[]byte("op1"), []byte("op2")}, }, } msg, _ := createTestCodeExecuteMessage(t, mockHG, domain, ops) // Process message state := hgstate.NewHypergraphState(mockHG) msgs, err := engine.ProcessMessage(1, big.NewInt(0), msg.Address, msg.Payload, state) assertCodeExecutionResult(t, mode, msgs, err, false) // The execution stages should be computed and stored }) }) // Test 23: Materialize stores rendezvous t.Run("materialize_stores_rendezvous", func(t *testing.T) { runTestWithAllModes(t, "materialize_stores_rendezvous", func(t *testing.T, mode TestExecutionMode) { logger := zap.NewNop() mockInclusionProver := new(mocks.MockInclusionProver) mockInclusionProver.On("CommitRaw", mock.Anything, mock.Anything).Return(make([]byte, 74), nil) mockHG := tests.CreateHypergraphWithInclusionProver(mockInclusionProver) mockHG.On("Commit").Return(map[tries.ShardKey][][]byte{}).Maybe() mockHG.On("TrackChange", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil).Maybe() mockKeyManager := new(mocks.MockKeyManager) mockBulletproofProver := new(mocks.MockBulletproofProver) mockVerEnc := new(mocks.MockVerifiableEncryptor) mockDecaf := new(mocks.MockDecafConstructor) mockCompiler := new(mocks.MockCompiler) // Map test mode to actual engine mode var engineMode engines.ExecutionMode switch mode { case TestGlobalMode: engineMode = engines.GlobalMode case TestApplicationMode: engineMode = engines.ApplicationMode case TestMixedMode: engineMode = engines.ApplicationMode } engine, err := engines.NewComputeExecutionEngine( logger, mockHG, mockKeyManager, mockInclusionProver, mockBulletproofProver, mockVerEnc, mockDecaf, mockCompiler, engineMode, ) require.NoError(t, err) // Set up mocks setupComputeMocks(t, mockHG, mockInclusionProver, mockBulletproofProver, engineMode) setupTokenIntrinsicMocks(t, mockHG) // Generate keys for metadata readKey := make([]byte, 57) writeKey := make([]byte, 57) rand.Read(readKey) rand.Read(writeKey) // Perform deployment with the same keys domain := performDeploymentWithKeys(t, engine, mockHG, mockCompiler, readKey, writeKey, engineMode) // Set up compute metadata setupComputeMetadata(t, mockHG, domain, readKey, writeKey) ops := []*compute.ExecuteOperation{ { Application: compute.Application{ Address: makeExtrinsicAddress("app"), ExecutionContext: compute.ExecutionContextExtrinsic, }, Identifier: []byte("op1"), Dependencies: [][]byte{}, }, } msg, ce := createTestCodeExecuteMessage(t, mockHG, domain, ops) // Process message state := hgstate.NewHypergraphState(mockHG) msgs, err := engine.ProcessMessage(1, big.NewInt(0), msg.Address, msg.Payload, state) assertCodeExecutionResult(t, mode, msgs, err, false) // Verify rendezvous is stored correctly assert.NotNil(t, ce.Rendezvous) }) }) // Test 24: Finalize collects all operation results t.Run("finalize_collects_all_operation_results", func(t *testing.T) { runTestWithAllModes(t, "finalize_collects_all_operation_results", func(t *testing.T, mode TestExecutionMode) { logger := zap.NewNop() mockInclusionProver := new(mocks.MockInclusionProver) mockInclusionProver.On("CommitRaw", mock.Anything, mock.Anything).Return(make([]byte, 74), nil) mockHG := tests.CreateHypergraphWithInclusionProver(mockInclusionProver) mockHG.On("Commit").Return(map[tries.ShardKey][][]byte{}).Maybe() mockHG.On("TrackChange", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil).Maybe() mockHG.On("GetCoveredPrefix").Return([]int{}, nil) mockKeyManager := new(mocks.MockKeyManager) mockKeyManager.On("ValidateSignature", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(true, nil) mockBulletproofProver := new(mocks.MockBulletproofProver) mockVerEnc := new(mocks.MockVerifiableEncryptor) mockDecaf := new(mocks.MockDecafConstructor) mockCompiler := new(mocks.MockCompiler) // Map test mode to actual engine mode var engineMode engines.ExecutionMode switch mode { case TestGlobalMode: engineMode = engines.GlobalMode case TestApplicationMode: engineMode = engines.ApplicationMode case TestMixedMode: engineMode = engines.ApplicationMode } engine, err := engines.NewComputeExecutionEngine( logger, mockHG, mockKeyManager, mockInclusionProver, mockBulletproofProver, mockVerEnc, mockDecaf, mockCompiler, engineMode, ) require.NoError(t, err) // Set up mocks setupComputeMocks(t, mockHG, mockInclusionProver, mockBulletproofProver, engineMode) // Set up compute metadata with proper keys readKey := make([]byte, 57) rand.Read(readKey) writePub, writePriv, err := ed448.GenerateKey(rand.Reader) writeKey := []byte(writePub) domain := make([]byte, 32) rand.Read(domain) setupComputeMetadata(t, mockHG, domain, readKey, writeKey) // Additional mocks specific to this test mockHG.On("Get", mock.Anything, mock.Anything, mock.Anything).Return([]byte("old_value"), nil) mockHG.On("Set", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil) // Create mock execution results results := []*compute.ExecutionResult{ { OperationID: []byte("op1"), Success: true, Output: []byte("result1"), }, { OperationID: []byte("op2"), Success: true, Output: []byte("result2"), }, } var rendezvous [32]byte rand.Read(rendezvous[:]) msg, _ := createTestCodeFinalizeMessage(t, domain, []byte(writePriv), &compute.ComputeIntrinsicConfiguration{ReadPublicKey: readKey, WritePublicKey: writeKey}, rendezvous, results, mockHG, mockKeyManager) // Process message state := hgstate.NewHypergraphState(mockHG) msgs, err := engine.ProcessMessage(1, big.NewInt(0), msg.Address, msg.Payload, state) assertCodeExecutionResult(t, mode, msgs, err, false) }) }) // Test 25: Finalize commits durable state changes t.Run("finalize_commits_durable_state_changes", func(t *testing.T) { runTestWithAllModes(t, "finalize_commits_durable_state_changes", func(t *testing.T, mode TestExecutionMode) { logger := zap.NewNop() mockInclusionProver := new(mocks.MockInclusionProver) mockInclusionProver.On("CommitRaw", mock.Anything, mock.Anything).Return(make([]byte, 74), nil) mockHG := tests.CreateHypergraphWithInclusionProver(mockInclusionProver) mockHG.On("Commit").Return(map[tries.ShardKey][][]byte{}).Maybe() mockHG.On("TrackChange", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil).Maybe() mockHG.On("GetCoveredPrefix").Return([]int{}, nil) mockKeyManager := new(mocks.MockKeyManager) mockKeyManager.On("ValidateSignature", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(true, nil) mockBulletproofProver := new(mocks.MockBulletproofProver) mockVerEnc := new(mocks.MockVerifiableEncryptor) mockDecaf := new(mocks.MockDecafConstructor) mockCompiler := new(mocks.MockCompiler) // Map test mode to actual engine mode var engineMode engines.ExecutionMode switch mode { case TestGlobalMode: engineMode = engines.GlobalMode case TestApplicationMode: engineMode = engines.ApplicationMode case TestMixedMode: engineMode = engines.ApplicationMode } engine, err := engines.NewComputeExecutionEngine( logger, mockHG, mockKeyManager, mockInclusionProver, mockBulletproofProver, mockVerEnc, mockDecaf, mockCompiler, engineMode, ) require.NoError(t, err) // Set up only the mocks needed for finalize operation // Set up metadata with test keys (Ed448 keys are 57 bytes) readKey := make([]byte, 57) rand.Read(readKey) writePub, writePriv, err := ed448.GenerateKey(rand.Reader) writeKey := []byte(writePub) domain := make([]byte, 32) rand.Read(domain) // Set up compute metadata metadataAddress := slices.Concat(domain, bytes.Repeat([]byte{0xff}, 32)) rdfSchema := `BASE PREFIX rdf: PREFIX rdfs: PREFIX qcl: PREFIX req: req:Request a rdfs:Class. req:A a rdfs:Property; rdfs:domain qcl:Uint; qcl:size 1; qcl:order 0; rdfs:range req:Request. ` // Valid RDF schema for test err = tests.SetHypergraphComputeMetadataData( mockHG, metadataAddress, rdfSchema, nil, // creator not needed for test readKey, writeKey, ) require.NoError(t, err) // Additional mocks specific to this test mockHG.On("Get", mock.Anything, mock.Anything, mock.Anything).Return([]byte("old_value"), nil) mockHG.On("Set", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil) // Add CommitRaw mock for app mode mockInclusionProver.On("CommitRaw", mock.Anything, mock.Anything).Return(make([]byte, 74), nil).Maybe() // Mock GetVertex for any address (needed for finalize operations) mockHG.On("GetVertex", mock.Anything).Return(nil, store.ErrNotFound).Maybe() // Add transaction mocks for commit operation txn := &mockTransaction{} mockHG.On("NewTransaction", false).Return(txn, nil).Maybe() mockHG.On("GetProver").Return(mockInclusionProver).Maybe() mockHG.On("Commit").Return(map[tries.ShardKey][][]byte{}).Maybe() mockHG.On("AddVertex", mock.Anything, mock.Anything).Return(nil).Maybe() mockHG.On("SetVertexData", mock.Anything, mock.Anything, mock.Anything).Return(nil).Maybe() // Mock the deployed code retrieval for finalize mockHG.On("GetVertexData", mock.MatchedBy(func(addr [64]byte) bool { // Check if it's trying to get deployed code return bytes.HasPrefix(addr[:32], domain) && bytes.Equal(addr[32:48], bytes.Repeat([]byte{0x00}, 16)) })).Return([]byte("deployed_code"), nil) // Create state transitions results := []*compute.ExecutionResult{ { OperationID: []byte("op1"), Success: true, Output: []byte("result1"), }, } var rendezvous [32]byte rand.Read(rendezvous[:]) msg, _ := createTestCodeFinalizeMessage(t, domain, []byte(writePriv), &compute.ComputeIntrinsicConfiguration{ReadPublicKey: readKey, WritePublicKey: writeKey}, rendezvous, results, mockHG, mockKeyManager) // Process message state := hgstate.NewHypergraphState(mockHG) msgs, err := engine.ProcessMessage(1, big.NewInt(0), msg.Address, msg.Payload, state) assertCodeExecutionResult(t, mode, msgs, err, false) // For finalize operations in global mode, we expect no state changes // since it's just acknowledging the finalization // In app mode, state changes should be persisted if mode != TestGlobalMode { // In app mode, verify that state changes were persisted // Since we can't easily verify the exact calls, we trust the test passes } }) }) // Test 26: Finalize rollback on operation failure t.Run("finalize_rollback_on_operation_failure", func(t *testing.T) { runTestWithAllModes(t, "finalize_rollback_on_operation_failure", func(t *testing.T, mode TestExecutionMode) { logger := zap.NewNop() mockInclusionProver := new(mocks.MockInclusionProver) mockInclusionProver.On("CommitRaw", mock.Anything, mock.Anything).Return(make([]byte, 74), nil) mockHG := tests.CreateHypergraphWithInclusionProver(mockInclusionProver) mockHG.On("Commit").Return(map[tries.ShardKey][][]byte{}).Maybe() mockHG.On("TrackChange", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil).Maybe() mockHG.On("GetCoveredPrefix").Return([]int{}, nil) mockKeyManager := new(mocks.MockKeyManager) mockKeyManager.On("ValidateSignature", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(true, nil) mockBulletproofProver := new(mocks.MockBulletproofProver) mockVerEnc := new(mocks.MockVerifiableEncryptor) mockDecaf := new(mocks.MockDecafConstructor) mockCompiler := new(mocks.MockCompiler) // Map test mode to actual engine mode var engineMode engines.ExecutionMode switch mode { case TestGlobalMode: engineMode = engines.GlobalMode case TestApplicationMode: engineMode = engines.ApplicationMode case TestMixedMode: engineMode = engines.ApplicationMode } engine, err := engines.NewComputeExecutionEngine( logger, mockHG, mockKeyManager, mockInclusionProver, mockBulletproofProver, mockVerEnc, mockDecaf, mockCompiler, engineMode, ) require.NoError(t, err) // Set up compute metadata with test keys (Ed448 keys are 57 bytes) readKey := make([]byte, 57) rand.Read(readKey) writePub, writePriv, err := ed448.GenerateKey(rand.Reader) writeKey := []byte(writePub) domain := make([]byte, 32) rand.Read(domain) // Set up compute metadata metadataAddress := slices.Concat(domain, bytes.Repeat([]byte{0xff}, 32)) rdfSchema := `BASE PREFIX rdf: PREFIX rdfs: PREFIX qcl: PREFIX req: req:Request a rdfs:Class. req:A a rdfs:Property; rdfs:domain qcl:Uint; qcl:size 1; qcl:order 0; rdfs:range req:Request. ` // Valid RDF schema for test err = tests.SetHypergraphComputeMetadataData( mockHG, metadataAddress, rdfSchema, nil, // creator not needed for test readKey, writeKey, ) require.NoError(t, err) // Additional mocks specific to this test mockHG.On("Get", mock.Anything, mock.Anything, mock.Anything).Return([]byte("old_value"), nil) mockHG.On("Set", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil) // Add CommitRaw mock for app mode mockInclusionProver.On("CommitRaw", mock.Anything, mock.Anything).Return(make([]byte, 74), nil).Maybe() // Mock GetVertex for any address (needed for finalize operations) mockHG.On("GetVertex", mock.Anything).Return(nil, store.ErrNotFound).Maybe() // Add transaction mocks for commit operation txn := &mockTransaction{} mockHG.On("NewTransaction", false).Return(txn, nil).Maybe() mockHG.On("GetProver").Return(mockInclusionProver).Maybe() mockHG.On("Commit").Return(map[tries.ShardKey][][]byte{}).Maybe() mockHG.On("AddVertex", mock.Anything, mock.Anything).Return(nil).Maybe() mockHG.On("SetVertexData", mock.Anything, mock.Anything, mock.Anything).Return(nil).Maybe() // Mock the deployed code retrieval for finalize mockHG.On("GetVertexData", mock.MatchedBy(func(addr [64]byte) bool { // Check if it's trying to get deployed code return bytes.HasPrefix(addr[:32], domain) && bytes.Equal(addr[32:48], bytes.Repeat([]byte{0x00}, 16)) })).Return([]byte("deployed_code"), nil) // Create results with failure results := []*compute.ExecutionResult{ { OperationID: []byte("op1"), Success: false, Error: []byte("execution failed"), }, } var rendezvous [32]byte rand.Read(rendezvous[:]) msg, _ := createTestCodeFinalizeMessage(t, domain, []byte(writePriv), &compute.ComputeIntrinsicConfiguration{ReadPublicKey: readKey, WritePublicKey: writeKey}, rendezvous, results, mockHG, mockKeyManager) // Process message state := hgstate.NewHypergraphState(mockHG) msgs, err := engine.ProcessMessage(1, big.NewInt(0), msg.Address, msg.Payload, state) assertCodeExecutionResult(t, mode, msgs, err, false) // State changes should not be committed for failed operations }) }) // Test 27: Finalize dispatch message output only t.Run("finalize_dispatch_message_output_only", func(t *testing.T) { runTestWithAllModes(t, "finalize_dispatch_message_output_only", func(t *testing.T, mode TestExecutionMode) { logger := zap.NewNop() mockInclusionProver := new(mocks.MockInclusionProver) mockInclusionProver.On("CommitRaw", mock.Anything, mock.Anything).Return(make([]byte, 74), nil) mockHG := tests.CreateHypergraphWithInclusionProver(mockInclusionProver) mockHG.On("Commit").Return(map[tries.ShardKey][][]byte{}).Maybe() mockHG.On("TrackChange", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil).Maybe() mockHG.On("GetCoveredPrefix").Return([]int{}, nil) mockKeyManager := new(mocks.MockKeyManager) mockKeyManager.On("ValidateSignature", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(true, nil) mockBulletproofProver := new(mocks.MockBulletproofProver) mockVerEnc := new(mocks.MockVerifiableEncryptor) mockDecaf := new(mocks.MockDecafConstructor) mockCompiler := new(mocks.MockCompiler) // Map test mode to actual engine mode var engineMode engines.ExecutionMode switch mode { case TestGlobalMode: engineMode = engines.GlobalMode case TestApplicationMode: engineMode = engines.ApplicationMode case TestMixedMode: engineMode = engines.ApplicationMode } engine, err := engines.NewComputeExecutionEngine( logger, mockHG, mockKeyManager, mockInclusionProver, mockBulletproofProver, mockVerEnc, mockDecaf, mockCompiler, engineMode, ) require.NoError(t, err) // Set up compute metadata with test keys (Ed448 keys are 57 bytes) readKey := make([]byte, 57) rand.Read(readKey) writePub, writePriv, err := ed448.GenerateKey(rand.Reader) writeKey := []byte(writePub) domain := make([]byte, 32) rand.Read(domain) // Set up compute metadata metadataAddress := slices.Concat(domain, bytes.Repeat([]byte{0xff}, 32)) rdfSchema := `BASE PREFIX rdf: PREFIX rdfs: PREFIX qcl: PREFIX req: req:Request a rdfs:Class. req:A a rdfs:Property; rdfs:domain qcl:Uint; qcl:size 1; qcl:order 0; rdfs:range req:Request. ` // Valid RDF schema for test err = tests.SetHypergraphComputeMetadataData( mockHG, metadataAddress, rdfSchema, nil, // creator not needed for test readKey, writeKey, ) require.NoError(t, err) // Additional mocks specific to this test mockHG.On("Get", mock.Anything, mock.Anything, mock.Anything).Return([]byte("old_value"), nil) mockHG.On("Set", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil) // Add CommitRaw mock for app mode mockInclusionProver.On("CommitRaw", mock.Anything, mock.Anything).Return(make([]byte, 74), nil).Maybe() // Mock GetVertex for any address (needed for finalize operations) mockHG.On("GetVertex", mock.Anything).Return(nil, store.ErrNotFound).Maybe() // Add transaction mocks for commit operation txn := &mockTransaction{} mockHG.On("NewTransaction", false).Return(txn, nil).Maybe() mockHG.On("GetProver").Return(mockInclusionProver).Maybe() mockHG.On("Commit").Return(map[tries.ShardKey][][]byte{}).Maybe() mockHG.On("AddVertex", mock.Anything, mock.Anything).Return(nil).Maybe() mockHG.On("SetVertexData", mock.Anything, mock.Anything, mock.Anything).Return(nil).Maybe() // Mock the deployed code retrieval for finalize mockHG.On("GetVertexData", mock.MatchedBy(func(addr [64]byte) bool { // Check if it's trying to get deployed code return bytes.HasPrefix(addr[:32], domain) && bytes.Equal(addr[32:48], bytes.Repeat([]byte{0x00}, 16)) })).Return([]byte("deployed_code"), nil) // Create results with message output results := []*compute.ExecutionResult{ { OperationID: []byte("op1"), Success: true, Output: []byte("transient_output"), }, } var rendezvous [32]byte rand.Read(rendezvous[:]) // Create finalize with message output cf := compute.NewCodeFinalize( rendezvous, [32]byte(domain), results, []*compute.StateTransition{}, // No state transitions []byte("message_output_only"), []byte(writePriv), &compute.ComputeIntrinsicConfiguration{ ReadPublicKey: readKey, WritePublicKey: writeKey, }, nil, nil, nil, nil, nil, nil, ) // Wrap in MessageRequest and serialize finalizeReq := &protobufs.MessageRequest{ Request: &protobufs.MessageRequest_CodeFinalize{ CodeFinalize: cf.ToProtobuf(), }, } outFees := []*big.Int{big.NewInt(1)} total := big.NewInt(10000000) outFees = append(outFees, total) payment, err := tests.CreateValidQUILPendingTransactionPayload( mockHG, 1, [][]byte{make([]byte, 56)}, [][]byte{make([]byte, 56)}, [][]byte{make([]byte, 56)}, [][]byte{make([]byte, 56)}, []*big.Int{big.NewInt(10000001)}, []*big.Int{big.NewInt(0)}, outFees, 0, ) if err != nil { panic(err) } bundle := &protobufs.MessageBundle{ Requests: []*protobufs.MessageRequest{ payment, finalizeReq, }, } bundleBytes, err := bundle.ToCanonicalBytes() require.NoError(t, err) // Create message hash := sha3.Sum256(bundleBytes) require.NoError(t, err) msg := &protobufs.Message{ Address: domain, Hash: hash[:], Payload: bundleBytes, } // Process message state := hgstate.NewHypergraphState(mockHG) msgs, err := engine.ProcessMessage(1, big.NewInt(0), msg.Address, msg.Payload, state) assertCodeExecutionResult(t, mode, msgs, err, false) }) }) // Test 28: Finalize partial success handling t.Run("finalize_partial_success_handling", func(t *testing.T) { runTestWithAllModes(t, "finalize_partial_success_handling", func(t *testing.T, mode TestExecutionMode) { logger := zap.NewNop() mockInclusionProver := new(mocks.MockInclusionProver) mockInclusionProver.On("CommitRaw", mock.Anything, mock.Anything).Return(make([]byte, 74), nil) mockHG := tests.CreateHypergraphWithInclusionProver(mockInclusionProver) mockHG.On("Commit").Return(map[tries.ShardKey][][]byte{}).Maybe() mockHG.On("TrackChange", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil).Maybe() mockHG.On("GetCoveredPrefix").Return([]int{}, nil) mockKeyManager := new(mocks.MockKeyManager) mockKeyManager.On("ValidateSignature", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(true, nil) mockBulletproofProver := new(mocks.MockBulletproofProver) mockVerEnc := new(mocks.MockVerifiableEncryptor) mockDecaf := new(mocks.MockDecafConstructor) mockCompiler := new(mocks.MockCompiler) // Map test mode to actual engine mode var engineMode engines.ExecutionMode switch mode { case TestGlobalMode: engineMode = engines.GlobalMode case TestApplicationMode: engineMode = engines.ApplicationMode case TestMixedMode: engineMode = engines.ApplicationMode } engine, err := engines.NewComputeExecutionEngine( logger, mockHG, mockKeyManager, mockInclusionProver, mockBulletproofProver, mockVerEnc, mockDecaf, mockCompiler, engineMode, ) require.NoError(t, err) // Set up compute metadata with test keys (Ed448 keys are 57 bytes) readKey := make([]byte, 57) rand.Read(readKey) writePub, writePriv, err := ed448.GenerateKey(rand.Reader) writeKey := []byte(writePub) domain := make([]byte, 32) rand.Read(domain) // Set up compute metadata metadataAddress := slices.Concat(domain, bytes.Repeat([]byte{0xff}, 32)) rdfSchema := `BASE PREFIX rdf: PREFIX rdfs: PREFIX qcl: PREFIX req: req:Request a rdfs:Class. req:A a rdfs:Property; rdfs:domain qcl:Uint; qcl:size 1; qcl:order 0; rdfs:range req:Request. ` // Valid RDF schema for test err = tests.SetHypergraphComputeMetadataData( mockHG, metadataAddress, rdfSchema, nil, // creator not needed for test readKey, writeKey, ) require.NoError(t, err) // Additional mocks specific to this test mockHG.On("Get", mock.Anything, mock.Anything, mock.Anything).Return([]byte("old_value"), nil) mockHG.On("Set", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil) // Add CommitRaw mock for app mode mockInclusionProver.On("CommitRaw", mock.Anything, mock.Anything).Return(make([]byte, 74), nil).Maybe() // Mock GetVertex for any address (needed for finalize operations) mockHG.On("GetVertex", mock.Anything).Return(nil, store.ErrNotFound).Maybe() // Add transaction mocks for commit operation txn := &mockTransaction{} mockHG.On("NewTransaction", false).Return(txn, nil).Maybe() mockHG.On("GetProver").Return(mockInclusionProver).Maybe() mockHG.On("Commit").Return(map[tries.ShardKey][][]byte{}).Maybe() mockHG.On("AddVertex", mock.Anything, mock.Anything).Return(nil).Maybe() mockHG.On("SetVertexData", mock.Anything, mock.Anything, mock.Anything).Return(nil).Maybe() // Mock the deployed code retrieval for finalize mockHG.On("GetVertexData", mock.MatchedBy(func(addr [64]byte) bool { // Check if it's trying to get deployed code return bytes.HasPrefix(addr[:32], domain) && bytes.Equal(addr[32:48], bytes.Repeat([]byte{0x00}, 16)) })).Return([]byte("deployed_code"), nil) // Create mixed results - some succeed, some fail results := []*compute.ExecutionResult{ { OperationID: []byte("op1"), Success: true, Output: []byte("result1"), }, { OperationID: []byte("op2"), Success: false, Error: []byte("op2 failed"), }, { OperationID: []byte("op3"), Success: true, Output: []byte("result3"), }, } var rendezvous [32]byte rand.Read(rendezvous[:]) msg, _ := createTestCodeFinalizeMessage(t, domain, []byte(writePriv), &compute.ComputeIntrinsicConfiguration{ReadPublicKey: readKey, WritePublicKey: writeKey}, rendezvous, results, mockHG, mockKeyManager) // Process message state := hgstate.NewHypergraphState(mockHG) msgs, err := engine.ProcessMessage(1, big.NewInt(0), msg.Address, msg.Payload, state) assertCodeExecutionResult(t, mode, msgs, err, false) }) }) // Test 29: Empty operations list rejected t.Run("empty_operations_list_rejected", func(t *testing.T) { runTestWithAllModes(t, "empty_operations_list_rejected", func(t *testing.T, mode TestExecutionMode) { logger := zap.NewNop() mockInclusionProver := new(mocks.MockInclusionProver) mockInclusionProver.On("CommitRaw", mock.Anything, mock.Anything).Return(make([]byte, 74), nil) mockHG := tests.CreateHypergraphWithInclusionProver(mockInclusionProver) mockHG.On("Commit").Return(map[tries.ShardKey][][]byte{}).Maybe() mockHG.On("TrackChange", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil).Maybe() mockHG.On("GetCoveredPrefix").Return([]int{}, nil) mockKeyManager := new(mocks.MockKeyManager) mockKeyManager.On("ValidateSignature", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(true, nil) mockBulletproofProver := new(mocks.MockBulletproofProver) mockVerEnc := new(mocks.MockVerifiableEncryptor) mockDecaf := new(mocks.MockDecafConstructor) mockCompiler := new(mocks.MockCompiler) // Map test mode to actual engine mode var engineMode engines.ExecutionMode switch mode { case TestGlobalMode: engineMode = engines.GlobalMode case TestApplicationMode: engineMode = engines.ApplicationMode case TestMixedMode: engineMode = engines.ApplicationMode } engine, err := engines.NewComputeExecutionEngine( logger, mockHG, mockKeyManager, mockInclusionProver, mockBulletproofProver, mockVerEnc, mockDecaf, mockCompiler, engineMode, ) require.NoError(t, err) domain := make([]byte, 32) rand.Read(domain) // Set up compute metadata with test keys (Ed448 keys are 57 bytes) readKey := make([]byte, 57) writeKey := make([]byte, 57) rand.Read(readKey) rand.Read(writeKey) // Set up compute metadata metadataAddress := slices.Concat(domain, bytes.Repeat([]byte{0xff}, 32)) rdfSchema := `BASE PREFIX rdf: PREFIX rdfs: PREFIX qcl: PREFIX req: req:Request a rdfs:Class. req:A a rdfs:Property; rdfs:domain qcl:Uint; qcl:size 1; qcl:order 0; rdfs:range req:Request. ` // Valid RDF schema for test err = tests.SetHypergraphComputeMetadataData( mockHG, metadataAddress, rdfSchema, nil, // creator not needed for test readKey, writeKey, ) require.NoError(t, err) // Additional mocks specific to this test mockHG.On("Get", mock.Anything, mock.Anything, mock.Anything).Return([]byte("old_value"), nil) mockHG.On("Set", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil) // Add CommitRaw mock for app mode mockInclusionProver.On("CommitRaw", mock.Anything, mock.Anything).Return(make([]byte, 74), nil).Maybe() // Mock GetVertex for any address (needed for finalize operations) mockHG.On("GetVertex", mock.Anything).Return(nil, store.ErrNotFound).Maybe() // Add transaction mocks for commit operation txn := &mockTransaction{} mockHG.On("NewTransaction", false).Return(txn, nil).Maybe() mockHG.On("GetProver").Return(mockInclusionProver).Maybe() mockHG.On("Commit").Return(map[tries.ShardKey][][]byte{}).Maybe() mockHG.On("AddVertex", mock.Anything, mock.Anything).Return(nil).Maybe() mockHG.On("SetVertexData", mock.Anything, mock.Anything, mock.Anything).Return(nil).Maybe() // Add NewMultiproof mock mockMultiproof := &mocks.MockMultiproof{} mockMultiproof.On("FromBytes", mock.Anything).Return(nil).Maybe() mockInclusionProver.On("NewMultiproof").Return(mockMultiproof).Maybe() // Set up mocks mockBulletproofProver.On("SimpleVerify", mock.Anything, mock.Anything, mock.Anything).Return(true) // Create message with empty operations list ops := []*compute.ExecuteOperation{} msg, _ := createTestCodeExecuteMessage(t, mockHG, domain, ops) // Process message should fail state := hgstate.NewHypergraphState(mockHG) msgs, err := engine.ProcessMessage(1, big.NewInt(0), msg.Address, msg.Payload, state) assert.Error(t, err) assert.Nil(t, msgs) // In global mode, CodeExecute messages are not allowed after deployment // In app mode, we should get the empty operations error if mode == TestGlobalMode { assert.Contains(t, err.Error(), "non-deploy messages not allowed in global mode") } else { assert.Contains(t, err.Error(), "empty") } }) }) // Test 30: Max operations limit enforcement t.Run("max_operations_limit_enforcement", func(t *testing.T) { runTestWithAllModes(t, "max_operations_limit_enforcement", func(t *testing.T, mode TestExecutionMode) { logger := zap.NewNop() mockInclusionProver := new(mocks.MockInclusionProver) mockInclusionProver.On("CommitRaw", mock.Anything, mock.Anything).Return(make([]byte, 74), nil) mockHG := tests.CreateHypergraphWithInclusionProver(mockInclusionProver) mockHG.On("Commit").Return(map[tries.ShardKey][][]byte{}).Maybe() mockHG.On("TrackChange", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil).Maybe() mockHG.On("GetCoveredPrefix").Return([]int{}, nil) mockKeyManager := new(mocks.MockKeyManager) mockKeyManager.On("ValidateSignature", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(true, nil) mockBulletproofProver := new(mocks.MockBulletproofProver) mockVerEnc := new(mocks.MockVerifiableEncryptor) mockDecaf := new(mocks.MockDecafConstructor) mockCompiler := new(mocks.MockCompiler) // Map test mode to actual engine mode var engineMode engines.ExecutionMode switch mode { case TestGlobalMode: engineMode = engines.GlobalMode case TestApplicationMode: engineMode = engines.ApplicationMode case TestMixedMode: engineMode = engines.ApplicationMode } engine, err := engines.NewComputeExecutionEngine( logger, mockHG, mockKeyManager, mockInclusionProver, mockBulletproofProver, mockVerEnc, mockDecaf, mockCompiler, engineMode, ) require.NoError(t, err) domain := make([]byte, 32) rand.Read(domain) // For app mode, set up compute metadata so the intrinsic can be loaded // Set up compute metadata with test keys (Ed448 keys are 57 bytes) readKey := make([]byte, 57) writeKey := make([]byte, 57) rand.Read(readKey) rand.Read(writeKey) // Set up compute metadata metadataAddress := slices.Concat(domain, bytes.Repeat([]byte{0xff}, 32)) rdfSchema := `BASE PREFIX rdf: PREFIX rdfs: PREFIX qcl: PREFIX req: req:Request a rdfs:Class. req:A a rdfs:Property; rdfs:domain qcl:Uint; qcl:size 1; qcl:order 0; rdfs:range req:Request. ` // Valid RDF schema for test err = tests.SetHypergraphComputeMetadataData( mockHG, metadataAddress, rdfSchema, nil, // creator not needed for test readKey, writeKey, ) require.NoError(t, err) // Additional mocks specific to this test mockHG.On("Get", mock.Anything, mock.Anything, mock.Anything).Return([]byte("old_value"), nil) mockHG.On("Set", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil) // Add CommitRaw mock for app mode mockInclusionProver.On("CommitRaw", mock.Anything, mock.Anything).Return(make([]byte, 74), nil).Maybe() // Mock GetVertex for any address (needed for finalize operations) mockHG.On("GetVertex", mock.Anything).Return(nil, store.ErrNotFound).Maybe() // Add transaction mocks for commit operation txn := &mockTransaction{} mockHG.On("NewTransaction", false).Return(txn, nil).Maybe() mockHG.On("GetProver").Return(mockInclusionProver).Maybe() mockHG.On("Commit").Return(map[tries.ShardKey][][]byte{}).Maybe() mockHG.On("AddVertex", mock.Anything, mock.Anything).Return(nil).Maybe() mockHG.On("SetVertexData", mock.Anything, mock.Anything, mock.Anything).Return(nil).Maybe() // Add NewMultiproof mock mockMultiproof := &mocks.MockMultiproof{} mockMultiproof.On("FromBytes", mock.Anything).Return(nil).Maybe() mockInclusionProver.On("NewMultiproof").Return(mockMultiproof).Maybe() // Mock GetVertexData for deployed code addresses (returns empty tree) mockHG.On("GetVertexData", mock.Anything).Return(&tries.VectorCommitmentTree{}, nil).Maybe() // Set up mocks mockBulletproofProver.On("SimpleVerify", mock.Anything, mock.Anything, mock.Anything).Return(true) // Create more operations than allowed limit (assuming limit is 100) ops := make([]*compute.ExecuteOperation, 101) for i := 0; i < 101; i++ { ops[i] = &compute.ExecuteOperation{ Application: compute.Application{ Address: makeExtrinsicAddress(fmt.Sprintf("app%d", i)), ExecutionContext: compute.ExecutionContextExtrinsic, }, Identifier: []byte(fmt.Sprintf("op%d", i)), Dependencies: [][]byte{}, } } msg, _ := createTestCodeExecuteMessage(t, mockHG, domain, ops) // Process message should fail state := hgstate.NewHypergraphState(mockHG) msgs, err := engine.ProcessMessage(1, big.NewInt(0), msg.Address, msg.Payload, state) assert.Error(t, err) assert.Nil(t, msgs) // In global mode, CodeExecute messages are not allowed after deployment // In app mode, we should get the limit error if mode == TestGlobalMode { assert.Contains(t, err.Error(), "non-deploy messages not allowed in global mode") } else { assert.Contains(t, err.Error(), "limit") } }) }) // Test 31: dynamic fee enforcement t.Run("dynamic_fee_enforcement", func(t *testing.T) { runTestWithAllModes(t, "dynamic_fee_enforcement", func(t *testing.T, mode TestExecutionMode) { logger := zap.NewNop() mockInclusionProver := new(mocks.MockInclusionProver) mockInclusionProver.On("CommitRaw", mock.Anything, mock.Anything).Return(make([]byte, 74), nil) mockHG := tests.CreateHypergraphWithInclusionProver(mockInclusionProver) mockHG.On("Commit").Return(map[tries.ShardKey][][]byte{}).Maybe() mockHG.On("TrackChange", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil).Maybe() mockHG.On("GetCoveredPrefix").Return([]int{}, nil) mockKeyManager := new(mocks.MockKeyManager) mockKeyManager.On("ValidateSignature", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(true, nil) mockBulletproofProver := new(mocks.MockBulletproofProver) mockVerEnc := new(mocks.MockVerifiableEncryptor) mockDecaf := new(mocks.MockDecafConstructor) mockCompiler := new(mocks.MockCompiler) // Map test mode to actual engine mode var engineMode engines.ExecutionMode switch mode { case TestGlobalMode: engineMode = engines.GlobalMode case TestApplicationMode: engineMode = engines.ApplicationMode case TestMixedMode: engineMode = engines.ApplicationMode } engine, err := engines.NewComputeExecutionEngine( logger, mockHG, mockKeyManager, mockInclusionProver, mockBulletproofProver, mockVerEnc, mockDecaf, mockCompiler, engineMode, ) require.NoError(t, err) // Set up compute metadata with test keys (Ed448 keys are 57 bytes) readKey := make([]byte, 57) rand.Read(readKey) writePub, writePriv, err := ed448.GenerateKey(rand.Reader) writeKey := []byte(writePub) domain := make([]byte, 32) rand.Read(domain) // Set up compute metadata metadataAddress := slices.Concat(domain, bytes.Repeat([]byte{0xff}, 32)) rdfSchema := `BASE PREFIX rdf: PREFIX rdfs: PREFIX qcl: PREFIX req: req:Request a rdfs:Class. req:A a rdfs:Property; rdfs:domain qcl:Uint; qcl:size 1; qcl:order 0; rdfs:range req:Request. ` // Valid RDF schema for test err = tests.SetHypergraphComputeMetadataData( mockHG, metadataAddress, rdfSchema, nil, // creator not needed for test readKey, writeKey, ) require.NoError(t, err) // Additional mocks specific to this test mockHG.On("Get", mock.Anything, mock.Anything, mock.Anything).Return([]byte("old_value"), nil) mockHG.On("Set", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil) // Mock GetVertex for any address (needed for finalize operations) mockHG.On("GetVertex", mock.Anything).Return(nil, store.ErrNotFound).Maybe() // Add transaction mocks for commit operation txn := &mockTransaction{} mockHG.On("NewTransaction", false).Return(txn, nil) mockHG.On("GetProver").Return(mockInclusionProver) mockInclusionProver.On("CommitRaw", mock.Anything, mock.Anything).Return(make([]byte, 74), nil) mockHG.On("Commit").Return(map[tries.ShardKey][][]byte{}).Maybe() mockHG.On("AddVertex", mock.Anything, mock.Anything).Return(nil).Maybe() mockHG.On("SetVertexData", mock.Anything, mock.Anything, mock.Anything).Return(nil).Maybe() results := []*compute.ExecutionResult{ { OperationID: []byte("op1"), Success: true, Output: []byte("result1"), }, { OperationID: []byte("op2"), Success: true, Output: []byte("result2"), }, } var rendezvous [32]byte rand.Read(rendezvous[:]) msg, cf := createTestCodeFinalizeMessage(t, domain, []byte(writePriv), &compute.ComputeIntrinsicConfiguration{ReadPublicKey: readKey, WritePublicKey: writeKey}, rendezvous, results, mockHG, mockKeyManager) // Process message state := hgstate.NewHypergraphState(mockHG) // Dynamic fee too high msgs, err := engine.ProcessMessage(1, big.NewInt(10000000), msg.Address, msg.Payload, state) assertCodeExecutionResult(t, mode, msgs, err, true) assert.Len(t, cf.Results, 2) }) }) // Test 32: Multiple execution contexts t.Run("multiple_execution_contexts", func(t *testing.T) { runTestWithAllModes(t, "multiple_execution_contexts", func(t *testing.T, mode TestExecutionMode) { logger := zap.NewNop() mockInclusionProver := new(mocks.MockInclusionProver) mockInclusionProver.On("CommitRaw", mock.Anything, mock.Anything).Return(make([]byte, 74), nil) mockHG := tests.CreateHypergraphWithInclusionProver(mockInclusionProver) mockHG.On("Commit").Return(map[tries.ShardKey][][]byte{}).Maybe() mockHG.On("TrackChange", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil).Maybe() mockHG.On("GetCoveredPrefix").Return([]int{}, nil) mockKeyManager := new(mocks.MockKeyManager) mockBulletproofProver := new(mocks.MockBulletproofProver) mockVerEnc := new(mocks.MockVerifiableEncryptor) mockDecaf := new(mocks.MockDecafConstructor) mockCompiler := new(mocks.MockCompiler) // Map test mode to actual engine mode var engineMode engines.ExecutionMode switch mode { case TestGlobalMode: engineMode = engines.GlobalMode case TestApplicationMode: engineMode = engines.ApplicationMode case TestMixedMode: engineMode = engines.ApplicationMode } engine, err := engines.NewComputeExecutionEngine( logger, mockHG, mockKeyManager, mockInclusionProver, mockBulletproofProver, mockVerEnc, mockDecaf, mockCompiler, engineMode, ) require.NoError(t, err) // Set up mocks setupComputeMocks(t, mockHG, mockInclusionProver, mockBulletproofProver, engineMode) setupTokenIntrinsicMocks(t, mockHG) // Generate keys for metadata readKey := make([]byte, 57) writeKey := make([]byte, 57) rand.Read(readKey) rand.Read(writeKey) // Perform deployment with the same keys domain := performDeploymentWithKeys(t, engine, mockHG, mockCompiler, readKey, writeKey, engineMode) // Set up compute metadata setupComputeMetadata(t, mockHG, domain, readKey, writeKey) // Create operations with different execution contexts ops := []*compute.ExecuteOperation{ { Application: compute.Application{ Address: []byte{0x00, 0x01, 0x06, 0x01}, ExecutionContext: compute.ExecutionContextIntrinsic, }, Identifier: []byte("op1"), Dependencies: [][]byte{}, }, { Application: compute.Application{ Address: hgstate.VertexAddsDiscriminator, ExecutionContext: compute.ExecutionContextHypergraph, }, Identifier: []byte("op2"), Dependencies: [][]byte{[]byte("op1")}, }, { Application: compute.Application{ Address: makeExtrinsicAddress("extrinsic_app"), ExecutionContext: compute.ExecutionContextExtrinsic, }, Identifier: []byte("op3"), Dependencies: [][]byte{[]byte("op2")}, }, } msg, _ := createTestCodeExecuteMessage(t, mockHG, domain, ops) // Process message state := hgstate.NewHypergraphState(mockHG) msgs, err := engine.ProcessMessage(1, big.NewInt(0), msg.Address, msg.Payload, state) assertCodeExecutionResult(t, mode, msgs, err, false) }) }) // Test 33: Code not deployed execution fails t.Run("code_not_deployed_execution_fails", func(t *testing.T) { runTestWithAllModes(t, "code_not_deployed_execution_fails", func(t *testing.T, mode TestExecutionMode) { logger := zap.NewNop() mockInclusionProver := new(mocks.MockInclusionProver) mockInclusionProver.On("CommitRaw", mock.Anything, mock.Anything).Return(make([]byte, 74), nil) mockHG := tests.CreateHypergraphWithInclusionProver(mockInclusionProver) mockHG.On("Commit").Return(map[tries.ShardKey][][]byte{}).Maybe() mockHG.On("TrackChange", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil).Maybe() mockHG.On("GetCoveredPrefix").Return([]int{}, nil) mockKeyManager := new(mocks.MockKeyManager) mockBulletproofProver := new(mocks.MockBulletproofProver) mockVerEnc := new(mocks.MockVerifiableEncryptor) mockDecaf := new(mocks.MockDecafConstructor) mockCompiler := new(mocks.MockCompiler) // Map test mode to actual engine mode var engineMode engines.ExecutionMode switch mode { case TestGlobalMode: engineMode = engines.GlobalMode case TestApplicationMode: engineMode = engines.ApplicationMode case TestMixedMode: engineMode = engines.ApplicationMode } engine, err := engines.NewComputeExecutionEngine( logger, mockHG, mockKeyManager, mockInclusionProver, mockBulletproofProver, mockVerEnc, mockDecaf, mockCompiler, engineMode, ) require.NoError(t, err) // Set up compute metadata with test keys (Ed448 keys are 57 bytes) readKey := make([]byte, 57) writeKey := make([]byte, 57) rand.Read(readKey) rand.Read(writeKey) domain := make([]byte, 32) rand.Read(domain) // Set up compute metadata metadataAddress := slices.Concat(domain, bytes.Repeat([]byte{0xff}, 32)) rdfSchema := `BASE PREFIX rdf: PREFIX rdfs: PREFIX qcl: PREFIX req: req:Request a rdfs:Class. req:A a rdfs:Property; rdfs:domain qcl:Uint; qcl:size 1; qcl:order 0; rdfs:range req:Request. ` // Valid RDF schema for test err = tests.SetHypergraphComputeMetadataData( mockHG, metadataAddress, rdfSchema, nil, // creator not needed for test readKey, writeKey, ) require.NoError(t, err) // Set up mocks - no deployment performed mockBulletproofProver.On("SimpleVerify", mock.Anything, mock.Anything, mock.Anything).Return(true) mockHG.On("GetVertexData", mock.Anything, mock.Anything, mock.Anything).Return(nil, fmt.Errorf("code not found")) // Mock GetVertex for any address (needed for code execution operations) mockHG.On("GetVertex", mock.Anything).Return(nil, store.ErrNotFound).Maybe() // Add mocks for app mode mockInclusionProver.On("CommitRaw", mock.Anything, mock.Anything).Return(make([]byte, 74), nil).Maybe() mockMultiproof := &mocks.MockMultiproof{} mockMultiproof.On("FromBytes", mock.Anything).Return(nil).Maybe() mockInclusionProver.On("NewMultiproof").Return(mockMultiproof, nil).Maybe() // Add transaction mocks for verify operation txn := &mockTransaction{} mockHG.On("NewTransaction", false).Return(txn, nil).Maybe() mockHG.On("GetProver").Return(mockInclusionProver).Maybe() mockHG.On("Commit").Return(map[tries.ShardKey][][]byte{}).Maybe() mockHG.On("AddVertex", mock.Anything, mock.Anything).Return(nil).Maybe() mockHG.On("SetVertexData", mock.Anything, mock.Anything, mock.Anything).Return(nil).Maybe() // Create operation referencing non-deployed code ops := []*compute.ExecuteOperation{ { Application: compute.Application{ Address: makeExtrinsicAddress("non_deployed_app"), ExecutionContext: compute.ExecutionContextExtrinsic, }, Identifier: []byte("op1"), Dependencies: [][]byte{}, }, } msg, _ := createTestCodeExecuteMessage(t, mockHG, domain, ops) // Process message should fail state := hgstate.NewHypergraphState(mockHG) msgs, err := engine.ProcessMessage(1, big.NewInt(0), msg.Address, msg.Payload, state) assert.Error(t, err) // Different error messages in different modes if engineMode == engines.GlobalMode { assert.Contains(t, err.Error(), "non-deploy messages not allowed in global mode") } else { assert.Contains(t, err.Error(), "not found") } assert.Nil(t, msgs) }) }) // Test 34: Input types validation from deployment t.Run("input_types_validation_from_deployment", func(t *testing.T) { runTestWithAllModes(t, "input_types_validation_from_deployment", func(t *testing.T, mode TestExecutionMode) { logger := zap.NewNop() mockInclusionProver := new(mocks.MockInclusionProver) mockInclusionProver.On("CommitRaw", mock.Anything, mock.Anything).Return(make([]byte, 74), nil) mockHG := tests.CreateHypergraphWithInclusionProver(mockInclusionProver) mockHG.On("Commit").Return(map[tries.ShardKey][][]byte{}).Maybe() mockHG.On("TrackChange", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil).Maybe() mockHG.On("GetCoveredPrefix").Return([]int{}, nil) mockKeyManager := new(mocks.MockKeyManager) mockBulletproofProver := new(mocks.MockBulletproofProver) mockVerEnc := new(mocks.MockVerifiableEncryptor) mockDecaf := new(mocks.MockDecafConstructor) mockCompiler := new(mocks.MockCompiler) // Map test mode to actual engine mode var engineMode engines.ExecutionMode switch mode { case TestGlobalMode: engineMode = engines.GlobalMode case TestApplicationMode: engineMode = engines.ApplicationMode case TestMixedMode: engineMode = engines.ApplicationMode } engine, err := engines.NewComputeExecutionEngine( logger, mockHG, mockKeyManager, mockInclusionProver, mockBulletproofProver, mockVerEnc, mockDecaf, mockCompiler, engineMode, ) require.NoError(t, err) // Set up compute metadata with test keys (Ed448 keys are 57 bytes) readKey := make([]byte, 57) writeKey := make([]byte, 57) rand.Read(readKey) rand.Read(writeKey) domain := make([]byte, 32) rand.Read(domain) // Set up compute metadata metadataAddress := slices.Concat(domain, bytes.Repeat([]byte{0xff}, 32)) rdfSchema := `BASE PREFIX rdf: PREFIX rdfs: PREFIX qcl: PREFIX req: req:Request a rdfs:Class. req:A a rdfs:Property; rdfs:domain qcl:Uint; qcl:size 1; qcl:order 0; rdfs:range req:Request. ` // Valid RDF schema for test err = tests.SetHypergraphComputeMetadataData( mockHG, metadataAddress, rdfSchema, nil, // creator not needed for test readKey, writeKey, ) require.NoError(t, err) // Set up mocks txn := &mockTransaction{} mockHG.On("NewTransaction", false).Return(txn, nil) mockHG.On("GetProver").Return(mockInclusionProver) mockInclusionProver.On("CommitRaw", mock.Anything, mock.Anything).Return(make([]byte, 74), nil) mockMultiproof := &mocks.MockMultiproof{} mockMultiproof.On("FromBytes", mock.Anything).Return(nil).Maybe() mockInclusionProver.On("NewMultiproof").Return(mockMultiproof, nil).Maybe() mockHG.On("Commit").Return(map[tries.ShardKey][][]byte{}).Maybe() mockHG.On("AddVertex", mock.Anything, mock.Anything).Return(nil) mockHG.On("GetVertex", mock.Anything).Return(&mockVertex{}, nil) // Set up mock for deployed code retrieval // The test is using "typed_app" as the code address code := &tries.VectorCommitmentTree{} code.Insert([]byte{0}, []byte("circuit"), nil, big.NewInt(7)) mockHG.On("GetVertexData", mock.MatchedBy(func(addr [64]byte) bool { // Check if the address ends with "typed_app" codeAddrPart := string(bytes.TrimRight(addr[32:], "\x00")) return codeAddrPart == "typed_app" })).Return(code, nil) mockHG.On("GetVertexData", mock.Anything).Return(&tries.VectorCommitmentTree{}, nil) mockHG.On("SetVertexData", mock.Anything, mock.Anything, mock.Anything).Return(nil) mockBulletproofProver.On("SimpleVerify", mock.Anything, mock.Anything, mock.Anything).Return(true) // Perform deployment with specific input types performDeployment(t, engine, mockHG, mockCompiler, engineMode) ops := []*compute.ExecuteOperation{ { Application: compute.Application{ Address: makeExtrinsicAddress("typed_app"), ExecutionContext: compute.ExecutionContextExtrinsic, }, Identifier: []byte("op1"), Dependencies: [][]byte{}, }, } msg, _ := createTestCodeExecuteMessage(t, mockHG, domain, ops) // Process message state := hgstate.NewHypergraphState(mockHG) msgs, err := engine.ProcessMessage(1, big.NewInt(0), msg.Address, msg.Payload, state) assertCodeExecutionResult(t, mode, msgs, err, false) }) }) // Test 35: Output types validation from deployment t.Run("output_types_validation_from_deployment", func(t *testing.T) { runTestWithAllModes(t, "output_types_validation_from_deployment", func(t *testing.T, mode TestExecutionMode) { logger := zap.NewNop() mockInclusionProver := new(mocks.MockInclusionProver) mockInclusionProver.On("CommitRaw", mock.Anything, mock.Anything).Return(make([]byte, 74), nil) mockHG := tests.CreateHypergraphWithInclusionProver(mockInclusionProver) mockHG.On("Commit").Return(map[tries.ShardKey][][]byte{}).Maybe() mockHG.On("TrackChange", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil).Maybe() mockHG.On("GetCoveredPrefix").Return([]int{}, nil) mockKeyManager := new(mocks.MockKeyManager) mockBulletproofProver := new(mocks.MockBulletproofProver) mockVerEnc := new(mocks.MockVerifiableEncryptor) mockDecaf := new(mocks.MockDecafConstructor) mockCompiler := new(mocks.MockCompiler) // Map test mode to actual engine mode var engineMode engines.ExecutionMode switch mode { case TestGlobalMode: engineMode = engines.GlobalMode case TestApplicationMode: engineMode = engines.ApplicationMode case TestMixedMode: engineMode = engines.ApplicationMode } engine, err := engines.NewComputeExecutionEngine( logger, mockHG, mockKeyManager, mockInclusionProver, mockBulletproofProver, mockVerEnc, mockDecaf, mockCompiler, engineMode, ) require.NoError(t, err) // Set up compute metadata with test keys (Ed448 keys are 57 bytes) readKey := make([]byte, 57) writeKey := make([]byte, 57) rand.Read(readKey) rand.Read(writeKey) domain := make([]byte, 32) rand.Read(domain) // Set up compute metadata metadataAddress := slices.Concat(domain, bytes.Repeat([]byte{0xff}, 32)) rdfSchema := `BASE PREFIX rdf: PREFIX rdfs: PREFIX qcl: PREFIX req: req:Request a rdfs:Class. req:A a rdfs:Property; rdfs:domain qcl:Uint; qcl:size 1; qcl:order 0; rdfs:range req:Request. ` // Valid RDF schema for test err = tests.SetHypergraphComputeMetadataData( mockHG, metadataAddress, rdfSchema, nil, // creator not needed for test readKey, writeKey, ) require.NoError(t, err) // Set up mocks txn := &mockTransaction{} mockHG.On("NewTransaction", false).Return(txn, nil) mockHG.On("GetProver").Return(mockInclusionProver) mockInclusionProver.On("CommitRaw", mock.Anything, mock.Anything).Return(make([]byte, 74), nil) mockMultiproof := &mocks.MockMultiproof{} mockMultiproof.On("FromBytes", mock.Anything).Return(nil).Maybe() mockInclusionProver.On("NewMultiproof").Return(mockMultiproof, nil).Maybe() mockHG.On("Commit").Return(map[tries.ShardKey][][]byte{}).Maybe() mockHG.On("AddVertex", mock.Anything, mock.Anything).Return(nil) mockHG.On("GetVertex", mock.Anything).Return(&mockVertex{}, nil) // Set up mock for deployed code retrieval // The test is using "typed_output_app" as the code address code := &tries.VectorCommitmentTree{} code.Insert([]byte{0}, []byte("circuit"), nil, big.NewInt(7)) mockHG.On("GetVertexData", mock.MatchedBy(func(addr [64]byte) bool { // Check if the address ends with "typed_output_app" codeAddrPart := string(bytes.TrimRight(addr[32:], "\x00")) return codeAddrPart == "typed_output_app" })).Return(code, nil) mockHG.On("GetVertexData", mock.Anything).Return(&tries.VectorCommitmentTree{}, nil) mockHG.On("SetVertexData", mock.Anything, mock.Anything, mock.Anything).Return(nil) mockBulletproofProver.On("SimpleVerify", mock.Anything, mock.Anything, mock.Anything).Return(true) // Perform deployment with specific output types performDeployment(t, engine, mockHG, mockCompiler, engineMode) ops := []*compute.ExecuteOperation{ { Application: compute.Application{ Address: makeExtrinsicAddress("typed_output_app"), ExecutionContext: compute.ExecutionContextExtrinsic, }, Identifier: []byte("op1"), Dependencies: [][]byte{}, }, } msg, _ := createTestCodeExecuteMessage(t, mockHG, domain, ops) // Process message state := hgstate.NewHypergraphState(mockHG) msgs, err := engine.ProcessMessage(1, big.NewInt(0), msg.Address, msg.Payload, state) assertCodeExecutionResult(t, mode, msgs, err, false) }) }) // Test 23: Bundled messages support multiple operations atomically t.Run("bundled_messages_atomic_operations", func(t *testing.T) { runTestWithAllModes(t, "bundled_messages_atomic_operations", func(t *testing.T, mode TestExecutionMode) { logger := zap.NewNop() mockInclusionProver := new(mocks.MockInclusionProver) mockInclusionProver.On("CommitRaw", mock.Anything, mock.Anything).Return(make([]byte, 74), nil) mockHG := tests.CreateHypergraphWithInclusionProver(mockInclusionProver) mockHG.On("Commit").Return(map[tries.ShardKey][][]byte{}).Maybe() mockHG.On("TrackChange", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil).Maybe() mockHG.On("GetCoveredPrefix").Return([]int{}, nil) mockKeyManager := new(mocks.MockKeyManager) mockBulletproofProver := new(mocks.MockBulletproofProver) mockVerEnc := new(mocks.MockVerifiableEncryptor) mockDecaf := new(mocks.MockDecafConstructor) mockCompiler := new(mocks.MockCompiler) // Map test mode to actual engine mode var engineMode engines.ExecutionMode switch mode { case TestGlobalMode: engineMode = engines.GlobalMode case TestApplicationMode: engineMode = engines.ApplicationMode case TestMixedMode: engineMode = engines.ApplicationMode } engine, err := engines.NewComputeExecutionEngine( logger, mockHG, mockKeyManager, mockInclusionProver, mockBulletproofProver, mockVerEnc, mockDecaf, mockCompiler, engineMode, ) require.NoError(t, err) // Set up mocks setupComputeMocks(t, mockHG, mockInclusionProver, mockBulletproofProver, engineMode) setupTokenIntrinsicMocks(t, mockHG) // Generate keys for metadata readKey := make([]byte, 57) writeKey := make([]byte, 57) rand.Read(readKey) rand.Read(writeKey) domain := make([]byte, 32) rand.Read(domain) // Set up compute metadata metadataAddress := slices.Concat(domain, bytes.Repeat([]byte{0xff}, 32)) rdfSchema := `BASE PREFIX rdf: PREFIX rdfs: PREFIX qcl: PREFIX req: req:Request a rdfs:Class. req:A a rdfs:Property; rdfs:domain qcl:Uint; qcl:size 1; qcl:order 0; rdfs:range req:Request. ` err = tests.SetHypergraphComputeMetadataData( mockHG, metadataAddress, rdfSchema, nil, // creator not needed for test readKey, writeKey, ) require.NoError(t, err) // Create operations for bundling operations := []*compute.ExecuteOperation{ { Application: compute.Application{ Address: makeExtrinsicAddress("app_a"), ExecutionContext: compute.ExecutionContextExtrinsic, }, Identifier: []byte("op1"), Dependencies: [][]byte{}, }, { Application: compute.Application{ Address: makeExtrinsicAddress("app_b"), ExecutionContext: compute.ExecutionContextExtrinsic, }, Identifier: []byte("op2"), Dependencies: [][]byte{}, }, } // Create a bundled message that includes both deployment and execution bundledMsg := createDeployAndExecuteBundle(t, mockHG, readKey, writeKey, operations) // Process the bundled message - this should work even in Global mode // because the bundle contains both deployment and execution atomically state := hgstate.NewHypergraphState(mockHG) msgs, err := engine.ProcessMessage(1, big.NewInt(0), bundledMsg.Address, bundledMsg.Payload, state) // In global mode, this should fail because bundles bypass the // single-operation restriction, except when not including a deploy if engineMode == engines.GlobalMode { assert.Error(t, err, "Non-deploy bundled messages should not work in GlobalMode") assert.Nil(t, msgs, "Should not get responses from bundled operations") } else { assertCodeExecutionResult(t, mode, msgs, err, false) } }) }) // Test 24: Multiple bundled operations processed sequentially t.Run("bundled_multiple_operations_sequential", func(t *testing.T) { runTestWithAllModes(t, "bundled_multiple_operations_sequential", func(t *testing.T, mode TestExecutionMode) { logger := zap.NewNop() mockInclusionProver := new(mocks.MockInclusionProver) mockInclusionProver.On("CommitRaw", mock.Anything, mock.Anything).Return(make([]byte, 74), nil) mockHG := tests.CreateHypergraphWithInclusionProver(mockInclusionProver) mockHG.On("Commit").Return(map[tries.ShardKey][][]byte{}).Maybe() mockHG.On("TrackChange", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil).Maybe() mockHG.On("GetCoveredPrefix").Return([]int{}, nil) mockKeyManager := new(mocks.MockKeyManager) mockBulletproofProver := new(mocks.MockBulletproofProver) mockVerEnc := new(mocks.MockVerifiableEncryptor) mockDecaf := new(mocks.MockDecafConstructor) mockCompiler := new(mocks.MockCompiler) // Map test mode to actual engine mode var engineMode engines.ExecutionMode switch mode { case TestGlobalMode: engineMode = engines.GlobalMode case TestApplicationMode: engineMode = engines.ApplicationMode case TestMixedMode: engineMode = engines.ApplicationMode } engine, err := engines.NewComputeExecutionEngine( logger, mockHG, mockKeyManager, mockInclusionProver, mockBulletproofProver, mockVerEnc, mockDecaf, mockCompiler, engineMode, ) require.NoError(t, err) // Set up mocks setupComputeMocks(t, mockHG, mockInclusionProver, mockBulletproofProver, engineMode) setupTokenIntrinsicMocks(t, mockHG) // Generate keys for metadata readKey := make([]byte, 57) writeKey := make([]byte, 57) rand.Read(readKey) rand.Read(writeKey) domain := make([]byte, 32) rand.Read(domain) // Set up compute metadata metadataAddress := slices.Concat(domain, bytes.Repeat([]byte{0xff}, 32)) rdfSchema := `BASE PREFIX rdf: PREFIX rdfs: PREFIX qcl: PREFIX req: req:Request a rdfs:Class. req:A a rdfs:Property; rdfs:domain qcl:Uint; qcl:size 1; qcl:order 0; rdfs:range req:Request. ` // Valid RDF schema for test err = tests.SetHypergraphComputeMetadataData( mockHG, metadataAddress, rdfSchema, nil, // creator not needed for test readKey, writeKey, ) require.NoError(t, err) // Create multiple operation sets ops1 := []*compute.ExecuteOperation{ { Application: compute.Application{ Address: makeExtrinsicAddress("app_1"), ExecutionContext: compute.ExecutionContextExtrinsic, }, Identifier: []byte("op1_a"), Dependencies: [][]byte{}, }, } ops2 := []*compute.ExecuteOperation{ { Application: compute.Application{ Address: makeExtrinsicAddress("app_2"), ExecutionContext: compute.ExecutionContextExtrinsic, }, Identifier: []byte("op2_a"), Dependencies: [][]byte{}, }, } ops3 := []*compute.ExecuteOperation{ { Application: compute.Application{ Address: makeExtrinsicAddress("app_3"), ExecutionContext: compute.ExecutionContextExtrinsic, }, Identifier: []byte("op3_a"), Dependencies: [][]byte{}, }, } // Create a bundle with multiple operation sets bundledMsg := createMultiOperationBundle(t, mockHG, domain, ops1, ops2, ops3) // Process the bundled message state := hgstate.NewHypergraphState(mockHG) msgs, err := engine.ProcessMessage(1, big.NewInt(0), bundledMsg.Address, bundledMsg.Payload, state) // Verify that all operations were processed if engineMode == engines.GlobalMode { // In global mode, this will fail due to deployment requirements // but it demonstrates the bundling concept if err == nil { t.Logf("Global mode result: error=%v, responses=%d", err, len(msgs.Messages)) } else { t.Logf("Global mode result: error=%v", err) } } else { // In application mode, verify sequential processing if err == nil { assert.NotNil(t, msgs) } } }) }) } // createBundledMessage creates a message containing multiple bundled operations func createBundledMessage(t *testing.T, domain []byte, operations ...*protobufs.MessageRequest) *protobufs.Message { bundle := &protobufs.MessageBundle{ Requests: operations, } // Serialize the bundle bundleBytes, err := bundle.ToCanonicalBytes() require.NoError(t, err) // Create the message hash := sha3.Sum256(bundleBytes) require.NoError(t, err) return &protobufs.Message{ Address: domain, Hash: hash[:], Payload: bundleBytes, } } // createDeployAndExecuteBundle creates a bundle with deployment and execution operations func createDeployAndExecuteBundle(t *testing.T, mockHg *mocks.MockHypergraph, readKey, writeKey []byte, operations []*compute.ExecuteOperation) *protobufs.Message { // Create deployment payload deployArgs := &protobufs.ComputeDeploy{ Config: &protobufs.ComputeConfiguration{ ReadPublicKey: readKey, WritePublicKey: writeKey, }, RdfSchema: []byte(`BASE PREFIX rdf: PREFIX rdfs: PREFIX qcl: qcl:Application a rdfs:Class. qcl:address a rdfs:Property; rdfs:domain qcl:ByteArray; qcl:size 64; qcl:order 0; rdfs:range qcl:Application. qcl:computationSchema a rdfs:Property; rdfs:domain qcl:String; qcl:size 1024; qcl:order 1; rdfs:range qcl:Application. qcl:permittedContracts a rdfs:Property; rdfs:domain qcl:ByteArray; qcl:size 64; qcl:order 2; rdfs:range qcl:Application.`), } // Create code execute payload var domain [32]byte rand.Read(domain[:]) var rendezvous [32]byte rand.Read(rendezvous[:]) // Create valid payment transaction bytes outFees := []*big.Int{big.NewInt(1), big.NewInt(1)} total := big.NewInt(10000000) outFees = append(outFees, total) payment, err := tests.CreateValidQUILPendingTransactionPayload( mockHg, 1, [][]byte{make([]byte, 56)}, [][]byte{make([]byte, 56)}, [][]byte{make([]byte, 56)}, [][]byte{make([]byte, 56)}, []*big.Int{big.NewInt(10000002)}, []*big.Int{big.NewInt(0)}, outFees, 0, ) if err != nil { panic(err) } paymentBytes, err := payment.GetPendingTransaction().ToCanonicalBytes() ce := compute.NewCodeExecute( domain, paymentBytes, []byte("mock_secret"), rendezvous, operations, nil, nil, nil, nil, nil, nil, ) // Manually set up proof of payment (like createTestCodeExecuteMessage does) ce.ProofOfPayment[0] = paymentBytes ce.ProofOfPayment[1] = make([]byte, 112) // Schnorr signature size rand.Read(ce.ProofOfPayment[1]) // Create bundled message return createBundledMessage(t, domain[:], payment, &protobufs.MessageRequest{Request: &protobufs.MessageRequest_ComputeDeploy{ComputeDeploy: deployArgs}}, &protobufs.MessageRequest{Request: &protobufs.MessageRequest_CodeExecute{CodeExecute: ce.ToProtobuf()}}) } // createCompleteBundleWithPayment creates a bundle with payment, intrinsic deploy, code deploy, and execution func createCompleteBundleWithPayment( t *testing.T, mockHG *mocks.MockHypergraph, domain []byte, readKey, writeKey []byte, sourceCode []byte, mockCompiler *mocks.MockCompiler, operations []*compute.ExecuteOperation, ) *protobufs.Message { payloads := []*protobufs.MessageRequest{} outFees := []*big.Int{big.NewInt(1)} total := big.NewInt(10000000) outFees = append(outFees, total) payment, err := tests.CreateValidQUILPendingTransactionPayload( mockHG, 1, [][]byte{make([]byte, 56)}, [][]byte{make([]byte, 56)}, [][]byte{make([]byte, 56)}, [][]byte{make([]byte, 56)}, []*big.Int{big.NewInt(10000001)}, []*big.Int{big.NewInt(0)}, outFees, 0, ) if err != nil { panic(err) } paymentBytes, err := payment.GetPendingTransaction().ToCanonicalBytes() payloads = append(payloads, payment) // Create intrinsic deployment payload deployArgs := &protobufs.ComputeDeploy{ Config: &protobufs.ComputeConfiguration{ ReadPublicKey: readKey, WritePublicKey: writeKey, }, RdfSchema: []byte(`BASE PREFIX rdf: PREFIX rdfs: PREFIX qcl: PREFIX req: req:Request a rdfs:Class. req:A a rdfs:Property; rdfs:domain qcl:Uint; qcl:size 1; qcl:order 0; rdfs:range req:Request. `), } payloads = append(payloads, &protobufs.MessageRequest{Request: &protobufs.MessageRequest_ComputeDeploy{ComputeDeploy: deployArgs}}) // Create code deployment payload (if source code provided) if sourceCode != nil { deployment, err := compute.NewCodeDeployment( [32]byte(domain), sourceCode, [2]string{"qcl:Int", "qcl:Int"}, [2][]int{{4}, {4}}, []string{"qcl:Int"}, mockCompiler, ) require.NoError(t, err) err = deployment.Prove(1) require.NoError(t, err) payloads = append(payloads, &protobufs.MessageRequest{Request: &protobufs.MessageRequest_CodeDeploy{CodeDeploy: deployment.ToProtobuf()}}) } // Create code execution payload (if operations provided) if len(operations) > 0 { var domain [32]byte rand.Read(domain[:]) var rendezvous [32]byte rand.Read(rendezvous[:]) // Manually set up proof of payment (like createTestCodeExecuteMessage does) proofOfPayment := [2][]byte{} proofOfPayment[0] = paymentBytes proofOfPayment[1] = make([]byte, 112) // Schnorr signature size rand.Read(proofOfPayment[1]) ce := &compute.CodeExecute{ Domain: domain, Rendezvous: rendezvous, ProofOfPayment: proofOfPayment, ExecuteOperations: operations, } payloads = append(payloads, &protobufs.MessageRequest{Request: &protobufs.MessageRequest_CodeExecute{CodeExecute: ce.ToProtobuf()}}) } // Create bundled message return createBundledMessage(t, compute.COMPUTE_INTRINSIC_DOMAIN[:], payloads...) } // createMultiOperationBundle creates a bundle with multiple code execution operations func createMultiOperationBundle(t *testing.T, mockHG *mocks.MockHypergraph, domain []byte, operations ...[]*compute.ExecuteOperation) *protobufs.Message { payloads := []*protobufs.MessageRequest{} outFees := []*big.Int{big.NewInt(1)} total := big.NewInt(10000000) outFees = append(outFees, total) payment, err := tests.CreateValidQUILPendingTransactionPayload( mockHG, 1, [][]byte{make([]byte, 56)}, [][]byte{make([]byte, 56)}, [][]byte{make([]byte, 56)}, [][]byte{make([]byte, 56)}, []*big.Int{big.NewInt(10000001)}, []*big.Int{big.NewInt(0)}, outFees, 0, ) if err != nil { panic(err) } paymentBytes, err := payment.GetPendingTransaction().ToCanonicalBytes() for _, ops := range operations { var rendezvous [32]byte rand.Read(rendezvous[:]) ce := compute.NewCodeExecute( [32]byte(domain), paymentBytes, []byte("mock_secret"), rendezvous, ops, nil, nil, nil, nil, nil, nil, ) // Manually set up proof of payment (like createTestCodeExecuteMessage does) ce.ProofOfPayment[0] = paymentBytes ce.ProofOfPayment[1] = make([]byte, 112) // Schnorr signature size rand.Read(ce.ProofOfPayment[1]) payloads = append(payloads, payment, &protobufs.MessageRequest{Request: &protobufs.MessageRequest_CodeExecute{CodeExecute: ce.ToProtobuf()}}) } return createBundledMessage(t, domain[:], payloads...) } var _ hypergraph.Vertex = (*mockVertex)(nil)