Skip to content

Commit

Permalink
Merge pull request #1437 from o1-labs/mainnet-support2
Browse files Browse the repository at this point in the history
Missed part of the Mainnet support.
  • Loading branch information
shimkiv committed Feb 16, 2024
2 parents 6b28285 + ae26719 commit 67f5882
Show file tree
Hide file tree
Showing 12 changed files with 163 additions and 97 deletions.
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
_Security_ in case of vulnerabilities.
-->

## [Unreleased](https://github.com/o1-labs/o1js/compare/834a44002...HEAD)
## [Unreleased](https://github.com/o1-labs/o1js/compare/3b5f7c7...HEAD)

## [0.16.1](https://github.com/o1-labs/o1js/compare/834a44002...3b5f7c7)

### Breaking changes

Expand All @@ -35,6 +37,10 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
- `TokenAccountUpdateIterator`, a primitive to iterate over all token account updates in a transaction https://github.com/o1-labs/o1js/pull/1398
- this is used to implement `TokenContract` under the hood

### Fixed

- Mainnet support. https://github.com/o1-labs/o1js/pull/1437

## [0.16.0](https://github.com/o1-labs/o1js/compare/e5d1e0f...834a44002)

### Breaking changes
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "o1js",
"description": "TypeScript framework for zk-SNARKs and zkApps",
"version": "0.16.0",
"version": "0.16.1",
"license": "Apache-2.0",
"homepage": "https://github.com/o1-labs/o1js/",
"keywords": [
Expand Down
28 changes: 23 additions & 5 deletions src/lib/account-update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1017,10 +1017,20 @@ class AccountUpdate implements Types.AccountUpdate {
// implementations are equivalent, and catch regressions quickly
if (Provable.inCheckedComputation()) {
let input = Types.AccountUpdate.toInput(this);
return hashWithPrefix(prefixes.body, packToFields(input));
return hashWithPrefix(
activeInstance.getNetworkId() === 'mainnet'
? prefixes.zkappBodyMainnet
: prefixes.zkappBodyTestnet,
packToFields(input)
);
} else {
let json = Types.AccountUpdate.toJSON(this);
return Field(Test.hashFromJson.accountUpdate(JSON.stringify(json)));
return Field(
Test.hashFromJson.accountUpdate(
JSON.stringify(json),
activeInstance.getNetworkId()
)
);
}
}

Expand Down Expand Up @@ -1048,7 +1058,8 @@ class AccountUpdate implements Types.AccountUpdate {
forest,
(a) => a.hash(),
Poseidon.hashWithPrefix,
emptyHash
emptyHash,
activeInstance.getNetworkId()
);
return { accountUpdate, calls };
}
Expand Down Expand Up @@ -1386,7 +1397,13 @@ class AccountUpdate implements Types.AccountUpdate {
// call forest stuff

function hashAccountUpdate(update: AccountUpdate) {
return genericHash(AccountUpdate, prefixes.body, update);
return genericHash(
AccountUpdate,
activeInstance.getNetworkId() === 'mainnet'
? prefixes.zkappBodyMainnet
: prefixes.zkappBodyTestnet,
update
);
}

class HashedAccountUpdate extends Hashed.create(
Expand Down Expand Up @@ -1983,7 +2000,8 @@ function addMissingSignatures(
): ZkappCommandSigned {
let additionalPublicKeys = additionalKeys.map((sk) => sk.toPublicKey());
let { commitment, fullCommitment } = transactionCommitments(
TypesBigint.ZkappCommand.fromJSON(ZkappCommand.toJSON(zkappCommand))
TypesBigint.ZkappCommand.fromJSON(ZkappCommand.toJSON(zkappCommand)),
activeInstance.getNetworkId()
);

function addFeePayerSignature(accountUpdate: FeePayerUnsigned): FeePayer {
Expand Down
3 changes: 2 additions & 1 deletion src/lib/mina.ts
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,8 @@ function LocalBlockchain({

let zkappCommandJson = ZkappCommand.toJSON(txn.transaction);
let commitments = transactionCommitments(
TypesBigint.ZkappCommand.fromJSON(zkappCommandJson)
TypesBigint.ZkappCommand.fromJSON(zkappCommandJson),
minaNetworkId
);

if (enforceTransactionLimits) verifyTransactionLimits(txn.transaction);
Expand Down
2 changes: 1 addition & 1 deletion src/lib/mina/token/forest-iterator.unit-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ test.custom({ timeBudget: 1000 })(
(flatUpdatesBigint) => {
// reference: bigint callforest hash from mina-signer
let forestBigint = accountUpdatesToCallForest(flatUpdatesBigint);
let expectedHash = callForestHash(forestBigint);
let expectedHash = callForestHash(forestBigint, 'testnet');

let flatUpdates = flatUpdatesBigint.map(accountUpdateFromBigint);
let forest = AccountUpdateForest.fromFlatArray(flatUpdates);
Expand Down
4 changes: 2 additions & 2 deletions src/mina-signer/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/mina-signer/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "mina-signer",
"description": "Node API for signing transactions on various networks for Mina Protocol",
"version": "3.0.0",
"version": "3.0.1",
"type": "module",
"scripts": {
"build": "tsc -p ../../tsconfig.mina-signer.json",
Expand Down
62 changes: 47 additions & 15 deletions src/mina-signer/src/sign-zkapp-command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,10 @@ function signZkappCommand(
): Json.ZkappCommand {
let zkappCommand = ZkappCommand.fromJSON(zkappCommand_);

let { commitment, fullCommitment } = transactionCommitments(zkappCommand);
let { commitment, fullCommitment } = transactionCommitments(
zkappCommand,
networkId
);
let privateKey = PrivateKey.fromBase58(privateKeyBase58);
let publicKey = zkappCommand.feePayer.body.publicKey;

Expand All @@ -71,7 +74,10 @@ function verifyZkappCommandSignature(
) {
let zkappCommand = ZkappCommand.fromJSON(zkappCommand_);

let { commitment, fullCommitment } = transactionCommitments(zkappCommand);
let { commitment, fullCommitment } = transactionCommitments(
zkappCommand,
networkId
);
let publicKey = PublicKey.fromBase58(publicKeyBase58);

// verify fee payer signature
Expand Down Expand Up @@ -108,14 +114,17 @@ function verifyAccountUpdateSignature(
return verifyFieldElement(signature, usedCommitment, publicKey, networkId);
}

function transactionCommitments(zkappCommand: ZkappCommand) {
function transactionCommitments(
zkappCommand: ZkappCommand,
networkId: NetworkId
) {
if (!isCallDepthValid(zkappCommand)) {
throw Error('zkapp command: invalid call depth');
}
let callForest = accountUpdatesToCallForest(zkappCommand.accountUpdates);
let commitment = callForestHash(callForest);
let commitment = callForestHash(callForest, networkId);
let memoHash = Memo.hash(Memo.fromBase58(zkappCommand.memo));
let feePayerDigest = feePayerHash(zkappCommand.feePayer);
let feePayerDigest = feePayerHash(zkappCommand.feePayer, networkId);
let fullCommitment = hashWithPrefix(prefixes.accountUpdateCons, [
memoHash,
feePayerDigest,
Expand Down Expand Up @@ -150,32 +159,55 @@ function accountUpdatesToCallForest<A extends { body: { callDepth: number } }>(
return forest;
}

function accountUpdateHash(update: AccountUpdate) {
const zkAppBodyPrefix = (network: string) => {
switch (network) {
case 'mainnet':
return prefixes.zkappBodyMainnet;
case 'testnet':
return prefixes.zkappBodyTestnet;

default:
return 'ZkappBody' + network;
}
};

function accountUpdateHash(update: AccountUpdate, networkId: NetworkId) {
assertAuthorizationKindValid(update);
let input = AccountUpdate.toInput(update);
let fields = packToFields(input);
return hashWithPrefix(prefixes.body, fields);
return hashWithPrefix(zkAppBodyPrefix(networkId), fields);
}

function callForestHash(forest: CallForest<AccountUpdate>): bigint {
return callForestHashGeneric(forest, accountUpdateHash, hashWithPrefix, 0n);
function callForestHash(
forest: CallForest<AccountUpdate>,
networkId: NetworkId
): bigint {
return callForestHashGeneric(
forest,
accountUpdateHash,
hashWithPrefix,
0n,
networkId
);
}

function callForestHashGeneric<A, F>(
forest: CallForest<A>,
hash: (a: A) => F,
hash: (a: A, networkId: NetworkId) => F,
hashWithPrefix: (prefix: string, input: F[]) => F,
emptyHash: F
emptyHash: F,
networkId: NetworkId
): F {
let stackHash = emptyHash;
for (let callTree of [...forest].reverse()) {
let calls = callForestHashGeneric(
callTree.children,
hash,
hashWithPrefix,
emptyHash
emptyHash,
networkId
);
let treeHash = hash(callTree.accountUpdate);
let treeHash = hash(callTree.accountUpdate, networkId);
let nodeHash = hashWithPrefix(prefixes.accountUpdateNode, [
treeHash,
calls,
Expand All @@ -193,9 +225,9 @@ type FeePayer = ZkappCommand['feePayer'];
function createFeePayer(feePayer: FeePayer['body']): FeePayer {
return { authorization: '', body: feePayer };
}
function feePayerHash(feePayer: FeePayer) {
function feePayerHash(feePayer: FeePayer, networkId: NetworkId) {
let accountUpdate = accountUpdateFromFeePayer(feePayer);
return accountUpdateHash(accountUpdate);
return accountUpdateHash(accountUpdate, networkId);
}

function accountUpdateFromFeePayer({
Expand Down
Loading

0 comments on commit 67f5882

Please sign in to comment.