mirror of
https://github.com/luxfi/node.git
synced 2026-10-30 15:24:05 +00:00
The module already called itself github.com/luxfi/node while containing no node in Go: cmd/luxd was twenty-one lines that printed the size of a few types, and the Go column of the matrix measured a VM plugin. A repo that fetches the thing it claims to be has not replaced it, so the Go sources move in — 1515 files, the daemon and everything under it — and the build reaches outside this module for nothing. Rust and C++ sit beside it unchanged and are still measured against it by the differential. That is the point of one repo: the reference implementation and the two ports are the same checkout, so parity is a thing you can run rather than a thing you assert. Verified: builds, and the closure carries no lux-private — checked at build time rather than believed. The daemon starts twelve chains on a local network (P X C Q Z A B G K M F, plus D through its plugin) and reports healthy.
351 lines
9.9 KiB
Go
351 lines
9.9 KiB
Go
// Copyright (C) 2019-2025, Lux Industries Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package warp
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
|
|
"github.com/luxfi/ids"
|
|
"github.com/luxfi/zap"
|
|
)
|
|
|
|
// TeleportVersion is the current version of the Teleport protocol
|
|
const TeleportVersion uint8 = 1
|
|
|
|
// TeleportType represents the type of cross-chain operation
|
|
type TeleportType uint8
|
|
|
|
const (
|
|
// TeleportTransfer is a standard asset transfer between chains
|
|
TeleportTransfer TeleportType = iota
|
|
// TeleportSwap is an atomic swap between chains
|
|
TeleportSwap
|
|
// TeleportLock locks assets on the source chain
|
|
TeleportLock
|
|
// TeleportUnlock unlocks assets on the destination chain
|
|
TeleportUnlock
|
|
// TeleportAttest is an attestation message (oracle data, price feeds)
|
|
TeleportAttest
|
|
// TeleportGovernance is a cross-chain governance message
|
|
TeleportGovernance
|
|
// TeleportPrivate is an encrypted private transfer
|
|
TeleportPrivate
|
|
)
|
|
|
|
var (
|
|
ErrInvalidTeleportVersion = errors.New("invalid teleport version")
|
|
ErrInvalidTeleportType = errors.New("invalid teleport type")
|
|
ErrMissingPayload = errors.New("teleport message missing payload")
|
|
)
|
|
|
|
// TeleportMessage wraps a Warp message for cross-chain bridging operations.
|
|
// This is the high-level abstraction for Teleport cross-chain messaging.
|
|
//
|
|
// Warp 1.5 supports three signature types:
|
|
// - BitSetSignature: Classical BLS (legacy)
|
|
// - CoronaSignature: Quantum-safe (recommended)
|
|
// - HybridBLSCoronaSignature: BLS+Corona hybrid (deprecated)
|
|
type TeleportMessage struct {
|
|
// Version is the Teleport protocol version
|
|
Version uint8 `serialize:"true"`
|
|
|
|
// MessageType indicates the type of cross-chain operation
|
|
MessageType TeleportType `serialize:"true"`
|
|
|
|
// SourceChainID identifies the source blockchain
|
|
SourceChainID ids.ID `serialize:"true"`
|
|
|
|
// DestChainID identifies the destination blockchain
|
|
DestChainID ids.ID `serialize:"true"`
|
|
|
|
// Nonce prevents replay attacks
|
|
Nonce uint64 `serialize:"true"`
|
|
|
|
// Payload contains the application-specific message data
|
|
// For TeleportPrivate, this should be an EncryptedWarpPayload
|
|
Payload []byte `serialize:"true"`
|
|
|
|
// Encrypted indicates whether the payload is encrypted
|
|
Encrypted bool `serialize:"true"`
|
|
}
|
|
|
|
// NewTeleportMessage creates a new Teleport message for cross-chain communication
|
|
func NewTeleportMessage(
|
|
messageType TeleportType,
|
|
sourceChainID ids.ID,
|
|
destChainID ids.ID,
|
|
nonce uint64,
|
|
payload []byte,
|
|
) *TeleportMessage {
|
|
return &TeleportMessage{
|
|
Version: TeleportVersion,
|
|
MessageType: messageType,
|
|
SourceChainID: sourceChainID,
|
|
DestChainID: destChainID,
|
|
Nonce: nonce,
|
|
Payload: payload,
|
|
Encrypted: false,
|
|
}
|
|
}
|
|
|
|
// NewPrivateTeleportMessage creates an encrypted Teleport message
|
|
func NewPrivateTeleportMessage(
|
|
sourceChainID ids.ID,
|
|
destChainID ids.ID,
|
|
nonce uint64,
|
|
payload []byte,
|
|
recipientPubKey []byte,
|
|
recipientKeyID []byte,
|
|
) (*TeleportMessage, error) {
|
|
// Encrypt the payload using ML-KEM + AES-256-GCM
|
|
encrypted, err := EncryptWarpPayload(payload, recipientPubKey, recipientKeyID)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to encrypt teleport payload: %w", err)
|
|
}
|
|
|
|
// Serialize the encrypted payload (native ZAP, wkind-tagged)
|
|
encryptedBytes := marshalEncryptedWarpPayload(encrypted)
|
|
|
|
return &TeleportMessage{
|
|
Version: TeleportVersion,
|
|
MessageType: TeleportPrivate,
|
|
SourceChainID: sourceChainID,
|
|
DestChainID: destChainID,
|
|
Nonce: nonce,
|
|
Payload: encryptedBytes,
|
|
Encrypted: true,
|
|
}, nil
|
|
}
|
|
|
|
// ToWarpMessage converts a TeleportMessage to an UnsignedMessage for signing
|
|
func (t *TeleportMessage) ToWarpMessage(networkID uint32) (*UnsignedMessage, error) {
|
|
if err := t.Validate(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Serialize the TeleportMessage as the Warp payload (native ZAP)
|
|
teleportPayload := marshalTeleportMessage(t)
|
|
|
|
return NewUnsignedMessage(networkID, t.SourceChainID, teleportPayload)
|
|
}
|
|
|
|
// ParseTeleportMessage deserializes a wkind-tagged TeleportMessage buffer.
|
|
func ParseTeleportMessage(data []byte) (*TeleportMessage, error) {
|
|
zm, err := zap.Parse(data)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
root := zm.Root()
|
|
if k := wkind(root.Uint8(offWKind)); k != wkindTeleportMessage {
|
|
return nil, fmt.Errorf("%w: %d is not a teleport message", ErrUnknownWireKind, k)
|
|
}
|
|
return parseTeleportMessage(root), nil
|
|
}
|
|
|
|
// Validate checks if the TeleportMessage is well-formed
|
|
func (t *TeleportMessage) Validate() error {
|
|
if t.Version != TeleportVersion {
|
|
return fmt.Errorf("%w: got %d, expected %d", ErrInvalidTeleportVersion, t.Version, TeleportVersion)
|
|
}
|
|
|
|
if t.MessageType > TeleportPrivate {
|
|
return fmt.Errorf("%w: %d", ErrInvalidTeleportType, t.MessageType)
|
|
}
|
|
|
|
if len(t.Payload) == 0 {
|
|
return ErrMissingPayload
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// DecryptPayload decrypts an encrypted TeleportMessage payload
|
|
func (t *TeleportMessage) DecryptPayload(recipientPrivKey []byte) ([]byte, error) {
|
|
if !t.Encrypted {
|
|
return t.Payload, nil
|
|
}
|
|
|
|
// Deserialize the encrypted payload (native ZAP, wkind-tagged)
|
|
zm, err := zap.Parse(t.Payload)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to deserialize encrypted payload: %w", err)
|
|
}
|
|
root := zm.Root()
|
|
if k := wkind(root.Uint8(offWKind)); k != wkindEncryptedWarpPayload {
|
|
return nil, fmt.Errorf("%w: %d is not an encrypted payload", ErrUnknownWireKind, k)
|
|
}
|
|
encrypted := parseEncryptedWarpPayload(root)
|
|
|
|
// Decrypt using ML-KEM
|
|
plaintext, err := encrypted.Decrypt(recipientPrivKey)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to decrypt teleport payload: %w", err)
|
|
}
|
|
|
|
return plaintext, nil
|
|
}
|
|
|
|
// String returns a human-readable representation of the TeleportMessage
|
|
func (t *TeleportMessage) String() string {
|
|
typeStr := "Unknown"
|
|
switch t.MessageType {
|
|
case TeleportTransfer:
|
|
typeStr = "Transfer"
|
|
case TeleportSwap:
|
|
typeStr = "Swap"
|
|
case TeleportLock:
|
|
typeStr = "Lock"
|
|
case TeleportUnlock:
|
|
typeStr = "Unlock"
|
|
case TeleportAttest:
|
|
typeStr = "Attest"
|
|
case TeleportGovernance:
|
|
typeStr = "Governance"
|
|
case TeleportPrivate:
|
|
typeStr = "Private"
|
|
}
|
|
|
|
encryptedStr := ""
|
|
if t.Encrypted {
|
|
encryptedStr = " [encrypted]"
|
|
}
|
|
|
|
return fmt.Sprintf("Teleport{v%d %s%s: %s -> %s, nonce=%d, payload=%d bytes}",
|
|
t.Version, typeStr, encryptedStr,
|
|
t.SourceChainID.String()[:8], t.DestChainID.String()[:8],
|
|
t.Nonce, len(t.Payload))
|
|
}
|
|
|
|
// TeleportTransferPayload represents a cross-chain asset transfer
|
|
type TeleportTransferPayload struct {
|
|
// AssetID is the asset being transferred
|
|
AssetID ids.ID `serialize:"true"`
|
|
|
|
// Amount is the quantity being transferred
|
|
Amount uint64 `serialize:"true"`
|
|
|
|
// Sender is the source address (chain-specific encoding)
|
|
Sender []byte `serialize:"true"`
|
|
|
|
// Recipient is the destination address (chain-specific encoding)
|
|
Recipient []byte `serialize:"true"`
|
|
|
|
// Fee paid for the bridge operation
|
|
Fee uint64 `serialize:"true"`
|
|
|
|
// Memo is optional metadata
|
|
Memo []byte `serialize:"true"`
|
|
}
|
|
|
|
// NewTransferPayload creates a new transfer payload for cross-chain asset transfers
|
|
func NewTransferPayload(
|
|
assetID ids.ID,
|
|
amount uint64,
|
|
sender []byte,
|
|
recipient []byte,
|
|
fee uint64,
|
|
memo []byte,
|
|
) *TeleportTransferPayload {
|
|
return &TeleportTransferPayload{
|
|
AssetID: assetID,
|
|
Amount: amount,
|
|
Sender: sender,
|
|
Recipient: recipient,
|
|
Fee: fee,
|
|
Memo: memo,
|
|
}
|
|
}
|
|
|
|
// Bytes serializes the transfer payload (native ZAP, wkind-tagged).
|
|
func (p *TeleportTransferPayload) Bytes() ([]byte, error) {
|
|
return marshalTeleportTransferPayload(p), nil
|
|
}
|
|
|
|
// ParseTransferPayload deserializes a transfer payload.
|
|
func ParseTransferPayload(data []byte) (*TeleportTransferPayload, error) {
|
|
zm, err := zap.Parse(data)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
root := zm.Root()
|
|
if k := wkind(root.Uint8(offWKind)); k != wkindTeleportTransferPayload {
|
|
return nil, fmt.Errorf("%w: %d is not a transfer payload", ErrUnknownWireKind, k)
|
|
}
|
|
return parseTeleportTransferPayload(root), nil
|
|
}
|
|
|
|
// Bytes serializes the attest payload (native ZAP, wkind-tagged).
|
|
func (p *TeleportAttestPayload) Bytes() ([]byte, error) {
|
|
return marshalTeleportAttestPayload(p), nil
|
|
}
|
|
|
|
// ParseAttestPayload deserializes an attest payload.
|
|
func ParseAttestPayload(data []byte) (*TeleportAttestPayload, error) {
|
|
zm, err := zap.Parse(data)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
root := zm.Root()
|
|
if k := wkind(root.Uint8(offWKind)); k != wkindTeleportAttestPayload {
|
|
return nil, fmt.Errorf("%w: %d is not an attest payload", ErrUnknownWireKind, k)
|
|
}
|
|
return parseTeleportAttestPayload(root), nil
|
|
}
|
|
|
|
// TeleportAttestPayload represents an attestation (oracle data)
|
|
type TeleportAttestPayload struct {
|
|
// AttestationType identifies what is being attested
|
|
AttestationType uint8 `serialize:"true"`
|
|
|
|
// Timestamp of the attestation
|
|
Timestamp uint64 `serialize:"true"`
|
|
|
|
// Data is the attestation payload (e.g., price feed, compute result)
|
|
Data []byte `serialize:"true"`
|
|
|
|
// AttesterID identifies who created the attestation
|
|
AttesterID ids.NodeID `serialize:"true"`
|
|
}
|
|
|
|
// Warp 1.5 Signature Selection
|
|
// ============================
|
|
|
|
// SignatureType indicates which signature algorithm to use
|
|
type SignatureType uint8
|
|
|
|
const (
|
|
// SigTypeBLS uses classical BLS signatures (Warp 1.0 compatibility)
|
|
SigTypeBLS SignatureType = iota
|
|
// SigTypeCorona uses quantum-safe Corona signatures (recommended)
|
|
SigTypeCorona
|
|
// SigTypeHybrid uses BLS+Corona hybrid (deprecated)
|
|
SigTypeHybrid
|
|
)
|
|
|
|
// RecommendedSignatureType returns the recommended signature type for Warp 1.5
|
|
// This is Corona (quantum-safe) by default
|
|
func RecommendedSignatureType() SignatureType {
|
|
return SigTypeCorona
|
|
}
|
|
|
|
// IsQuantumSafe returns whether the signature type provides post-quantum security
|
|
func (s SignatureType) IsQuantumSafe() bool {
|
|
return s == SigTypeCorona || s == SigTypeHybrid
|
|
}
|
|
|
|
// String returns the name of the signature type
|
|
func (s SignatureType) String() string {
|
|
switch s {
|
|
case SigTypeBLS:
|
|
return "BLS"
|
|
case SigTypeCorona:
|
|
return "Corona"
|
|
case SigTypeHybrid:
|
|
return "Hybrid"
|
|
default:
|
|
return "Unknown"
|
|
}
|
|
}
|