Phase 14: Interoperability & Privacy enhancements New synor-bridge crate with Ethereum lock-mint bridge: - Bridge trait for generic cross-chain implementations - Vault management with daily limits and pause controls - Transfer lifecycle (pending → confirmed → minted) - Multi-relayer signature verification - Wrapped token minting (ETH → sETH, ERC20 → sERC20) - Burn-unlock flow for redemption Also fixes synor-ibc lib.rs exports and adds rand dependency. 21 tests passing for synor-bridge.
241 lines
9.3 KiB
Rust
241 lines
9.3 KiB
Rust
//! Inter-Blockchain Communication (IBC) Protocol for Synor
|
|
//!
|
|
//! This crate implements the IBC protocol for cross-chain interoperability,
|
|
//! enabling Synor to communicate with Cosmos ecosystem chains and beyond.
|
|
//!
|
|
//! # Architecture
|
|
//!
|
|
//! ```text
|
|
//! ┌─────────────────────────────────────────────────────────────────┐
|
|
//! │ IBC Protocol Stack │
|
|
//! ├─────────────────────────────────────────────────────────────────┤
|
|
//! │ ┌──────────────┐ ┌──────────────┐ ┌──────────────────────┐ │
|
|
//! │ │ Light Client │ │ Channel │ │ Connection │ │
|
|
//! │ │ Verification │ │ Management │ │ Management │ │
|
|
//! │ └──────────────┘ └──────────────┘ └──────────────────────┘ │
|
|
//! ├─────────────────────────────────────────────────────────────────┤
|
|
//! │ ┌──────────────────────────────────────────────────────────┐ │
|
|
//! │ │ Packet Relayer │ │
|
|
//! │ │ - Packet commitment │ │
|
|
//! │ │ - Acknowledgment handling │ │
|
|
//! │ │ - Timeout management │ │
|
|
//! │ └──────────────────────────────────────────────────────────┘ │
|
|
//! ├─────────────────────────────────────────────────────────────────┤
|
|
//! │ ┌──────────────────────────────────────────────────────────┐ │
|
|
//! │ │ Atomic Swaps (HTLC) │ │
|
|
//! │ │ - Hashlock verification │ │
|
|
//! │ │ - Timelock expiration │ │
|
|
//! │ │ - Cross-chain atomicity │ │
|
|
//! │ └──────────────────────────────────────────────────────────┘ │
|
|
//! └─────────────────────────────────────────────────────────────────┘
|
|
//! ```
|
|
//!
|
|
//! # IBC Handshake Flow
|
|
//!
|
|
//! ```text
|
|
//! Chain A Chain B
|
|
//! │ │
|
|
//! ├──── ConnOpenInit ─────────────►│
|
|
//! │ │
|
|
//! │◄─── ConnOpenTry ───────────────┤
|
|
//! │ │
|
|
//! ├──── ConnOpenAck ─────────────►│
|
|
//! │ │
|
|
//! │◄─── ConnOpenConfirm ───────────┤
|
|
//! │ │
|
|
//! │ ═══ Connection Established ═══ │
|
|
//! ```
|
|
//!
|
|
//! # Quick Start
|
|
//!
|
|
//! ```rust,ignore
|
|
//! use synor_ibc::{IbcHandler, IbcConfig, ClientState, ConsensusState};
|
|
//! use synor_ibc::{PortId, ChannelOrder, Timeout};
|
|
//!
|
|
//! // Create IBC handler
|
|
//! let handler = IbcHandler::new(IbcConfig::default());
|
|
//!
|
|
//! // Create a light client
|
|
//! let client_id = handler.create_client(client_state, consensus_state)?;
|
|
//!
|
|
//! // Open a connection
|
|
//! let conn_id = handler.connection_open_init(client_id, counterparty_client_id, None)?;
|
|
//!
|
|
//! // Bind a port and open a channel
|
|
//! handler.bind_port(PortId::transfer(), "transfer".to_string())?;
|
|
//! let channel_id = handler.channel_open_init(port, conn_id, counterparty_port, ChannelOrder::Unordered, "ics20-1".to_string())?;
|
|
//!
|
|
//! // Send a packet
|
|
//! let sequence = handler.send_packet(port, channel, data, Timeout::height(1000))?;
|
|
//! ```
|
|
|
|
#![allow(dead_code)]
|
|
|
|
// Core modules
|
|
pub mod channel;
|
|
pub mod client;
|
|
pub mod commitment;
|
|
pub mod connection;
|
|
pub mod error;
|
|
pub mod handler;
|
|
pub mod packet;
|
|
pub mod swap;
|
|
pub mod types;
|
|
|
|
// Re-exports for convenience
|
|
pub use channel::{
|
|
Channel, ChannelCounterparty, ChannelId, ChannelManager, ChannelOrder, ChannelState, PortId,
|
|
};
|
|
pub use client::{
|
|
ClientId, ClientState, ClientType, Commit, CommitSig, ConsensusState, Header, LightClient,
|
|
SignedHeader, TrustLevel, Validator, ValidatorSet,
|
|
};
|
|
pub use commitment::{
|
|
channel_path, client_state_path, connection_path, consensus_state_path, next_sequence_ack_path,
|
|
next_sequence_recv_path, next_sequence_send_path, packet_acknowledgement_path,
|
|
packet_commitment_path, packet_receipt_path, CommitmentProof, MerklePath, MerkleProof, ProofOp,
|
|
ProofOpType,
|
|
};
|
|
pub use connection::{
|
|
ConnectionEnd, ConnectionId, ConnectionManager, ConnectionState,
|
|
Counterparty as ConnectionCounterparty,
|
|
};
|
|
pub use error::{IbcError, IbcResult};
|
|
pub use handler::{IbcConfig, IbcHandler};
|
|
pub use packet::{
|
|
Acknowledgement, FungibleTokenPacketData, Packet, PacketCommitment, PacketHandler,
|
|
PacketReceipt, Timeout,
|
|
};
|
|
pub use swap::{
|
|
AtomicSwap, Hashlock, Htlc, SwapAction, SwapAsset, SwapId, SwapManager, SwapPacketData,
|
|
SwapState, Timelock,
|
|
};
|
|
pub use types::{ChainId, CommitmentPrefix, Height, Signer, Timestamp, Version};
|
|
|
|
/// IBC protocol version
|
|
pub const IBC_VERSION: &str = "1.0.0";
|
|
|
|
/// Default timeout in blocks
|
|
pub const DEFAULT_TIMEOUT_BLOCKS: u64 = 1000;
|
|
|
|
/// Default timeout in nanoseconds (1 hour)
|
|
pub const DEFAULT_TIMEOUT_NANOS: u64 = 3_600_000_000_000;
|
|
|
|
/// Maximum packet data size (1 MB)
|
|
pub const MAX_PACKET_DATA_SIZE: usize = 1024 * 1024;
|
|
|
|
/// IBC module events
|
|
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
|
pub enum IbcEvent {
|
|
/// Client created
|
|
CreateClient {
|
|
client_id: ClientId,
|
|
client_type: ClientType,
|
|
consensus_height: Height,
|
|
},
|
|
/// Client updated
|
|
UpdateClient {
|
|
client_id: ClientId,
|
|
consensus_height: Height,
|
|
},
|
|
/// Connection opened (init)
|
|
OpenInitConnection {
|
|
connection_id: ConnectionId,
|
|
client_id: ClientId,
|
|
counterparty_client_id: ClientId,
|
|
},
|
|
/// Connection opened (try)
|
|
OpenTryConnection {
|
|
connection_id: ConnectionId,
|
|
client_id: ClientId,
|
|
counterparty_connection_id: ConnectionId,
|
|
},
|
|
/// Connection opened (ack)
|
|
OpenAckConnection { connection_id: ConnectionId },
|
|
/// Connection opened (confirm)
|
|
OpenConfirmConnection { connection_id: ConnectionId },
|
|
/// Channel opened (init)
|
|
OpenInitChannel {
|
|
port_id: PortId,
|
|
channel_id: ChannelId,
|
|
connection_id: ConnectionId,
|
|
},
|
|
/// Channel opened (try)
|
|
OpenTryChannel {
|
|
port_id: PortId,
|
|
channel_id: ChannelId,
|
|
counterparty_channel_id: ChannelId,
|
|
},
|
|
/// Channel opened (ack)
|
|
OpenAckChannel {
|
|
port_id: PortId,
|
|
channel_id: ChannelId,
|
|
},
|
|
/// Channel opened (confirm)
|
|
OpenConfirmChannel {
|
|
port_id: PortId,
|
|
channel_id: ChannelId,
|
|
},
|
|
/// Channel closed
|
|
CloseChannel {
|
|
port_id: PortId,
|
|
channel_id: ChannelId,
|
|
},
|
|
/// Packet sent
|
|
SendPacket { packet: Packet },
|
|
/// Packet received
|
|
ReceivePacket { packet: Packet },
|
|
/// Packet acknowledged
|
|
AcknowledgePacket {
|
|
packet: Packet,
|
|
acknowledgement: Acknowledgement,
|
|
},
|
|
/// Packet timed out
|
|
TimeoutPacket { packet: Packet },
|
|
/// Swap initiated
|
|
SwapInitiated {
|
|
swap_id: SwapId,
|
|
initiator: String,
|
|
responder: String,
|
|
},
|
|
/// Swap completed
|
|
SwapCompleted { swap_id: SwapId },
|
|
/// Swap refunded
|
|
SwapRefunded { swap_id: SwapId },
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_chain_id() {
|
|
let chain = ChainId::new("synor-1");
|
|
assert_eq!(chain.to_string(), "synor-1");
|
|
}
|
|
|
|
#[test]
|
|
fn test_commitment_prefix() {
|
|
let prefix = CommitmentPrefix::default();
|
|
assert_eq!(prefix.key_prefix, b"ibc");
|
|
}
|
|
|
|
#[test]
|
|
fn test_height() {
|
|
let h = Height::new(1, 100);
|
|
assert_eq!(h.revision_number, 1);
|
|
assert_eq!(h.revision_height, 100);
|
|
}
|
|
|
|
#[test]
|
|
fn test_ibc_handler_creation() {
|
|
let handler = IbcHandler::default();
|
|
assert_eq!(handler.chain_id(), "synor-1");
|
|
}
|
|
|
|
#[test]
|
|
fn test_swap_manager_creation() {
|
|
let manager = SwapManager::new();
|
|
assert!(manager.get_active_swaps().is_empty());
|
|
}
|
|
}
|