npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@cheny56/zk-confidential-onchain

v1.0.0

Published

Confidential smart contracts using native ZK precompile (0x16). Optimized for PQC-Quorum nodes with ~10x gas savings.

Readme

@cheny56/zk-confidential-onchain

Confidential Smart Contracts using Native ZK Precompile

A privacy-preserving token system optimized for PQC-Quorum nodes with native ZK support:

  • Inputs are private - Transfer amounts are hidden
  • State is hidden - Balances stored as commitments
  • Only proofs are public - ZK proofs verify correctness without revealing data
  • Native verification - Uses precompile at 0x16 for ~10x gas savings

npm version License: MIT

Features

  • Native Precompile - ~500K gas vs ~5M gas for Solidity verification
  • 🔐 Go Prover - Uses gnark for fast, reliable proof generation
  • 🔒 Full Privacy - Balances, transfers, identities all hidden
  • 🏢 Enterprise Ready - Designed for PQC-Quorum private networks

Prerequisites

This package requires:

  1. PQC-Quorum node with ZK precompile enabled at 0x16
  2. Go 1.21+ for proof generation
  3. Node.js 18+ for the client SDK

Installation

npm install @cheny56/zk-confidential-onchain

Quick Start

1. Build the Go Prover

cd go
go build -o ../bin/prover ./prover

2. Use the Client

const { ConfidentialTokenClient } = require('@cheny56/zk-confidential-onchain/client');

// Initialize client
const client = new ConfidentialTokenClient({
    provider: provider,
    signer: wallet,
    contractAddress: '0x...',
    proverPath: './bin/prover',  // Path to Go prover binary
});

await client.init();

// Deposit 1 ETH privately
const { note } = await client.deposit(ethers.parseEther('1'));
console.log('Private balance:', client.getBalance());

// Transfer 0.5 ETH to someone
const recipientSecret = client.generateRecipientSecret();
await client.transfer(ethers.parseEther('0.5'), recipientSecret);

// Withdraw to public address
await client.withdraw(ethers.parseEther('0.3'), recipientAddress);

Architecture

┌─────────────────────────────────────────────────────────────────────────────┐
│                    ON-CHAIN ZK CONFIDENTIAL TOKEN                            │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│   ┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐        │
│   │   JavaScript    │    │   Go Prover     │    │   Quorum Node   │        │
│   │   Client SDK    │    │   (gnark)       │    │   (Precompile)  │        │
│   └────────┬────────┘    └────────┬────────┘    └────────┬────────┘        │
│            │                      │                      │                 │
│            ▼                      ▼                      ▼                 │
│   ┌─────────────────────────────────────────────────────────────────┐      │
│   │                                                                  │      │
│   │   1. Client prepares transaction inputs                         │      │
│   │   2. Client calls Go prover binary with inputs                  │      │
│   │   3. Prover generates Groth16 proof using gnark                 │      │
│   │   4. Client sends proof to ConfidentialToken contract           │      │
│   │   5. Contract calls precompile at 0x16 to verify                │      │
│   │   6. Precompile verifies in ~500K gas (vs ~5M Solidity)         │      │
│   │                                                                  │      │
│   └─────────────────────────────────────────────────────────────────┘      │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘

Precompile Interface

The ZK precompile at address 0x16 provides:

// Verify a Groth16 proof
function verifyGroth16(
    bytes32 vkHash,       // Hash of verification key
    bytes proof,          // The ZK proof
    bytes publicInputs    // Public inputs to the circuit
) external view returns (bool);

// Register a verification key
function registerVK(
    bytes vk              // Serialized verification key
) external returns (bytes32 vkHash);

Table of Contents

How It Works

Deposit Flow

User                    Client                  Go Prover           Contract
  │                        │                        │                   │
  │──deposit(amount)──────>│                        │                   │
  │                        │──generateMintProof────>│                   │
  │                        │<──────proof────────────│                   │
  │                        │                        │                   │
  │                        │──────deposit(commitment, proof)───────────>│
  │                        │                        │      ┌────────────┴────┐
  │                        │                        │      │ staticcall 0x16 │
  │                        │                        │      │ verifyGroth16() │
  │                        │                        │      └────────────┬────┘
  │<───────────────────────│<──────────────────────tx confirmed─────────│

Transfer Flow (Private → Private)

  1. Select input notes - Find unspent notes totaling transfer amount
  2. Create output notes - Recipient note + change note
  3. Compute nullifier - Prevents double-spending
  4. Generate ZK proof - Proves ownership and value conservation
  5. Submit transaction - Contract verifies via precompile

Go Prover Setup

Directory Structure

go/
├── circuits/
│   ├── mint_circuit.go      # Mint circuit definition
│   └── transfer_circuit.go  # Transfer circuit definition
├── prover/
│   └── prover.go            # Main prover binary
├── go.mod
└── go.sum

Building

cd go
go mod tidy
go build -o ../bin/prover ./prover

Testing the Prover

# Generate a test proof
./bin/prover mint \
  --value=1000 \
  --secret=0x1234... \
  --nonce=0x5678...

API Reference

ConfidentialTokenClient

const client = new ConfidentialTokenClient({
    provider,           // Ethers provider
    signer,            // Ethers signer
    contractAddress,   // Contract address
    proverPath,        // Path to Go prover binary
    demoMode,          // Skip proofs for testing (default: false)
});

// Initialize
await client.init(masterSecret?);

// Deposit (public → private)
const { note, tx } = await client.deposit(amount);

// Transfer (private → private)
const { recipientNote, changeNote, tx } = await client.transfer(amount, recipientSecret);

// Withdraw (private → public)
const { tx } = await client.withdraw(amount, recipientAddress);

