import { Field, Bool, Pickles, Provable } from '../snarky.js'; import { Types } from '../snarky/types.js'; import { PrivateKey, PublicKey } from './signature.js'; import { UInt64, UInt32, Int64, Sign } from './int.js'; import { SmartContract } from './zkapp.js'; import * as Precondition from './precondition.js'; import { Proof } from './proof_system.js'; import { Context } from './global-context.js'; export { Permissions, AccountUpdate, ZkappPublicInput }; export { smartContractContext, SetOrKeep, Permission, Preconditions, Body, Authorization, FeePayerUnsigned, ZkappCommand, zkappCommandToJson, addMissingSignatures, addMissingProofs, signJsonTransaction, ZkappStateLength, Events, SequenceEvents, TokenId, Token, CallForest, createChildAccountUpdate, AccountUpdatesLayout, zkAppProver, }; declare const ZkappStateLength = 8; declare let smartContractContext: Context.t<{ this: SmartContract; methodCallDepth: number; isCallback: boolean; selfUpdate: AccountUpdate; }>; declare let zkAppProver: { run(witnesses: unknown[], proverData: { transaction: ZkappCommand; accountUpdate: AccountUpdate; index: number; }, callback: () => Promise): Promise<[{ witnesses?: unknown[] | undefined; proverData?: any; inProver?: boolean | undefined; inCompile?: boolean | undefined; inCheckedComputation?: boolean | undefined; inAnalyze?: boolean | undefined; inRunAndCheck?: boolean | undefined; inWitnessBlock?: boolean | undefined; }, Result]>; getData(): { transaction: ZkappCommand; accountUpdate: AccountUpdate; index: number; }; }; declare type AuthRequired = Types.Json.AuthRequired; declare type AccountUpdateBody = Types.AccountUpdate['body']; declare type Update = AccountUpdateBody['update']; /** * Preconditions for the network and accounts */ declare type Preconditions = AccountUpdateBody['preconditions']; /** * Either set a value or keep it the same. */ declare type SetOrKeep = { isSome: Bool; value: T; }; /** * One specific permission value. * * A [[ Permission ]] tells one specific permission for our zkapp how it should behave * when presented with requested modifications. * * Use static factory methods on this class to use a specific behavior. See * documentation on those methods to learn more. */ declare type Permission = Types.AuthRequired; declare let Permission: { /** * Modification is impossible. */ impossible: () => Permission; /** * Modification is always permitted */ none: () => Permission; /** * Modification is permitted by zkapp proofs only */ proof: () => Permission; /** * Modification is permitted by signatures only, using the private key of the zkapp account */ signature: () => Permission; /** * Modification is permitted by zkapp proofs or signatures */ proofOrSignature: () => Permission; }; declare type Permissions_ = Update['permissions']['value']; /** * Permissions specify how specific aspects of the zkapp account are allowed to * be modified. All fields are denominated by a [[ Permission ]]. */ interface Permissions extends Permissions_ { /** * The [[ Permission ]] corresponding to the 8 state fields associated with an * account. */ editState: Permission; /** * The [[ Permission ]] corresponding to the ability to send transactions from this * account. */ send: Permission; /** * The [[ Permission ]] corresponding to the ability to receive transactions to this * account. */ receive: Permission; /** * The [[ Permission ]] corresponding to the ability to set the delegate field of * the account. */ setDelegate: Permission; /** * The [[ Permission ]] corresponding to the ability to set the permissions field of * the account. */ setPermissions: Permission; /** * The [[ Permission ]] corresponding to the ability to set the verification key * associated with the circuit tied to this account. Effectively * "upgradability" of the smart contract. */ setVerificationKey: Permission; /** * The [[ Permission ]] corresponding to the ability to set the zkapp uri typically * pointing to the source code of the smart contract. Usually this should be * changed whenever the [[ Permissions.setVerificationKey ]] is changed. * Effectively "upgradability" of the smart contract. */ setZkappUri: Permission; /** * The [[ Permission ]] corresponding to the ability to change the sequence state * associated with the account. * * TODO: Define sequence state here as well. */ editSequenceState: Permission; /** * The [[ Permission ]] corresponding to the ability to set the token symbol for * this account. */ setTokenSymbol: Permission; incrementNonce: Permission; setVotingFor: Permission; } declare let Permissions: { /** * Default permissions are: * [[ Permissions.editState ]]=[[ Permission.proof ]] * [[ Permissions.send ]]=[[ Permission.signature ]] * [[ Permissions.receive ]]=[[ Permission.none ]] * [[ Permissions.setDelegate ]]=[[ Permission.signature ]] * [[ Permissions.setPermissions ]]=[[ Permission.signature ]] * [[ Permissions.setVerificationKey ]]=[[ Permission.signature ]] * [[ Permissions.setZkappUri ]]=[[ Permission.signature ]] * [[ Permissions.editSequenceState ]]=[[ Permission.proof ]] * [[ Permissions.setTokenSymbol ]]=[[ Permission.signature ]] */ default: () => Permissions; initial: () => Permissions; fromString: (permission: AuthRequired) => Permission; fromJSON: (permissions: { editState: AuthRequired; send: AuthRequired; receive: AuthRequired; setDelegate: AuthRequired; setPermissions: AuthRequired; setVerificationKey: AuthRequired; setZkappUri: AuthRequired; editSequenceState: AuthRequired; setTokenSymbol: AuthRequired; incrementNonce: AuthRequired; setVotingFor: AuthRequired; }) => Permissions; /** * Modification is impossible. */ impossible: () => Permission; /** * Modification is always permitted */ none: () => Permission; /** * Modification is permitted by zkapp proofs only */ proof: () => Permission; /** * Modification is permitted by signatures only, using the private key of the zkapp account */ signature: () => Permission; /** * Modification is permitted by zkapp proofs or signatures */ proofOrSignature: () => Permission; }; declare type Event = Field[]; declare type Events = { hash: Field; data: Event[]; }; declare const Events: { empty(): Events; pushEvent(events: Events, event: Event): Events; hash(events: Event[]): Field; }; declare const SequenceEvents: { empty(): Events; pushEvent(sequenceEvents: Events, event: Event): Events; hash(events: Event[]): Field; emptySequenceState(): Field; updateSequenceState(state: Field, sequenceEventsHash: Field): Field; }; /** * The body of describing how some [[ AccountUpdate ]] should change. * * TODO: We need to rename this still. */ interface Body extends AccountUpdateBody { /** * The address for this body. */ publicKey: PublicKey; /** * Specify [[ Update ]]s to tweakable pieces of the account record backing * this address in the ledger. */ update: Update; /** * The TokenId for this account. */ tokenId: Field; /** * By what [[ Int64 ]] should the balance of this account change. All * balanceChanges must balance by the end of smart contract execution. */ balanceChange: { magnitude: UInt64; sgn: Sign; }; /** * Recent events that have been emitted from this account. * * TODO: Add a reference to general explanation of events. */ events: Events; sequenceEvents: Events; caller: Field; callData: Field; callDepth: number; preconditions: Preconditions; useFullCommitment: Bool; incrementNonce: Bool; authorizationKind: AccountUpdateBody['authorizationKind']; } declare const Body: { noUpdate(): Update; /** * A body that Don't change part of the underlying account record. */ keepAll(publicKey: PublicKey): Body; dummy(): Body; }; declare type FeePayer = Types.ZkappCommand['feePayer']; declare type FeePayerUnsigned = FeePayer & { lazyAuthorization?: LazySignature | undefined; }; /** * Either check a value or ignore it. * * Used within [[ AccountPredicate ]]s and [[ ProtocolStatePredicate ]]s. */ declare type OrIgnore = { isSome: Bool; value: T; }; /** * An interval representing all the values between `lower` and `upper` inclusive * of both the `lower` and `upper` values. * * @typeParam A something with an ordering where one can quantify a lower and * upper bound. */ declare type ClosedInterval = { lower: T; upper: T; }; declare const Preconditions: { ignoreAll(): Preconditions; }; declare type Control = Types.AccountUpdate['authorization']; declare type LazyNone = { kind: 'lazy-none'; }; declare type LazySignature = { kind: 'lazy-signature'; privateKey?: PrivateKey; }; declare type LazyProof = { kind: 'lazy-proof'; methodName: string; args: any[]; previousProofs: { publicInput: Field[]; proof: Pickles.Proof; }[]; ZkappClass: typeof SmartContract; memoized: { fields: Field[]; aux: any[]; }[]; blindingValue: Field; }; declare const TokenId: { default: Field; toBase58(field: Field): string; fromBase58(base58: string): Field; toJSON(x: Field): string; toFields: (x: Field) => Field[]; toAuxiliary: (x?: Field | undefined) => any[]; fromFields: (x: Field[], aux: any[]) => Field; sizeInFields(): number; check: (x: Field) => void; toInput: (x: Field) => { fields?: Field[] | undefined; packed?: [Field, number][] | undefined; }; }; declare class Token { readonly id: Field; readonly parentTokenId: Field; readonly tokenOwner: PublicKey; static Id: { default: Field; toBase58(field: Field): string; fromBase58(base58: string): Field; toJSON(x: Field): string; toFields: (x: Field) => Field[]; toAuxiliary: (x?: Field | undefined) => any[]; fromFields: (x: Field[], aux: any[]) => Field; sizeInFields(): number; check: (x: Field) => void; toInput: (x: Field) => { fields?: Field[] | undefined; packed?: [Field, number][] | undefined; }; }; static getId(tokenOwner: PublicKey, parentTokenId?: Field): Field; constructor({ tokenOwner, parentTokenId, }: { tokenOwner: PublicKey; parentTokenId?: Field; }); } declare class AccountUpdate implements Types.AccountUpdate { id: number; /** * A human-readable label for the account update, indicating how that update was created. * Can be modified by applications to add richer information. */ label: string; body: Body; isDelegateCall: Bool; authorization: Control; lazyAuthorization: LazySignature | LazyProof | LazyNone | undefined; account: Precondition.Account; network: Precondition.Network; children: { callsType: { type: 'None'; } | { type: 'Witness'; } | { type: 'Equals'; value: Field; }; accountUpdates: AccountUpdate[]; }; parent: AccountUpdate | undefined; private isSelf; static SequenceEvents: { empty(): Events; pushEvent(sequenceEvents: Events, event: Event): Events; hash(events: Event[]): Field; emptySequenceState(): Field; updateSequenceState(state: Field, sequenceEventsHash: Field): Field; }; constructor(body: Body, authorization?: Control); static clone(accountUpdate: AccountUpdate): AccountUpdate; token(): { id: Field; parentTokenId: Field; tokenOwner: Types.PublicKey; mint({ address, amount, }: { address: PublicKey; amount: number | bigint | UInt64; }): AccountUpdate; burn({ address, amount, }: { address: PublicKey; amount: number | bigint | UInt64; }): void; send({ from, to, amount, }: { from: PublicKey; to: PublicKey; amount: number | bigint | UInt64; }): AccountUpdate; }; get tokenId(): Field; get tokenSymbol(): { set(tokenSymbol: string): void; }; send({ to, amount, }: { to: PublicKey | AccountUpdate; amount: number | bigint | UInt64; }): void; approve(childUpdate: AccountUpdate, layout?: AccountUpdatesLayout): void; get balance(): { addInPlace(x: Int64 | UInt32 | UInt64 | string | number | bigint): void; subInPlace(x: Int64 | UInt32 | UInt64 | string | number | bigint): void; }; get update(): Update; static setValue(maybeValue: SetOrKeep, value: T): void; /** Constrain a property to lie between lower and upper bounds. * * @param property The property to constrain * @param lower The lower bound * @param upper The upper bound * * Example: To constrain the account balance of a SmartContract to lie between 0 and 20 MINA, you can use * * ```ts * \@method onlyRunsWhenBalanceIsLow() { * let lower = UInt64.zero; * let upper = UInt64.from(20e9); * AccountUpdate.assertBetween(this.self.body.preconditions.account.balance, lower, upper); * // ... * } * ``` */ static assertBetween(property: OrIgnore>, lower: T, upper: T): void; /** Fix a property to a certain value. * * @param property The property to constrain * @param value The value it is fixed to * * Example: To fix the account nonce of a SmartContract to 0, you can use * * ```ts * \@method onlyRunsWhenNonceIsZero() { * AccountUpdate.assertEquals(this.self.body.preconditions.account.nonce, UInt32.zero); * // ... * } * ``` */ static assertEquals(property: OrIgnore | T>, value: T): void; get publicKey(): PublicKey; sign(privateKey?: PrivateKey): void; static signFeePayerInPlace(feePayer: FeePayerUnsigned, privateKey?: PrivateKey): void; static getNonce(accountUpdate: AccountUpdate | FeePayerUnsigned): any; private static getNonceUnchecked; toJSON(): Types.Json.AccountUpdate; hash(): Field; toPublicInput(): ZkappPublicInput; static defaultAccountUpdate(address: PublicKey, tokenId?: Field): AccountUpdate; static dummy(): AccountUpdate; isDummy(): Bool; static defaultFeePayer(address: PublicKey, key: PrivateKey, nonce: UInt32): FeePayerUnsigned; static dummyFeePayer(): FeePayerUnsigned; static create(publicKey: PublicKey, tokenId?: Field): AccountUpdate; static attachToTransaction(accountUpdate: AccountUpdate): void; static createSigned(signer: PrivateKey): AccountUpdate; /** * Use this method to pay the account creation fee for another account. * Beware that you _don't_ need to pass in the new account! * Instead, the protocol will automatically identify accounts in your transaction that need funding. * * If you provide an optional `initialBalance`, this will be subtracted from the fee-paying account as well, * but you have to separately ensure that it's added to the new account's balance. * * @param feePayerKey the private key of the account that pays the fee * @param initialBalance the initial balance of the new account (default: 0) */ static fundNewAccount(feePayerKey: PrivateKey, { initialBalance }?: { initialBalance?: string | number | Types.UInt64 | undefined; }): void; private static provable; private toProvable; static sizeInFields: () => number; static toFields(a: AccountUpdate): Field[]; static toAuxiliary(a?: AccountUpdate): (any[] | { lazyAuthorization: LazySignature | LazyProof | LazyNone | undefined; children: { callsType: { type: "None"; } | { type: "Witness"; } | { type: "Equals"; value: Field; }; accountUpdates: AccountUpdate[]; }; parent: AccountUpdate | undefined; id: number; label: string; })[]; static toInput(a: AccountUpdate): { fields?: Field[] | undefined; packed?: [Field, number][] | undefined; }; static toJSON(a: AccountUpdate): { accountUpdate: Types.Json.AccountUpdate; isDelegateCall: boolean; }; static check(a: AccountUpdate): void; static fromFields(fields: Field[], [other, aux]: any[]): AccountUpdate; static witness(type: Provable, compute: () => { accountUpdate: AccountUpdate; result: T; }, { skipCheck }?: { skipCheck?: boolean | undefined; }): { accountUpdate: AccountUpdate; result: T; }; static witnessChildren(accountUpdate: AccountUpdate, childLayout: AccountUpdatesLayout, options?: { skipCheck: boolean; }): void; /** * Like AccountUpdate.witness, but lets you specify a layout for the accountUpdate's children, * which also get witnessed */ static witnessTree(resultType: Provable, childLayout: AccountUpdatesLayout, compute: () => { accountUpdate: AccountUpdate; result: T; }, options?: { skipCheck: boolean; }): { accountUpdate: AccountUpdate; result: T; }; /** * Describes the children of an account update, which are laid out in a tree. * * The tree layout is described recursively by using a combination of `AccountUpdate.Layout.NoChildren`, `AccountUpdate.Layout.StaticChildren(...)` and `AccountUpdate.Layout.AnyChildren`. * - `NoChildren` means an account update that can't have children * - `AnyChildren` means an account update can have an arbitrary amount of children, which means you can't access those children in your circuit (because the circuit is static). * - `StaticChildren` means the account update must have a certain static amount of children and expects as arguments a description of each of those children. * As a shortcut, you can also pass `StaticChildren` a number, which means it has that amount of children but no grandchildren. * * This is best understood by examples: * * ```ts * let { NoChildren, AnyChildren, StaticChildren } = AccounUpdate.Layout; * * NoChildren // an account update with no children * AnyChildren // an account update with arbitrary children * StaticChildren(NoChildren) // an account update with 1 child, which doesn't have children itself * StaticChildren(1) // shortcut for StaticChildren(NoChildren) * StaticChildren(2) // shortcut for StaticChildren(NoChildren, NoChildren) * StaticChildren(0) // equivalent to NoChildren * * // an update with 2 children, of which one has arbitrary children and the other has exactly 1 descendant * StaticChildren(AnyChildren, StaticChildren(1)) * ``` */ static Layout: { StaticChildren: { (n: number): AccountUpdatesLayout; (...args: AccountUpdatesLayout[]): AccountUpdatesLayout; }; NoChildren: number; AnyChildren: "AnyChildren"; NoDelegation: "NoDelegation"; }; toPretty(): any; } declare type AccountUpdatesLayout = number | 'AnyChildren' | 'NoDelegation' | AccountUpdatesLayout[]; declare const CallForest: { toFlatList(forest: AccountUpdate[], depth?: number): AccountUpdate[]; emptyHash(): Field; hashChildren(update: AccountUpdate): Field; hashChildrenBase({ children }: AccountUpdate): Field; addCallers(updates: AccountUpdate[], context?: { self: Field; caller: Field; }): void; /** * Used in the prover to witness the context from which to compute its caller */ computeCallerContext(update: AccountUpdate): { self: Field; caller: Field; }; callerContextType: import("../snarky.js").ProvablePure<{ self: Field; caller: Field; }> & { toInput: (x: { self: Field; caller: Field; }) => { fields?: Field[] | undefined; packed?: [Field, number][] | undefined; }; toJSON: (x: { self: Field; caller: Field; }) => { self: string; caller: string; }; }; computeCallDepth(update: AccountUpdate): number; forEach(updates: AccountUpdate[], callback: (update: AccountUpdate) => void): void; forEachPredecessor(updates: AccountUpdate[], update: AccountUpdate, callback: (update: AccountUpdate) => void): void; }; declare function createChildAccountUpdate(parent: AccountUpdate, childAddress: PublicKey, tokenId?: Field): AccountUpdate; declare type ZkappCommand = { feePayer: FeePayerUnsigned; accountUpdates: AccountUpdate[]; memo: string; }; declare type ZkappCommandSigned = { feePayer: FeePayer; accountUpdates: (AccountUpdate & { lazyAuthorization?: LazyProof; })[]; memo: string; }; declare type ZkappCommandProved = { feePayer: FeePayerUnsigned; accountUpdates: (AccountUpdate & { lazyAuthorization?: LazySignature; })[]; memo: string; }; declare const ZkappCommand: { toPretty(transaction: ZkappCommand): any[]; }; declare function zkappCommandToJson({ feePayer, accountUpdates, memo }: ZkappCommand): Types.Json.ZkappCommand; declare const Authorization: { hasLazyProof(accountUpdate: AccountUpdate): boolean; hasAny(accountUpdate: AccountUpdate): boolean; setSignature(accountUpdate: AccountUpdate, signature: string): void; setProof(accountUpdate: AccountUpdate, proof: string): void; setLazySignature(accountUpdate: AccountUpdate, signature?: Omit): void; setLazyProof(accountUpdate: AccountUpdate, proof: Omit): void; setLazyNone(accountUpdate: AccountUpdate): void; }; declare function addMissingSignatures(zkappCommand: ZkappCommand, additionalKeys?: PrivateKey[]): ZkappCommandSigned; /** * The public input for zkApps consists of certain hashes of the proving AccountUpdate (and its child accountUpdates) which is constructed during method execution. For SmartContract proving, a method is run twice: First outside the proof, to obtain the public input, and once in the prover, which takes the public input as input. The current transaction is hashed again inside the prover, which asserts that the result equals the input public input, as part of the snark circuit. The block producer will also hash the transaction they receive and pass it as a public input to the verifier. Thus, the transaction is fully constrained by the proof - the proof couldn't be used to attest to a different transaction. */ declare type ZkappPublicInput = { accountUpdate: Field; calls: Field; }; declare let ZkappPublicInput: import("../snarky.js").ProvablePure<{ accountUpdate: Field; calls: Field; }> & { toInput: (x: { accountUpdate: Field; calls: Field; }) => { fields?: Field[] | undefined; packed?: [Field, number][] | undefined; }; toJSON: (x: { accountUpdate: Field; calls: Field; }) => { accountUpdate: string; calls: string; }; }; declare function addMissingProofs(zkappCommand: ZkappCommand, { proofsEnabled }: { proofsEnabled?: boolean | undefined; }): Promise<{ zkappCommand: ZkappCommandProved; proofs: (Proof | undefined)[]; }>; /** * Sign all accountUpdates of a transaction which belong to the account determined by [[ `privateKey` ]]. * @returns the modified transaction JSON */ declare function signJsonTransaction(transactionJson: string, privateKey: PrivateKey | string): string;