Architecture¶
Siliqua consists roughly of five different components:
siliqua.wallet.WalletWallet with optional encryption that can be saved into JSON format
siliqua.network.BaseNetworkPluginNetwork provider that updates the wallet with new blocks and broadcasts unconfirmed blocks into the NANO network
-
Work provider that polls the wallet for missing proof-of-work and generates them
-
The main “server” instance that’s responsible for handling wallet, network and work providers and communication between them to keep the wallet up-to-date
-
The user interface that creates the server instance and allows the user to manage their wallet
Of these components, network, work and UI are modular and can be selected on startup using either a configuration file or command-line options. New components can be implemented by subclassing the corresponding classes and exposing them using setuptools’ entrypoint feature. For example, a new work component could be created that performs PoW generation using a 3rd party service.
Network¶
Each network server has the following queues:
siliqua.network.BaseNetworkPlugin.processed_block_queueBlocks received from the network that correspond to accounts in the wallet. The network server pushes blocks into this queue.
siliqua.network.BaseNetworkPlugin.pocketable_block_queueSend blocks that can be pocketed by accounts in the wallet. The network server pushes blocks into this queue.
siliqua.network.BaseNetworkPlugin.broadcast_block_queueBlocks created by the wallet that are pending broadcast into the network. The wallet pushes blocks into this queue indirectly by
siliqua.server.WalletServer.update().
All the queues operate as FIFO queues: oldest blocks are pushed into queues first and oldest blocks are pulled from the queues first.
siliqua.network.BaseNetworkPlugin.account_sync_statuses is a dictionary
following an account ID to siliqua.network.AccountSyncStatus mapping.
The dictionary is used to keep track of which accounts are in the wallet
and which accounts have finished synchronizing with the network.
Proof-of-work¶
Each work server consists of siliqua.work.BaseWorkPlugin.work_units dictionary
following a “work block hash” to siliqua.work.WorkUnit mapping.
This dictionary can be accessed simultaneously by the wallet and the work server
itself. To prevent race conditions, the lock siliqua.work.BaseWorkPlugin.work_lock
is used whenever the dictionary is accessed.
User interface¶
Each user interface plugin must override the following methods:
-
Returns either a
click.Groupinstance if the user interface consists of multiple commands or aclick.Commandif the user interface only consists of a single command. Multiple command approach is used by the referencestdiocommand-line implementation, while single command approach would be ideal for graphical user interfaces. -
Takes a
siliqua.server.WalletServerinstance and aclick.Contextinstance and is responsible for starting the user interface. Thesiliqua.server.WalletServermight be missing some components, so the method is responsible for either prompting the user to configure the application or report an error due to insufficient configuration.