mirror of
https://github.com/luxfi/node.git
synced 2026-07-27 03:39:39 +00:00
* 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.
890 lines
28 KiB
Go
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.)
|