跳到主要内容
// 文档版本:1.0.0文書

NixProtocol 文档

加载文档模块中

为您的应用添加基于 UTXO 的隐私支付。NixProtocol 使用 Noir ZK 电路和 Grumpkin 曲线密码学,为 EVM 链提供隐私池协议。测试网已在 Avalanche Fuji & Base Sepolia 上线。

测试网已上线Avalanche FujiBase SepoliaAvalancheEthereum

架构概述

ARCH_001

NixProtocol 通过结合加密、零知识证明和智能合约的分层架构提供隐私。

系统架构
您的应用
@nixprotocol/nix-wallet
Key Gen
(Grumpkin)
ECIES
Encrypt
ZK Proof Generator
(UltraHonk/Noir)
Smart Contracts
NixPool
(Privacy Pool)
Merkle Trees
(Note Storage)
UltraHonk Verifier
(Proof Verification)
Avalanche Fuji|Base Sepolia|Avalanche|Ethereum

数据流

01
Client Side
  • Derive Grumpkin keypair via Poseidon2
  • Encrypt notes with ECIES
  • Generate UltraHonk proofs locally
  • Authorize via ZK proofs (no signatures)
02
On-Chain
  • Verify ZK proofs
  • Store note commitments in Merkle tree
  • Verify nullifiers & update roots
  • Emit privacy-preserving events
03
Auditor Access
  • Selective disclosure keys
  • View-only access grants
  • Compliance reporting
  • Audit trail generation

关键组件

GRP
Grumpkin Curve

Embedded elliptic curve for ZK-friendly operations. Used for keypairs, ECIES encryption, and NixAddress encoding. Native to Noir circuits via Barretenberg.

UH
UltraHonk Proofs

Compiled from Noir circuits via Barretenberg. No trusted setup required. 3 circuits: deposit, registration, and transact.

PSN
Poseidon2 Hash

ZK-optimized hash function used for note commitments, nullifiers, and Merkle trees. Poseidon2 variant for improved performance in Noir circuits.

快速开始

QUICK_START

5 分钟内上手运行。生成密钥、加密数据并创建证明。

1

安装 SDK

bash
npm install @nixprotocol/nix-wallet viem
2

生成密钥对

typescript
import { deriveNixKeyFromSignature } from '@nixprotocol/nix-wallet';

// Deterministic from wallet signature (recommended)
// Signs "NixProtocol key derivation v3", then Poseidon2-hashes the signature
const keyPair = await deriveNixKeyFromSignature(walletClient);

console.log('Public Key:', keyPair.publicKey);    // { x: bigint, y: bigint }
console.log('Commitment:', keyPair.commitment);   // Poseidon2(pk.x, pk.y)
console.log('Private Key:', keyPair.privateKey);  // Grumpkin scalar
3

加密并创建笔记

typescript
import { ecies, poseidon2Hash } from '@nixprotocol/nix-wallet';

// Encrypt a note value to recipient's Grumpkin public key
const randomness = BigInt('0x' + crypto.randomUUID().replace(/-/g, ''));
const ciphertext = ecies.encrypt(1000n, randomness, recipientPublicKey);

// Decrypt (only recipient can do this)
const decrypted = ecies.decrypt(privateKey, ciphertext.authKeyX, ciphertext.authKeyY, ciphertext.encrypted);

// Create note commitment
const commitment = poseidon2Hash([value, ownerPkX, ownerPkY, salt]);

安装

PKG_INSTALL

NixProtocol 以一组 NPM 包的形式提供,适用于不同的集成需求。

PKG.01
@nixprotocol/nix-walletBUSL-1.1

Core wallet library - key derivation, encryption, proofs, NixAddress, and UTXO management

PKG.02
@nixprotocol/contractsBUSL-1.1

NixPool Solidity contracts and TypeScript bindings

PKG.03
@nixprotocol/relayerBUSL-1.1

Gas abstraction with ZK proof authorization

加密

NixProtocol 使用基于 Grumpkin 曲线的 ECIES 加密来加密 UTXO 笔记数据和审计员可访问的交易记录。

关键属性

  • Asymmetric Encryption: Encrypt data to any Grumpkin public key
  • Probabilistic: Same plaintext encrypts differently each time
  • ZK-Friendly: Grumpkin curve is native to Noir circuits via Barretenberg

