Skip to content

Commit

Permalink
Merge branch 'main' into feature/conditional-recursive-proving
Browse files Browse the repository at this point in the history
  • Loading branch information
mitschabaude committed Jan 8, 2025
2 parents 8383bb6 + f7d522e commit dec0558
Show file tree
Hide file tree
Showing 24 changed files with 522 additions and 37 deletions.
17 changes: 17 additions & 0 deletions .github/workflows/build-bindings.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ jobs:
nix run o1js#update-bindings --max-jobs 4
#fail if this changes any files
cd src/bindings
echo If this check fails you can download a patch from the patch-upload job
echo "https://github.com/o1-labs/o1js/blob/main/README-dev.md#bindings-check-in-ci"
git diff --exit-code
- name: add build to gc-root if on main
if: github.ref == 'refs/heads/main'
Expand All @@ -39,3 +41,18 @@ jobs:
run: |
nix-store --gc --print-dead
nix-store --optimise
patch-upload:
needs: nix-build
if: ${{ failure() }}
runs-on: [sdk-self-hosted-linux-amd64-build-system]
steps:
- name: generate patch
run: |
cd src/bindings
git add .
git diff HEAD --textconv --text > ../../bindings.patch
- name: Upload patch
uses: actions/upload-artifact@v4
with:
name: bindings.patch
path: bindings.patch
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm

- Compiling stuck in the browser for recursive zkprograms https://github.com/o1-labs/o1js/pull/1906
- Error message in `rangeCheck16` gadget https://github.com/o1-labs/o1js/pull/1920
- Deprecate `testnet` `networkId` in favor of `devnet` https://github.com/o1-labs/o1js/pull/1938

## [2.1.0](https://github.com/o1-labs/o1js/compare/b04520d...e1bac02) - 2024-11-13

Expand Down
14 changes: 14 additions & 0 deletions README-dev.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,20 @@ In addition to building the OCaml and Rust code, the build script also generates

o1js uses these types to ensure that the constants used in the protocol are consistent with the OCaml source files.

### Bindings check in ci

If the bindings check fails in CI it will upload a patch you can use to update the bindings without having to rebuild locally.
This can also be helpful when the bindings don't build identically, as unfortunately often happens.

To use this patch:
- Click details on the `Build o1js bindings / build-bindings-ubunutu` job
- Go to the `patch-upload` job and expand the logs for `Upload patch`
- Download the file linked in the last line of the logs ie.
`Artifact download URL: https://github.com/o1-labs/o1js/actions/runs/12401083741/artifacts/2339952965`
- unzip it
- navigate to `src/bindings`
- run `git apply path/to/bindings.patch`

## Development

### Branching Policy
Expand Down
4 changes: 2 additions & 2 deletions flake.lock

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

2 changes: 1 addition & 1 deletion generate-keys.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env node
import Client from './dist/node/mina-signer/mina-signer.js';

let client = new Client({ network: 'testnet' });
let client = new Client({ network: 'devnet' });

