Files
node/vms/chainadapter/adapters_extended.go
T
Hanzo DevandGitHub 09a4d1343d chore(node): kill subnet — chain/network vocabulary across node (#116)
* feat(platformvm): CreateSovereignL1Tx — single-tx sovereign L1 launch

Adds a new platformvm tx type that atomically registers a sovereign L1
in one P-chain commit. Replaces what is today the four-step flow:

  CreateNetworkTx + AddChainValidatorTx ×N + CreateChainTx ×K + ConvertNetworkToL1Tx

with one signed tx. After commit, the primary network has a permanent
record of the L1's network ID + initial validator set + chain manifest
+ on-chain validator-manager contract — but it does NOT track-chains
or validate the L1's blocks. The L1 runs its own consensus from
genesis. L2/L3/L4 follow the same pattern recursively.

Type shape:

  type CreateSovereignL1Tx struct {
    BaseTx
    Owner           fx.Owner                       // CreateNetworkTx parity
    Validators      []*ConvertNetworkToL1Validator // genesis validator set
    Chains          []*SovereignL1Chain            // VM ID + genesis blob per chain
    ManagerChainIdx uint32                         // index into Chains[]
    ManagerAddress  types.JSONByteSlice            // validator-manager contract
  }

  type SovereignL1Chain struct {
    BlockchainName string
    VMID           ids.ID
    FxIDs          []ids.ID
    GenesisData    []byte
  }

SyntacticVerify enforces:
  - at least one validator (sorted, unique)
  - at least one chain, ≤ MaxSovereignL1Chains (16)
  - ManagerChainIdx is in range of Chains[]
  - ManagerAddress ≤ MaxChainAddressLength
  - per-chain name + VMID + FxIDs + genesis bounds
  - BaseTx + Owner + each Validator each verify

Wired into:
  - Visitor interface
  - codec (registered as the next tx type after ConvertNetworkToL1Tx)
  - signer + complexity + metrics + executor stubs across all visitor
    implementations

Executor body is stubbed with a TODO. The atomic state transition
(mint new networkID from tx hash, seed validator-manager state,
register each Chain, charge fee) lands in a follow-up PR. This PR is
the type definition + interface plumbing so downstream tools (wallet,
CLI, fee calc, metrics) can target the tx type while the executor is
implemented.

* chore(node): kill subnet — chain/network vocabulary across node

Zero remaining `subnet|Subnet|SUBNET` in node Go source. Per canonical
no-subnet rule.

## Wire types (Go fields only; byte-level wire encoding unchanged)

  message/wire/types.go  TrackedSubnets    → TrackedChains
  message/wire/zap.go    same on Read/Write
  proto/p2p/p2p_zap.go   SubnetUptime alias → ChainUptime
                          (consumes luxfi/proto rename in companion PR)

## Comment scrub

  message/wire/types.go            "(chain, subnet) pair" → "(chain, network) pair"
  network/peer/handshake.go        "primary-network or subnet" → "primary-network or per-chain"
  node/node.go                     "per-subnet"   → "per-chain"
                                   "P→subnet warp" → "P→chain warp"
  genesis/builder/builder.go       "their own subnets" → "their own chains"
  vms/platformvm/client.go         dropped "subnet jargon" reference
  vms/platformvm/service.go        dropped "net / subnet jargon" reference
  vms/platformvm/config/internal.go  "subnet-spawned blockchain" → "per-chain blockchain"

## ICPSubnet (Internet Computer adapter)

  ICPSubnet → ICPNet  (type rename — unrelated to platform subnet,
                        but still a subnet word; killed for consistency)
  map field `subnets` → `nets`

## Examples

  wallet/network/primary/examples/bootstrap-hanzo/main.go:
    --subnet-id  → --network-id (CLI flag)
    existingSubnetID local var → existingNetID
    "subnet ID" log lines → "network ID"
    "SUBNET_ID=" output → "NETWORK_ID="
    "subnet-evm VM ID" → "EVM VM ID"
    All comments rephrased.

  wallet/network/primary/examples/heartbeat-tx/main.go: one comment
    rephrase.

go.work workspace cleanup:
  - Removed ./operator/go entry (placeholder; lux/operator polyglot
    layout pending the cross-repo migration)
  - Removed ./operator entry (mid-migration; nothing to build)

Build clean. Zero `grep -rIn "subnet|Subnet" --include="*.go"` matches.
2026-05-29 21:17:44 -07:00

890 lines
28 KiB
Go

// Copyright (C) 2019-2025, Lux Industries Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package chainadapter
import (
"context"
"sync"
"time"
)
// ======== Generic EVM L1 Adapter ========
// Supports EVM-compatible L1 chains with various consensus mechanisms
type GenericEVMAdapter struct {
mu sync.RWMutex
chainID ChainID
chainName string
evmChainID uint64
config *ChainConfig
headers map[uint64]*EVMHeader
latestFinalized uint64
blockTime time.Duration
confirmations uint64
verifyMode VerificationMode
initialized bool
}
func NewGenericEVMAdapter(chainID ChainID, name string, evmID uint64, blockTime time.Duration, confs uint64, mode VerificationMode) *GenericEVMAdapter {
return &GenericEVMAdapter{
chainID: chainID,
chainName: name,
evmChainID: evmID,
headers: make(map[uint64]*EVMHeader),
blockTime: blockTime,
confirmations: confs,
verifyMode: mode,
}
}
func (a *GenericEVMAdapter) ChainID() ChainID { return a.chainID }
func (a *GenericEVMAdapter) ChainName() string { return a.chainName }
func (a *GenericEVMAdapter) VerificationMode() VerificationMode { return a.verifyMode }
func (a *GenericEVMAdapter) GetBlockTime() time.Duration { return a.blockTime }
func (a *GenericEVMAdapter) GetRequiredConfirmations() uint64 { return a.confirmations }
func (a *GenericEVMAdapter) EVMChainID() uint64 { return a.evmChainID }
func (a *GenericEVMAdapter) Initialize(config *ChainConfig) error {
a.mu.Lock()
defer a.mu.Unlock()
a.config = config
a.initialized = true
return nil
}
func (a *GenericEVMAdapter) VerifyBlockHeader(ctx context.Context, header *BlockHeader) error {
if header.ChainID != a.chainID {
return ErrChainNotSupported
}
return nil
}
func (a *GenericEVMAdapter) VerifyTransaction(ctx context.Context, proof *TxInclusionProof) error { return nil }
func (a *GenericEVMAdapter) VerifyMessage(ctx context.Context, msg *CrossChainMessage) error { return nil }
func (a *GenericEVMAdapter) VerifyEvent(ctx context.Context, event *ChainEvent) error { return nil }
func (a *GenericEVMAdapter) GetLatestFinalizedBlock(ctx context.Context) (uint64, error) {
a.mu.RLock()
defer a.mu.RUnlock()
return a.latestFinalized, nil
}
func (a *GenericEVMAdapter) IsFinalized(ctx context.Context, block uint64) (bool, error) {
a.mu.RLock()
defer a.mu.RUnlock()
return block <= a.latestFinalized, nil
}
func (a *GenericEVMAdapter) GetValidatorSet(ctx context.Context) (*ValidatorSet, error) { return nil, nil }
func (a *GenericEVMAdapter) Close() error {
a.mu.Lock()
defer a.mu.Unlock()
a.headers = nil
a.initialized = false
return nil
}
// ======== ZK Rollup Adapter ========
// For zkSync, Starknet, Scroll, Linea, Polygon zkEVM
type ZKRollupAdapter struct {
mu sync.RWMutex
chainID ChainID
chainName string
evmChainID uint64
config *ChainConfig
batches map[uint64]*ZKBatch
latestVerified uint64
blockTime time.Duration
proofSystem string // "plonk", "stark", "groth16"
initialized bool
}
type ZKBatch struct {
BatchNumber uint64 `json:"batchNumber"`
L1BlockNumber uint64 `json:"l1BlockNumber"`
StateRoot [32]byte `json:"stateRoot"`
TxRoot [32]byte `json:"txRoot"`
ProofHash [32]byte `json:"proofHash"`
Verified bool `json:"verified"`
}
func NewZKRollupAdapter(chainID ChainID, name string, evmID uint64, proofSystem string) *ZKRollupAdapter {
return &ZKRollupAdapter{
chainID: chainID,
chainName: name,
evmChainID: evmID,
batches: make(map[uint64]*ZKBatch),
blockTime: 2 * time.Second,
proofSystem: proofSystem,
}
}
func (a *ZKRollupAdapter) ChainID() ChainID { return a.chainID }
func (a *ZKRollupAdapter) ChainName() string { return a.chainName }
func (a *ZKRollupAdapter) VerificationMode() VerificationMode { return ModeZKProof }
func (a *ZKRollupAdapter) GetBlockTime() time.Duration { return a.blockTime }
func (a *ZKRollupAdapter) GetRequiredConfirmations() uint64 { return 1 }
func (a *ZKRollupAdapter) EVMChainID() uint64 { return a.evmChainID }
func (a *ZKRollupAdapter) Initialize(config *ChainConfig) error {
a.mu.Lock()
defer a.mu.Unlock()
a.config = config
a.initialized = true
return nil
}
func (a *ZKRollupAdapter) VerifyBlockHeader(ctx context.Context, header *BlockHeader) error {
if header.ChainID != a.chainID {
return ErrChainNotSupported
}
// Verify ZK proof has been validated on L1
return nil
}
func (a *ZKRollupAdapter) VerifyTransaction(ctx context.Context, proof *TxInclusionProof) error { return nil }
func (a *ZKRollupAdapter) VerifyMessage(ctx context.Context, msg *CrossChainMessage) error { return nil }
func (a *ZKRollupAdapter) VerifyEvent(ctx context.Context, event *ChainEvent) error { return nil }
func (a *ZKRollupAdapter) GetLatestFinalizedBlock(ctx context.Context) (uint64, error) {
a.mu.RLock()
defer a.mu.RUnlock()
return a.latestVerified, nil
}
func (a *ZKRollupAdapter) IsFinalized(ctx context.Context, block uint64) (bool, error) {
a.mu.RLock()
defer a.mu.RUnlock()
return block <= a.latestVerified, nil
}
func (a *ZKRollupAdapter) GetValidatorSet(ctx context.Context) (*ValidatorSet, error) { return nil, nil }
func (a *ZKRollupAdapter) Close() error {
a.mu.Lock()
defer a.mu.Unlock()
a.batches = nil
a.initialized = false
return nil
}
// ======== Cosmos SDK Chain Adapter ========
// For Osmosis, Injective, Sei, Celestia, etc.
type CosmosSDKAdapter struct {
mu sync.RWMutex
chainID ChainID
chainName string
bech32Prefix string
config *ChainConfig
blocks map[uint64]*CosmosSDKBlock
validators []*CosmosSDKValidator
latestFinalized uint64
blockTime time.Duration
initialized bool
}
type CosmosSDKBlock struct {
Height uint64 `json:"height"`
Hash [32]byte `json:"hash"`
AppHash [32]byte `json:"appHash"`
ValidatorsHash [32]byte `json:"validatorsHash"`
Timestamp uint64 `json:"timestamp"`
Signatures [][]byte `json:"signatures"`
}
type CosmosSDKValidator struct {
Address [20]byte `json:"address"`
PubKey []byte `json:"pubKey"`
VotingPower int64 `json:"votingPower"`
}
func NewCosmosSDKAdapter(chainID ChainID, name, prefix string, blockTime time.Duration) *CosmosSDKAdapter {
return &CosmosSDKAdapter{
chainID: chainID,
chainName: name,
bech32Prefix: prefix,
blocks: make(map[uint64]*CosmosSDKBlock),
blockTime: blockTime,
}
}
func (a *CosmosSDKAdapter) ChainID() ChainID { return a.chainID }
func (a *CosmosSDKAdapter) ChainName() string { return a.chainName }
func (a *CosmosSDKAdapter) VerificationMode() VerificationMode { return ModeBFT }
func (a *CosmosSDKAdapter) GetBlockTime() time.Duration { return a.blockTime }
func (a *CosmosSDKAdapter) GetRequiredConfirmations() uint64 { return 1 }
func (a *CosmosSDKAdapter) Initialize(config *ChainConfig) error {
a.mu.Lock()
defer a.mu.Unlock()
a.config = config
a.initialized = true
return nil
}
func (a *CosmosSDKAdapter) VerifyBlockHeader(ctx context.Context, header *BlockHeader) error {
if header.ChainID != a.chainID {
return ErrChainNotSupported
}
// Verify Tendermint/CometBFT signatures (2/3 voting power)
return nil
}
func (a *CosmosSDKAdapter) VerifyTransaction(ctx context.Context, proof *TxInclusionProof) error { return nil }
func (a *CosmosSDKAdapter) VerifyMessage(ctx context.Context, msg *CrossChainMessage) error { return nil }
func (a *CosmosSDKAdapter) VerifyEvent(ctx context.Context, event *ChainEvent) error { return nil }
func (a *CosmosSDKAdapter) GetLatestFinalizedBlock(ctx context.Context) (uint64, error) {
a.mu.RLock()
defer a.mu.RUnlock()
return a.latestFinalized, nil
}
func (a *CosmosSDKAdapter) IsFinalized(ctx context.Context, block uint64) (bool, error) {
a.mu.RLock()
defer a.mu.RUnlock()
return block <= a.latestFinalized, nil
}
func (a *CosmosSDKAdapter) GetValidatorSet(ctx context.Context) (*ValidatorSet, error) { return nil, nil }
func (a *CosmosSDKAdapter) Close() error {
a.mu.Lock()
defer a.mu.Unlock()
a.blocks = nil
a.validators = nil
a.initialized = false
return nil
}
// ======== Bitcoin Fork Adapter ========
// For Litecoin, Bitcoin Cash, Dogecoin, etc. (PoW with SPV)
type BitcoinForkAdapter struct {
mu sync.RWMutex
chainID ChainID
chainName string
config *ChainConfig
headers map[uint64]*BitcoinHeader
headerByHash map[[32]byte]*BitcoinHeader
latestHeight uint64
blockTime time.Duration
confirmations uint64
initialized bool
}
func NewBitcoinForkAdapter(chainID ChainID, name string, blockTime time.Duration, confs uint64) *BitcoinForkAdapter {
return &BitcoinForkAdapter{
chainID: chainID,
chainName: name,
headers: make(map[uint64]*BitcoinHeader),
headerByHash: make(map[[32]byte]*BitcoinHeader),
blockTime: blockTime,
confirmations: confs,
}
}
func (a *BitcoinForkAdapter) ChainID() ChainID { return a.chainID }
func (a *BitcoinForkAdapter) ChainName() string { return a.chainName }
func (a *BitcoinForkAdapter) VerificationMode() VerificationMode { return ModeSPV }
func (a *BitcoinForkAdapter) GetBlockTime() time.Duration { return a.blockTime }
func (a *BitcoinForkAdapter) GetRequiredConfirmations() uint64 { return a.confirmations }
func (a *BitcoinForkAdapter) Initialize(config *ChainConfig) error {
a.mu.Lock()
defer a.mu.Unlock()
a.config = config
a.initialized = true
return nil
}
func (a *BitcoinForkAdapter) VerifyBlockHeader(ctx context.Context, header *BlockHeader) error {
if header.ChainID != a.chainID {
return ErrChainNotSupported
}
// Verify PoW meets difficulty target
return nil
}
func (a *BitcoinForkAdapter) VerifyTransaction(ctx context.Context, proof *TxInclusionProof) error { return nil }
func (a *BitcoinForkAdapter) VerifyMessage(ctx context.Context, msg *CrossChainMessage) error { return nil }
func (a *BitcoinForkAdapter) VerifyEvent(ctx context.Context, event *ChainEvent) error { return nil }
func (a *BitcoinForkAdapter) GetLatestFinalizedBlock(ctx context.Context) (uint64, error) {
a.mu.RLock()
defer a.mu.RUnlock()
if a.latestHeight < a.confirmations {
return 0, nil
}
return a.latestHeight - a.confirmations, nil
}
func (a *BitcoinForkAdapter) IsFinalized(ctx context.Context, block uint64) (bool, error) {
a.mu.RLock()
defer a.mu.RUnlock()
return a.latestHeight >= block+a.confirmations, nil
}
func (a *BitcoinForkAdapter) GetValidatorSet(ctx context.Context) (*ValidatorSet, error) { return nil, nil }
func (a *BitcoinForkAdapter) Close() error {
a.mu.Lock()
defer a.mu.Unlock()
a.headers = nil
a.headerByHash = nil
a.initialized = false
return nil
}
// ======== DAG Adapter ========
// For Hedera, IOTA, Kaspa (DAG-based consensus)
type DAGAdapter struct {
mu sync.RWMutex
chainID ChainID
chainName string
config *ChainConfig
vertices map[[32]byte]*DAGVertex
latestConfirmed uint64
blockTime time.Duration
consensusType string // "hashgraph", "tangle", "ghostdag"
initialized bool
}
type DAGVertex struct {
Hash [32]byte `json:"hash"`
Parents [][32]byte `json:"parents"`
Timestamp uint64 `json:"timestamp"`
Round uint64 `json:"round"`
Confirmed bool `json:"confirmed"`
}
func NewDAGAdapter(chainID ChainID, name, consensusType string, blockTime time.Duration) *DAGAdapter {
return &DAGAdapter{
chainID: chainID,
chainName: name,
vertices: make(map[[32]byte]*DAGVertex),
blockTime: blockTime,
consensusType: consensusType,
}
}
func (a *DAGAdapter) ChainID() ChainID { return a.chainID }
func (a *DAGAdapter) ChainName() string { return a.chainName }
func (a *DAGAdapter) VerificationMode() VerificationMode { return ModeDAG }
func (a *DAGAdapter) GetBlockTime() time.Duration { return a.blockTime }
func (a *DAGAdapter) GetRequiredConfirmations() uint64 { return 1 }
func (a *DAGAdapter) Initialize(config *ChainConfig) error {
a.mu.Lock()
defer a.mu.Unlock()
a.config = config
a.initialized = true
return nil
}
func (a *DAGAdapter) VerifyBlockHeader(ctx context.Context, header *BlockHeader) error {
if header.ChainID != a.chainID {
return ErrChainNotSupported
}
return nil
}
func (a *DAGAdapter) VerifyTransaction(ctx context.Context, proof *TxInclusionProof) error { return nil }
func (a *DAGAdapter) VerifyMessage(ctx context.Context, msg *CrossChainMessage) error { return nil }
func (a *DAGAdapter) VerifyEvent(ctx context.Context, event *ChainEvent) error { return nil }
func (a *DAGAdapter) GetLatestFinalizedBlock(ctx context.Context) (uint64, error) {
a.mu.RLock()
defer a.mu.RUnlock()
return a.latestConfirmed, nil
}
func (a *DAGAdapter) IsFinalized(ctx context.Context, vertex uint64) (bool, error) {
a.mu.RLock()
defer a.mu.RUnlock()
return vertex <= a.latestConfirmed, nil
}
func (a *DAGAdapter) GetValidatorSet(ctx context.Context) (*ValidatorSet, error) { return nil, nil }
func (a *DAGAdapter) Close() error {
a.mu.Lock()
defer a.mu.Unlock()
a.vertices = nil
a.initialized = false
return nil
}
// ======== Polkadot Parachain Adapter ========
type ParachainAdapter struct {
mu sync.RWMutex
chainID ChainID
chainName string
paraID uint32
config *ChainConfig
headers map[uint64]*PolkadotHeader
latestFinalized uint64
blockTime time.Duration
initialized bool
}
func NewParachainAdapter(chainID ChainID, name string, paraID uint32, blockTime time.Duration) *ParachainAdapter {
return &ParachainAdapter{
chainID: chainID,
chainName: name,
paraID: paraID,
headers: make(map[uint64]*PolkadotHeader),
blockTime: blockTime,
}
}
func (a *ParachainAdapter) ChainID() ChainID { return a.chainID }
func (a *ParachainAdapter) ChainName() string { return a.chainName }
func (a *ParachainAdapter) VerificationMode() VerificationMode { return ModeGRANDPA }
func (a *ParachainAdapter) GetBlockTime() time.Duration { return a.blockTime }
func (a *ParachainAdapter) GetRequiredConfirmations() uint64 { return 1 }
func (a *ParachainAdapter) Initialize(config *ChainConfig) error {
a.mu.Lock()
defer a.mu.Unlock()
a.config = config
a.initialized = true
return nil
}
func (a *ParachainAdapter) VerifyBlockHeader(ctx context.Context, header *BlockHeader) error {
if header.ChainID != a.chainID {
return ErrChainNotSupported
}
// Verify relay chain finality + parachain inclusion proof
return nil
}
func (a *ParachainAdapter) VerifyTransaction(ctx context.Context, proof *TxInclusionProof) error { return nil }
func (a *ParachainAdapter) VerifyMessage(ctx context.Context, msg *CrossChainMessage) error { return nil }
func (a *ParachainAdapter) VerifyEvent(ctx context.Context, event *ChainEvent) error { return nil }
func (a *ParachainAdapter) GetLatestFinalizedBlock(ctx context.Context) (uint64, error) {
a.mu.RLock()
defer a.mu.RUnlock()
return a.latestFinalized, nil
}
func (a *ParachainAdapter) IsFinalized(ctx context.Context, block uint64) (bool, error) {
a.mu.RLock()
defer a.mu.RUnlock()
return block <= a.latestFinalized, nil
}
func (a *ParachainAdapter) GetValidatorSet(ctx context.Context) (*ValidatorSet, error) { return nil, nil }
func (a *ParachainAdapter) Close() error {
a.mu.Lock()
defer a.mu.Unlock()
a.headers = nil
a.initialized = false
return nil
}
// ======== Stellar Adapter (SCP) ========
type StellarAdapter struct {
mu sync.RWMutex
config *ChainConfig
ledgers map[uint64]*StellarLedger
quorumSet *StellarQuorumSet
latestClosed uint64
initialized bool
}
type StellarLedger struct {
Sequence uint64 `json:"sequence"`
Hash [32]byte `json:"hash"`
PrevHash [32]byte `json:"prevHash"`
TxSetHash [32]byte `json:"txSetHash"`
CloseTime uint64 `json:"closeTime"`
}
type StellarQuorumSet struct {
Threshold uint32 `json:"threshold"`
Validators [][32]byte `json:"validators"`
InnerSets []*StellarQuorumSet `json:"innerSets,omitempty"`
}
func NewStellarAdapter() *StellarAdapter {
return &StellarAdapter{
ledgers: make(map[uint64]*StellarLedger),
}
}
func (a *StellarAdapter) ChainID() ChainID { return idStellar }
func (a *StellarAdapter) ChainName() string { return "Stellar" }
func (a *StellarAdapter) VerificationMode() VerificationMode { return ModeSCP }
func (a *StellarAdapter) GetBlockTime() time.Duration { return 5 * time.Second }
func (a *StellarAdapter) GetRequiredConfirmations() uint64 { return 1 }
func (a *StellarAdapter) Initialize(config *ChainConfig) error {
a.mu.Lock()
defer a.mu.Unlock()
a.config = config
a.initialized = true
return nil
}
func (a *StellarAdapter) VerifyBlockHeader(ctx context.Context, header *BlockHeader) error {
if header.ChainID != idStellar {
return ErrChainNotSupported
}
// Verify SCP federated voting
return nil
}
func (a *StellarAdapter) VerifyTransaction(ctx context.Context, proof *TxInclusionProof) error { return nil }
func (a *StellarAdapter) VerifyMessage(ctx context.Context, msg *CrossChainMessage) error { return nil }
func (a *StellarAdapter) VerifyEvent(ctx context.Context, event *ChainEvent) error { return nil }
func (a *StellarAdapter) GetLatestFinalizedBlock(ctx context.Context) (uint64, error) {
a.mu.RLock()
defer a.mu.RUnlock()
return a.latestClosed, nil
}
func (a *StellarAdapter) IsFinalized(ctx context.Context, ledger uint64) (bool, error) {
a.mu.RLock()
defer a.mu.RUnlock()
return ledger <= a.latestClosed, nil
}
func (a *StellarAdapter) GetValidatorSet(ctx context.Context) (*ValidatorSet, error) { return nil, nil }
func (a *StellarAdapter) Close() error {
a.mu.Lock()
defer a.mu.Unlock()
a.ledgers = nil
a.quorumSet = nil
a.initialized = false
return nil
}
// ======== Algorand Adapter (Pure PoS / BA*) ========
type AlgorandAdapter struct {
mu sync.RWMutex
config *ChainConfig
blocks map[uint64]*AlgorandBlock
latestRound uint64
initialized bool
}
type AlgorandBlock struct {
Round uint64 `json:"round"`
Hash [32]byte `json:"hash"`
PrevHash [32]byte `json:"prevHash"`
Seed [32]byte `json:"seed"` // VRF seed
TxnRoot [32]byte `json:"txnRoot"`
Timestamp uint64 `json:"timestamp"`
Certificate []byte `json:"certificate"` // Block certificate
}
func NewAlgorandAdapter() *AlgorandAdapter {
return &AlgorandAdapter{
blocks: make(map[uint64]*AlgorandBlock),
}
}
func (a *AlgorandAdapter) ChainID() ChainID { return idAlgorand }
func (a *AlgorandAdapter) ChainName() string { return "Algorand" }
func (a *AlgorandAdapter) VerificationMode() VerificationMode { return ModePBA }
func (a *AlgorandAdapter) GetBlockTime() time.Duration { return 3300 * time.Millisecond }
func (a *AlgorandAdapter) GetRequiredConfirmations() uint64 { return 1 }
func (a *AlgorandAdapter) Initialize(config *ChainConfig) error {
a.mu.Lock()
defer a.mu.Unlock()
a.config = config
a.initialized = true
return nil
}
func (a *AlgorandAdapter) VerifyBlockHeader(ctx context.Context, header *BlockHeader) error {
if header.ChainID != idAlgorand {
return ErrChainNotSupported
}
// Verify BA* consensus certificate
return nil
}
func (a *AlgorandAdapter) VerifyTransaction(ctx context.Context, proof *TxInclusionProof) error { return nil }
func (a *AlgorandAdapter) VerifyMessage(ctx context.Context, msg *CrossChainMessage) error { return nil }
func (a *AlgorandAdapter) VerifyEvent(ctx context.Context, event *ChainEvent) error { return nil }
func (a *AlgorandAdapter) GetLatestFinalizedBlock(ctx context.Context) (uint64, error) {
a.mu.RLock()
defer a.mu.RUnlock()
return a.latestRound, nil
}
func (a *AlgorandAdapter) IsFinalized(ctx context.Context, round uint64) (bool, error) {
a.mu.RLock()
defer a.mu.RUnlock()
return round <= a.latestRound, nil
}
func (a *AlgorandAdapter) GetValidatorSet(ctx context.Context) (*ValidatorSet, error) { return nil, nil }
func (a *AlgorandAdapter) Close() error {
a.mu.Lock()
defer a.mu.Unlock()
a.blocks = nil
a.initialized = false
return nil
}
// ======== Internet Computer Adapter (Chain Key) ========
type ICPAdapter struct {
mu sync.RWMutex
config *ChainConfig
blocks map[uint64]*ICPBlock
nets map[[32]byte]*ICPNet
latestHeight uint64
initialized bool
}
type ICPBlock struct {
Height uint64 `json:"height"`
Hash [32]byte `json:"hash"`
ParentHash [32]byte `json:"parentHash"`
StateRoot [32]byte `json:"stateRoot"`
Timestamp uint64 `json:"timestamp"`
ChainID [32]byte `json:"chainId"`
}
type ICPNet struct {
ChainID [32]byte `json:"chainId"`
PublicKey []byte `json:"publicKey"` // Threshold BLS
Nodes [][32]byte `json:"nodes"`
}
func NewICPAdapter() *ICPAdapter {
return &ICPAdapter{
blocks: make(map[uint64]*ICPBlock),
nets: make(map[[32]byte]*ICPNet),
}
}
func (a *ICPAdapter) ChainID() ChainID { return idICP }
func (a *ICPAdapter) ChainName() string { return "Internet Computer" }
func (a *ICPAdapter) VerificationMode() VerificationMode { return ModeChainKey }
func (a *ICPAdapter) GetBlockTime() time.Duration { return 1 * time.Second }
func (a *ICPAdapter) GetRequiredConfirmations() uint64 { return 1 }
func (a *ICPAdapter) Initialize(config *ChainConfig) error {
a.mu.Lock()
defer a.mu.Unlock()
a.config = config
a.initialized = true
return nil
}
func (a *ICPAdapter) VerifyBlockHeader(ctx context.Context, header *BlockHeader) error {
if header.ChainID != idICP {
return ErrChainNotSupported
}
// Verify Chain Key (threshold BLS) signature
return nil
}
func (a *ICPAdapter) VerifyTransaction(ctx context.Context, proof *TxInclusionProof) error { return nil }
func (a *ICPAdapter) VerifyMessage(ctx context.Context, msg *CrossChainMessage) error { return nil }
func (a *ICPAdapter) VerifyEvent(ctx context.Context, event *ChainEvent) error { return nil }
func (a *ICPAdapter) GetLatestFinalizedBlock(ctx context.Context) (uint64, error) {
a.mu.RLock()
defer a.mu.RUnlock()
return a.latestHeight, nil
}
func (a *ICPAdapter) IsFinalized(ctx context.Context, block uint64) (bool, error) {
a.mu.RLock()
defer a.mu.RUnlock()
return block <= a.latestHeight, nil
}
func (a *ICPAdapter) GetValidatorSet(ctx context.Context) (*ValidatorSet, error) { return nil, nil }
func (a *ICPAdapter) Close() error {
a.mu.Lock()
defer a.mu.Unlock()
a.blocks = nil
a.nets = nil
a.initialized = false
return nil
}
// ======== Monero Adapter (RingCT) ========
type MoneroAdapter struct {
mu sync.RWMutex
config *ChainConfig
blocks map[uint64]*MoneroBlock
latestHeight uint64
initialized bool
}
type MoneroBlock struct {
Height uint64 `json:"height"`
Hash [32]byte `json:"hash"`
PrevHash [32]byte `json:"prevHash"`
MinerTxHash [32]byte `json:"minerTxHash"`
Timestamp uint64 `json:"timestamp"`
Difficulty uint64 `json:"difficulty"`
Nonce uint32 `json:"nonce"`
}
func NewMoneroAdapter() *MoneroAdapter {
return &MoneroAdapter{
blocks: make(map[uint64]*MoneroBlock),
}
}
func (a *MoneroAdapter) ChainID() ChainID { return idMonero }
func (a *MoneroAdapter) ChainName() string { return "Monero" }
func (a *MoneroAdapter) VerificationMode() VerificationMode { return ModeSPV } // PoW with privacy
func (a *MoneroAdapter) GetBlockTime() time.Duration { return 2 * time.Minute }
func (a *MoneroAdapter) GetRequiredConfirmations() uint64 { return 10 }
func (a *MoneroAdapter) Initialize(config *ChainConfig) error {
a.mu.Lock()
defer a.mu.Unlock()
a.config = config
a.initialized = true
return nil
}
func (a *MoneroAdapter) VerifyBlockHeader(ctx context.Context, header *BlockHeader) error {
if header.ChainID != idMonero {
return ErrChainNotSupported
}
// Verify RandomX PoW
return nil
}
func (a *MoneroAdapter) VerifyTransaction(ctx context.Context, proof *TxInclusionProof) error { return nil }
func (a *MoneroAdapter) VerifyMessage(ctx context.Context, msg *CrossChainMessage) error { return nil }
func (a *MoneroAdapter) VerifyEvent(ctx context.Context, event *ChainEvent) error { return nil }
func (a *MoneroAdapter) GetLatestFinalizedBlock(ctx context.Context) (uint64, error) {
a.mu.RLock()
defer a.mu.RUnlock()
if a.latestHeight < 10 {
return 0, nil
}
return a.latestHeight - 10, nil
}
func (a *MoneroAdapter) IsFinalized(ctx context.Context, block uint64) (bool, error) {
a.mu.RLock()
defer a.mu.RUnlock()
return a.latestHeight >= block+10, nil
}
func (a *MoneroAdapter) GetValidatorSet(ctx context.Context) (*ValidatorSet, error) { return nil, nil }
func (a *MoneroAdapter) Close() error {
a.mu.Lock()
defer a.mu.Unlock()
a.blocks = nil
a.initialized = false
return nil
}
// ======== Tezos Adapter (Liquid PoS) ========
type TezosAdapter struct {
mu sync.RWMutex
config *ChainConfig
blocks map[uint64]*TezosBlock
bakers map[string]*TezosBaker
latestFinalized uint64
initialized bool
}
type TezosBlock struct {
Level uint64 `json:"level"`
Hash [32]byte `json:"hash"`
Predecessor [32]byte `json:"predecessor"`
Timestamp uint64 `json:"timestamp"`
Baker string `json:"baker"`
Priority int `json:"priority"`
}
type TezosBaker struct {
Address string `json:"address"`
Balance uint64 `json:"balance"`
StakingBalance uint64 `json:"stakingBalance"`
}
func NewTezosAdapter() *TezosAdapter {
return &TezosAdapter{
blocks: make(map[uint64]*TezosBlock),
bakers: make(map[string]*TezosBaker),
}
}
func (a *TezosAdapter) ChainID() ChainID { return idTezos }
func (a *TezosAdapter) ChainName() string { return "Tezos" }
func (a *TezosAdapter) VerificationMode() VerificationMode { return ModeLightClient }
func (a *TezosAdapter) GetBlockTime() time.Duration { return 15 * time.Second }
func (a *TezosAdapter) GetRequiredConfirmations() uint64 { return 2 }
func (a *TezosAdapter) Initialize(config *ChainConfig) error {
a.mu.Lock()
defer a.mu.Unlock()
a.config = config
a.initialized = true
return nil
}
func (a *TezosAdapter) VerifyBlockHeader(ctx context.Context, header *BlockHeader) error {
if header.ChainID != idTezos {
return ErrChainNotSupported
}
return nil
}
func (a *TezosAdapter) VerifyTransaction(ctx context.Context, proof *TxInclusionProof) error { return nil }
func (a *TezosAdapter) VerifyMessage(ctx context.Context, msg *CrossChainMessage) error { return nil }
func (a *TezosAdapter) VerifyEvent(ctx context.Context, event *ChainEvent) error { return nil }
func (a *TezosAdapter) GetLatestFinalizedBlock(ctx context.Context) (uint64, error) {
a.mu.RLock()
defer a.mu.RUnlock()
return a.latestFinalized, nil
}
func (a *TezosAdapter) IsFinalized(ctx context.Context, level uint64) (bool, error) {
a.mu.RLock()
defer a.mu.RUnlock()
return level <= a.latestFinalized, nil
}
func (a *TezosAdapter) GetValidatorSet(ctx context.Context) (*ValidatorSet, error) { return nil, nil }
func (a *TezosAdapter) Close() error {
a.mu.Lock()
defer a.mu.Unlock()
a.blocks = nil
a.bakers = nil
a.initialized = false
return nil
}
// (Lux/Quasar C-Chain is handled natively by the Lux node — no foreign-chain adapter needed.)