数学基础

Grumpkin Curve

Embedded elliptic curve native to Barretenberg/Noir:

Short Weierstrass curve: y² = x³ - 17 (embedded curve of BN254)
ECIES Encryption

For message m, recipient public key P = sG:

Encrypt: Generate ephemeral keypair (r, R=rG), shared secret S=rP, encrypt m with symmetric key derived from S
Decrypt: Compute S=sR, derive symmetric key, decrypt m
Note Commitments

Note commitments use Poseidon2 hash: commitment = Poseidon2(value, ownerPubKey, salt). Nullifiers prevent double-spending: nullifier = Poseidon2(commitment, privateKey).

安全参数

Curve Security

~128-bit security level (Grumpkin curve, embedded in BN254)

Ephemeral Keys

Fresh random ephemeral key per encryption

Note Size

Commitment (1 field element) + ECIES-encrypted data

Merkle Depth

20 levels supporting ~1M notes

零知识证明

NixProtocol 使用通过 Barretenberg 从 Noir 电路编译的 UltraHonk 证明。无需可信设置。

Registration Circuit

Proves knowledge of Grumpkin private key corresponding to registered public key

Deposit Circuit

Creates a new UTXO note commitment from an ERC-20 deposit with ECIES-encrypted data

Transact Circuit

Consumes 2 input notes, creates 2 output notes. Proves Merkle membership, correct nullifiers, and value conservation

NixAddress 和 UTXO 笔记

NixAddress 使用紧凑的 Grumpkin 公钥作为您真实 EVM 地址的别名。分享它即可在隐私池中接收 UTXO 笔记,而不会暴露您的链上身份。

typescript
import { deriveNixKeyFromSignature, nixAddressFromKeyPair,
  encodeNixAddress, decodeNixAddress } from '@nixprotocol/nix-wallet';

// Derive keypair from wallet signature
const keyPair = await deriveNixKeyFromSignature(walletClient);
const nixAddress = nixAddressFromKeyPair(keyPair);
console.log('NixAddress:', nixAddress);
// nix:<commitment>:<pk.x>:<pk.y>

// Decode to get commitment + public key
const { commitment, publicKey } = decodeNixAddress(nixAddress);

合规与审计员访问

兼顾隐私与问责。每个 NixPool 都有一个指定的审计员,持有在部署时设定的单个 Grumpkin 私钥。此密钥可以解密 ECIES 加密的笔记数据以用于合规报告。

工作原理

1
Auditor Key Assignment

A single Grumpkin private key is designated as the auditor key when the NixPool is deployed. The corresponding public key is stored on-chain.

2
ECIES Encryption

Transaction data is ECIES-encrypted to the auditor's Grumpkin public key during each deposit and transfer.

3
Compliance Decryption

The auditor uses their Grumpkin private key to decrypt note data, revealing amounts and ownership for compliance reporting.

实现

typescript
import { NixAuditorClient } from '@nixprotocol/nix-wallet';

// Initialize auditor client with the designated Grumpkin private key
const auditorClient = new NixAuditorClient({
  auditorPrivateKey: process.env.AUDITOR_GRUMPKIN_KEY,
  poolAddress: '0x94e5f37c557dA9B2C0F0636BbCDB3743B30Ba6B1', // NixPool on Fuji
});

// Decrypt ECIES-encrypted note data from on-chain events
const decryptedNotes = await auditorClient.decryptPoolNotes({
  fromBlock: 1000000,
  toBlock: 'latest',
});

// Generate compliance report from decrypted data
const report = await auditorClient.generateComplianceReport({
  notes: decryptedNotes,
  fromDate: '2025-01-01',
  toDate: '2025-12-31',
});

审计员可以看到什么

Note Amounts

Decrypt UTXO note values from ECIES-encrypted on-chain data

Note Ownership

Identify note owners via decrypted Grumpkin public keys

Transaction Flow

Trace deposit, transfer, and withdrawal activity across the pool

监管兼容:专为需要审计追踪、税务报告和监管合规的机构设计,同时对公众保持用户隐私。

SDK 概述

