/// <reference types="node" />
/**
 * Type aliases for fixed-length byte sequences used throughout the codebase.
 * These help maintain type safety and clarify the expected byte lengths.
 */
export declare type Address = Buffer;
export declare type Address32 = Buffer;
export declare type Bytes32 = Buffer;
/**
 * Constants used for key derivation and tree organization.
 * These define the structure and layout of the binary tree.
 */
export declare const BASIC_DATA_LEAF_KEY = 0;
export declare const CODE_HASH_LEAF_KEY = 1;
export declare const HEADER_STORAGE_OFFSET = 64;
export declare const CODE_OFFSET = 128;
export declare const STEM_SUBTREE_WIDTH = 256;
export declare const MAIN_STORAGE_OFFSET = 256;
export declare const pushOffset = 95;
export declare const push1: number;
export declare const push32: number;
/** Function type for hash operations */
export declare type HashFunction = (data: any) => any;
/**
 * Converts a 20-byte Ethereum address to a 32-byte address by left-padding with zeros.
 *
 * @example
 * ```typescript
 * const addr20 = Buffer.from('1234567890123456789012345678901234567890', 'hex')
 * const addr32 = oldStyleAddressToAddress32(addr20)
 * // addr32 = 0x000000000000123456789012345678901234567890 (32 bytes)
 * ```
 */
export declare function oldStyleAddressToAddress32(address: Address): Address32;
/**
 * Applies a hash function to input data with proper buffering.
 *
 * @example
 * ```typescript
 * const input = Buffer.from('Hello World')
 * const hashFn = (data) => blake3.hash(data)
 * const hash = treeHash(input, hashFn)
 * // hash = 32-byte BLAKE3 hash of 'Hello World'
 * ```
 */
export declare function treeHash(input: Buffer, hashFn: HashFunction): Bytes32;
/**
 * Derives a tree key from an address and indices using a hash function.
 * Used to generate unique keys for different parts of the tree structure.
 * The resulting key is composed of a 31-byte stem (derived from address and treeIndex)
 * and a 1-byte subIndex.
 *
 * @param address - A 32-byte address to derive the key from
 * @param treeIndex - Primary index used to derive different trees for the same address
 * @param subIndex - Secondary index used to derive different keys within the same tree
 * @param hashFn - Hash function to use for key derivation
 * @returns A 32-byte key that uniquely identifies this storage slot
 * @throws Error if address is not 32 bytes
 *
 * @example
 * ```typescript
 * const addr32 = oldStyleAddressToAddress32(address)
 * const treeKey = getTreeKey(addr32, 0, 1, blake3.hash)
 * // Returns a unique key for this address's tree at index 0, subIndex 1
 * ```
 */
export declare function getTreeKey(address: Address32, treeIndex: number, subIndex: number, hashFn: HashFunction): Address32;
/**
 * Derives a key for storing an account's basic data (nonce, balance, etc.).
 *
 * @example
 * ```typescript
 * const addr32 = oldStyleAddressToAddress32(address)
 * const basicDataKey = getTreeKeyForBasicData(addr32, hashFn)
 * tree.insert(basicDataKey, accountData)
 * ```
 */
export declare function getTreeKeyForBasicData(address: Address32, hashFn: HashFunction): Address32;
/**
 * Derives a key for storing a contract's code hash.
 *
 * @example
 * ```typescript
 * const addr32 = oldStyleAddressToAddress32(contractAddress)
 * const codeHashKey = getTreeKeyForCodeHash(addr32, hashFn)
 * tree.insert(codeHashKey, codeHash)
 * ```
 */
