This blog begins a wonderful series of events that record the development of the TAO. As many already know, this stands for Tritium, Amine, and Obsidian representing major version 3.0, 4.0, and 5.0 respectively.

Some on topic but slightly tangential reasoning behind the names of the TAO.

Tritium is the third isotope of hydrogen (hydrogen-3)

Amine is the base for all amino acids among other fundamental compounds. It is also a molecule consisting of 4 parts. Catching my drift now?

Obsidian is a volcanic glass that was used as an instrument in prehistoric surgery that can be made sharper than steel. It ranges in the 5’s on the Mohs Scale.

Correlations anyone?

Anyhow, my reasoning for these timely blogs is to give the community better information regarding what has been done since the last blog post. I’m going to start the standard here with dumping a “git pull origin master” from the head commit set back exactly to the date of last blog. This will — you know, let the code speak for itself.

.gitignore | 2 +-

Dockerfile | 100 +

config/.aliases | 31 +

config/.cshrc | 1 +

config/docker-run-tritium | 23 +

config/nexus.conf | 4 +

config/run-nexus | 7 +

contrib/STYLEGUIDE.md | 43 +

docs/.gitkeep | 0

docs/how-to-docker.md | 68 +

lisp/.gitkeep | 0

lisp/README | 48 +

lisp/RL | 83 +

lisp/lisp-join.py | 174 +

lisp/lisp.config.xtr | 111 +

lisp/make-crypto-eid.py | 193 +

makefile.cli | 227 +-

src/LLC/hash/SK.cpp | 38 +

src/LLC/hash/SK.h | 587 +-

src/LLC/hash/SK/Keccak-compact64.c | 45 +-

src/LLC/hash/SK/KeccakDuplex.c | 22 +-

src/LLC/hash/SK/KeccakDuplex.h | 8 +-

src/LLC/hash/SK/KeccakF-1600-interface.h | 38 +-

src/LLC/hash/SK/KeccakHash.c | 8 +-

src/LLC/hash/SK/KeccakHash.h | 8 +-

src/LLC/hash/SK/KeccakSponge.c | 38 +-

src/LLC/hash/SK/KeccakSponge.h | 14 +-

src/LLC/hash/SK/brg_types.h | 25 +-

src/LLC/hash/SK/skein_port.h | 6 +-

src/LLC/hash/Skein3Fish/include/brg_types.h | 16 +-

src/LLC/hash/Skein3Fish/include/skein_port.h | 6 +-

src/LLC/hash/macro.h | 10 +-

src/LLC/include/key.h | 324 +-

src/LLC/include/random.h | 18 +-

src/LLC/key.cpp | 70 +-

src/LLC/random.cpp | 36 +-

src/LLC/types/bignum.h | 1219 +-

src/LLC/types/uint1024.h | 677 +-

src/LLD/templates/filemap.h | 66 +-

src/LLD/templates/hashmap.h | 60 +-

src/LLD/templates/journal.h | 10 +-

src/LLD/templates/key.h | 83 +-

src/LLD/templates/pool.h | 56 +-

src/LLD/templates/sector.h | 78 +-

src/LLD/templates/transaction.h | 24 +-

src/LLD/templates/version.h | 41 +

src/LLP/hosts.cpp | 16 +-

src/LLP/include/hosts.h | 12 +-

src/LLP/include/inv.h | 24 +-

src/LLP/include/legacy.h | 354 +-

src/LLP/include/network.h | 103 +-

src/LLP/include/permissions.h | 10 +-

src/LLP/include/version.h | 45 +

src/LLP/inv.cpp | 103 +

src/LLP/legacy.cpp | 684 +-

src/LLP/network.cpp | 174 +-

src/LLP/socket.cpp | 245 +

src/LLP/templates/data.h | 157 +-

src/LLP/templates/server.h | 334 +-

src/LLP/templates/socket.h | 124 +