@nixprotocol/nix-wallet 包是大多数集成的主要入口点。

导出

deriveNixKeyFromSignature(walletClient) - Deterministic keypair from wallet signature via Poseidon2
generateNixKeyPair() - Random Grumpkin keypair
ecies.encrypt(data, pubKey) - ECIES encrypt to Grumpkin key
ecies.decrypt(ciphertext, privKey) - Decrypt ECIES ciphertext
poseidon2.hash(inputs) - Poseidon2 hash function
createNoteCommitment(value, pubKey, salt) - Create UTXO note commitment

密钥生成

生成 Grumpkin 密钥对用于加密和证明生成。密钥通过 Poseidon2 哈希从 EVM 钱包签名确定性推导,确保同一钱包始终生成相同的 NixProtocol 私钥。

重要提示:生产环境中请使用基于钱包签名的确定性密钥推导。随机密钥对需要安全的私钥存储。

ECIES 加密

基于 Grumpkin 曲线的 ECIES 加密,用于加密笔记数据和审计员记录。

typescript
import { ecies } from '@nixprotocol/nix-wallet';

// ECIES ciphertext structure
interface ECIESCiphertext {
  authKeyX: bigint;    // Ephemeral Grumpkin point x
  authKeyY: bigint;    // Ephemeral Grumpkin point y
  encrypted: bigint;   // Encrypted value
}

// Encrypt note data to recipient's Grumpkin public key
const randomness = BigInt('0x' + crypto.randomUUID().replace(/-/g, ''));
const encrypted = ecies.encrypt(value, randomness, recipientPublicKey);

// Decrypt (only recipient can do this)
const decrypted = ecies.decrypt(privateKey, encrypted.authKeyX, encrypted.authKeyY, encrypted.encrypted);

// Auditor can also decrypt with auditor key
const auditValue = ecies.decrypt(auditorPrivateKey, auditCt.authKeyX, auditCt.authKeyY, auditCt.encrypted);

Nix ID

Nix ID 是一个可分享的支付标识符,编码了您的 Grumpkin 公钥承诺和坐标,用于在隐私池中接收 UTXO 笔记。

NixAddress format:

nix:<commitment>:<pk.x>:<pk.y>

Commitment is Poseidon2(pk.x, pk.y), ensuring address integrity is self-verifiable.

智能合约概述

NixProtocol 智能合约处理链上隐私操作,包括 UTXO 笔记管理和 ZK 证明验证。

NixPool

Main privacy pool contract: deposits, transfers, withdrawals with UTXO notes

Merkle Trees

Poseidon2-based Merkle trees (depth 20) for note commitment storage

UltraHonk Verifier

On-chain proof verification for all 3 circuits

NixPool Contract

基于 UTXO 的隐私支付的主要隐私池合约。

solidity
// Register Grumpkin public key with ZK proof
function register(
    bytes calldata proof,
    bytes32 publicKeyHash
) external;

// Deposit ERC-20 tokens, creating a UTXO note
function deposit(
    address token,
    uint256 amount,
    bytes calldata proof,
    bytes32 noteCommitment
) external;

// Transact: consume 2 input notes, create 2 output notes
function transact(
    bytes calldata proof,
    bytes32[2] calldata nullifiers,
    bytes32[2] calldata newCommitments,
    bytes calldata encryptedNotes
) external;

NixPool

UTXO 笔记承诺的默克尔树存储。

solidity
// Merkle tree stores note commitments
function getMerkleRoot() external view returns (bytes32);

// Check root history (last 100 roots valid)
function isKnownRoot(bytes32 root) external view returns (bool);

// Check if nullifier has been used
function isSpent(bytes32 nullifier) external view returns (bool);

// Get current note index
function nextIndex() external view returns (uint256);

已部署地址

合约部署即将推出。

参考实现。安全审计进行中。审计完成前请勿部署大额资金。

隐私 ERC-20 指南

5 步为任何 ERC-20 代币添加基于 UTXO 的隐私支付。

  1. 1Deploy NixPool contract for your ERC-20 token
  2. 2Users register with Grumpkin public key
  3. 3Deposit converts public tokens to UTXO notes
  4. 4Transact consumes input notes, creates output notes
  5. 5Withdraw burns notes and releases public tokens

