Taking a look at COTI with my code review today. White label payments solution, high throughput claims, custom stable coins, wants to revolutionize the way digital currencies are perceived by merchants and buyers using their Trustchain consensus. So basically doing the whole “We can out-PayPal PayPal and everyone else too” routine.
Interesting though, how they want to do it, and I had to delve pretty deep to get into their solution and how it actually works. I will tell you, since this is a longer code review, I do like what they came up with. I don’t think it’s exactly what they say it is, but it’s still pretty neat.
So, COTI, Currency Of The Internet — DAG-based infrastructure optimized for payment networks and stable coins. Off we go.
Fullnode, dsp-node, trustscore-node, zerospend-server look interesting.
Actual Java, I’m a little bit surprised. I was expecting scala.
Zerospend , base packages zerospend and basenode.
DspVoteServer? Transactions are voted on? There is a subset of delegates or validators that get elected and can then vote on transactions? Interesting, is this a distributed system or a decentralized one?
Looks right, we propagate a transaction to all DSP nodes (we will figure out what these are later), and then we vote on them. So BFT, but with DSP nodes (whatever they are).
So what I think we are going to see here is a transaction based BFT model with DSP nodes being randomly selected into their own shards? This would allow you to have concurrent votes on transactions. Although it might just be transactions and not shards, since if shards you still have to vote on the results of the shards. Is this UTXO? Let’s keep digging.
Starvation and zero spend transactions, we will need to look at the whitepaper what these do.
Randomized (sort of) trust scores at genesis.
pot time. Proof of Trust. max trust score = 100. Wait, are trustscores on transactions? I thought they were on voting nodes. Ok, so this is the trustscore of a transaction, assuming as some value based off of its parents, hence the DAG. I’m making assumptions though, let’s keep looking.
Good abstraction. Basenode is developed on its own with all the basic node features. I like the design pattern.
Wait, zerospend does not use proof of trust? And proof of trust is based on getRoundedSenderTrustScore(). Keep digging.
Some models, and http interfaces, websocket implementation, moving on.
RocksDB makes a visit.
The graph is nodes? Now I’m confused.
Transaction data, let’s break it down,
hash, amount, left parent (vertex), right parent (vertex) (what decides the parents?), trust chain transaction hashes, user trust score token hashes, trust chain consensus, trust chain trust score, transaction consensus update time, create time, attachment time, process start time, pow start time, pow end time, sender trust score, sender hash, node ip address, node hash ,node signature, children transactions, valid, valid by nodes, ….
Let’s look at an ethereum transaction
13 fields. The transaction data might be a bit excessive. Can’t see where leftParentHash or right is assigned. Will keep looking.
ZeroMQ, I’m getting a very distributed feel here. I think this is a very cool distributed payment solution, but I’m hesitant to call it decentralized. I am enjoying the code so far though.
Let’s jump into the trustscore node.
setKycTrustScore? What am I looking at here. If an account KYC’s we increase their trust score. That’s interesting. Smart.
So far we have the trust score nodes, they can update score information, they check trustScoreData via request.userHash, request.kycTrustScore, request.signature, and a hash of the kycServerPublicKey. I need to have a deeper look at new TrustScoreData, I’m curious if this can be exploited.
Not too much happening in it. So looking back at the setKYC, we need to look at trustScoreCrypto.verifySignature to see if this is exploitable.
Inherits from SignatureValidationCrypto, so let’s look
So, I could sign the payload and then have the trustScore updated? I’m confused what is stopping me from self signing and exploiting this. Let’s look back at the original.
Ah, kycServerPublicKey, only TrustScore Nodes can do this. But ok, let’s assume I’m a malicious one. Not sure how that is stopped. Again, this seems distributed, not decentralized.
I’ll dig into the whitepaper in a bit. Let’s keep going. Time for DSP node.
Ok, so fullnodes register with DSP nodes. Curious what stops me from just calling addNewAddress and spamming. DSP nodes then publish this shared data. So they are acting as relayers for the network.
Interesting. New transaction from full node. Oh, we just propagate again.
Ok, DSP nodes are just relay proxies. They propagate events throughout the network and keep track of all servers (and server types). Definitely a distributed solution.
Let’s hit fullnode.
Pretty cool, higher trust score = higher priority.
The node signs the message? Addresses are added and kept track of?
Get sources and proof of work, IOTA style.
Ok, so full node we just create transactions, addresses, and do a bit of POW on the transactions. Transactions are sent to DSP node relayers, trustscore nodes provide the trust data and allows management of kyc data, and zerospend server implements the zero spend transactions.
Yeah, this is a distributed solution.
“Hundreds of thousands of TPS. Arguments for this can be found in Section 10”, ok, we will get to it.
“MultiDAG”, didn’t see it anywhere in the code, not sure the architecture as designed will allow for it, the transaction relationship is quite fixed as a first class citizen currently.
“Smart contracts”, where? “Arbitration Service”, not yet. Wait, DSP nodes are double spend prevention nodes? I saw that in DSP voting service, (the BFT on transactions) but not in the DSP servers, they are just acting as relayers?
Oh, so they are “decentralized” because anyone can be a full node, and full nodes collect fees. No, this is not a decentralized solution, the real work still happens in the trustscore, dsp, and zerospend servers. Fullnodes just create transactions and does some proof of work to validate previous transactions.
The Trust Chain algorithm isn’t 100% accurate, sure, you do validate previous transactions via proof of work, but until the BFT vote by the DSP service this isn’t finalized. So finality is still only after BFT style transaction vote. And it’s standard http communication, so it will get pretty network intensive very fast. You can validate hundreds of thousands of transactions, but finality throughput is still lower, probably around 2–3 thousand.
COTI Code Review Conclusion:
Not decentralized, this isn’t the next bitcoin, but it’s a very cool distributed payment solution. We know they have quite a few merchants onboard already, and they are expanding. This is using the stable coin though and not coti dime. Fullnodes are low spec and can be easily run by someone for the rewards. Although ideally you would be a merchant, since you get more benefit by being the originating source of the transactions.
I wouldn’t call it a blockchain (and I’m talking about the category, not the data structure, even DAG’s are blockchains), but again, I think it’s a nice product. Good design, good architecture, well thought out. I think they have some promises in the whitepaper they are going to struggle with. Smart contracts and hundreds of thousands of TPS being two that immediately jump out given their design. But I like it.
Don’t know if it’s something good to buy now, but I’ll probably boot up a fullnode and mine a few.
You can chat about COTI in our Telegram group.
Disclaimer: Crypto Briefing code reviews are performed by auditing what is on display in the master branch of the repo’s made available. This was performed as an educational review and any comments in the article are the opinion of the writer. It is normal for code to change rapidly, hence we timestamp our code reviews so that they present a snapshot at a moment in time. Information contained herein should not be used as any comment or advice on the project as a whole.
COTI Code Review Timestamp: November 18th 2018