NixProtocol 문서
애플리케이션에 UTXO 기반 프라이버시 결제를 추가하세요. NixProtocol은 Noir ZK 회로와 Grumpkin 곡선 암호학을 사용하는 EVM 체인용 프라이버시 풀 프로토콜을 제공합니다. Avalanche Fuji & Base Sepolia에서 테스트넷 라이브.
아키텍처 개요
NixProtocol은 암호화, 영지식 증명 및 스마트 컨트랙트를 결합한 계층 아키텍처를 통해 프라이버시를 제공합니다.
데이터 흐름
- › Derive Grumpkin keypair via Poseidon2
- › Encrypt notes with ECIES
- › Generate UltraHonk proofs locally
- › Authorize via ZK proofs (no signatures)
- › Verify ZK proofs
- › Store note commitments in Merkle tree
- › Verify nullifiers & update roots
- › Emit privacy-preserving events
- › Selective disclosure keys
- › View-only access grants
- › Compliance reporting
- › Audit trail generation
주요 구성 요소
Embedded elliptic curve for ZK-friendly operations. Used for keypairs, ECIES encryption, and NixAddress encoding. Native to Noir circuits via Barretenberg.
Compiled from Noir circuits via Barretenberg. No trusted setup required. 3 circuits: deposit, registration, and transact.
ZK-optimized hash function used for note commitments, nullifiers, and Merkle trees. Poseidon2 variant for improved performance in Noir circuits.
퀵스타트
5분 만에 시작하세요. 키를 생성하고, 데이터를 암호화하고, 증명을 만드세요.
SDK 설치
npm install @nixprotocol/nix-wallet viem키쌍 생성
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암호화 및 노트 생성
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]);설치
NixProtocol은 다양한 통합 요구에 맞는 NPM 패키지 세트로 제공됩니다.
@nixprotocol/nix-walletBUSL-1.1Core wallet library - key derivation, encryption, proofs, NixAddress, and UTXO management
@nixprotocol/contractsBUSL-1.1NixPool Solidity contracts and TypeScript bindings
@nixprotocol/relayerBUSL-1.1Gas abstraction with ZK proof authorization
암호화
NixProtocol은 UTXO 노트 데이터와 감사자 접근 가능한 거래 레코드를 암호화하기 위해 Grumpkin 곡선에서 ECIES 암호화를 사용합니다.
주요 속성
- •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
수학적 기반
Embedded elliptic curve native to Barretenberg/Noir:
Short Weierstrass curve: y² = x³ - 17 (embedded curve of BN254)For message m, recipient public key P = sG:
Note commitments use Poseidon2 hash: commitment = Poseidon2(value, ownerPubKey, salt). Nullifiers prevent double-spending: nullifier = Poseidon2(commitment, privateKey).
보안 매개변수
~128-bit security level (Grumpkin curve, embedded in BN254)
Fresh random ephemeral key per encryption
Commitment (1 field element) + ECIES-encrypted data
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는 실제 EVM 주소를 컴팩트한 Grumpkin 공개 키로 별명 처리합니다. 온체인 신원을 노출하지 않고 프라이버시 풀에서 UTXO 노트를 수신하기 위해 공유하세요.
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 암호화 노트 데이터를 복호화할 수 있습니다.
감사자 접근 작동 방식
A single Grumpkin private key is designated as the auditor key when the NixPool is deployed. The corresponding public key is stored on-chain.
Transaction data is ECIES-encrypted to the auditor's Grumpkin public key during each deposit and transfer.
The auditor uses their Grumpkin private key to decrypt note data, revealing amounts and ownership for compliance reporting.
구현
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',
});감사자가 볼 수 있는 것
Decrypt UTXO note values from ECIES-encrypted on-chain data
Identify note owners via decrypted Grumpkin public keys
Trace deposit, transfer, and withdrawal activity across the pool
규제 호환: 공개 뷰에서 사용자 프라이버시를 유지하면서 감사 추적, 세금 보고 및 규제 컴플라이언스가 필요한 기관을 위해 설계되었습니다.
SDK 개요
@nixprotocol/nix-wallet 패키지는 대부분의 통합을 위한 메인 진입점입니다.
내보내기
deriveNixKeyFromSignature(walletClient) - Deterministic keypair from wallet signature via Poseidon2generateNixKeyPair() - Random Grumpkin keypairecies.encrypt(data, pubKey) - ECIES encrypt to Grumpkin keyecies.decrypt(ciphertext, privKey) - Decrypt ECIES ciphertextposeidon2.hash(inputs) - Poseidon2 hash functioncreateNoteCommitment(value, pubKey, salt) - Create UTXO note commitment키 생성
암호화 및 증명 생성을 위한 Grumpkin 키쌍을 생성하세요. 키는 Poseidon2 해싱을 사용하여 EVM 지갑 서명에서 결정론적으로 파생되어, 동일한 지갑이 항상 동일한 NixProtocol 개인 키를 생성합니다.
중요: 프로덕션에서는 지갑 서명에서 결정론적 키 파생을 사용하세요. 무작위 키쌍은 안전한 개인 키 저장이 필요합니다.
ECIES 암호화
노트 데이터 및 감사자 레코드를 암호화하기 위한 Grumpkin 곡선에서의 ECIES 암호화.
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는 프라이버시 풀에서 UTXO 노트를 수신하기 위한 Grumpkin 공개 키 커밋먼트와 좌표를 인코딩하는 공유 가능한 결제 식별자입니다.
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 컨트랙트
UTXO 기반 프라이버시 결제를 위한 메인 프라이버시 풀 컨트랙트.
// 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 노트 커밋먼트를 위한 머클 트리 저장소.
// 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 기반 프라이버시 결제를 추가하세요.
- 1Deploy NixPool contract for your ERC-20 token
- 2Users register with Grumpkin public key
- 3Deposit converts public tokens to UTXO notes
- 4Transact consumes input notes, creates output notes
- 5Withdraw burns notes and releases public tokens
전체 통합 예제
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!');릴레이어 거래
사용자를 위한 가스 처리 방법을 맞춤 설정하세요. 사용자가 ZK 증명을 생성하면 릴레이어가 구성 가능한 가스 수수료로 온체인에 거래를 제출합니다. 승인을 위한 서명이 필요 없습니다. 가스리스 토큰 승인을 위한 ERC-2612 Permit을 지원합니다.
작동 방식
기본 사용법
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);자체 호스팅 릴레이어
// 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 });
});수수료 구조
| Operation | Gas 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.
통합 경로
프라이버시 요구 사항에 따라 올바른 접근 방식을 선택하세요.
Add Privacy to ERC-20
Deposit any ERC-20 into the UTXO privacy pool. Amounts hidden with unlinkable transfers.
Relayer UX
Users generate proofs, relayer submits with customizable gas fees. Better UX with flexible gas management.
Full Privacy Payments
Complete anonymity with unlinkable withdrawals using NixPool dark pool pattern.
에러 처리
일반적인 에러 및 통합에서의 처리 방법.
| Error Code | Cause | Solution |
|---|---|---|
INVALID_PROOF | ZK proof verification failed | Regenerate proof with correct inputs |
INSUFFICIENT_BALANCE | UTXO note value less than transfer amount | Check decrypted balance before transfer |
NOT_REGISTERED | User hasn't registered their Grumpkin public key | Call register() with valid proof first |
NULLIFIER_USED | Attempting to spend already-spent note | Use fresh commitment for new transaction |
INVALID_MERKLE_ROOT | Merkle root doesn't match on-chain state | Fetch latest root before proof generation |
DECRYPTION_FAILED | Wrong private key or corrupted ciphertext | Verify keypair matches registered public key |
에러 처리하기
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;
}디버깅 팁
Set NIX_DEBUG=true to log proof inputs and circuit constraints.
Most errors stem from keypair mismatch. Always verify public key matches on-chain registration.
UltraHonk proof verification is gas-heavy (~3M gas). Ensure transactions have sufficient gas limit.
보안 모범 사례
프로덕션 배포를 위한 중요 보안 고려 사항.
키 관리
Use deterministic key derivation from wallet signatures. Keys should be derived on-demand, not persisted.
Use deriveNixKeyFromSignature(walletClient) to deterministically derive a Grumpkin keypair from a wallet signature via Poseidon2 hashing.
증명 생성
Every proof must use cryptographically random values. Reusing randomness leaks private information.
Generate proofs in browser/client. Never send private keys or amounts to backend servers.
Always verify proofs locally before submitting to chain to save gas on invalid proofs.
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
// 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
// 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
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 출력과 일치해야 하는 오프체인 연산을 위해 설계되었습니다.
설치
go get github.com/nixprotocol/poseidon2-go파라미터
| Parameter | Value |
|---|---|
| 필드 | BN254 스칼라 필드 (Fr) |
| 상태 너비 | 4 |
| 속도 | 3 |
| 용량 | 1 |
| 전체 라운드 | 8 |
| 부분 라운드 | 56 |
| S-box | x⁵ |
내보낸 함수
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}})와 동일한 편의 래퍼입니다.
HashToBytesHash와 동일하지만 결과를 32바이트 빅엔디안 배열로 반환합니다.
Permute4요소 상태에 대한 인플레이스 Poseidon2 순열입니다. Hash 내부에서 사용되며, 고급 스펀지 구성을 위해 노출됩니다.
스펀지 구조
Hash와 HashToBytes는 입력을 상태 슬롯 [1..3](rate = 3)에 흡수하고, 슬롯 0은 용량으로 유지하는 스펀지를 사용합니다. rate 크기 청크마다 전체 순열이 실행됩니다. 출력은 최종 흡수 후 한 번 더 순열을 실행한 state[0]입니다.
사용법
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 서버
NixProtocol SDK를 래핑하는 Model Context Protocol 서버로, AI 에이전트 통합을 지원합니다. Claude 또는 MCP 호환 에이전트에 연결하여 자연어로 프라이버시 결제를 가능하게 합니다.
설정
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 파싱 및 검증환경 변수
| Variable | Description |
|---|---|
| NIX_RPC_URL | 대상 체인의 RPC 엔드포인트 |
| NIX_CONTRACT_ADDRESS | 배포된 NixPool 주소 |
| NIX_CHAIN_ID | 대상 체인 ID |
| NIX_EVM_PRIVATE_KEY | 가스용 EVM 키 (입금 전용) |
| NIX_PRIVATE_KEY | Nix 개인키 (선택, 지갑에서 파생 가능) |
| NIX_CIRCUIT_PATH | 컴파일된 회로 아티팩트 경로 |
| NIX_RELAYER_URL | 가스리스 거래를 위한 릴레이어 엔드포인트 |
릴레이어 API 레퍼런스
릴레이어는 사용자를 대신하여 거래를 제출하므로 사용자가 네이티브 가스 토큰을 보유할 필요가 없습니다. Chainlink 가격 피드를 사용하여 동적으로 수수료를 계산하고 프라이버시 풀 자체에서 수수료를 차감합니다.
엔드포인트
GET /:chainId/relay/fee-info?token=<address>주어진 토큰의 현재 수수료 견적을 반환합니다. 가스 비용 추정, 릴레이어 마진, 노트 암호화를 위한 릴레이어 공개키를 포함합니다.
// Response
{
"feeAmount": "500000",
"feeToken": "0x5425...",
"gasEstimate": "350000",
"relayerPublicKey": { "x": "0x...", "y": "0x..." }
}POST /:chainId/relay/transact거래 증명(전송 또는 출금)을 제출합니다. 릴레이어가 증명을 검증하고, 수수료 출력이 가스 비용을 충당하는지 확인한 후 온체인에 제출합니다.
// Request body
{
"proof": "0x...",
"publicInputs": ["0x...", ...],
"encryptedNotes": "0x..."
}POST /:chainId/relay/register등록 증명을 제출합니다. 릴레이어가 등록 머클 트리에 신원 커밋먼트를 제출합니다.
수수료 계산
수수료는 (추정 가스 * 가스 가격 * 토큰 가격) + 마진으로 계산됩니다. 기본 마진은 30%이며 최소 $0.50입니다. 토큰 가격은 Chainlink 오라클에서 가져옵니다.
속도 제한
릴레이어는 IP 주소별 속도 제한을 시행합니다. 기본값: 분당 20건.
자체 호스팅
# 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감사자 도구
감사자는 NixPool 배포 시 설정된 단일 Grumpkin 개인키를 보유합니다. 이 키로 감사자는 공개 뷰에서의 사용자 프라이버시에 영향을 주지 않으면서 컴플라이언스 보고를 위한 모든 거래 데이터를 복호화할 수 있습니다.
감사자가 복호화할 수 있는 것
SDK 함수
decryptAuditorNote(ciphertext, auditorPrivKey) - 노트의 금액 및 블라인딩 팩터 복호화decryptRecipientCommitment(ciphertext, auditorPrivKey) - 노트 수신자 복호화parseDepositCalldata(txData) - 콜데이터에서 입금 증명 공개 입력 추출parseTransactCalldata(txData) - 콜데이터에서 거래 증명 공개 입력 추출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에 내장 감사자 인터페이스를 포함하여 감사자가 개인키를 입력해 모든 풀 거래를 복호화하고 검사할 수 있습니다.
풀 클라이언트
PoolClient는 입금, 전송, 출금 및 온체인 쿼리를 위해 NixPool 스마트 컨트랙트를 래핑합니다. ABI 인코딩, 머클 루트 조회 및 이벤트 가져오기를 처리합니다.
주요 메서드
deposit(proof, noteHash, ...) - 입금 거래 제출transact(proof, nullifiers, ...) - 전송 또는 출금 제출register(proof, commitment) - 신원 커밋먼트 등록getNotes(fromBlock?) - 풀에서 NoteCreated 이벤트 가져오기getMerkleRoot() - 현재 머클 루트 가져오기isSpent(nullifier) - 널리파이어 사용 여부 확인사용법
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);노트 매니저
NoteManager는 UTXO 노트의 오프체인 추적을 처리합니다. NoteCreated 이벤트를 스캔하고, 사용자의 개인키로 각 노트를 시험적으로 복호화하며, IndexedDB(브라우저) 또는 메모리(Node.js)에 소유 노트의 로컬 캐시를 유지합니다.
주요 메서드
scan() - 새 노트 스캔 및 로컬 캐시 업데이트getUnspentNotes() - 이 키가 소유한 모든 미사용 노트 반환getBalance() - 모든 미사용 노트 금액의 합계markSpent(nullifier) - 성공적인 거래 후 노트를 사용됨으로 표시캐싱
NoteManager는 매 로드 시 전체 체인을 재스캔하지 않도록 IndexedDB(키: nixpay-v2-events)에 이벤트를 캐시합니다. Node.js 환경에서는 메모리 내 저장소로 폴백합니다.
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();