完整集成示例

typescript
import { createWalletClient, custom } from 'viem';
import {
  deriveNixKeyFromSignature,
  generateRegistrationProof,
  generateDepositProof,
  generateTransactProof,
  ecies,
  poseidon2,
  createNoteCommitment
} from '@nixprotocol/nix-wallet';
import { NixPool__factory } from '@nixprotocol/contracts';

// Setup
const walletClient = createWalletClient({
  transport: custom(window.ethereum),
  account: userAddress,
});

// Step 1: Derive keypair from wallet signature (deterministic via Poseidon2)
// Signs "NixProtocol key derivation v3", splits sig into 3 chunks,
// then Poseidon2-hashes them to produce a valid Grumpkin scalar
const keyPair = await deriveNixKeyFromSignature(walletClient);

// Step 2: Register (one-time per address)
const isRegistered = await nixPool.isRegistered(userAddress);
if (!isRegistered) {
  const regProof = await generateRegistrationProof(keyPair);
  const regTx = await nixPool.register(regProof, keyPair.commitment);
  await regTx.wait();
}

// Step 3: Deposit - convert public tokens to UTXO note
const USDC_ADDRESS = '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48';
const amount = 100_000000n; // 100 USDC (6 decimals)

// First approve
await usdc.approve(NIX_POOL_ADDRESS, amount);

// Create note commitment and deposit proof
const salt = crypto.getRandomValues(new Uint8Array(32));
const noteCommitment = createNoteCommitment(amount, keyPair.publicKey, salt);
const depositProof = await generateDepositProof({ keyPair, amount, salt });
const depositTx = await nixPool.deposit(USDC_ADDRESS, amount, depositProof, noteCommitment);
await depositTx.wait();

// Step 4: Transact - consume input notes, create output notes
const transactProof = await generateTransactProof({
  inputNotes: [myNote1, myNote2],
  outputNotes: [recipientNote, changeNote],
  merkleRoot: await nixPool.getMerkleRoot(),
  senderKeyPair: keyPair,
});

const encryptedNotes = ecies.encrypt(outputNoteData, recipientPublicKey);
const transactTx = await nixPool.transact(
  transactProof.proof,
  transactProof.nullifiers,
  transactProof.newCommitments,
  encryptedNotes
);
await transactTx.wait();
console.log('Private transaction complete!');

中继器交易

定制用户的 Gas 处理方式。用户生成 ZK 证明,中继器以可配置的 Gas 费用在链上提交交易。授权无需签名。支持 ERC-2612 Permit 实现无 Gas 代币授权。

工作原理

1
User creates transaction
2
Generates ZK proof
3
Relayer submits proof on-chain
4
Fee deducted from output note

基本用法

typescript
import { NixRelayer } from '@nixprotocol/relayer';

const relayer = new NixRelayer({
  url: 'https://relayer.nixprotocol.com',
  chainId: 43113, // Avalanche Fuji testnet
});

// User signs, relayer pays gas
const result = await relayer.sendPrivateTransfer({
  signer: userSigner,           // User's wallet (MetaMask, etc.)
  token: USDC_ADDRESS,
  recipient: recipientAddress,
  proof: transferProof,
  feeToken: USDC_ADDRESS,       // Pay fee in USDC
  maxFee: ethers.parseUnits('1', 6), // Max 1 USDC fee
});

console.log('Tx hash:', result.txHash);

自托管中继器

typescript
// server.ts - Your own relayer backend
import { NixRelayerServer } from '@nixprotocol/relayer/server';

const relayer = new NixRelayerServer({
  privateKey: process.env.RELAYER_PRIVATE_KEY,
  rpcUrl: process.env.RPC_URL,
  supportedTokens: [USDC, USDT, DAI],
  feePercentage: 0.1, // 0.1% fee
});

// Validate and execute meta-transactions
app.post('/relay', async (req, res) => {
  const { signedRequest } = req.body;

  // Verify signature and fee payment
  const isValid = await relayer.verifyRequest(signedRequest);
  if (!isValid) return res.status(400).json({ error: 'Invalid request' });

  // Execute on-chain
  const result = await relayer.execute(signedRequest);
  res.json({ txHash: result.hash });
});

费用结构

