import { AccountUpdate, Bool, Field, SmartContract, State, UInt64, PublicKey, TokenContract, Provable, type DeployArgs, VerificationKey, AccountUpdateForest } from 'o1js';
import { FrC, NodeProofLeft } from '@nori-zk/proof-conversion/min';
import { EthInput, Bytes32FieldPair } from '@nori-zk/o1js-zk-utils';
import { MerkleTreeContractDepositAttestorInput } from './depositAttestation.js';
import { SCRAMWitness } from './scram.js';
export type FungibleTokenAdminBase = SmartContract & {
    canMint(accountUpdate: AccountUpdate): Promise<Bool>;
    canChangeAdmin(admin: PublicKey): Promise<Bool>;
    canPause(): Promise<Bool>;
    canResume(): Promise<Bool>;
    canChangeVerificationKey(vk: VerificationKey): Promise<Bool>;
};
export interface NoriTokenControllerDeployProps extends Exclude<DeployArgs, undefined> {
    adminPublicKey: PublicKey;
    tokenBaseAddress: PublicKey;
    storageVKHash: Field;
    newStoreHash: Bytes32FieldPair;
    ethTokenBridgeAddress: Field;
    noriHeliosProgramPi0: FrC;
    proofConversionPO2: Field;
    genesisRoot: Field;
}
declare const BurnEvent_base: (new (value: {
    from: PublicKey;
    amount: UInt64;
    burnedSoFar: UInt64;
    receiverEth: import("o1js/dist/node/lib/provable/field.js").Field;
}) => {
    from: PublicKey;
    amount: UInt64;
    burnedSoFar: UInt64;
    receiverEth: import("o1js/dist/node/lib/provable/field.js").Field;
}) & {
    _isStruct: true;
} & Omit<import("o1js/dist/node/lib/provable/types/provable-intf.js").Provable<{
    from: PublicKey;
    amount: UInt64;
    burnedSoFar: UInt64;
    receiverEth: import("o1js/dist/node/lib/provable/field.js").Field;
}, {
    from: {
        x: bigint;
        isOdd: boolean;
    };
    amount: bigint;
    burnedSoFar: bigint;
    receiverEth: bigint;
}>, "fromFields"> & {
    fromFields: (fields: import("o1js/dist/node/lib/provable/field.js").Field[]) => {
        from: PublicKey;
        amount: UInt64;
        burnedSoFar: UInt64;
        receiverEth: import("o1js/dist/node/lib/provable/field.js").Field;
    };
} & {
    fromValue: (value: {
        from: PublicKey | {
            x: Field | bigint;
            isOdd: Bool | boolean;
        };
        amount: number | bigint | UInt64;
        burnedSoFar: number | bigint | UInt64;
        receiverEth: string | number | bigint | import("o1js/dist/node/lib/provable/field.js").Field;
    }) => {
        from: PublicKey;
        amount: UInt64;
        burnedSoFar: UInt64;
        receiverEth: import("o1js/dist/node/lib/provable/field.js").Field;
    };
    toInput: (x: {
        from: PublicKey;
        amount: UInt64;
        burnedSoFar: UInt64;
        receiverEth: import("o1js/dist/node/lib/provable/field.js").Field;
    }) => {
        fields?: Field[] | undefined;
        packed?: [Field, number][] | undefined;
    };
    toJSON: (x: {
        from: PublicKey;
        amount: UInt64;
        burnedSoFar: UInt64;
        receiverEth: import("o1js/dist/node/lib/provable/field.js").Field;
    }) => {
        from: string;
        amount: string;
        burnedSoFar: string;
        receiverEth: string;
    };
    fromJSON: (x: {
        from: string;
        amount: string;
        burnedSoFar: string;
        receiverEth: string;
    }) => {
        from: PublicKey;
        amount: UInt64;
        burnedSoFar: UInt64;
        receiverEth: import("o1js/dist/node/lib/provable/field.js").Field;
    };
    empty: () => {
        from: PublicKey;
        amount: UInt64;
        burnedSoFar: UInt64;
        receiverEth: import("o1js/dist/node/lib/provable/field.js").Field;
    };
};
export declare class BurnEvent extends BurnEvent_base {
}
declare class DepositRootAction extends Field {
}
/**
 * NoriTokenBridge — Mina anchor for the Nori ETH ↔ Mina token bridge.
 *
 * Verifies SP1 consensus MPT transition proofs (`update`), maintains a rolling
 * window of verified Ethereum deposit roots, and mints the corresponding
 * FungibleToken balance when a user presents a matching deposit plus SCRAM
 * witness (`noriMint`). Also supports burning for the Mina → ETH direction
 * (`alignedLock`).
 *
 * Acts as the admin contract for the FungibleToken — `canMint` gates minting
 * via a single-use `mintLock` flag that `noriMint` flips immediately before
 * calling `token.mint`. Direct calls to `FungibleToken.mint` therefore fail.
 */
