Files
zeekayandHanzo Dev bbce4b6975 chains: rename thresholdvm → mpcvm (LP-134 T-Chain retirement finished)
Under LP-0130's canonical roster, chains/thresholdvm/ hosts the M-Chain
VM (MPC threshold signing). The package name "thresholdvm" was the last
piece of T-Chain nomenclature still shipping in code — legacy from the
pre-LP-134 shared-substrate design. Renamed to mpcvm/ so the package
name matches the M-Chain letter and LP-7100 spec.

- chains/thresholdvm/ → chains/mpcvm/ (dir + inner files + package decl)
- Sed-replace thresholdvm → mpcvm across .go / .md / .yml / .json / .sh
- Fee/settlement primitive references now say mpcvm
- LLM.md canonical chain roster (LP-0130) already points at mpcvm/

F-Chain runtime pieces (fhe/, protocol/tfhe_keygen/,
runtime/f_chain_adapter.go) stay under mpcvm/ for now — they consume
the same shared threshold primitives. A follow-up extract to
chains/fhevm/ can happen once F-Chain runtime graduates.

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-03 01:22:30 -07:00

276 lines
8.1 KiB
Go

// Copyright (C) 2019-2025, Lux Industries Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package fhe
import (
"context"
"encoding/binary"
"testing"
"github.com/luxfi/ids"
"github.com/luxfi/log"
"github.com/luxfi/warp"
"github.com/stretchr/testify/require"
)
func createTestWarpEnvelope(payload []byte, sourceChainID ids.ID) *warp.Envelope {
return &warp.Envelope{
Message: warp.Message{
SourceChainID: sourceChainID,
Payload: payload,
},
}
}
func TestWarpHandlerNilMessage(t *testing.T) {
require := require.New(t)
logger := log.Noop()
handler := NewWarpHandler(logger, nil)
require.NotNil(handler)
err := handler.HandleMessage(context.Background(), nil)
require.Error(err)
require.Contains(err.Error(), "nil message")
}
func TestWarpHandlerPayloadTooShort(t *testing.T) {
require := require.New(t)
logger := log.Noop()
handler := NewWarpHandler(logger, nil)
// Create a message with payload < 4 bytes
msg := createTestWarpEnvelope([]byte{0x01, 0x02, 0x03}, ids.GenerateTestID())
err := handler.HandleMessage(context.Background(), msg)
require.ErrorIs(err, ErrInvalidPayload)
}
func TestWarpHandlerUnknownSelector(t *testing.T) {
require := require.New(t)
logger := log.Noop()
handler := NewWarpHandler(logger, nil)
// Create a message with unknown selector
payload := make([]byte, 4)
binary.BigEndian.PutUint32(payload, 0xDEADBEEF) // Unknown selector
msg := createTestWarpEnvelope(payload, ids.GenerateTestID())
err := handler.HandleMessage(context.Background(), msg)
require.ErrorIs(err, ErrInvalidSelector)
}
func TestWarpHandlerDecryptionRequestPayloadTooShort(t *testing.T) {
require := require.New(t)
logger := log.Noop()
handler := NewWarpHandler(logger, nil)
// Create a message with SelectorRequestDecryption but insufficient data
// handleDecryptionRequest expects 33 bytes after selector
payload := make([]byte, 20) // 4 (selector) + 16 (insufficient)
binary.BigEndian.PutUint32(payload, SelectorRequestDecryption)
msg := createTestWarpEnvelope(payload, ids.GenerateTestID())
err := handler.HandleMessage(context.Background(), msg)
require.ErrorIs(err, ErrInvalidPayload)
}
func TestWarpHandlerDecryptionWithCallbackPayloadTooShort(t *testing.T) {
require := require.New(t)
logger := log.Noop()
handler := NewWarpHandler(logger, nil)
// Create a message with SelectorRequestDecryptionCallback but insufficient data
// handleDecryptionWithCallback expects 57 bytes after selector
payload := make([]byte, 40) // 4 (selector) + 36 (insufficient)
binary.BigEndian.PutUint32(payload, SelectorRequestDecryptionCallback)
msg := createTestWarpEnvelope(payload, ids.GenerateTestID())
err := handler.HandleMessage(context.Background(), msg)
require.ErrorIs(err, ErrInvalidPayload)
}
func TestSelectorConstants(t *testing.T) {
require := require.New(t)
// Verify selectors are distinct and non-zero
require.NotZero(SelectorRequestDecryption)
require.NotZero(SelectorRequestDecryptionCallback)
require.NotEqual(SelectorRequestDecryption, SelectorRequestDecryptionCallback)
// Verify expected values (using explicit cast for type consistency)
var selectorDecrypt uint32 = SelectorRequestDecryption
var selectorCallback uint32 = SelectorRequestDecryptionCallback
require.Equal(uint32(0x5a6d3af9), selectorDecrypt)
require.Equal(uint32(0x7b8c4d12), selectorCallback)
}
func TestFHEDecryptionServiceStartStop(t *testing.T) {
require := require.New(t)
logger := log.Noop()
service := NewFHEDecryptionService(logger)
require.NotNil(service)
// Start service
err := service.Start(context.Background())
require.NoError(err)
// Try to start again - should fail
err = service.Start(context.Background())
require.Error(err)
require.Contains(err.Error(), "already running")
// Stop service
err = service.Stop()
require.NoError(err)
// Stop again - should be idempotent
err = service.Stop()
require.NoError(err)
}
func TestFHEDecryptionServiceRegisterHandler(t *testing.T) {
require := require.New(t)
logger := log.Noop()
service := NewFHEDecryptionService(logger)
require.NotNil(service)
chainID := ids.GenerateTestID()
handler := NewWarpHandler(logger, nil)
// Register handler
service.RegisterHandler(chainID, handler)
// Get handler
got, ok := service.GetHandler(chainID)
require.True(ok)
require.Equal(handler, got)
// Get non-existent handler
_, ok = service.GetHandler(ids.GenerateTestID())
require.False(ok)
}
func TestFHEDecryptionServiceMultipleHandlers(t *testing.T) {
require := require.New(t)
logger := log.Noop()
service := NewFHEDecryptionService(logger)
// Register multiple handlers
chain1 := ids.GenerateTestID()
chain2 := ids.GenerateTestID()
handler1 := NewWarpHandler(logger, nil)
handler2 := NewWarpHandler(logger, nil)
service.RegisterHandler(chain1, handler1)
service.RegisterHandler(chain2, handler2)
// Verify each handler is registered correctly
got1, ok := service.GetHandler(chain1)
require.True(ok)
require.Equal(handler1, got1)
got2, ok := service.GetHandler(chain2)
require.True(ok)
require.Equal(handler2, got2)
}
func TestNewWarpHandler(t *testing.T) {
require := require.New(t)
logger := log.Noop()
handler := NewWarpHandler(logger, nil)
require.NotNil(handler)
require.NotNil(handler.logger)
require.Nil(handler.relayer)
}
func TestNewFHEDecryptionService(t *testing.T) {
require := require.New(t)
logger := log.Noop()
service := NewFHEDecryptionService(logger)
require.NotNil(service)
require.NotNil(service.handlers)
require.False(service.running)
}
func TestWarpHandlerDecryptionRequestWithRelayer(t *testing.T) {
require := require.New(t)
logger := log.Noop()
// Create full relayer setup
storage := NewInMemoryCiphertextStorage()
relayer := NewRelayer(logger, nil, storage, 1, ids.GenerateTestID(), ids.GenerateTestID(), nil, nil)
require.NoError(relayer.Start(context.Background()))
defer relayer.Stop()
handler := NewWarpHandler(logger, relayer)
// Create valid decryption request payload
// selector (4) + ciphertextHash (32) + decryptionType (1) = 37 bytes
payload := make([]byte, 37)
binary.BigEndian.PutUint32(payload, SelectorRequestDecryption)
copy(payload[4:36], []byte{
0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00,
0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00,
})
payload[36] = 0x01 // decryptionType
msg := createTestWarpEnvelope(payload, ids.GenerateTestID())
err := handler.HandleMessage(context.Background(), msg)
require.NoError(err)
}
func TestWarpHandlerDecryptionWithCallbackWithRelayer(t *testing.T) {
require := require.New(t)
logger := log.Noop()
// Create full relayer setup
storage := NewInMemoryCiphertextStorage()
relayer := NewRelayer(logger, nil, storage, 1, ids.GenerateTestID(), ids.GenerateTestID(), nil, nil)
require.NoError(relayer.Start(context.Background()))
defer relayer.Stop()
handler := NewWarpHandler(logger, relayer)
// Create valid decryption with callback payload
// selector (4) + ciphertextHash (32) + decryptionType (1) + callbackAddress (20) + callbackSelector (4) = 61 bytes
payload := make([]byte, 61)
binary.BigEndian.PutUint32(payload, SelectorRequestDecryptionCallback)
// ciphertextHash
copy(payload[4:36], []byte{
0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00,
0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x01,
})
payload[36] = 0x02 // decryptionType
// callbackAddress (20 bytes)
copy(payload[37:57], []byte{
0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00, 0x11,
0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
0xaa, 0xbb, 0xcc, 0xdd,
})
// callbackSelector (4 bytes)
binary.BigEndian.PutUint32(payload[57:61], 0x12345678)
msg := createTestWarpEnvelope(payload, ids.GenerateTestID())
err := handler.HandleMessage(context.Background(), msg)
require.NoError(err)
}
// TestWarpHandlerDecryptionRequestNoRelayer is skipped because the handler
// panics on nil relayer rather than returning an error gracefully.
// TestWarpHandlerDecryptionWithCallbackNoRelayer is skipped for the same reason.