Files
chains/mpcvm/fhe/handler.go
T
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

200 lines
5.3 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"
"errors"
"fmt"
"sync"
"github.com/luxfi/geth/common"
"github.com/luxfi/ids"
"github.com/luxfi/log"
"github.com/luxfi/warp"
)
const (
// Function selectors (first 4 bytes of keccak256 hash)
SelectorRequestDecryption = 0x5a6d3af9 // requestDecryption(bytes32,uint8)
SelectorRequestDecryptionCallback = 0x7b8c4d12 // requestDecryptionWithCallback(bytes32,uint8,address,bytes4)
)
var (
ErrInvalidSelector = errors.New("invalid function selector")
ErrInvalidPayload = errors.New("invalid payload format")
)
// WarpHandler processes FHE-related Warp messages from C-Chain
type WarpHandler struct {
logger log.Logger
relayer *Relayer
}
// NewWarpHandler creates a new Warp message handler for FHE decryption
func NewWarpHandler(logger log.Logger, relayer *Relayer) *WarpHandler {
return &WarpHandler{
logger: logger,
relayer: relayer,
}
}
// HandleMessage processes an incoming signed Warp envelope for FHE decryption.
// The envelope's Beam BitSetSignature is aggregated and verified against the
// canonical validator set by the node warp backend before delivery; this
// handler reads the authenticated content from env.Message.
func (h *WarpHandler) HandleMessage(ctx context.Context, env *warp.Envelope) error {
if env == nil {
return errors.New("nil message")
}
msg := &env.Message
payload := msg.Payload
if len(payload) < 4 {
return ErrInvalidPayload
}
// Extract function selector
selector := binary.BigEndian.Uint32(payload[:4])
switch selector {
case SelectorRequestDecryption:
return h.handleDecryptionRequest(ctx, msg, payload[4:])
case SelectorRequestDecryptionCallback:
return h.handleDecryptionWithCallback(ctx, msg, payload[4:])
default:
h.logger.Debug("Unknown FHE selector",
"selector", fmt.Sprintf("0x%08x", selector),
)
return ErrInvalidSelector
}
}
// handleDecryptionRequest handles a simple decryption request
func (h *WarpHandler) handleDecryptionRequest(ctx context.Context, msg *warp.Message, data []byte) error {
// Parse: ciphertextHash (32 bytes) + decryptionType (1 byte)
if len(data) < 33 {
return ErrInvalidPayload
}
ciphertextHash := common.BytesToHash(data[:32])
decryptionType := data[32]
h.logger.Info("Received decryption request",
"ciphertextHash", ciphertextHash.Hex(),
"type", decryptionType,
"sourceChain", msg.SourceChainID,
)
// Create decryption request
req := &DecryptionRequest{
RequestID: ciphertextHash,
CiphertextHash: ciphertextHash,
DecryptionType: decryptionType,
SourceChainID: msg.SourceChainID,
}
return h.relayer.SubmitRequest(ctx, req)
}
// handleDecryptionWithCallback handles a decryption request with callback
func (h *WarpHandler) handleDecryptionWithCallback(ctx context.Context, msg *warp.Message, data []byte) error {
// Parse: ciphertextHash (32 bytes) + decryptionType (1 byte) + callbackAddress (20 bytes) + callbackSelector (4 bytes)
if len(data) < 57 {
return ErrInvalidPayload
}
ciphertextHash := common.BytesToHash(data[:32])
decryptionType := data[32]
callbackAddress := common.BytesToAddress(data[33:53])
callbackSelector := binary.BigEndian.Uint32(data[53:57])
h.logger.Info("Received decryption request with callback",
"ciphertextHash", ciphertextHash.Hex(),
"type", decryptionType,
"callback", callbackAddress.Hex(),
"selector", fmt.Sprintf("0x%08x", callbackSelector),
"sourceChain", msg.SourceChainID,
)
req := &DecryptionRequest{
RequestID: ciphertextHash,
CiphertextHash: ciphertextHash,
DecryptionType: decryptionType,
SourceChainID: msg.SourceChainID,
CallbackAddress: callbackAddress,
CallbackSelector: callbackSelector,
HasCallback: true,
}
return h.relayer.SubmitRequest(ctx, req)
}
// FHEDecryptionService manages FHE decryption operations
type FHEDecryptionService struct {
logger log.Logger
// Active handlers
handlers map[ids.ID]*WarpHandler
handlersMu sync.RWMutex
// Service state
running bool
cancel context.CancelFunc
}
// NewFHEDecryptionService creates a new FHE decryption service
func NewFHEDecryptionService(logger log.Logger) *FHEDecryptionService {
return &FHEDecryptionService{
logger: logger,
handlers: make(map[ids.ID]*WarpHandler),
}
}
// Start begins the FHE decryption service
func (s *FHEDecryptionService) Start(ctx context.Context) error {
if s.running {
return errors.New("service already running")
}
_, cancel := context.WithCancel(ctx)
s.cancel = cancel
s.running = true
s.logger.Info("FHE Decryption Service started")
return nil
}
// Stop shuts down the FHE decryption service
func (s *FHEDecryptionService) Stop() error {
if !s.running {
return nil
}
if s.cancel != nil {
s.cancel()
}
s.running = false
s.logger.Info("FHE Decryption Service stopped")
return nil
}
// RegisterHandler registers a Warp handler for a specific chain
func (s *FHEDecryptionService) RegisterHandler(chainID ids.ID, handler *WarpHandler) {
s.handlersMu.Lock()
defer s.handlersMu.Unlock()
s.handlers[chainID] = handler
}
// GetHandler returns the handler for a specific chain
func (s *FHEDecryptionService) GetHandler(chainID ids.ID) (*WarpHandler, bool) {
s.handlersMu.RLock()
defer s.handlersMu.RUnlock()
handler, ok := s.handlers[chainID]
return handler, ok
}