OperationGas Cost~Fee (L2)
Private Transfer~3M gas~$0.15-1.50
Withdraw~3M gas~$0.15-1.50
Register~2.8M gas~$0.14-1.40

* Estimated fees on L2 chains (Avalanche, Base, Arbitrum). Currently deployed on Avalanche Fuji and Base Sepolia testnets.

集成路径

根据您的隐私需求选择合适的方案。

Basic1-2 hours

Add Privacy to ERC-20

Deposit any ERC-20 into the UTXO privacy pool. Amounts hidden with unlinkable transfers.

Intermediate2-4 hours

Relayer UX

Users generate proofs, relayer submits with customizable gas fees. Better UX with flexible gas management.

Advanced1-2 days

Full Privacy Payments

Complete anonymity with unlinkable withdrawals using NixPool dark pool pattern.

错误处理

常见错误及其在集成中的处理方法。

Error CodeCauseSolution
INVALID_PROOFZK proof verification failedRegenerate proof with correct inputs
INSUFFICIENT_BALANCEUTXO note value less than transfer amountCheck decrypted balance before transfer
NOT_REGISTEREDUser hasn't registered their Grumpkin public keyCall register() with valid proof first
NULLIFIER_USEDAttempting to spend already-spent noteUse fresh commitment for new transaction
INVALID_MERKLE_ROOTMerkle root doesn't match on-chain stateFetch latest root before proof generation
DECRYPTION_FAILEDWrong private key or corrupted ciphertextVerify keypair matches registered public key

处理错误

typescript
import { NixError, NixErrorCode } from '@nixprotocol/nix-wallet';

try {
  const tx = await nixPool.privateTransfer(recipient, proof);
  await tx.wait();
} catch (error) {
  if (error instanceof NixError) {
    switch (error.code) {
      case NixErrorCode.INVALID_PROOF:
        // Regenerate proof with fresh randomness
        const newProof = await generateTransferProof(/*...*/);
        break;
      case NixErrorCode.INSUFFICIENT_BALANCE:
        // Show user their actual balance
        const balance = await getDecryptedBalance();
        throw new Error(`Insufficient balance: ${balance}`);
      default:
        console.error('Nix error:', error.message);
    }
  }
  throw error;
}

调试技巧

Enable Debug Mode

Set NIX_DEBUG=true to log proof inputs and circuit constraints.

Verify Keys Match

Most errors stem from keypair mismatch. Always verify public key matches on-chain registration.

Check Gas Limits

UltraHonk proof verification is gas-heavy (~3M gas). Ensure transactions have sufficient gas limit.

安全最佳实践

生产部署的关键安全注意事项。

密钥管理

Never Store Private Keys in LocalStorage

Use deterministic key derivation from wallet signatures. Keys should be derived on-demand, not persisted.

Do: Derive Keys from Signatures

Use deriveNixKeyFromSignature(walletClient) to deterministically derive a Grumpkin keypair from a wallet signature via Poseidon2 hashing.

证明生成

Use Fresh Randomness

Every proof must use cryptographically random values. Reusing randomness leaks private information.

Client-Side Only

Generate proofs in browser/client. Never send private keys or amounts to backend servers.

Verify Before Submit

Always verify proofs locally before submitting to chain to save gas on invalid proofs.

Timing Attacks

Add random delays between operations to prevent transaction graph analysis.

智能合约安全

  • Verify Circuit Hash: Ensure deployed UltraHonk verifier matches compiled Noir circuit
  • Check Nullifier Storage: Nullifiers must be stored permanently to prevent double-spend
  • Merkle Tree Depth: Use sufficient depth (20+) to support expected user base
  • Reentrancy Guards: All state-changing functions must be protected
安全审计状态

参考实现正在接受安全审计。审计完成前请勿部署大额资金。如需企业部署安全审查,请联系我们。

完整 API 参考

完整的函数签名和类型定义。

@nixprotocol/nix-wallet

typescript
// Key Generation
function deriveNixKeyFromSignature(walletClient: WalletClient): Promise<NixKeyPair>;
function generateNixKeyPair(): NixKeyPair;
function importNixKey(privateKeyHex: string): NixKeyPair;
function exportNixKey(keyPair: NixKeyPair): string;

