Overview
Utility functions provide cryptographic primitives, encoding helpers, and data manipulation tools used throughout the Tornado Nova system.
Source Locations: src/utils.js, src/utxo.js, src/keypair.js
Cryptographic Functions
poseidonHash
function poseidonHash ( items )
Computes Poseidon hash of an array of field elements. Poseidon is a ZK-friendly hash function.
items
Array<BigNumber | number>
required
Array of values to hash
Returns: BigNumber - Hash result as a field element
Source: src/utils.js:7
const { poseidonHash } = require ( './src/utils' )
const { ethers } = require ( 'hardhat' )
const hash = poseidonHash ([ 1 , 2 , 3 ])
console . log ( hash . toString ())
// Hash commitment
const commitment = poseidonHash ([ amount , pubkey , blinding ])
poseidonHash2
function poseidonHash2 ( a , b )
Computes Poseidon hash of exactly two field elements. Optimized for merkle tree operations.
a
BigNumber | number
required
First value
b
BigNumber | number
required
Second value
Returns: BigNumber - Hash result
Source: src/utils.js:8
const { poseidonHash2 } = require ( './src/utils' )
// Used in merkle tree
const parent = poseidonHash2 ( leftChild , rightChild )
randomBN
function randomBN ( nbytes = 31 )
Generates a cryptographically secure random BigNumber.
Number of random bytes to generate (default 31 to stay within field size)
Returns: BigNumber - Random number
Source: src/utils.js:15
const { randomBN } = require ( './src/utils' )
// Generate random blinding factor
const blinding = randomBN ()
// Generate smaller random number
const randomValue = randomBN ( 16 ) // 16 bytes
Encoding Functions
toFixedHex
function toFixedHex ( number , length = 32 )
Converts a number or Buffer to a fixed-length hex string with ‘0x’ prefix.
number
BigNumber | number | Buffer
required
Value to convert
Byte length of output (will be padded with zeros)
Returns: string - Hex string of format 0x... with exactly length * 2 hex digits
Source: src/utils.js:51
const { toFixedHex } = require ( './src/utils' )
const { ethers } = require ( 'hardhat' )
// Convert address to fixed hex (20 bytes)
const addressHex = toFixedHex ( recipientAddress , 20 )
// "0x000000000000000000000000742d35cc6634c0532925a3b844bc9e7595f0beb"
// Convert number to 32 bytes
const amountHex = toFixedHex ( ethers . utils . parseEther ( '1.0' ))
// "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000"
// Handle negative numbers
const negativeHex = toFixedHex ( - 100 )
// Properly encodes as field element
toBuffer
function toBuffer ( value , length )
Converts a value to a Buffer of specified byte length.
value
BigNumber | number
required
Value to convert
Byte length of output buffer
Returns: Buffer - Buffer padded to specified length
Source: src/utils.js:65
const { toBuffer } = require ( './src/utils' )
// Convert amount to 31 bytes
const amountBuf = toBuffer ( amount , 31 )
// Concatenate multiple values
const combined = Buffer . concat ([
toBuffer ( amount , 31 ),
toBuffer ( blinding , 31 )
])
getExtDataHash
function getExtDataHash ({
recipient ,
extAmount ,
relayer ,
fee ,
encryptedOutput1 ,
encryptedOutput2 ,
isL1Withdrawal ,
l1Fee
})
Computes the hash of external data structure for ZK proof verification.
recipient
string | BigNumber
required
Recipient address
extAmount
string | BigNumber
required
External amount
relayer
string | BigNumber
required
Relayer address
fee
string | BigNumber
required
Fee amount
Returns: BigNumber - Hash modulo FIELD_SIZE
Source: src/utils.js:17
const { getExtDataHash , toFixedHex } = require ( './src/utils' )
const extData = {
recipient: toFixedHex ( recipientAddress , 20 ),
extAmount: toFixedHex ( amount ),
relayer: toFixedHex ( relayerAddress , 20 ),
fee: toFixedHex ( feeAmount ),
encryptedOutput1: output1 . encrypt (),
encryptedOutput2: output2 . encrypt (),
isL1Withdrawal: false ,
l1Fee: 0
}
const extDataHash = getExtDataHash ( extData )
// Used in ZK proof
shuffle
Randomly shuffles an array in-place using Fisher-Yates algorithm.
Array to shuffle (modified in-place)
Returns: Array - The shuffled array (same reference)
Source: src/utils.js:74
const { shuffle } = require ( './src/utils' )
// Shuffle inputs for privacy
const inputs = [ utxo1 , utxo2 , utxo3 ]
shuffle ( inputs )
// Shuffle outputs
const outputs = [ outputUtxo1 , outputUtxo2 ]
shuffle ( outputs )
// Array is modified in-place
console . log ( inputs ) // Randomly ordered
Constants
FIELD_SIZE
const FIELD_SIZE = BigNumber . from (
'21888242871839275222246405745257275088548364400416034343698204186575808495617'
)
The field size for BN254 elliptic curve used in the ZK-SNARKs. All field elements must be less than this value.
Source: src/utils.js:10
const { FIELD_SIZE } = require ( './src/utils' )
// Ensure value is within field
const fieldElement = value . mod ( FIELD_SIZE )
// Calculate public amount
const publicAmount = BigNumber . from ( extAmount )
. sub ( fee )
. add ( FIELD_SIZE )
. mod ( FIELD_SIZE )
Utility Classes
Keypair
See the Types Reference for full Keypair class documentation.
Key Methods:
constructor(privkey?) - Create new keypair
toString() - Export as string
Keypair.fromString(str) - Import from string
sign(commitment, merklePath) - Sign for nullifier
encrypt(bytes) - Encrypt data
decrypt(data) - Decrypt data
Source: src/keypair.js:36
Utxo
See the Types Reference for full Utxo class documentation.
Key Methods:
constructor({ amount, keypair, blinding, index }) - Create UTXO
getCommitment() - Get commitment hash
getNullifier() - Get nullifier hash
encrypt() - Encrypt UTXO data
Utxo.decrypt(keypair, data, index) - Decrypt UTXO
Source: src/utxo.js:6
Encryption Helpers
packEncryptedMessage
function packEncryptedMessage ( encryptedMessage )
Packs encrypted message object into hex string format.
Encrypted message object with nonce, ephemPublicKey, ciphertext (base64)
Returns: string - Hex string with ‘0x’ prefix
Format: 24 bytes nonce + 32 bytes ephemeral public key + ciphertext
Source: src/keypair.js:6
unpackEncryptedMessage
function unpackEncryptedMessage ( encryptedMessage )
Unpacks hex string into encrypted message object.
Hex string (with or without ‘0x’ prefix)
Returns: object - Object with version, nonce, ephemPublicKey, ciphertext (all base64)
Source: src/keypair.js:20
Testing Utilities
getSignerFromAddress
async function getSignerFromAddress ( address )
Impersonates an address in Hardhat for testing. Only works in local Hardhat network.
Returns: Promise<Signer> - Ethers.js signer for the address
Source: src/utils.js:91
const { getSignerFromAddress } = require ( './src/utils' )
// Impersonate the multisig
const multisigSigner = await getSignerFromAddress ( multisigAddress )
// Call restricted function
const tornadoPool = await ethers . getContractAt (
'TornadoPool' ,
poolAddress ,
multisigSigner
)
await tornadoPool . configureLimits ( newLimit )
Usage Examples
Complete Transaction Flow
Key Management
UTXO Management
Field Arithmetic
const {
toFixedHex ,
getExtDataHash ,
poseidonHash ,
randomBN ,
FIELD_SIZE
} = require ( './src/utils' )
const { Keypair } = require ( './src/keypair' )
const Utxo = require ( './src/utxo' )
// Create keypair
const keypair = new Keypair ()
// Create UTXO
const utxo = new Utxo ({
amount: ethers . utils . parseEther ( '1.0' ),
keypair ,
blinding: randomBN ()
})
// Get commitment
const commitment = utxo . getCommitment ()
console . log ( `Commitment: ${ toFixedHex ( commitment ) } ` )
// Encrypt for recipient
const encrypted = utxo . encrypt ()
// Create external data
const extData = {
recipient: toFixedHex ( recipientAddress , 20 ),
extAmount: toFixedHex ( utxo . amount ),
relayer: toFixedHex ( 0 , 20 ),
fee: toFixedHex ( 0 ),
encryptedOutput1: encrypted ,
encryptedOutput2: new Utxo (). encrypt (),
isL1Withdrawal: false ,
l1Fee: 0
}
// Hash external data
const extDataHash = getExtDataHash ( extData )
console . log ( `ExtData hash: ${ toFixedHex ( extDataHash ) } ` )
Field Elements: All cryptographic operations work with field elements modulo FIELD_SIZE. Negative numbers are represented as FIELD_SIZE - abs(value).
Random Number Generation: Always use randomBN() for generating blinding factors and other cryptographic secrets. Never use Math.random() or predictable values.