o1js
Version:
TypeScript framework for zk-SNARKs and zkApps
689 lines • 29.6 kB
JavaScript
import { AccountId, AccountTiming } from './account.js';
import { AccountUpdateAuthorizationKind, AccountUpdateAuthorizationKindWithZkappContext, } from './authorization.js';
import { Option, TokenId, Update, ZkappUri, mapUndefined } from './core.js';
import { Permissions } from './permissions.js';
import { Preconditions } from './preconditions.js';
import { GenericStateUpdates, StateUpdates } from './state.js';
import { Pickles } from '../../../bindings.js';
import { Bool } from '../../provable/bool.js';
import { Field } from '../../provable/field.js';
import { Int64, UInt64 } from '../../provable/int.js';
import { Proof } from '../../proof-system/zkprogram.js';
import { emptyHashWithPrefix, hashWithPrefix, packToFields, TokenSymbol, } from '../../provable/crypto/poseidon.js';
import { PublicKey } from '../../provable/crypto/signature.js';
import { mocks, prefixes } from '../../../bindings/crypto/constants.js';
import * as Bindings from '../../../bindings/mina-transaction/v2/index.js';
import * as PoseidonBigint from '../../../mina-signer/src/poseidon-bigint.js';
import { Signature, signFieldElement, zkAppBodyPrefix, } from '../../../mina-signer/src/signature.js';
import { Struct } from '../../provable/types/struct.js';
import { VerificationKey } from '../../../lib/proof-system/verification-key.js';
// TODO: make private abstractions over many fields (eg new apis for Update and Constraint.*)
// TODO: replay checks
export { AccountUpdate, Authorized, GenericData, AccountUpdateTree, ContextFreeAccountUpdate, AccountUpdateCommitment, CommittedList, EventsHashConfig, ActionsHashConfig, };
class AccountUpdateCommitment extends Struct({
accountUpdateCommitment: Field,
}) {
constructor(accountUpdateCommitment) {
super({ accountUpdateCommitment });
}
}
// TODO: move elsewhere
const GenericData = {
toFields(x) {
return x;
},
toAuxiliary(x) {
return [x.length];
},
fromFieldsDynamic(fields, aux) {
const [_len] = aux;
let len = _len ?? fields.length;
return { value: fields.slice(0, len), fieldsConsumed: len };
},
};
function EventsHashConfig(T) {
return {
emptyPrefix: 'MinaZkappEventsEmpty',
consPrefix: prefixes.events,
hash(x) {
const fields = T.toFields(x);
return hashWithPrefix(prefixes.event, fields);
},
};
}
function ActionsHashConfig(T) {
return {
emptyPrefix: 'MinaZkappActionsEmpty',
consPrefix: prefixes.sequenceEvents,
hash(x) {
const fields = T.toFields(x);
return hashWithPrefix(prefixes.event, fields);
},
};
}
// TODO: move elsewhere
class CommittedList {
constructor({ Item, data, hash }) {
this.Item = Item;
this.data = data;
this.hash = hash;
}
toInternalRepr() {
return {
data: this.data.map(this.Item.toFields),
hash: this.hash,
};
}
// IMPORTANT: It is the callers responsibility to ensure the commitment will compute the same
// after mapping the list (this function does not check this for you at runtime).
mapUnsafe(NewItem, f) {
return new CommittedList({
Item: NewItem,
data: this.data.map(f),
hash: this.hash,
});
}
static hashList(config, items) {
let hash = emptyHashWithPrefix(config.emptyPrefix);
for (let i = items.length - 1; i >= 0; i--) {
const item = items[i];
hash = hashWithPrefix(config.consPrefix, [hash, config.hash(item)]);
}
return hash;
}
static from(Item, config, value) {
if (value instanceof CommittedList)
return value;
let items;
//let hash;
if (value === undefined) {
items = [];
}
else if (value instanceof Array) {
items = value;
}
else {
// TODO: think about this a bit more... we don't have the aux data here, so we should do
// something to restrict the types
if ('fromFields' in Item) {
items = value.data.map((fields) => Item.fromFields(fields, []));
}
else {
items = value.data.map((fields) => {
const { value: result, fieldsConsumed } = Item.fromFieldsDynamic(fields, []);
if (fieldsConsumed !== fields.length)
throw new Error('expected all fields to be consumed when casting dynamic item');
return result;
});
}
//hash = value.hash;
}
//hash = hash ?? CommittedList.hashList(config, items);
return new CommittedList({
Item,
data: items,
hash: CommittedList.hashList(config, items),
});
}
}
// TODO: CONSIDER -- merge this logic into AccountUpdate
// class AccountUpdateTree<AccountUpdateType> {
class AccountUpdateTree {
constructor(rootAccountUpdate, children) {
this.rootAccountUpdate = rootAccountUpdate;
this.children = children;
}
// depth first traversal (parents before children)
static forEachNode(tree, depth, f) {
f(tree.rootAccountUpdate, depth);
tree.children.forEach((child) => AccountUpdateTree.forEachNode(child, depth + 1, f));
}
// inverted depth first traversal (children before parents)
static forEachNodeInverted(tree, depth, f) {
tree.children.forEach((child) => AccountUpdateTree.forEachNodeInverted(child, depth + 1, f));
f(tree.rootAccountUpdate, depth);
}
static reduce(tree, f) {
const childValues = tree.children.map((child) => AccountUpdateTree.reduce(child, f));
return f(tree.rootAccountUpdate, childValues);
}
// TODO: delete (realized I didn't need it part way through writing)
// // build context as we descend the tree, map, then reduce as we ascend
// static mapReduceWithContext<T, Ctx, R>(
// tree: AccountUpdateTree<T>,
// context: Ctx,
// mapContext: (ctx: Ctx, index: number) => Ctx,
// map: (ctx: Ctx, accountUpdate: T) => R,
// reduce: (values: R[]) => R
// ): R {
// if(tree.children.length === 0) {
// return map(context, tree.rootAccountUpdate);
// } else {
// const reducedValues = tree.children.map((child, index) =>
// AccountUpdateTree.mapReduceWithContext(
// child,
// mapContext(context, index),
// mapContext,
// map,
// reduce
// );
// );
// return reduce(reducedValues);
// }
// }
// TODO: refactor the type parameter interfaces
static mapRoot(tree, f) {
const newAccountUpdate = f(tree.rootAccountUpdate);
return new AccountUpdateTree(newAccountUpdate, tree.children);
}
static async map(tree, f) {
const newAccountUpdate = await f(tree.rootAccountUpdate);
const newChildren = await AccountUpdateTree.mapForest(tree.children, f);
return new AccountUpdateTree(newAccountUpdate, newChildren);
}
static mapForest(forest, f) {
return Promise.all(forest.map((tree) => AccountUpdateTree.map(tree, f)));
}
// TODO: I think this can be safely made polymorphic over the account update state, actions, and events representations
// TODO: Field, not bigint
static hash(tree, networkId) {
// TODO: is it ok to do this and ignore the toValue encodings entirely?
const accountUpdateFieldInput = tree.rootAccountUpdate.toInput();
const accountUpdateBigintInput = {
fields: accountUpdateFieldInput.fields?.map((f) => f.toBigInt()),
packed: accountUpdateFieldInput.packed?.map(([f, n]) => [
f.toBigInt(),
n,
]),
};
// TODO: negotiate between this implementation and AccountUpdate#hash to figure out what is correct
// TODO NOW: ^ this was done, but we need to update this function to share code still
const accountUpdateCommitment = PoseidonBigint.hashWithPrefix(zkAppBodyPrefix(networkId), PoseidonBigint.packToFields(accountUpdateBigintInput));
const childrenCommitment = AccountUpdateTree.hashForest(networkId, tree.children);
return PoseidonBigint.hashWithPrefix(prefixes.accountUpdateNode, [
accountUpdateCommitment,
childrenCommitment,
]);
}
// TODO: Field, not bigint
static hashForest(networkId, forest) {
const consHash = (acc, tree) => PoseidonBigint.hashWithPrefix(prefixes.accountUpdateCons, [
AccountUpdateTree.hash(tree, networkId),
acc,
]);
return [...forest].reverse().reduce(consHash, 0n);
}
static unrollForest(forest, f) {
const seq = [];
forest.forEach((tree) => AccountUpdateTree.forEachNode(tree, 0, (accountUpdate, depth) => seq.push(f(accountUpdate, depth))));
return seq;
}
static sizeInFields() {
return AccountUpdate.sizeInFields();
}
static toFields(x) {
return AccountUpdate.toFields(x.rootAccountUpdate);
}
static toAuxiliary(x) {
return [AccountUpdate.toAuxiliary(x?.rootAccountUpdate), x?.children ?? []];
}
static fromFields(fields, aux) {
return new AccountUpdateTree(AccountUpdate.fromFields(fields, aux[0]), aux[1]);
}
static toValue(x) {
return x;
}
static fromValue(x) {
return x;
}
static check(_x) {
// TODO
}
static from(descr, createAccountUpdate) {
return new AccountUpdateTree(createAccountUpdate(descr), descr.children ?? []);
}
}
// in a ZkModule context: ContextFreeAccountUpdate is an AccountUpdate without an account id and call data
class ContextFreeAccountUpdate {
constructor(State, Event, Action, descr) {
function castUpdate(value, defaultValue, f) {
if (value instanceof Update) {
return value;
}
else {
return Update.from(mapUndefined(value, f), defaultValue);
}
}
this.State = State;
this.authorizationKind = AccountUpdateAuthorizationKind.from(descr.authorizationKind);
this.preconditions =
mapUndefined(descr.preconditions, (x) => Preconditions.from(State, x)) ??
Preconditions.emptyPoly(State);
this.balanceChange = descr.balanceChange ?? Int64.create(UInt64.zero);
this.incrementNonce = descr.incrementNonce ?? new Bool(false);
this.useFullCommitment = descr.useFullCommitment ?? new Bool(false);
this.implicitAccountCreationFee = descr.implicitAccountCreationFee ?? new Bool(false);
this.mayUseToken = descr.mayUseToken ?? {
parentsOwnToken: new Bool(false),
inheritFromParent: new Bool(false),
};
this.pushEvents = CommittedList.from(Event, EventsHashConfig(Event), descr.pushEvents);
this.pushActions = CommittedList.from(Action, ActionsHashConfig(Action), descr.pushActions);
if (descr instanceof ContextFreeAccountUpdate) {
this.stateUpdates = descr.stateUpdates;
this.permissionsUpdate = descr.permissionsUpdate;
this.delegateUpdate = descr.delegateUpdate;
this.verificationKeyUpdate = descr.verificationKeyUpdate;
this.zkappUriUpdate = descr.zkappUriUpdate;
this.tokenSymbolUpdate = descr.tokenSymbolUpdate;
this.timingUpdate = descr.timingUpdate;
this.votingForUpdate = descr.votingForUpdate;
}
else {
this.stateUpdates = descr.setState ?? StateUpdates.empty(State);
this.permissionsUpdate = castUpdate(descr.setPermissions, Permissions.empty(), Permissions.from);
this.delegateUpdate = Update.from(descr.setDelegate, PublicKey.empty());
this.verificationKeyUpdate = Update.from(descr.setVerificationKey, VerificationKey.empty());
this.zkappUriUpdate = castUpdate(descr.setZkappUri, ZkappUri.empty(), ZkappUri.from);
this.tokenSymbolUpdate = castUpdate(descr.setTokenSymbol, TokenSymbol.empty(), TokenSymbol.from);
this.timingUpdate = Update.from(descr.setTiming, AccountTiming.empty());
this.votingForUpdate = Update.from(descr.setVotingFor, Field.empty());
}
}
toGeneric() {
return ContextFreeAccountUpdate.generic({
authorizationKind: this.authorizationKind,
preconditions: this.preconditions.toGeneric(),
balanceChange: this.balanceChange,
incrementNonce: this.incrementNonce,
useFullCommitment: this.useFullCommitment,
implicitAccountCreationFee: this.implicitAccountCreationFee,
mayUseToken: this.mayUseToken,
pushEvents: this.pushEvents.mapUnsafe(GenericData, this.pushEvents.Item.toFields),
pushActions: this.pushActions.mapUnsafe(GenericData, this.pushActions.Item.toFields),
setState: StateUpdates.toGeneric(this.State, this.stateUpdates),
setPermissions: this.permissionsUpdate,
setDelegate: this.delegateUpdate,
setVerificationKey: this.verificationKeyUpdate,
setZkappUri: this.zkappUriUpdate,
setTokenSymbol: this.tokenSymbolUpdate,
setTiming: this.timingUpdate,
setVotingFor: this.votingForUpdate,
});
}
static fromGeneric(x, State, Event, Action) {
// TODO: this method is broken because we aren't storing aux data in the generic format...
return new ContextFreeAccountUpdate(State, Event, Action, {
authorizationKind: x.authorizationKind,
preconditions: Preconditions.fromGeneric(x.preconditions, State),
balanceChange: x.balanceChange,
incrementNonce: x.incrementNonce,
useFullCommitment: x.useFullCommitment,
implicitAccountCreationFee: x.implicitAccountCreationFee,
mayUseToken: x.mayUseToken,
pushEvents: x.pushEvents.mapUnsafe(Event, (fields) =>
// TODO: this is really unsafe, make it safe
'fromFieldsDynamic' in Event
? Event.fromFieldsDynamic(fields, []).value
: Event.fromFields(fields, [])),
pushActions: x.pushActions.mapUnsafe(Action, (fields) =>
// TODO: this is really unsafe, make it safe
'fromFieldsDynamic' in Action
? Action.fromFieldsDynamic(fields, []).value
: Action.fromFields(fields, [])),
setState: StateUpdates.fromGeneric(x.stateUpdates, State),
setPermissions: x.permissionsUpdate,
setDelegate: x.delegateUpdate,
setVerificationKey: x.verificationKeyUpdate,
setZkappUri: x.zkappUriUpdate,
setTokenSymbol: x.tokenSymbolUpdate,
setTiming: x.timingUpdate,
setVotingFor: x.votingForUpdate,
});
}
static generic(descr) {
return new ContextFreeAccountUpdate('GenericState', GenericData, GenericData, descr);
}
static emptyPoly(State, Event, Action) {
return new ContextFreeAccountUpdate(State, Event, Action, {
authorizationKind: AccountUpdateAuthorizationKind.None(),
});
}
static empty() {
return ContextFreeAccountUpdate.emptyPoly('GenericState', GenericData, GenericData);
}
static from(State, Event, Action, x) {
if (x instanceof ContextFreeAccountUpdate)
return x;
if (x === undefined)
return ContextFreeAccountUpdate.emptyPoly(State, Event, Action);
return new ContextFreeAccountUpdate(State, Event, Action, x);
}
}
class AccountUpdate extends ContextFreeAccountUpdate {
// TODO: circuit friendly representation (we really don't want to toBoolean() in the constructor here...)
// proof: {pending: true, isRequired: Bool} | Proof<undefined, AccountUpdateCommitment>;
constructor(State, Event, Action, descr) {
// TODO NOW: THIS PATTERN IS BROKEN (we are casting and update into a description, which only works because the missing fields are all optional)
const superInput = 'update' in descr ? descr.update : descr;
super(State, Event, Action, superInput);
if (this.authorizationKind.isProved.toBoolean()) {
this.proof = 'proof' in descr && descr.proof !== undefined ? descr.proof : 'ProofPending';
}
else {
if ('proof' in descr && descr.proof !== undefined) {
throw new Error('proof was provided when constructing an AccountUpdate that does not require a proof');
}
this.proof = 'NoProofRequired';
}
this.accountId = descr.accountId;
this.verificationKeyHash =
descr.verificationKeyHash ?? new Field(mocks.dummyVerificationKeyHash);
this.callData = descr.callData ?? new Field(0);
}
get authorizationKindWithZkappContext() {
return new AccountUpdateAuthorizationKindWithZkappContext(this.authorizationKind, this.verificationKeyHash);
}
toInternalRepr(callDepth) {
return {
authorizationKind: this.authorizationKindWithZkappContext,
publicKey: this.accountId.publicKey,
tokenId: this.accountId.tokenId.value,
callData: this.callData,
callDepth: callDepth,
balanceChange: this.balanceChange,
incrementNonce: this.incrementNonce,
useFullCommitment: this.useFullCommitment,
implicitAccountCreationFee: this.implicitAccountCreationFee,
mayUseToken: this.mayUseToken,
events: this.pushEvents.toInternalRepr(),
actions: this.pushActions.toInternalRepr(),
preconditions: this.preconditions.toInternalRepr(),
update: {
appState: StateUpdates.toFieldUpdates(this.State, this.stateUpdates).map((update) => update.toOption()),
delegate: this.delegateUpdate.toOption(),
verificationKey: Option.map(this.verificationKeyUpdate.toOption(), (data) => data instanceof VerificationKey ? new VerificationKey(data) : data),
permissions: this.permissionsUpdate.toOption(),
zkappUri: this.zkappUriUpdate.toOption(),
tokenSymbol: this.tokenSymbolUpdate.toOption(),
timing: this.timingUpdate.toOption(),
votingFor: this.votingForUpdate.toOption(),
},
};
}
toInput() {
return Bindings.Layout.AccountUpdateBody.toInput(this.toInternalRepr(0));
}
commit(networkId) {
const commitment = hashWithPrefix(zkAppBodyPrefix(networkId), packToFields(this.toInput()));
return new AccountUpdateCommitment(commitment);
}
toGeneric() {
return new AccountUpdate('GenericState', GenericData, GenericData, {
update: super.toGeneric(),
proof: this.proof instanceof Proof ? this.proof : undefined,
accountId: this.accountId,
verificationKeyHash: this.verificationKeyHash,
callData: this.callData,
});
}
static fromGeneric(x, State, Event, Action) {
return new AccountUpdate(State, Event, Action, {
update: ContextFreeAccountUpdate.fromGeneric(x, State, Event, Action),
proof: x.proof instanceof Proof ? x.proof : undefined,
accountId: x.accountId,
verificationKeyHash: x.verificationKeyHash,
callData: x.callData,
});
}
async authorize(authEnv) {
let proof = null;
let signature = null;
switch (this.proof) {
case 'NoProofRequired':
if (this.authorizationKind.isProved.toBoolean()) {
throw new Error(`account update proof was marked as not required, but authorization kind was ${this.authorizationKind.identifier()}`);
}
else {
break;
}
case 'ProofPending':
if (this.authorizationKind.isProved.toBoolean()) {
throw new Error(`account update proof is still pending; a proof must be generated and assigned to an account update before calling authorize`);
}
else {
console.warn(`account update is marked to required a proof, but the authorization kind is ${this.authorizationKind.identifier()} (and the proof is still pending)`);
break;
}
default:
if (this.authorizationKind.isProved.toBoolean()) {
proof = Pickles.proofToBase64Transaction(this.proof.proof);
}
else {
console.warn(`account update has a proof, but no proof is required by authorization kind ${this.authorizationKind.identifier()}, so it will not be included`);
}
}
if (this.authorizationKind.isSigned.toBoolean()) {
let txnCommitment;
if (this.useFullCommitment.toBoolean()) {
if (authEnv.fullTransactionCommitment === undefined) {
throw new Error('unable to authorize account update: useFullCommitment is true, but not full transaction commitment was provided in authorization environment');
}
txnCommitment = authEnv.fullTransactionCommitment;
}
else {
txnCommitment = authEnv.accountUpdateForestCommitment;
}
const privateKey = await authEnv.getPrivateKey(this.accountId.publicKey);
const sig = signFieldElement(txnCommitment, privateKey.toBigInt(), authEnv.networkId);
signature = Signature.toBase58(sig);
}
return new Authorized({ proof, signature }, this);
}
static create(x) {
return new AccountUpdate('GenericState', GenericData, GenericData, x);
}
static fromInternalRepr(x) {
return new AccountUpdate('GenericState', GenericData, GenericData, {
accountId: new AccountId(x.publicKey, new TokenId(x.tokenId)),
verificationKeyHash: x.authorizationKind.verificationKeyHash,
authorizationKind: new AccountUpdateAuthorizationKind(x.authorizationKind),
callData: x.callData,
balanceChange: Int64.create(x.balanceChange.magnitude, x.balanceChange.sgn),
incrementNonce: x.incrementNonce,
useFullCommitment: x.useFullCommitment,
implicitAccountCreationFee: x.implicitAccountCreationFee,
mayUseToken: x.mayUseToken,
pushEvents: CommittedList.from(GenericData, EventsHashConfig(GenericData), x.events),
pushActions: CommittedList.from(GenericData, ActionsHashConfig(GenericData), x.actions),
preconditions: Preconditions.fromInternalRepr(x.preconditions),
setState: new GenericStateUpdates(x.update.appState.map(Update.fromOption)),
setDelegate: Update.fromOption(x.update.delegate),
setVerificationKey: Update.fromOption(x.update.verificationKey),
setPermissions: Update.fromOption(Option.map(x.update.permissions, Permissions.fromInternalRepr)),
setZkappUri: Update.fromOption(Option.map(x.update.zkappUri, (uri) => new ZkappUri(uri))),
setTokenSymbol: Update.fromOption(Option.map(x.update.tokenSymbol, (symbol) => new TokenSymbol(symbol))),
setTiming: Update.fromOption(Option.map(x.update.timing, (timing) => new AccountTiming(timing))),
setVotingFor: Update.fromOption(x.update.votingFor),
});
}
static sizeInFields() {
return Bindings.Layout.AccountUpdateBody.sizeInFields();
}
static toFields(x) {
return Bindings.Layout.AccountUpdateBody.toFields(x.toInternalRepr(0));
}
static toAuxiliary(x, callDepth) {
return Bindings.Layout.AccountUpdateBody.toAuxiliary(x?.toInternalRepr(callDepth ?? 0));
}
static fromFields(fields, aux) {
return AccountUpdate.fromInternalRepr(Bindings.Layout.AccountUpdateBody.fromFields(fields, aux));
}
static toValue(x) {
return x;
}
static fromValue(x) {
return x;
}
static check(_x) {
// TODO
}
static empty() {
return new AccountUpdate('GenericState', GenericData, GenericData, {
accountId: AccountId.empty(),
callData: Field.empty(),
update: ContextFreeAccountUpdate.empty(),
});
}
}
// TODO NOW: un-namespace this
/*
type ContextFreeDescription<
State extends StateLayout = 'GenericState',
Event = Field[],
Action = Field[]
> = ContextFreeAccountUpdateDescription<State, Event, Action>;
type ContextFree<
State extends StateLayout = 'GenericState',
Event = Field[],
Action = Field[]
> = ContextFreeAccountUpdate<State, Event, Action>;
const ContextFree = ContextFreeAccountUpdate;
*/
// TODO: can we enforce that Authorized account updates are immutable?
class Authorized {
constructor(authorization, update) {
this.authorization = authorization;
this.update = update;
}
toAccountUpdate() {
return this.update;
}
get State() {
return this.update.State;
}
get authorizationKind() {
return this.update.authorizationKind;
}
get accountId() {
return this.update.accountId;
}
get verificationKeyHash() {
return this.update.verificationKeyHash;
}
get callData() {
return this.update.callData;
}
get preconditions() {
return this.update.preconditions;
}
get balanceChange() {
return this.update.balanceChange;
}
get incrementNonce() {
return this.update.incrementNonce;
}
get useFullCommitment() {
return this.update.useFullCommitment;
}
get implicitAccountCreationFee() {
return this.update.implicitAccountCreationFee;
}
get mayUseToken() {
return this.update.mayUseToken;
}
get pushEvents() {
return this.update.pushEvents;
}
get pushActions() {
return this.update.pushActions;
}
get stateUpdates() {
return this.update.stateUpdates;
}
get permissionsUpdate() {
return this.update.permissionsUpdate;
}
get delegateUpdate() {
return this.update.delegateUpdate;
}
get verificationKeyUpdate() {
return this.update.verificationKeyUpdate;
}
get zkappUriUpdate() {
return this.update.zkappUriUpdate;
}
get tokenSymbolUpdate() {
return this.update.tokenSymbolUpdate;
}
get timingUpdate() {
return this.update.timingUpdate;
}
get votingForUpdate() {
return this.update.votingForUpdate;
}
get authorizationKindWithZkappContext() {
return this.update.authorizationKindWithZkappContext;
}
hash(netId) {
let input = Bindings.Layout.ZkappAccountUpdate.toInput(this.toInternalRepr(0));
return hashWithPrefix(zkAppBodyPrefix(netId), packToFields(input));
}
toInternalRepr(callDepth) {
return {
authorization: {
proof: this.authorization.proof === null ? undefined : this.authorization.proof,
signature: this.authorization.signature === null ? undefined : this.authorization.signature,
},
body: this.update.toInternalRepr(callDepth),
};
}
static fromInternalRepr(x) {
return new Authorized({
// when the internal representation is returned from the previous version when casting from fields,
// (if there is no proof or authorization, values are set to false rather than to undefined)
proof: x.authorization.proof !== false ? (x.authorization.proof ?? null) : null,
signature: x.authorization.proof !== false ? (x.authorization.signature ?? null) : null,
}, AccountUpdate.fromInternalRepr(x.body));
}
toJSON(callDepth) {
return Authorized.toJSON(this, callDepth);
}
toInput() {
return Authorized.toInput(this);
}
toFields() {
return Authorized.toFields(this);
}
static empty() {
return new Authorized({ proof: null, signature: null }, AccountUpdate.empty());
}
static sizeInFields() {
return Bindings.Layout.ZkappAccountUpdate.sizeInFields();
}
static toJSON(x, callDepth) {
return Bindings.Layout.ZkappAccountUpdate.toJSON(x.toInternalRepr(callDepth));
}
static toInput(x) {
return Bindings.Layout.ZkappAccountUpdate.toInput(x.toInternalRepr(0));
}
static toFields(x) {
return Bindings.Layout.ZkappAccountUpdate.toFields(x.toInternalRepr(0));
}
static toAuxiliary(x, callDepth) {
return Bindings.Layout.ZkappAccountUpdate.toAuxiliary(x?.toInternalRepr(callDepth ?? 0));
}
static fromFields(fields, aux) {
return Authorized.fromInternalRepr(Bindings.Layout.ZkappAccountUpdate.fromFields(fields, aux));
}
static toValue(x) {
return x;
}
static fromValue(x) {
return x;
}
static check(_x) {
throw new Error('TODO');
}
}
//# sourceMappingURL=account-update.js.map