export declare class NoriTokenBridge extends TokenContract implements FungibleTokenAdminBase {
    /** Admin key authorised to set integrity params, update VKs, rotate the store hash, and inject deposit roots. */
    adminPublicKey: State<PublicKey>;
    /** Address of the FungibleToken this bridge mints into / burns from. */
    tokenBaseAddress: State<PublicKey>;
    /** Required VK hash for every per-user NoriStorageInterface account (enforced in setUpStorage). */
    storageVKHash: State<import("o1js/dist/node/lib/provable/field.js").Field>;
    /**
     * Single-use mint gate. `noriMint` clears this (false) just before calling
     * `token.mint`; `canMint` then requires it false and re-locks it (true).
     * Any `FungibleToken.mint` call not originating from `noriMint` fails
     * because the lock remains true.
     */
    mintLock: State<import("o1js/dist/node/lib/provable/bool.js").Bool>;
    /** Poseidon hash of the most recently verified Ethereum execution state root (Field(1) before the first update). */
    verifiedStateRoot: State<import("o1js/dist/node/lib/provable/field.js").Field>;
    /** Latest Ethereum slot verified by this bridge (strictly increasing). */
    latestHead: State<UInt64>;
    /**
     * Public input 0 from the SP1 consensus MPT transition proof (sp1Proof.proof.Plonk.public_inputs[0]),
     * the Nori SP1 Helios program identifier (bridgeHeadNoriSP1HeliosProgramPi0).
     * Canonical value committed in o1js-zk-utils/src/integrity/nori-sp1-helios-program.pi0.json —
     * a copy of nori-elf/nori-sp1-helios-program.pi0.json from bridge-head.
     * Set on-chain via updateNoriHeliosProgramPi0 after deployment (not baked into the circuit).
     * Changes frequently as the Helios light client evolves.
     */
    noriHeliosProgramPi0: State<FrC>;
    /**
     * Public output 2 from the converted consensus MPT transition proof
     * (proofConversionOutput.proofData.publicOutput[2]).
     * Canonical value committed in o1js-zk-utils/src/integrity/ProofConversion.sp1ToPlonk.po2.json.
     * Set on-chain via updateProofConversionPO2 after deployment (not baked into the circuit).
     * Infrequently changes, for instance when SP1 undergoes a major version upgrade
     * (e.g. v5 -> v6) that affects the cryptography of proof conversion.
     */
    proofConversionPO2: State<import("o1js/dist/node/lib/provable/field.js").Field>;
    /**
     * Poseidon hash of the Ethereum chain genesis validators root.
     * Immutable after deploy — no admin setter exists by design.
     *
     * The Helios store hash (latestHeliusStoreInputHash*) is an opaque commitment over a
     * serialized light client store containing finalized headers, sync committees, and
     * optionally a next sync committee / best valid update. It must be upgradable because:
     *   1. The store serialization format may need to change as Helios evolves.
     *   2. A best-valid-update scenario (e.g. extended finality failure on Ethereum) would
     *      require a forced Helios store reconstruction and therefore a new store hash.
     *
     * That necessary upgradability is a governance attack surface: because the store hash is
     * opaque, a compromised governance update could swap it to one rooted on a different chain
     * with no visible on-chain evidence or verification. This field prevents that — `update`
     * verifies the proof's genesis root against this value, so governance can rotate the
     * store hash (subject to the strictly-increasing slot constraint) but cannot redirect
     * the bridge to a different chain. The genesis validators root is a
     * fixed, well-known constant that does not change across non-contentious hard forks.
     */
    genesisRoot: State<import("o1js/dist/node/lib/provable/field.js").Field>;
    /** Chain-linkage hash (high byte) — the next proof's `inputStoreHash` must match this + lower bytes. */
    latestHeliusStoreInputHashHighByte: State<import("o1js/dist/node/lib/provable/field.js").Field>;
    /** Chain-linkage hash (lower 31 bytes), pair with `latestHeliusStoreInputHashHighByte`. */
    latestHeliusStoreInputHashLowerBytes: State<import("o1js/dist/node/lib/provable/field.js").Field>;
    /** Deposits root from the most recent successful `update` (exposed for off-chain consumers). */
    latestVerifiedContractDepositsRoot: State<import("o1js/dist/node/lib/provable/field.js").Field>;
    /** The Ethereum contract address associated with this token bridge. */
    ethTokenBridgeAddress: State<import("o1js/dist/node/lib/provable/field.js").Field>;
    /** Action-state hash marking the start of the valid deposit-root window. */
    windowStart: State<import("o1js/dist/node/lib/provable/field.js").Field>;
    /** Number of deposit-root actions currently in the window (max maxWindow). */
    windowSize: State<import("o1js/dist/node/lib/provable/field.js").Field>;
    readonly events: {
        Burn: typeof BurnEvent;
    };
    reducer: {
        dispatch(action: DepositRootAction): void;
        reduce<State>(actions: import("o1js").MerkleList<import("o1js").MerkleList<DepositRootAction>>, stateType: Provable<State>, reduce: (state: State, action: DepositRootAction) => State, initial: State, options?: {
            maxUpdatesWithActions?: number;
            maxActionsPerUpdate?: number;
            skipActionStatePrecondition?: boolean;
        }): State;
        forEach(actions: import("o1js").MerkleList<import("o1js").MerkleList<DepositRootAction>>, reduce: (action: DepositRootAction) => void, options?: {
            maxUpdatesWithActions?: number;
            maxActionsPerUpdate?: number;
            skipActionStatePrecondition?: boolean;
        }): void;
        getActions({ fromActionState, endActionState, }?: {
            fromActionState?: Field;
            endActionState?: Field;
        }): import("o1js").MerkleList<import("o1js").MerkleList<DepositRootAction>>;
        fetchActions({ fromActionState, endActionState, }?: {
            fromActionState?: Field;
            endActionState?: Field;
        }): Promise<DepositRootAction[][]>;
    };
    deploy(props: NoriTokenControllerDeployProps): Promise<void>;
    approveBase(_forest: AccountUpdateForest): Promise<void>;
    private ethVerify;
    /**
     * Settle the latest Ethereum state root and NoriTokenBridge deposit root
     * by verifying converted SP1 nori-bride-head proof
     * @param input public outputs from the SP1 proof
     * @param proof converted SP1 to Plonk proof, verified against the on-chain VK for the conversion circuit
     *
     * Verify an SP1 consensus MPT transition proof and advance the bridge
     * head. On success:
     *   - `input.genesisRoot` is verified against the immutable on-chain `genesisRoot`
     *     (rejects proofs from a different chain)
     *   - `input.contractAddress` is verified against `ethTokenBridgeAddress`
     *   - `latestHead` is set to `input.outputSlot` (must strictly increase)
     *   - `verifiedStateRoot` is set to Poseidon(`input.executionStateRoot`)
     *   - `latestHeliusStoreInputHash{HighByte,LowerBytes}` advance to the
     *     new store hash (prior values must match the proof's `inputStoreHash`)
     *   - `input.verifiedContractDepositsRoot` is dispatched into the rolling
     *     window; when the window is full, the oldest action is evicted —
     *     its identity is derived in-circuit via the reducer (no caller witness).
     */
    update(input: EthInput, proof: NodeProofLeft): Promise<void>;
    /**
     * Dispatch a new deposit root action and evict the oldest if the window is full.
     *
     * The oldest action is derived in-circuit by iterating the current window's
     * actions via the reducer. Because o1js's reducer asserts that the chain
     * `windowStart -> ... -> account.actionState` matches the actions it yields
     * (and Poseidon is collision-resistant), a poisoned `windowStart` cannot
     * pass reduce — and the action captured here is provably the real oldest.
     *
     * Order matters: reduce runs over the current window BEFORE the new root is
     * dispatched, so the new root is not part of the reduction scope.
     */
    private dispatchAndEvict;
    setUpStorage(user: PublicKey, vk: VerificationKey): Promise<void>;
    noriMint(merkleTreeContractDepositAttestorInput: MerkleTreeContractDepositAttestorInput, SCRAMWitness: SCRAMWitness, windowStartWitness: Field): Promise<void>;
    /**
     * @param amountToBurn  the amount the user wants to burn on Mina. Must be greater than minBridgeBurnAmount.
     * @param receiver - the Ethereum address (as a Field) that will receive the bridged tokens on the other side. Must be provided by the user when burning.
     */
    alignedLock(amountToBurn: Field, receiver: Field): Promise<void>;
    private ensureAdminSignature;
    /**
     * Update the verification key.
     * Required if proof-conversion vk has to change.
     * May be required for any changes with ethVerify() like EthInput type
     */
    updateVerificationKey(vk: VerificationKey): Promise<void>;
    updateNoriHeliosProgramPi0(newPi0: FrC): Promise<void>;
    updateProofConversionPO2(newPO2: Field): Promise<void>;
    updateStoreHash(newStoreHash: Bytes32FieldPair): Promise<void>;
    /**
     * FungibleToken admin hook. Pass-through gate: noriMint clears mintLock
     * immediately before calling token.mint; this method consumes that
     * clearance and re-locks. Direct calls to FungibleToken.mint therefore
     * fail because mintLock remains true outside of an active noriMint.
     */
    canMint(_accountUpdate: AccountUpdate): Promise<import("o1js/dist/node/lib/provable/bool.js").Bool>;
    canChangeAdmin(_admin: PublicKey): Promise<import("o1js/dist/node/lib/provable/bool.js").Bool>;
    canPause(): Promise<Bool>;
    canResume(): Promise<Bool>;
    canChangeVerificationKey(_vk: VerificationKey): Promise<Bool>;
}
export {};