console.log(client.genKeys());
2 changes: 1 addition & 1 deletion src/lib/mina/local-blockchain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ async function LocalBlockchain({
const originalProofsEnabled = proofsEnabled;

return {
getNetworkId: () => 'testnet' as NetworkId,
getNetworkId: () => 'devnet' as NetworkId,
proofsEnabled,
getNetworkConstants() {
return {
Expand Down
2 changes: 1 addition & 1 deletion src/lib/mina/mina-instance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ let activeInstance: Mina = {
fetchActions: noActiveInstance,
getActions: noActiveInstance,
proofsEnabled: true,
getNetworkId: () => 'testnet',
getNetworkId: () => 'devnet',
};

/**
Expand Down
2 changes: 1 addition & 1 deletion src/lib/mina/mina.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ function Network(
}
| string
): Mina {
let minaNetworkId: NetworkId = 'testnet';
let minaNetworkId: NetworkId = 'devnet';
let minaGraphqlEndpoint: string;
let archiveEndpoint: string;
let lightnetAccountManagerEndpoint: string;
Expand Down
3 changes: 2 additions & 1 deletion src/lib/mina/token/forest-iterator.unit-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
import assert from 'assert';
import { Field, Bool } from '../../provable/wrapped.js';
import { PublicKey } from '../../provable/crypto/signature.js';
import { NetworkId } from '../../../mina-signer/index.js';

// RANDOM NUMBER GENERATORS for account updates

Expand Down Expand Up @@ -56,7 +57,7 @@ test.custom({ timeBudget: 1000 })(
(flatUpdatesBigint) => {
// reference: bigint callforest hash from mina-signer
let forestBigint = accountUpdatesToCallForest(flatUpdatesBigint);
let expectedHash = callForestHash(forestBigint, 'testnet');
let expectedHash = callForestHash(forestBigint, 'devnet');

let flatUpdates = flatUpdatesBigint.map(accountUpdateFromBigint);
let forest = AccountUpdateForest.fromFlatArray(flatUpdates);
Expand Down
10 changes: 5 additions & 5 deletions src/lib/provable/crypto/signature.ts
Original file line number Diff line number Diff line change
Expand Up @@ -266,22 +266,22 @@ class Signature extends CircuitValue {
let publicKey = PublicKey.fromPrivateKey(privKey).toGroup();
let d = privKey.s;

// we chose an arbitrary prefix for the signature, and it happened to be 'testnet'
// we chose an arbitrary prefix for the signature
// there's no consequences in practice and the signatures can be used with any network
// if there needs to be a custom nonce, include it in the message itself
let kPrime = Scalar.from(
deriveNonce(
{ fields: msg.map((f) => f.toBigInt()) },
{ x: publicKey.x.toBigInt(), y: publicKey.y.toBigInt() },
d.toBigInt(),
'testnet'
'devnet'
)
);

let { x: r, y: ry } = Group.generator.scale(kPrime);
let k = ry.isOdd().toBoolean() ? kPrime.neg() : kPrime;
let h = hashWithPrefix(
signaturePrefix('testnet'),
signaturePrefix('devnet'),
msg.concat([publicKey.x, publicKey.y, r])
);
let e = Scalar.fromField(h);
Expand All @@ -296,11 +296,11 @@ class Signature extends CircuitValue {
verify(publicKey: PublicKey, msg: Field[]): Bool {
let point = publicKey.toGroup();

// we chose an arbitrary prefix for the signature, and it happened to be 'testnet'
// we chose an arbitrary prefix for the signature
// there's no consequences in practice and the signatures can be used with any network
// if there needs to be a custom nonce, include it in the message itself
let h = hashWithPrefix(
signaturePrefix('testnet'),
signaturePrefix('devnet'),
msg.concat([point.x, point.y, this.r])
);

Expand Down
4 changes: 2 additions & 2 deletions src/mina-signer/mina-signer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ class Client {
*/
signFields(fields: bigint[], privateKey: Json.PrivateKey): Signed<bigint[]> {
let privateKey_ = PrivateKey.fromBase58(privateKey);
let signature = sign({ fields }, privateKey_, 'testnet');
let signature = sign({ fields }, privateKey_, 'devnet');
return {
signature: Signature.toBase58(signature),
publicKey: PublicKey.toBase58(PrivateKey.toPublicKey(privateKey_)),
Expand All @@ -172,7 +172,7 @@ class Client {
Signature.fromBase58(signature),
{ fields: data },
PublicKey.fromBase58(publicKey),
'testnet'
'devnet'
);
}

Expand Down
2 changes: 1 addition & 1 deletion src/mina-signer/src/random-transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ const RandomTransaction = {
zkappCommand,
zkappCommandAndFeePayerKey,
zkappCommandJson,
networkId: Random.oneOf<NetworkId[]>('testnet', 'mainnet', {
networkId: Random.oneOf<NetworkId[]>('testnet', 'mainnet', 'devnet', {
custom: 'other',
}),
accountUpdateWithCallDepth: accountUpdate,
Expand Down
16 changes: 14 additions & 2 deletions src/mina-signer/src/sign-legacy.unit-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,15 @@ import { RandomTransaction } from './random-transaction.js';
import { NetworkId } from './types.js';

let { privateKey, publicKey } = keypair;
let networks: NetworkId[] = ['testnet', 'mainnet'];
let networks: NetworkId[] = ['devnet', 'testnet', 'mainnet'];

// test hard-coded cases against reference signature

for (let network of networks) {
let i = 0;
let reference = signatures[NetworkId.toString(network)];
let reference = NetworkId.toString(network) === 'testnet'
? signatures['devnet']
: signatures[NetworkId.toString(network)];

for (let payment of payments) {
let signature = signPayment(payment, privateKey, network);
Expand Down Expand Up @@ -73,16 +75,26 @@ test(
verifyPayment(payment, sig, publicKey, network);

// valid signatures & verification matrix
let devnet = signPayment(payment, privateKey, 'devnet');
let testnet = signPayment(payment, privateKey, 'testnet');
let mainnet = signPayment(payment, privateKey, 'mainnet');
assert(verify(devnet, 'testnet') === true);
assert(verify(testnet, 'devnet') === true);

assert(verify(testnet, 'testnet') === true);
assert(verify(testnet, 'mainnet') === false);
assert(verify(mainnet, 'testnet') === false);

assert(verify(devnet, 'devnet') === true);
assert(verify(devnet, 'mainnet') === false);
assert(verify(mainnet, 'devnet') === false);
assert(verify(mainnet, 'mainnet') === true);

// fails when signing with wrong private key
let testnetWrong = signPayment(payment, otherKey, 'testnet');
let devnetWrong = signPayment(payment, otherKey, 'devnet');
let mainnetWrong = signPayment(payment, otherKey, 'mainnet');
assert(verify(devnetWrong, 'devnet') === false);
assert(verify(testnetWrong, 'testnet') === false);
assert(verify(mainnetWrong, 'mainnet') === false);
}
Expand Down
16 changes: 16 additions & 0 deletions src/mina-signer/src/sign-zkapp-command.unit-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,12 @@ test(
expect(hash).toEqual(hashSnarky.toBigInt());

// check against different network hash
expect(hash).not.toEqual(
accountUpdateHash(
accountUpdate,
NetworkId.toString(networkId) === 'mainnet' ? 'devnet' : 'mainnet'
)
);
expect(hash).not.toEqual(
accountUpdateHash(
accountUpdate,
Expand Down Expand Up @@ -262,6 +268,9 @@ test(
expect(
verify(sigFieldElements, networkId === 'mainnet' ? 'testnet' : 'mainnet')
).toEqual(false);
expect(
verify(sigFieldElements, networkId === 'mainnet' ? 'devnet' : 'mainnet')
).toEqual(false);

// full end-to-end test: sign a zkapp transaction
let sig = signZkappCommand(zkappCommandJson, feePayerKeyBase58, networkId);
Expand All @@ -278,6 +287,13 @@ test(
networkId === 'mainnet' ? 'testnet' : 'mainnet'
)
).toEqual(false);
expect(
verifyZkappCommandSignature(
sig,
feePayerAddressBase58,
networkId === 'mainnet' ? 'devnet' : 'mainnet'
)
).toEqual(false);
}
);

Expand Down
9 changes: 6 additions & 3 deletions src/mina-signer/src/signature.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export {
};

const networkIdMainnet = 0x01n;
const networkIdTestnet = 0x00n;
const networkIdDevnet = 0x00n;

type Signature = { r: Field; s: Scalar };
type SignatureJson = { field: string; scalar: string };
Expand Down Expand Up @@ -111,7 +111,7 @@ function verifyFieldElement(
* @param privateKey The `privateKey` represents an element of the Pallas scalar field, and should be given as a native bigint.
* It can be converted from the base58 string representation using {@link PrivateKey.fromBase58}.
*
* @param networkId The `networkId` is either "testnet" or "mainnet" and ensures that testnet transactions can
* @param networkId The `networkId` is either "devnet" or "mainnet" and ensures that testnet transactions can
* never be used as valid mainnet transactions.
*
* @see {@link deriveNonce} and {@link hashMessage} for details on how the nonce and hash are computed.
Expand Down Expand Up @@ -331,8 +331,9 @@ function getNetworkIdHashInput(network: NetworkId): [bigint, number] {
switch (s) {
case 'mainnet':
return [networkIdMainnet, 8];
case 'devnet':
case 'testnet':
return [networkIdTestnet, 8];
return [networkIdDevnet, 8];
default:
return networkIdOfString(s);
}
Expand All @@ -356,6 +357,7 @@ const signaturePrefix = (network: NetworkId) => {
switch (s) {
case 'mainnet':
return prefixes.signatureMainnet;
case 'devnet':
case 'testnet':
return prefixes.signatureTestnet;
default:
Expand All @@ -368,6 +370,7 @@ const zkAppBodyPrefix = (network: NetworkId) => {
switch (s) {
case 'mainnet':
return prefixes.zkappBodyMainnet;
case 'devnet':
case 'testnet':
return prefixes.zkappBodyTestnet;
default:
Expand Down
29 changes: 22 additions & 7 deletions src/mina-signer/src/signature.unit-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ function checkConsistentSingle(
// verify
expect(verifyFieldElement(sig, msg, pk, networkId)).toEqual(true);

// verify against different network
// if the signature was generated with networkId=mainnet, the signature should not verify against testnet or devnet
expect(
verifyFieldElement(
sig,
Expand All @@ -42,6 +42,14 @@ function checkConsistentSingle(
networkId === 'mainnet' ? 'testnet' : 'mainnet'
)
).toEqual(false);
expect(
verifyFieldElement(
sig,
msg,
pk,
networkId === 'mainnet' ? 'devnet' : 'mainnet'
)
).toEqual(false);

// consistent with OCaml
let msgMl = FieldConst.fromBigint(msg);
Expand All @@ -56,16 +64,21 @@ function checkConsistentSingle(

// check that various multi-field hash inputs can be verified
function checkCanVerify(msg: HashInput, key: PrivateKey, pk: PublicKey) {
let sigDev = sign(msg, key, 'devnet');
let sigTest = sign(msg, key, 'testnet');
let sigMain = sign(msg, key, 'mainnet');
// verify
let okTestnetTestnet = verify(sigTest, msg, pk, 'testnet');
let okMainnetTestnet = verify(sigMain, msg, pk, 'testnet');
let okTestnetMainnet = verify(sigTest, msg, pk, 'mainnet');
let okTestnetDevnet = verify(sigTest, msg, pk, 'devnet');
let okDevnetTestnet = verify(sigDev, msg, pk, 'testnet');
let okDevnetDevnet = verify(sigDev, msg, pk, 'devnet');
let okMainnetDevnet = verify(sigMain, msg, pk, 'devnet');
let okDevnetMainnet = verify(sigDev, msg, pk, 'mainnet');
let okMainnetMainnet = verify(sigMain, msg, pk, 'mainnet');
expect(okTestnetTestnet).toEqual(true);
expect(okMainnetTestnet).toEqual(false);
expect(okTestnetMainnet).toEqual(false);
expect(okTestnetDevnet).toEqual(true);
expect(okDevnetTestnet).toEqual(true);
expect(okDevnetDevnet).toEqual(true);
expect(okMainnetDevnet).toEqual(false);
expect(okDevnetMainnet).toEqual(false);
expect(okMainnetMainnet).toEqual(true);
}

Expand Down Expand Up @@ -105,13 +118,15 @@ for (let i = 0; i < 10; i++) {
// hard coded single field elements
let hardcoded = [0n, 1n, 2n, p - 1n];
for (let x of hardcoded) {
checkConsistentSingle(x, key, keySnarky, publicKey, 'devnet');
checkConsistentSingle(x, key, keySnarky, publicKey, 'testnet');
checkConsistentSingle(x, key, keySnarky, publicKey, 'mainnet');
checkConsistentSingle(x, key, keySnarky, publicKey, { custom: 'other' });
}
// random single field elements
for (let i = 0; i < 10; i++) {
let x = randomFields[i];
checkConsistentSingle(x, key, keySnarky, publicKey, 'devnet');
checkConsistentSingle(x, key, keySnarky, publicKey, 'testnet');
checkConsistentSingle(x, key, keySnarky, publicKey, 'mainnet');
checkConsistentSingle(x, key, keySnarky, publicKey, { custom: 'other' });
Expand Down
2 changes: 1 addition & 1 deletion src/mina-signer/src/test-vectors/legacySignatures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ let strings = [
* - the 3 strings.
*/
let signatures: { [k: string]: { field: string; scalar: string }[] } = {
testnet: [
devnet: [
{
field:
'3925887987173883783388058255268083382298769764463609405200521482763932632383',
Expand Down
Loading

0 comments on commit dec0558

Please sign in to comment.