For the people who only read the headlines:
TurtleCoin v2 is 23x more private than Monero. We win.
For the rest of you nerds who like details, keep reading..
At the heart of every blockchain project is the code that makes the magic happen. The fundamental math that handles the calculations required to handle our good friend Elliptic Curve Cryptography (“ECC”). ECC serves as the method for how private keys and public keys are generated, how those points on the graph are related, and how those points are manipulated (added, subtracted, multiplied, etc.). The ability to manipulate the points in a secure way provides us with the foundational building tools to build the vast majority of blockchain networks.
TurtleCoin® is no different. Today, v1 relies on a slight variation of ED25519 using Curve25519. The implementation differs from ED25519 which relies on SHA-512 (SHA-2) by instead utilizing a non standards compliant implementation of Keccak (aka SHA-3) in the form of
cn_fast_hash as well as encoding private keys slightly different than as defined in the RFCs.
For the nerds in the crowd, the implementation is non standard due to a use of a slightly different padding.
Those of you that have worked to create various implementations of wallet software, address generators, etc. have undoubtedly came across this variation a few times and said to yourself “wtf” when you try to use a standard SHA-3 or ED25519 library in the language of your choice.
Out With The Old, In With The New
The new crypto core is still built on Curve25519; however, instead of using non-standard Keccak, we’re moving to the SHA-3 standard. Every construction whether it be key derivations, output creation & scanning, signature construction, view key generation, etc. has been moved over to better support the use of standard hashing libraries. It’s not a huge change, but it does make a difference. The result of this is that if you were to restore a v2 wallet using a wallet seed generated by v1 software, you will get two totally different wallet addresses.
To be abundantly clear, v1 and v2 keys, seeds, and wallets will not be interoperable.
In addition to that change, considerable work has been done to make using the primitives a lot easier in downstream code. The framing around the cryptographic foundations has been rewritten to make using, reading, and understanding how those primitives work as easy as possible while still maintaining as much performance as we can. The end result is a generally easy to understand and read implementation of the framework required to build a blockchain project.
Turning code that looks like this:
This not only makes the code about 1,000x easier to read and understand but greatly reduces the entry barrier required to get in there and start working with things. It also makes it a lot easier to build more advanced constructs including some of the additions that have been baked into the new cryptographic core.
Reducing Transaction Size
As we have discussed in previous updates, one of the foundational issues that the network has had in the past is the explosive growth of the chain in terms of storage requirements. While dropping junk in TX_EXTRA has been a large driver of that growth, the vast majority of the storage is driven by the input signatures attached to each transaction input. Today, these signatures amount to 512bytes (0.5KB) per input with a ring size of 4. It doesn’t seem like much, but when some transactions have 10s or hundreds of inputs that 512 bytes explodes at a very linear rate.
While the bulk of a transaction is the signatures of those inputs, the need for working with certain denominations of coins or “pretty amounts” (ie. 1, 2, 3, 10, 20, 30, 100, 200, 1000, etc.) also contributes to the bulk of a transaction size. The use of pretty amounts is what drives the need for fusion transactions whereby all of the smaller denominations (“dust”) are traded in for larger denomination outputs that can be spent later. The requirement that denominations exist and are used results in more dust, more transactions, and a larger chain overall.
To combat this issue, we’re doing away with the requirement to transact in denominations and changing the ways in which signatures are constructed.
To get rid of the requirement to transact in certain denominations v2 will utilize masked amounts and rely on Pedersen Commitments to denote both input and output values of the coins that are transacted without ever revealing to a third-party the actual value of the coins.
Pedersen Commitments have been heavily used in other blockchain projects such as Monero (XMR). A side benefit to this method includes the increased privacy of the transactions on the network.
Pedersen commitments have a nifty property in that they can be added and subtracted from each other much like regular numbers can be added and subtracted from each other and arrive at the same result.
For example, assuming our commitment generator is :
The commitments do not reveal the actual values of and and an outside party has no clue what those values are.
This is very handy for ensuring that the tally of output commitments is equal to the tally of input commitments – or put simply, that a transaction is in balance.
The primary issue with using Pedersen Commitments for transacting on a network are that it is possible to construct output commitments that overflow the number space that ultimately results in the rampant creation of new coins without the authorization to do so.
For a quick example, let’s assume that we have an unsigned 8-bit number space available. We know that if we overflow the maximum value of that space (255), that the number overflows and comes back around to end up where it doesn’t make sense. We also know negative values stuffed into that same space results in a value that underflows and arrives at a place that doesn’t make sense.
Let’s take a quick look at this in practice and how this can be exploited.
Note: The values are shown below for explanation purposes, in practice, they are hidden by their commitments.
Then we construct two (or more) outputs to arrive at the same value:
We can clearly see that However; in 8-bit math, the number rolls over the top such that resulting in the tally of inputs and outputs matching. If you’re following along, you can see that we just minted coins (256 to be exact) out of thin air. Not cool.
The same trickery can be performed using negative values as well (ie. ) because of the number bounds that turn that into which wraps around again such that . Definitely not cool.
This is where Zero Knowledge Range Proofs come in to save the day. They allow us to prove to a third-party (ie. the network) that the values contained in the output commitments of a transaction are within a certain range without revealing the values they represent. In our case, the range is defined as 0 to otherwise known as what can fit within an unsigned 64-bit number space.
We will be using Bulletproofs+ (“BPs+”) for our Zero Knowledge Range Proof in v2. To prove to a third-party (the network) that the values of the commitments in our transactions are within the bounds specified.
You may have noticed that we skipped right over Bulletproofs (“BPs”) and instead went straight for Bulletproofs+. The constructions are relatively similar with the resulting difference being that the cryptographic proof of the values of our commitments are within the defined range are smaller in terms of byte size and verify just a little bit faster than Bulletproofs.
Another huge benefit of BPs or BPs+ is that a proof can be batched meaning that we can prove the values of multiple commitments all within a singular proof. Instead of submitting one proof for each output commitment, we are able to submit a single proof for all of the output commitments in a single transaction. This greatly reduces the amount of storage required to transmit and/or store the transaction while still maintaining masked amounts. This results in smaller transactions and thus lower transaction fees.
For the sake of testing and benchmarking the new cryptographic core contains implementations of both Bulletproofs and Bulletproofs+. We’ll be relying on BPs+ until something better comes along.
Borromean Ring Signatures
Today, v1 uses Borroeman Ring Signatures and each input in a transaction contains such signature whose size is proportional to the ring size. As the size of the ring grows, the size of the ring signature for each input grows as mentioned above. The growth is linear to the number of ring participants which is detrimental to the size of transactions and thus drives up transaction fees.
Adding commitments into the mix only further slows things down and causes massive chain bloat. At a ring size of 256 participants, the signature size is
16,384 bytes or 16KB without including the signing of the commitments. Yikes!
So, what are our options if we want to increase ring size as part of the change to v2?
Concise Linkable Ring Signatures (CLSAG)
You may recognize CLSAG from a recent XMR upgrade performed in October 2020. CLSAG greatly reduces the size of the signature of each input supplied for a transaction. While it still grows at a linear rate it grows quite a bit slower. It’s also a bit faster in the construction and verification routines as opposed to Borromean.
At a ring size of 256 participants, the signature size is considerably smaller in our construction coming in at
8,259 bytes or ~8KB including commitments which is a drastic reduction in storage space.
Cutting the size of the signatures in about half results in our transactions costing significantly less. Woot!
Can we do better? Can we crank this thing up to 11? You’re damn right we can.
Arcturus is the new hotness put together by the Monero Research Lab (“MRL”) that significantly reduces the size of a “ring signature” while ensuring the that tally of input and output commitments match. Not only that, but it also works to prove the commitments to zero for those commitments (ie. proving that you know the real values of those commitments). If that were not enough, it also permits multi-index proving such that it’s possible to combine all of the attestations that we know the values of the commitments as well as have the private ephemeral for each real input being spent into a single proof.
I’m taking a bit of liberty here in calling Arcturus a ring signature as it’s not so much a ring signature as it is a cryptographic proof; however it is functionally equivalent to a ring signature for our purposes and helps keep the information relatable.
Comparatively speaking, verification times are, at times, about twice (2x) as fast (or more) as a CLSAG verification of the same ring size.
The multi-index capabilities of Arcturus have massive benefits to v2. Instead of having a signature for each input in a transaction, we are able to combine all of the inputs into a single signature (proof). This means that as we include more inputs in a transaction the signature does not grow linearly anymore thus reducing transaction size resulting in even lower transaction fees.
The downside is that the construction (generation) time is considerably longer for large rings. That’s okay though as signatures/proofs are only constructed when you use your wallet to create a new transaction.
As you can see, the size of the ring no longer grows linearly with the size of the ring. At a ring size of 256 participants, the signature size comes in at a panty dropping
1,294 bytes in our implementation. This means that our signature is not only ~16% the size of a CLSAG signature but is also ~8% of the size of a Borromean signature. Couple that with the fact that we can now bake multiple spends inside a single signature (proof) and we’ve potentially cut up to 99% (depending on the number of inputs) of the signature bulk off a transaction sent on the network. HELL YES!
What’s this mean for users? Very, very, very, very low transaction fees!
A Smaller Chain He Said…
Now that we have cut down the size of transactions so that they are a fraction of their previous size, we got to thinking… how else can we cut down on the storage requirements of the v2 chain and cut down on chain sync time. As we all know syncing the chain on a node is by far the best way to find the time to learn a new hobby. It’s not fast – even with checkpoints – it takes a while.
After mulling it over a bit, the thought came to us that we don’t need to carry around our range proofs and transaction signatures indefinitely… that they are in fact… immediately and forever prunable. Notice we said immediately prunable as in we don’t need to wait for a certain number of blocks to pass before pruning the signatures and range proofs from the transactions. Nor do we need to make this optional for node operators – it just is. Transactions can be pruned as soon as they are committed to the chain (included in a block).
Nodes will keep transactions in an alternate mempool for a certain number of blocks, in the rare event that a re-organization event does occur, they will be able to pluck the full details of the transaction from that alternate mempool. Once enough blocks have passed, transactions in the alternate mempool can be purged.
You may be scratching your head and wondering what we’re thinking as that information has to be there to verify a transaction during the sync process… right? No, it doesn’t.
In a traditional PoW network, such information has to be maintained to ensure that the blockchain is valid from start to the tip of the chain – verifying every bit along the way. This method also allows for handling chain re-organization events which are common in blockchain networks.
We already use checkpoints to short-circuit many of the checks normally performed by providing a list of trusted hashes for prior blocks. Checkpoints allow us to bypass the need to verify everything in that range of blocks (including the transactions and their signatures/proofs) and saves a lot of time.
In the v2 PoS scenario, we vote to trust that the block producers and validators have verified the signatures and range proofs for each transaction in a block before throwing their stamp of approval on the block (via a signature). Once the producers and validators sign a block, it’s solid, it’s not going anywhere. It is “in stone” as they say and while a chain re-organization is possible, it’s very unlikely. If they don’t properly verify signatures and range proofs well… that’s where they get penalized.
What this allows us to do is to define the structure of our transactions differently. Whereas today transaction hashes (and thus the hashes included in blocks) are generally constructed based upon the hash of every byte of a transaction
(prefix || signature || range_proof), TurtleCoin® v2 transaction hashes will be computed based upon the hash of
(prefix || H(signature) || H(range_proof)).
By constructing our transactions in this way, we are able to keep the full transaction (including the full signature and range proof) in the pending transaction mempool so that producers and validators can verify the signatures and range proofs. When the transaction is committed to the chain (included in the block), we can instantly drop the full signature and range proof from the data and swap the hashes of those structures into their place for long term storage which drastically reduces the storage required to operate a node.
While a signature + range proof may require
1,938 bytes in the mempool, once committed to disk, that same signature and range proof will only require
64 bytes of storage. This results in a reduction in transaction storage requirements of over 96%. Combine this with the fact that we will no longer produce empty blocks and we might be able to keep the chain on a floppy disk for a while.
Pretty cool aeh?
Enhanced Privacy Features
If you’ve read through all that, you can see that the vast majority of the work for v2 has focused on reducing the chain size and making verifications faster to support making the chain faster to sync and allowing wallets to sync as fast as possible. This greatly improves the experience when working with the network which was on of the core goals for v2.
However, in focusing on improving the experience of using TurtleCoin® we picked up numerous privacy enhancements along the way. What we have in the oven now is something truly unique. The combination of enabling Amount Masking and Arcturus allow us to provide 100% privacy with ring sizes far larger (and thus much harder to trace) than other projects – all coupled together with PoS.
While we test, benchmark, and debate whether 256, 512, 1,024, or larger ring sizes make the most sense for the network, we know that any of those ring sizes far exceed the ring sizes used by other projects (including XMR) and provide people with a network that they can securely and easily transact on. Throw in the fact that the relaunch allows us to enable the use of massive ring sizes starting with block
0, the privacy offered by TurtleCoin® v2 will exceed that of practically every other privacy project out there.
No tainted outputs, no legacy spends, no small traceable rings, no messy output migrations. Just secure, confidential, and highly anonymized transactions on a small lightweight chain.
Now that we have the core cryptography out of the way we can direct our focus back to finalizing block and transaction structures (90% complete) then start work on building up the blockchain storage subsystem, building the staking system, and wiring up the rest of the network node. From there, we’ll work on building out the new CLI wallet that will be designed from the ground up.
We hope you’re as excited as we are as we continue to build the next generation of the TurtleCoin® network from scratch using the latest and greatest technology available.