Hey all!

Decided to write up a little post about how I went about implementing BIP47 Reusable Payment Codes into Crescent Cash (via bitcoincashj).

Development started off by finding a nearly two year old pull request into https://github.com/bitcoinj-cash/bitcoinj, here: https://github.com/bitcoinj-cash/bitcoinj/pull/39

After taking a look at the code that kmels wrote, it seemed like this could work. I implemented kmels' pull request into my own bitcoincashj repository (I am the current maintainer of bitcoincashj/bitcoinj-cash), and got to prototyping in the wallet-template module of the bitcoincashj project in IntelliJ.

It didn't work basically at all. Apparently, when kmels was testing stuff or working on the BIP47 portion, he left out a lot of code that made the BIP47AppKit.java class complete, and function as expected. There were a lot of unused methods, and comments in his code indicated those methods should be used. BIP47AppKit in its original state wouldn't even properly start. I took the liberty of changing BIP47AppKit and made it how SLPAppKit was made. Now it worked and synced very quickly. Yet a lot of BIP47 functions were a bit buggy, and we still had a lot of unused and important methods!

One such example is rescanTxBlock in BIP47AppKit.java (https://github.com/pokkst/bitcoincashj/blob/master/core/src/main/java/org/bitcoinj/kits/BIP47AppKit.java#L535). This method was unused, but addTransactionsListener (https://github.com/pokkst/bitcoincashj/blob/master/core/src/main/java/org/bitcoinj/kits/BIP47AppKit.java#L247) had a comment that indicated the chain was to be rolled-back 2 blocks upon receiving a BIP47 notification transaction, yet rescanTxBlock was never called.

So, I worked on implementing rescanTxBlock into addTransactionsListener, and for some reason the initial transaction to a BIP47 address AFTER the BIP47 notification transaction didn't work 100% of the time. When I was testing, my test wallets usually only had one to two UTXOs at a given time. So the transaction to the first BIP47 payment address was usually a child transaction of the notification transaction, and when rescanning the notification transaction block, this would cause issues.

To solve this, I toyed around with rescanTxBlock, and found out the reason the transaction to the BIP47 payment address (the one immediately after the notification transaction) wasn't being recognized was because of the possibility of it being a child to the notification transaction. I simply called a few methods to remove the notification transaction from the wallet (it's not really needed anyway once the BIP47 payment channel is saved in the local .bip47 metadata file). Notification transactions would clutter the transactions list anyway.

Another issue was the fact that when sending a payment to a BIP47 payment address, the index in the payment channel would not increment. Turns out, this wasn't called anywhere in kmels code, so in Crescent Cash I call it manually after creating a BIP47 payment, and save the channel state. This is for greater privacy, as if the index was never incremented upwards then each BIP47 payment would always go to the respective channel's first address in the list.

Next was dealing with Cash Accounts in regards to BIP47 payment codes. Cash Accounts has support for V1 of payment codes already, but the /register/ endpoint to the Cash Account API did not support sending payment codes in the payments array of the registration JSON. I contacted Johnathan Silverblood and he worked on getting that working, and got it done very quickly. :)

Next I worked on programming an "upgrade" system into Crescent Cash that would re-register all wallets with new Cash Accounts that support both BIP47 payment codes and normal Bitcoin Cash addresses.

After getting the core system working in Crescent Cash Android and Desktop, I worked on UI stuff like an address toggle on the receive screen for switching between the BIP47 payment code and the wallet's Bitcoin Cash addresses.

And now Crescent Cash is the first Bitcoin Cash wallet that has private Cash Accounts!

The update will be going live later today.

-pokkst