interface Point {
  x: bigint;
  y: bigint;
}

interface NixKeyPair {
  privateKey: bigint;       // Grumpkin scalar
  publicKey: Point;         // Grumpkin curve point
  commitment: bigint;       // Poseidon2(pk.x, pk.y)
}

// ECIES Encryption
namespace ecies {
  function encrypt(value: bigint, randomness: bigint, receiverPk: Point): ECIESCiphertext;
  function decrypt(sk: bigint, authKeyX: bigint, authKeyY: bigint, encrypted: bigint): bigint;
}

interface ECIESCiphertext {
  authKeyX: bigint;
  authKeyY: bigint;
  encrypted: bigint;
}

// Poseidon2 Hash
function poseidon2Hash(inputs: bigint[]): bigint;
function computeCommitment(pkx: bigint, pky: bigint): bigint;

// Note Commitments
function createNoteCommitment(value: bigint, pubKey: Point, salt: bigint): bigint;

// Proof Generation
function generateRegistrationProof(keyPair: NixKeyPair): Promise<ProofResult>;
function generateDepositProof(params: DepositParams): Promise<ProofResult>;
function generateTransactProof(params: TransactParams): Promise<ProofResult>;

interface ProofResult {
  proof: `0x${string}`;        // UltraHonk proof bytes
  publicInputs: `0x${string}`[];
}

NixAddress & NixWallet

typescript
// NixAddress encoding/decoding
function encodeNixAddress(data: NixAddressData): string;
function decodeNixAddress(nixAddress: string): NixAddressData;
function nixAddressFromKeyPair(keyPair: NixKeyPair): string;

interface NixAddressData {
  commitment: bigint;           // Poseidon2(pk.x, pk.y)
  publicKey: Point;             // Grumpkin curve point
}
// Format: "nix:<commitment>:<pk.x>:<pk.y>"

// NixWallet class - high-level wallet interface
class NixWallet {
  static create(config: NixWalletConfig): Promise<NixWallet>;
  register(): Promise<void>;
  deposit(token: Address, amount: bigint): Promise<void>;
  transfer(recipientNixAddress: string, amount: bigint): Promise<void>;
  withdraw(token: Address, amount: bigint, to: Address): Promise<void>;
  syncBalances(): Promise<void>;
  exportPrivateKey(): string;
}

Contract ABIs

solidity
interface INixPool {
  function register(bytes calldata proof, bytes32 publicKeyHash) external;
  function deposit(
    address token,
    uint256 amount,
    bytes calldata proof,
    bytes32 noteCommitment
  ) external;
  function transact(
    bytes calldata proof,
    bytes32[2] calldata nullifiers,
    bytes32[2] calldata newCommitments,
    bytes calldata encryptedNotes
  ) external;
  function withdraw(
    bytes calldata proof,
    bytes32 nullifier,
    address token,
    uint256 amount,
    address recipient
  ) external;

  function getMerkleRoot() external view returns (bytes32);
  function isKnownRoot(bytes32 root) external view returns (bool);
  function isSpent(bytes32 nullifier) external view returns (bool);
  function isRegistered(address user) external view returns (bool);
  function nextIndex() external view returns (uint256);
}

poseidon2-go

BN254 标量域上 Poseidon2 哈希函数的纯 Go 实现。专为需要与链上或电路内 Poseidon2 输出匹配的链下计算而设计。

安装

bash
go get github.com/nixprotocol/poseidon2-go

参数

ParameterValue
BN254 标量域 (Fr)
状态宽度4
速率3
容量1
完整轮数8
部分轮数56
S-boxx⁵

导出函数

go
func Hash(inputs []fr.Element) fr.Element
func Hash2(a, b fr.Element) fr.Element
func HashToBytes(inputs []fr.Element) [32]byte
func Permute(s *[4]fr.Element)
Hash

可变长度哈希。通过海绵结构以 rate-3 块吸收输入,返回一个域元素。

Hash2

双输入哈希。等同于 Hash([]fr.Element{a, b}) 的便捷封装。

HashToBytes

与 Hash 相同,但将结果以 32 字节大端数组返回。

Permute

对 4 元素状态的原地 Poseidon2 置换。Hash 内部使用,为高级海绵结构开放。