src/LLP/templates/types.h | 444 +-

src/TAO/API/rpcdump.cpp | 234 +

src/TAO/API/rpcserver.cpp | 3551 ++++++

src/TAO/API/rpcserver.h | 77 +

src/TAO/Ledger/checkpoints.cpp | 104 +

src/TAO/Ledger/difficulty.cpp | 470 +

src/TAO/Ledger/global.cpp | 287 +

src/TAO/Ledger/include/block.h | 57 +

src/TAO/Ledger/include/checkpoints.h | 63 +

src/TAO/Ledger/include/difficulty.h | 57 +

src/TAO/Ledger/include/global.h | 370 +

src/TAO/Ledger/include/prime.h | 51 +

src/TAO/Ledger/include/sigchain.h | 136 +-

src/TAO/Ledger/include/supply.h | 76 +

src/TAO/Ledger/include/time.h | 77 +

src/TAO/Ledger/include/trust.h | 197 +

src/TAO/Ledger/prime.cpp | 128 +

src/TAO/Ledger/supply.cpp | 181 +

src/TAO/Ledger/trust.cpp | 1063 ++

src/TAO/Ledger/types/block.cpp | 315 +

src/TAO/Ledger/types/include/block.h | 312 +

src/TAO/Ledger/types/include/data.h | 78 +

src/TAO/Ledger/types/include/locator.h | 109 +

src/TAO/Ledger/types/include/state.h | 124 +

src/TAO/Ledger/types/include/transaction.h | 66 +

src/TAO/Legacy/crypter.cpp | 150 +

src/TAO/Legacy/db.cpp | 576 +

src/TAO/Legacy/include/crypter.h | 113 +

src/TAO/Legacy/include/db.h | 345 +

src/TAO/Legacy/include/keystore.h | 199 +

src/TAO/Legacy/include/wallet.h | 768 ++

src/TAO/Legacy/include/walletdb.h | 192 +

src/TAO/Legacy/keystore.cpp | 218 +

src/TAO/Legacy/types/address.cpp | 127 +

src/TAO/Legacy/types/enum.cpp | 180 +

src/TAO/Legacy/types/include/address.h | 140 +

src/TAO/Legacy/types/include/enum.h | 226 +

src/TAO/Legacy/types/include/inpoint.h | 82 +

src/TAO/Legacy/types/include/merkle.h | 74 +

src/TAO/Legacy/types/include/outpoint.h | 144 +

src/TAO/Legacy/types/include/script.h | 463 +

src/TAO/Legacy/types/include/secret.h | 100 +

src/TAO/Legacy/types/include/transaction.h | 380 +

src/TAO/Legacy/types/include/txin.h | 165 +

src/TAO/Legacy/types/include/txout.h | 166 +

src/TAO/Legacy/types/outpoint.cpp | 46 +

src/TAO/Legacy/types/script.cpp | 1569 +++

src/TAO/Legacy/types/secret.cpp | 85 +

src/TAO/Legacy/types/transaction.cpp | 971 ++

src/TAO/Legacy/types/txin.cpp | 93 +

src/TAO/Legacy/types/txout.cpp | 93 +

src/TAO/Legacy/wallet.cpp | 1697 +++

src/TAO/Legacy/walletdb.cpp | 458 +

src/TAO/Operation/include/execute.h | 191 +

src/TAO/Operation/include/operations.h | 83 +

src/TAO/Register/include/object.h | 105 +

src/TAO/Register/include/state.h | 154 +

src/Util/args.cpp | 32 +-

src/Util/base58.cpp | 226 +

src/Util/config.cpp | 16 +-

src/Util/debug.cpp | 6 +-

src/Util/include/allocators.h | 6 +-

src/Util/include/args.h | 26 +-

src/Util/include/base58.h | 225 +

src/Util/include/base64.h | 24 +-

src/Util/include/config.h | 14 +-

