I’m obviously biased, but since I’m probably the only one who thoroughly studied and understands both codebases, here’s my take:
WALLET
The Grin++ wallet was designed to be more secure from the beginning. Much greater care was taken when dealing with any secrets, using a much stronger PBKDF, never storing any unencrypted passwords or private keys in memory, using secure memory containers that prevent paging and immediately clear from memory after being used, and never storing the session key (used to decrypt secrets) in the same process as the encrypted secrets.
grin-wallet, OTOH, uses a typical PBKDF not necessarily designed for protecting funds for an immutable ledger, and originally stored the wallet password in plaintext in the same process as the node. However, grin-wallet has come a very long way since the early days, and has eliminated most of these early weaknesses by adopting a similar token mechanism, splitting node process from the wallet, and even optionally encrypting communications over the owner APIs. So design-wise now, they both have decent security properties.
Grin-wallet has been fully audited, whereas Grin++ is still mid-audit. Grin-wallet has also had more eyes on it, but not like you would expect. Most PRs are merged with maybe 1 approver, if any (I look at all grin-wallet PRs, but don’t usually thoroughly review). 95ish% of the code was written by Yeast, whereas the Grin++ code is 99.9ish% written and reviewed by myself. So grin-wallet is a little better in that aspect, but both codebases are desperately in need of more critical reviewers.
NODE
The Grin++ node is significantly faster and more reliable than the grin node at most operations. Being written by a single person was a huge advantage, because I could design every part to work together with the whole picture in mind, which led to a simpler and faster design. However, the grin node has had way more developers, significantly more reviewers, and a full audit. Regarding security, even though I’m not aware of any security issues with Grin++, the grin node should be considered more secure.
NIFFLER
Regarding Niffler, it’s hard to say. It’s been a long time since I’ve looked at the code, and the last time I did was back before the session token mechanism was implemented, when passwords were still stored plaintext in RAM. Maybe @xiaojay can chime in about whether he has switched to the new APIs yet.
OTHER
Rust is noisy AF, and its compiler makes me want to punch a wall, but it’s a much more memory-secure language. I monitor Grin++ memory closely, but there’s a far greater chance of a buffer overflow resulting in some kind of remotely exploitable vulnerability. fwiw, the only remotely exploitable vulnerability found so far only affected grin, not Grin++, but I’m nowhere near ready to take a victory lap yet
Regarding “battle-tested”, both are used quite heavily. While grin is obviously used by more people, it’s only by about twice as many people, if you trust the peers lists of some of the seed nodes. I have access to the peers list on a few, and the network appears to fluctuate between 30-35% of Grin++ nodes. However, all exchanges and pools use grin-wallet, so many more transactions come from grin-wallet, or a modified version of it, and I’m sure it’s responsible for protecting a far greater number of grins.
TL;DR
They each have pros and cons. I’m not aware of any serious security issues with either of them, but the grin protocol is still very new, so it’s better to act as if they’re both still in beta.