Iroha Basics
Iroha Basics
Iroha v 1.0
(draft 18.06.2017)
1. Overview
Iroha aims to be a simple and modularized permissioned, distributed ledger platform.
2. System architecture
We consider 3 types of network participants:
client -- creates and sends transactions or queries current state. May be mobile or standalone application or peer itself.
peer -- maintains a full copy of the ledger as well as current state of accounts. Some subset of peers may be used for validation of
incoming transactions.
ordering service -- this entity is used as a external message queue. Also it is used for global ordering of transactions. We consider Kafka
as a good candidate. This is a single point of failure in a system, unless kafka is clustered.
Overall architecture can be represented as implementation of Event Sourcing + CQRS (command query responsibility segregation) patterns:
Application write interface and Application read interface
We call it Torii.
These interfaces are in fact single grpc server. It is used by clients to interact with peer through the network.
Both commands (transactions) and queries (read access) are performed through this interface.
Event Queue
We call it ordering service. Itself it should be clustered to remove single point of failure. But for development it is okay to use single kafka instanc
e.
Ordering service is in fact external messaging queue used by all peers. It is used to set global ordering for transactions.
Event Store
We call it block store. It stores ledger itself, and is managed by irohad. Every block is stored in a separate file. To preserve the order of blocks,
each block is named after ledger "height" -- simply00..01 (16 chars per filename), starting from 1. Name is encoded in hex. For every new block
new block id is assigned incrementally, thus creating new version of a ledger.
block header
pairs <public key, signature> of peers, who validated block
time when block was created
block meta
number of transactions in block
ledger version = block id = height of blockchain
global merkle root of previous block (we call it prev_hash)
global merkle root of current block
global merkle root of previous block added as leftmost leaf to the binary merkle tree of fixed size (called maximum block
size -- currently $2^{15} = 32768$)
then hashes of transactions are pushed one-by-one in the same order, as in block body
thus, maximum number of transactions in single block = $2^{15}-1=32767$ (tree becomes complete binary tree)
block body
a list of transactions
Since one peer may be connected to multiple networks (but one at a time), multiple ledgers should be stored.
db
network-1
0000000000000001
0000000000000002
0000000000000003
0000000000000004
testnet
0000000000000001
0000000000000002
To perform efficient search in block store we need indexes. Any provider of such service can be used, but we selected Redis, mainly because:
it is fast
it can be clustered
it has snapshotting and on-disk persistence, so we don't have to recreate whole index after system fail
To update indexes approach from event sourcing is used: Redis stores last applied block id. So, after new block with block_id is added to the bl
ock store, and after changes in Redis, stored block id is updated to block_id. In case of failure, it is easy to compare last block ids stored in
Redis and in block store and then, synchronize.
Event Handler
It consists of:
Application State
Currently it is implemented with postgresql. It stores current state of accounts, which is calculated after applying of all transactions from block
store.
Account creates a domain in which it can create assets. There are two type of assets: countable and uncountable. Account may have many
wallets (and many accounts may use one wallet), countable assets are stored in wallet. Uncountable assets are stored in account.
Asset can be created only inside a domain. Together with name asset can be addressed as asset_name#domain.
Entities:
Relations:
AccountHasAsset - shows that account has uncountable asset. Can be understood as "has 1 asset", example: has "has 1
credit", but details of credit are encoded in Asset->data.
AccountHasWallet - shows that account has wallet and permission for this wallet:
transfer assets from the wallet to another wallet
increase amount of assets (emission)
decrease amount of assets (remission)
DomainHasAccount - shows that account belongs to the domain, it has certain username in this domain (example: bogdan@soramit
su.co.jp) and certain permissions in this domain:
create new assets in domain
create subdomains
invite other accounts in this domain
give permissions to the account in this domain
2.3 iroha-cli
This is REPL command-line interface to communicate with irohad.
This service does not answer a question "how to connect new nodes", but answers the question "if connected nodes are online or offline".
Peer has a timer A (50-60 secs, chosen at random every round) for every other peer that is known. After timer A expiration, peer sends UDP
message "PING" and installs new timer B for 5 seconds. Other peer, that receives this message responds with "PONG" and resets its timer
A. Peer that receives "PONG" resets his timer A and removes timer B. New round begins.
After that, new peers should be connected. They issue new transaction Add Peer with their data (ip, public key, signagure) to this peer and the
first peer adds other peers to the network.
2.6 Consensus algorithm
2.7 Synchronization