diff --git a/CHANGELOG.md b/CHANGELOG.md index 87ea98b0b5..780e3df938 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,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 diff --git a/flake.lock b/flake.lock index 6fe1645e40..142eb21dc0 100644 --- a/flake.lock +++ b/flake.lock @@ -265,8 +265,8 @@ "utils": "utils" }, "locked": { - "lastModified": 1734626051, - "narHash": "sha256-4LLy5VMM5TK4LpQXEBiA8ziwYyqGx2ZAuunXGCDpraQ=", + "lastModified": 1736283575, + "narHash": "sha256-aI4sxplaKydvPfvk98Qws35HHi2n9BMPKQqmVfP7zZA=", "path": "src/mina", "type": "path" }, diff --git a/generate-keys.js b/generate-keys.js index b702948882..b638d116a7 100755 --- a/generate-keys.js +++ b/generate-keys.js @@ -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()); diff --git a/src/bindings b/src/bindings index 043f47adf7..14ce3b8f5e 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit 043f47adf7cd9a48eda4736a2a37df30e433de55 +Subproject commit 14ce3b8f5e23dbcd9afe3d53304ee84cfc92076b diff --git a/src/lib/mina/local-blockchain.ts b/src/lib/mina/local-blockchain.ts index 2a80874c32..4d049cac09 100644 --- a/src/lib/mina/local-blockchain.ts +++ b/src/lib/mina/local-blockchain.ts @@ -106,7 +106,7 @@ async function LocalBlockchain({ const originalProofsEnabled = proofsEnabled; return { - getNetworkId: () => 'testnet' as NetworkId, + getNetworkId: () => 'devnet' as NetworkId, proofsEnabled, getNetworkConstants() { return { diff --git a/src/lib/mina/mina-instance.ts b/src/lib/mina/mina-instance.ts index 77bc328ba9..640953936b 100644 --- a/src/lib/mina/mina-instance.ts +++ b/src/lib/mina/mina-instance.ts @@ -117,7 +117,7 @@ let activeInstance: Mina = { fetchActions: noActiveInstance, getActions: noActiveInstance, proofsEnabled: true, - getNetworkId: () => 'testnet', + getNetworkId: () => 'devnet', }; /** diff --git a/src/lib/mina/mina.ts b/src/lib/mina/mina.ts index 67edd659e5..c7ea264848 100644 --- a/src/lib/mina/mina.ts +++ b/src/lib/mina/mina.ts @@ -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; diff --git a/src/lib/mina/token/forest-iterator.unit-test.ts b/src/lib/mina/token/forest-iterator.unit-test.ts index 97f0409ca3..18c6966743 100644 --- a/src/lib/mina/token/forest-iterator.unit-test.ts +++ b/src/lib/mina/token/forest-iterator.unit-test.ts @@ -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 @@ -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); diff --git a/src/lib/provable/crypto/signature.ts b/src/lib/provable/crypto/signature.ts index d1f0cced8a..d5ed209d81 100644 --- a/src/lib/provable/crypto/signature.ts +++ b/src/lib/provable/crypto/signature.ts @@ -266,7 +266,7 @@ 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( @@ -274,14 +274,14 @@ class Signature extends CircuitValue { { 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); @@ -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]) ); diff --git a/src/mina-signer/mina-signer.ts b/src/mina-signer/mina-signer.ts index d6b9793a43..29d53757e0 100644 --- a/src/mina-signer/mina-signer.ts +++ b/src/mina-signer/mina-signer.ts @@ -152,7 +152,7 @@ class Client { */ signFields(fields: bigint[], privateKey: Json.PrivateKey): Signed { 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_)), @@ -172,7 +172,7 @@ class Client { Signature.fromBase58(signature), { fields: data }, PublicKey.fromBase58(publicKey), - 'testnet' + 'devnet' ); } diff --git a/src/mina-signer/src/random-transaction.ts b/src/mina-signer/src/random-transaction.ts index ac475348e5..87d286fd28 100644 --- a/src/mina-signer/src/random-transaction.ts +++ b/src/mina-signer/src/random-transaction.ts @@ -141,7 +141,7 @@ const RandomTransaction = { zkappCommand, zkappCommandAndFeePayerKey, zkappCommandJson, - networkId: Random.oneOf('testnet', 'mainnet', { + networkId: Random.oneOf('testnet', 'mainnet', 'devnet', { custom: 'other', }), accountUpdateWithCallDepth: accountUpdate, diff --git a/src/mina-signer/src/sign-legacy.unit-test.ts b/src/mina-signer/src/sign-legacy.unit-test.ts index 3654943682..30cf195743 100644 --- a/src/mina-signer/src/sign-legacy.unit-test.ts +++ b/src/mina-signer/src/sign-legacy.unit-test.ts @@ -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); @@ -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); } diff --git a/src/mina-signer/src/sign-zkapp-command.unit-test.ts b/src/mina-signer/src/sign-zkapp-command.unit-test.ts index e0f1ccacdc..d833a6b5da 100644 --- a/src/mina-signer/src/sign-zkapp-command.unit-test.ts +++ b/src/mina-signer/src/sign-zkapp-command.unit-test.ts @@ -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, @@ -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); @@ -278,6 +287,13 @@ test( networkId === 'mainnet' ? 'testnet' : 'mainnet' ) ).toEqual(false); + expect( + verifyZkappCommandSignature( + sig, + feePayerAddressBase58, + networkId === 'mainnet' ? 'devnet' : 'mainnet' + ) + ).toEqual(false); } ); diff --git a/src/mina-signer/src/signature.ts b/src/mina-signer/src/signature.ts index bd3d384978..784927e4ca 100644 --- a/src/mina-signer/src/signature.ts +++ b/src/mina-signer/src/signature.ts @@ -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 }; @@ -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. @@ -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); } @@ -356,6 +357,7 @@ const signaturePrefix = (network: NetworkId) => { switch (s) { case 'mainnet': return prefixes.signatureMainnet; + case 'devnet': case 'testnet': return prefixes.signatureTestnet; default: @@ -368,6 +370,7 @@ const zkAppBodyPrefix = (network: NetworkId) => { switch (s) { case 'mainnet': return prefixes.zkappBodyMainnet; + case 'devnet': case 'testnet': return prefixes.zkappBodyTestnet; default: diff --git a/src/mina-signer/src/signature.unit-test.ts b/src/mina-signer/src/signature.unit-test.ts index 0565a1b9af..3bd81efcd3 100644 --- a/src/mina-signer/src/signature.unit-test.ts +++ b/src/mina-signer/src/signature.unit-test.ts @@ -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, @@ -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); @@ -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); } @@ -105,6 +118,7 @@ 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' }); @@ -112,6 +126,7 @@ for (let i = 0; i < 10; i++) { // 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' }); diff --git a/src/mina-signer/src/test-vectors/legacySignatures.ts b/src/mina-signer/src/test-vectors/legacySignatures.ts index 7090587475..7cb559ce6d 100644 --- a/src/mina-signer/src/test-vectors/legacySignatures.ts +++ b/src/mina-signer/src/test-vectors/legacySignatures.ts @@ -91,7 +91,7 @@ let strings = [ * - the 3 strings. */ let signatures: { [k: string]: { field: string; scalar: string }[] } = { - testnet: [ + devnet: [ { field: '3925887987173883783388058255268083382298769764463609405200521482763932632383', diff --git a/src/mina-signer/src/types.ts b/src/mina-signer/src/types.ts index 6eb7e75c80..f3692cf03a 100644 --- a/src/mina-signer/src/types.ts +++ b/src/mina-signer/src/types.ts @@ -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) { diff --git a/src/mina-signer/tests/client.test.ts b/src/mina-signer/tests/client.test.ts index 4ca384a2d2..e620429ee2 100644 --- a/src/mina-signer/tests/client.test.ts +++ b/src/mina-signer/tests/client.test.ts @@ -13,7 +13,12 @@ describe('Client Class Initialization', () => { expect(client).toBeDefined(); }); - it('should throw an error if a value that is not `mainnet` or `testnet` is specified', () => { + it('should accept `devnet` as a valid network parameter', () => { + client = new Client({ network: 'devnet' }); + expect(client).toBeDefined(); + }); + + it('should throw an error if a value that is not `mainnet`, `devnet`, or `testnet` is specified', () => { try { //@ts-ignore client = new Client({ network: 'new-network' }); diff --git a/src/mina-signer/tests/message.test.ts b/src/mina-signer/tests/message.test.ts index bd9586fb19..0b5b6f6fd2 100644 --- a/src/mina-signer/tests/message.test.ts +++ b/src/mina-signer/tests/message.test.ts @@ -37,6 +37,14 @@ describe('Message', () => { expect(client.verifyTransaction(message)).toEqual(true); }); + it('does not verify a signed message from `devnet`', () => { + const message = client.signMessage('hello', privateKey); + const devnetClient = new Client({ network: 'devnet' }); + const invalidMessage = devnetClient.verifyMessage(message); + expect(invalidMessage).toBeFalsy(); + expect(devnetClient.verifyTransaction(message)).toEqual(false); + }); + it('does not verify a signed message from `testnet`', () => { const message = client.signMessage('hello', privateKey); const testnetClient = new Client({ network: 'testnet' }); @@ -46,12 +54,12 @@ describe('Message', () => { }); }); - describe('Testnet network', () => { + describe('Devnet network', () => { let client: Client; let privateKey: PrivateKey; beforeAll(async () => { - client = new Client({ network: 'testnet' }); + client = new Client({ network: 'devnet' }); ({ privateKey } = client.genKeys()); }); @@ -89,4 +97,63 @@ describe('Message', () => { expect(mainnetClient.verifyTransaction(message)).toEqual(false); }); }); + + describe('Testnet network', () => { + let testnetClient: Client; + let devnetClient: Client; + let privateKey: PrivateKey; + + beforeAll(async () => { + testnetClient = new Client({ network: 'testnet' }); + devnetClient = new Client({ network: 'devnet' }); + ({ privateKey } = devnetClient.genKeys()); + }); + + it('generates the same signatures as devnet', () => { + const testnetMessage = testnetClient.signMessage('hello', privateKey); + const devnetMessage = devnetClient.signMessage('hello', privateKey); + expect(testnetMessage).toEqual(devnetMessage); + }); + + + it('generates the same signatures as devnet using signTransaction', () => { + const testnetMessage = testnetClient.signTransaction('hello', privateKey); + const devnetMessage = devnetClient.signTransaction('hello', privateKey); + expect(testnetMessage).toEqual(devnetMessage); + }); + + it('verifies a signed message from devnet and vice versa', () => { + const testnetMessage = testnetClient.signMessage('hello', privateKey); + const devnetMessage = devnetClient.signMessage('hello', privateKey); + + const verifiedDevnetMessage = testnetClient.verifyMessage(devnetMessage); + const verifiedTestnetMessage = devnetClient.verifyMessage(testnetMessage); + expect(verifiedDevnetMessage).toBeTruthy(); + expect(verifiedTestnetMessage).toBeTruthy(); + + expect(testnetClient.verifyTransaction(devnetMessage)).toEqual(true); + expect(devnetClient.verifyTransaction(testnetMessage)).toEqual(true); + }); + + it('verifies a signed message generated by signTransaction from devnet and vice versa', () => { + const testnetMessage = testnetClient.signTransaction('hello', privateKey); + const devnetMessage = devnetClient.signTransaction('hello', privateKey); + + const verifiedDevnetMessage = testnetClient.verifyMessage(devnetMessage); + const verifiedTestnetMessage = devnetClient.verifyMessage(testnetMessage); + expect(verifiedDevnetMessage).toBeTruthy(); + expect(verifiedTestnetMessage).toBeTruthy(); + + expect(testnetClient.verifyTransaction(devnetMessage)).toEqual(true); + expect(devnetClient.verifyTransaction(testnetMessage)).toEqual(true); + }); + + it('does not verify a signed message from `mainnet`', () => { + const message = testnetClient.signMessage('hello', privateKey); + const mainnetClient = new Client({ network: 'mainnet' }); + const invalidMessage = mainnetClient.verifyMessage(message); + expect(invalidMessage).toBeFalsy(); + expect(mainnetClient.verifyTransaction(message)).toEqual(false); + }); + }); }); diff --git a/src/mina-signer/tests/payment.test.ts b/src/mina-signer/tests/payment.test.ts index de84939d67..34fbf24abe 100644 --- a/src/mina-signer/tests/payment.test.ts +++ b/src/mina-signer/tests/payment.test.ts @@ -103,6 +103,23 @@ describe('Payment', () => { expect(hashedPayment).toBeDefined(); }); + it('does not verify a signed payment from `devnet`', () => { + const payment = client.signPayment( + { + to: keypair.publicKey, + from: keypair.publicKey, + amount: '1', + fee: '1', + nonce: '0', + }, + keypair.privateKey + ); + const devnetClient = new Client({ network: 'devnet' }); + const invalidPayment = devnetClient.verifyPayment(payment); + expect(invalidPayment).toBeFalsy(); + expect(devnetClient.verifyTransaction(payment)).toEqual(false); + }); + it('does not verify a signed payment from `testnet`', () => { const payment = client.signPayment( { @@ -121,12 +138,12 @@ describe('Payment', () => { }); }); - describe('Testnet network', () => { + describe('Devnet network', () => { let client: Client; let keypair: Keypair; beforeAll(async () => { - client = new Client({ network: 'testnet' }); + client = new Client({ network: 'devnet' }); keypair = client.genKeys(); }); @@ -239,4 +256,191 @@ describe('Payment', () => { expect(mainnetClient.verifyTransaction(payment)).toEqual(false); }); }); + describe('Testnet network', () => { + let testnetClient: Client; + let devnetClient: Client; + let keypair: Keypair; + + beforeAll(async () => { + testnetClient = new Client({ network: 'testnet' }); + devnetClient = new Client({ network: 'devnet' }); + keypair = testnetClient.genKeys(); + }); + + it('generates the same signed payment as devnet', () => { + const testnetPayment = testnetClient.signPayment( + { + to: keypair.publicKey, + from: keypair.publicKey, + amount: '1', + fee: '1', + nonce: '0', + }, + keypair.privateKey + ); + const devnetPayment = devnetClient.signPayment( + { + to: keypair.publicKey, + from: keypair.publicKey, + amount: '1', + fee: '1', + nonce: '0', + }, + keypair.privateKey + ); + expect(testnetPayment).toEqual(devnetPayment); + }); + + it('generates the same signed transaction by using signTransaction as a devnet client', () => { + const testnetTransaction = testnetClient.signTransaction( + { + to: keypair.publicKey, + from: keypair.publicKey, + amount: '1', + fee: '1', + nonce: '0', + }, + keypair.privateKey + ); + const devnetTransaction = devnetClient.signTransaction( + { + to: keypair.publicKey, + from: keypair.publicKey, + amount: '1', + fee: '1', + nonce: '0', + }, + keypair.privateKey + ); + expect(testnetTransaction).toEqual(devnetTransaction); + }); + + it('devnet client verifies a signed testnet payment and vice versa', () => { + const testnetPayment = testnetClient.signPayment( + { + to: keypair.publicKey, + from: keypair.publicKey, + amount: '1', + fee: '1', + nonce: '0', + }, + keypair.privateKey + ); + const devnetPayment = devnetClient.signPayment( + { + to: keypair.publicKey, + from: keypair.publicKey, + amount: '1', + fee: '1', + nonce: '0', + }, + keypair.privateKey + ); + const verifiedDevnetPayment = testnetClient.verifyPayment(devnetPayment); + expect(verifiedDevnetPayment).toBeTruthy(); + expect(testnetClient.verifyTransaction(devnetPayment)).toEqual(true); + + const verifiedTestnetPayment = devnetClient.verifyPayment(testnetPayment); + expect(verifiedTestnetPayment).toBeTruthy(); + expect(devnetClient.verifyTransaction(testnetPayment)).toEqual(true); + }); + it('devnet client verifies a signed testnet payment generated with signTransaction and vice versa', () => { + const testnetPayment = testnetClient.signTransaction( + { + to: keypair.publicKey, + from: keypair.publicKey, + amount: '1', + fee: '1', + nonce: '0', + }, + keypair.privateKey + ); + const devnetPayment = devnetClient.signTransaction( + { + to: keypair.publicKey, + from: keypair.publicKey, + amount: '1', + fee: '1', + nonce: '0', + }, + keypair.privateKey + ); + const verifiedDevnetPayment = testnetClient.verifyPayment(devnetPayment); + expect(verifiedDevnetPayment).toBeTruthy(); + expect(testnetClient.verifyTransaction(devnetPayment)).toEqual(true); + + const verifiedTestnetPayment = devnetClient.verifyPayment(testnetPayment); + expect(verifiedTestnetPayment).toBeTruthy(); + expect(devnetClient.verifyTransaction(testnetPayment)).toEqual(true); + }); + + it('generates same signed payment hash as devnet', () => { + const testnetPayment = testnetClient.signPayment( + { + to: keypair.publicKey, + from: keypair.publicKey, + amount: '1', + fee: '1', + nonce: '0', + }, + keypair.privateKey + ); + const hashedTestnetPayment = testnetClient.hashPayment(testnetPayment); + const devnetPayment = devnetClient.signPayment( + { + to: keypair.publicKey, + from: keypair.publicKey, + amount: '1', + fee: '1', + nonce: '0', + }, + keypair.privateKey + ); + const hashedDevnetPayment = devnetClient.hashPayment(devnetPayment); + expect(hashedTestnetPayment).toEqual(hashedDevnetPayment); + }); + + it('generates same signed payment hash as devnet for payment generated with signTransaction', () => { + const testnetPayment = testnetClient.signTransaction( + { + to: keypair.publicKey, + from: keypair.publicKey, + amount: '1', + fee: '1', + nonce: '0', + }, + keypair.privateKey + ); + const hashedTestnetPayment = testnetClient.hashPayment(testnetPayment); + const devnetPayment = devnetClient.signTransaction( + { + to: keypair.publicKey, + from: keypair.publicKey, + amount: '1', + fee: '1', + nonce: '0', + }, + keypair.privateKey + ); + const hashedDevnetPayment = devnetClient.hashPayment(devnetPayment); + expect(hashedTestnetPayment).toEqual(hashedDevnetPayment); + }); + + it('does not verify a signed payment from `mainnet`', () => { + const payment = testnetClient.signPayment( + { + to: keypair.publicKey, + from: keypair.publicKey, + amount: '1', + fee: '1', + nonce: '0', + }, + keypair.privateKey + ); + const mainnetClient = new Client({ network: 'mainnet' }); + const invalidPayment = mainnetClient.verifyPayment(payment); + expect(invalidPayment).toBeFalsy(); + expect(mainnetClient.verifyTransaction(payment)).toEqual(false); + }); + }); }); diff --git a/src/mina-signer/tests/stake-delegation.test.ts b/src/mina-signer/tests/stake-delegation.test.ts index 16cdf0d8f6..58d273040c 100644 --- a/src/mina-signer/tests/stake-delegation.test.ts +++ b/src/mina-signer/tests/stake-delegation.test.ts @@ -114,7 +114,7 @@ describe('Stake Delegation', () => { }); }); - describe('Testnet network', () => { + describe('Devnet network', () => { let client: Client; let keypair: Keypair; @@ -211,4 +211,132 @@ describe('Stake Delegation', () => { expect(mainnetClient.verifyTransaction(delegation)).toEqual(false); }); }); + describe('Testnet network', () => { + let testnetClient: Client; + let devnetClient: Client; + let keypair: Keypair; + + beforeAll(async () => { + testnetClient = new Client({ network: 'testnet' }); + devnetClient = new Client({ network: 'devnet' }); + keypair = testnetClient.genKeys(); + }); + + it('generates the same signed stake delegation as devnet', () => { + const testnetDelegation = testnetClient.signStakeDelegation( + { + to: keypair.publicKey, + from: keypair.publicKey, + fee: '1', + nonce: '0', + }, + keypair.privateKey + ); + const devnetDelegation = testnetClient.signStakeDelegation( + { + to: keypair.publicKey, + from: keypair.publicKey, + fee: '1', + nonce: '0', + }, + keypair.privateKey + ); + expect(testnetDelegation).toEqual(devnetDelegation); + }); + it('generates the same signed stake delegation as devnet using signTransaction', () => { + const testnetDelegation = testnetClient.signTransaction( + { + to: keypair.publicKey, + from: keypair.publicKey, + fee: '1', + nonce: '0', + }, + keypair.privateKey + ); + const devnetDelegation = testnetClient.signTransaction( + { + to: keypair.publicKey, + from: keypair.publicKey, + fee: '1', + nonce: '0', + }, + keypair.privateKey + ); + expect(testnetDelegation).toEqual(devnetDelegation); + }); + + + it('verifies a signed delegation from devnet and vice versa', () => { + const testnetDelegation = testnetClient.signStakeDelegation( + { + to: keypair.publicKey, + from: keypair.publicKey, + fee: '1', + nonce: '0', + }, + keypair.privateKey + ); + const devnetDelegation = testnetClient.signStakeDelegation( + { + to: keypair.publicKey, + from: keypair.publicKey, + fee: '1', + nonce: '0', + }, + keypair.privateKey + ); + const verifiedDevnetDelegation = testnetClient.verifyStakeDelegation(devnetDelegation); + expect(verifiedDevnetDelegation).toBeTruthy(); + expect(testnetClient.verifyTransaction(devnetDelegation)).toEqual(true); + + const verifiedTestnetDelegation = devnetClient.verifyStakeDelegation(testnetDelegation); + expect(verifiedTestnetDelegation).toBeTruthy(); + expect(devnetClient.verifyTransaction(testnetDelegation)).toEqual(true); + }); + + + it('verifies a signed delegation generated by signTransaction from devnet and vice versa', () => { + const testnetDelegation = testnetClient.signTransaction( + { + to: keypair.publicKey, + from: keypair.publicKey, + fee: '1', + nonce: '0', + }, + keypair.privateKey + ); + const devnetDelegation = testnetClient.signTransaction( + { + to: keypair.publicKey, + from: keypair.publicKey, + fee: '1', + nonce: '0', + }, + keypair.privateKey + ); + const verifiedDevnetDelegation = testnetClient.verifyStakeDelegation(devnetDelegation); + expect(verifiedDevnetDelegation).toBeTruthy(); + expect(testnetClient.verifyTransaction(devnetDelegation)).toEqual(true); + + const verifiedTestnetDelegation = devnetClient.verifyStakeDelegation(testnetDelegation); + expect(verifiedTestnetDelegation).toBeTruthy(); + expect(devnetClient.verifyTransaction(testnetDelegation)).toEqual(true); + }); + + it('does not verify a signed message from `mainnet`', () => { + const delegation = testnetClient.signStakeDelegation( + { + to: keypair.publicKey, + from: keypair.publicKey, + fee: '1', + nonce: '0', + }, + keypair.privateKey + ); + const mainnetClient = new Client({ network: 'mainnet' }); + const invalidMessage = mainnetClient.verifyStakeDelegation(delegation); + expect(invalidMessage).toBeFalsy(); + expect(mainnetClient.verifyTransaction(delegation)).toEqual(false); + }); + }); }); diff --git a/src/mina-signer/tests/zkapp.unit-test.ts b/src/mina-signer/tests/zkapp.unit-test.ts index 1b3ffb66c3..6580df4a8c 100644 --- a/src/mina-signer/tests/zkapp.unit-test.ts +++ b/src/mina-signer/tests/zkapp.unit-test.ts @@ -8,7 +8,7 @@ import { PrivateKey } from '../../lib/provable/crypto/signature.js'; import { Signature } from '../src/signature.js'; import { mocks } from '../../bindings/crypto/constants.js'; -const client = new Client({ network: 'testnet' }); +const client = new Client({ network: 'devnet' }); let { publicKey, privateKey } = client.genKeys(); let dummy = ZkappCommand.toJSON(ZkappCommand.empty());