src/Util/include/convert.h | 46 +-

src/Util/include/debug.h | 6 +-

src/Util/include/hex.h | 34 +-

src/Util/include/json.h | 18912 ++++++++++++

src/Util/include/mutex.h | 6 +-

src/Util/include/parse.h | 30 +-

src/Util/include/runtime.h | 46 +-

src/Util/include/sorting.h | 6 +-

src/Util/include/version.h | 37 +

src/Util/macro/header.h | 27 +

src/Util/templates/containers.h | 10 +-

src/Util/templates/mruset.h | 6 +-

src/Util/templates/serialize.h | 314 +-

src/main.cpp | 893 +-

tests/smoke/README.md | 95 +

tests/smoke/examples/nexus.conf.publictestnet | 12 +

tests/smoke/mainnet-setup-for-debugger.sh | 5 +

makefile.unix => tests/smoke/makefile.unix.test | 125 +-

tests/smoke/public-testnet-setup.sh | 5 +

tests/smoke/run-start-nexus-test.sh | 265 +

tests/smoke/setup-for-debugger.sh | 5 +

tests/smoke/setup-for-debugger2.sh | 5 +

tests/smoke/setup-two-local-test-nodes.sh | 7 +

tests/smoke/start-local-testnet.sh | 21 +

tests/smoke/startminerfortest.sh | 5 +

154 files changed, 43266 insertions(+), 4466 deletions(-)

Lots of file dumps, collectively its an addition of ~ 39,000 lines of code. I’ll explain why there’s so much new code, and what’s happening under the hood as we speak. Bear with me if you’re not very technical, or skip to the end since I’m going to get fairly detailed.

Let’s start with the Network Layer:

Network:

The network as you all most likely know is powered by the Lower Level Protocol. The Lower Level Protocol (LLP from here forward) is a polymorphic template protocol. Yes that’s a mouthful, but it’s just another way for us coder people to say, “I build this template once, and I can use it for anything”. This is called good code design, since, you end up needing less endlessly repeating sequences of the same code with slight alterations. In this case, you drop in a new packet type, write a new ProcessPacket method, and boom you have a new protocol.

So what makes this special? It’s because most servers on the internet have a very hard time scaling. They usually follow the blocking one per thread model, using socket selects, or even operating on a single thread asynchronous model like node.js and boost asio. Now this is important to understand, because asynchronous models have been touted as being far more scale able — this is true, but not to be mistaken for how this can be implemented. When you hear people say Node.js scale able elastic computing front end, they mean asynchronous sockets since Node.js uses Google’s V8 Javascript engine, and allows sockets and Javascript on the server side (this usually happens on the client side).

Anyhow, let’s continue. The LLP is also a multi-threaded asynchronous socket packet handler… this means that any user wanting to work with the LLP can create literally any protocol they want, and are always going to have the trusty, well tested, server back end. The LLP is now completely absolved of any boost dependencies, part of the new coding standards in this project. The reason for removing all boost is that it is quite a heavy framework that was developed for the C++98 veterans, to do nice simple things that the STL couldn’t do. Now, C++11/14 standards contain a lot of the boost necessities in STL which means that all boost code can be removed (phew).

So enough on that, let’s see some results from my latest stress test:

This is a single computer, 1000 connections, and 144,485 requests per second. This performance is well within requirements for VISA scale abilty (20k / second peak). It is very important for these base layers to not become bottlenecks, so there has been a lot of attention given to the LLP over the course of this week.

Ledger:

Now we start to get to some fun stuff, the Ledger! As you can see from the above “git pull origin master”, there are a lot of files. Each one, as you will notice, is organized very neatly based on its function, and put in its proper namespace.The Ledger code consists of block validation, transaction validation, and basic lower level ledger data scripts to handle register reads and writes. Most of the legacy code is implemented and operating in order to allow backwards compatibility with the Legacy UTXO sets — while allowing a transition time into the more efficient Tritium Transaction.