// Query
client.getBalance();          // Total private balance
client.getSpendableNotes();   // Spendable notes
client.exportWallet();        // Backup wallet

// Utility
const secret = client.generateRecipientSecret();  // Generate recipient secret

Note

const { Note } = require('@cheny56/zk-confidential-onchain/lib');

// Create manually
const note = new Note(value, ownerSecret, nonce?);
await note.init();

// Properties
note.value;           // Note amount
note.commitment;      // Public commitment
note.nullifier;       // Nullifier (after tree position set)
note.canSpend();      // Check if spendable

MerkleTree

const { MerkleTree } = require('@cheny56/zk-confidential-onchain/lib');

const tree = new MerkleTree(20);  // depth 20
await tree.init();

const index = await tree.insert(commitment);
const { path, indices } = await tree.generateProof(index);
const valid = await tree.verifyProof(leaf, index, path, indices, root);

Step-by-Step Guide

Step 1: Setup Environment

# Clone repository
git clone https://github.com/cheny56/zk-confidential-onchain
cd zk-confidential-onchain

# Install dependencies
npm install

# Build Go prover
cd go && go build -o ../bin/prover ./prover && cd ..

Step 2: Deploy Contract

const { ethers } = require('ethers');
const ConfidentialToken = require('./artifacts/ConfidentialToken.json');

// Connect to PQC-Quorum node
const provider = new ethers.JsonRpcProvider('http://localhost:8545');
const wallet = new ethers.Wallet(PRIVATE_KEY, provider);

// Deploy contract
const factory = new ethers.ContractFactory(
    ConfidentialToken.abi,
    ConfidentialToken.bytecode,
    wallet
);

const token = await factory.deploy(
    'Private Token',
    'PRIV',
    mintVKHash,      // Hash of mint verification key
    transferVKHash,  // Hash of transfer verification key
    withdrawVKHash   // Hash of withdraw verification key
);

console.log('Contract deployed:', await token.getAddress());

Step 3: Register Verification Keys

// The verification keys are registered on first use or can be pre-registered
// The Go prover outputs the verification keys during setup

// Register via precompile (one-time)
const precompile = new ethers.Contract('0x0000000000000000000000000000000000000016', [
    'function registerVK(bytes vk) returns (bytes32)'
], wallet);

const mintVKHash = await precompile.registerVK(mintVKBytes);
const transferVKHash = await precompile.registerVK(transferVKBytes);

Step 4: Use the Client

const { ConfidentialTokenClient } = require('@cheny56/zk-confidential-onchain/client');

const client = new ConfidentialTokenClient({
    provider,
    signer: wallet,
    contractAddress: await token.getAddress(),
    proverPath: './bin/prover',
});

await client.init();
client.setContract(token);

// Deposit 1000 wei
await client.deposit(1000n);
console.log('Balance:', client.getBalance());

// Transfer 300 to someone
const recipientSecret = client.generateRecipientSecret();
await client.transfer(300n, recipientSecret);

// Withdraw 200 to public address
await client.withdraw(200n, '0x...');

Step 5: Verify Setup

# Run verification example
node examples/verify-setup.js

Contract Deployment

Deploy Script

node scripts/deploy.js

Manual Deployment

const { ethers } = require('ethers');

async function deploy() {
    const provider = new ethers.JsonRpcProvider('http://localhost:8545');
    const wallet = new ethers.Wallet(PRIVATE_KEY, provider);
    
    // Read contract artifact
    const artifact = require('./artifacts/ConfidentialToken.json');
    
    // Deploy
    const factory = new ethers.ContractFactory(
        artifact.abi,
        artifact.bytecode,
        wallet
    );
    
    // Verification key hashes (from Go prover setup)
    const mintVKHash = '0x...';
    const transferVKHash = '0x...';
    const withdrawVKHash = '0x...';
    
    const contract = await factory.deploy(
        'Confidential Token',
        'CONF',
        mintVKHash,
        transferVKHash,
        withdrawVKHash
    );
    
    await contract.waitForDeployment();
    console.log('Deployed to:', await contract.getAddress());
}

Performance

Gas Comparison

| Operation | Native Precompile | Solidity Verifier | Savings | |-----------|-------------------|-------------------|---------| | Mint | ~400K gas | ~3M gas | 87% | | Transfer | ~600K gas | ~5M gas | 88% | | Withdraw | ~500K gas | ~4M gas | 87% |

Proof Generation Time

| Circuit | Time (Go/gnark) | Time (snarkjs) | |-----------|-----------------|----------------| | Mint | ~100ms | ~2s | | Transfer | ~500ms | ~10s | | Withdraw | ~300ms | ~5s |

Security Considerations

  1. Trusted Setup: The circuit requires a one-time trusted setup
  2. Precompile Trust: The native precompile must be trusted
  3. Prover Isolation: Run the Go prover in a secure environment
  4. Key Management: Protect master secrets and backups
  5. Nullifier Tracking: On-chain nullifier set prevents double-spending

Package Contents

zk-confidential-onchain/
├── lib/
│   ├── index.js           # Main exports
│   ├── mimc.js            # MiMC hash (gnark compatible)
│   ├── merkle.js          # Merkle tree
│   └── note.js            # Note management
├── client/
│   └── confidential-client.js  # Contract interaction
├── contracts/
│   ├── ConfidentialToken.sol
│   └── CommitmentTree.sol
├── go/
│   ├── circuits/          # gnark circuit definitions
│   └── prover/            # Prover binary
├── examples/
│   ├── basic-balance.js
│   ├── transfer-simulation.js
│   └── verify-setup.js
├── scripts/
│   └── deploy.js
├── package.json
└── README.md

License

MIT

Related