export declare function getTreeKeyForCodeHash(address: Address32, hashFn: HashFunction): Address32;
/**
 * Derives a tree key for a storage slot in a contract's storage.
 * Handles two types of storage:
 * 1. Header storage (slots 0-63): Used for contract metadata and special storage
 * 2. Main storage (slots 256+): Used for regular contract storage
 *
 * The storage layout is:
 * - Header storage: slots [0, 63] mapped to positions [64, 127]
 * - Main storage: slots [256+] mapped to positions [384+]
 * This creates gaps in the tree to allow for future extensions.
 *
 * @param address - The 32-byte contract address
 * @param storageKey - The storage slot number to access
 * @param hashFn - Hash function to use for key derivation
 * @returns A 32-byte key that uniquely identifies this storage slot
 *
 * @example
 * ```typescript
 * const addr32 = oldStyleAddressToAddress32(contractAddress)
 * // Get key for a header storage slot (0-63)
 * const headerKey = getTreeKeyForStorageSlot(addr32, 5, blake3.hash)
 * // Get key for a main storage slot (256+)
 * const mainKey = getTreeKeyForStorageSlot(addr32, 300, blake3.hash)
 * ```
 */
export declare function getTreeKeyForStorageSlot(address: Address32, storageKey: number, hashFn: HashFunction): Address32;
/**
 * Derives a key for storing a chunk of contract code.
 * Used when contract code is split into 32-byte chunks.
 *
 * @example
 * ```typescript
 * const addr32 = oldStyleAddressToAddress32(contractAddress)
 * const chunks = chunkifyCode(contractCode)
 * chunks.forEach((chunk, i) => {
 *   const key = getTreeKeyForCodeChunk(addr32, i, hashFn)
 *   tree.insert(key, chunk)
 * })
 * ```
 */
export declare function getTreeKeyForCodeChunk(address: Address32, chunkId: number, hashFn: HashFunction): Address32;
/**
 * Splits EVM bytecode into 31-byte chunks with metadata.
 * Each chunk is prefixed with a byte indicating the number of bytes
 * that are part of PUSH data in the next chunk.
 *
 * @example
 * ```typescript
 * const code = Buffer.from('6001600201', 'hex') // PUSH1 01 PUSH1 02 ADD
 * const chunks = chunkifyCode(code)
 * // chunks[0] = [0x01, 0x60, 0x01, 0x60, 0x02, 0x01, 0x00...] (32 bytes)
 * ```
 */
export declare function chunkifyCode(code: Buffer): Bytes32[];
/**
 * Node types in the binary tree.
 * - StemNode: Leaf node containing up to 256 values
 * - InternalNode: Internal node with left and right children
 */
export declare type BinaryTreeNode = StemNode | InternalNode;
/**
 * Leaf node in the binary tree that stores actual values.
 * Contains a 31-byte stem and an array of 256 possible values.
 *
 * @example
 * ```typescript
 * const stem = Buffer.alloc(31, 0)
 * const node = new StemNode(stem)
 * node.setValue(0, Buffer.alloc(32).fill(1)) // Set value at index 0
 * ```
 */
export declare class StemNode {
    stem: Buffer;
    values: Array<Buffer | null>;
    nodeType: 'stem';
    /**
     * Creates a new StemNode with the given stem.
     *
     * @param stem - The 31-byte stem for this node.
     */
    constructor(stem: Buffer);
    /**
     * Sets the value at the given index.
     *
     * @param index - The index to set the value at.
     * @param value - The 32-byte value to set.
     */
    setValue(index: number, value: Buffer): void;
}
/**
 * Internal node in the binary tree with left and right children.
 * Used to create the tree structure based on key bit patterns.
 *
 * @example
 * ```typescript
 * const node = new InternalNode()
 * node.left = new StemNode(Buffer.alloc(31, 0))
 * node.right = new StemNode(Buffer.alloc(31, 1))
 * ```
 */
export declare class InternalNode {
    left: BinaryTreeNode | null;
    right: BinaryTreeNode | null;
    nodeType: 'internal';
}
/**
 * Main binary tree implementation that stores key-value pairs.
 * Uses a configurable hash function and supports various operations.
 *
 * @example
 * ```typescript
 * const tree = new BinaryTree(blake3.hash)
 * tree.insert(key, value)
 * const root = tree.merkelize()
 * const serialized = tree.serialize()
 * ```
 */