There are two block structures here in the ledger layer, Legacy and Tritium. Legacy blocks push the heavy block data and transaction data coupled to a 2MB limit every 50 seconds, newer lighter Tritium blocks only retain the transaction hash, which means that maximum transaction size now goes down to 64 bytes. Since the transaction is broadcast over the LLP to the entire network, and it operates efficiently, transaction processing can be done mostly in the time while waiting for the block. This means that transactions locked into the memory pool, can be cached and verified and easily connected when the block comes, requiring little processing power, and blocks that can contain up to 32,768 transactions every 50 seconds. This amounts to a maximum transaction rate of 655 / second assuming a 42 Kb/s data rate.

This feature is a stepping stone towards a 3DC, simulating a single L1 state channel.

Register:

Now we start to get above the ledger abstraction, and into new territory. Registers are sitting on top of the ledger, having identification tied from the ledger. The ledger scripts are the interface that allow registers to be defined, and permissions of each to be granted. The two types of registers that exist as of now are state and object registers.

A state register is the raw bytes of data that represent the state of whatever object one defines. An object register contains more type-safe data sets. What this means, is that an Account will be an object register to store the state of your balance. It goes similar to this:

std::vector<uint8_t> vchIdentifier;

uint64_t nBalance;

The account’s address is actually the register’s address, so that if a user is to commit a DEBIT op to that register address, the owner of the address would be required to issue the CREDIT of the according balance. The vchIdentifier is what holds the unique type of account this is, which in other words means the ability to create tokens that transfer with the same efficiency as NXS. This is just the beginning, I’ll get more technical on the scope of these layers and how they weave together in blogs following this one.

src/TAO/Register/include/object.h | 105 +

src/TAO/Register/include/state.h | 154 +

Operation:

The operation layer gives context to the register layer. To the ledger, a transaction is just raw bytes like a packet is to a network router, but it isn’t until you get higher up the stack that context is given to that data. This is one of the methods that has been developed to scale efficiently, and as you can see, every layer needs to be well thought through, interfaced, and connected together seamlessly. If the lower layers create bottlenecks it affects all the layers above it.

The following operations have been defined:

OP_WRITE = 0x01,

OP_READ = 0x02,

OP_REGISTER = 0x03,

OP_AUTHORIZE = 0x04,

OP_TRANSFER = 0x05,

OP_ACCOUNT = 0x20,

OP_CREDIT = 0x21,

OP_DEBIT = 0x22,

OP_BALANCE = 0x23,

OP_EXPIRE = 0x24,

OP_CREATE = 0x25,

These represent basic byte code logic sequences that execute to change the states of object registers through verification of other nodes. This list will continue to grow, for now, the simpler with the highest functionality, the more efficient and scale able.

src/TAO/Operation/include/execute.h | 191 +

src/TAO/Operation/include/operations.h | 83 +

I’ll go into more details on my next blog post exactly how these weave together to make for very interesting use cases with Nexus Contracts.

API:

The API, ah yes, what many people are waiting for. This operates on a HTTP-JSON server that allows anyone to create contracts without needing to learn all the lower level code that drives the entire engine. The message format will be broken into many different industry specific API’s, and be powered by an HTTP-LLP server.

As you could see from the above LLP test results, the API will be able to handle quite a lot of load even operating on a single node. Now since the network is Peer to Peer, this means that an API instance will be running on any node that decides to deploy that as a service.

I will go into more details on the specifications of the API and message format in the next blog update.

Until Next Time:

I hope this was an informative blog update— in light of being able to communicate in a more technical nature the developments of the TAO code base. I will continue to share benchmarks of tests, simulating high throughput transaction environments, and more load tests of each layer as they are woven together to be ready for the public testnet deployment.

I look forward to the working groups this year, to get our first standardization process complete — and prepare for main net deployment.

Cheers,

Viz.