This guide explains how the Mina Privacy Framework integrates with Zcash shielded transactions.
The framework connects to a Zcash node via JSON-RPC to:
- Generate shielded (z-addr) addresses
- Send shielded transactions with memos
- Query shielded balances
- Create cross-chain proofs for Mina zkApps
# Create config directory
mkdir -p /tmp/zcash-data
# Create config file
cat > /tmp/zcash-data/zcash.conf << 'EOF'
regtest=1
rpcuser=zcashuser
rpcpassword=zcashpass
rpcallowip=0.0.0.0/0
rpcbind=0.0.0.0
nuparams=5ba81b19:1
nuparams=76b809bb:1
nuparams=2bb40e60:1
nuparams=f5b9230b:1
nuparams=e9ff75a6:1
nuparams=c2d6d0b4:1
i-am-aware-zcashd-will-be-replaced-by-zebrad-and-zallet-in-2025=1
allowdeprecated=z_getnewaddress
allowdeprecated=z_getbalance
allowdeprecated=getnewaddress
exportdir=/srv/zcashd/.zcash/exports
txindex=1
EOF
# Start container
docker run -d --name zcashd-regtest \
--platform linux/amd64 \
-p 18232:18232 \
-v /tmp/zcash-data:/srv/zcashd/.zcash \
electriccoinco/zcashd:latest
# Wait for startup
sleep 30
# Set higher transaction fee (required for NU5)
curl -s -X POST http://localhost:18232 \
-u zcashuser:zcashpass \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":"1","method":"settxfee","params":[0.001]}'
# Mine initial blocks (101 for mature coins)
curl -s -X POST http://localhost:18232 \
-u zcashuser:zcashpass \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":"1","method":"generate","params":[101]}'cd joi
export ZCASH_RPC_URL=http://localhost:18232
export ZCASH_RPC_USER=zcashuser
export ZCASH_RPC_PASSWORD=zcashpass
npm test -- src/integration/zcash-rpc-integration.test.tsimport { createRealZcashPool } from './zcash/ShieldedPool';
// Connect to Zcash node
const pool = createRealZcashPool(
'http://localhost:18232',
'zcashuser',
'zcashpass'
);
// Generate shielded address
const zAddr = await pool.generateShieldedAddress();
console.log(zAddr); // zregtestsapling1...
// Check balance
const balance = await pool.getBalance(zAddr);
console.log(`Balance: ${balance} ZEC`);// Send shielded transaction with memo
const opId = await pool.sendShielded(
fromZAddr,
toZAddr,
0.5, // amount in ZEC
'Private memo' // encrypted memo
);
// Wait for confirmation
const txid = await rpcClient.waitForOperation(opId, 60000);
console.log(`Transaction: ${txid}`);import { PublicKey } from 'o1js';
// Map Mina key to Zcash address
pool.mapAddress(minaPublicKey, zcashAddress);
// Retrieve mapping
const zAddr = pool.getZcashAddress(minaPublicKey);
// Create cross-chain proof (for oracle verification)
const proof = await pool.createCrossChainProof(txid);| Method | Description |
|---|---|
getblockchaininfo |
Network status and block height |
z_getnewaddress |
Generate new shielded address |
z_getaddressforaccount |
Generate from HD account (new API) |
z_getbalance |
Query shielded address balance |
z_sendmany |
Send shielded transaction |
z_shieldcoinbase |
Shield coinbase rewards |
z_getoperationstatus |
Check async operation status |
generate |
Mine blocks (regtest only) |
- Full control over blockchain
- Mine blocks instantly
- No external dependencies
- All network upgrades active
- Real testnet blockchain
- Requires testnet ZEC (from faucet)
- Slower sync time
# zcash.conf options used
regtest=1 # Enable regtest mode
rpcuser=zcashuser # RPC username
rpcpassword=zcashpass # RPC password
rpcbind=0.0.0.0 # Listen on all interfaces
txindex=1 # Enable transaction index
# Network upgrade activation (all at block 1 for regtest)
nuparams=5ba81b19:1 # Overwinter
nuparams=76b809bb:1 # Sapling
nuparams=2bb40e60:1 # Blossom
nuparams=f5b9230b:1 # Heartwood
nuparams=e9ff75a6:1 # Canopy
nuparams=c2d6d0b4:1 # NU5
# Required deprecation acknowledgment
i-am-aware-zcashd-will-be-replaced-by-zebrad-and-zallet-in-2025=1
# Allow deprecated methods we use
allowdeprecated=z_getnewaddress
allowdeprecated=z_getbalance
allowdeprecated=getnewaddressSet a higher transaction fee:
curl -X POST http://localhost:18232 \
-u zcashuser:zcashpass \
-d '{"method":"settxfee","params":[0.001]}'Ensure nuparams are set correctly in zcash.conf to activate Sapling at block 1.
Wait for zcashd to fully start (30+ seconds on first run).
Use --platform linux/amd64 flag (runs via Rosetta emulation).
Real transactions executed on regtest:
-
Shield Operation (0.9 ZEC)
- TXID:
565d329a167730b8b70874cc793d81a63c66ba4153d4c3cd456ef85596e0333b
- TXID:
-
Shielded Transfer (0.3 ZEC with memo)
- TXID:
0ae9ffaa6cb4fb49aaf0578313589cdaac442a53a124b8f8a7b13d616a20f887
- TXID:
See INTEGRATION_TEST_RESULTS.md for full test output.