o1js
Version:
TypeScript framework for zk-SNARKs and zkApps
99 lines • 3.89 kB
JavaScript
import { Random } from '../../lib/testing/property.js';
import { PrivateKey } from './curve-bigint.js';
import { Signature } from './signature.js';
export { RandomTransaction };
let { record } = Random;
// legacy transactions
const common = record({
fee: Random.map(Random.uint32, (x) => (x * BigInt(1e9)).toString()),
feePayer: Random.json.publicKey,
nonce: Random.json.uint32,
validUntil: Random.json.uint32,
memo: Random.json.memoString,
});
const payment = record({
common,
body: record({
receiver: Random.json.publicKey,
amount: Random.json.uint64,
}),
});
const signedPayment = record({
data: payment,
signature: Random.json.signatureJson,
});
const delegation = record({
common,
body: record({
newDelegate: Random.json.publicKey,
}),
});
const signedDelegation = record({
data: delegation,
signature: Random.json.signatureJson,
});
// zkapp transactions
// generator for { feePayer, accountUpdates, memo } with 2 modifications to the naive version
// modification #1: call depth
// in every list of account updates, call depth starts from 0,
// can increase by at most one, decrease by any amount up to 0.
// we increment with 1/3 chance
let incrementDepth = Random.map(Random.dice(3), (x) => x === 0);
let callDepth = Random.step(incrementDepth, Random.dice.ofSize, (depth, increment, diceOfSize) => {
return increment ? depth + 1 : diceOfSize(depth + 1);
}, 0);
// account update with a call depth that takes valid steps
let accountUpdate = Random.map(Random.accountUpdate, callDepth, (accountUpdate, callDepth) => {
accountUpdate.body.callDepth = callDepth;
return accountUpdate;
});
// modification #2: use the fee payer's public key for account updates, with 1/3 chance
// this is an important test case and won't happen by chance
let useFeePayerKey = Random.map(Random.dice(3), (x) => x === 0);
let accountUpdateFrom = Random.dependent(accountUpdate, useFeePayerKey, (feePayer, [accountUpdate, useFeePayerKey]) => {
if (useFeePayerKey)
accountUpdate.body.publicKey = feePayer;
return accountUpdate;
});
let feePayerFrom = Random.dependent(Random.feePayer, (publicKey, [feePayer]) => {
feePayer.body.publicKey = publicKey;
feePayer.authorization = Signature.toBase58(Signature.dummy());
return feePayer;
});
let size = Random.nat(20);
// reset: true makes call depth start from 0 again at the start of each sampled array
let accountUpdatesFrom = Random.array(accountUpdateFrom, size, { reset: true });
let zkappCommandFrom = Random.dependent(feePayerFrom, accountUpdatesFrom, Random.memo, (publicKey, [feePayerFrom, accountUpdatesFrom, memo]) => {
let feePayer = feePayerFrom(publicKey);
let accountUpdates = accountUpdatesFrom.map((from) => from(publicKey));
return { feePayer, accountUpdates, memo };
});
let zkappCommand = zkappCommandFrom(Random.publicKey);
let zkappCommandAndFeePayerKey = Random.map(Random.privateKey, zkappCommandFrom, (feePayerKey, zkappCommandFrom) => ({
feePayerKey,
zkappCommand: zkappCommandFrom(PrivateKey.toPublicKey(feePayerKey)),
}));
// json zkapp command, supporting invalid samples
let accountUpdateJson = Random.map.withInvalid(Random.json.accountUpdate, callDepth, (accountUpdate, callDepth) => {
accountUpdate.body.callDepth = callDepth;
return accountUpdate;
});
let zkappCommandJson = Random.record({
feePayer: Random.json.feePayer,
accountUpdates: Random.array(accountUpdateJson, size),
memo: Random.memo,
});
const RandomTransaction = {
payment,
delegation,
signedPayment,
signedDelegation,
zkappCommand,
zkappCommandAndFeePayerKey,
zkappCommandJson,
networkId: Random.oneOf('testnet', 'mainnet', 'devnet', {
custom: 'other',
}),
accountUpdateWithCallDepth: accountUpdate,
};
//# sourceMappingURL=random-transaction.js.map