# Architecture of the eclair codebase Eclair is developed in [Scala](https://www.scala-lang.org/) and relies heavily on [Akka](https://akka.io/). Akka is an [actor programming](https://doc.akka.io/docs/akka/current/typed/guide/actors-intro.html?language=scala) framework similar to [Erlang](https://www.erlang.org/) for the JVM. The actor model provides a clean separation between components, allowing eclair to: 1. Isolate faults and ensure high availability 2. Scale across CPUs and machines efficiently 3. Simplify development and testing At a high-level, almost every entity is a separate, sandboxed actor: - Every peer connection is an actor instance - Every lightning channel is an actor instance - Every payment attempt is an actor instance Some actors are long-lived (e.g. lightning channels) while others are very short-lived (e.g. payment attempts). ## Top-level projects Eclair is split into three top-level projects: - `eclair-core`: core library implementing lightning - `eclair-node`: server daemon built upon `eclair-core` (exposes a Json RPC and WebSocket endpoint) - `eclair-front`: when using cluster mode, front-end server daemons handling peer connections The entry point for `eclair-core` is in `Setup.scala`, where we start the actor system, connect to `bitcoind` and create top-level actors. ## Actor system overview Here is a high-level view of the hierarchy of some of the main actors in the system: ```ascii +---------+ +-------->| Channel | | +---------+ +------+ +---------+ +---------------->| Peer |----->| Channel | | +------+ +---------+ | | +---------+ | +-------->| Channel | | +---------+ +-------------+ | Switchboard | +-------------+ | +---------+ | +-------->| Channel | | | +---------+ | +------+ +---------+ +---------------->| Peer |----->| Channel | +------+ +---------+ | +---------+ +-------->| Channel | +---------+ +----------------+ +---------------->| ChannelRelayer | | +----------------+ +---------+ | Relayer | +---------+ | +-------------+ +---------------->| NodeRelayer | +-------------+ +------------------+ +----------->| PaymentLifecycle | | +------------------+ +---------------------------+ +------------------+ +---------------->| MultiPartPaymentLifecycle |----->| PaymentLifecycle | | +---------------------------+ +------------------+ | | +------------------+ | +----------->| PaymentLifecycle | +------------------+ +------------------+ | PaymentInitiator | +------------------+ +------------------+ | +----------->| PaymentLifecycle | | | +------------------+ | +---------------------------+ +------------------+ +---------------->| MultiPartPaymentLifecycle |----->| PaymentLifecycle | +---------------------------+ +------------------+ | +------------------+ +----------->| PaymentLifecycle | +------------------+ +---------------------+ +---------------->| MultiPartPaymentFSM | | +---------------------+ +----------------+ | PaymentHandler | +----------------+ | +---------------------+ +---------------->| MultiPartPaymentFSM | +---------------------+ +----------+ | Register | +----------+ +--------+ | Router | +--------+ ``` And a short description of each actor's role: - Switchboard: creates and deletes peers - Peer: p2p connection to another lightning node (standard lightning messages described in [Bolt 1](https://github.com/lightning/bolts/blob/master/01-messaging.md)) - Channel: channel with another lightning node ([Bolt 2](https://github.com/lightning/bolts/blob/master/02-peer-protocol.md)) - Register: maps channel IDs to actors (provides a clean boundary between channel and payment components) - PaymentInitiator: entry point for sending payments - Relayer: entry point for relaying payments - PaymentHandler: entry point for receiving payments - Router: p2p gossip and the network graph ([Bolt 7](https://github.com/lightning/bolts/blob/master/07-routing-gossip.md)) Actors have two ways of communicating: - direct messages: when actors have a reference to other actors, they can exchange [direct messages](https://doc.akka.io/docs/akka/current/typed/interaction-patterns.html) - events: actors can emit events to a shared [event stream](https://doc.akka.io/docs/akka/current/event-bus.html), and other actors can register to these events ## Payment scenarios Let's dive into a few payment scenarios to show which actors are involved. ### Sending a payment When we send a payment: - we run a path-finding algorithm (`Router`) - we split the payment into smaller chunks if [MPP](https://github.com/lightning/bolts/blob/master/04-onion-routing.md#basic-multi-part-payments) is used (`MultiPartPaymentLifecycle`) - we retry with alternative routes in some failure cases and record failing channels/payments (`PaymentLifecycle`) - we add HTLCs to some of our channels ```ascii +------------------+ +---------+ +----->| PaymentLifecycle |-----+ +----->| Channel | | +------------------+ | | +---------+ +------------------+ +---------------------------+ | +------------------+ | +----------+ | +---------+ | PaymentInitiator |-------->| MultiPartPaymentLifecycle |----+----->| PaymentLifecycle |-----+----->| Register |-----+----->| Channel | +------------------+ +---------------------------+ | +------------------+ | +----------+ | +---------+ | | +------------------+ | | +---------+ | +----->| PaymentLifecycle |-----+ +----->| Channel | | +------------------+ +---------+ | | | | | +--------+ | +----->| Router |<-----------+ +--------+ ``` ### Receiving a payment When we receive a payment: - htlcs are forwarded by channels to the relayer - a payment handler compares these htlcs to our payments database - and decides to fail or fulfill them ```ascii +---------+ | Channel |-----+ +---------+ | +---------+ | +---------+ +----------------+ +----------+ | Channel |-----+----->| Relayer |----->| PaymentHandler |----->| Register | +---------+ | +---------+ +----------------+ +----------+ +---------+ | | Channel |-----+ +---------+ ``` ### Relaying a payment When we relay a payment: - htlcs are forwarded by channels to the relayer - the relayer identifies the type of relay requested and delegates work to a channel relayer or a node relayer - if a node relayer is used ([trampoline payments](https://github.com/lightning/bolts/pull/829)): - incoming htlcs are validated by a payment handler (similar to the flow to receive payments) - outgoing htlcs are sent out (similar to the flow to send payments) ```ascii +----------------+ +----------+ +---------+ +--------->| ChannelRelayer |----->| Register |----->| Channel | | +----------------+ +----------+ +---------+ +---------+ +---------+ | Channel |----->| Relayer | +---------+ +---------+ | +-------------+ +---------------------------+ +--------->| NodeRelayer |----->| MultiPartPaymentLifecycle | +-------------+ +---------------------------+ ^ | v +----------------+ | PaymentHandler | +----------------+ ``` ## Channel scenarios Let's describe some channel operations and see which actors are involved. ### Opening a channel When we open a channel: - we exchange messages with our peer - we use funds from our on-chain bitcoin wallet - we start watching on-chain transactions to ensure our peer doesn't cheat us ```ascii +------+ +---------+ +--------+ | Peer |----->| Channel |-----+----->| Wallet | +------+ +---------+ | +--------+ ^ | | +---------+ | | +----->| Watcher | +--------------+ +---------+ ``` ### Closing a channel When our peer tries to cheat: - the blockchain watcher notices it and notifies the channel - the channel publishes on-chain transactions - and we notify our peer by sending an error message ```ascii +---------+ +---------+ +------+ | Watcher |<----->| Channel |----->| Peer | +---------+ +---------+ +------+ ```