海绵结构

Hash 和 HashToBytes 使用海绵结构,将输入吸收到状态槽 [1..3](rate = 3),槽 0 保留为容量。每个 rate 大小的块后运行完整置换。输出是最终吸收后再执行一次置换的 state[0]。

用法

go
package main

import (
    "fmt"
    poseidon2 "github.com/nixprotocol/poseidon2-go"
    "github.com/consensys/gnark-crypto/ecc/bn254/fr"
)

func main() {
    var a, b fr.Element
    a.SetUint64(1)
    b.SetUint64(2)

    h := poseidon2.Hash2(a, b)
    fmt.Println("hash:", h.String())

    raw := poseidon2.HashToBytes([]fr.Element{a, b})
    fmt.Printf("bytes: %x\n", raw)
}

轮常数和 MDS 矩阵与 NixProtocol 中使用的 Noir 和 Solidity 实现匹配,因此使用此库计算的哈希值对于相同输入将产生相同输出。

MCP 服务器

MCP_SERVER

封装 NixProtocol SDK 的 Model Context Protocol 服务器,用于 AI 代理集成。将其接入 Claude 或任何 MCP 兼容代理,通过自然语言实现隐私支付。

设置

bash
npm install @nixprotocol/mcp-server

# Add to your MCP config (e.g. claude_desktop_config.json)
{
  "mcpServers": {
    "nixprotocol": {
      "command": "npx",
      "args": ["@nixprotocol/mcp-server"],
      "env": {
        "NIX_RPC_URL": "https://api.avax-test.network/ext/bc/C/rpc",
        "NIX_CONTRACT_ADDRESS": "0x94e5...",
        "NIX_CHAIN_ID": "43113",
        "NIX_CIRCUIT_PATH": "./circuits",
        "NIX_RELAYER_URL": "https://relayer.nixprotocol.com"
      }
    }
  }
}

可用工具

nix_init_wallet - 初始化证明器、客户端,并可选导入私钥
nix_get_address - 返回当前密钥对的 NixAddress
nix_get_balance - 扫描笔记并返回代币余额
nix_get_history - 列出所有笔记及已用/未用状态
nix_register - 向池进行一次性身份注册
nix_deposit - 将 ERC-20 代币存入隐私池
nix_transfer - 向 NixAddress 收款人进行隐私转账
nix_withdraw - 从池中提款到 EVM 地址
nix_get_fee - 查询中继器当前费用信息
nix_decode_address - 解析并验证 NixAddress

环境变量

VariableDescription
NIX_RPC_URL目标链的 RPC 端点
NIX_CONTRACT_ADDRESS已部署的 NixPool 地址
NIX_CHAIN_ID目标链 ID
NIX_EVM_PRIVATE_KEY用于 Gas 的 EVM 密钥(仅存款)
NIX_PRIVATE_KEYNix 私钥(可选,可从钱包派生)
NIX_CIRCUIT_PATH编译后的电路工件路径
NIX_RELAYER_URL无 Gas 交易的中继器端点

中继器 API 参考

RELAYER_API

中继器代表用户提交交易,因此用户无需持有原生 Gas 代币。它使用 Chainlink 价格源动态计算费用,并从隐私池本身扣除费用。

端点

GET /:chainId/relay/fee-info?token=<address>

返回给定代币的当前费用报价,包括 Gas 成本估算、中继器利润率和用于加密笔记的中继器公钥。

json
// Response
{
  "feeAmount": "500000",
  "feeToken": "0x5425...",
  "gasEstimate": "350000",
  "relayerPublicKey": { "x": "0x...", "y": "0x..." }
}
POST /:chainId/relay/transact

提交交易证明(转账或提款)。中继器验证证明,检查费用输出是否覆盖 Gas 成本,然后提交上链。

json
// Request body
{
  "proof": "0x...",
  "publicInputs": ["0x...", ...],
  "encryptedNotes": "0x..."
}
POST /:chainId/relay/register

提交注册证明。中继器将身份承诺提交到注册默克尔树。

费用计算

费用计算方式:(预估 Gas × Gas 价格 × 代币价格)+ 利润率。默认利润率为 30%,最低 $0.50。代币价格从 Chainlink 预言机获取。

