Skip to main content
TAPLE is a DLT (Distributed Ledger Technology) focused on traceability, characterized by its scalability, flexibility for deployment on different devices, and reduced resource consumption.

Overview

TAPLE Core provides a library for instantiating nodes of this DLT to create a functional network through a single structure containing all required logic. The architecture is designed around an event-driven model with multiple coordinating components.
From the source code (lib.rs:2-4): “TAPLE is a DLT focused on traceability characterized by its level of scalability, its flexibility to be employed in different devices and use cases and its reduced resource consumption, including power consumption.”

Core Components

TAPLE’s architecture consists of several key managers that coordinate through asynchronous message passing:

Node Structure

The main Node struct orchestrates all components and provides the entry point for the system:
pub struct Node<M: DatabaseManager<C>, C: DatabaseCollection> {
    notification_rx: mpsc::Receiver<Notification>,
    token: CancellationToken,
    _m: PhantomData<M>,
    _c: PhantomData<C>,
}
Source: node.rs:56-61

Component Architecture

TAPLE is built on a modular architecture with the following key components:

1. Event Manager

Manages the lifecycle of events from creation through completion. Coordinates with governance and ledger managers to process event requests.
let event_manager = EventManager::new(
    event_rx,
    governance_update_rx,
    GovernanceAPI::new(governance_tx.clone()),
    DB::new(database.clone()),
    token.clone(),
    task_tx.clone(),
    notification_tx.clone(),
    ledger_tx.clone(),
    signature_manager.get_own_identifier(),
    signature_manager.clone(),
    settings.node.digest_derivator
);
Source: node.rs:184-196

2. Ledger Manager

Responses for maintaining the distributed ledger, storing events, and managing subject state:
let ledger_manager = LedgerManager::new(
    ledger_rx,
    token.clone(),
    notification_tx.clone(),
    GovernanceAPI::new(governance_tx.clone()),
    DB::new(database.clone()),
    task_tx.clone(),
    distribution_tx,
    controller_id.clone(),
    settings.node.digest_derivator
);
Source: node.rs:198-208

3. Governance Manager

Handles governance contracts and policies that define network rules, schemas, and permissions.
let mut governance_manager = Governance::<M, C>::new(
    governance_rx,
    token.clone(),
    notification_tx.clone(),
    DB::new(database.clone()),
    governance_update_sx.clone(),
);
Source: node.rs:176-182

4. Protocol Manager

Manages the TAPLE protocol messages, routing incoming messages to appropriate handlers.
let protocol_manager = ProtocolManager::new(
    protocol_rx,
    distribution_tx.clone(),
    evaluation_tx,
    validation_tx,
    event_tx.clone(),
    approval_tx.clone(),
    ledger_tx.clone(),
    token.clone(),
    notification_tx.clone(),
);
Source: node.rs:161-174

5. Network Processor

Handles peer-to-peer networking using libp2p:
let network_manager = NetworkProcessor::new(
    settings.network.listen_addr.clone(),
    network_access_points(&settings.network.known_nodes)?,
    network_tx,
    kp.clone(),
    token.clone(),
    notification_tx.clone(),
    external_addresses(&settings.network.external_address)?,
)
.expect("Network created");
Source: node.rs:128-137

6. Evaluator Manager (Optional Feature)

Executes smart contracts to evaluate state transitions:
let evaluator_manager = EvaluatorManager::new(
    evaluation_rx,
    database.clone(),
    signature_manager.clone(),
    governance_update_sx.subscribe(),
    token.clone(),
    notification_tx.clone(),
    GovernanceAPI::new(governance_tx.clone()),
    settings.node.smartcontracts_directory.clone(),
    task_tx.clone(),
    settings.node.digest_derivator
);
Source: node.rs:232-243

7. Validation Manager (Optional Feature)

Validates events according to governance rules and cryptographic verification. Source: node.rs:273-282

8. Approval Manager (Optional Feature)

Manages the approval process for events that require explicit approval from designated approvers. Source: node.rs:246-257

9. Distribution Manager

Handles event distribution across the network to relevant nodes. Source: node.rs:259-270

Communication Pattern

All components communicate through asynchronous channels using the MpscChannel pattern:
const BUFFER_SIZE: usize = 1000;

let (event_rx, event_tx) = MpscChannel::<EventCommand, EventResponse>::new(BUFFER_SIZE);
let (ledger_rx, ledger_tx) = MpscChannel::<LedgerCommand, LedgerResponse>::new(BUFFER_SIZE);
let (governance_rx, governance_tx) = MpscChannel::<GovernanceMessage, GovernanceResponse>::new(BUFFER_SIZE);
Source: node.rs:48, 79-87
This message-passing architecture ensures loose coupling between components and enables concurrent processing of operations.

Database Layer

TAPLE uses a generic database abstraction allowing different storage backends:
pub struct Node<M: DatabaseManager<C>, C: DatabaseCollection> {
    // ...
}
The database is wrapped in an Arc for shared access across components:
let database = Arc::new(database);
Source: node.rs:115

Lifecycle Management

The node lifecycle is managed through:
  1. Initialization: Node::build() creates and wires all components
  2. Execution: Each component runs in its own tokio task
  3. Shutdown: Coordinated graceful shutdown via CancellationToken
tokio::spawn(async move {
    governance_manager.run().await;
});

tokio::spawn(async move {
    ledger_manager.run().await;
});

tokio::spawn(async move {
    event_manager.run().await;
});
Source: node.rs:298-308

Notification System

Applications receive notifications about important events through a channel:
pub async fn recv_notification(&mut self) -> Option<Notification> {
    self.notification_rx.recv().await
}
Source: node.rs:364-366
The notification buffer has a fixed size (1000). Applications must consume notifications to prevent blocking the node.

Key Design Principles

  1. Modularity: Each component has a single, well-defined responsibility
  2. Asynchronous: All operations are non-blocking using Tokio async runtime
  3. Type Safety: Strong typing with generics for database and collection types
  4. Flexibility: Feature flags allow customization of included components
  5. Scalability: Message passing architecture enables horizontal scaling

Next Steps

Governance

Learn how governance controls network behavior

Subjects

Understand subjects and their lifecycle

Events

Explore the event-driven model

Cryptography

Dive into cryptographic schemes

Build docs developers (and LLMs) love