Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deprecate 'testnet' network id in favor of 'devnet' #1938

Merged
merged 16 commits into from
Jan 7, 2025
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,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
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
12 changes: 11 additions & 1 deletion src/mina-signer/src/sign-legacy.unit-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ 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

Expand Down Expand Up @@ -73,16 +73,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;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is where constants used during signing are set, changing the networkId to devnet will not change the underlying constants so the signatures themselves will not be changed

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"/"testnet" or "mainnet" and ensures that testnet transactions can
hattyhattington17 marked this conversation as resolved.
Show resolved Hide resolved
* 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':
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add a deprecation warning here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you thinking a log statement or a comment? It's a bit noisy during tests with the log

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking a log... why is it noisy? Because we have tests still using testnet? I suppose we can do a very soft deprecation for now and continue to fully support testnet, but eventually we will want to remove it from our tests.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no logs from library code please!

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
56 changes: 56 additions & 0 deletions src/mina-signer/src/test-vectors/legacySignatures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,62 @@ let strings = [
* - the 3 strings.
*/
let signatures: { [k: string]: { field: string; scalar: string }[] } = {
devnet: [
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: we could save a few lines here since devnet and testnet are the same payload anyway

{
field:
'3925887987173883783388058255268083382298769764463609405200521482763932632383',
scalar:
'445615701481226398197189554290689546503290167815530435382795701939759548136',
},
{
field:
'11838925242791061185900891854974280922359055483441419242429642295065318643984',
scalar:
'5057044820006008308046028014628135487302791372585541488835641418654652928805',
},
{
field:
'13570419670106759824217358880396743605262660069048455950202130815805728575057',
scalar:
'2256128221267944805514947515637443480133552241968312777663034361688965989223',
},
{
field:
'18603328765572408555868399359399411973012220541556204196884026585115374044583',
scalar:
'17076342019359061119005549736934690084415105419939473687106079907606137611470',
},
{
field:
'1786373894608285187089973929748850875336413409295396991315429715474432640801',
scalar:
'10435258496141097615588833319454104720521911644724923418749752896069542389757',
},
{
field:
'11710586766419351067338319607483640291676872446372400739329190129174446858072',
scalar:
'21663533922934564101122062377096487451020504743791218020915919810997397884837',
},
{
field:
'11583775536286847540414661987230057163492736306749717851628536966882998258109',
scalar:
'14787360096063782022566783796923142259879388947509616216546009448340181956495',
},
{
field:
'24809097509137086694730479515383937245108109696879845335879579016397403384488',
scalar:
'23723859937408726087117568974923795978435877847592289069941156359435022279156',
},
{
field:
'23803497755408154859878117448681790665144834176143832235351783889976460433296',
scalar:
'21219917886278462345652813021708727397787183083051040637716760620250038837684',
},
],
testnet: [
{
field:
Expand Down
4 changes: 3 additions & 1 deletion src/mina-signer/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ export type Field = number | bigint | string;
export type PublicKey = string;
export type PrivateKey = string;
export type Signature = SignatureJson;
export type NetworkId = 'mainnet' | 'testnet' | { custom: string };

// testnet is deprecated in favor of devnet
export type NetworkId = 'mainnet' | 'devnet' | 'testnet' | { custom: string };

export const NetworkId = {
toString(network: NetworkId) {
Expand Down
Loading
Loading