速率限制

中继器按 IP 地址实施速率限制。默认:每分钟 20 次请求。

自托管

bash
# Clone and run your own relayer
npm install @nixprotocol/relayer

# Configure environment
export PRIVATE_KEY="0x..."
export RPC_URL="https://api.avax-test.network/ext/bc/C/rpc"
export PORT=3001

# Start
npx nix-relayer

审计工具

AUDITOR

审计员持有在 NixPool 部署时设置的单个 Grumpkin 私钥。使用此密钥,审计员可以解密所有交易数据用于合规报告,同时不影响公开视图中的用户隐私。

审计员可解密的内容

存款金额和收款人承诺
输入和输出的转账金额
收款人承诺(谁收到了资金)
注册数据(每个用户的 EVM 地址和公钥)

SDK 函数

decryptAuditorNote(ciphertext, auditorPrivKey) - 解密笔记的金额和盲化因子
decryptRecipientCommitment(ciphertext, auditorPrivKey) - 解密笔记的收款人
parseDepositCalldata(txData) - 从调用数据中提取存款证明公开输入
parseTransactCalldata(txData) - 从调用数据中提取交易证明公开输入
typescript
import { decryptAuditorNote, decryptRecipientCommitment } from '@nixprotocol/sdk';

// Auditor decrypts a deposit note
const note = decryptAuditorNote(
  encryptedCiphertext,
  auditorPrivateKey
);
console.log('Amount:', note.amount);
console.log('Blinding:', note.blinding);

// Auditor decrypts recipient identity
const recipient = decryptRecipientCommitment(
  recipientCiphertext,
  auditorPrivateKey
);

NixPay 审计页面

NixPay 在 /auditor 路径包含内置审计界面,审计员可以输入私钥来解密和检查所有池交易。

池客户端

POOL_CLIENT

PoolClient 封装 NixPool 智能合约,用于存款、转账、提款和链上查询。它处理 ABI 编码、默克尔根查找和事件获取。

关键方法

deposit(proof, noteHash, ...) - 提交存款交易
transact(proof, nullifiers, ...) - 提交转账或提款
register(proof, commitment) - 注册身份承诺
getNotes(fromBlock?) - 从池中获取 NoteCreated 事件
getMerkleRoot() - 获取当前默克尔根
isSpent(nullifier) - 检查废弃器是否已被使用

用法

typescript
import { PoolClient } from '@nixprotocol/sdk';
import { createPublicClient, http } from 'viem';
import { avalancheFuji } from 'viem/chains';

const publicClient = createPublicClient({
  chain: avalancheFuji,
  transport: http(),
});

const pool = new PoolClient({
  contractAddress: '0x94e5...',
  publicClient,
});

// Fetch all notes from the pool
const notes = await pool.getNotes();

// Check if a nullifier has been spent
const spent = await pool.isSpent(nullifierHash);

笔记管理器

NOTE_MGR

NoteManager 处理 UTXO 笔记的链下跟踪。它扫描 NoteCreated 事件,使用用户的私钥试解密每个笔记,并在 IndexedDB(浏览器)或内存(Node.js)中维护已拥有笔记的本地缓存。

关键方法

scan() - 扫描新笔记并更新本地缓存
getUnspentNotes() - 返回此密钥拥有的所有未使用笔记
getBalance() - 所有未使用笔记金额的总和
markSpent(nullifier) - 成功交易后将笔记标记为已使用

缓存

NoteManager 在 IndexedDB(键:nixpay-v2-events)中缓存事件,避免每次加载时重新扫描整条链。在 Node.js 环境中,回退到内存存储。

typescript
import { NoteManager } from '@nixprotocol/sdk';

const noteManager = new NoteManager({
  poolClient,
  privateKey: nixPrivateKey,
});

// Scan for new notes (uses IndexedDB cache)
await noteManager.scan();

// Get spendable balance
const balance = noteManager.getBalance();
console.log('Balance:', balance.toString());

// Get unspent notes for building transactions
const notes = noteManager.getUnspentNotes();
支援

需要集成帮助?

我们为复杂的隐私需求提供定制开发。

暗号化|ZK_PROOFS|PRIVACY|プライバシー