First up, there’s a ton of new code. 50k+ new lines of it. Great job, Nexus devs!
Lower Level Crypto:
Nexus is monitoring new quantum-resistant signature schemes that use lattices to replace the Elliptic Curve Cryptography scheme that is currently used for private/public keys. Lattices will make your signature chain more secure against quantum computers but requires greater processing, which is already a throughput bottleneck at 4.3k TPS.
Lower Level Database:
A new keychain called a Binary Hash Map has been created as an alternative to the Binary File Map (another form of indexing). Essentially, if the blockchain is indexed via account, then the account name is run through a hash function which determines its location in the index, called a bucket. A bucket collision is when the hash output is the same for another input.
When this occurs, it searches through multiple hashmaps from the largest index to smallest index and places the information in the first empty bucket at the calculated position. When the key needs to be retrieved, it calculates the bucket location and then checks that bucket in each hashmap until the key is found. Greater bucket collision resistance means that the Binary Hash Map is more efficient.
The Binary LRU cache is pretty self-explanatory. Information that is used most frequently is retained whilst infrequently used data is replaced.
The Transaction Journal is like a page file for the blockchain. Rather than holding every transaction that has been processed and is awaiting placement into a block in RAM, which can be corrupted after power failure, the LLD sets aside a portion of the hard drive in a file and stores the pending writes there. After reboot, it can recover if there was a failure at any point in the ACID transaction, due to checkpointing the journal file before events are committed to the main database.
ACID is not just known for great visual effects and synesthesia, but is a well-known acronym from the world of databases. It stands for Atomicity, Consistency, Isolation and Durability. Meaning:
- When a transaction is made, every part of the transaction must be valid or the transaction fails.
- Transactions must be in order, for instance a DEBIT must happen before a CREDIT, or for that instant in time the ledger would be in an invalid state.
- Once a transaction is made, it is irreversible. You cannot make another transaction that would invalidate a previous transaction. For instance, let’s say I have 1000 NXS and buy something worth 500 NXS. If I try to quickly go and transfer 501 NXS, it would fail.
For further reading about ACID: https://vladmihalcea.com/a-beginners-guide-to-acid-and-database-transactions/
Lower Level Protocol (LLP):
The LLP handles the networking layer of Tritium, managing sockets and connections with other nodes. The benchmarks reported here are run on the underlay without LISP. As can be seen in the photo, and as Colin explained, this benchmark is not performed with any Ledger layer validation and is simply a load test on network capability alone. Under real-world conditions, this will not be the case.
A transaction object contains all the information needed to make a transaction, for instance sending account, receiving account, amount to be transferred, signature data, public key, tx ID etc. When a new transaction is received, the node performs pre-processing to validate the transaction. When a block is received, the node then checks to see if that transaction is included in the broadcast block, and then commits this collection of indexes to disk using an ACID transaction (remember, ‘all or nothing’). This benchmark of 647ms was for post-processing only. Pre-processing takes a little longer, but given an average block time of 50 seconds, there is plenty of time available to perform this processing.
Preprocessing tests received transactions to ensure that they are valid and do not violate ledger, register, or operations verification. For a short period, I believe about 12 months was the stated duration, nodes will be able to process both Tritium transactions and legacy transactions. Tritium transactions use the new account model with the new signature chains, whereas legacy transactions still use the UTXO system with private/public key security. Legacy addresses can send to Tritium accounts, but Tritium accounts cannot send to Legacy addresses. Any Legacy addresses containing coins after this period will be inaccessible.
All pre-processed transactions are retained in a mempool awaiting inclusion in a block. If a second transaction is received which contradicts or invalidates an already processed transaction, then that second transaction is rejected.
Tritium blocks do not contain all the information that was contained within the transaction object. They only contain a list of all the transaction IDs contained within the block. When the block is received, nodes compare every transaction ID which has passed pre-processing and if the block contains an unknown or unprocessed transaction ID, then that block is not accepted until that transaction is received and processed. This list of transaction IDs also serves to verify the merkle root that was calculated in the block header.
Before Amine is implemented, all the pre and post processing is performed by the same nodes via PoS or PoW miners. Under Amine, they will be separated, with pre-processing or transaction validation performed via the PoS/Trust nodes, and post-processing or block verification performed by miners.
Obsidian will split the consensus process over 3 channels, the L1, L2 and L3 locks. The first 2 locks are the same as explained above. The L3 lock is a hardening stage using proof of work. Instead of miners racing to find a winning block hash, each miner works to find the most weighted hash within a 60 second period. Miners then submit this hash (which is based off the L2 locks, previous block hash, their Signature Chain’s Genesis ID, and randomly generated nonce) to the network and combined into a single merkle root hash. This way each miner gains a portion of the reward proportional to how much collective weight they contributed.
This explains that by including the register pre-state within the transaction object, it forms part of the transaction hash which is part of the block header. Light nodes can then check block headers to see if the pre-state of a new transaction formed part of a recorded block. Because this information is recorded within the block header, older pre-states can be pruned and removed from the blockchain, decreasing blockchain bloat. If a node were to attempt to include an older pre-state, it would fail register verification on receive of a new transaction, being that the published pre-state was not consistent with the current register’s state in the LLD instance that holds register data.
This section goes on to point out that extravagant claims of “100k TPS” are unrealistic without some sort of blockchain pruning or sharding, and that network bandwidth and hard drive storage are bottlenecks to this sort of throughput.
The post state is the new state of the register which is recorded in the database, and transacting nodes have to include a post-state checksum along with the transaction, which must be the same as that calculated by the validating nodes. This is important for the development of dapps built on Nexus, for if a dapp makes a transaction and expects a certain result, then the checksum provides the means to prevent the register moving to a state which the application did not intend. Its a form of error handling.
This section is basically just reiterating the contents of the Tritium whitepaper.
State registers can be manipulated by primitive operations, which will be detailed further below. These registers contain state information for external applications shared across multiple instances. This might be the location of a sea container or the status of a driver’s license.
State registers come in three flavours, Raw, Append, and Read-Only.
Raw registers have no security parameters besides ownership, only the owner of the register can modify the content of this register.
Append registers can only be added to and retains their original data and state history within the register database. This is useful for tracking ownership of property, land titles etc.
Read-only registers are unable to be changed even by the owner. It is useful for holding constants or information that will not change.
Currently, there are two types of objects, accounts and tokens. These are specialized registers which are used internally within the Operation layer. As such, their data format is pre-set and their contents can only be manipulated with specialized operations.
The Register operation assigns a new memory address to a new register. Think of this as declaring a variable within a program. Eventually, when sharding is implemented, this will need to allow assigning and accessing memory addresses in remote shards through inter-shard communication.
The Write and Append operations are self-explanatory.
The Transfer operation changes ownership of State or Token registers from one signature chain to another. This operation can only be performed by the owner of said register
A successful transaction of funds uses both a Debit and Credit operation. These operations can only be applied to Account registers. In the event of a successful Debit operation but lack a corresponding Credit operation, the issuing Debit account is able to redeem those unclaimed funds.
The next two operations, Validate and Require, operate along similar lines to IF control statements within programs. These allow conditions to be placed on the execution of operations and form the basis of Nexus’s Advanced Contracts.
Using Colin’s example of a decentralized exchange of tokens, the user wishing to sell tokens would execute the Require operation, which debits the funds and then waits for the conditions to be fulfilled. The buyer then performs a Validation operation which triggers the evaluation of User A’s conditions and removes the funds from User B’s account. Both users are then able to execute a Credit operation to deposit the corresponding funds into their accounts.