export declare class UnifiedBinaryTree {
    root: BinaryTreeNode | null;
    hashFn: HashFunction;
    /**
     * Creates a new BinaryTree instance with the given hash function.
     *
     * @param hashFn - The hash function to use for key derivation.
     */
    constructor(hashFn: HashFunction);
    /**
     * Inserts a key-value pair into the binary tree.
     * The key is split into two parts:
     * - stem (first 31 bytes): Determines the path in the tree
     * - subIndex (last byte): Determines the position within a leaf node
     *
     * If this is the first insertion, creates a new leaf node.
     * Otherwise, recursively traverses or builds the tree structure.
     *
     * @param key - A 32-byte key that determines where to store the value
     * @param value - A 32-byte value to store
     * @throws Error if key or value is not exactly 32 bytes
     *
     * @example
     * ```typescript
     * const tree = new BinaryTree(hashFn)
     * const key = getTreeKey(address, 0, 1, hashFn)
     * const value = Buffer.alloc(32).fill(1)
     * tree.insert(key, value)
     * ```
     */
    insert(key: Buffer, value: Buffer): void;
    /**
     * Recursively inserts a key-value pair into the tree.
     * This method handles three cases:
     * 1. Empty node: Creates a new leaf node
     * 2. Stem node: Either updates value or splits into internal node
     * 3. Internal node: Recursively traverses left or right based on stem bits
     *
     * @param node - Current node in traversal (null if empty)
     * @param stem - The 31-byte path component of the key
     * @param subIndex - The leaf position component of the key
     * @param value - The 32-byte value to store
     * @param depth - Current depth in the tree (max 247 to prevent hash collisions)
     * @returns The new or updated node
     * @throws Error if tree depth exceeds 247 levels
     */
    private insertRecursive;
    /**
     * Converts a byte array to an array of individual bits.
     * Each byte is converted to 8 bits, maintaining the most-significant-bit first order.
     * Used for making path decisions in the binary tree based on stem bytes.
     *
     * @param data - Buffer containing bytes to convert
     * @returns Array of bits (0s and 1s) in MSB-first order
     *
     * @example
     * ```typescript
     * const bytes = Buffer.from([0xA5]) // Binary: 10100101
     * const bits = bytesToBits(bytes)
     * // bits = [1,0,1,0,0,1,0,1]
     * //         ^ MSB        LSB ^
     * ```
     *
     * Process for each byte:
     * 1. Right shift by (7-i) positions to get desired bit to LSB
     * 2. AND with 1 to isolate that bit
     * 3. Push result (0 or 1) to output array
     */
    private bytesToBits;
    /**
     * Converts an array of bits back into a Buffer of bytes.
     * This is the inverse operation of bytesToBits.
     * Processes bits in groups of 8, maintaining MSB-first order.
     *
     * @param bits - Array of 0s and 1s to convert to bytes
     * @returns Buffer containing the reconstructed bytes
     * @throws Error if the number of bits is not divisible by 8
     *
     * @example
     * ```typescript
     * const bits = [1,0,1,0,0,1,0,1] // Represents binary 10100101
     * const bytes = bitsToBytes(bits)
     * // bytes = Buffer.from([0xA5])
     * ```
     *
     * Process for each byte:
     * 1. Take 8 bits at a time
     * 2. For each bit:
     *    - Shift it left to its correct position (7-j positions)
     *    - OR it with the accumulating byte value
     * 3. Add completed byte to array
     */
    private bitsToBytes;
    /**
     * Applies the hash function to the given data with special handling for null values.
     * Used primarily for Merkle tree calculations and node hashing.
     *
     * Special cases:
     * - null input -> returns 32-byte zero buffer
     * - 64-byte zero buffer -> returns 32-byte zero buffer
     * This handling ensures consistent treatment of empty/uninitialized nodes.
     *
     * @param data - Buffer to hash, must be either 32 or 64 bytes, or null
     * @returns A 32-byte hash of the data, or zero32 for empty cases
     * @throws Error if data length is not 32 or 64 bytes
     *
     * @example
     * ```typescript
     * // Regular hashing
     * const hash1 = hashData(nodeBuffer) // Returns hash of data
     *
     * // Empty cases - all return 32 zeros
     * const hash2 = hashData(null)
     * const hash3 = hashData(Buffer.alloc(64, 0))
     * ```
     */
    private hashData;
    /**
     * Computes the Merkle root of the entire tree.
     * The Merkle root is a single 32-byte hash that uniquely represents the entire tree state.
     *
     * The computation follows these rules:
     * 1. For Internal nodes: hash(leftChild || rightChild)
     * 2. For Stem nodes: hash(stem || 0x00 || merkleOfValues)
     * 3. For empty nodes: return 32 bytes of zeros
     *
     * @returns A 32-byte Buffer containing the Merkle root
     *
     * @example
     * ```typescript
     * const tree = new BinaryTree(hashFn)
     * tree.insert(key1, value1)
     * tree.insert(key2, value2)
     * const root = tree.merkelize()
     * // root now contains a 32-byte hash representing the entire tree
     * ```
     */
    merkelize(): Buffer;
    /**
     * Incrementally updates the value for an existing key.
     * For our implementation, update is the same as insert.
     *
     * @param key - A 32-byte key.
     * @param value - A 32-byte value.
     */
    update(key: Buffer, value: Buffer): void;
    /**
     * Performs a batch insertion of key-value pairs.
     *
     * @param entries - An array of objects with 'key' and 'value' properties.
     */
    insertBatch(entries: {
        key: Buffer;
        value: Buffer;
    }[]): void;
    /**
     * Serializes the entire tree structure into a JSON Buffer.
     * Converts the tree into a format that can be stored or transmitted,
     * preserving the complete structure and all values.
     *
     * The serialized format for each node type is:
     * 1. Stem Node:
     *    ```json
     *    {
     *      "nodeType": "stem",
     *      "stem": "hex string of 31 bytes",
     *      "values": ["hex string or null", ...] // 256 entries
     *    }
     *    ```
     * 2. Internal Node:
     *    ```json
     *    {
     *      "nodeType": "internal",
     *      "left": <node or null>,
     *      "right": <node or null>
     *    }
     *    ```
     *
     * @returns Buffer containing the JSON string representation of the tree
     *
     * @example
     * ```typescript
     * const tree = new BinaryTree(hashFn)
     * tree.insert(key, value)
     * const serialized = tree.serialize()
     * // Save to file or transmit
     * const newTree = UnifiedBinaryTree.deserialize(serialized, hashFn)
     * ```
     */
    serialize(): Buffer;
    /**
     * Reconstructs a BinaryTree from its serialized form.
     * This is the inverse operation of serialize().
     *
     * Expected input format:
     * ```json
     * {
     *   "root": {
     *     "nodeType": "internal"|"stem",
     *     // For stem nodes:
     *     "stem": "hex string",
     *     "values": ["hex string"|null, ...],
     *     // For internal nodes:
     *     "left": <node|null>,
     *     "right": <node|null>
     *   }
     * }
     * ```
     *
     * @param data - Buffer containing the JSON serialized tree
     * @param hashFn - Hash function to use for the reconstructed tree
     * @returns A new BinaryTree instance with the deserialized structure
     * @throws Error if JSON parsing fails or format is invalid
     *
     * @example
     * ```typescript
     * const serialized = existingTree.serialize()
     * const newTree = UnifiedBinaryTree.deserialize(serialized, hashFn)
     * // newTree is now identical to existingTree
     * ```
     */
    static deserialize(data: Buffer, hashFn: HashFunction): UnifiedBinaryTree;
    /**
     * Splits a leaf node when inserting a new key with a different stem.
     * This method handles two cases:
     * 1. Matching bits at current depth: Continue splitting recursively
     * 2. Different bits at current depth: Create new internal node and arrange leaves
     *
     * The process ensures that keys with different stems are properly distributed
     * in the tree based on their binary representation.
     *
     * @param leaf - The existing leaf node to split
     * @param stemBits - Binary representation of the new stem
     * @param existingStemBits - Binary representation of the existing stem
     * @param subIndex - Position within leaf node for new value
     * @param value - Value to store at the new position
     * @param depth - Current depth in the tree
     * @returns A new internal node containing both the existing and new data
     *
     * Example:
     * If stems differ at bit 3:
     * - New stem:      [1,0,1,0,...]
     * - Existing stem: [1,0,1,1,...]
     *                        ^ split here
     * Creates an internal node with the leaf nodes arranged based on bit 3
     */
    private splitLeaf;
}
