Integrating Zcash Shielded Transactions on SideShift AI
Zcash has two types of addresses/payments. A transparent, t-address, is just like a Bitcoin address and uses the same commands as the Bitcoin Core API I’m used to. A shielded address, often referred to as a z-address conceals the sender, recipient, and amount of transactions. Using z-addresses appears to require a new set of commands prefixed with z_
, such as z_getnewaddress
.
SideShift AI already has support for shifting to and from t-addresses which uses the exact same code as used for Bitcoin, Litecoin, and more.
Detecting deposits
For detecting incoming deposits, we won’t be able to look through every transaction in every block and see if it’s to us. The privacy technology makes this impossible. I notice a couple of commands that can be helpful:
z_listreceivedbyaddress
: We could assign a new z-address to every SideShift AI order and pollz_listreceivedbyaddress
to see if it has returns a transaction previously not processed. This could become a performance issue if the number of addresses is large, but I’m fine with it.z_listunspent
: This command will list all the funds we’ve received that aren’t spent. We could poll this command to notice new transactions.
I’ll try z_listunspent
first and see if I can make it work. But first I’ll need to let users choose it as a deposit option:
Most of the code from t-addresses can be re-used and I can add z-address as a deposit option quite quickly.
The order details page also renders fine.
I have a balance in ZEC, but it’s held in a t-address. Can I send from a t-address to a z-address? I’ll try to find out.
Nope, that doesn’t work. Maybe there’s a different command for this.
It seems there’s only z_sendmany
:
It interestingly specifies the from-address. This can become useful when implementing withdrawals later. I use listunspent
to see which addresses have funds in them:
z_commands are async, probably because they can be slow due to the advanced cryptography used. I check the progress:
The transaction was sent! I check z_getbalance
for unconfirmed funds:
I wait for a confirmation and see what z_listunspent
returns:
I’ll make some code that polls z_listunspent:
Only 60 lines. I try to run it:
I’ll try another just to be sure.
And wait for 10 confirmations.
The deposit was credited and the shift to LTC completed. Next I’ll look at handing shifts to z-addresses.
Sending settlements
By polling z_listunspent
to detect deposits we have a problem when settling by sending outgoing z-address transactions. We could create a race condition where:
- Alice starts a shift from z-addr to BTC
- Bob starts a shift from BTC to the z-addr
- Alice sends in 10 ZEC to the z-addr
- Alice sends in 2.5 ZEC to the z-addr
- Bob sends in 0.1 BTC to the Bitcoin address
- SideShift AI detects and credits the 10 ZEC from Alice
- SideShift AI detects and credits the 0.1 BTC from Bob
- SideShift sends out 7 ZEC as settlement to Bob, which spends both the 2.5 ZEC and the 10 ZEC from Alice with a change output of 5.5 ZEC
- SideShift polls
z_listunspent
but does not see the 2.5 ZEC from Alice, because it was already spent to settle for Bob
The command we’ll be using to send funds is z_sendmany
. It looks like this:
We can supply a fromaddress
! This means we can choose a single address and always send from that one. Sure, we might end up spending some extra money on fees when consolidating, but that’s acceptable.
I make a new z-address that’ll serve as the hot wallet.
Let’s try coding this up:
And give it a shot:
It settles in an acceptable time, in just under a minute:
Closing remarks
There are probably a thousand more clever ways of doing this, but at SideShift AI the focus is to get product out the door fast and then iterate.
I haven’t even checked that the amounts and fees are done exactly correct yet, which our dear TEST PILOTS will assist with.
Ready to become a TEST PILOT? See https://sideshift.ai/pilot