 Okay, let's start. I'm Alex from Evernim. I'm a software engineer at Evernim. And also, I'm a maintainer of Hyperledger Indie project. And today I'm going to tell you about one of the sub-projects of Indie. This is Indie Distributed Ledger. So, what do you know about Indie? For most people, Indie is all about identity. That's true. And not everyone actually realized that Indie has its own Distributed Ledger, and it has its own implementation of Distributed Ledger. And this implementation is not dependent on any other blockchain platforms, any other blockchain systems. This is really one of the Distributed Ledgers, which is part of Hyperledger. And what is important, this is BFT, PBFT-like implementation of a consensus protocol. Moreover, this implementation is in production. It's part of Sovereign Network for more than two years. And also, Indie is one of active Hyperledger projects. I mentioned Sovereign Foundation and Sovereign Networks, but there are also other deployments of Indie Network, of Indie Ledger, such as FinDi, Kiva, and so on. So, it's working for more than two years in production and has real customers and real applications working on top of this. Okay, so what we are going to discuss today. The first fall, we are going to understand why we need a public blockchain in self-sustaining identity. So, why we need a blockchain in these kind of identity solutions. Then we are going to consider what projects Hyperledger Indie Ledger consists of. And we are going to discuss the architecture of Indie Ledger, how the actual databases look like. And of course, deal with the consensus protocol. What consensus protocol Indie implements and what is specific of this protocol. Okay, so self-sustaining identity. There are other great topics describing what is areas, what is Indie, what is verifiable credentials. This is also just a very quick overview that in order to have a verifiable credentials, the issuer usually creates the issuer's claim which is signed by him. And it's issued in the form of a digital verifiable credential which is stored on the Prover's wallet and then can be presented to a verifier in an SS0 knowledge proof form. So, the question is why do we need a blockchain here, actually. But you can see some errors. And we need the blockchain because of multiple reasons. The first reason is that we need a schema for these credentials. We need to know how it looks like. We need to know what is the public key of the issuer to be used for signing this credential. We need to know whether this credential is revoked or not. We need to have a list of revocation entries, the revocation registry. So, but in general, why we need the blockchain here, why not just a database. And the answer is that we need a decentralized source of trust. And also, we would like the ledger to be public so that it means that anyone in the ecosystem, anyone in the world, should be able to read this data for identity use cases. And it's pretty important to understand what data in Indian verifiable credentials workflow is on the blockchain and what data is considered to be private and never goes to the blockchain. And again, here you all know about GDPR, about the laws in California and so on. So, the rule of thumb here that no private data is ever written to the blockchain in the ledger. But what is written then? Some public DIDs, public decentralized identifiers and the corresponding DID documents, it can be written to the blockchain, issuer's public keys, which will be used for verification of credentials. It goes to the blockchain, credential schema, and information about revocation. That's usually what we can see in the blockchain. And what is never written to the blockchain is pairwise DIDs, this peer-to-peer communication that Daniel Harman was telling about credentials itself proves it never goes to the blockchain. And of course, private keys. Okay, so in the ledger, in the distributed ledger, it consists of two projects in Hyperledger. This is IndiePlanum and IndieNode. What is the difference? IndiePlanum is a kind of general purpose project related to implementation of the consensus protocol, the ledger database, state, and so on. And IndieNode, it's built on top of this, on top of IndiePlanum. And it introduces and implements identity-related stuff, identity-related transactions. For example, if you would like to know how the schema transaction or credential definition transactions from the Indie world look like, you should go to IndieNode. But if you're interested in consensus protocols and this stuff, then you should go to IndiePlanum. In general, Indie is a ledger purpose built for identity. But from my previous explanation, it follows that, in principle, it can be used as a general purpose ledger. So, Planum is a core stuff. And you can extend Planum, implementing custom transactions because we have so-called concept of pluggable request handlers. And you can even implement your own plugins. That's actually what IndieNode does. So, it extends pluggable request handlers interfaces and implements identity-related stuff on top of the common logic within IndiePlanum. So, it's pretty important to understand that, in general, IndiePlanum can be used as a general purpose ledger. So, a brief overview of IndiePlanum and Node. It's written in Python. It depends on ZMMQ, IndieCryptor, and currently we're migrating to Ursa. And Lipsodium. It follows a modular architecture and message doing behavior. And we've been working on improving this. And also, we do care about tests in Indies. So, it has extensive test coverage. It tries to follow TDD. It has a lot of unit tests, integration tests. And also, simulation tests property-based testing is pretty important for distributed ledger and BFT-like consensus protocol. Also, we have a number of system tests and a lot of tests. And it's important to mention that we do test on real deployments of 25 Node spools which are distributed in different parts of the world, in AWS, for example. So, Plenum and the Node ledger is really tested at scale and in real environment. So, IndieLedger can be considered as a public permissioned one. So, you know, Bitcoin is about decentralized money. Ethereum is mostly about decentralized applications. And Indie is about decentralized identity. And so, why is it public? It's public because anyone can read from the ledger. And why it's permissioned? Because it's not like Bitcoin or Ethereum that anyone can, you know, join the network and participate in processing transactions. In Indie, only the specific stewards can join the network and can own and has a node which validates transactions. And also, right access to the ledger is permissioned that we have some policies strict in this. So, in the heart, we have the validator pool consisting of nodes. And this is more or less fixed number of nodes, well-defined nodes. Of course, it needs to be distributed. It needs to be owned by different so-called stewards who has a private key for this node, who does the maintenance of this node, makes sure that it's connected to all other nodes in the pool, and so on. And this validator pool, it's responsible for actual processing for requests and ordering them as part of consensus protocol. In addition to the validator pool, we may have so-called observer pool. And this is the nodes which can process read requests. The number of validator pool nodes in a validator pool is usually quite, it's not infinite because of the consensus protocol that we use. The current sovereign networks usually have about 25 nodes there. But the number of observer pools can be, we may have much more nodes there. So, the validators, as I said, they have consensus logic implemented there. That's what they do when they get a transaction, when they get a right request. They come to a consensus, what is the sequence number of these requests? In what order it should be written to the ledger? By ledger here, I mean like ledger database. So, each node replicates these databases. So, it has the same information, the same data on every node. And, yes, any other PBFT-like protocol, we have n nodes, which is equal to 3f plus 1, where f is the maximum number of crashed or unavailable or malicious nodes. And we use 0mq as a secure transport. It's TCP-based protocol. It uses authenticated encryption instead of digital signatures. And BLS signatures. It's also part of consensus protocol to be able to verify the data written to the ledger. I'm going to tell you about BLS signatures a bit more in the next slides. Okay, so let's consider how write and read requests are processed by the ledger. Write requests. So, the ledger is permissioned. So, any write request must be signed or multi-signed by the users. And we use ed255x9 digital signature here. And write request is sent to all nodes in the system, all nodes from the validator pool. And we expect to get f plus 1 equal replies to be sure that it's actually written. As for the read requests, we have only one error here. It's sufficient to send a read request to one node only, to a single node only. And the user can trust the result, the reply, because of the BLS aggregated signatures and because of the state proofs. So, we are going to talk about this in more details. And no signatures are required there. So, the ledger is public from the read request point of view. Let's talk about authentication and authorization. So, authentication as well as authorization is based on the information present on the ledger. So, as I said, every write request must be signed. And the signature is very fine against the public key, which is also present on the ledger. This public key is put there as part of DID doc or kind of information associated with the DID of the user, of the sender of the transaction, so that all the nodes can get a request and can get the associated public key from the ledger and verify the signature. And for read requests, we don't require any authentication. Anyone can read. As for authorization about whether a person is allowed to do this particular action, this is also based on the information present toward on the ledger. And we are using a role-based approach here, where for every DID, we have an associated role and also have a concept of configurable rules so that we can set for every action how many signatures of a particular role are required. And we can use or and expressions in order to set this. And this is the authorization policy which is stored in a config ledger. Read request, again, no authorization is required. Okay, now let's talk about the ledger itself as a database, which is replicated on every node. So the ledger consists of transaction log, and this is just an ordered list of all the transactions which are written to the pool. And we have a Merkle tree for the whole ledger attached. And the Merkle tree, you know, it's kind of a common structure in all the blockchains. And we have actually three databases associated with every ledger, transaction log itself, and two databases for Merkle leaves and Merkle nodes. We use TroxDB as a key value storage to store every of these data structures. And also it's worth mentioning that we have a so-called catch-up process so that if a node is lagging behind or is just started, I need to get the information, missing information to have the equal representation, the equal ledger. And this is what catch-up procedure does. All other information, all other state of the node, can be restored from the ledger. So as I mentioned, we use Merkle trees and we use consistency check just by verifying that two Merkle trees root hashes are equal, and it's a very fast and convenient way to see that two ledgers are equal during part of our consensus protocol. Also, we use state proofs or inclusion proofs to verify the results of get transaction. So if you ask for a transaction, you can verify that this data is really actually part of this Merkle tree. And it's also used during the catch-up procedure when you get the missing information from other nodes. Okay, Indy has multiple ledgers. It's not just one. So we have so-called audit ledger, and this is the ledger which actually introduces the order, ordering across all the ledgers, all other ledgers. So it can be considered as a source of blocks. Also, we have a pool ledger, and this is a ledger consisting information about the current state of the pool, what nodes are in the pool, what are the public keys, and so on. We have config ledger, and this is a ledger containing some information about, for example, validation of transactions, authorization policies, some config which all the nodes need to come to consensus. And the main ledger. The main ledger is the main ledger containing application-specific or identity-specific data. So if we consider Indy and identity use cases, then all the transactions, such as schema, cred depth, revocation, it's all part of the domain ledger. And it's worth mentioning that plugins can add new ledgers, can register and add new ledgers for their purposes. So pool ledger, in general, the current configuration of the pool consists of a block of Genesis transactions and a number of so-called node transactions associated with every node in the pool. And you can use this node transaction, for example, to add a new node or to remove a node from the pool or to edit information about this node, for example, rotate its keys. And on this example, you can see that from these four Genesis transactions and these five node transactions, you can get the current state of the pool. So it contains actually four nodes in this case. Audit ledger. So the main purpose of audit ledger is to introduce synchronization and ordering between all other ledgers. And also it can be used for external audit of data, written in multiple ledgers. Audit transaction, every audit transaction can be considered as a block associated with a sequence number and also having references to miracle tree root hashes of every ledger that it has. So just by following audit ledger, you can restore the real ordering of all the transactions and what ledger it belongs to. And also audit ledger can be used a lot in the general consensus protocol verification. It's used in restoring current primaries, for example, and some state, internal state of every node. State. So in addition to ledger, ledger database on every node, you have a concept of state. This is kind of a snapshot of the current ledger. So each ledger except audit has a state and in principle, this is a Patricia Merkel tree, very similar to how it's used in Ethereum. It's a combination of radix tree, like a keyword storage, and a Merkel tree. In other words, state maps the ordered list of transactions stored in the ledger to the current state as a dictionary, like current snapshot. We use ROXDB as a keyword storage here as well. So while it's needed, for example, we have a DID, and we have a key associated with the DID, and we can rotate this key. We can change the value. So the state will be just the current value of this key for a particular DID. So it can allow you to get the current state, which is very, which is really actually used when you process read requests, when you return replies to the clients, and when you do some verification of the data to be stored on the ledger. Now let's move to consensus protocol. As I mentioned before, India has its own implementation of a consensus protocol, and this is business default tolerant protocol. So in general, we have two types of consensus protocols. This is CFT crashful tolerant and BFT business default tolerant. In a CFT world, the nodes can be unavailable, can crash, and the protocol will still come to consensus if no more than particular number of such nodes are unavailable. But in BFT world, it's even more. The nodes can be available, but it may just behave maliciously. They can send some arbitrary data to different nodes. But if the number of these nodes is less than f, where the total number of nodes is 3f plus 1, then the protocol can still come to consensus. And you may have heard the famous story about business generals and where it came from. Okay, so Plenum, India Plenum, it has the implementation of a protocol which is called RBFT, and this is a PBFT-like consensus protocol. So you know, PBFT was probably the first practical business default tolerant protocol created in 1999 by Mikhail Kastron and Barbara Liskov. And you can consider RBFT as a multiple instances of PBFT running at the same time. And it helps to notice some malicious behavior in the network better. We are going to discuss it on the next slides. In general, PBFT-like protocols, they have better throughput and low latency than proof of work. That's why they are so good in permissioned networks. So any PBFT protocol consists of three main phases, which is called three-phase commit. And the first phase there is when a primary, and this is a leader-based, a primary-based protocol, where a primary proposes the next set of transactions to be ordered. And the primary sends a so-called prep-repair message. On other nodes, they come to agreement using prepare and commit messages. And after they got a quorum of commit messages, the transaction is considered to be ordered. It's written to the ledger and reply sent to a client. Why we have actually two phases, prepare and commit, not just one. This is because the primary can be malicious. The protocol is leader-based, and the primary can be malicious in different ways. It can be just disconnected or stopped, or it can intentionally degrade performance, or it may send some inconsistent data. In all of these cases, if other nodes notice that the primary is malicious, they need to change the primary. And this is a process which is called a view change. So in every view, we have a different primary. When we change the primary, we go to the next view. And in general, we change in plan with implemented in the same way as in original PBFT paper. We use a variant without digital signatures. And that's actually why we have multiple instances of the PBFT protocol in RBFT. That every instance has its own primary, and they all execute at the same time, calculate throughput, latency, and compare performance. And if other instances back up instances sees that the master protocol instance, which is actually the one which executes the real transactions, degrades performance, they do a view change. They change the primary. This is the reason why RBFT is better in catching this kind of behavior. In general, the view change protocol on PBFT, well, the main thing here is to make sure that all transactions that could be potentially ordered on at least one correct node should eventually be ordered on all the nodes. And this is done by letting the next primary in a new view kind of reorder all these kind of transactions, which could be potentially ordered. Okay, so the plan has a number of features which worth mentioning. The first one that every request, every transaction is ordered not one by one, because you can see that this is quite heavy process of through phase commit. And this is n square asymptotics there. So we can order a batch of transactions at once in one prep repair message, which of course improves performance a lot. And usually this is a trade-off between throughput and latency, depending on how many transactions you include in one prep repair. Also as part of our consensus protocol, we check for data consistency. So we apply all the transactions optimistically in uncommitted state, and we're making sure that the data on our node is equal to the data on the primary. If yes, we continue to order this transaction. If not, we do the view change and change the primary. And, well, in addition to just applying the data, we do this dynamic validation. For example, we validate that data is immutable, or this is a really, the user has a permission to do this action, something like this. And this verification is done against the current uncommitted state. So we apply every transaction one by one and do this verification. Also it's worth mentioning that Plenum can have multiple batches, multiple prep repairs in flight. So it can process like 10 prep repairs. But all prep repairs must be applied sequentially. So if we don't have prep repair number 12, then we need to wait or request it from other nodes before we can go further. And maybe the last important thing, last feature in Plenum, it's BLS aggregated signature. So, as I mentioned before, it's sufficient to send read requests to a single node only. And why the client can trust this data? It can trust because of two things. The first thing that in every reply to a read request, we return a proof that this request belongs to a Merkle tree, to the Patricia Merkle tree on the node. That's fine. The client can verify that this data is on this Merkle tree. But the next question is how would you know that this Merkle tree is really the same as on other nodes? Because it can be that this node just created a fake Merkle tree and returned this data to the user. And the answer to this question is that every node during consensus protocol, they sign, they cryptographically sign the root hashes of the state. So that also in addition to the state proof, we return this signature. So the client can verify the signature, can verify the root of the Merkle tree and trust the data. So, yeah, during the commit phase, every node signs the ledger Merkle root hash, the state Merkle root hash, the current timestamp, so that we have this so-called aggregated BLS multi-signature to be verified by the client. Okay, well, so as a summary, ledger, indie ledger is a ledger purpose built for identity. But on the other hand, it can be used as a general purpose ledger. Indie has its own implementation of consensus protocol, business default-tolerant-like consensus protocol. In Indie, we have multiple ledgers. Every ledger has a state, a Patricia Merkle tree state as a snapshot and has a Merkle tree. Authentication, authorization, it's all based on the information present on the ledger. And one of the features of important features of Indie is efficient reads. You can read just from one node. You don't need to download the whole blockchain, the whole ledger. You can just send a read request and verify it with a small amount of time and date required. And, yeah, this is very pretty important for public permissioned ledger use cases. So there are some links to our code, to the RBFT paper, to PBFT paper. And thank you. Any questions? This feature is considered to be partially implemented. We already have the key things for this feature. And actually, one of the key things for this feature is this one, PLS aggregated signatures and to be able to transfer data from one node only. And also, we have observer interfaces. But we don't have any real observer nodes in production. And I believe there is also some, a couple of things that needs to be finished before it can go there. So it's partially implemented and we don't have real examples in soaring. But I think it could be a great contribution from community. And it would not be so hard to do this and, yeah, have observer nodes in production. I believe you need to maybe implement a couple of things in order how you can, you know, register this node and so on. But in general, I think you can try to do this and it should mostly work. Yeah. Not necessary. We're considering some strategies where observer nodes could replace validators. For example, if validators behave maliciously or the other way around. But in general, observer nodes don't need to be a validator node. In terms of the code, it can run the same code, the same Indian node or sovereign code. But it just depends on the role that we assign for this particular node. Yeah. It's the problem. Yeah. It's the problem in any blockchain that it's immutable storage ever growing. Actually, the information in audio transaction is not as big because it doesn't contain real data. It contains only like hashes or fruit hashes. So it's not a lot of data, but yeah, it's immutable. Yeah. So we use RocksDB as a persistent storage for this data for any, every ledger, every state. I've used RocksDB. So it's not in RAM. It's not in memory. It's actually persisted. RocksDB has, of course, some, you know, optimizations that for frequently used data it uses some in memory accesses. But in general, it can be persisted. And in general, we can scale it on this level. So we can create multiple, you know, databases. And so of course, it's usually a trade-off between, you know, how to access the data, which is frequently accessed, being accessed, versus, like the disk space. But yeah, it's possible to do this. Yeah. You know, that we have a NIM transaction, which is, can be used to store DID and the persisted public keys. But we don't have a request to just return a DID doc. This is kind of one of the features which is in our backlog. So you can just, you know, process the data on the client site and form the DID doc in a way it's defined by W3C. And in order to how to store other information required for DID doc, such as service endpoints, you know, these controllers, we have a special transaction which is called a trip attribute, where you can put any data associated with the DID. So you can use this transaction to store a DID doc. But in general, we have plans for a real DID doc support, more convenient for end users. So you can just request it and get back in a, you know, interoperable form. Any other questions? I really feel a bit out of time. So I can stay here and everyone has any questions, so I'll be happy to answer.