From 302e3bbb2d7a7d54f362026edb314f3d3596b6d6 Mon Sep 17 00:00:00 2001 From: Facundo Date: Wed, 17 Apr 2024 18:25:07 +0100 Subject: [PATCH 001/102] feat: make public l1tol2 message consumption take leafIndex (#5805) --- .../aztec-nr/aztec/src/context/avm_context.nr | 20 ++++++++++-- .../aztec-nr/aztec/src/context/interface.nr | 2 +- .../aztec/src/context/public_context.nr | 3 +- .../contracts/gas_token_contract/src/main.nr | 4 +-- .../contracts/test_contract/src/main.nr | 19 ++++++++--- .../token_bridge_contract/src/main.nr | 9 ++++-- .../src/e2e_cross_chain_messaging.test.ts | 7 +++- yarn-project/end-to-end/src/e2e_fees.test.ts | 1 + .../e2e_public_cross_chain_messaging.test.ts | 32 +++++++++++++++---- .../e2e_public_to_private_messaging.test.ts | 25 +++++++++++---- .../src/flakey_e2e_account_init_fees.test.ts | 1 + .../src/shared/cross_chain_test_harness.ts | 4 +-- .../src/shared/gas_portal_test_harness.ts | 21 +++++++++--- .../end-to-end/src/shared/uniswap_l1_l2.ts | 31 ++++++++++++++++-- .../simulator/src/public/index.test.ts | 6 ++-- 15 files changed, 148 insertions(+), 37 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/context/avm_context.nr b/noir-projects/aztec-nr/aztec/src/context/avm_context.nr index 4e80ea93f46..c4a6350af39 100644 --- a/noir-projects/aztec-nr/aztec/src/context/avm_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/avm_context.nr @@ -1,3 +1,4 @@ +use crate::hash::{compute_secret_hash, compute_message_hash, compute_message_nullifier}; use dep::protocol_types::{ address::{AztecAddress, EthAddress}, constants::{L1_TO_L2_MESSAGE_LENGTH, NESTED_CALL_L2_GAS_BUFFER}, header::Header @@ -128,8 +129,23 @@ impl PublicContextInterface for AvmContext { assert(false, "'push_unencrypted_log' not required for avm - use emit_unencrypted_log!"); } - fn consume_l1_to_l2_message(&mut self, content: Field, secret: Field, sender: EthAddress) { - assert(false, "'consume_l1_to_l2_message' not implemented!"); + fn consume_l1_to_l2_message(&mut self, content: Field, secret: Field, sender: EthAddress, leaf_index: Field) { + let secret_hash = compute_secret_hash(secret); + let message_hash = compute_message_hash( + sender, + self.chain_id(), + /*recipient=*/self.this_address(), + self.version(), + content, + secret_hash + ); + let nullifier = compute_message_nullifier(message_hash, secret, leaf_index); + + assert(!self.nullifier_exists(nullifier, self.this_address()), "L1-to-L2 message is already nullified"); + assert(self.l1_to_l2_msg_exists(message_hash, leaf_index), "Tried to consume nonexistent L1-to-L2 message"); + + // Push nullifier (and the "commitment" corresponding to this can be "empty") + self.push_new_nullifier(nullifier, 0); } fn message_portal(&mut self, recipient: EthAddress, content: Field) { diff --git a/noir-projects/aztec-nr/aztec/src/context/interface.nr b/noir-projects/aztec-nr/aztec/src/context/interface.nr index 724ec73c09d..a076158d71d 100644 --- a/noir-projects/aztec-nr/aztec/src/context/interface.nr +++ b/noir-projects/aztec-nr/aztec/src/context/interface.nr @@ -33,7 +33,7 @@ trait PublicContextInterface { fn fee_per_l1_gas(self) -> Field; fn fee_per_l2_gas(self) -> Field; fn message_portal(&mut self, recipient: EthAddress, content: Field); - fn consume_l1_to_l2_message(&mut self, content: Field, secret: Field, sender: EthAddress); + fn consume_l1_to_l2_message(&mut self, content: Field, secret: Field, sender: EthAddress, leaf_index: Field); fn emit_unencrypted_log(&mut self, log: T); // TODO(1165) Merge push_unencrypted_log into emit_unencrypted_log, since oracle call // in PublicContext will no longer be needed for extracting log hash diff --git a/noir-projects/aztec-nr/aztec/src/context/public_context.nr b/noir-projects/aztec-nr/aztec/src/context/public_context.nr index ad3aa93d879..ba70631a79f 100644 --- a/noir-projects/aztec-nr/aztec/src/context/public_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/public_context.nr @@ -263,7 +263,8 @@ impl PublicContextInterface for PublicContext { // We can consume message with a secret in public context because the message cannot be modified and therefore // there is no front-running risk (e.g. somebody could front run you to claim your tokens to your address). - fn consume_l1_to_l2_message(&mut self, content: Field, secret: Field, sender: EthAddress) { + // Leaf index is not used in public context, but it is used in the AVMContext which will replace it. + fn consume_l1_to_l2_message(&mut self, content: Field, secret: Field, sender: EthAddress, _leaf_index: Field) { let this = (*self).this_address(); let nullifier = process_l1_to_l2_message( self.historical_header.state.l1_to_l2_message_tree.root, diff --git a/noir-projects/noir-contracts/contracts/gas_token_contract/src/main.nr b/noir-projects/noir-contracts/contracts/gas_token_contract/src/main.nr index ba8ecf6c608..ec1adf32116 100644 --- a/noir-projects/noir-contracts/contracts/gas_token_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/gas_token_contract/src/main.nr @@ -12,11 +12,11 @@ contract GasToken { } #[aztec(public)] - fn claim_public(to: AztecAddress, amount: Field, secret: Field) { + fn claim_public(to: AztecAddress, amount: Field, secret: Field, leaf_index: Field) { let content_hash = get_bridge_gas_msg_hash(to, amount); // Consume message and emit nullifier - context.consume_l1_to_l2_message(content_hash, secret, context.this_portal_address()); + context.consume_l1_to_l2_message(content_hash, secret, context.this_portal_address(), leaf_index); let new_balance = storage.balances.at(to).read() + U128::from_integer(amount); storage.balances.at(to).write(new_balance); diff --git a/noir-projects/noir-contracts/contracts/test_contract/src/main.nr b/noir-projects/noir-contracts/contracts/test_contract/src/main.nr index 535e96dc43a..c8ea069d730 100644 --- a/noir-projects/noir-contracts/contracts/test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/test_contract/src/main.nr @@ -268,10 +268,20 @@ contract Test { } #[aztec(public)] - fn consume_mint_public_message(to: AztecAddress, amount: Field, secret: Field) { + fn consume_mint_public_message( + to: AztecAddress, + amount: Field, + secret: Field, + message_leaf_index: Field + ) { let content_hash = get_mint_public_content_hash(to, amount); // Consume message and emit nullifier - context.consume_l1_to_l2_message(content_hash, secret, context.this_portal_address()); + context.consume_l1_to_l2_message( + content_hash, + secret, + context.this_portal_address(), + message_leaf_index + ); } #[aztec(private)] @@ -293,10 +303,11 @@ contract Test { fn consume_message_from_arbitrary_sender_public( content: Field, secret: Field, - sender: EthAddress + sender: EthAddress, + message_leaf_index: Field ) { // Consume message and emit nullifier - context.consume_l1_to_l2_message(content, secret, sender); + context.consume_l1_to_l2_message(content, secret, sender, message_leaf_index); } #[aztec(private)] diff --git a/noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr b/noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr index c5814ed81ce..32f9653915b 100644 --- a/noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr @@ -34,11 +34,16 @@ contract TokenBridge { // docs:start:claim_public // Consumes a L1->L2 message and calls the token contract to mint the appropriate amount publicly #[aztec(public)] - fn claim_public(to: AztecAddress, amount: Field, secret: Field) { + fn claim_public(to: AztecAddress, amount: Field, secret: Field, message_leaf_index: Field) { let content_hash = get_mint_public_content_hash(to, amount); // Consume message and emit nullifier - context.consume_l1_to_l2_message(content_hash, secret, context.this_portal_address()); + context.consume_l1_to_l2_message( + content_hash, + secret, + context.this_portal_address(), + message_leaf_index + ); // Mint tokens Token::at(storage.token.read()).mint_public(to, amount).call(&mut context); diff --git a/yarn-project/end-to-end/src/e2e_cross_chain_messaging.test.ts b/yarn-project/end-to-end/src/e2e_cross_chain_messaging.test.ts index e7d3b42101f..862c4a1ac09 100644 --- a/yarn-project/end-to-end/src/e2e_cross_chain_messaging.test.ts +++ b/yarn-project/end-to-end/src/e2e_cross_chain_messaging.test.ts @@ -245,11 +245,16 @@ describe('e2e_cross_chain_messaging', () => { secretHashForL2MessageConsumption, ); + // get message leaf index, needed for claiming in public + const maybeIndexAndPath = await aztecNode.getL1ToL2MessageMembershipWitness('latest', msgHash, 0n); + expect(maybeIndexAndPath).toBeDefined(); + const messageLeafIndex = maybeIndexAndPath![0]; + // 3. Consume L1 -> L2 message and try to mint publicly on L2 - should fail await expect( l2Bridge .withWallet(user2Wallet) - .methods.claim_public(ownerAddress, bridgeAmount, secretForL2MessageConsumption) + .methods.claim_public(ownerAddress, bridgeAmount, secretForL2MessageConsumption, messageLeafIndex) .prove(), ).rejects.toThrow(`No non-nullified L1 to L2 message found for message hash ${wrongMessage.hash().toString()}`); }, 120_000); diff --git a/yarn-project/end-to-end/src/e2e_fees.test.ts b/yarn-project/end-to-end/src/e2e_fees.test.ts index a13b7830b90..d6301790f78 100644 --- a/yarn-project/end-to-end/src/e2e_fees.test.ts +++ b/yarn-project/end-to-end/src/e2e_fees.test.ts @@ -81,6 +81,7 @@ describe('e2e_fees', () => { sequencerAddress = wallets[2].getAddress(); gasBridgeTestHarness = await GasPortalTestingHarnessFactory.create({ + aztecNode: aztecNode, pxeService: pxe, publicClient: deployL1ContractsValues.publicClient, walletClient: deployL1ContractsValues.walletClient, diff --git a/yarn-project/end-to-end/src/e2e_public_cross_chain_messaging.test.ts b/yarn-project/end-to-end/src/e2e_public_cross_chain_messaging.test.ts index b26721bd672..e8aa0bacee3 100644 --- a/yarn-project/end-to-end/src/e2e_public_cross_chain_messaging.test.ts +++ b/yarn-project/end-to-end/src/e2e_public_cross_chain_messaging.test.ts @@ -5,6 +5,8 @@ import { type DebugLogger, type DeployL1Contracts, EthAddress, + type EthAddressLike, + type FieldLike, Fr, L1Actor, L1ToL2Message, @@ -92,8 +94,13 @@ describe('e2e_public_cross_chain_messaging', () => { // Wait for the message to be available for consumption await crossChainTestHarness.makeMessageConsumable(msgHash); + // Get message leaf index, needed for claiming in public + const maybeIndexAndPath = await aztecNode.getL1ToL2MessageMembershipWitness('latest', msgHash, 0n); + expect(maybeIndexAndPath).toBeDefined(); + const messageLeafIndex = maybeIndexAndPath![0]; + // 3. Consume L1 -> L2 message and mint public tokens on L2 - await crossChainTestHarness.consumeMessageOnAztecAndMintPublicly(bridgeAmount, secret); + await crossChainTestHarness.consumeMessageOnAztecAndMintPublicly(bridgeAmount, secret, messageLeafIndex); await crossChainTestHarness.expectPublicBalanceOnL2(ownerAddress, bridgeAmount); const afterBalance = bridgeAmount; @@ -161,14 +168,26 @@ describe('e2e_public_cross_chain_messaging', () => { secretHash, ); + // get message leaf index, needed for claiming in public + const maybeIndexAndPath = await aztecNode.getL1ToL2MessageMembershipWitness('latest', msgHash, 0n); + expect(maybeIndexAndPath).toBeDefined(); + const messageLeafIndex = maybeIndexAndPath![0]; + // user2 tries to consume this message and minting to itself -> should fail since the message is intended to be consumed only by owner. await expect( - l2Bridge.withWallet(user2Wallet).methods.claim_public(user2Wallet.getAddress(), bridgeAmount, secret).prove(), + l2Bridge + .withWallet(user2Wallet) + .methods.claim_public(user2Wallet.getAddress(), bridgeAmount, secret, messageLeafIndex) + .prove(), ).rejects.toThrow(`No non-nullified L1 to L2 message found for message hash ${wrongMessage.hash().toString()}`); // user2 consumes owner's L1-> L2 message on bridge contract and mints public tokens on L2 logger.info("user2 consumes owner's message on L2 Publicly"); - await l2Bridge.withWallet(user2Wallet).methods.claim_public(ownerAddress, bridgeAmount, secret).send().wait(); + await l2Bridge + .withWallet(user2Wallet) + .methods.claim_public(ownerAddress, bridgeAmount, secret, messageLeafIndex) + .send() + .wait(); // ensure funds are gone to owner and not user2. await crossChainTestHarness.expectPublicBalanceOnL2(ownerAddress, bridgeAmount); await crossChainTestHarness.expectPublicBalanceOnL2(user2Wallet.getAddress(), 0n); @@ -312,7 +331,8 @@ describe('e2e_public_cross_chain_messaging', () => { const testContract = await TestContract.deploy(user1Wallet).send().deployed(); const consumeMethod = isPrivate - ? testContract.methods.consume_message_from_arbitrary_sender_private + ? (content: FieldLike, secret: FieldLike, sender: EthAddressLike, _leafIndex: FieldLike) => + testContract.methods.consume_message_from_arbitrary_sender_private(content, secret, sender) : testContract.methods.consume_message_from_arbitrary_sender_public; const secret = Fr.random(); @@ -329,7 +349,7 @@ describe('e2e_public_cross_chain_messaging', () => { const [message1Index, _1] = (await aztecNode.getL1ToL2MessageMembershipWitness('latest', message.hash(), 0n))!; // Finally, we consume the L1 -> L2 message using the test contract either from private or public - await consumeMethod(message.content, secret, message.sender.sender).send().wait(); + await consumeMethod(message.content, secret, message.sender.sender, message1Index).send().wait(); // We send and consume the exact same message the second time to test that oracles correctly return the new // non-nullified message @@ -348,7 +368,7 @@ describe('e2e_public_cross_chain_messaging', () => { // Now we consume the message again. Everything should pass because oracle should return the duplicate message // which is not nullified - await consumeMethod(message.content, secret, message.sender.sender).send().wait(); + await consumeMethod(message.content, secret, message.sender.sender, message2Index).send().wait(); }, 120_000, ); diff --git a/yarn-project/end-to-end/src/e2e_public_to_private_messaging.test.ts b/yarn-project/end-to-end/src/e2e_public_to_private_messaging.test.ts index 805628e74a8..51077dc9de8 100644 --- a/yarn-project/end-to-end/src/e2e_public_to_private_messaging.test.ts +++ b/yarn-project/end-to-end/src/e2e_public_to_private_messaging.test.ts @@ -1,4 +1,4 @@ -import { type AztecAddress, type DebugLogger, type EthAddress } from '@aztec/aztec.js'; +import { type AztecAddress, type AztecNode, type DebugLogger, type EthAddress } from '@aztec/aztec.js'; import { setup } from './fixtures/utils.js'; import { CrossChainTestHarness } from './shared/cross_chain_test_harness.js'; @@ -7,18 +7,23 @@ describe('e2e_public_to_private_messaging', () => { let logger: DebugLogger; let teardown: () => Promise; + let aztecNode: AztecNode; let ethAccount: EthAddress; - let underlyingERC20: any; - let ownerAddress: AztecAddress; - let crossChainTestHarness: CrossChainTestHarness; beforeEach(async () => { - const { aztecNode, pxe, deployL1ContractsValues, wallet, logger: logger_, teardown: teardown_ } = await setup(2); + const { + aztecNode: aztecNode_, + pxe, + deployL1ContractsValues, + wallet, + logger: logger_, + teardown: teardown_, + } = await setup(2); crossChainTestHarness = await CrossChainTestHarness.new( - aztecNode, + aztecNode_, pxe, deployL1ContractsValues.publicClient, deployL1ContractsValues.walletClient, @@ -26,6 +31,7 @@ describe('e2e_public_to_private_messaging', () => { logger_, ); + aztecNode = crossChainTestHarness.aztecNode; ethAccount = crossChainTestHarness.ethAccount; ownerAddress = crossChainTestHarness.ownerAddress; underlyingERC20 = crossChainTestHarness.underlyingERC20; @@ -53,7 +59,12 @@ describe('e2e_public_to_private_messaging', () => { await crossChainTestHarness.makeMessageConsumable(msgHash); - await crossChainTestHarness.consumeMessageOnAztecAndMintPublicly(bridgeAmount, secret); + // get message leaf index, needed for claiming in public + const maybeIndexAndPath = await aztecNode.getL1ToL2MessageMembershipWitness('latest', msgHash, 0n); + expect(maybeIndexAndPath).toBeDefined(); + const messageLeafIndex = maybeIndexAndPath![0]; + + await crossChainTestHarness.consumeMessageOnAztecAndMintPublicly(bridgeAmount, secret, messageLeafIndex); await crossChainTestHarness.expectPublicBalanceOnL2(ownerAddress, bridgeAmount); // Create the commitment to be spent in the private domain diff --git a/yarn-project/end-to-end/src/flakey_e2e_account_init_fees.test.ts b/yarn-project/end-to-end/src/flakey_e2e_account_init_fees.test.ts index 1cb3ab1ba33..9f0d16ed810 100644 --- a/yarn-project/end-to-end/src/flakey_e2e_account_init_fees.test.ts +++ b/yarn-project/end-to-end/src/flakey_e2e_account_init_fees.test.ts @@ -94,6 +94,7 @@ describe('e2e_fees_account_init', () => { }); gasBridgeTestHarness = await GasPortalTestingHarnessFactory.create({ + aztecNode: ctx.aztecNode, pxeService: ctx.pxe, publicClient: ctx.deployL1ContractsValues.publicClient, walletClient: ctx.deployL1ContractsValues.walletClient, diff --git a/yarn-project/end-to-end/src/shared/cross_chain_test_harness.ts b/yarn-project/end-to-end/src/shared/cross_chain_test_harness.ts index 342e0ce917f..63975935c91 100644 --- a/yarn-project/end-to-end/src/shared/cross_chain_test_harness.ts +++ b/yarn-project/end-to-end/src/shared/cross_chain_test_harness.ts @@ -319,10 +319,10 @@ export class CrossChainTestHarness { await this.addPendingShieldNoteToPXE(bridgeAmount, secretHashForRedeemingMintedNotes, consumptionReceipt.txHash); } - async consumeMessageOnAztecAndMintPublicly(bridgeAmount: bigint, secret: Fr) { + async consumeMessageOnAztecAndMintPublicly(bridgeAmount: bigint, secret: Fr, leafIndex: bigint) { this.logger.info('Consuming messages on L2 Publicly'); // Call the mint tokens function on the Aztec.nr contract - await this.l2Bridge.methods.claim_public(this.ownerAddress, bridgeAmount, secret).send().wait(); + await this.l2Bridge.methods.claim_public(this.ownerAddress, bridgeAmount, secret, leafIndex).send().wait(); } async withdrawPrivateFromAztecToL1(withdrawAmount: bigint, nonce: Fr = Fr.ZERO): Promise> { diff --git a/yarn-project/end-to-end/src/shared/gas_portal_test_harness.ts b/yarn-project/end-to-end/src/shared/gas_portal_test_harness.ts index 1897042ab05..7a0c7625302 100644 --- a/yarn-project/end-to-end/src/shared/gas_portal_test_harness.ts +++ b/yarn-project/end-to-end/src/shared/gas_portal_test_harness.ts @@ -1,5 +1,6 @@ import { type AztecAddress, + type AztecNode, type DebugLogger, EthAddress, Fr, @@ -27,6 +28,7 @@ export interface IGasBridgingTestHarness { } export interface GasPortalTestingHarnessFactoryConfig { + aztecNode: AztecNode; pxeService: PXE; publicClient: PublicClient; walletClient: WalletClient; @@ -34,6 +36,7 @@ export interface GasPortalTestingHarnessFactoryConfig { logger: DebugLogger; mockL1?: boolean; } + export class GasPortalTestingHarnessFactory { private constructor(private config: GasPortalTestingHarnessFactoryConfig) {} @@ -49,7 +52,7 @@ export class GasPortalTestingHarnessFactory { } private async createReal() { - const { pxeService, publicClient, walletClient, wallet, logger } = this.config; + const { aztecNode, pxeService, publicClient, walletClient, wallet, logger } = this.config; const ethAccount = EthAddress.fromString((await walletClient.getAddresses())[0]); const l1ContractAddresses = (await pxeService.getNodeInfo()).l1ContractAddresses; @@ -82,6 +85,7 @@ export class GasPortalTestingHarnessFactory { const gasL2 = await GasTokenContract.at(getCanonicalGasTokenAddress(gasPortalAddress), wallet); return new GasBridgingTestHarness( + aztecNode, pxeService, logger, gasL2, @@ -118,6 +122,8 @@ class MockGasBridgingTestHarness implements IGasBridgingTestHarness { */ class GasBridgingTestHarness implements IGasBridgingTestHarness { constructor( + /** Aztec node */ + public aztecNode: AztecNode, /** Private eXecution Environment (PXE). */ public pxeService: PXE, /** Logger. */ @@ -201,10 +207,10 @@ class GasBridgingTestHarness implements IGasBridgingTestHarness { return Fr.fromString(messageHash); } - async consumeMessageOnAztecAndMintPublicly(bridgeAmount: bigint, owner: AztecAddress, secret: Fr) { + async consumeMessageOnAztecAndMintPublicly(bridgeAmount: bigint, owner: AztecAddress, secret: Fr, leafIndex: bigint) { this.logger.info('Consuming messages on L2 Publicly'); // Call the mint tokens function on the Aztec.nr contract - await this.l2Token.methods.claim_public(owner, bridgeAmount, secret).send().wait(); + await this.l2Token.methods.claim_public(owner, bridgeAmount, secret, leafIndex).send().wait(); } async getL2PublicBalanceOf(owner: AztecAddress) { @@ -223,15 +229,20 @@ class GasBridgingTestHarness implements IGasBridgingTestHarness { await this.mintTokensOnL1(l1TokenBalance); // 2. Deposit tokens to the TokenPortal - await this.sendTokensToPortalPublic(bridgeAmount, owner, secretHash); + const msgHash = await this.sendTokensToPortalPublic(bridgeAmount, owner, secretHash); expect(await this.getL1BalanceOf(this.ethAccount)).toBe(l1TokenBalance - bridgeAmount); // Perform an unrelated transactions on L2 to progress the rollup by 2 blocks. await this.l2Token.methods.check_balance(0).send().wait(); await this.l2Token.methods.check_balance(0).send().wait(); + // Get message leaf index, needed for claiming in public + const maybeIndexAndPath = await this.aztecNode.getL1ToL2MessageMembershipWitness('latest', msgHash, 0n); + expect(maybeIndexAndPath).toBeDefined(); + const messageLeafIndex = maybeIndexAndPath![0]; + // 3. Consume L1-> L2 message and mint public tokens on L2 - await this.consumeMessageOnAztecAndMintPublicly(bridgeAmount, owner, secret); + await this.consumeMessageOnAztecAndMintPublicly(bridgeAmount, owner, secret, messageLeafIndex); await this.expectPublicBalanceOnL2(owner, bridgeAmount); } } diff --git a/yarn-project/end-to-end/src/shared/uniswap_l1_l2.ts b/yarn-project/end-to-end/src/shared/uniswap_l1_l2.ts index 81dc6b3cb4c..f23c35ea442 100644 --- a/yarn-project/end-to-end/src/shared/uniswap_l1_l2.ts +++ b/yarn-project/end-to-end/src/shared/uniswap_l1_l2.ts @@ -14,6 +14,7 @@ import { InboxAbi, UniswapPortalAbi, UniswapPortalBytecode } from '@aztec/l1-art import { UniswapContract } from '@aztec/noir-contracts.js/Uniswap'; import { jest } from '@jest/globals'; +import { strict as assert } from 'assert'; import { type Account, type Chain, @@ -409,9 +410,22 @@ export const uniswapL1L2TestSuite = ( // Wait for the message to be available for consumption await wethCrossChainHarness.makeMessageConsumable(wethDepositMsgHash); + // Get message leaf index, needed for claiming in public + const wethDepositMaybeIndexAndPath = await aztecNode.getL1ToL2MessageMembershipWitness( + 'latest', + wethDepositMsgHash, + 0n, + ); + assert(wethDepositMaybeIndexAndPath !== undefined, 'Message not found in tree'); + const wethDepositMessageLeafIndex = wethDepositMaybeIndexAndPath[0]; + // 2. Claim WETH on L2 logger.info('Minting weth on L2'); - await wethCrossChainHarness.consumeMessageOnAztecAndMintPublicly(wethAmountToBridge, secretForMintingWeth); + await wethCrossChainHarness.consumeMessageOnAztecAndMintPublicly( + wethAmountToBridge, + secretForMintingWeth, + wethDepositMessageLeafIndex, + ); await wethCrossChainHarness.expectPublicBalanceOnL2(ownerAddress, wethAmountToBridge); // Store balances @@ -585,9 +599,22 @@ export const uniswapL1L2TestSuite = ( // Wait for the message to be available for consumption await daiCrossChainHarness.makeMessageConsumable(outTokenDepositMsgHash); + // Get message leaf index, needed for claiming in public + const outTokenDepositMaybeIndexAndPath = await aztecNode.getL1ToL2MessageMembershipWitness( + 'latest', + outTokenDepositMsgHash, + 0n, + ); + assert(outTokenDepositMaybeIndexAndPath !== undefined, 'Message not found in tree'); + const outTokenDepositMessageLeafIndex = outTokenDepositMaybeIndexAndPath[0]; + // 6. claim dai on L2 logger.info('Consuming messages to mint dai on L2'); - await daiCrossChainHarness.consumeMessageOnAztecAndMintPublicly(daiAmountToBridge, secretForDepositingSwappedDai); + await daiCrossChainHarness.consumeMessageOnAztecAndMintPublicly( + daiAmountToBridge, + secretForDepositingSwappedDai, + outTokenDepositMessageLeafIndex, + ); await daiCrossChainHarness.expectPublicBalanceOnL2(ownerAddress, daiL2BalanceBeforeSwap + daiAmountToBridge); const wethL2BalanceAfterSwap = await wethCrossChainHarness.getL2PublicBalanceOf(ownerAddress); diff --git a/yarn-project/simulator/src/public/index.test.ts b/yarn-project/simulator/src/public/index.test.ts index 7cd22cf4df1..6f74908fadd 100644 --- a/yarn-project/simulator/src/public/index.test.ts +++ b/yarn-project/simulator/src/public/index.test.ts @@ -397,6 +397,7 @@ describe('ACIR public execution simulator', () => { const tokenRecipient = AztecAddress.random(); let bridgedAmount = 20n; let secret = new Fr(1); + let leafIndex: bigint; let crossChainMsgRecipient: AztecAddress | undefined; let crossChainMsgSender: EthAddress | undefined; @@ -410,6 +411,7 @@ describe('ACIR public execution simulator', () => { beforeEach(() => { bridgedAmount = 20n; secret = new Fr(1); + leafIndex = 0n; crossChainMsgRecipient = undefined; crossChainMsgSender = undefined; @@ -423,7 +425,7 @@ describe('ACIR public execution simulator', () => { secret, ); - const computeArgs = () => encodeArguments(mintPublicArtifact, [tokenRecipient, bridgedAmount, secret]); + const computeArgs = () => encodeArguments(mintPublicArtifact, [tokenRecipient, bridgedAmount, secret, leafIndex]); const computeCallContext = () => makeCallContext(contractAddress, { @@ -455,7 +457,7 @@ describe('ACIR public execution simulator', () => { root = pedersenHash([root, sibling]); } commitmentsDb.getL1ToL2MembershipWitness.mockImplementation(() => { - return Promise.resolve(new MessageLoadOracleInputs(0n, siblingPath)); + return Promise.resolve(new MessageLoadOracleInputs(leafIndex, siblingPath)); }); if (updateState) { From 71b60f32c3b3781dda1c79bb6a926050bad7bb55 Mon Sep 17 00:00:00 2001 From: Facundo Date: Wed, 17 Apr 2024 19:24:52 +0100 Subject: [PATCH 002/102] fix(avm-simulator): L1TOL2MESSAGEEXISTS opcode (#5807) The opcode should check for the value at the given leaf index. --- .../pxe/src/simulator_oracle/index.ts | 5 +++ .../simulator/src/avm/avm_simulator.test.ts | 5 +-- .../simulator/src/avm/fixtures/index.ts | 22 ++---------- .../simulator/src/avm/journal/journal.test.ts | 23 ++++++------ .../simulator/src/avm/journal/journal.ts | 23 +++--------- .../src/avm/opcodes/accrued_substate.test.ts | 36 ++++++++++++++----- yarn-project/simulator/src/public/db.ts | 6 ++++ .../simulator/src/public/public_executor.ts | 4 +++ 8 files changed, 62 insertions(+), 62 deletions(-) diff --git a/yarn-project/pxe/src/simulator_oracle/index.ts b/yarn-project/pxe/src/simulator_oracle/index.ts index 56e65ee0e81..d5ba6c1a032 100644 --- a/yarn-project/pxe/src/simulator_oracle/index.ts +++ b/yarn-project/pxe/src/simulator_oracle/index.ts @@ -159,6 +159,11 @@ export class SimulatorOracle implements DBOracle { return new MessageLoadOracleInputs(messageIndex, siblingPath); } + // Only used in public. + public getL1ToL2LeafValue(_leafIndex: bigint): Promise { + throw new Error('Unimplemented in private!'); + } + /** * Gets the index of a commitment in the note hash tree. * @param commitment - The commitment. diff --git a/yarn-project/simulator/src/avm/avm_simulator.test.ts b/yarn-project/simulator/src/avm/avm_simulator.test.ts index 6eeb992c72e..411d6c8fa84 100644 --- a/yarn-project/simulator/src/avm/avm_simulator.test.ts +++ b/yarn-project/simulator/src/avm/avm_simulator.test.ts @@ -20,7 +20,6 @@ import { initContext, initExecutionEnvironment, initGlobalVariables, - initL1ToL2MessageOracleInput, initMachineState, randomMemoryBytes, randomMemoryFields, @@ -484,9 +483,7 @@ describe('AVM simulator: transpiled Noir contracts', () => { const calldata = [msgHash, leafIndex]; const context = initContext({ env: initExecutionEnvironment({ calldata }) }); - jest - .spyOn(context.persistableState.hostStorage.commitmentsDb, 'getL1ToL2MembershipWitness') - .mockResolvedValue(initL1ToL2MessageOracleInput(leafIndex.toBigInt())); + jest.spyOn(context.persistableState.hostStorage.commitmentsDb, 'getL1ToL2LeafValue').mockResolvedValue(msgHash); const bytecode = getAvmTestContractBytecode('l1_to_l2_msg_exists'); const results = await new AvmSimulator(context).executeBytecode(bytecode); diff --git a/yarn-project/simulator/src/avm/fixtures/index.ts b/yarn-project/simulator/src/avm/fixtures/index.ts index c03fa818166..ef9233bb686 100644 --- a/yarn-project/simulator/src/avm/fixtures/index.ts +++ b/yarn-project/simulator/src/avm/fixtures/index.ts @@ -1,5 +1,4 @@ -import { SiblingPath } from '@aztec/circuit-types'; -import { GasFees, GasSettings, GlobalVariables, Header, L1_TO_L2_MSG_TREE_HEIGHT } from '@aztec/circuits.js'; +import { GasFees, GasSettings, GlobalVariables, Header } from '@aztec/circuits.js'; import { FunctionSelector } from '@aztec/foundation/abi'; import { AztecAddress } from '@aztec/foundation/aztec-address'; import { EthAddress } from '@aztec/foundation/eth-address'; @@ -8,12 +7,7 @@ import { Fr } from '@aztec/foundation/fields'; import { mock } from 'jest-mock-extended'; import merge from 'lodash.merge'; -import { - type CommitmentsDB, - MessageLoadOracleInputs, - type PublicContractsDB, - type PublicStateDB, -} from '../../index.js'; +import { type CommitmentsDB, type PublicContractsDB, type PublicStateDB } from '../../index.js'; import { AvmContext } from '../avm_context.js'; import { AvmContextInputs, AvmExecutionEnvironment } from '../avm_execution_environment.js'; import { AvmMachineState } from '../avm_machine_state.js'; @@ -111,18 +105,6 @@ export function allSameExcept(original: any, overrides: any): any { return merge({}, original, overrides); } -/** - * Create an empty L1ToL2Message oracle input - */ -export function initL1ToL2MessageOracleInput( - leafIndex?: bigint, -): MessageLoadOracleInputs { - return new MessageLoadOracleInputs( - leafIndex ?? 0n, - new SiblingPath(L1_TO_L2_MSG_TREE_HEIGHT, Array(L1_TO_L2_MSG_TREE_HEIGHT)), - ); -} - /** * Adjust the user index to account for the AvmContextInputs size. * This is a hack for testing, and should go away once AvmContextInputs themselves go away. diff --git a/yarn-project/simulator/src/avm/journal/journal.test.ts b/yarn-project/simulator/src/avm/journal/journal.test.ts index 400d7066921..8a42f1e6796 100644 --- a/yarn-project/simulator/src/avm/journal/journal.test.ts +++ b/yarn-project/simulator/src/avm/journal/journal.test.ts @@ -6,7 +6,6 @@ import { Fr } from '@aztec/foundation/fields'; import { type MockProxy, mock } from 'jest-mock-extended'; import { type CommitmentsDB, type PublicContractsDB, type PublicStateDB } from '../../index.js'; -import { initL1ToL2MessageOracleInput } from '../fixtures/index.js'; import { HostStorage } from './host_storage.js'; import { AvmPersistableStateManager, type JournalData } from './journal.js'; @@ -114,28 +113,28 @@ describe('journal', () => { ]); }); it('checkL1ToL2MessageExists works for missing message', async () => { - const utxo = new Fr(2); + const msgHash = new Fr(2); const leafIndex = new Fr(42); - const exists = await journal.checkL1ToL2MessageExists(utxo, leafIndex); + const exists = await journal.checkL1ToL2MessageExists(msgHash, leafIndex); expect(exists).toEqual(false); const journalUpdates = journal.flush(); expect(journalUpdates.l1ToL2MessageChecks).toEqual([ - expect.objectContaining({ leafIndex: leafIndex, msgHash: utxo, exists: false }), + expect.objectContaining({ leafIndex: leafIndex, msgHash, exists: false }), ]); }); - it('checkL1ToL2MessageExists works for existing nullifiers', async () => { - const utxo = new Fr(2); + it('checkL1ToL2MessageExists works for existing msgHash', async () => { + const msgHash = new Fr(2); const leafIndex = new Fr(42); - commitmentsDb.getL1ToL2MembershipWitness.mockResolvedValue(initL1ToL2MessageOracleInput(leafIndex.toBigInt())); - const exists = await journal.checkL1ToL2MessageExists(utxo, leafIndex); + commitmentsDb.getL1ToL2LeafValue.mockResolvedValue(msgHash); + const exists = await journal.checkL1ToL2MessageExists(msgHash, leafIndex); expect(exists).toEqual(true); const journalUpdates = journal.flush(); expect(journalUpdates.l1ToL2MessageChecks).toEqual([ - expect.objectContaining({ leafIndex: leafIndex, msgHash: utxo, exists: true }), + expect.objectContaining({ leafIndex: leafIndex, msgHash, exists: true }), ]); }); it('Should maintain nullifiers', async () => { @@ -150,11 +149,11 @@ describe('journal', () => { }); it('Should maintain l1 messages', () => { const recipient = EthAddress.fromField(new Fr(1)); - const utxo = new Fr(2); - journal.writeL1Message(recipient, utxo); + const msgHash = new Fr(2); + journal.writeL1Message(recipient, msgHash); const journalUpdates = journal.flush(); - expect(journalUpdates.newL1Messages).toEqual([{ recipient, content: utxo }]); + expect(journalUpdates.newL1Messages).toEqual([{ recipient, content: msgHash }]); }); }); diff --git a/yarn-project/simulator/src/avm/journal/journal.ts b/yarn-project/simulator/src/avm/journal/journal.ts index d32cf8d5119..5c21dd175a3 100644 --- a/yarn-project/simulator/src/avm/journal/journal.ts +++ b/yarn-project/simulator/src/avm/journal/journal.ts @@ -172,24 +172,11 @@ export class AvmPersistableStateManager { * @returns exists - whether the message exists in the L1 to L2 Messages tree */ public async checkL1ToL2MessageExists(msgHash: Fr, msgLeafIndex: Fr): Promise { - let exists = false; - try { - // The following 2 values are used to compute a message nullifier. Given that here we do not care about getting - // non-nullified messages we can just pass in random values and the nullifier check will effectively be ignored - // (no nullifier will be found). - const ignoredContractAddress = AztecAddress.random(); - const ignoredSecret = Fr.random(); - const gotMessage = await this.hostStorage.commitmentsDb.getL1ToL2MembershipWitness( - ignoredContractAddress, - msgHash, - ignoredSecret, - ); - exists = gotMessage !== undefined && gotMessage.index == msgLeafIndex.toBigInt(); - } catch { - // error getting message - doesn't exist! - exists = false; - } - this.log.debug(`l1ToL2Messages(${msgHash})@${msgLeafIndex} ?? exists: ${exists}.`); + const valueAtIndex = await this.hostStorage.commitmentsDb.getL1ToL2LeafValue(msgLeafIndex.toBigInt()); + const exists = valueAtIndex?.equals(msgHash) ?? false; + this.log.debug( + `l1ToL2Messages(@${msgLeafIndex}) ?? exists: ${exists}, expected: ${msgHash}, found: ${valueAtIndex}.`, + ); this.trace.traceL1ToL2MessageCheck(msgHash, msgLeafIndex, exists); return Promise.resolve(exists); } diff --git a/yarn-project/simulator/src/avm/opcodes/accrued_substate.test.ts b/yarn-project/simulator/src/avm/opcodes/accrued_substate.test.ts index 5eac2f364f4..88c7cadd138 100644 --- a/yarn-project/simulator/src/avm/opcodes/accrued_substate.test.ts +++ b/yarn-project/simulator/src/avm/opcodes/accrued_substate.test.ts @@ -8,12 +8,7 @@ import { type CommitmentsDB } from '../../index.js'; import { type AvmContext } from '../avm_context.js'; import { Field, Uint8 } from '../avm_memory_types.js'; import { InstructionExecutionError } from '../errors.js'; -import { - initContext, - initExecutionEnvironment, - initHostStorage, - initL1ToL2MessageOracleInput, -} from '../fixtures/index.js'; +import { initContext, initExecutionEnvironment, initHostStorage } from '../fixtures/index.js'; import { AvmPersistableStateManager } from '../journal/journal.js'; import { EmitNoteHash, @@ -348,7 +343,7 @@ describe('Accrued Substate', () => { // mock commitments db to show message exists const commitmentsDb = mock(); - commitmentsDb.getL1ToL2MembershipWitness.mockResolvedValue(initL1ToL2MessageOracleInput(leafIndex.toBigInt())); + commitmentsDb.getL1ToL2LeafValue.mockResolvedValue(msgHash.toFr()); const hostStorage = initHostStorage({ commitmentsDb }); context = initContext({ persistableState: new AvmPersistableStateManager(hostStorage) }); @@ -356,7 +351,6 @@ describe('Accrued Substate', () => { context.machineState.memory.set(msgLeafIndexOffset, leafIndex); await new L1ToL2MessageExists(/*indirect=*/ 0, msgHashOffset, msgLeafIndexOffset, existsOffset).execute(context); - // never created, doesn't exist! const exists = context.machineState.memory.getAs(existsOffset); expect(exists).toEqual(new Uint8(1)); @@ -365,6 +359,32 @@ describe('Accrued Substate', () => { expect.objectContaining({ leafIndex: leafIndex.toFr(), msgHash: msgHash.toFr(), exists: true }), ]); }); + + it('Should correctly show false when another L1ToL2 message exists at that index', async () => { + const msgHash = new Field(69n); + const leafIndex = new Field(42n); + const msgHashOffset = 0; + const msgLeafIndexOffset = 1; + const existsOffset = 2; + + const commitmentsDb = mock(); + commitmentsDb.getL1ToL2LeafValue.mockResolvedValue(Fr.ZERO); + const hostStorage = initHostStorage({ commitmentsDb }); + context = initContext({ persistableState: new AvmPersistableStateManager(hostStorage) }); + + context.machineState.memory.set(msgHashOffset, msgHash); + context.machineState.memory.set(msgLeafIndexOffset, leafIndex); + await new L1ToL2MessageExists(/*indirect=*/ 0, msgHashOffset, msgLeafIndexOffset, existsOffset).execute(context); + + // never created, doesn't exist! + const exists = context.machineState.memory.getAs(existsOffset); + expect(exists).toEqual(new Uint8(0)); + + const journalState = context.persistableState.flush(); + expect(journalState.l1ToL2MessageChecks).toEqual([ + expect.objectContaining({ leafIndex: leafIndex.toFr(), msgHash: msgHash.toFr(), exists: false }), + ]); + }); }); describe('EmitUnencryptedLog', () => { diff --git a/yarn-project/simulator/src/public/db.ts b/yarn-project/simulator/src/public/db.ts index 88d2a66025a..68e08315d6b 100644 --- a/yarn-project/simulator/src/public/db.ts +++ b/yarn-project/simulator/src/public/db.ts @@ -92,6 +92,12 @@ export interface CommitmentsDB { secret: Fr, ): Promise>; + /** + * @param leafIndex the leaf to look up + * @returns The l1 to l2 leaf value or undefined if not found. + */ + getL1ToL2LeafValue(leafIndex: bigint): Promise; + /** * Gets the index of a commitment in the note hash tree. * @param commitment - The commitment. diff --git a/yarn-project/simulator/src/public/public_executor.ts b/yarn-project/simulator/src/public/public_executor.ts index 1f1bc28115e..c40a815732b 100644 --- a/yarn-project/simulator/src/public/public_executor.ts +++ b/yarn-project/simulator/src/public/public_executor.ts @@ -257,6 +257,10 @@ export class WorldStateDB implements CommitmentsDB { return new MessageLoadOracleInputs(messageIndex, siblingPath); } + public async getL1ToL2LeafValue(leafIndex: bigint): Promise { + return await this.db.getLeafValue(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, leafIndex); + } + public async getCommitmentIndex(commitment: Fr): Promise { return await this.db.findLeafIndex(MerkleTreeId.NOTE_HASH_TREE, commitment); } From 70b3f3f1aebbb626014d54e121e841938407bdaf Mon Sep 17 00:00:00 2001 From: Santiago Palladino Date: Wed, 17 Apr 2024 15:56:59 -0300 Subject: [PATCH 003/102] chore(ci): Notify internal Slack channel when CI breaks on master (#5788) Uses the official Slack github action with the recommended "workflow" flow. @ludamad, @charlielye, and @PhilWindle are admins of the workflow in Slack. --- .github/workflows/ci.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 44a736a22c2..8ad90c70469 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -149,3 +149,18 @@ jobs: needs: [e2e, bb-native-tests, bb-bench] steps: - run: echo Pull request merging now allowed. + + notify: + needs: [e2e, bb-native-tests, bb-bench] + runs-on: ubuntu-latest + if: ${{ github.ref == 'refs/heads/master' && failure() }} + steps: + - name: Send notification to aztec3-ci channel if workflow failed on master + uses: slackapi/slack-github-action@v1.25.0 + with: + payload: | + { + "url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" + } + env: + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_NOTIFY_WORKFLOW_TRIGGER_URL }} From 15b569f24e55d374bfb5a54c8771118653e5e77c Mon Sep 17 00:00:00 2001 From: esau <152162806+sklppy88@users.noreply.github.com> Date: Wed, 17 Apr 2024 21:08:10 +0200 Subject: [PATCH 004/102] feat: implement canonical key registry 5609 and implement shared mutable getter from another contract 5689 (#5723) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Resolves #5609 and #5689 --------- Co-authored-by: Jan BeneÅ¡ --- .../aztec/src/state_vars/shared_mutable.nr | 2 + .../shared_mutable_private_getter.nr | 70 +++++ noir-projects/noir-contracts/Nargo.toml | 1 + .../key_registry_contract/Nargo.toml | 9 + .../key_registry_contract/src/main.nr | 118 ++++++++ .../contracts/test_contract/src/main.nr | 39 +++ .../types/src/address/partial_address.nr | 16 +- .../src/composed/cli_docs_sandbox.test.ts | 1 + .../end-to-end/src/e2e_key_registry.test.ts | 261 ++++++++++++++++++ .../end-to-end/src/e2e_state_vars.test.ts | 56 +++- yarn-project/tsconfig.json | 2 +- 11 files changed, 570 insertions(+), 5 deletions(-) create mode 100644 noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable_private_getter.nr create mode 100644 noir-projects/noir-contracts/contracts/key_registry_contract/Nargo.toml create mode 100644 noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr create mode 100644 yarn-project/end-to-end/src/e2e_key_registry.test.ts diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable.nr b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable.nr index fa61113bc78..533639390d8 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable.nr @@ -1,4 +1,6 @@ mod shared_mutable; mod scheduled_value_change; +mod shared_mutable_private_getter; use shared_mutable::SharedMutable; +use shared_mutable_private_getter::SharedMutablePrivateGetter; diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable_private_getter.nr b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable_private_getter.nr new file mode 100644 index 00000000000..2f4f4339481 --- /dev/null +++ b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable_private_getter.nr @@ -0,0 +1,70 @@ +use dep::protocol_types::{hash::pedersen_hash, traits::FromField, address::AztecAddress}; + +use crate::context::{PrivateContext, Context}; +use crate::history::public_storage::public_storage_historical_read; +use crate::public_storage; +use crate::state_vars::{storage::Storage, shared_mutable::scheduled_value_change::ScheduledValueChange}; + +struct SharedMutablePrivateGetter { + context: PrivateContext, + // The contract address of the contract we want to read from + other_contract_address: AztecAddress, + // The storage slot where the SharedMutable is stored on the other contract + storage_slot: Field, +} + +// We have this as a view-only interface to reading Shared Mutables in other contracts. +// Currently the Shared Mutable does not support this. We can adapt SharedMutable at a later date +impl SharedMutablePrivateGetter { + pub fn new( + context: PrivateContext, + other_contract_address: AztecAddress, + storage_slot: Field, + ) -> Self { + assert(storage_slot != 0, "Storage slot 0 not allowed. Storage slots must start from 1."); + assert(other_contract_address.to_field() != 0, "Other contract address cannot be 0"); + Self { context, other_contract_address, storage_slot } + } + + pub fn get_current_value_in_private(self) -> T where T: FromField { + let mut context = self.context; + + let (scheduled_value_change, historical_block_number) = self.historical_read_from_public_storage(context); + let block_horizon = scheduled_value_change.get_block_horizon(historical_block_number); + + // We prevent this transaction from being included in any block after the block horizon, ensuring that the + // historical public value matches the current one, since it can only change after the horizon. + context.set_tx_max_block_number(block_horizon); + scheduled_value_change.get_current_at(historical_block_number) + } + + fn historical_read_from_public_storage( + self, + context: PrivateContext + ) -> (ScheduledValueChange, u32) where T: FromField { + let derived_slot = self.get_derived_storage_slot(); + + // Ideally the following would be simply public_storage::read_historical, but we can't implement that yet. + let mut raw_fields = [0; 3]; + for i in 0..3 { + raw_fields[i] = public_storage_historical_read( + context, + derived_slot + i as Field, + self.other_contract_address + ); + } + + let scheduled_value: ScheduledValueChange = ScheduledValueChange::deserialize(raw_fields); + let historical_block_number = context.historical_header.global_variables.block_number as u32; + + (scheduled_value, historical_block_number) + } + + fn get_derived_storage_slot(self) -> Field { + // Since we're actually storing three values (a ScheduledValueChange struct), we hash the storage slot to get a + // unique location in which we can safely store as much data as we need. This could be removed if we informed + // the slot allocator of how much space we need so that proper padding could be added. + // See https://github.com/AztecProtocol/aztec-packages/issues/5492 + pedersen_hash([self.storage_slot, 0], 0) + } +} diff --git a/noir-projects/noir-contracts/Nargo.toml b/noir-projects/noir-contracts/Nargo.toml index 73e8bb9295e..b3d1c57c752 100644 --- a/noir-projects/noir-contracts/Nargo.toml +++ b/noir-projects/noir-contracts/Nargo.toml @@ -24,6 +24,7 @@ members = [ "contracts/escrow_contract", "contracts/gas_token_contract", "contracts/import_test_contract", + "contracts/key_registry_contract", "contracts/inclusion_proofs_contract", "contracts/lending_contract", "contracts/parent_contract", diff --git a/noir-projects/noir-contracts/contracts/key_registry_contract/Nargo.toml b/noir-projects/noir-contracts/contracts/key_registry_contract/Nargo.toml new file mode 100644 index 00000000000..cae3a7ead7e --- /dev/null +++ b/noir-projects/noir-contracts/contracts/key_registry_contract/Nargo.toml @@ -0,0 +1,9 @@ +[package] +name = "key_registry_contract" +authors = [""] +compiler_version = ">=0.25.0" +type = "contract" + +[dependencies] +aztec = { path = "../../../aztec-nr/aztec" } +authwit = { path = "../../../aztec-nr/authwit" } diff --git a/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr b/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr new file mode 100644 index 00000000000..8f2810f3dbf --- /dev/null +++ b/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr @@ -0,0 +1,118 @@ +contract KeyRegistry { + use dep::std::hash::poseidon2::Poseidon2::hash as poseidon2_hash; + use dep::authwit::auth::assert_current_call_valid_authwit_public; + + use dep::aztec::{ + context::gas::GasOpts, + state_vars::{ + SharedMutable, + Map + }, + protocol_types::{ + abis::function_selector::FunctionSelector, + contract_class_id::ContractClassId, + address::{ + AztecAddress, + EthAddress, + PublicKeysHash, + PartialAddress, + }, + constants::{ + GENERATOR_INDEX__CONTRACT_ADDRESS_V1, + GENERATOR_INDEX__PUBLIC_KEYS_HASH + }, + traits::{ + Serialize, + Deserialize, + } + }, + }; + + global KEY_ROTATION_DELAY = 5; + + #[aztec(storage)] + struct Storage { + // We are not supporting rotating / changing keys other than the nullifier public in the registry at the moment, but will in the future. + // Uncomment lines below to enable that functionality + nullifier_public_key_registry: Map>, + // incoming_public_key_registry: Map>, + // outgoing_public_key_registry: Map>, + // tagging_public_key_registry: Map>, + } + + #[aztec(public)] + fn rotate_nullifier_public_key( + address: AztecAddress, + new_nullifier_public_key: Field, + ) { + assert( + new_nullifier_public_key != 0, + "New nullifier public key must be non-zero" + ); + + if (!address.eq(context.msg_sender())) { + assert_current_call_valid_authwit_public(&mut context, address); + } + + let nullifier_key_registry = storage.nullifier_public_key_registry.at(address); + + nullifier_key_registry.schedule_value_change(new_nullifier_public_key); + } + + #[aztec(public)] + fn register( + address: AztecAddress, + partial_address: PartialAddress, + nullifier_public_key: Field, + incoming_public_key: Field, + outgoing_public_key: Field, + tagging_public_key: Field, + ) { + assert( + (nullifier_public_key != 0) & + (incoming_public_key != 0) & + (outgoing_public_key != 0) & + (tagging_public_key != 0), + "All public keys must be non-zero" + ); + + // TODO (ek): Do it below after refactoring all public_keys_hash_elemtns + // let public_keys_hash = PublicKeysHash::compute(nullifier_public_key, tagging_public_key, incoming_public_key, outgoing_public_key); + // let address = AztecAddress::compute(public_keys_hash, partial_address); + // We could also pass in original_public_keys_hash instead of computing it here, if all we need the original one is for being able to prove ownership of address + let public_keys_hash = poseidon2_hash([ + nullifier_public_key, + incoming_public_key, + outgoing_public_key, + tagging_public_key, + GENERATOR_INDEX__PUBLIC_KEYS_HASH, + ], + 5 + ); + + let computed_address = AztecAddress::from_field( + poseidon2_hash([ + partial_address.to_field(), + public_keys_hash.to_field(), + GENERATOR_INDEX__CONTRACT_ADDRESS_V1 as Field, + ], + 3 + ) + ); + + assert(computed_address.eq(address), "Computed address does not match supplied address"); + + let nullifier_key_registry = storage.nullifier_public_key_registry.at(address); + // We are not supporting rotating / changing keys other than the nullifier public in the registry at the moment, but will in the future. + // Uncomment lines below to enable that functionality + // let incoming_key_registry = storage.incoming_public_key_registry.at(address); + // let outgoing_key_registry = storage.outgoing_public_key_registry.at(address); + // let tagging_key_registry = storage.taggin_public_key_registry.at(address); + + nullifier_key_registry.schedule_value_change(nullifier_public_key); + // We are not supporting rotating / changing keys other than the nullifier public in the registry at the moment, but will in the future. + // Uncomment lines below to enable that functionality // incoming_key_registry.schedule_value_change(new_incoming_public_key); + // outgoing_key_registry.schedule_value_change(new_outgoing_public_key); + // tagging_key_registry.schedule_value_change(new_tagging_public_key); + } +} diff --git a/noir-projects/noir-contracts/contracts/test_contract/src/main.nr b/noir-projects/noir-contracts/contracts/test_contract/src/main.nr index c8ea069d730..92e8ad6490c 100644 --- a/noir-projects/noir-contracts/contracts/test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/test_contract/src/main.nr @@ -9,6 +9,9 @@ contract Test { abis::private_circuit_public_inputs::PrivateCircuitPublicInputs, constants::{MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NOTES_PER_PAGE}, traits::Serialize }; + + use dep::aztec::state_vars::shared_mutable::SharedMutablePrivateGetter; + // docs:start:unencrypted_import use dep::aztec::prelude::emit_unencrypted_log; // docs:end:unencrypted_import @@ -387,6 +390,42 @@ contract Test { constant.value } + #[aztec(private)] + fn test_shared_mutable_private_getter_for_registry_contract( + contract_address_to_read: AztecAddress, + storage_slot_of_shared_mutable: Field, + address_to_get_in_registry: AztecAddress, + ) { + // We have to derive this slot to get the location of the shared mutable inside the Map + let derived_slot = dep::aztec::hash::pedersen_hash([storage_slot_of_shared_mutable, address_to_get_in_registry.to_field()], 0); + // It's a bit wonky because we need to know the delay for get_current_value_in_private to work correctly + let registry_private_getter: SharedMutablePrivateGetter = SharedMutablePrivateGetter::new(context, contract_address_to_read, derived_slot); + let nullifier_public_key = registry_private_getter.get_current_value_in_private(); + + emit_unencrypted_log_from_private(&mut context, nullifier_public_key); + } + + #[aztec(private)] + fn test_shared_mutable_private_getter( + contract_address_to_read: AztecAddress, + storage_slot_of_shared_mutable: Field, + ) { + // It's a bit wonky because we need to know the delay for get_current_value_in_private to work correctly + let test: SharedMutablePrivateGetter = SharedMutablePrivateGetter::new(context, contract_address_to_read, storage_slot_of_shared_mutable); + let authorized = test.get_current_value_in_private(); + + emit_unencrypted_log_from_private(&mut context, authorized); + } + + #[aztec(public)] + fn delay() { + // We use this as a util function to "mine a block" + dep::aztec::log::emit_unencrypted_log( + &mut context, + "dummy" + ); + } + // Purely exists for testing unconstrained fn get_random(kinda_seed: Field) -> pub Field { kinda_seed * unsafe_rand() diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/address/partial_address.nr b/noir-projects/noir-protocol-circuits/crates/types/src/address/partial_address.nr index df67b7f6dc2..359fae794ba 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/address/partial_address.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/address/partial_address.nr @@ -4,9 +4,11 @@ use crate::{ aztec_address::AztecAddress }, constants::GENERATOR_INDEX__PARTIAL_ADDRESS, contract_class_id::ContractClassId, - hash::pedersen_hash, traits::ToField + hash::pedersen_hash, traits::{ToField, FromField, Serialize, Deserialize} }; +global PARTIAL_ADDRESS_LENGTH = 1; + // Partial address struct PartialAddress { inner : Field @@ -18,6 +20,18 @@ impl ToField for PartialAddress { } } +impl Serialize for PartialAddress { + fn serialize(self: Self) -> [Field; PARTIAL_ADDRESS_LENGTH] { + [self.to_field()] + } +} + +impl Deserialize for PartialAddress { + fn deserialize(fields: [Field; PARTIAL_ADDRESS_LENGTH]) -> Self { + PartialAddress { inner: fields[0] } + } +} + impl PartialAddress { pub fn from_field(field: Field) -> Self { Self { inner: field } diff --git a/yarn-project/end-to-end/src/composed/cli_docs_sandbox.test.ts b/yarn-project/end-to-end/src/composed/cli_docs_sandbox.test.ts index 3b0a8e20400..446330a461e 100644 --- a/yarn-project/end-to-end/src/composed/cli_docs_sandbox.test.ts +++ b/yarn-project/end-to-end/src/composed/cli_docs_sandbox.test.ts @@ -117,6 +117,7 @@ FPCContractArtifact GasTokenContractArtifact ImportTestContractArtifact InclusionProofsContractArtifact +KeyRegistryContractArtifact LendingContractArtifact MultiCallEntrypointContractArtifact ParentContractArtifact diff --git a/yarn-project/end-to-end/src/e2e_key_registry.test.ts b/yarn-project/end-to-end/src/e2e_key_registry.test.ts new file mode 100644 index 00000000000..37f6ac8cea5 --- /dev/null +++ b/yarn-project/end-to-end/src/e2e_key_registry.test.ts @@ -0,0 +1,261 @@ +import { type AccountWallet, AztecAddress, Fr, type PXE } from '@aztec/aztec.js'; +import { GeneratorIndex } from '@aztec/circuits.js'; +import { poseidon2Hash } from '@aztec/foundation/crypto'; +import { KeyRegistryContract, TestContract } from '@aztec/noir-contracts.js'; + +import { jest } from '@jest/globals'; + +import { publicDeployAccounts, setup } from './fixtures/utils.js'; + +const TIMEOUT = 100_000; + +describe('SharedMutablePrivateGetter', () => { + let keyRegistry: KeyRegistryContract; + let testContract: TestContract; + let pxe: PXE; + jest.setTimeout(TIMEOUT); + + let wallets: AccountWallet[]; + + let teardown: () => Promise; + + beforeAll(async () => { + ({ teardown, pxe, wallets } = await setup(2)); + testContract = await TestContract.deploy(wallets[0]).send().deployed(); + keyRegistry = await KeyRegistryContract.deploy(wallets[0]).send().deployed(); + + await publicDeployAccounts(wallets[0], wallets.slice(0, 2)); + }, 120_000); + + const delay = async (blocks: number) => { + for (let i = 0; i < blocks; i++) { + await testContract.methods.delay().send().wait(); + } + }; + + afterAll(() => teardown()); + + describe('failure cases', () => { + let accountAddedToRegistry: AztecAddress; + + describe('should fail registering with bad input', () => { + const partialAddress = new Fr(69); + + const masterNullifierPublicKey = new Fr(12); + const masterIncomingViewingPublicKey = new Fr(34); + const masterOutgoingViewingPublicKey = new Fr(56); + const masterTaggingPublicKey = new Fr(78); + + // TODO(#5726): use computePublicKeysHash function + const publicKeysHash = poseidon2Hash([ + masterNullifierPublicKey, + masterIncomingViewingPublicKey, + masterOutgoingViewingPublicKey, + masterTaggingPublicKey, + GeneratorIndex.PUBLIC_KEYS_HASH, + ]); + + // We hash the partial address and the public keys hash to get the account address + // TODO(#5726): Move the following line to AztecAddress class? + accountAddedToRegistry = poseidon2Hash([partialAddress, publicKeysHash, GeneratorIndex.CONTRACT_ADDRESS_V1]); + + it('should fail registering with mismatched address', async () => { + const mismatchedAddress = Fr.random(); + + await expect( + keyRegistry + .withWallet(wallets[0]) + .methods.register( + AztecAddress.fromField(mismatchedAddress), + partialAddress, + masterNullifierPublicKey, + masterIncomingViewingPublicKey, + masterOutgoingViewingPublicKey, + masterTaggingPublicKey, + ) + .send() + .wait(), + ).rejects.toThrow('Computed address does not match supplied address'); + }); + + it('should fail registering with mismatched nullifier public key', async () => { + const mismatchedMasterNullifierPublicKey = Fr.random(); + + await expect( + keyRegistry + .withWallet(wallets[0]) + .methods.register( + AztecAddress.fromField(accountAddedToRegistry), + partialAddress, + mismatchedMasterNullifierPublicKey, + masterIncomingViewingPublicKey, + masterOutgoingViewingPublicKey, + masterTaggingPublicKey, + ) + .send() + .wait(), + ).rejects.toThrow('Computed address does not match supplied address'); + }); + }); + + describe('should fail when rotating keys with bad input', () => { + it('should fail when trying to rotate setting a 0 key', async () => { + await expect( + keyRegistry + .withWallet(wallets[0]) + .methods.rotate_nullifier_public_key(wallets[0].getAddress(), new Fr(0)) + .send() + .wait(), + ).rejects.toThrow('New nullifier public key must be non-zero'); + }); + + it('should fail when trying to rotate for another address without authwit', async () => { + await expect( + keyRegistry + .withWallet(wallets[0]) + .methods.rotate_nullifier_public_key(wallets[1].getAddress(), new Fr(2)) + .send() + .wait(), + ).rejects.toThrow('Assertion failed: Message not authorized by account'); + }); + }); + }); + + describe('key registration flow', () => { + let accountAddedToRegistry: AztecAddress; + + it('should generate and register with original keys', async () => { + const partialAddress = new Fr(69); + + const masterNullifierPublicKey = new Fr(12); + const masterIncomingViewingPublicKey = new Fr(34); + const masterOutgoingViewingPublicKey = new Fr(56); + const masterTaggingPublicKey = new Fr(78); + + const publicKeysHash = poseidon2Hash([ + masterNullifierPublicKey, + masterIncomingViewingPublicKey, + masterOutgoingViewingPublicKey, + masterTaggingPublicKey, + GeneratorIndex.PUBLIC_KEYS_HASH, + ]); + + // We hash the partial address and the public keys hash to get the account address + // TODO(#5726): Move the following line to AztecAddress class? + accountAddedToRegistry = poseidon2Hash([partialAddress, publicKeysHash, GeneratorIndex.CONTRACT_ADDRESS_V1]); + + await keyRegistry + .withWallet(wallets[0]) + .methods.register( + AztecAddress.fromField(accountAddedToRegistry), + partialAddress, + masterNullifierPublicKey, + masterIncomingViewingPublicKey, + masterOutgoingViewingPublicKey, + masterTaggingPublicKey, + ) + .send() + .wait(); + }); + + it('checks our registry contract from test contract and fails because the address has not been registered yet', async () => { + const { txHash } = await testContract.methods + .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, accountAddedToRegistry) + .send() + .wait(); + + const rawLogs = await pxe.getUnencryptedLogs({ txHash }); + expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(Fr.ZERO); + }); + + it('checks our registry contract from test contract and finds the address and associated nullifier public key after a delay', async () => { + await delay(5); + + const { txHash } = await testContract.methods + .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, accountAddedToRegistry) + .send() + .wait(); + + const rawLogs = await pxe.getUnencryptedLogs({ txHash }); + + expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(12)); + }); + }); + + describe('key rotation flow', () => { + it('we rotate the nullifier key', async () => { + // This changes + const newMasterNullifierPublicKey = new Fr(910); + + await keyRegistry + .withWallet(wallets[0]) + .methods.rotate_nullifier_public_key(wallets[0].getAddress(), newMasterNullifierPublicKey) + .send() + .wait(); + }); + + it("checks our registry contract from test contract and finds our old public key because the key rotation hasn't been applied yet", async () => { + const { txHash } = await testContract.methods + .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) + .send() + .wait(); + + const rawLogs = await pxe.getUnencryptedLogs({ txHash }); + expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(0)); + }); + + it('checks our registry contract from test contract and finds the new nullifier public key that has been rotated', async () => { + await delay(5); + + const { txHash } = await testContract.methods + .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) + .send() + .wait(); + + const rawLogs = await pxe.getUnencryptedLogs({ txHash }); + + expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(910)); + }); + }); + + describe('key rotation flow with authwit', () => { + it('wallet 0 lets wallet 1 call rotate_nullifier_public_key on his behalf with a pre-defined new public key', async () => { + // This changes + const newMasterNullifierPublicKey = new Fr(420); + + const action = keyRegistry + .withWallet(wallets[1]) + .methods.rotate_nullifier_public_key(wallets[0].getAddress(), newMasterNullifierPublicKey); + + await wallets[0] + .setPublicAuthWit({ caller: wallets[1].getCompleteAddress().address, action }, true) + .send() + .wait(); + + await action.send().wait(); + }); + + it("checks our registry contract from test contract and finds our old public key because the key rotation hasn't been applied yet", async () => { + const { txHash } = await testContract.methods + .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) + .send() + .wait(); + + const rawLogs = await pxe.getUnencryptedLogs({ txHash }); + expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(910)); + }); + + it('checks our registry contract from test contract and finds the new nullifier public key that has been rotated', async () => { + await delay(5); + + const { txHash } = await testContract.methods + .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) + .send() + .wait(); + + const rawLogs = await pxe.getUnencryptedLogs({ txHash }); + + expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(420)); + }); + }); +}); diff --git a/yarn-project/end-to-end/src/e2e_state_vars.test.ts b/yarn-project/end-to-end/src/e2e_state_vars.test.ts index f13ee0bd420..8a6ed6dc23e 100644 --- a/yarn-project/end-to-end/src/e2e_state_vars.test.ts +++ b/yarn-project/end-to-end/src/e2e_state_vars.test.ts @@ -1,5 +1,5 @@ -import { type Wallet } from '@aztec/aztec.js'; -import { DocsExampleContract } from '@aztec/noir-contracts.js'; +import { AztecAddress, Fr, type PXE, type Wallet } from '@aztec/aztec.js'; +import { AuthContract, DocsExampleContract, TestContract } from '@aztec/noir-contracts.js'; import { jest } from '@jest/globals'; @@ -8,6 +8,7 @@ import { setup } from './fixtures/utils.js'; const TIMEOUT = 100_000; describe('e2e_state_vars', () => { + let pxe: PXE; jest.setTimeout(TIMEOUT); let wallet: Wallet; @@ -19,7 +20,7 @@ describe('e2e_state_vars', () => { const RANDOMNESS = 2n; beforeAll(async () => { - ({ teardown, wallet } = await setup()); + ({ teardown, wallet, pxe } = await setup(2)); contract = await DocsExampleContract.deploy(wallet).send().deployed(); }, 30_000); @@ -222,4 +223,53 @@ describe('e2e_state_vars', () => { expect(randomness).toEqual(RANDOMNESS); }); }); + + describe('SharedMutablePrivateGetter', () => { + let authContract: AuthContract; + let testContract: TestContract; + + const delay = async (blocks: number) => { + for (let i = 0; i < blocks; i++) { + await authContract.methods.get_authorized().send().wait(); + } + }; + + beforeAll(async () => { + testContract = await TestContract.deploy(wallet).send().deployed(); + // We use the auth contract here because has a nice, clear, simple implementation of the Shared Mutable, + // and we will need to read from it to test our private getter. + authContract = await AuthContract.deploy(wallet, wallet.getAddress()).send().deployed(); + + // We set the authorized value here, knowing there will be some delay before the value change takes place + await authContract + .withWallet(wallet) + .methods.set_authorized(AztecAddress.fromField(new Fr(6969696969))) + .send() + .wait(); + }, 30_000); + + it("checks authorized in auth contract from test contract and finds the old value because the change hasn't been applied yet", async () => { + const { txHash } = await testContract.methods + .test_shared_mutable_private_getter(authContract.address, 2) + .send() + .wait(); + + // The function above emits an unencrypted log as a means of returning the data + const rawLogs = await pxe.getUnencryptedLogs({ txHash }); + expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(0)); + }); + + it('checks authorized in auth contract from test contract and finds the correctly set value', async () => { + await delay(5); + + const { txHash } = await testContract.methods + .test_shared_mutable_private_getter(authContract.address, 2) + .send() + .wait(); + + // The function above emits an unencrypted log as a means of returning the data + const rawLogs = await pxe.getUnencryptedLogs({ txHash }); + expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(6969696969)); + }); + }); }); diff --git a/yarn-project/tsconfig.json b/yarn-project/tsconfig.json index 95f7ccc5cee..eafb807f772 100644 --- a/yarn-project/tsconfig.json +++ b/yarn-project/tsconfig.json @@ -16,7 +16,7 @@ "resolveJsonModule": true, "composite": true, "skipLibCheck": true, - "noImplicitOverride": true, + "noImplicitOverride": true }, "references": [ { "path": "accounts/tsconfig.json" }, From 6b0f919d83209a83e5d1900942a160424b30fe22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Wed, 17 Apr 2024 17:12:28 -0300 Subject: [PATCH 005/102] test: use new mock.get_last_params() for public storage writes (#5823) This uses the new mock features implemented in https://github.com/noir-lang/noir/pull/4789 to test calls to storage writes. It's not incredibly exciting, but is a nice example of how such an oracle is used and nicely adds to the completeness of the ~`SharedMutable`~`PriblicMutable` tests. --- .../aztec-nr/aztec/src/public_storage.nr | 10 ++-- .../shared_mutable/shared_mutable.nr | 52 ++++++++++++++++--- 2 files changed, 52 insertions(+), 10 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/public_storage.nr b/noir-projects/aztec-nr/aztec/src/public_storage.nr index 7375ab91e5a..d46b2c5ffca 100644 --- a/noir-projects/aztec-nr/aztec/src/public_storage.nr +++ b/noir-projects/aztec-nr/aztec/src/public_storage.nr @@ -61,8 +61,12 @@ mod tests { #[test] fn test_write() { - // Here we'd want to test that what is written to storage is deserialized to the same struct, but the current - // oracle mocks lack these capabilities. - // TODO: implement this once https://github.com/noir-lang/noir/issues/4652 is closed + let slot = 7; + let to_write = TestStruct { a: 13, b: 42 }; + + let mock = OracleMock::mock("storageWrite").returns([0; 2]); // The return value is unused + + public_storage::write(slot, to_write); + assert_eq(mock.get_last_params(), (slot, to_write.serialize())); } } diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable.nr b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable.nr index 63e3a9c05c3..5d327b1f25b 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable.nr @@ -155,7 +155,7 @@ mod test { #[test] fn test_get_current_value_in_public_after_change() { - let (state_var, block_number ) = setup(false); + let (state_var, block_number) = setup(false); let slot = state_var.get_derived_storage_slot(); let (pre, post) = (13, 17); @@ -172,16 +172,54 @@ mod test { let slot = state_var.get_derived_storage_slot(); let (pre, post) = (13, 17); + // Change in the future + OracleMock::mock("storageRead").with_params((slot, 3)).returns([pre, post, block_number + 1]); + + let write_mock = OracleMock::mock("storageWrite").returns([0; 3]); // The oracle return value is actually unused + + let new_value = 42; + state_var.schedule_value_change(new_value); + + // The new scheduled change replaces the old one + assert_eq(write_mock.get_last_params(), (slot, [pre, new_value, block_number + TEST_DELAY])); + } + + #[test] + fn test_schedule_value_change_at_change() { + let (state_var, block_number) = setup(false); + let slot = state_var.get_derived_storage_slot(); + let (pre, post) = (13, 17); - OracleMock::mock("storageRead").with_params((slot, 3)).returns([pre, post, block_number + 1]); + // Change in the current block + OracleMock::mock("storageRead").with_params((slot, 3)).returns([pre, post, block_number]); + + let write_mock = OracleMock::mock("storageWrite").returns([0; 3]); // The oracle return value is actually unused + + let new_value = 42; + state_var.schedule_value_change(new_value); + + // The previous 'post' value is the current one and becomes the 'pre' value + assert_eq(write_mock.get_last_params(), (slot, [post, new_value, block_number + TEST_DELAY])); + } + + #[test] + fn test_schedule_value_change_after_change() { + let (state_var, block_number) = setup(false); + + let slot = state_var.get_derived_storage_slot(); + let (pre, post) = (13, 17); + + // Change in the past + OracleMock::mock("storageRead").with_params((slot, 3)).returns([pre, post, block_number - 1]); + + let write_mock = OracleMock::mock("storageWrite").returns([0; 3]); // The oracle return value is actually unused let new_value = 42; - // Here we want to assert that the `storageWrite` oracle is called with a certain set of values, but the current - // oracle mocks don't have those capabilities. - // TODO: implement this once https://github.com/noir-lang/noir/issues/4652 is closed - // OracleMock::mock("storageWrite").expect_call((slot, [pre, new_value, block_number + DELAY])); - // state_var.schedule_value_change(new_value); + state_var.schedule_value_change(new_value); + + // The previous 'post' value is the current one and becomes the 'pre' value + assert_eq(write_mock.get_last_params(), (slot, [post, new_value, block_number + TEST_DELAY])); } #[test] From 3cf9c2c908b361437050e97fcdf67359727eff8b Mon Sep 17 00:00:00 2001 From: ludamad Date: Wed, 17 Apr 2024 19:50:58 -0400 Subject: [PATCH 006/102] fix: start-spot.yml (#5824) --- .github/workflows/start-spot.yml | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/.github/workflows/start-spot.yml b/.github/workflows/start-spot.yml index 350d6520cd8..f6b532935fa 100644 --- a/.github/workflows/start-spot.yml +++ b/.github/workflows/start-spot.yml @@ -7,24 +7,22 @@ jobs: uses: ./.github/workflows/setup-runner.yml with: runner_label: ${{ github.actor }}-x86 - subaction: stop - # not used: ebs_cache_size_gb: 256 runner_concurrency: 50 + subaction: start ec2_instance_type: m6a.32xlarge - ec2_ami_id: ami-0d8a9b0419ddb331a - ec2_instance_ttl: 40 + ec2_ami_id: ami-04d8422a9ba4de80f + ec2_instance_ttl: 40 # refreshed by jobs secrets: inherit stop-bench: uses: ./.github/workflows/setup-runner.yml with: runner_label: ${{ github.actor }}-bench-x86 - subaction: stop - # not used: ebs_cache_size_gb: 64 runner_concurrency: 1 + subaction: start ec2_instance_type: m6a.4xlarge - ec2_ami_id: ami-0d8a9b0419ddb331a - ec2_instance_ttl: 15 + ec2_ami_id: ami-04d8422a9ba4de80f + ec2_instance_ttl: 15 # refreshed by jobs secrets: inherit From edeea3dfe425b83b36c981dde3ce169e33aaece9 Mon Sep 17 00:00:00 2001 From: Santiago Palladino Date: Thu, 18 Apr 2024 04:34:12 -0300 Subject: [PATCH 007/102] docs: Migration notes for GasOpts in public calls (#5822) --- docs/docs/misc/migration_notes.md | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/docs/docs/misc/migration_notes.md b/docs/docs/misc/migration_notes.md index 5b0a8c0cf29..7ccee0ee58f 100644 --- a/docs/docs/misc/migration_notes.md +++ b/docs/docs/misc/migration_notes.md @@ -18,7 +18,6 @@ It is now possible to import contracts on another contracts and use their automa 4. Arrays become arrays of Fields following rules 2 and 3 5. Structs become arrays of Fields, with every item defined in the same order as they are in Noir code, following rules 2, 3, 4 and 5 (recursive) - ```diff - context.call_public_function( - storage.gas_token_address.read_private(), @@ -36,13 +35,13 @@ It is now possible to import contracts on another contracts and use their automa - storage.subscription_token_address.read_private(), - FunctionSelector::from_signature("transfer((Field),(Field),Field,Field)"), - [ -- context.msg_sender().to_field(), -- storage.subscription_recipient_address.read_private().to_field(), -- storage.subscription_price.read_private(), +- context.msg_sender().to_field(), +- storage.subscription_recipient_address.read_private().to_field(), +- storage.subscription_price.read_private(), - nonce - ] - ); -+ use dep::gas_token::GasToken; ++ use dep::gas_token::GasToken; + use dep::token::Token; + + ... @@ -65,6 +64,21 @@ The `request_max_block_number` function has been renamed to `set_tx_max_block_nu + context.set_tx_max_block_number(value); ``` +### [Aztec.nr] Required gas limits for public-to-public calls + +When calling a public function from another public function using the `call_public_function` method, you must now specify how much gas you're allocating to the nested call. This will later allow you to limit the amount of gas consumed by the nested call, and handle any out of gas errors. + +Note that gas limits are not yet enforced. For now, it is suggested you use `dep::aztec::context::gas::GasOpts::default()` which will forward all available gas. + +```diff ++ use dep::aztec::context::gas::GasOpts; + +- context.call_public_function(target_contract, target_selector, args); ++ context.call_public_function(target_contract, target_selector, args, GasOpts::default()); +``` + +Note that this is not required when enqueuing a public function from a private one, since top-level enqueued public functions will always consume all gas available for the transaction, as it is not possible to handle any out-of-gas errors. + ## 0.33 ### [Aztec.nr] Storage struct annotation From fb7a6175b185725e607d28a8930a15d88f84e117 Mon Sep 17 00:00:00 2001 From: Alex Gherghisan Date: Thu, 18 Apr 2024 12:31:34 +0100 Subject: [PATCH 008/102] fix!: move fixtures to @aztec/circuits.js/testing/fixtures (#5826) Moves circuits.js' fixtures to their own export since they only work in a nodejs environment. --- yarn-project/circuits.js/package.json | 1 + yarn-project/circuits.js/src/tests/index.ts | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/circuits.js/package.json b/yarn-project/circuits.js/package.json index 1c375c3b714..ecb0883e920 100644 --- a/yarn-project/circuits.js/package.json +++ b/yarn-project/circuits.js/package.json @@ -11,6 +11,7 @@ "./hash": "./dest/hash/index.js", "./barretenberg": "./dest/barretenberg/index.js", "./testing": "./dest/tests/index.js", + "./testing/fixtures": "./dest/tests/fixtures.js", "./interfaces": "./dest/interfaces/index.js", "./utils": "./dest/utils/index.js", "./types": "./dest/types/index.js", diff --git a/yarn-project/circuits.js/src/tests/index.ts b/yarn-project/circuits.js/src/tests/index.ts index 4fa91dd0835..e24620a0a23 100644 --- a/yarn-project/circuits.js/src/tests/index.ts +++ b/yarn-project/circuits.js/src/tests/index.ts @@ -1,2 +1 @@ -export * from './fixtures.js'; export * from './factories.js'; From c3dd039e5d2a779cc9bda1c0ac46306563914578 Mon Sep 17 00:00:00 2001 From: Alex Gherghisan Date: Thu, 18 Apr 2024 12:31:59 +0100 Subject: [PATCH 009/102] chore: remove empty yarn.lock (#5835) Removes empty yarn.lock at the root of repo created in error --- yarn.lock | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 yarn.lock diff --git a/yarn.lock b/yarn.lock deleted file mode 100644 index fb57ccd13af..00000000000 --- a/yarn.lock +++ /dev/null @@ -1,4 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - From 9434784b12f5e5402e93596110ee2e131317b251 Mon Sep 17 00:00:00 2001 From: Santiago Palladino Date: Thu, 18 Apr 2024 08:44:42 -0300 Subject: [PATCH 010/102] chore: Remove private kernel snapshot test (#5829) Follows the policy of "remove snapshots that don't provide useful info", and deletes a test suite that not just generated snapshots, but also depended on data generated from e2e tests, which meant that a change in noir-protocol-circuits required a new e2e test run to regenerate snapshots in a unit test of noir-protocol-circuit-types. --- .../src/e2e_nested_contract.test.ts | 32 - .../src/__snapshots__/index.test.ts.snap | 2166 ----------------- .../src/index.test.ts | 52 - 3 files changed, 2250 deletions(-) delete mode 100644 yarn-project/noir-protocol-circuits-types/src/__snapshots__/index.test.ts.snap delete mode 100644 yarn-project/noir-protocol-circuits-types/src/index.test.ts diff --git a/yarn-project/end-to-end/src/e2e_nested_contract.test.ts b/yarn-project/end-to-end/src/e2e_nested_contract.test.ts index 0310b4bbfd1..661978ce75c 100644 --- a/yarn-project/end-to-end/src/e2e_nested_contract.test.ts +++ b/yarn-project/end-to-end/src/e2e_nested_contract.test.ts @@ -1,9 +1,6 @@ import { type AztecAddress, BatchCall, type DebugLogger, Fr, type PXE, type Wallet, toBigIntBE } from '@aztec/aztec.js'; -import { getTestData, isGenerateTestDataEnabled } from '@aztec/foundation/testing'; import { ChildContract, ImportTestContract, ParentContract, TestContract } from '@aztec/noir-contracts.js'; -import { writeFileSync } from 'fs'; - import { setup } from './fixtures/utils.js'; describe('e2e_nested_contract', () => { @@ -34,35 +31,6 @@ describe('e2e_nested_contract', () => { .entry_point(childContract.address, childContract.methods.value.selector) .send() .wait(); - - if (isGenerateTestDataEnabled()) { - { - const privateKernelInputsInit = getTestData('private-kernel-inputs-init'); - const nestedCallPrivateKernelInput = privateKernelInputsInit[0]; - writeFileSync( - '../noir-protocol-circuits-types/src/fixtures/nested-call-private-kernel-init.hex', - nestedCallPrivateKernelInput.toBuffer().toString('hex'), - ); - } - - { - const privateKernelInputsInner = getTestData('private-kernel-inputs-inner'); - const nestedCallPrivateKernelInput = privateKernelInputsInner[privateKernelInputsInner.length - 1]; - writeFileSync( - '../noir-protocol-circuits-types/src/fixtures/nested-call-private-kernel-inner.hex', - nestedCallPrivateKernelInput.toBuffer().toString('hex'), - ); - } - - { - const privateKernelInputsOrdering = getTestData('private-kernel-inputs-ordering'); - const nestedCallPrivateKernelInput = privateKernelInputsOrdering[0]; - writeFileSync( - '../noir-protocol-circuits-types/src/fixtures/nested-call-private-kernel-ordering.hex', - nestedCallPrivateKernelInput.toBuffer().toString('hex'), - ); - } - } }, 100_000); it('fails simulation if calling a function not allowed to be called externally', async () => { diff --git a/yarn-project/noir-protocol-circuits-types/src/__snapshots__/index.test.ts.snap b/yarn-project/noir-protocol-circuits-types/src/__snapshots__/index.test.ts.snap deleted file mode 100644 index 4c0efd45b43..00000000000 --- a/yarn-project/noir-protocol-circuits-types/src/__snapshots__/index.test.ts.snap +++ /dev/null @@ -1,2166 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Private kernel Executes private kernel inner for a nested call 1`] = ` -PrivateKernelCircuitPublicInputs { - "aggregationObject": AggregationObject { - "hasData": false, - "p0": G1AffineElement { - "x": Fq<0x0000000000000000000000000000000000000000000000000000000000000001>, - "y": Fq<0x0000000000000000000000000000000000000000000000000000000000000002>, - }, - "p1": G1AffineElement { - "x": Fq<0x0000000000000000000000000000000000000000000000000000000000000001>, - "y": Fq<0x0000000000000000000000000000000000000000000000000000000000000002>, - }, - "proofWitnessIndices": [ - 3027, - 3028, - 3029, - 3030, - 3031, - 3032, - 3033, - 3034, - 3035, - 3036, - 3037, - 3038, - 3039, - 3040, - 3041, - 3042, - ], - "publicInputs": [], - }, - "constants": CombinedConstantData { - "gasSettings": GasSettings { - "da": DimensionGasSettings { - "gasLimit": 1000000000, - "maxFeePerGas": Fr<0x0000000000000000000000000000000000000000000000000000000000000001>, - "teardownGasLimit": 100000000, - }, - "inclusionFee": Fr<0x0000000000000000000000000000000000000000000000000000000000000001>, - "l1": DimensionGasSettings { - "gasLimit": 1000000000, - "maxFeePerGas": Fr<0x0000000000000000000000000000000000000000000000000000000000000001>, - "teardownGasLimit": 100000000, - }, - "l2": DimensionGasSettings { - "gasLimit": 1000000000, - "maxFeePerGas": Fr<0x0000000000000000000000000000000000000000000000000000000000000001>, - "teardownGasLimit": 100000000, - }, - }, - "historicalHeader": Header { - "contentCommitment": ContentCommitment { - "inHash": Buffer<0x00089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c>, - "outHash": Buffer<0x0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c3>, - "txTreeHeight": Fr<0x0000000000000000000000000000000000000000000000000000000000000001>, - "txsEffectsHash": Buffer<0x007710847c110c9d1d2feb57e05a986dfb30c2d33811a9d05c76c9657af34d07>, - }, - "globalVariables": { - "blockNumber": "0x0000000000000000000000000000000000000000000000000000000000000003", - "chainId": "0x0000000000000000000000000000000000000000000000000000000000007a69", - "coinbase": "0x0000000000000000000000000000000000000000", - "feeRecipient": "0x0000000000000000000000000000000000000000000000000000000000000000", - "gasFees": { - "feePerDaGas": "0x0000000000000000000000000000000000000000000000000000000000000001", - "feePerL1Gas": "0x0000000000000000000000000000000000000000000000000000000000000001", - "feePerL2Gas": "0x0000000000000000000000000000000000000000000000000000000000000001", - }, - "timestamp": "0x00000000000000000000000000000000000000000000000000000000661e94db", - "version": "0x0000000000000000000000000000000000000000000000000000000000000001", - }, - "lastArchive": AppendOnlyTreeSnapshot { - "nextAvailableLeafIndex": 3, - "root": Fr<0x0eed5cdbaafbbc794dbfae12e568d38ba22a9c222066df87fd213f7c5240117e>, - }, - "state": StateReference { - "l1ToL2MessageTree": AppendOnlyTreeSnapshot { - "nextAvailableLeafIndex": 48, - "root": Fr<0x1864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f80>, - }, - "partial": PartialStateReference { - "noteHashTree": AppendOnlyTreeSnapshot { - "nextAvailableLeafIndex": 384, - "root": Fr<0x234676c856daf7c0bf73f0e9a3980387c0a78cceb1be03d3b9542ad31ebfa1d8>, - }, - "nullifierTree": AppendOnlyTreeSnapshot { - "nextAvailableLeafIndex": 512, - "root": Fr<0x00d1d7b14ec97e9e3332c3eb5734202d6e3a0c76b3a7de8a05a857d7c885ae0e>, - }, - "publicDataTree": AppendOnlyTreeSnapshot { - "nextAvailableLeafIndex": 256, - "root": Fr<0x0572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b>, - }, - }, - }, - }, - "txContext": TxContext { - "chainId": Fr<0x0000000000000000000000000000000000000000000000000000000000007a69>, - "isFeePaymentTx": false, - "isRebatePaymentTx": false, - "version": Fr<0x0000000000000000000000000000000000000000000000000000000000000001>, - }, - }, - "end": PrivateAccumulatedData { - "encryptedLogPreimagesLength": Fr<0x000000000000000000000000000000000000000000000000000000000000000c>, - "encryptedLogsHashes": [ - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - ], - "gasUsed": Gas { - "daGas": 0, - "l1Gas": 0, - "l2Gas": 0, - }, - "newL2ToL1Msgs": [ - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - ], - "newNoteHashes": [ - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - ], - "newNullifiers": [ - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x1cbfe3e489299947cef42ee1812ff6b238b856ae13f95437b82ce86f44fe4fb6>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffectLinkedToNoteHash { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - ], - "privateCallStack": [ - CallRequest { - "callerContext": CallerContext { - "msgSender": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - "storageContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - "callerContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - "endSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "hash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "startSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - CallRequest { - "callerContext": CallerContext { - "msgSender": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - "storageContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - "callerContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - "endSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "hash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "startSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - CallRequest { - "callerContext": CallerContext { - "msgSender": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - "storageContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - "callerContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - "endSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "hash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "startSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - CallRequest { - "callerContext": CallerContext { - "msgSender": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - "storageContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - "callerContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - "endSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "hash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "startSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - CallRequest { - "callerContext": CallerContext { - "msgSender": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - "storageContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - "callerContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - "endSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "hash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "startSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - CallRequest { - "callerContext": CallerContext { - "msgSender": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - "storageContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - "callerContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - "endSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "hash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "startSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - CallRequest { - "callerContext": CallerContext { - "msgSender": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - "storageContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - "callerContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - "endSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "hash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "startSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - CallRequest { - "callerContext": CallerContext { - "msgSender": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - "storageContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - "callerContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - "endSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "hash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "startSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - ], - "publicCallStack": [ - CallRequest { - "callerContext": CallerContext { - "msgSender": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - "storageContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - "callerContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - "endSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "hash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "startSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - CallRequest { - "callerContext": CallerContext { - "msgSender": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - "storageContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - "callerContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - "endSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "hash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "startSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - CallRequest { - "callerContext": CallerContext { - "msgSender": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - "storageContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - "callerContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - "endSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "hash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "startSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - CallRequest { - "callerContext": CallerContext { - "msgSender": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - "storageContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - "callerContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - "endSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "hash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "startSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - CallRequest { - "callerContext": CallerContext { - "msgSender": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - "storageContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - "callerContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - "endSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "hash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "startSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - CallRequest { - "callerContext": CallerContext { - "msgSender": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - "storageContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - "callerContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - "endSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "hash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "startSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - CallRequest { - "callerContext": CallerContext { - "msgSender": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - "storageContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - "callerContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - "endSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "hash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "startSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - CallRequest { - "callerContext": CallerContext { - "msgSender": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - "storageContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - "callerContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - "endSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "hash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "startSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - ], - "unencryptedLogPreimagesLength": Fr<0x000000000000000000000000000000000000000000000000000000000000000c>, - "unencryptedLogsHashes": [ - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - ], - }, - "minRevertibleSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000002>, - "validationRequests": ValidationRequests { - "forRollup": RollupValidationRequests { - "maxBlockNumber": MaxBlockNumber { - "isSome": false, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - }, - "noteHashReadRequests": [ - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - SideEffect { - "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - ], - "nullifierKeyValidationRequests": [ - NullifierKeyValidationRequestContext { - "contractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - "publicKey": Point { - "kind": "point", - "x": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "y": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - "secretKey": Fq<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - NullifierKeyValidationRequestContext { - "contractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - "publicKey": Point { - "kind": "point", - "x": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "y": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - "secretKey": Fq<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - NullifierKeyValidationRequestContext { - "contractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - "publicKey": Point { - "kind": "point", - "x": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "y": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - "secretKey": Fq<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - NullifierKeyValidationRequestContext { - "contractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - "publicKey": Point { - "kind": "point", - "x": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "y": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - "secretKey": Fq<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - ], - "nullifierNonExistentReadRequests": [ - ReadRequestContext { - "contractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - "counter": 0, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - ReadRequestContext { - "contractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - "counter": 0, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - ReadRequestContext { - "contractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - "counter": 0, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - ReadRequestContext { - "contractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - "counter": 0, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - ReadRequestContext { - "contractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - "counter": 0, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - ReadRequestContext { - "contractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - "counter": 0, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - ReadRequestContext { - "contractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - "counter": 0, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - ReadRequestContext { - "contractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - "counter": 0, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - ], - "nullifierReadRequests": [ - ReadRequestContext { - "contractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - "counter": 0, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - ReadRequestContext { - "contractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - "counter": 0, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - ReadRequestContext { - "contractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - "counter": 0, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - ReadRequestContext { - "contractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - "counter": 0, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - ReadRequestContext { - "contractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - "counter": 0, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - ReadRequestContext { - "contractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - "counter": 0, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - ReadRequestContext { - "contractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - "counter": 0, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - ReadRequestContext { - "contractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, - "counter": 0, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - ], - "publicDataReads": [ - PublicDataRead { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - PublicDataRead { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - PublicDataRead { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - PublicDataRead { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - PublicDataRead { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - PublicDataRead { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - PublicDataRead { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - PublicDataRead { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - PublicDataRead { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - PublicDataRead { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - PublicDataRead { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - PublicDataRead { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - PublicDataRead { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - PublicDataRead { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - PublicDataRead { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - PublicDataRead { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - PublicDataRead { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - PublicDataRead { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - PublicDataRead { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - PublicDataRead { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - PublicDataRead { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - PublicDataRead { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - PublicDataRead { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - PublicDataRead { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - PublicDataRead { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - PublicDataRead { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - PublicDataRead { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - PublicDataRead { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - PublicDataRead { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - PublicDataRead { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - PublicDataRead { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - PublicDataRead { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - ], - }, -} -`; - -exports[`Private kernel Executes private kernel ordering after a deployment 1`] = ` -PrivateKernelTailCircuitPublicInputs { - "aggregationObject": AggregationObject { - "hasData": false, - "p0": G1AffineElement { - "x": Fq<0x0000000000000000000000000000000000000000000000000000000000000001>, - "y": Fq<0x0000000000000000000000000000000000000000000000000000000000000002>, - }, - "p1": G1AffineElement { - "x": Fq<0x0000000000000000000000000000000000000000000000000000000000000001>, - "y": Fq<0x0000000000000000000000000000000000000000000000000000000000000002>, - }, - "proofWitnessIndices": [ - 3027, - 3028, - 3029, - 3030, - 3031, - 3032, - 3033, - 3034, - 3035, - 3036, - 3037, - 3038, - 3039, - 3040, - 3041, - 3042, - ], - "publicInputs": [], - }, - "constants": CombinedConstantData { - "gasSettings": GasSettings { - "da": DimensionGasSettings { - "gasLimit": 1000000000, - "maxFeePerGas": Fr<0x0000000000000000000000000000000000000000000000000000000000000001>, - "teardownGasLimit": 100000000, - }, - "inclusionFee": Fr<0x0000000000000000000000000000000000000000000000000000000000000001>, - "l1": DimensionGasSettings { - "gasLimit": 1000000000, - "maxFeePerGas": Fr<0x0000000000000000000000000000000000000000000000000000000000000001>, - "teardownGasLimit": 100000000, - }, - "l2": DimensionGasSettings { - "gasLimit": 1000000000, - "maxFeePerGas": Fr<0x0000000000000000000000000000000000000000000000000000000000000001>, - "teardownGasLimit": 100000000, - }, - }, - "historicalHeader": Header { - "contentCommitment": ContentCommitment { - "inHash": Buffer<0x0000000000000000000000000000000000000000000000000000000000000000>, - "outHash": Buffer<0x0000000000000000000000000000000000000000000000000000000000000000>, - "txTreeHeight": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "txsEffectsHash": Buffer<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - "globalVariables": { - "blockNumber": "0x0000000000000000000000000000000000000000000000000000000000000000", - "chainId": "0x0000000000000000000000000000000000000000000000000000000000000000", - "coinbase": "0x0000000000000000000000000000000000000000", - "feeRecipient": "0x0000000000000000000000000000000000000000000000000000000000000000", - "gasFees": { - "feePerDaGas": "0x0000000000000000000000000000000000000000000000000000000000000000", - "feePerL1Gas": "0x0000000000000000000000000000000000000000000000000000000000000000", - "feePerL2Gas": "0x0000000000000000000000000000000000000000000000000000000000000000", - }, - "timestamp": "0x0000000000000000000000000000000000000000000000000000000000000000", - "version": "0x0000000000000000000000000000000000000000000000000000000000000000", - }, - "lastArchive": AppendOnlyTreeSnapshot { - "nextAvailableLeafIndex": 0, - "root": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - "state": StateReference { - "l1ToL2MessageTree": AppendOnlyTreeSnapshot { - "nextAvailableLeafIndex": 0, - "root": Fr<0x1864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f80>, - }, - "partial": PartialStateReference { - "noteHashTree": AppendOnlyTreeSnapshot { - "nextAvailableLeafIndex": 0, - "root": Fr<0x16642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb>, - }, - "nullifierTree": AppendOnlyTreeSnapshot { - "nextAvailableLeafIndex": 128, - "root": Fr<0x0bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278>, - }, - "publicDataTree": AppendOnlyTreeSnapshot { - "nextAvailableLeafIndex": 64, - "root": Fr<0x0572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b>, - }, - }, - }, - }, - "txContext": TxContext { - "chainId": Fr<0x0000000000000000000000000000000000000000000000000000000000007a69>, - "isFeePaymentTx": false, - "isRebatePaymentTx": false, - "version": Fr<0x0000000000000000000000000000000000000000000000000000000000000001>, - }, - }, - "forPublic": undefined, - "forRollup": PartialPrivateTailPublicInputsForRollup { - "end": CombinedAccumulatedData { - "encryptedLogPreimagesLength": Fr<0x000000000000000000000000000000000000000000000000000000000000013c>, - "encryptedLogsHash": Fr<0x0071e599f47dc5bf086c58651ed033ba8cc6a92633997f5170cca8c19acee03b>, - "gasUsed": Gas { - "daGas": 0, - "l1Gas": 0, - "l2Gas": 0, - }, - "newL2ToL1Msgs": [ - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - ], - "newNoteHashes": [ - Fr<0x07cb8cd31632ab31e7c957add2d3a061122405360982009a0e7fb1d5a1488539>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - ], - "newNullifiers": [ - Fr<0x26fd8601b83cf50cefc8fd01a8f4f257818b236b4b05a4d655d1e250617cca47>, - Fr<0x239e2829a14b926fda5538c945938ffb2d69bca6532cf8d9ef8cb03654928c21>, - Fr<0x1ad338c82a5771b8c493d4fdd310e05a947584891295750cc1267bc96bbd0cde>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - ], - "publicDataUpdateRequests": [ - PublicDataUpdateRequest { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - }, - PublicDataUpdateRequest { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - }, - PublicDataUpdateRequest { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - }, - PublicDataUpdateRequest { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - }, - PublicDataUpdateRequest { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - }, - PublicDataUpdateRequest { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - }, - PublicDataUpdateRequest { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - }, - PublicDataUpdateRequest { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - }, - PublicDataUpdateRequest { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - }, - PublicDataUpdateRequest { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - }, - PublicDataUpdateRequest { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - }, - PublicDataUpdateRequest { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - }, - PublicDataUpdateRequest { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - }, - PublicDataUpdateRequest { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - }, - PublicDataUpdateRequest { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - }, - PublicDataUpdateRequest { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - }, - PublicDataUpdateRequest { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - }, - PublicDataUpdateRequest { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - }, - PublicDataUpdateRequest { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - }, - PublicDataUpdateRequest { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - }, - PublicDataUpdateRequest { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - }, - PublicDataUpdateRequest { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - }, - PublicDataUpdateRequest { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - }, - PublicDataUpdateRequest { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - }, - PublicDataUpdateRequest { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - }, - PublicDataUpdateRequest { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - }, - PublicDataUpdateRequest { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - }, - PublicDataUpdateRequest { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - }, - PublicDataUpdateRequest { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - }, - PublicDataUpdateRequest { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - }, - PublicDataUpdateRequest { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - }, - PublicDataUpdateRequest { - "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "sideEffectCounter": undefined, - }, - ], - "unencryptedLogPreimagesLength": Fr<0x0000000000000000000000000000000000000000000000000000000000000008>, - "unencryptedLogsHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - "rollupValidationRequests": RollupValidationRequests { - "maxBlockNumber": MaxBlockNumber { - "isSome": false, - "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - }, - }, - "revertCode": RevertCode { - "code": 0, - }, -} -`; diff --git a/yarn-project/noir-protocol-circuits-types/src/index.test.ts b/yarn-project/noir-protocol-circuits-types/src/index.test.ts deleted file mode 100644 index 6f7b32e0c13..00000000000 --- a/yarn-project/noir-protocol-circuits-types/src/index.test.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { PrivateKernelInnerCircuitPrivateInputs, PrivateKernelTailCircuitPrivateInputs } from '@aztec/circuits.js'; -import { type DebugLogger, createDebugLogger } from '@aztec/foundation/log'; -import { setupCustomSnapshotSerializers } from '@aztec/foundation/testing'; -import { fileURLToPath } from '@aztec/foundation/url'; - -import { readFileSync } from 'fs'; -import { dirname, resolve } from 'path'; - -import { executeInner, executeTail } from './index.js'; - -describe('Private kernel', () => { - let logger: DebugLogger; - - beforeAll(() => { - setupCustomSnapshotSerializers(expect); - logger = createDebugLogger('noir-private-kernel'); - }); - - // Taken from e2e_nested_contract => performs nested calls => last inner - // To regenerate fixture data run the following on the yarn-project/e2e folder - // AZTEC_GENERATE_TEST_DATA=1 yarn test e2e_nested_contract -t 'performs nested calls' - it('Executes private kernel inner for a nested call', async () => { - logger.info('Initialized Noir instance with private kernel init circuit'); - - const filepath = resolve( - dirname(fileURLToPath(import.meta.url)), - './fixtures/nested-call-private-kernel-inner.hex', - ); - const serialized = Buffer.from(readFileSync(filepath).toString(), 'hex'); - const kernelInputs = PrivateKernelInnerCircuitPrivateInputs.fromBuffer(serialized); - - const kernelOutputs = await executeInner(kernelInputs); - - expect(kernelOutputs).toMatchSnapshot(); - }); - - // Taken from e2e_nested_contract => performs nested calls => first ordering - // To regenerate fixture data run the following on the yarn-project/e2e folder - // AZTEC_GENERATE_TEST_DATA=1 yarn test e2e_nested_contract -t 'performs nested calls' - it('Executes private kernel ordering after a deployment', async () => { - const filepath = resolve( - dirname(fileURLToPath(import.meta.url)), - './fixtures/nested-call-private-kernel-ordering.hex', - ); - const serialized = Buffer.from(readFileSync(filepath).toString(), 'hex'); - const kernelInputs = PrivateKernelTailCircuitPrivateInputs.fromBuffer(serialized); - - const kernelOutputs = await executeTail(kernelInputs); - - expect(kernelOutputs).toMatchSnapshot(); - }); -}); From 834067f12b07a36b9348a368b83d61d789c5c22b Mon Sep 17 00:00:00 2001 From: Facundo Date: Thu, 18 Apr 2024 13:07:55 +0100 Subject: [PATCH 011/102] chore: replace use of PublicContext with interface (#5840) Towards AVM migrations. --- .../noir-contracts/contracts/fpc_contract/src/fee.nr | 4 ++-- .../noir-contracts/contracts/gas_token_contract/src/lib.nr | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/noir-projects/noir-contracts/contracts/fpc_contract/src/fee.nr b/noir-projects/noir-contracts/contracts/fpc_contract/src/fee.nr index 84f6bdcee04..17a4ae012e7 100644 --- a/noir-projects/noir-contracts/contracts/fpc_contract/src/fee.nr +++ b/noir-projects/noir-contracts/contracts/fpc_contract/src/fee.nr @@ -1,5 +1,5 @@ -use dep::aztec::context::PublicContext; +use dep::aztec::context::interface::PublicContextInterface; -pub fn calculate_fee(_context: PublicContext) -> U128 { +pub fn calculate_fee(_context: TPublicContext) -> U128 where TPublicContext: PublicContextInterface { U128::from_integer(1) } diff --git a/noir-projects/noir-contracts/contracts/gas_token_contract/src/lib.nr b/noir-projects/noir-contracts/contracts/gas_token_contract/src/lib.nr index dc2a42daf39..9e1afebac29 100644 --- a/noir-projects/noir-contracts/contracts/gas_token_contract/src/lib.nr +++ b/noir-projects/noir-contracts/contracts/gas_token_contract/src/lib.nr @@ -1,9 +1,8 @@ use dep::aztec::prelude::{AztecAddress, EthAddress}; -use dep::aztec::context::PublicContext; +use dep::aztec::context::interface::PublicContextInterface; use dep::aztec::protocol_types::hash::sha256_to_field; -pub fn calculate_fee(_context: PublicContext) -> U128 { - // TODO(palla/gas-in-circuits): Use the transaction_fee injected into the context +pub fn calculate_fee(_context: TPublicContext) -> U128 where TPublicContext: PublicContextInterface { U128::from_integer(1) } From cb1e25b8c6f203d8a7e4beb2f027d72bee981695 Mon Sep 17 00:00:00 2001 From: Facundo Date: Thu, 18 Apr 2024 13:51:36 +0100 Subject: [PATCH 012/102] chore: allow expressions in constant generation (#5839) Noir supports expressions in constants, so now we can leverage that. Changes * Moved note-related constants to the `note` crate because they were only used there. * Updated all possible structs to use expressions for their lengths. --- .../references/storage/private_state.md | 2 +- .../src/core/libraries/ConstantsGen.sol | 55 ++++++++++----- noir-projects/aztec-nr/aztec/src/note.nr | 1 + .../aztec-nr/aztec/src/note/constants.nr | 6 ++ .../aztec-nr/aztec/src/note/note_getter.nr | 8 +-- .../aztec/src/note/note_viewer_options.nr | 3 +- .../oracle/get_l1_to_l2_membership_witness.nr | 4 +- .../aztec/src/state_vars/private_set.nr | 3 +- .../contracts/card_game_contract/src/cards.nr | 5 +- .../contracts/card_game_contract/src/main.nr | 4 +- .../contracts/test_contract/src/main.nr | 4 +- .../src/abis/private_circuit_public_inputs.nr | 16 ++--- .../src/abis/public_circuit_public_inputs.nr | 2 +- .../crates/types/src/abis/read_request.nr | 12 ++-- .../crates/types/src/abis/side_effect.nr | 23 +++---- .../crates/types/src/constants.nr | 60 ++++++---------- .../src/contrakt/storage_update_request.nr | 2 +- yarn-project/circuits.js/src/constants.gen.ts | 68 ++++++++++++++----- .../circuits.js/src/scripts/constants.in.ts | 2 +- 19 files changed, 166 insertions(+), 114 deletions(-) create mode 100644 noir-projects/aztec-nr/aztec/src/note/constants.nr diff --git a/docs/docs/developers/contracts/references/storage/private_state.md b/docs/docs/developers/contracts/references/storage/private_state.md index dd82a21a02c..6215902d3ef 100644 --- a/docs/docs/developers/contracts/references/storage/private_state.md +++ b/docs/docs/developers/contracts/references/storage/private_state.md @@ -240,7 +240,7 @@ Functionally similar to [`get_notes`](#get_notes), but executed unconstrained an #include_code view_notes /noir-projects/aztec-nr/value-note/src/balance_utils.nr rust -There's also a limit on the maximum number of notes that can be returned in one go. To find the current limit, refer to [this file](https://github.com/AztecProtocol/aztec-packages/blob/#include_aztec_version/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr) and look for `MAX_NOTES_PER_PAGE`. +There's also a limit on the maximum number of notes that can be returned in one go. To find the current limit, refer to [this file](https://github.com/AztecProtocol/aztec-packages/blob/#include_aztec_version/noir-projects/aztec-nr/aztec/src/note/constants.nr) and look for `MAX_NOTES_PER_PAGE`. The key distinction is that this method is unconstrained. It does not perform a check to verify if the notes actually exist, which is something the [`get_notes`](#get_notes) method does under the hood. Therefore, it should only be used in an unconstrained contract function. diff --git a/l1-contracts/src/core/libraries/ConstantsGen.sol b/l1-contracts/src/core/libraries/ConstantsGen.sol index ea4ec9cca1c..6661fc67443 100644 --- a/l1-contracts/src/core/libraries/ConstantsGen.sol +++ b/l1-contracts/src/core/libraries/ConstantsGen.sol @@ -70,9 +70,10 @@ library Constants { uint256 internal constant FUNCTION_SELECTOR_NUM_BYTES = 4; uint256 internal constant ARGS_HASH_CHUNK_LENGTH = 64; uint256 internal constant ARGS_HASH_CHUNK_COUNT = 64; + uint256 internal constant MAX_ARGS_LENGTH = ARGS_HASH_CHUNK_COUNT * ARGS_HASH_CHUNK_LENGTH; uint256 internal constant INITIALIZATION_SLOT_SEPARATOR = 1000_000_000; uint256 internal constant INITIAL_L2_BLOCK_NUM = 1; - uint256 internal constant BLOB_SIZE_IN_BYTES = 126976; + uint256 internal constant BLOB_SIZE_IN_BYTES = 31 * 4096; uint256 internal constant NESTED_CALL_L2_GAS_BUFFER = 20000; uint256 internal constant MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS = 16200; uint256 internal constant MAX_PACKED_BYTECODE_SIZE_PER_PRIVATE_FUNCTION_IN_FIELDS = 3000; @@ -89,17 +90,12 @@ library Constants { 0x85864497636cf755ae7bde03f267ce01a520981c21c3682aaf82a631; uint256 internal constant DEPLOYER_CONTRACT_ADDRESS = 0x1b5ecf3d26907648cf737f4304759b8c5850478e839e72f8ce1f5791b286e8f2; - uint256 internal constant L1_TO_L2_MESSAGE_ORACLE_CALL_LENGTH = 17; - uint256 internal constant MAX_NOTE_FIELDS_LENGTH = 20; - uint256 internal constant GET_NOTE_ORACLE_RETURN_LENGTH = 23; - uint256 internal constant MAX_NOTES_PER_PAGE = 10; - uint256 internal constant VIEW_NOTE_ORACLE_RETURN_LENGTH = 212; uint256 internal constant AZTEC_ADDRESS_LENGTH = 1; - uint256 internal constant CALL_CONTEXT_LENGTH = 21; - uint256 internal constant GAS_SETTINGS_LENGTH = 10; uint256 internal constant DIMENSION_GAS_SETTINGS_LENGTH = 3; uint256 internal constant GAS_FEES_LENGTH = 3; uint256 internal constant GAS_LENGTH = 3; + uint256 internal constant GAS_SETTINGS_LENGTH = 1 + 3 * DIMENSION_GAS_SETTINGS_LENGTH; + uint256 internal constant CALL_CONTEXT_LENGTH = 8 + GAS_SETTINGS_LENGTH + GAS_LENGTH; uint256 internal constant CONTENT_COMMITMENT_LENGTH = 4; uint256 internal constant CONTRACT_INSTANCE_LENGTH = 6; uint256 internal constant CONTRACT_STORAGE_READ_LENGTH = 2; @@ -107,21 +103,48 @@ library Constants { uint256 internal constant ETH_ADDRESS_LENGTH = 1; uint256 internal constant FUNCTION_DATA_LENGTH = 2; uint256 internal constant FUNCTION_LEAF_PREIMAGE_LENGTH = 5; - uint256 internal constant GLOBAL_VARIABLES_LENGTH = 9; - uint256 internal constant HEADER_LENGTH = 23; + uint256 internal constant GLOBAL_VARIABLES_LENGTH = 6 + GAS_FEES_LENGTH; + uint256 internal constant APPEND_ONLY_TREE_SNAPSHOT_LENGTH = 2; uint256 internal constant L1_TO_L2_MESSAGE_LENGTH = 6; uint256 internal constant L2_TO_L1_MESSAGE_LENGTH = 2; uint256 internal constant MAX_BLOCK_NUMBER_LENGTH = 2; uint256 internal constant NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH = 4; uint256 internal constant NULLIFIER_KEY_VALIDATION_REQUEST_CONTEXT_LENGTH = 5; uint256 internal constant PARTIAL_STATE_REFERENCE_LENGTH = 6; - uint256 internal constant PRIVATE_CALL_STACK_ITEM_LENGTH = 238; - uint256 internal constant PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH = 235; - uint256 internal constant PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH = 222; - uint256 internal constant STATE_REFERENCE_LENGTH = 8; + uint256 internal constant READ_REQUEST_LENGTH = 2; + uint256 internal constant SIDE_EFFECT_LENGTH = 2; + uint256 internal constant SIDE_EFFECT_LINKED_TO_NOTE_HASH_LENGTH = 3; + uint256 internal constant STATE_REFERENCE_LENGTH = + APPEND_ONLY_TREE_SNAPSHOT_LENGTH + PARTIAL_STATE_REFERENCE_LENGTH; uint256 internal constant TX_CONTEXT_DATA_LENGTH = 4; - uint256 internal constant TX_REQUEST_LENGTH = 18; - uint256 internal constant ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH = 25; + uint256 internal constant TX_REQUEST_LENGTH = + 2 + TX_CONTEXT_DATA_LENGTH + FUNCTION_DATA_LENGTH + GAS_SETTINGS_LENGTH; + uint256 internal constant HEADER_LENGTH = APPEND_ONLY_TREE_SNAPSHOT_LENGTH + + CONTENT_COMMITMENT_LENGTH + STATE_REFERENCE_LENGTH + GLOBAL_VARIABLES_LENGTH; + uint256 internal constant PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH = CALL_CONTEXT_LENGTH + 3 + + MAX_BLOCK_NUMBER_LENGTH + (SIDE_EFFECT_LENGTH * MAX_NOTE_HASH_READ_REQUESTS_PER_CALL) + + (READ_REQUEST_LENGTH * MAX_NULLIFIER_READ_REQUESTS_PER_CALL) + + (NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH * MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL) + + (SIDE_EFFECT_LENGTH * MAX_NEW_NOTE_HASHES_PER_CALL) + + (SIDE_EFFECT_LINKED_TO_NOTE_HASH_LENGTH * MAX_NEW_NULLIFIERS_PER_CALL) + + MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL + + (L2_TO_L1_MESSAGE_LENGTH * MAX_NEW_L2_TO_L1_MSGS_PER_CALL) + 2 + + (SIDE_EFFECT_LENGTH * MAX_ENCRYPTED_LOGS_PER_CALL) + + (SIDE_EFFECT_LENGTH * MAX_UNENCRYPTED_LOGS_PER_CALL) + 2 + HEADER_LENGTH + 2; + uint256 internal constant PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH = CALL_CONTEXT_LENGTH + 2 + + (READ_REQUEST_LENGTH * MAX_NULLIFIER_READ_REQUESTS_PER_CALL) + + (READ_REQUEST_LENGTH * MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL) + + (CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH * MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL) + + (CONTRACT_STORAGE_READ_LENGTH * MAX_PUBLIC_DATA_READS_PER_CALL) + + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL + (SIDE_EFFECT_LENGTH * MAX_NEW_NOTE_HASHES_PER_CALL) + + (SIDE_EFFECT_LINKED_TO_NOTE_HASH_LENGTH * MAX_NEW_NULLIFIERS_PER_CALL) + + (L2_TO_L1_MESSAGE_LENGTH * MAX_NEW_L2_TO_L1_MSGS_PER_CALL) + 2 + + (SIDE_EFFECT_LENGTH * MAX_UNENCRYPTED_LOGS_PER_CALL) + 1 + HEADER_LENGTH + AZTEC_ADDRESS_LENGTH /* revert_code */ + + 1 + GAS_LENGTH; + uint256 internal constant PRIVATE_CALL_STACK_ITEM_LENGTH = + AZTEC_ADDRESS_LENGTH + FUNCTION_DATA_LENGTH + PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH; + uint256 internal constant ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH = + 2 + FUNCTION_DATA_LENGTH + CALL_CONTEXT_LENGTH; uint256 internal constant GET_NOTES_ORACLE_RETURN_LENGTH = 674; uint256 internal constant NOTE_HASHES_NUM_BYTES_PER_BASE_ROLLUP = 2048; uint256 internal constant NULLIFIERS_NUM_BYTES_PER_BASE_ROLLUP = 2048; diff --git a/noir-projects/aztec-nr/aztec/src/note.nr b/noir-projects/aztec-nr/aztec/src/note.nr index b457a126b2d..6479366face 100644 --- a/noir-projects/aztec-nr/aztec/src/note.nr +++ b/noir-projects/aztec-nr/aztec/src/note.nr @@ -1,3 +1,4 @@ +mod constants; mod lifecycle; mod note_getter; mod note_getter_options; diff --git a/noir-projects/aztec-nr/aztec/src/note/constants.nr b/noir-projects/aztec-nr/aztec/src/note/constants.nr new file mode 100644 index 00000000000..66a404c1b3d --- /dev/null +++ b/noir-projects/aztec-nr/aztec/src/note/constants.nr @@ -0,0 +1,6 @@ +global MAX_NOTE_FIELDS_LENGTH: u64 = 20; +// The plus 1 is 1 extra field for nonce. +// + 2 for EXTRA_DATA: [number_of_return_notes, contract_address] +global GET_NOTE_ORACLE_RETURN_LENGTH: u64 = MAX_NOTE_FIELDS_LENGTH + 1 + 2; +global MAX_NOTES_PER_PAGE: u64 = 10; +global VIEW_NOTE_ORACLE_RETURN_LENGTH: u64 = MAX_NOTES_PER_PAGE * (MAX_NOTE_FIELDS_LENGTH + 1) + 2; \ No newline at end of file diff --git a/noir-projects/aztec-nr/aztec/src/note/note_getter.nr b/noir-projects/aztec-nr/aztec/src/note/note_getter.nr index 2829583ccab..21fa5ad1530 100644 --- a/noir-projects/aztec-nr/aztec/src/note/note_getter.nr +++ b/noir-projects/aztec-nr/aztec/src/note/note_getter.nr @@ -1,11 +1,7 @@ -use dep::protocol_types::{ - constants::{ - MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, GET_NOTE_ORACLE_RETURN_LENGTH, GET_NOTES_ORACLE_RETURN_LENGTH, - MAX_NOTES_PER_PAGE, VIEW_NOTE_ORACLE_RETURN_LENGTH -} -}; +use dep::protocol_types::{constants::{MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, GET_NOTES_ORACLE_RETURN_LENGTH}}; use crate::context::PrivateContext; use crate::note::{ + constants::{GET_NOTE_ORACLE_RETURN_LENGTH, MAX_NOTES_PER_PAGE, VIEW_NOTE_ORACLE_RETURN_LENGTH}, note_getter_options::{NoteGetterOptions, Select, Sort, SortOrder, Comparator, NoteStatus, PropertySelector}, note_interface::NoteInterface, note_viewer_options::NoteViewerOptions, utils::compute_note_hash_for_consumption diff --git a/noir-projects/aztec-nr/aztec/src/note/note_viewer_options.nr b/noir-projects/aztec-nr/aztec/src/note/note_viewer_options.nr index eeed1ddac84..c2bd2002cca 100644 --- a/noir-projects/aztec-nr/aztec/src/note/note_viewer_options.nr +++ b/noir-projects/aztec-nr/aztec/src/note/note_viewer_options.nr @@ -1,7 +1,8 @@ use dep::std::option::Option; use crate::note::note_getter_options::{PropertySelector, Select, Sort, Comparator, NoteStatus}; -use dep::protocol_types::{constants::MAX_NOTES_PER_PAGE, traits::ToField}; +use dep::protocol_types::traits::ToField; use crate::note::note_interface::NoteInterface; +use crate::note::constants::MAX_NOTES_PER_PAGE; // docs:start:NoteViewerOptions struct NoteViewerOptions { diff --git a/noir-projects/aztec-nr/aztec/src/oracle/get_l1_to_l2_membership_witness.nr b/noir-projects/aztec-nr/aztec/src/oracle/get_l1_to_l2_membership_witness.nr index e1f61401b17..55adcae73a1 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/get_l1_to_l2_membership_witness.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/get_l1_to_l2_membership_witness.nr @@ -1,4 +1,6 @@ -use dep::protocol_types::{address::AztecAddress, constants::L1_TO_L2_MESSAGE_ORACLE_CALL_LENGTH}; +use dep::protocol_types::{address::AztecAddress}; + +global L1_TO_L2_MESSAGE_ORACLE_CALL_LENGTH: u64 = 17; // Obtains membership witness (index and sibling path) for a message in the L1 to L2 message tree. #[oracle(getL1ToL2MembershipWitness)] diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/private_set.nr b/noir-projects/aztec-nr/aztec/src/state_vars/private_set.nr index b72b405d197..c48e9b3708f 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/private_set.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/private_set.nr @@ -1,9 +1,10 @@ use dep::protocol_types::{ - constants::{MAX_NOTES_PER_PAGE, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL}, + constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, abis::side_effect::{SideEffect, SideEffectLinkedToNoteHash} }; use crate::context::{PrivateContext, PublicContext, Context}; use crate::note::{ + constants::MAX_NOTES_PER_PAGE, lifecycle::{create_note, create_note_hash_from_public, destroy_note}, note_getter::{get_notes, view_notes}, note_getter_options::NoteGetterOptions, note_header::NoteHeader, note_interface::NoteInterface, note_viewer_options::NoteViewerOptions, diff --git a/noir-projects/noir-contracts/contracts/card_game_contract/src/cards.nr b/noir-projects/noir-contracts/contracts/card_game_contract/src/cards.nr index ccad0898f9a..51f914b567a 100644 --- a/noir-projects/noir-contracts/contracts/card_game_contract/src/cards.nr +++ b/noir-projects/noir-contracts/contracts/card_game_contract/src/cards.nr @@ -3,9 +3,10 @@ use dep::aztec::prelude::{AztecAddress, FunctionSelector, PrivateContext, NoteHe use dep::aztec::{ protocol_types::{ traits::{ToField, Serialize, FromField}, - constants::{MAX_NOTES_PER_PAGE, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL} + constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, }, - context::{PublicContext, Context}, note::note_getter::view_notes, state_vars::PrivateSet + context::{PublicContext, Context}, note::note_getter::view_notes, state_vars::PrivateSet, + note::constants::MAX_NOTES_PER_PAGE, }; use dep::std; use dep::std::{option::Option}; diff --git a/noir-projects/noir-contracts/contracts/card_game_contract/src/main.nr b/noir-projects/noir-contracts/contracts/card_game_contract/src/main.nr index d4416eff7cd..fb37c121fcb 100644 --- a/noir-projects/noir-contracts/contracts/card_game_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/card_game_contract/src/main.nr @@ -2,12 +2,12 @@ mod cards; mod game; contract CardGame { - use dep::aztec::protocol_types::{abis::function_selector::FunctionSelector, address::AztecAddress, constants::MAX_NOTES_PER_PAGE}; + use dep::aztec::protocol_types::{abis::function_selector::FunctionSelector, address::AztecAddress}; use dep::aztec::{context::Context, hash::pedersen_hash, state_vars::{Map, PublicMutable}}; use dep::value_note::{balance_utils, value_note::{ValueNote, VALUE_NOTE_LEN}}; - use dep::aztec::note::note_header::NoteHeader; + use dep::aztec::note::{note_header::NoteHeader, constants::MAX_NOTES_PER_PAGE}; use crate::cards::{PACK_CARDS, Deck, Card, get_pack_cards, compute_deck_strength}; use crate::game::{NUMBER_OF_PLAYERS, NUMBER_OF_CARDS_DECK, PLAYABLE_CARDS, PlayerEntry, Game, GAME_SERIALIZED_LEN}; diff --git a/noir-projects/noir-contracts/contracts/test_contract/src/main.nr b/noir-projects/noir-contracts/contracts/test_contract/src/main.nr index 92e8ad6490c..851b8e59ee6 100644 --- a/noir-projects/noir-contracts/contracts/test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/test_contract/src/main.nr @@ -7,9 +7,11 @@ contract Test { use dep::aztec::protocol_types::{ abis::private_circuit_public_inputs::PrivateCircuitPublicInputs, - constants::{MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NOTES_PER_PAGE}, traits::Serialize + constants::{MAX_NOTE_HASH_READ_REQUESTS_PER_CALL}, traits::Serialize }; + use dep::aztec::note::constants::MAX_NOTES_PER_PAGE; + use dep::aztec::state_vars::shared_mutable::SharedMutablePrivateGetter; // docs:start:unencrypted_import diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr index 0e49b29d76d..09fbc60463e 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr @@ -93,32 +93,32 @@ impl Serialize for PrivateCircuitPublicInp fields.extend_from_array(self.max_block_number.serialize()); - for i in 0..MAX_NOTE_HASH_READ_REQUESTS_PER_CALL{ + for i in 0..self.note_hash_read_requests.len() { fields.extend_from_array(self.note_hash_read_requests[i].serialize()); } - for i in 0..MAX_NULLIFIER_READ_REQUESTS_PER_CALL{ + for i in 0..self.nullifier_read_requests.len() { fields.extend_from_array(self.nullifier_read_requests[i].serialize()); } - for i in 0..MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL{ + for i in 0..self.nullifier_key_validation_requests.len() { fields.extend_from_array(self.nullifier_key_validation_requests[i].serialize()); } - for i in 0..MAX_NEW_NOTE_HASHES_PER_CALL{ + for i in 0..self.new_note_hashes.len() { fields.extend_from_array(self.new_note_hashes[i].serialize()); } - for i in 0..MAX_NEW_NULLIFIERS_PER_CALL{ + for i in 0..self.new_nullifiers.len() { fields.extend_from_array(self.new_nullifiers[i].serialize()); } fields.extend_from_array(self.private_call_stack_hashes); fields.extend_from_array(self.public_call_stack_hashes); - for i in 0..MAX_NEW_L2_TO_L1_MSGS_PER_CALL { + for i in 0..self.new_l2_to_l1_msgs.len() { fields.extend_from_array(self.new_l2_to_l1_msgs[i].serialize()); } fields.push(self.start_side_effect_counter as Field); fields.push(self.end_side_effect_counter as Field); - for i in 0..MAX_ENCRYPTED_LOGS_PER_CALL{ + for i in 0..self.encrypted_logs_hashes.len() { fields.extend_from_array(self.encrypted_logs_hashes[i].serialize()); } - for i in 0..MAX_UNENCRYPTED_LOGS_PER_CALL{ + for i in 0..self.unencrypted_logs_hashes.len() { fields.extend_from_array(self.unencrypted_logs_hashes[i].serialize()); } fields.push(self.encrypted_log_preimages_length); diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_circuit_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_circuit_public_inputs.nr index 6ac77bcc55d..ca5dc4742f3 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_circuit_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_circuit_public_inputs.nr @@ -17,7 +17,7 @@ use crate::{ traits::{Hash, Serialize, Deserialize, Empty}, utils::reader::Reader }; -struct PublicCircuitPublicInputs{ +struct PublicCircuitPublicInputs { call_context: CallContext, args_hash: Field, diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/read_request.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/read_request.nr index 1d6acb753f1..1a1e221405c 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/read_request.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/read_request.nr @@ -1,10 +1,10 @@ use crate::{ abis::side_effect::{OrderedValue, ContractScopedOrderedValue}, - traits::{Empty, Serialize, Deserialize}, address::AztecAddress + traits::{Empty, Serialize, Deserialize}, address::AztecAddress, + constants::READ_REQUEST_LENGTH, }; use dep::std::cmp::Eq; -global READ_REQUEST_SERIALIZED_LEN = 2; global READ_REQUEST_CONTEXT_SERIALIZED_LEN = 3; struct ReadRequest { @@ -37,14 +37,14 @@ impl Empty for ReadRequest { } } -impl Serialize for ReadRequest { - fn serialize(self) -> [Field; READ_REQUEST_SERIALIZED_LEN] { +impl Serialize for ReadRequest { + fn serialize(self) -> [Field; READ_REQUEST_LENGTH] { [self.value, self.counter as Field] } } -impl Deserialize for ReadRequest { - fn deserialize(values: [Field; READ_REQUEST_SERIALIZED_LEN]) -> Self { +impl Deserialize for ReadRequest { + fn deserialize(values: [Field; READ_REQUEST_LENGTH]) -> Self { Self { value: values[0], counter: values[1] as u32, diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/side_effect.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/side_effect.nr index d7e4cca3fe8..63448cc0ebe 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/side_effect.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/side_effect.nr @@ -1,11 +1,10 @@ use crate::{ address::AztecAddress, constants::GENERATOR_INDEX__SIDE_EFFECT, - traits::{Empty, Hash, Serialize, Deserialize} + traits::{Empty, Hash, Serialize, Deserialize}, + constants::{SIDE_EFFECT_LENGTH, SIDE_EFFECT_LINKED_TO_NOTE_HASH_LENGTH}, }; use dep::std::cmp::Eq; -global SIDE_EFFECT_SERIALIZED_LEN = 2; - trait Ordered { fn counter(self) -> u32; } @@ -64,14 +63,14 @@ impl Hash for SideEffect { } } -impl Serialize for SideEffect { - fn serialize(self) -> [Field; SIDE_EFFECT_SERIALIZED_LEN] { +impl Serialize for SideEffect { + fn serialize(self) -> [Field; SIDE_EFFECT_LENGTH] { [self.value, self.counter as Field] } } -impl Deserialize for SideEffect { - fn deserialize(values: [Field; SIDE_EFFECT_SERIALIZED_LEN]) -> Self { +impl Deserialize for SideEffect { + fn deserialize(values: [Field; SIDE_EFFECT_LENGTH]) -> Self { Self { value: values[0], counter: values[1] as u32, @@ -79,7 +78,7 @@ impl Deserialize for SideEffect { } } -struct SideEffectLinkedToNoteHash{ +struct SideEffectLinkedToNoteHash { value: Field, note_hash: Field, counter: u32, @@ -126,14 +125,14 @@ impl Hash for SideEffectLinkedToNoteHash { } } -impl Serialize<3> for SideEffectLinkedToNoteHash { - fn serialize(self) -> [Field; 3] { +impl Serialize for SideEffectLinkedToNoteHash { + fn serialize(self) -> [Field; SIDE_EFFECT_LINKED_TO_NOTE_HASH_LENGTH] { [self.value, self.note_hash, self.counter as Field] } } -impl Deserialize<3> for SideEffectLinkedToNoteHash { - fn deserialize(values: [Field; 3]) -> Self { +impl Deserialize for SideEffectLinkedToNoteHash { + fn deserialize(values: [Field; SIDE_EFFECT_LINKED_TO_NOTE_HASH_LENGTH]) -> Self { Self { value: values[0], note_hash: values[1], diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr index 4d040a0db25..e8e5f1cf2ee 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr @@ -33,12 +33,8 @@ global MAX_NOTE_HASH_READ_REQUESTS_PER_CALL: u64 = 32; global MAX_NULLIFIER_READ_REQUESTS_PER_CALL: u64 = 2; // Change it to a larger value when there's a seperate reset circuit. global MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL: u64 = 2; global MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL: u64 = 1; -// Note: if changing enc logs per call value by n, change PRIVATE_CALL_STACK_ITEM_LENGTH and PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH by 2n -// and change DEPLOYER_CONTRACT_ADDRESS to new value -global MAX_ENCRYPTED_LOGS_PER_CALL: u64 = 4; -// Note: if changing unenc logs per call value by n, change PRIVATE_CALL_STACK_ITEM_LENGTH, PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH, and PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH by 2n -// and change DEPLOYER_CONTRACT_ADDRESS to new value -global MAX_UNENCRYPTED_LOGS_PER_CALL: u64 = 4; +global MAX_ENCRYPTED_LOGS_PER_CALL: u64 = 4; // If modifying, update DEPLOYER_CONTRACT_ADDRESS. +global MAX_UNENCRYPTED_LOGS_PER_CALL: u64 = 4; // If modifying, update DEPLOYER_CONTRACT_ADDRESS. // "PER TRANSACTION" CONSTANTS global MAX_NEW_NOTE_HASHES_PER_TX: u64 = 64; @@ -59,7 +55,9 @@ global NUM_UNENCRYPTED_LOGS_HASHES_PER_TX: u64 = 1; // docs:end:constants // KERNEL CIRCUIT PRIVATE INPUTS CONSTANTS -global MAX_PUBLIC_DATA_HINTS: u64 = 64; // MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX + MAX_PUBLIC_DATA_READS_PER_TX; +// global MAX_PUBLIC_DATA_HINTS: u64 = MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX + MAX_PUBLIC_DATA_READS_PER_TX; +// FIX: Sadly, writing this as above causes a type error in type_conversion.ts. +global MAX_PUBLIC_DATA_HINTS: u64 = 64; // ROLLUP CONTRACT CONSTANTS - constants used only in l1-contracts global NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP: u64 = 16; @@ -101,8 +99,7 @@ global MAX_ARGS_LENGTH: u64 = ARGS_HASH_CHUNK_COUNT * ARGS_HASH_CHUNK_LENGTH; // to be large enough so that it's ensured that it doesn't collide with storage slots of other variables. global INITIALIZATION_SLOT_SEPARATOR: Field = 1000_000_000; global INITIAL_L2_BLOCK_NUM: Field = 1; -// 126976 = 31 * 4096; -global BLOB_SIZE_IN_BYTES: Field = 126976; +global BLOB_SIZE_IN_BYTES: Field = 31 * 4096; // How much gas is subtracted from L2GASLEFT when making a nested public call by default in the AVM global NESTED_CALL_L2_GAS_BUFFER = 20000; @@ -131,27 +128,13 @@ global REGISTERER_UNCONSTRAINED_FUNCTION_BROADCASTED_MAGIC_VALUE = 0xe7af8166354 global DEPLOYER_CONTRACT_INSTANCE_DEPLOYED_MAGIC_VALUE = 0x85864497636cf755ae7bde03f267ce01a520981c21c3682aaf82a631; global DEPLOYER_CONTRACT_ADDRESS = 0x1b5ecf3d26907648cf737f4304759b8c5850478e839e72f8ce1f5791b286e8f2; -// NOIR CONSTANTS - constants used only in yarn-packages/noir-contracts -// Some are defined here because Noir doesn't yet support globals referencing other globals yet. -// Move these constants to a noir file once the issue below is resolved: -// https://github.com/noir-lang/noir/issues/1734 -global L1_TO_L2_MESSAGE_ORACLE_CALL_LENGTH: u64 = 17; -global MAX_NOTE_FIELDS_LENGTH: u64 = 20; -// GET_NOTE_ORACLE_RETURN_LENGT = MAX_NOTE_FIELDS_LENGTH + 1 + 2 -// The plus 1 is 1 extra field for nonce. -// + 2 for EXTRA_DATA: [number_of_return_notes, contract_address] -global GET_NOTE_ORACLE_RETURN_LENGTH: u64 = 23; -global MAX_NOTES_PER_PAGE: u64 = 10; -// VIEW_NOTE_ORACLE_RETURN_LENGTH = MAX_NOTES_PER_PAGE * (MAX_NOTE_FIELDS_LENGTH + 1) + 2; -global VIEW_NOTE_ORACLE_RETURN_LENGTH: u64 = 212; - // LENGTH OF STRUCTS SERIALIZED TO FIELDS global AZTEC_ADDRESS_LENGTH = 1; -global CALL_CONTEXT_LENGTH: u64 = 21; // 8 + GAS_SETTINGS_LENGTH + GAS_LENGTH -global GAS_SETTINGS_LENGTH: u64 = 10; // 1 + 3 * DIMENSION_GAS_SETTINGS_LENGTH global DIMENSION_GAS_SETTINGS_LENGTH: u64 = 3; global GAS_FEES_LENGTH: u64 = 3; global GAS_LENGTH: u64 = 3; +global GAS_SETTINGS_LENGTH: u64 = 1 + 3 * DIMENSION_GAS_SETTINGS_LENGTH; +global CALL_CONTEXT_LENGTH: u64 = 8 + GAS_SETTINGS_LENGTH + GAS_LENGTH; global CONTENT_COMMITMENT_LENGTH: u64 = 4; global CONTRACT_INSTANCE_LENGTH: u64 = 6; global CONTRACT_STORAGE_READ_LENGTH: u64 = 2; @@ -159,26 +142,26 @@ global CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH: u64 = 2; global ETH_ADDRESS_LENGTH = 1; global FUNCTION_DATA_LENGTH: u64 = 2; global FUNCTION_LEAF_PREIMAGE_LENGTH: u64 = 5; -global GLOBAL_VARIABLES_LENGTH: u64 = 9; // 6 + GAS_FEES_LENGTH -global HEADER_LENGTH: u64 = 23; // 2 for last_archive + 4 for content commitment + 8 for state reference + GLOBAL_VARIABLES_LENGTH +global GLOBAL_VARIABLES_LENGTH: u64 = 6 + GAS_FEES_LENGTH; +global APPEND_ONLY_TREE_SNAPSHOT_LENGTH = 2; global L1_TO_L2_MESSAGE_LENGTH: u64 = 6; global L2_TO_L1_MESSAGE_LENGTH: u64 = 2; global MAX_BLOCK_NUMBER_LENGTH: u64 = 2; // 1 for the option flag, 1 for the value global NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH = 4; global NULLIFIER_KEY_VALIDATION_REQUEST_CONTEXT_LENGTH = 5; global PARTIAL_STATE_REFERENCE_LENGTH: u64 = 6; -global PRIVATE_CALL_STACK_ITEM_LENGTH: u64 = 238; -// Change this ONLY if you have changed the PrivateCircuitPublicInputs structure. -// In other words, if the structure/size of the public inputs of a function call changes then we should change this -// constant as well PRIVATE_CALL_STACK_ITEM_LENGTH -global PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH: u64 = 235; -// Change this ONLY if you have changed the PublicCircuitPublicInputs structure. -global PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH: u64 = 222; -global STATE_REFERENCE_LENGTH: u64 = 8; // 2 for snap + 8 for partial +global READ_REQUEST_LENGTH = 2; +global SIDE_EFFECT_LENGTH = 2; +global SIDE_EFFECT_LINKED_TO_NOTE_HASH_LENGTH = 3; +global STATE_REFERENCE_LENGTH: u64 = APPEND_ONLY_TREE_SNAPSHOT_LENGTH + PARTIAL_STATE_REFERENCE_LENGTH; global TX_CONTEXT_DATA_LENGTH: u64 = 4; -global TX_REQUEST_LENGTH: u64 = 18; // 2 + TX_CONTEXT_DATA_LENGTH + FUNCTION_DATA_LENGTH + GAS_SETTINGS_LENGTH +global TX_REQUEST_LENGTH: u64 = 2 + TX_CONTEXT_DATA_LENGTH + FUNCTION_DATA_LENGTH + GAS_SETTINGS_LENGTH; +global HEADER_LENGTH: u64 = APPEND_ONLY_TREE_SNAPSHOT_LENGTH + CONTENT_COMMITMENT_LENGTH + STATE_REFERENCE_LENGTH + GLOBAL_VARIABLES_LENGTH; +global PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH: u64 = CALL_CONTEXT_LENGTH + 3 + MAX_BLOCK_NUMBER_LENGTH + (SIDE_EFFECT_LENGTH * MAX_NOTE_HASH_READ_REQUESTS_PER_CALL) + (READ_REQUEST_LENGTH * MAX_NULLIFIER_READ_REQUESTS_PER_CALL) + (NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH * MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL) + (SIDE_EFFECT_LENGTH * MAX_NEW_NOTE_HASHES_PER_CALL) + (SIDE_EFFECT_LINKED_TO_NOTE_HASH_LENGTH * MAX_NEW_NULLIFIERS_PER_CALL) + MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL + (L2_TO_L1_MESSAGE_LENGTH * MAX_NEW_L2_TO_L1_MSGS_PER_CALL) + 2 + (SIDE_EFFECT_LENGTH * MAX_ENCRYPTED_LOGS_PER_CALL) + (SIDE_EFFECT_LENGTH * MAX_UNENCRYPTED_LOGS_PER_CALL) + 2 + HEADER_LENGTH + 2; +global PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH: u64 = CALL_CONTEXT_LENGTH + 2 + (READ_REQUEST_LENGTH * MAX_NULLIFIER_READ_REQUESTS_PER_CALL) + (READ_REQUEST_LENGTH * MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL) + (CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH * MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL) + (CONTRACT_STORAGE_READ_LENGTH * MAX_PUBLIC_DATA_READS_PER_CALL) + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL + (SIDE_EFFECT_LENGTH * MAX_NEW_NOTE_HASHES_PER_CALL) + (SIDE_EFFECT_LINKED_TO_NOTE_HASH_LENGTH * MAX_NEW_NULLIFIERS_PER_CALL) + (L2_TO_L1_MESSAGE_LENGTH * MAX_NEW_L2_TO_L1_MSGS_PER_CALL) + 2 + (SIDE_EFFECT_LENGTH * MAX_UNENCRYPTED_LOGS_PER_CALL) + 1 + HEADER_LENGTH + AZTEC_ADDRESS_LENGTH + /* revert_code */ 1 + GAS_LENGTH; +global PRIVATE_CALL_STACK_ITEM_LENGTH: u64 = AZTEC_ADDRESS_LENGTH + FUNCTION_DATA_LENGTH + PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH; -global ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH: Field = 25; // 2 + FUNCTION_DATA_LENGTH + CALL_CONTEXT_LENGTH +global ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH: u64 = 2 + FUNCTION_DATA_LENGTH + CALL_CONTEXT_LENGTH; global GET_NOTES_ORACLE_RETURN_LENGTH: u64 = 674; global NOTE_HASHES_NUM_BYTES_PER_BASE_ROLLUP: Field = 2048; global NULLIFIERS_NUM_BYTES_PER_BASE_ROLLUP: Field = 2048; @@ -189,7 +172,8 @@ global CONTRACT_DATA_NUM_BYTES_PER_BASE_ROLLUP_UNPADDED: Field = 52; global L2_TO_L1_MSGS_NUM_BYTES_PER_BASE_ROLLUP: Field = 64; global LOGS_HASHES_NUM_BYTES_PER_BASE_ROLLUP: Field = 64; global NUM_MSGS_PER_BASE_PARITY: u64 = 4; -// NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP / NUM_MSGS_PER_BASE_PARITY +// global NUM_BASE_PARITY_PER_ROOT_PARITY: u64 = NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP / NUM_MSGS_PER_BASE_PARITY; +// FIX: Sadly, writing this as above causes a type error in type_conversion.ts. global NUM_BASE_PARITY_PER_ROOT_PARITY: u64 = 4; /** diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/contrakt/storage_update_request.nr b/noir-projects/noir-protocol-circuits/crates/types/src/contrakt/storage_update_request.nr index 01176175f60..34654e18775 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/contrakt/storage_update_request.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/contrakt/storage_update_request.nr @@ -4,7 +4,7 @@ use crate::{ }; use dep::std::cmp::Eq; -struct StorageUpdateRequest{ +struct StorageUpdateRequest { storage_slot : Field, new_value : Field, } diff --git a/yarn-project/circuits.js/src/constants.gen.ts b/yarn-project/circuits.js/src/constants.gen.ts index 9ac707568fd..6441113ed89 100644 --- a/yarn-project/circuits.js/src/constants.gen.ts +++ b/yarn-project/circuits.js/src/constants.gen.ts @@ -56,9 +56,10 @@ export const L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH = 12; export const FUNCTION_SELECTOR_NUM_BYTES = 4; export const ARGS_HASH_CHUNK_LENGTH = 64; export const ARGS_HASH_CHUNK_COUNT = 64; +export const MAX_ARGS_LENGTH = ARGS_HASH_CHUNK_COUNT * ARGS_HASH_CHUNK_LENGTH; export const INITIALIZATION_SLOT_SEPARATOR = 1000_000_000; export const INITIAL_L2_BLOCK_NUM = 1; -export const BLOB_SIZE_IN_BYTES = 126976; +export const BLOB_SIZE_IN_BYTES = 31 * 4096; export const NESTED_CALL_L2_GAS_BUFFER = 20000; export const MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS = 16200; export const MAX_PACKED_BYTECODE_SIZE_PER_PRIVATE_FUNCTION_IN_FIELDS = 3000; @@ -74,17 +75,12 @@ export const REGISTERER_UNCONSTRAINED_FUNCTION_BROADCASTED_MAGIC_VALUE = export const DEPLOYER_CONTRACT_INSTANCE_DEPLOYED_MAGIC_VALUE = 0x85864497636cf755ae7bde03f267ce01a520981c21c3682aaf82a631n; export const DEPLOYER_CONTRACT_ADDRESS = 0x1b5ecf3d26907648cf737f4304759b8c5850478e839e72f8ce1f5791b286e8f2n; -export const L1_TO_L2_MESSAGE_ORACLE_CALL_LENGTH = 17; -export const MAX_NOTE_FIELDS_LENGTH = 20; -export const GET_NOTE_ORACLE_RETURN_LENGTH = 23; -export const MAX_NOTES_PER_PAGE = 10; -export const VIEW_NOTE_ORACLE_RETURN_LENGTH = 212; export const AZTEC_ADDRESS_LENGTH = 1; -export const CALL_CONTEXT_LENGTH = 21; -export const GAS_SETTINGS_LENGTH = 10; export const DIMENSION_GAS_SETTINGS_LENGTH = 3; export const GAS_FEES_LENGTH = 3; export const GAS_LENGTH = 3; +export const GAS_SETTINGS_LENGTH = 1 + 3 * DIMENSION_GAS_SETTINGS_LENGTH; +export const CALL_CONTEXT_LENGTH = 8 + GAS_SETTINGS_LENGTH + GAS_LENGTH; export const CONTENT_COMMITMENT_LENGTH = 4; export const CONTRACT_INSTANCE_LENGTH = 6; export const CONTRACT_STORAGE_READ_LENGTH = 2; @@ -92,21 +88,61 @@ export const CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH = 2; export const ETH_ADDRESS_LENGTH = 1; export const FUNCTION_DATA_LENGTH = 2; export const FUNCTION_LEAF_PREIMAGE_LENGTH = 5; -export const GLOBAL_VARIABLES_LENGTH = 9; -export const HEADER_LENGTH = 23; +export const GLOBAL_VARIABLES_LENGTH = 6 + GAS_FEES_LENGTH; +export const APPEND_ONLY_TREE_SNAPSHOT_LENGTH = 2; export const L1_TO_L2_MESSAGE_LENGTH = 6; export const L2_TO_L1_MESSAGE_LENGTH = 2; export const MAX_BLOCK_NUMBER_LENGTH = 2; export const NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH = 4; export const NULLIFIER_KEY_VALIDATION_REQUEST_CONTEXT_LENGTH = 5; export const PARTIAL_STATE_REFERENCE_LENGTH = 6; -export const PRIVATE_CALL_STACK_ITEM_LENGTH = 238; -export const PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH = 235; -export const PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH = 222; -export const STATE_REFERENCE_LENGTH = 8; +export const READ_REQUEST_LENGTH = 2; +export const SIDE_EFFECT_LENGTH = 2; +export const SIDE_EFFECT_LINKED_TO_NOTE_HASH_LENGTH = 3; +export const STATE_REFERENCE_LENGTH = APPEND_ONLY_TREE_SNAPSHOT_LENGTH + PARTIAL_STATE_REFERENCE_LENGTH; export const TX_CONTEXT_DATA_LENGTH = 4; -export const TX_REQUEST_LENGTH = 18; -export const ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH = 25; +export const TX_REQUEST_LENGTH = 2 + TX_CONTEXT_DATA_LENGTH + FUNCTION_DATA_LENGTH + GAS_SETTINGS_LENGTH; +export const HEADER_LENGTH = + APPEND_ONLY_TREE_SNAPSHOT_LENGTH + CONTENT_COMMITMENT_LENGTH + STATE_REFERENCE_LENGTH + GLOBAL_VARIABLES_LENGTH; +export const PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH = + CALL_CONTEXT_LENGTH + + 3 + + MAX_BLOCK_NUMBER_LENGTH + + SIDE_EFFECT_LENGTH * MAX_NOTE_HASH_READ_REQUESTS_PER_CALL + + READ_REQUEST_LENGTH * MAX_NULLIFIER_READ_REQUESTS_PER_CALL + + NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH * MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL + + SIDE_EFFECT_LENGTH * MAX_NEW_NOTE_HASHES_PER_CALL + + SIDE_EFFECT_LINKED_TO_NOTE_HASH_LENGTH * MAX_NEW_NULLIFIERS_PER_CALL + + MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL + + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL + + L2_TO_L1_MESSAGE_LENGTH * MAX_NEW_L2_TO_L1_MSGS_PER_CALL + + 2 + + SIDE_EFFECT_LENGTH * MAX_ENCRYPTED_LOGS_PER_CALL + + SIDE_EFFECT_LENGTH * MAX_UNENCRYPTED_LOGS_PER_CALL + + 2 + + HEADER_LENGTH + + 2; +export const PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH = + CALL_CONTEXT_LENGTH + + 2 + + READ_REQUEST_LENGTH * MAX_NULLIFIER_READ_REQUESTS_PER_CALL + + READ_REQUEST_LENGTH * MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL + + CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH * MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL + + CONTRACT_STORAGE_READ_LENGTH * MAX_PUBLIC_DATA_READS_PER_CALL + + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL + + SIDE_EFFECT_LENGTH * MAX_NEW_NOTE_HASHES_PER_CALL + + SIDE_EFFECT_LINKED_TO_NOTE_HASH_LENGTH * MAX_NEW_NULLIFIERS_PER_CALL + + L2_TO_L1_MESSAGE_LENGTH * MAX_NEW_L2_TO_L1_MSGS_PER_CALL + + 2 + + SIDE_EFFECT_LENGTH * MAX_UNENCRYPTED_LOGS_PER_CALL + + 1 + + HEADER_LENGTH + + AZTEC_ADDRESS_LENGTH + + /* revert_code */ 1 + + GAS_LENGTH; +export const PRIVATE_CALL_STACK_ITEM_LENGTH = + AZTEC_ADDRESS_LENGTH + FUNCTION_DATA_LENGTH + PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH; +export const ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH = 2 + FUNCTION_DATA_LENGTH + CALL_CONTEXT_LENGTH; export const GET_NOTES_ORACLE_RETURN_LENGTH = 674; export const NOTE_HASHES_NUM_BYTES_PER_BASE_ROLLUP = 2048; export const NULLIFIERS_NUM_BYTES_PER_BASE_ROLLUP = 2048; diff --git a/yarn-project/circuits.js/src/scripts/constants.in.ts b/yarn-project/circuits.js/src/scripts/constants.in.ts index a5fadc66e2a..33ede0eded4 100644 --- a/yarn-project/circuits.js/src/scripts/constants.in.ts +++ b/yarn-project/circuits.js/src/scripts/constants.in.ts @@ -122,7 +122,7 @@ function parseNoirFile(fileContent: string): ParsedContent { return; } - const [, name, _type, value] = line.match(/global\s+(\w+)(\s*:\s*\w+)?\s*=\s*(0x[a-fA-F0-9]+|[\d_]+);/) || []; + const [, name, _type, value] = line.match(/global\s+(\w+)(\s*:\s*\w+)?\s*=\s*(.+?);/) || []; if (!name || !value) { // eslint-disable-next-line no-console From c72f34ef0ff582269db245643909e02b66a4d37a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Pedro=20Sousa?= Date: Thu, 18 Apr 2024 15:17:09 +0100 Subject: [PATCH 013/102] chore: adding devcontainer with create aztec app (#5752) # Description This PR adds a codespace that starts with `npm create aztec-app` and installs the sandbox running with docker-in-docker. # Summary The changes to the boxes and structure are the following: - Splits .devcontainer into different folders, leaving the existing "dev" in one of them. Users need to choose which codespace they want to start - Makes changes to the `npx` script to accept box type and box name as options, and to skip the installation of the sandbox Each box has devcontainer that does the following: - Mounts the `scripts` folder in the default workspace folder, - Hacks it a bit with `mv` and `rm` to make sure the workspace folder is empty without leftover scripts lying around - Runs the scripts from the new location These scripts do the following _at build time_: - Install the sandbox, pulls the `foundry` images - Run the `npx` script and cleans up a bit - Runs yarn and installs playwright - Compiles and codegens the box contract's (because why not) This is pretty useful because we can prebuild these images thus making the dev process MUCH FASTER. Still, _running_ the sandbox needs to happen at runtime, but since the prebuild pulled everything, it's much faster: - Installs the github CLI tool and uses it to open the 8080 port to the public (unfortunately there's no better way of doing this) - Runs the sandbox in the background - Shows the user a friendly message with instructions --- .devcontainer/{ => dev}/devcontainer.json | 0 .devcontainer/react/devcontainer.json | 23 + .devcontainer/scripts/onCreateCommand.sh | 22 + .devcontainer/scripts/postAttachCommand.sh | 64 ++ .devcontainer/token/devcontainer.json | 30 + .devcontainer/vanilla/devcontainer.json | 30 + boxes/README.md | 2 +- boxes/bin.js | 32 +- boxes/boxes/react/.yarnrc.yml | 1 + boxes/boxes/vanilla/.yarnrc.yml | 1 + boxes/package.json | 2 +- boxes/scripts/steps/chooseBox.js | 89 +- boxes/scripts/steps/sandbox/install.js | 18 +- boxes/scripts/steps/sandbox/run.js | 5 +- boxes/scripts/utils.js | 22 +- boxes/yarn.lock | 1105 ++++++++++---------- 16 files changed, 844 insertions(+), 602 deletions(-) rename .devcontainer/{ => dev}/devcontainer.json (100%) create mode 100644 .devcontainer/react/devcontainer.json create mode 100755 .devcontainer/scripts/onCreateCommand.sh create mode 100755 .devcontainer/scripts/postAttachCommand.sh create mode 100644 .devcontainer/token/devcontainer.json create mode 100644 .devcontainer/vanilla/devcontainer.json create mode 100644 boxes/boxes/react/.yarnrc.yml create mode 100644 boxes/boxes/vanilla/.yarnrc.yml diff --git a/.devcontainer/devcontainer.json b/.devcontainer/dev/devcontainer.json similarity index 100% rename from .devcontainer/devcontainer.json rename to .devcontainer/dev/devcontainer.json diff --git a/.devcontainer/react/devcontainer.json b/.devcontainer/react/devcontainer.json new file mode 100644 index 00000000000..a403239429b --- /dev/null +++ b/.devcontainer/react/devcontainer.json @@ -0,0 +1,23 @@ +{ + "name": "React App", + "image": "node:lts-bookworm", + "features": { + "ghcr.io/devcontainers/features/docker-in-docker:2": {} + }, + "onCreateCommand": "cp -R /root/workspace /root/scripts && rm -rf /root/workspace/* && sh /root/scripts/onCreateCommand.sh app react", + "postAttachCommand": "sh /root/scripts/postAttachCommand.sh app react", + "customizations": { + "vscode": { + "settings": {}, + "extensions": ["noir-lang.vscode-noir"] + } + }, + "hostRequirements": { + "cpus": 8, + "memory": "8gb", + "storage": "32gb" + }, + "workspaceMount": "source=${localWorkspaceFolder}/.devcontainer/scripts,target=/root/workspace,type=bind", + "workspaceFolder": "/root/workspace", + "forwardPorts": [8080] +} diff --git a/.devcontainer/scripts/onCreateCommand.sh b/.devcontainer/scripts/onCreateCommand.sh new file mode 100755 index 00000000000..0208ef55640 --- /dev/null +++ b/.devcontainer/scripts/onCreateCommand.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash + +TYPE=$1 +NAME=$2 + +apt install gh + +curl -s install.aztec.network | NON_INTERACTIVE=1 BIN_PATH=/usr/local/bin bash -s +docker compose -f $HOME/.aztec/docker-compose.yml pull + +if ! grep -q "PXE_URL" ~/.bashrc; then + echo "export PXE_URL=https://\$CODESPACE_NAME-8080.preview.\$GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN" >> ~/.bashrc +fi + +yes | npx create-aztec-app -t $TYPE -n $NAME -s +mv react/* react/.* . +rm -rf react + +yarn + +npx -y playwright install --with-deps +yarn prep diff --git a/.devcontainer/scripts/postAttachCommand.sh b/.devcontainer/scripts/postAttachCommand.sh new file mode 100755 index 00000000000..e2ccda17ac5 --- /dev/null +++ b/.devcontainer/scripts/postAttachCommand.sh @@ -0,0 +1,64 @@ +#!/usr/bin/env bash +TYPE=$1 +NAME=$2 + +gh codespace ports visibility 8080:public -c $CODESPACE_NAME + +(nohup /usr/local/bin/aztec sandbox &) + +r=$(tput sgr0) # Reset color +bold=$(tput bold) # Bold text +g=$(tput setaf 46) # Light Green +b=$(tput setaf 21) # Bright Blue +p=$(tput setaf 13) # Magenta +y=$(tput setaf 226) # Bright Yellow +c=$(tput setaf 51) # Cyan +o=$(tput setaf 208) # Orange + +# Function to print colored text +print_colored() { + case $2 in + green) + color=$g + ;; + blue) + color=$b + ;; + magenta) + color=$p + ;; + yellow) + color=$y + ;; + cyan) + color=$c + ;; + orange) + color=$o + ;; + *) + color=$r + ;; + esac + echo "${color}$1${r}" +} + +echo +echo "${bold}${c} █████╗ ███████╗████████╗███████╗ ██████╗${r}" +echo "${bold}${o}██╔══██╗╚══███╔╝╚══██╔══╝██╔════╝██╔════╝${r}" +echo "${bold}${g}███████║ ███╔╝ ██║ █████╗ ██║${r}" +echo "${bold}${b}██╔══██║ ███╔╝ ██║ ██╔══╝ ██║${r}" +echo "${bold}${p}██║ ██║███████╗ ██║ ███████╗╚██████╗${r}" +echo "${bold}${y}╚═╝ ╚═╝╚══════╝ ╚═╝ ╚══════╝ ╚═════╝${r}" +echo +print_colored "${bold}Sandbox Codespace" "cyan" +print_colored "${bold}Your codespace is ready with your chosen box! 🎉" "cyan" +echo +print_colored "All the packages are already installed, and you can now run yarn dev or any other package.json script." "magenta" +print_colored "You can also use this codespace for its running sandbox, by connecting your local environment to it." "magenta" +echo +print_colored "To do so, set the PXE_URL to this codespace's sandbox URL:" "magenta" +print_colored "${PXE_URL}" "green" +print_colored "ex. PXE_URL=\"${PXE_URL}\" yarn dev" +echo +print_colored "${bold}Enjoy your sandbox! 🏖" "orange" diff --git a/.devcontainer/token/devcontainer.json b/.devcontainer/token/devcontainer.json new file mode 100644 index 00000000000..ebb1cef6f52 --- /dev/null +++ b/.devcontainer/token/devcontainer.json @@ -0,0 +1,30 @@ +{ + "name": "Token Contract Only", + "image": "node:lts-bookworm", + "features": { + "ghcr.io/devcontainers/features/docker-in-docker:2": {} + }, + "onCreateCommand": ".devcontainer/scripts/onCreateCommand.sh contract token_contract", + "postAttachCommand": ".devcontainer/scripts/postAttachCommand.sh contract token_contract", + "customizations": { + "vscode": { + "settings": {}, + "extensions": ["noir-lang.vscode-noir"] + } + }, + "workspaceMount": "source=${localWorkspaceFolder}/.devcontainer/token_contract,target=/root/workspace,type=bind", + "workspaceFolder": "/root/workspace", + "hostRequirements": { + "cpus": 8, + "memory": "8gb", + "storage": "32gb" + }, + "mounts": [ + { + "source": "${localWorkspaceFolder}/.devcontainer/scripts", + "target": "/root/workspace/.devcontainer/scripts", + "type": "bind" + } + ], + "forwardPorts": [8080] +} diff --git a/.devcontainer/vanilla/devcontainer.json b/.devcontainer/vanilla/devcontainer.json new file mode 100644 index 00000000000..340a8a41703 --- /dev/null +++ b/.devcontainer/vanilla/devcontainer.json @@ -0,0 +1,30 @@ +{ + "name": "Vanilla Typescript App", + "image": "node:lts-bookworm", + "features": { + "ghcr.io/devcontainers/features/docker-in-docker:2": {} + }, + "onCreateCommand": ".devcontainer/scripts/onCreateCommand.sh app vanilla", + "postAttachCommand": ".devcontainer/scripts/postAttachCommand.sh app vanilla", + "customizations": { + "vscode": { + "settings": {}, + "extensions": ["noir-lang.vscode-noir"] + } + }, + "workspaceMount": "source=${localWorkspaceFolder}/.devcontainer/vanilla,target=/root/workspace,type=bind", + "workspaceFolder": "/root/workspace", + "hostRequirements": { + "cpus": 8, + "memory": "8gb", + "storage": "32gb" + }, + "mounts": [ + { + "source": "${localWorkspaceFolder}/.devcontainer/scripts", + "target": "/root/workspace/.devcontainer/scripts", + "type": "bind" + } + ], + "forwardPorts": [8080] +} diff --git a/boxes/README.md b/boxes/README.md index c86e754a29f..67cf195e9ed 100644 --- a/boxes/README.md +++ b/boxes/README.md @@ -16,7 +16,7 @@ If you have [node](https://nodejs.org/en/download) installed, you can open a ter or -`npm create aztec-app` +`npx create-aztec-app` The script will install the sandbox, run it, and clone the boilerplate you chose. You can pass some options: diff --git a/boxes/bin.js b/boxes/bin.js index b4e614ccfd3..5757ebff0cc 100755 --- a/boxes/bin.js +++ b/boxes/bin.js @@ -1,5 +1,5 @@ #!/usr/bin/env node -import { Command } from "commander"; +import { Command, Option } from "commander"; const program = new Command(); import { chooseProject } from "./scripts/steps/chooseBox.js"; import { sandboxRun } from "./scripts/steps/sandbox/run.js"; @@ -86,17 +86,37 @@ const init = async ({ debug, github_token, version }) => { program.option("-d, --debug", "output extra debugging"); program.option("-gh, --github_token ", "a github token"); program.option("-v, --version ", "a version number or master tag"); +program.option("-s, --skip-sandbox", "install and run sandbox after cloning"); + +program.option( + "-t, --project-type ", + "the type of the project to clone ('app' or 'contract')", +); +program.option( + "-n, --project-name ", + "the name of the project to clone", +); +program.parse(); + +// this is some bad code, but it's def fun +// I'm matching all keys started with project and +// then using using modulo to say "if one is defined, two must be defined" +const optsKeys = Object.keys(program.opts()).filter((e) => /project*/g.test(e)); +if (optsKeys.length % 2) { + throw Error("You must define both the project type and the project name"); +} + program.action(async (options) => { + const { projectType, projectName, skipSandbox } = options; // SETUP: Initialize global variables await init(options); - // STEP 1: Choose the boilerplate - await chooseProject(); + await chooseProject({ projectType, projectName }); + if (skipSandbox) return; // STEP 2: Install the Sandbox - await sandboxInstallOrUpdate(); - + await sandboxInstallOrUpdate({ skipQuestion: skipSandbox }); // STEP 3: Running the Sandbox - await sandboxRun(); + await sandboxRun({ skipQuestion: skipSandbox }); }); program.parse(); diff --git a/boxes/boxes/react/.yarnrc.yml b/boxes/boxes/react/.yarnrc.yml new file mode 100644 index 00000000000..3186f3f0795 --- /dev/null +++ b/boxes/boxes/react/.yarnrc.yml @@ -0,0 +1 @@ +nodeLinker: node-modules diff --git a/boxes/boxes/vanilla/.yarnrc.yml b/boxes/boxes/vanilla/.yarnrc.yml new file mode 100644 index 00000000000..3186f3f0795 --- /dev/null +++ b/boxes/boxes/vanilla/.yarnrc.yml @@ -0,0 +1 @@ +nodeLinker: node-modules diff --git a/boxes/package.json b/boxes/package.json index b782ec6ec55..bff118dbe5b 100644 --- a/boxes/package.json +++ b/boxes/package.json @@ -1,7 +1,7 @@ { "name": "create-aztec-app", "packageManager": "yarn@4.1.0", - "version": "0.2.15", + "version": "0.3.16", "type": "module", "scripts": { "compile": "yarn workspaces foreach -A -v run compile", diff --git a/boxes/scripts/steps/chooseBox.js b/boxes/scripts/steps/chooseBox.js index 644a15a201b..d1f5ee33ec7 100644 --- a/boxes/scripts/steps/chooseBox.js +++ b/boxes/scripts/steps/chooseBox.js @@ -8,24 +8,31 @@ import { } from "../utils.js"; import { getPlaceholders } from "../config.js"; -async function chooseAndCloneBox() { +async function chooseAndCloneBox({ projectName }) { const availableBoxes = await getAvailableBoxes(); - const appType = await select({ - message: `Please choose your Aztec boilerplate:`, - choices: [ - ...availableBoxes.map((box) => { - return { value: box.name, name: box.description }; - }), - { value: "skip", name: "Skip this step" }, - ], - }); + if (!projectName) { + projectName = await select({ + message: `Please choose your Aztec boilerplate:`, + choices: [ + ...availableBoxes.map((box) => { + return { value: box.name, name: box.description }; + }), + { value: "skip", name: "Skip this step" }, + ], + }); + } else { + if (!availableBoxes.find((box) => box.name === projectName)) { + throw new Error(`Box ${projectName} not found`); + } + } const rootDir = await clone({ path: "boxes/boxes", - choice: appType, + choice: projectName, type: "box", tag, version, + name: projectName, }); await replacePaths({ @@ -37,25 +44,33 @@ async function chooseAndCloneBox() { success("Your code is ready!"); } -async function chooseAndCloneContract() { +async function chooseAndCloneContract({ projectName }) { const availableContracts = await getAvailableContracts(); // let user choose one of the contracts in noir-projects - const contract = await select({ - message: `Please choose your Aztec boilerplate:`, - choices: [ - ...availableContracts.map((contract) => { - return { value: contract.name, name: contract.name }; - }), - { value: "skip", name: "Skip this step" }, - ], - }); + + if (!projectName) { + projectName = await select({ + message: `Please choose your Aztec boilerplate:`, + choices: [ + ...availableContracts.map((contract) => { + return { value: contract.name, name: contract.name }; + }), + { value: "skip", name: "Skip this step" }, + ], + }); + } else { + if (!availableContracts.find((contract) => contract.name === projectName)) { + throw new Error(`Contract ${projectName} not found`); + } + } const rootDir = await clone({ path: "noir-projects/noir-contracts/contracts", - choice: contract, + choice: projectName, type: "contract", tag, version, + name: projectName, }); await replacePaths({ @@ -67,28 +82,30 @@ async function chooseAndCloneContract() { await processProject({ rootDir, - placeholders: getPlaceholders(contract), + placeholders: getPlaceholders(projectName), }); success("Your code is ready!"); // get the e2e test for that contract from yarn-project/end-to-end } -export async function chooseProject() { - const projectType = await select({ - message: `Please choose your type of project:`, - choices: [ - { value: "fs_app", name: "Boilerplate project with frontend" }, - { value: "contract_only", name: "Just a contract example" }, - { value: "skip", name: "Skip this step" }, - ], - }); +export async function chooseProject({ projectType, projectName }) { + if (!projectType) { + projectType = await select({ + message: `Please choose your type of project:`, + choices: [ + { value: "app", name: "Boilerplate project with frontend" }, + { value: "contract", name: "Just a contract example" }, + { value: "skip", name: "Skip this step" }, + ], + }); + } if (projectType === "skip") { return; - } else if (projectType === "contract_only") { - await chooseAndCloneContract(); - } else if (projectType === "fs_app") { - await chooseAndCloneBox(); + } else if (projectType === "contract") { + await chooseAndCloneContract({ projectName: projectName }); + } else if (projectType === "app") { + await chooseAndCloneBox({ projectName: projectName }); } } diff --git a/boxes/scripts/steps/sandbox/install.js b/boxes/scripts/steps/sandbox/install.js index 34926b6045b..af6c0924fe5 100644 --- a/boxes/scripts/steps/sandbox/install.js +++ b/boxes/scripts/steps/sandbox/install.js @@ -37,6 +37,14 @@ const runPty = async (command, { success: exitSuccess, error }) => { } }; +async function installSandbox() { + await runPty("yes | bash -i <(curl -s install.aztec.network); exit\n", { + success: "The Sandbox is installed!", + error: + "Failed to install the Sandbox. Please visit the docs at https://docs.aztec.network", + }); +} + function findOutUserVersion() { /** * We know user has docker installed. @@ -97,16 +105,8 @@ export async function sandboxInstallOrUpdate() { "Seems like you don't have the Aztec Sandbox installed. Do you want to install it?", default: true, }); - if (answer) { - await runPty( - "echo y | bash -i <(curl -s install.aztec.network); exit\n", - { - success: "The Sandbox is installed!", - error: - "Failed to install the Sandbox. Please visit the docs at https://docs.aztec.network", - }, - ); + await installSandbox(); } } else if ( // Another situation is where the sandbox matches the stable version (i.e. 0.24.0) or master diff --git a/boxes/scripts/steps/sandbox/run.js b/boxes/scripts/steps/sandbox/run.js index 2a6eed9ab0c..e857f0515fa 100644 --- a/boxes/scripts/steps/sandbox/run.js +++ b/boxes/scripts/steps/sandbox/run.js @@ -29,11 +29,12 @@ export async function sandboxRun() { "Sandbox can't be reached on localhost:8080. Do you want to start it?", default: true, }); - if (answer) { info("Starting the sandbox... This might take a few minutes."); info(`Go and explore the boilerplate code while you wait!`); - execSync(`$HOME/.aztec/bin/aztec sandbox`, { stdio: "inherit" }); + execSync(`$HOME/.aztec/bin/aztec sandbox`, { + stdio: "inherit", + }); } } } diff --git a/boxes/scripts/utils.js b/boxes/scripts/utils.js index a5fc790d313..e29511266b0 100644 --- a/boxes/scripts/utils.js +++ b/boxes/scripts/utils.js @@ -52,11 +52,13 @@ export async function getAvailableContracts() { } } -export async function clone({ path, choice, type }) { - const appName = await input({ - message: `Your ${type} name:`, - default: `my-aztec-${type}`, - }); +export async function clone({ path, choice, type, name }) { + if (!name) { + name = await input({ + message: `Your ${type} name:`, + default: `my-aztec-${type}`, + }); + } spinner.text = `Cloning the ${type} code...`; try { @@ -68,7 +70,7 @@ export async function clone({ path, choice, type }) { ); emitter.on("info", ({ message }) => debug(message)); emitter.on("warn", ({ message }) => error(message)); - await emitter.clone(`./${appName}`); + await emitter.clone(`./${name}`); if (type === "contract") { spinner.text = `Cloning default contract project...`; @@ -78,15 +80,15 @@ export async function clone({ path, choice, type }) { ); baseEmitter.on("info", debug); baseEmitter.on("warn", error); - await baseEmitter.clone(`./${appName}/base`); - await fs.cp(`./${appName}/base`, `./${appName}`, { + await baseEmitter.clone(`./${name}/base`); + await fs.cp(`./${name}/base`, `./${name}`, { recursive: true, force: true, }); - await fs.rm(`./${appName}/base`, { recursive: true, force: true }); + await fs.rm(`./${name}/base`, { recursive: true, force: true }); } spinner.succeed(); - return `./${appName}`; + return `./${name}`; } catch (e) { spinner.fail(); error(e); diff --git a/boxes/yarn.lock b/boxes/yarn.lock index dfcaf49a4d5..d1a4ff91e96 100644 --- a/boxes/yarn.lock +++ b/boxes/yarn.lock @@ -108,6 +108,7 @@ __metadata: "@aztec/circuit-types": "workspace:^" "@aztec/circuits.js": "workspace:^" "@aztec/foundation": "workspace:^" + "@aztec/protocol-contracts": "workspace:^" tslib: "npm:^2.4.0" languageName: node linkType: soft @@ -128,7 +129,7 @@ __metadata: resolution: "@aztec/foundation@portal:../yarn-project/foundation::locator=create-aztec-app%40workspace%3A." dependencies: "@aztec/bb.js": "portal:../../barretenberg/ts" - "@koa/cors": "npm:^4.0.0" + "@koa/cors": "npm:^5.0.0" "@noble/curves": "npm:^1.2.0" bn.js: "npm:^5.2.1" debug: "npm:^4.3.4" @@ -244,55 +245,55 @@ __metadata: languageName: unknown linkType: soft -"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.23.5": - version: 7.23.5 - resolution: "@babel/code-frame@npm:7.23.5" +"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.23.5, @babel/code-frame@npm:^7.24.1, @babel/code-frame@npm:^7.24.2": + version: 7.24.2 + resolution: "@babel/code-frame@npm:7.24.2" dependencies: - "@babel/highlight": "npm:^7.23.4" - chalk: "npm:^2.4.2" - checksum: 10c0/a10e843595ddd9f97faa99917414813c06214f4d9205294013e20c70fbdf4f943760da37dec1d998bf3e6fc20fa2918a47c0e987a7e458663feb7698063ad7c6 + "@babel/highlight": "npm:^7.24.2" + picocolors: "npm:^1.0.0" + checksum: 10c0/d1d4cba89475ab6aab7a88242e1fd73b15ecb9f30c109b69752956434d10a26a52cbd37727c4eca104b6d45227bd1dfce39a6a6f4a14c9b2f07f871e968cf406 languageName: node linkType: hard "@babel/compat-data@npm:^7.23.5": - version: 7.23.5 - resolution: "@babel/compat-data@npm:7.23.5" - checksum: 10c0/081278ed46131a890ad566a59c61600a5f9557bd8ee5e535890c8548192532ea92590742fd74bd9db83d74c669ef8a04a7e1c85cdea27f960233e3b83c3a957c + version: 7.24.4 + resolution: "@babel/compat-data@npm:7.24.4" + checksum: 10c0/9cd8a9cd28a5ca6db5d0e27417d609f95a8762b655e8c9c97fd2de08997043ae99f0139007083c5e607601c6122e8432c85fe391731b19bf26ad458fa0c60dd3 languageName: node linkType: hard "@babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3, @babel/core@npm:^7.23.9": - version: 7.24.0 - resolution: "@babel/core@npm:7.24.0" + version: 7.24.4 + resolution: "@babel/core@npm:7.24.4" dependencies: "@ampproject/remapping": "npm:^2.2.0" - "@babel/code-frame": "npm:^7.23.5" - "@babel/generator": "npm:^7.23.6" + "@babel/code-frame": "npm:^7.24.2" + "@babel/generator": "npm:^7.24.4" "@babel/helper-compilation-targets": "npm:^7.23.6" "@babel/helper-module-transforms": "npm:^7.23.3" - "@babel/helpers": "npm:^7.24.0" - "@babel/parser": "npm:^7.24.0" + "@babel/helpers": "npm:^7.24.4" + "@babel/parser": "npm:^7.24.4" "@babel/template": "npm:^7.24.0" - "@babel/traverse": "npm:^7.24.0" + "@babel/traverse": "npm:^7.24.1" "@babel/types": "npm:^7.24.0" convert-source-map: "npm:^2.0.0" debug: "npm:^4.1.0" gensync: "npm:^1.0.0-beta.2" json5: "npm:^2.2.3" semver: "npm:^6.3.1" - checksum: 10c0/bb37cbf0bdfd676b246af0a3d9a7932d10573f2d45114fdda02a71889e35530ce13d8930177e78b065d6734b8d45a4fbf7c77f223b1d44b4a28cfe5fefee93ed + checksum: 10c0/fc136966583e64d6f84f4a676368de6ab4583aa87f867186068655b30ef67f21f8e65a88c6d446a7efd219ad7ffb9185c82e8a90183ee033f6f47b5026641e16 languageName: node linkType: hard -"@babel/generator@npm:^7.23.6, @babel/generator@npm:^7.7.2": - version: 7.23.6 - resolution: "@babel/generator@npm:7.23.6" +"@babel/generator@npm:^7.24.1, @babel/generator@npm:^7.24.4, @babel/generator@npm:^7.7.2": + version: 7.24.4 + resolution: "@babel/generator@npm:7.24.4" dependencies: - "@babel/types": "npm:^7.23.6" - "@jridgewell/gen-mapping": "npm:^0.3.2" - "@jridgewell/trace-mapping": "npm:^0.3.17" + "@babel/types": "npm:^7.24.0" + "@jridgewell/gen-mapping": "npm:^0.3.5" + "@jridgewell/trace-mapping": "npm:^0.3.25" jsesc: "npm:^2.5.1" - checksum: 10c0/53540e905cd10db05d9aee0a5304e36927f455ce66f95d1253bb8a179f286b88fa7062ea0db354c566fe27f8bb96567566084ffd259f8feaae1de5eccc8afbda + checksum: 10c0/67a1b2f7cc985aaaa11b01e8ddd4fffa4f285837bc7a209738eb8203aa34bdafeb8507ed75fd883ddbabd641a036ca0a8d984e760f28ad4a9d60bff29d0a60bb languageName: node linkType: hard @@ -336,11 +337,11 @@ __metadata: linkType: hard "@babel/helper-module-imports@npm:^7.22.15": - version: 7.22.15 - resolution: "@babel/helper-module-imports@npm:7.22.15" + version: 7.24.3 + resolution: "@babel/helper-module-imports@npm:7.24.3" dependencies: - "@babel/types": "npm:^7.22.15" - checksum: 10c0/4e0d7fc36d02c1b8c8b3006dfbfeedf7a367d3334a04934255de5128115ea0bafdeb3e5736a2559917f0653e4e437400d54542da0468e08d3cbc86d3bbfa8f30 + "@babel/types": "npm:^7.24.0" + checksum: 10c0/052c188adcd100f5e8b6ff0c9643ddaabc58b6700d3bbbc26804141ad68375a9f97d9d173658d373d31853019e65f62610239e3295cdd58e573bdcb2fded188d languageName: node linkType: hard @@ -359,7 +360,7 @@ __metadata: languageName: node linkType: hard -"@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.10.4, @babel/helper-plugin-utils@npm:^7.12.13, @babel/helper-plugin-utils@npm:^7.14.5, @babel/helper-plugin-utils@npm:^7.22.5, @babel/helper-plugin-utils@npm:^7.8.0": +"@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.10.4, @babel/helper-plugin-utils@npm:^7.12.13, @babel/helper-plugin-utils@npm:^7.14.5, @babel/helper-plugin-utils@npm:^7.24.0, @babel/helper-plugin-utils@npm:^7.8.0": version: 7.24.0 resolution: "@babel/helper-plugin-utils@npm:7.24.0" checksum: 10c0/90f41bd1b4dfe7226b1d33a4bb745844c5c63e400f9e4e8bf9103a7ceddd7d425d65333b564d9daba3cebd105985764d51b4bd4c95822b97c2e3ac1201a8a5da @@ -385,9 +386,9 @@ __metadata: linkType: hard "@babel/helper-string-parser@npm:^7.23.4": - version: 7.23.4 - resolution: "@babel/helper-string-parser@npm:7.23.4" - checksum: 10c0/f348d5637ad70b6b54b026d6544bd9040f78d24e7ec245a0fc42293968181f6ae9879c22d89744730d246ce8ec53588f716f102addd4df8bbc79b73ea10004ac + version: 7.24.1 + resolution: "@babel/helper-string-parser@npm:7.24.1" + checksum: 10c0/2f9bfcf8d2f9f083785df0501dbab92770111ece2f90d120352fda6dd2a7d47db11b807d111e6f32aa1ba6d763fe2dc6603d153068d672a5d0ad33ca802632b2 languageName: node linkType: hard @@ -405,34 +406,35 @@ __metadata: languageName: node linkType: hard -"@babel/helpers@npm:^7.24.0": - version: 7.24.0 - resolution: "@babel/helpers@npm:7.24.0" +"@babel/helpers@npm:^7.24.4": + version: 7.24.4 + resolution: "@babel/helpers@npm:7.24.4" dependencies: "@babel/template": "npm:^7.24.0" - "@babel/traverse": "npm:^7.24.0" + "@babel/traverse": "npm:^7.24.1" "@babel/types": "npm:^7.24.0" - checksum: 10c0/dd27c9f11c1c5244ef312fae37636f2fcc69c541c46508017b846c4cf680af059f1922ce84e3f778f123a70d027ded75c96070ee8e906f3bc52dc26dc43df608 + checksum: 10c0/747ef62b7fe87de31a2f3c19ff337a86cbb79be2f6c18af63133b614ab5a8f6da5b06ae4b06fb0e71271cb6a27efec6f8b6c9f44c60b8a18777832dc7929e6c5 languageName: node linkType: hard -"@babel/highlight@npm:^7.23.4": - version: 7.23.4 - resolution: "@babel/highlight@npm:7.23.4" +"@babel/highlight@npm:^7.24.2": + version: 7.24.2 + resolution: "@babel/highlight@npm:7.24.2" dependencies: "@babel/helper-validator-identifier": "npm:^7.22.20" chalk: "npm:^2.4.2" js-tokens: "npm:^4.0.0" - checksum: 10c0/fbff9fcb2f5539289c3c097d130e852afd10d89a3a08ac0b5ebebbc055cc84a4bcc3dcfed463d488cde12dd0902ef1858279e31d7349b2e8cee43913744bda33 + picocolors: "npm:^1.0.0" + checksum: 10c0/98ce00321daedeed33a4ed9362dc089a70375ff1b3b91228b9f05e6591d387a81a8cba68886e207861b8871efa0bc997ceabdd9c90f6cce3ee1b2f7f941b42db languageName: node linkType: hard -"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.23.9, @babel/parser@npm:^7.24.0": - version: 7.24.0 - resolution: "@babel/parser@npm:7.24.0" +"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.23.9, @babel/parser@npm:^7.24.0, @babel/parser@npm:^7.24.1, @babel/parser@npm:^7.24.4": + version: 7.24.4 + resolution: "@babel/parser@npm:7.24.4" bin: parser: ./bin/babel-parser.js - checksum: 10c0/77593d0b9de9906823c4d653bb6cda1c7593837598516330f655f70cba6224a37def7dbe5b4dad0038482d407d8d209eb8be5f48ca9a13357d769f829c5adb8e + checksum: 10c0/8381e1efead5069cb7ed2abc3a583f4a86289b2f376c75cecc69f59a8eb36df18274b1886cecf2f97a6a0dff5334b27330f58535be9b3e4e26102cc50e12eac8 languageName: node linkType: hard @@ -492,13 +494,13 @@ __metadata: linkType: hard "@babel/plugin-syntax-jsx@npm:^7.7.2": - version: 7.23.3 - resolution: "@babel/plugin-syntax-jsx@npm:7.23.3" + version: 7.24.1 + resolution: "@babel/plugin-syntax-jsx@npm:7.24.1" dependencies: - "@babel/helper-plugin-utils": "npm:^7.22.5" + "@babel/helper-plugin-utils": "npm:^7.24.0" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/563bb7599b868773f1c7c1d441ecc9bc53aeb7832775da36752c926fc402a1fa5421505b39e724f71eb217c13e4b93117e081cac39723b0e11dac4c897f33c3e + checksum: 10c0/6cec76fbfe6ca81c9345c2904d8d9a8a0df222f9269f0962ed6eb2eb8f3f10c2f15e993d1ef09dbaf97726bf1792b5851cf5bd9a769f966a19448df6be95d19a languageName: node linkType: hard @@ -580,13 +582,13 @@ __metadata: linkType: hard "@babel/plugin-syntax-typescript@npm:^7.7.2": - version: 7.23.3 - resolution: "@babel/plugin-syntax-typescript@npm:7.23.3" + version: 7.24.1 + resolution: "@babel/plugin-syntax-typescript@npm:7.24.1" dependencies: - "@babel/helper-plugin-utils": "npm:^7.22.5" + "@babel/helper-plugin-utils": "npm:^7.24.0" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/4d6e9cdb9d0bfb9bd9b220fc951d937fce2ca69135ec121153572cebe81d86abc9a489208d6b69ee5f10cadcaeffa10d0425340a5029e40e14a6025021b90948 + checksum: 10c0/7a81e277dcfe3138847e8e5944e02a42ff3c2e864aea6f33fd9b70d1556d12b0e70f0d56cc1985d353c91bcbf8fe163e6cc17418da21129b7f7f1d8b9ac00c93 languageName: node linkType: hard @@ -601,25 +603,25 @@ __metadata: languageName: node linkType: hard -"@babel/traverse@npm:^7.24.0": - version: 7.24.0 - resolution: "@babel/traverse@npm:7.24.0" +"@babel/traverse@npm:^7.24.1": + version: 7.24.1 + resolution: "@babel/traverse@npm:7.24.1" dependencies: - "@babel/code-frame": "npm:^7.23.5" - "@babel/generator": "npm:^7.23.6" + "@babel/code-frame": "npm:^7.24.1" + "@babel/generator": "npm:^7.24.1" "@babel/helper-environment-visitor": "npm:^7.22.20" "@babel/helper-function-name": "npm:^7.23.0" "@babel/helper-hoist-variables": "npm:^7.22.5" "@babel/helper-split-export-declaration": "npm:^7.22.6" - "@babel/parser": "npm:^7.24.0" + "@babel/parser": "npm:^7.24.1" "@babel/types": "npm:^7.24.0" debug: "npm:^4.3.1" globals: "npm:^11.1.0" - checksum: 10c0/55ffd2b0ce0fbd0a09051edc4def4fb1e96f35e0b100c0dc2a7429df569971ae312c290e980e423471f350961705698a257c7eea8c8304918024cc26f02468ba + checksum: 10c0/c087b918f6823776537ba246136c70e7ce0719fc05361ebcbfd16f4e6f2f6f1f8f4f9167f1d9b675f27d12074839605189cc9d689de20b89a85e7c140f23daab languageName: node linkType: hard -"@babel/types@npm:^7.0.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.22.15, @babel/types@npm:^7.22.5, @babel/types@npm:^7.23.0, @babel/types@npm:^7.23.6, @babel/types@npm:^7.24.0, @babel/types@npm:^7.3.3, @babel/types@npm:^7.8.3": +"@babel/types@npm:^7.0.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.22.5, @babel/types@npm:^7.23.0, @babel/types@npm:^7.24.0, @babel/types@npm:^7.3.3, @babel/types@npm:^7.8.3": version: 7.24.0 resolution: "@babel/types@npm:7.24.0" dependencies: @@ -721,9 +723,9 @@ __metadata: linkType: hard "@humanwhocodes/object-schema@npm:^2.0.2": - version: 2.0.2 - resolution: "@humanwhocodes/object-schema@npm:2.0.2" - checksum: 10c0/6fd83dc320231d71c4541d0244051df61f301817e9f9da9fd4cb7e44ec8aacbde5958c1665b0c419401ab935114fdf532a6ad5d4e7294b1af2f347dd91a6983f + version: 2.0.3 + resolution: "@humanwhocodes/object-schema@npm:2.0.3" + checksum: 10c0/80520eabbfc2d32fe195a93557cef50dfe8c8905de447f022675aaf66abc33ae54098f5ea78548d925aa671cd4ab7c7daa5ad704fe42358c9b5e7db60f80696c languageName: node linkType: hard @@ -735,64 +737,70 @@ __metadata: linkType: hard "@inquirer/confirm@npm:^3.0.0": - version: 3.0.0 - resolution: "@inquirer/confirm@npm:3.0.0" + version: 3.1.4 + resolution: "@inquirer/confirm@npm:3.1.4" dependencies: - "@inquirer/core": "npm:^7.0.0" - "@inquirer/type": "npm:^1.2.0" - checksum: 10c0/70c6a7fa13c4e71207a984840b4619b367aae00b204dff80e6d8d59736874066c456610684ccd1a0efd679fa9c398b62d6b66a759d3349b957709442ddb2557e + "@inquirer/core": "npm:^8.0.0" + "@inquirer/type": "npm:^1.3.0" + checksum: 10c0/be7977b1ca35416c32ab9fe0d2f2c1b20e9a6145b0ee2e9dec283e8e363d200af8a8a9455dd09432f82bb31eb97037ce3238917b7016ac00737cd92c1d32a898 languageName: node linkType: hard -"@inquirer/core@npm:^7.0.0": - version: 7.0.0 - resolution: "@inquirer/core@npm:7.0.0" +"@inquirer/core@npm:^8.0.0": + version: 8.0.0 + resolution: "@inquirer/core@npm:8.0.0" dependencies: - "@inquirer/type": "npm:^1.2.0" + "@inquirer/figures": "npm:^1.0.0" + "@inquirer/type": "npm:^1.3.0" "@types/mute-stream": "npm:^0.0.4" - "@types/node": "npm:^20.11.16" + "@types/node": "npm:^20.12.7" "@types/wrap-ansi": "npm:^3.0.0" ansi-escapes: "npm:^4.3.2" chalk: "npm:^4.1.2" cli-spinners: "npm:^2.9.2" cli-width: "npm:^4.1.0" - figures: "npm:^3.2.0" mute-stream: "npm:^1.0.0" - run-async: "npm:^3.0.0" signal-exit: "npm:^4.1.0" strip-ansi: "npm:^6.0.1" wrap-ansi: "npm:^6.2.0" - checksum: 10c0/7a2a0e322b1a9fee996d369ebf2f220e236073147510df85d80ed6c90ce229c7ee4e2c8e10cefe1b0a04b4f17e62be5fb06dc84cdf509587c5c7baf3a4d6ddc4 + checksum: 10c0/54a65cefb65475e6ef533a414a77a6b7344cd1812239c62ccad1dcc63249088ed325c0e458c73b8681f559e49e95c628e288f46f2b230e20bbf269bd3137e078 + languageName: node + linkType: hard + +"@inquirer/figures@npm:^1.0.0": + version: 1.0.0 + resolution: "@inquirer/figures@npm:1.0.0" + checksum: 10c0/18fb0f68968173e1425b5d7dbc3c01f2f43293f2cc957e6dfe6ee9b3e42d2eec450351192f4440c96d081fa7d094e75d8bc37e300f6fcad548b32635f556f56a languageName: node linkType: hard "@inquirer/input@npm:^2.0.0": - version: 2.0.0 - resolution: "@inquirer/input@npm:2.0.0" + version: 2.1.4 + resolution: "@inquirer/input@npm:2.1.4" dependencies: - "@inquirer/core": "npm:^7.0.0" - "@inquirer/type": "npm:^1.2.0" - checksum: 10c0/0368b00de4c3245acdd98a4030001a83c24f1047afe9c2e8654be75573466a51583d7a8e70c738138d9110d8d84f6ffea8fc76b04aecd451add38b0fba4c2294 + "@inquirer/core": "npm:^8.0.0" + "@inquirer/type": "npm:^1.3.0" + checksum: 10c0/22c1683f446b15b4706adfdefdb38203874e6db498921829160c33cb1a95b4f39723ba820a335cf04f56ce29ca90caaf6b9403e7db7c4eba69f4ea69a43c9dd2 languageName: node linkType: hard "@inquirer/select@npm:^2.0.0": - version: 2.0.0 - resolution: "@inquirer/select@npm:2.0.0" + version: 2.3.0 + resolution: "@inquirer/select@npm:2.3.0" dependencies: - "@inquirer/core": "npm:^7.0.0" - "@inquirer/type": "npm:^1.2.0" + "@inquirer/core": "npm:^8.0.0" + "@inquirer/figures": "npm:^1.0.0" + "@inquirer/type": "npm:^1.3.0" ansi-escapes: "npm:^4.3.2" chalk: "npm:^4.1.2" - figures: "npm:^3.2.0" - checksum: 10c0/31c5ae8e0beea7fedb0b625814a39f52e6e32b04f9e11ded2465013d105c2066fd7d5f4773bd65b23d8c99fd0009864f60335dd22493c109b5f0765ef90f2c5d + checksum: 10c0/38052e4ae709f18b70296aa69583ef1ce62656f530285b0f8ff2f0c7dac55a15e04a718e4a4023d05d6cba8cf0bace41127901221515805164146e45fd22f158 languageName: node linkType: hard -"@inquirer/type@npm:^1.2.0": - version: 1.2.0 - resolution: "@inquirer/type@npm:1.2.0" - checksum: 10c0/f28c8acaff928b93bc2cb735b8d4615e435a9148d7c941b67ff91afa996172af970de3fe94953a43eb6514da93ef94ddb75c32530b5f113cd3b8bde6f7d10d47 +"@inquirer/type@npm:^1.3.0": + version: 1.3.0 + resolution: "@inquirer/type@npm:1.3.0" + checksum: 10c0/7d2886ee3fd24f16266b1724393dd6ed4cf22f6aa95665db022c9f2a1cea41b1b1fa778342f4accf3f251282d8cb6cdfe076535b0c763d3f0421da72717fe37a languageName: node linkType: hard @@ -1060,7 +1068,7 @@ __metadata: languageName: node linkType: hard -"@jridgewell/gen-mapping@npm:^0.3.0, @jridgewell/gen-mapping@npm:^0.3.2, @jridgewell/gen-mapping@npm:^0.3.5": +"@jridgewell/gen-mapping@npm:^0.3.5": version: 0.3.5 resolution: "@jridgewell/gen-mapping@npm:0.3.5" dependencies: @@ -1086,12 +1094,12 @@ __metadata: linkType: hard "@jridgewell/source-map@npm:^0.3.3": - version: 0.3.5 - resolution: "@jridgewell/source-map@npm:0.3.5" + version: 0.3.6 + resolution: "@jridgewell/source-map@npm:0.3.6" dependencies: - "@jridgewell/gen-mapping": "npm:^0.3.0" - "@jridgewell/trace-mapping": "npm:^0.3.9" - checksum: 10c0/b985d9ebd833a21a6e9ace820c8a76f60345a34d9e28d98497c16b6e93ce1f131bff0abd45f8585f14aa382cce678ed680d628c631b40a9616a19cfbc2049b68 + "@jridgewell/gen-mapping": "npm:^0.3.5" + "@jridgewell/trace-mapping": "npm:^0.3.25" + checksum: 10c0/6a4ecc713ed246ff8e5bdcc1ef7c49aaa93f7463d948ba5054dda18b02dcc6a055e2828c577bcceee058f302ce1fc95595713d44f5c45e43d459f88d267f2f04 languageName: node linkType: hard @@ -1112,7 +1120,7 @@ __metadata: languageName: node linkType: hard -"@jridgewell/trace-mapping@npm:^0.3.12, @jridgewell/trace-mapping@npm:^0.3.17, @jridgewell/trace-mapping@npm:^0.3.18, @jridgewell/trace-mapping@npm:^0.3.20, @jridgewell/trace-mapping@npm:^0.3.24, @jridgewell/trace-mapping@npm:^0.3.9": +"@jridgewell/trace-mapping@npm:^0.3.12, @jridgewell/trace-mapping@npm:^0.3.18, @jridgewell/trace-mapping@npm:^0.3.20, @jridgewell/trace-mapping@npm:^0.3.24, @jridgewell/trace-mapping@npm:^0.3.25": version: 0.3.25 resolution: "@jridgewell/trace-mapping@npm:0.3.25" dependencies: @@ -1122,19 +1130,19 @@ __metadata: languageName: node linkType: hard -"@koa/cors@npm:^4.0.0": - version: 4.0.0 - resolution: "@koa/cors@npm:4.0.0" +"@koa/cors@npm:^5.0.0": + version: 5.0.0 + resolution: "@koa/cors@npm:5.0.0" dependencies: vary: "npm:^1.1.2" - checksum: 10c0/53caa512e7aacf8d4ad0d9eb427fa84bdfd6fccb9a060b317d77acf352941ad7935bbc0b4569c0c73d9cdef0b3fce83b7e00190548f31076366dd8e60d7e1198 + checksum: 10c0/49e5f3b861590bd81aa3663a2f0658234a9b378840bb54a2947b3c5f2067f9d966b6fa2e9049fdc7c74c787456d1885bacd0b7ee1f134274d28282c7df99c3fd languageName: node linkType: hard "@leichtgewicht/ip-codec@npm:^2.0.1": - version: 2.0.4 - resolution: "@leichtgewicht/ip-codec@npm:2.0.4" - checksum: 10c0/3b0d8844d1d47c0a5ed7267c2964886adad3a642b85d06f95c148eeefd80cdabbd6aa0d63ccde8239967a2e9b6bb734a16bd57e1fda3d16bf56d50a7e7ec131b + version: 2.0.5 + resolution: "@leichtgewicht/ip-codec@npm:2.0.5" + checksum: 10c0/14a0112bd59615eef9e3446fea018045720cd3da85a98f801a685a818b0d96ef2a1f7227e8d271def546b2e2a0fe91ef915ba9dc912ab7967d2317b1a051d66b languageName: node linkType: hard @@ -1148,11 +1156,11 @@ __metadata: linkType: hard "@noble/curves@npm:^1.2.0": - version: 1.3.0 - resolution: "@noble/curves@npm:1.3.0" + version: 1.4.0 + resolution: "@noble/curves@npm:1.4.0" dependencies: - "@noble/hashes": "npm:1.3.3" - checksum: 10c0/704bf8fda8e1365a9bb9e9945bd06645ef4ce85aa2fac5594abe09f19889197518152319481b89a271e0ee011787bd2ee87202441500bca7ca587a2c3ac10b01 + "@noble/hashes": "npm:1.4.0" + checksum: 10c0/31fbc370df91bcc5a920ca3f2ce69c8cf26dc94775a36124ed8a5a3faf0453badafd2ee4337061ffea1b43c623a90ee8b286a5a81604aaf9563bdad7ff795d18 languageName: node linkType: hard @@ -1163,7 +1171,14 @@ __metadata: languageName: node linkType: hard -"@noble/hashes@npm:1.3.3, @noble/hashes@npm:~1.3.0, @noble/hashes@npm:~1.3.2": +"@noble/hashes@npm:1.4.0": + version: 1.4.0 + resolution: "@noble/hashes@npm:1.4.0" + checksum: 10c0/8c3f005ee72e7b8f9cff756dfae1241485187254e3f743873e22073d63906863df5d4f13d441b7530ea614b7a093f0d889309f28b59850f33b66cb26a779a4a5 + languageName: node + linkType: hard + +"@noble/hashes@npm:~1.3.0, @noble/hashes@npm:~1.3.2": version: 1.3.3 resolution: "@noble/hashes@npm:1.3.3" checksum: 10c0/23c020b33da4172c988e44100e33cd9f8f6250b68b43c467d3551f82070ebd9716e0d9d2347427aa3774c85934a35fa9ee6f026fca2117e3fa12db7bedae7668 @@ -1198,15 +1213,15 @@ __metadata: linkType: hard "@npmcli/agent@npm:^2.0.0": - version: 2.2.1 - resolution: "@npmcli/agent@npm:2.2.1" + version: 2.2.2 + resolution: "@npmcli/agent@npm:2.2.2" dependencies: agent-base: "npm:^7.1.0" http-proxy-agent: "npm:^7.0.0" https-proxy-agent: "npm:^7.0.1" lru-cache: "npm:^10.0.1" - socks-proxy-agent: "npm:^8.0.1" - checksum: 10c0/38ee5cbe8f3cde13be916e717bfc54fd1a7605c07af056369ff894e244c221e0b56b08ca5213457477f9bc15bca9e729d51a4788829b5c3cf296b3c996147f76 + socks-proxy-agent: "npm:^8.0.3" + checksum: 10c0/325e0db7b287d4154ecd164c0815c08007abfb07653cc57bceded17bb7fd240998a3cbdbe87d700e30bef494885eccc725ab73b668020811d56623d145b524ae languageName: node linkType: hard @@ -1285,9 +1300,9 @@ __metadata: linkType: hard "@scure/base@npm:~1.1.0, @scure/base@npm:~1.1.2": - version: 1.1.5 - resolution: "@scure/base@npm:1.1.5" - checksum: 10c0/6eb07be0202fac74a57c79d0d00a45f6f7e57447010c1e3d90a4275d197829727b7abc54b248fc6f9bef9ae374f7be5ee9154dde5b5b73da773560bf17aa8504 + version: 1.1.6 + resolution: "@scure/base@npm:1.1.6" + checksum: 10c0/237a46a1f45391fc57719154f14295db936a0b1562ea3e182dd42d7aca082dbb7062a28d6c49af16a7e478b12dae8a0fe678d921ea5056bcc30238d29eb05c55 languageName: node linkType: hard @@ -1352,9 +1367,9 @@ __metadata: linkType: hard "@tsconfig/node10@npm:^1.0.7": - version: 1.0.9 - resolution: "@tsconfig/node10@npm:1.0.9" - checksum: 10c0/c176a2c1e1b16be120c328300ea910df15fb9a5277010116d26818272341a11483c5a80059389d04edacf6fd2d03d4687ad3660870fdd1cc0b7109e160adb220 + version: 1.0.11 + resolution: "@tsconfig/node10@npm:1.0.11" + checksum: 10c0/28a0710e5d039e0de484bdf85fee883bfd3f6a8980601f4d44066b0a6bcd821d31c4e231d1117731c4e24268bd4cf2a788a6787c12fc7f8d11014c07d582783c languageName: node linkType: hard @@ -1469,12 +1484,12 @@ __metadata: linkType: hard "@types/eslint@npm:*": - version: 8.56.5 - resolution: "@types/eslint@npm:8.56.5" + version: 8.56.9 + resolution: "@types/eslint@npm:8.56.9" dependencies: "@types/estree": "npm:*" "@types/json-schema": "npm:*" - checksum: 10c0/1d5d70ea107c63adfaf63020f85859c404f90c21ada2a655376b8e76109df354643797e30c7afc3b2de84797d9f5ce9f03f53a5d29a186706a44afd90f76597c + checksum: 10c0/a800e3d10bd12fc837773101c35a65c189528e306bc41eca9f30176f5ede4d35944a0c0e16b668971db3521df2f2bef62ab2471740eadc72aeb39dbaba6c9101 languageName: node linkType: hard @@ -1486,14 +1501,14 @@ __metadata: linkType: hard "@types/express-serve-static-core@npm:*, @types/express-serve-static-core@npm:^4.17.33": - version: 4.17.43 - resolution: "@types/express-serve-static-core@npm:4.17.43" + version: 4.19.0 + resolution: "@types/express-serve-static-core@npm:4.19.0" dependencies: "@types/node": "npm:*" "@types/qs": "npm:*" "@types/range-parser": "npm:*" "@types/send": "npm:*" - checksum: 10c0/12480527eef86ad9f748d785811c88e6bb89f4a76e531cf2e18f1f4f0743e46783cf4d27a939dec96aec8770c54c060d9e697bb8544ecd202098140688c3b222 + checksum: 10c0/38a13dfbb38d18526276e68dae1097eb0ebef296e76bff2a9bf6831c052c2f87797e910c87bd3f0dd1a1b4136241c9d7c841779a00b22576d12aa9b483a63349 languageName: node linkType: hard @@ -1600,13 +1615,6 @@ __metadata: languageName: node linkType: hard -"@types/mime@npm:*": - version: 3.0.4 - resolution: "@types/mime@npm:3.0.4" - checksum: 10c0/db478bc0f99e40f7b3e01d356a9bdf7817060808a294978111340317bcd80ca35382855578c5b60fbc84ae449674bd9bb38427b18417e1f8f19e4f72f8b242cd - languageName: node - linkType: hard - "@types/mime@npm:^1": version: 1.3.5 resolution: "@types/mime@npm:1.3.5" @@ -1639,12 +1647,12 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:*, @types/node@npm:^20.11.16, @types/node@npm:^20.11.17, @types/node@npm:^20.5.9": - version: 20.11.24 - resolution: "@types/node@npm:20.11.24" +"@types/node@npm:*, @types/node@npm:^20.11.17, @types/node@npm:^20.12.7, @types/node@npm:^20.5.9": + version: 20.12.7 + resolution: "@types/node@npm:20.12.7" dependencies: undici-types: "npm:~5.26.4" - checksum: 10c0/5a62225eb4797b41e6953f9c08c4611d607b5422ddd153312fc81ed6ed37115228ae27e3e3caa1a3bf52d88310306a196ba1cfbd8b2ec918a20f64d80dfa22c9 + checksum: 10c0/dce80d63a3b91892b321af823d624995c61e39c6a223cc0ac481a44d337640cc46931d33efb3beeed75f5c85c3bda1d97cef4c5cd4ec333caf5dee59cff6eca0 languageName: node linkType: hard @@ -1656,16 +1664,16 @@ __metadata: linkType: hard "@types/prop-types@npm:*": - version: 15.7.11 - resolution: "@types/prop-types@npm:15.7.11" - checksum: 10c0/e53423cf9d510515ef8b47ff42f4f1b65a7b7b37c8704e2dbfcb9a60defe0c0e1f3cb1acfdeb466bad44ca938d7c79bffdd51b48ffb659df2432169d0b27a132 + version: 15.7.12 + resolution: "@types/prop-types@npm:15.7.12" + checksum: 10c0/1babcc7db6a1177779f8fde0ccc78d64d459906e6ef69a4ed4dd6339c920c2e05b074ee5a92120fe4e9d9f1a01c952f843ebd550bee2332fc2ef81d1706878f8 languageName: node linkType: hard "@types/qs@npm:*": - version: 6.9.12 - resolution: "@types/qs@npm:6.9.12" - checksum: 10c0/21a74f2b78d0839cee37f1a632f3361352f7dceac9edffd117227a695a13e58e18c138aac1f29403f2408221e678f538ca0b37d55012f8bba96d55905edbfe82 + version: 6.9.14 + resolution: "@types/qs@npm:6.9.14" + checksum: 10c0/11ad1eb7f6d7c216002789959d88acc7c43f72854fa4335f01de0df41b4c4024668dace8a37ba12270314345ede0ec6b07f93053a45e7bd4cd7318a3dcf0b6b8 languageName: node linkType: hard @@ -1677,22 +1685,21 @@ __metadata: linkType: hard "@types/react-dom@npm:^18.2.7": - version: 18.2.19 - resolution: "@types/react-dom@npm:18.2.19" + version: 18.2.25 + resolution: "@types/react-dom@npm:18.2.25" dependencies: "@types/react": "npm:*" - checksum: 10c0/88d7c6daa4659f661d0c97985d9fca492f24b421a34bb614dcd94c343aed7bea121463149e97fb01ecaa693be17b7d1542cf71ddb1705f3889a81eb2639a88aa + checksum: 10c0/87604407eca6884c5b4d4657cb511dc5ba28ea1cfa5d0ce1fc2d659a7ad1b64ae85dcda60e3f010641f9a52a6a60dfcaa6be3b0d0de9d624475052a13dae01f4 languageName: node linkType: hard "@types/react@npm:*, @types/react@npm:^18.2.15": - version: 18.2.62 - resolution: "@types/react@npm:18.2.62" + version: 18.2.78 + resolution: "@types/react@npm:18.2.78" dependencies: "@types/prop-types": "npm:*" - "@types/scheduler": "npm:*" csstype: "npm:^3.0.2" - checksum: 10c0/a45a986723b0febdcdcea754cfa426345f588fd9a522ab4136220a0b514ccba8f4986b23c73dd8e863d465ee1e733779bffffdd57c19488a318a5135f030c1e8 + checksum: 10c0/5eb8e1dd98c29aeddf40b90f466d1a9ce83b113d42a096633d632b834e7ae9821f24ba7999928de9d98cca37764532a7ea35355a8103a377d8baa750f1841b5c languageName: node linkType: hard @@ -1703,13 +1710,6 @@ __metadata: languageName: node linkType: hard -"@types/scheduler@npm:*": - version: 0.16.8 - resolution: "@types/scheduler@npm:0.16.8" - checksum: 10c0/f86de504945b8fc41b1f391f847444d542e2e4067cf7e5d9bfeb5d2d2393d3203b1161bc0ef3b1e104d828dabfb60baf06e8d2c27e27ff7e8258e6e618d8c4ec - languageName: node - linkType: hard - "@types/semver@npm:^7.5.0": version: 7.5.8 resolution: "@types/semver@npm:7.5.8" @@ -1737,13 +1737,13 @@ __metadata: linkType: hard "@types/serve-static@npm:*, @types/serve-static@npm:^1.13.10": - version: 1.15.5 - resolution: "@types/serve-static@npm:1.15.5" + version: 1.15.7 + resolution: "@types/serve-static@npm:1.15.7" dependencies: "@types/http-errors": "npm:*" - "@types/mime": "npm:*" "@types/node": "npm:*" - checksum: 10c0/811d1a2f7e74a872195e7a013bcd87a2fb1edf07eaedcb9dcfd20c1eb4bc56ad4ea0d52141c13192c91ccda7c8aeb8a530d8a7e60b9c27f5990d7e62e0fecb03 + "@types/send": "npm:*" + checksum: 10c0/26ec864d3a626ea627f8b09c122b623499d2221bbf2f470127f4c9ebfe92bd8a6bb5157001372d4c4bd0dd37a1691620217d9dc4df5aa8f779f3fd996b1c60ae languageName: node linkType: hard @@ -1925,13 +1925,13 @@ __metadata: languageName: node linkType: hard -"@webassemblyjs/ast@npm:1.11.6, @webassemblyjs/ast@npm:^1.11.5": - version: 1.11.6 - resolution: "@webassemblyjs/ast@npm:1.11.6" +"@webassemblyjs/ast@npm:1.12.1, @webassemblyjs/ast@npm:^1.12.1": + version: 1.12.1 + resolution: "@webassemblyjs/ast@npm:1.12.1" dependencies: "@webassemblyjs/helper-numbers": "npm:1.11.6" "@webassemblyjs/helper-wasm-bytecode": "npm:1.11.6" - checksum: 10c0/e28476a183c8a1787adcf0e5df1d36ec4589467ab712c674fe4f6769c7fb19d1217bfb5856b3edd0f3e0a148ebae9e4bbb84110cee96664966dfef204d9c31fb + checksum: 10c0/ba7f2b96c6e67e249df6156d02c69eb5f1bd18d5005303cdc42accb053bebbbde673826e54db0437c9748e97abd218366a1d13fa46859b23cde611b6b409998c languageName: node linkType: hard @@ -1949,10 +1949,10 @@ __metadata: languageName: node linkType: hard -"@webassemblyjs/helper-buffer@npm:1.11.6": - version: 1.11.6 - resolution: "@webassemblyjs/helper-buffer@npm:1.11.6" - checksum: 10c0/55b5d67db95369cdb2a505ae7ebdf47194d49dfc1aecb0f5403277dcc899c7d3e1f07e8d279646adf8eafd89959272db62ca66fbe803321661ab184176ddfd3a +"@webassemblyjs/helper-buffer@npm:1.12.1": + version: 1.12.1 + resolution: "@webassemblyjs/helper-buffer@npm:1.12.1" + checksum: 10c0/0270724afb4601237410f7fd845ab58ccda1d5456a8783aadfb16eaaf3f2c9610c28e4a5bcb6ad880cde5183c82f7f116d5ccfc2310502439d33f14b6888b48a languageName: node linkType: hard @@ -1974,15 +1974,15 @@ __metadata: languageName: node linkType: hard -"@webassemblyjs/helper-wasm-section@npm:1.11.6": - version: 1.11.6 - resolution: "@webassemblyjs/helper-wasm-section@npm:1.11.6" +"@webassemblyjs/helper-wasm-section@npm:1.12.1": + version: 1.12.1 + resolution: "@webassemblyjs/helper-wasm-section@npm:1.12.1" dependencies: - "@webassemblyjs/ast": "npm:1.11.6" - "@webassemblyjs/helper-buffer": "npm:1.11.6" + "@webassemblyjs/ast": "npm:1.12.1" + "@webassemblyjs/helper-buffer": "npm:1.12.1" "@webassemblyjs/helper-wasm-bytecode": "npm:1.11.6" - "@webassemblyjs/wasm-gen": "npm:1.11.6" - checksum: 10c0/b79b19a63181f32e5ee0e786fa8264535ea5360276033911fae597d2de15e1776f028091d08c5a813a3901fd2228e74cd8c7e958fded064df734f00546bef8ce + "@webassemblyjs/wasm-gen": "npm:1.12.1" + checksum: 10c0/0546350724d285ae3c26e6fc444be4c3b5fb824f3be0ec8ceb474179dc3f4430336dd2e36a44b3e3a1a6815960e5eec98cd9b3a8ec66dc53d86daedd3296a6a2 languageName: node linkType: hard @@ -2011,68 +2011,68 @@ __metadata: languageName: node linkType: hard -"@webassemblyjs/wasm-edit@npm:^1.11.5": - version: 1.11.6 - resolution: "@webassemblyjs/wasm-edit@npm:1.11.6" +"@webassemblyjs/wasm-edit@npm:^1.12.1": + version: 1.12.1 + resolution: "@webassemblyjs/wasm-edit@npm:1.12.1" dependencies: - "@webassemblyjs/ast": "npm:1.11.6" - "@webassemblyjs/helper-buffer": "npm:1.11.6" + "@webassemblyjs/ast": "npm:1.12.1" + "@webassemblyjs/helper-buffer": "npm:1.12.1" "@webassemblyjs/helper-wasm-bytecode": "npm:1.11.6" - "@webassemblyjs/helper-wasm-section": "npm:1.11.6" - "@webassemblyjs/wasm-gen": "npm:1.11.6" - "@webassemblyjs/wasm-opt": "npm:1.11.6" - "@webassemblyjs/wasm-parser": "npm:1.11.6" - "@webassemblyjs/wast-printer": "npm:1.11.6" - checksum: 10c0/9a56b6bf635cf7aa5d6e926eaddf44c12fba050170e452a8e17ab4e1b937708678c03f5817120fb9de1e27167667ce693d16ce718d41e5a16393996a6017ab73 + "@webassemblyjs/helper-wasm-section": "npm:1.12.1" + "@webassemblyjs/wasm-gen": "npm:1.12.1" + "@webassemblyjs/wasm-opt": "npm:1.12.1" + "@webassemblyjs/wasm-parser": "npm:1.12.1" + "@webassemblyjs/wast-printer": "npm:1.12.1" + checksum: 10c0/972f5e6c522890743999e0ed45260aae728098801c6128856b310dd21f1ee63435fc7b518e30e0ba1cdafd0d1e38275829c1e4451c3536a1d9e726e07a5bba0b languageName: node linkType: hard -"@webassemblyjs/wasm-gen@npm:1.11.6": - version: 1.11.6 - resolution: "@webassemblyjs/wasm-gen@npm:1.11.6" +"@webassemblyjs/wasm-gen@npm:1.12.1": + version: 1.12.1 + resolution: "@webassemblyjs/wasm-gen@npm:1.12.1" dependencies: - "@webassemblyjs/ast": "npm:1.11.6" + "@webassemblyjs/ast": "npm:1.12.1" "@webassemblyjs/helper-wasm-bytecode": "npm:1.11.6" "@webassemblyjs/ieee754": "npm:1.11.6" "@webassemblyjs/leb128": "npm:1.11.6" "@webassemblyjs/utf8": "npm:1.11.6" - checksum: 10c0/ce9a39d3dab2eb4a5df991bc9f3609960daa4671d25d700f4617152f9f79da768547359f817bee10cd88532c3e0a8a1714d383438e0a54217eba53cb822bd5ad + checksum: 10c0/1e257288177af9fa34c69cab94f4d9036ebed611f77f3897c988874e75182eeeec759c79b89a7a49dd24624fc2d3d48d5580b62b67c4a1c9bfbdcd266b281c16 languageName: node linkType: hard -"@webassemblyjs/wasm-opt@npm:1.11.6": - version: 1.11.6 - resolution: "@webassemblyjs/wasm-opt@npm:1.11.6" +"@webassemblyjs/wasm-opt@npm:1.12.1": + version: 1.12.1 + resolution: "@webassemblyjs/wasm-opt@npm:1.12.1" dependencies: - "@webassemblyjs/ast": "npm:1.11.6" - "@webassemblyjs/helper-buffer": "npm:1.11.6" - "@webassemblyjs/wasm-gen": "npm:1.11.6" - "@webassemblyjs/wasm-parser": "npm:1.11.6" - checksum: 10c0/82788408054171688e9f12883b693777219366d6867003e34dccc21b4a0950ef53edc9d2b4d54cabdb6ee869cf37c8718401b4baa4f70a7f7dd3867c75637298 + "@webassemblyjs/ast": "npm:1.12.1" + "@webassemblyjs/helper-buffer": "npm:1.12.1" + "@webassemblyjs/wasm-gen": "npm:1.12.1" + "@webassemblyjs/wasm-parser": "npm:1.12.1" + checksum: 10c0/992a45e1f1871033c36987459436ab4e6430642ca49328e6e32a13de9106fe69ae6c0ac27d7050efd76851e502d11cd1ac0e06b55655dfa889ad82f11a2712fb languageName: node linkType: hard -"@webassemblyjs/wasm-parser@npm:1.11.6, @webassemblyjs/wasm-parser@npm:^1.11.5": - version: 1.11.6 - resolution: "@webassemblyjs/wasm-parser@npm:1.11.6" +"@webassemblyjs/wasm-parser@npm:1.12.1, @webassemblyjs/wasm-parser@npm:^1.12.1": + version: 1.12.1 + resolution: "@webassemblyjs/wasm-parser@npm:1.12.1" dependencies: - "@webassemblyjs/ast": "npm:1.11.6" + "@webassemblyjs/ast": "npm:1.12.1" "@webassemblyjs/helper-api-error": "npm:1.11.6" "@webassemblyjs/helper-wasm-bytecode": "npm:1.11.6" "@webassemblyjs/ieee754": "npm:1.11.6" "@webassemblyjs/leb128": "npm:1.11.6" "@webassemblyjs/utf8": "npm:1.11.6" - checksum: 10c0/7a97a5f34f98bdcfd812157845a06d53f3d3f67dbd4ae5d6bf66e234e17dc4a76b2b5e74e5dd70b4cab9778fc130194d50bbd6f9a1d23e15ed1ed666233d6f5f + checksum: 10c0/e85cec1acad07e5eb65b92d37c8e6ca09c6ca50d7ca58803a1532b452c7321050a0328c49810c337cc2dfd100c5326a54d5ebd1aa5c339ebe6ef10c250323a0e languageName: node linkType: hard -"@webassemblyjs/wast-printer@npm:1.11.6": - version: 1.11.6 - resolution: "@webassemblyjs/wast-printer@npm:1.11.6" +"@webassemblyjs/wast-printer@npm:1.12.1": + version: 1.12.1 + resolution: "@webassemblyjs/wast-printer@npm:1.12.1" dependencies: - "@webassemblyjs/ast": "npm:1.11.6" + "@webassemblyjs/ast": "npm:1.12.1" "@xtuc/long": "npm:4.2.2" - checksum: 10c0/916b90fa3a8aadd95ca41c21d4316d0a7582cf6d0dcf6d9db86ab0de823914df513919fba60ac1edd227ff00e93a66b927b15cbddd36b69d8a34c8815752633c + checksum: 10c0/39bf746eb7a79aa69953f194943bbc43bebae98bd7cadd4d8bc8c0df470ca6bf9d2b789effaa180e900fab4e2691983c1f7d41571458bd2a26267f2f0c73705a languageName: node linkType: hard @@ -2235,12 +2235,12 @@ __metadata: languageName: node linkType: hard -"agent-base@npm:^7.0.2, agent-base@npm:^7.1.0": - version: 7.1.0 - resolution: "agent-base@npm:7.1.0" +"agent-base@npm:^7.0.2, agent-base@npm:^7.1.0, agent-base@npm:^7.1.1": + version: 7.1.1 + resolution: "agent-base@npm:7.1.1" dependencies: debug: "npm:^4.3.4" - checksum: 10c0/fc974ab57ffdd8421a2bc339644d312a9cca320c20c3393c9d8b1fd91731b9bbabdb985df5fc860f5b79d81c3e350daa3fcb31c5c07c0bb385aafc817df004ce + checksum: 10c0/e59ce7bed9c63bf071a30cc471f2933862044c97fd9958967bfe22521d7a0f601ce4ed5a8c011799d0c726ca70312142ae193bbebb60f576b52be19d4a363b50 languageName: node linkType: hard @@ -2495,15 +2495,16 @@ __metadata: linkType: hard "array-includes@npm:^3.1.7": - version: 3.1.7 - resolution: "array-includes@npm:3.1.7" + version: 3.1.8 + resolution: "array-includes@npm:3.1.8" dependencies: - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.2.0" - es-abstract: "npm:^1.22.1" - get-intrinsic: "npm:^1.2.1" + call-bind: "npm:^1.0.7" + define-properties: "npm:^1.2.1" + es-abstract: "npm:^1.23.2" + es-object-atoms: "npm:^1.0.0" + get-intrinsic: "npm:^1.2.4" is-string: "npm:^1.0.7" - checksum: 10c0/692907bd7f19d06dc58ccb761f34b58f5dc0b437d2b47a8fe42a1501849a5cf5c27aed3d521a9702667827c2c85a7e75df00a402c438094d87fc43f39ebf9b2b + checksum: 10c0/5b1004d203e85873b96ddc493f090c9672fd6c80d7a60b798da8a14bff8a670ff95db5aafc9abc14a211943f05220dacf8ea17638ae0af1a6a47b8c0b48ce370 languageName: node linkType: hard @@ -2514,29 +2515,17 @@ __metadata: languageName: node linkType: hard -"array.prototype.filter@npm:^1.0.3": - version: 1.0.3 - resolution: "array.prototype.filter@npm:1.0.3" - dependencies: - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.2.0" - es-abstract: "npm:^1.22.1" - es-array-method-boxes-properly: "npm:^1.0.0" - is-string: "npm:^1.0.7" - checksum: 10c0/8b70b5f866df5d90fa27aa5bfa30f5fefc44cbea94b0513699d761713658077c2a24cbf06aac5179eabddb6c93adc467af4c288b7a839c5bc5a769ee5a2d48ad - languageName: node - linkType: hard - "array.prototype.findlastindex@npm:^1.2.3": - version: 1.2.4 - resolution: "array.prototype.findlastindex@npm:1.2.4" + version: 1.2.5 + resolution: "array.prototype.findlastindex@npm:1.2.5" dependencies: - call-bind: "npm:^1.0.5" + call-bind: "npm:^1.0.7" define-properties: "npm:^1.2.1" - es-abstract: "npm:^1.22.3" + es-abstract: "npm:^1.23.2" es-errors: "npm:^1.3.0" + es-object-atoms: "npm:^1.0.0" es-shim-unscopables: "npm:^1.0.2" - checksum: 10c0/b23ae35cf7621c82c20981ee110626090734a264798e781b052e534e3d61d576f03d125d92cf2e3672062bb5cc5907e02e69f2d80196a55f3cdb0197b4aa8c64 + checksum: 10c0/962189487728b034f3134802b421b5f39e42ee2356d13b42d2ddb0e52057ffdcc170b9524867f4f0611a6f638f4c19b31e14606e8bcbda67799e26685b195aa3 languageName: node linkType: hard @@ -2609,11 +2598,11 @@ __metadata: linkType: hard "autoprefixer@npm:^10.4.15": - version: 10.4.18 - resolution: "autoprefixer@npm:10.4.18" + version: 10.4.19 + resolution: "autoprefixer@npm:10.4.19" dependencies: browserslist: "npm:^4.23.0" - caniuse-lite: "npm:^1.0.30001591" + caniuse-lite: "npm:^1.0.30001599" fraction.js: "npm:^4.3.7" normalize-range: "npm:^0.1.2" picocolors: "npm:^1.0.0" @@ -2622,11 +2611,11 @@ __metadata: postcss: ^8.1.0 bin: autoprefixer: bin/autoprefixer - checksum: 10c0/b6e1c1ba2fc6c09360cdcd75b00ce809c5dbe1ad4c30f0186764609a982aa5563d45965cb9e6a9d195c639a9fb1dcac2594484fc41624050195f626e9add666e + checksum: 10c0/fe0178eb8b1da4f15c6535cd329926609b22d1811e047371dccce50563623f8075dd06fb167daff059e4228da651b0bdff6d9b44281541eaf0ce0b79125bfd19 languageName: node linkType: hard -"available-typed-arrays@npm:^1.0.6, available-typed-arrays@npm:^1.0.7": +"available-typed-arrays@npm:^1.0.7": version: 1.0.7 resolution: "available-typed-arrays@npm:1.0.7" dependencies: @@ -2636,13 +2625,13 @@ __metadata: linkType: hard "axios@npm:^1.6.7": - version: 1.6.7 - resolution: "axios@npm:1.6.7" + version: 1.6.8 + resolution: "axios@npm:1.6.8" dependencies: - follow-redirects: "npm:^1.15.4" + follow-redirects: "npm:^1.15.6" form-data: "npm:^4.0.0" proxy-from-env: "npm:^1.1.0" - checksum: 10c0/131bf8e62eee48ca4bd84e6101f211961bf6a21a33b95e5dfb3983d5a2fe50d9fffde0b57668d7ce6f65063d3dc10f2212cbcb554f75cfca99da1c73b210358d + checksum: 10c0/0f22da6f490335479a89878bc7d5a1419484fbb437b564a80c34888fc36759ae4f56ea28d55a191695e5ed327f0bad56e7ff60fb6770c14d1be6501505d47ab9 languageName: node linkType: hard @@ -2744,9 +2733,9 @@ __metadata: linkType: hard "binary-extensions@npm:^2.0.0": - version: 2.2.0 - resolution: "binary-extensions@npm:2.2.0" - checksum: 10c0/d73d8b897238a2d3ffa5f59c0241870043aa7471335e89ea5e1ff48edb7c2d0bb471517a3e4c5c3f4c043615caa2717b5f80a5e61e07503d51dc85cb848e665d + version: 2.3.0 + resolution: "binary-extensions@npm:2.3.0" + checksum: 10c0/75a59cafc10fb12a11d510e77110c6c7ae3f4ca22463d52487709ca7f18f69d886aa387557cc9864fbdb10153d0bdb4caacabf11541f55e89ed6e18d12ece2b5 languageName: node linkType: hard @@ -3103,10 +3092,10 @@ __metadata: languageName: node linkType: hard -"caniuse-lite@npm:^1.0.30001587, caniuse-lite@npm:^1.0.30001591": - version: 1.0.30001593 - resolution: "caniuse-lite@npm:1.0.30001593" - checksum: 10c0/c1601015ee4846da731f78164d4d863e6ee49a32988c4d879e9ab07ebdedcd32122161a3ff09f991485208d7a743db62fb5bd3dfbe4312f271c03f810a85cb4f +"caniuse-lite@npm:^1.0.30001587, caniuse-lite@npm:^1.0.30001599": + version: 1.0.30001610 + resolution: "caniuse-lite@npm:1.0.30001610" + checksum: 10c0/015956a0bf2e3e233da3dc00c5632bbb4d416bcd6ced2f839e33e45b197a856234f97cb046e7427b83d7e3a3d6df314dfab1c86eb9d970970e00ad85a50b4933 languageName: node linkType: hard @@ -3525,10 +3514,10 @@ __metadata: languageName: node linkType: hard -"cookie@npm:0.5.0": - version: 0.5.0 - resolution: "cookie@npm:0.5.0" - checksum: 10c0/c01ca3ef8d7b8187bae434434582288681273b5a9ed27521d4d7f9f7928fe0c920df0decd9f9d3bbd2d14ac432b8c8cf42b98b3bdd5bfe0e6edddeebebe8b61d +"cookie@npm:0.6.0": + version: 0.6.0 + resolution: "cookie@npm:0.6.0" + checksum: 10c0/f2318b31af7a31b4ddb4a678d024514df5e705f9be5909a192d7f116cfb6d45cbacf96a473fa733faa95050e7cff26e7832bb3ef94751592f1387b71c8956686 languageName: node linkType: hard @@ -3658,14 +3647,14 @@ __metadata: linkType: hard "css-loader@npm:^6.8.1": - version: 6.10.0 - resolution: "css-loader@npm:6.10.0" + version: 6.11.0 + resolution: "css-loader@npm:6.11.0" dependencies: icss-utils: "npm:^5.1.0" postcss: "npm:^8.4.33" - postcss-modules-extract-imports: "npm:^3.0.0" - postcss-modules-local-by-default: "npm:^4.0.4" - postcss-modules-scope: "npm:^3.1.1" + postcss-modules-extract-imports: "npm:^3.1.0" + postcss-modules-local-by-default: "npm:^4.0.5" + postcss-modules-scope: "npm:^3.2.0" postcss-modules-values: "npm:^4.0.0" postcss-value-parser: "npm:^4.2.0" semver: "npm:^7.5.4" @@ -3677,7 +3666,7 @@ __metadata: optional: true webpack: optional: true - checksum: 10c0/acadd2a93f505bf8a8d1c6912a476ef953585f195412b6aa1f2581053bcce8563b833f2a6666c1e1521f4b35fb315176563495a38933becc89e3143cfa7dce45 + checksum: 10c0/bb52434138085fed06a33e2ffbdae9ee9014ad23bf60f59d6b7ee67f28f26c6b1764024d3030bd19fd884d6ee6ee2224eaed64ad19eb18fbbb23d148d353a965 languageName: node linkType: hard @@ -3717,6 +3706,39 @@ __metadata: languageName: node linkType: hard +"data-view-buffer@npm:^1.0.1": + version: 1.0.1 + resolution: "data-view-buffer@npm:1.0.1" + dependencies: + call-bind: "npm:^1.0.6" + es-errors: "npm:^1.3.0" + is-data-view: "npm:^1.0.1" + checksum: 10c0/8984119e59dbed906a11fcfb417d7d861936f16697a0e7216fe2c6c810f6b5e8f4a5281e73f2c28e8e9259027190ac4a33e2a65fdd7fa86ac06b76e838918583 + languageName: node + linkType: hard + +"data-view-byte-length@npm:^1.0.1": + version: 1.0.1 + resolution: "data-view-byte-length@npm:1.0.1" + dependencies: + call-bind: "npm:^1.0.7" + es-errors: "npm:^1.3.0" + is-data-view: "npm:^1.0.1" + checksum: 10c0/b7d9e48a0cf5aefed9ab7d123559917b2d7e0d65531f43b2fd95b9d3a6b46042dd3fca597c42bba384e66b70d7ad66ff23932f8367b241f53d93af42cfe04ec2 + languageName: node + linkType: hard + +"data-view-byte-offset@npm:^1.0.0": + version: 1.0.0 + resolution: "data-view-byte-offset@npm:1.0.0" + dependencies: + call-bind: "npm:^1.0.6" + es-errors: "npm:^1.3.0" + is-data-view: "npm:^1.0.1" + checksum: 10c0/21b0d2e53fd6e20cc4257c873bf6d36d77bd6185624b84076c0a1ddaa757b49aaf076254006341d35568e89f52eecd1ccb1a502cfb620f2beca04f48a6a62a8f + languageName: node + linkType: hard + "dateformat@npm:^4.6.3": version: 4.6.3 resolution: "dateformat@npm:4.6.3" @@ -3772,14 +3794,14 @@ __metadata: linkType: hard "dedent@npm:^1.0.0": - version: 1.5.1 - resolution: "dedent@npm:1.5.1" + version: 1.5.3 + resolution: "dedent@npm:1.5.3" peerDependencies: babel-plugin-macros: ^3.1.0 peerDependenciesMeta: babel-plugin-macros: optional: true - checksum: 10c0/f8612cd5b00aab58b18bb95572dca08dc2d49720bfa7201a444c3dae430291e8a06d4928614a6ec8764d713927f44bce9c990d3b8238fca2f430990ddc17c070 + checksum: 10c0/d94bde6e6f780be4da4fd760288fcf755ec368872f4ac5218197200d86430aeb8d90a003a840bff1c20221188e3f23adced0119cb811c6873c70d0ac66d12832 languageName: node linkType: hard @@ -3837,7 +3859,7 @@ __metadata: languageName: node linkType: hard -"define-data-property@npm:^1.0.1, define-data-property@npm:^1.1.2, define-data-property@npm:^1.1.4": +"define-data-property@npm:^1.0.1, define-data-property@npm:^1.1.4": version: 1.1.4 resolution: "define-data-property@npm:1.1.4" dependencies: @@ -4054,15 +4076,15 @@ __metadata: linkType: hard "electron-to-chromium@npm:^1.4.668": - version: 1.4.690 - resolution: "electron-to-chromium@npm:1.4.690" - checksum: 10c0/fba87387968bac5ac55161dc176e55d92a54146ae1e5fb16c3fdd5bf4f250ce6f271713659c0cdfa7fc0fd9a9ea1a79803f266fa2b936535b208c0759a4d3983 + version: 1.4.736 + resolution: "electron-to-chromium@npm:1.4.736" + checksum: 10c0/f3acb515dcb9333b318f9a8ee80a0c3975162da6cc45d9c00152e0de7004b2bfe1246fe6cdf0c41a1b7016780bd4324aff848830aba4227cb55480c1aa32d248 languageName: node linkType: hard "elliptic@npm:^6.5.4": - version: 6.5.4 - resolution: "elliptic@npm:6.5.4" + version: 6.5.5 + resolution: "elliptic@npm:6.5.5" dependencies: bn.js: "npm:^4.11.9" brorand: "npm:^1.1.0" @@ -4071,7 +4093,7 @@ __metadata: inherits: "npm:^2.0.4" minimalistic-assert: "npm:^1.0.1" minimalistic-crypto-utils: "npm:^1.0.1" - checksum: 10c0/5f361270292c3b27cf0843e84526d11dec31652f03c2763c6c2b8178548175ff5eba95341dd62baff92b2265d1af076526915d8af6cc9cb7559c44a62f8ca6e2 + checksum: 10c0/3e591e93783a1b66f234ebf5bd3a8a9a8e063a75073a35a671e03e3b25253b6e33ac121f7efe9b8808890fffb17b40596cc19d01e6e8d1fa13b9a56ff65597c8 languageName: node linkType: hard @@ -4128,13 +4150,13 @@ __metadata: languageName: node linkType: hard -"enhanced-resolve@npm:^5.0.0, enhanced-resolve@npm:^5.12.0, enhanced-resolve@npm:^5.15.0": - version: 5.15.1 - resolution: "enhanced-resolve@npm:5.15.1" +"enhanced-resolve@npm:^5.0.0, enhanced-resolve@npm:^5.12.0, enhanced-resolve@npm:^5.16.0": + version: 5.16.0 + resolution: "enhanced-resolve@npm:5.16.0" dependencies: graceful-fs: "npm:^4.2.4" tapable: "npm:^2.2.0" - checksum: 10c0/f56a0f3726dc5fb65cb4518ab0806aecfd553f4cd4146f403ffe618ece36610443d8624a89d18fe0bb0be307b1c9ca8fb835267345ca4afc25d2932d58ced715 + checksum: 10c0/dd69669cbb638ccacefd03e04d5e195ee6a99b7f5f8012f86d2df7781834de357923e06064ea621137c4ce0b37cc12b872b4e6d1ac6ab15fe98e7f1dfbbb08c4 languageName: node linkType: hard @@ -4162,11 +4184,11 @@ __metadata: linkType: hard "envinfo@npm:^7.7.3": - version: 7.11.1 - resolution: "envinfo@npm:7.11.1" + version: 7.12.0 + resolution: "envinfo@npm:7.12.0" bin: envinfo: dist/cli.js - checksum: 10c0/4550cce03d4d8a7b137d548faaf9c920356474231636cb4a6e74ae75db3b9cb04aa0a052ee391e2363af5db697166c207ba76e106338d758c6126830b3e16d75 + checksum: 10c0/32a48ddaab7b5a18bb9961bddc45757fe1f308e8f1067740393b58846e458efa05a747a5ca80d43913c4946620e76ed386c82d9a9e412ee7cc737773b9822651 languageName: node linkType: hard @@ -4186,16 +4208,20 @@ __metadata: languageName: node linkType: hard -"es-abstract@npm:^1.22.1, es-abstract@npm:^1.22.3": - version: 1.22.5 - resolution: "es-abstract@npm:1.22.5" +"es-abstract@npm:^1.22.1, es-abstract@npm:^1.22.3, es-abstract@npm:^1.23.0, es-abstract@npm:^1.23.2": + version: 1.23.3 + resolution: "es-abstract@npm:1.23.3" dependencies: array-buffer-byte-length: "npm:^1.0.1" arraybuffer.prototype.slice: "npm:^1.0.3" available-typed-arrays: "npm:^1.0.7" call-bind: "npm:^1.0.7" + data-view-buffer: "npm:^1.0.1" + data-view-byte-length: "npm:^1.0.1" + data-view-byte-offset: "npm:^1.0.0" es-define-property: "npm:^1.0.0" es-errors: "npm:^1.3.0" + es-object-atoms: "npm:^1.0.0" es-set-tostringtag: "npm:^2.0.3" es-to-primitive: "npm:^1.2.1" function.prototype.name: "npm:^1.1.6" @@ -4206,10 +4232,11 @@ __metadata: has-property-descriptors: "npm:^1.0.2" has-proto: "npm:^1.0.3" has-symbols: "npm:^1.0.3" - hasown: "npm:^2.0.1" + hasown: "npm:^2.0.2" internal-slot: "npm:^1.0.7" is-array-buffer: "npm:^3.0.4" is-callable: "npm:^1.2.7" + is-data-view: "npm:^1.0.1" is-negative-zero: "npm:^2.0.3" is-regex: "npm:^1.1.4" is-shared-array-buffer: "npm:^1.0.3" @@ -4220,25 +4247,18 @@ __metadata: object-keys: "npm:^1.1.1" object.assign: "npm:^4.1.5" regexp.prototype.flags: "npm:^1.5.2" - safe-array-concat: "npm:^1.1.0" + safe-array-concat: "npm:^1.1.2" safe-regex-test: "npm:^1.0.3" - string.prototype.trim: "npm:^1.2.8" - string.prototype.trimend: "npm:^1.0.7" - string.prototype.trimstart: "npm:^1.0.7" + string.prototype.trim: "npm:^1.2.9" + string.prototype.trimend: "npm:^1.0.8" + string.prototype.trimstart: "npm:^1.0.8" typed-array-buffer: "npm:^1.0.2" typed-array-byte-length: "npm:^1.0.1" typed-array-byte-offset: "npm:^1.0.2" - typed-array-length: "npm:^1.0.5" + typed-array-length: "npm:^1.0.6" unbox-primitive: "npm:^1.0.2" - which-typed-array: "npm:^1.1.14" - checksum: 10c0/4bca5a60f0dff6c0a5690d8e51374cfcb8760d5dbbb1069174b4d41461cf4e0c3e0c1993bccbc5aa0799ff078199f1bcde2122b8709e0d17c2beffafff01010a - languageName: node - linkType: hard - -"es-array-method-boxes-properly@npm:^1.0.0": - version: 1.0.0 - resolution: "es-array-method-boxes-properly@npm:1.0.0" - checksum: 10c0/4b7617d3fbd460d6f051f684ceca6cf7e88e6724671d9480388d3ecdd72119ddaa46ca31f2c69c5426a82e4b3091c1e81867c71dcdc453565cd90005ff2c382d + which-typed-array: "npm:^1.1.15" + checksum: 10c0/d27e9afafb225c6924bee9971a7f25f20c314f2d6cb93a63cada4ac11dcf42040896a6c22e5fb8f2a10767055ed4ddf400be3b1eb12297d281726de470b75666 languageName: node linkType: hard @@ -4251,7 +4271,7 @@ __metadata: languageName: node linkType: hard -"es-errors@npm:^1.0.0, es-errors@npm:^1.2.1, es-errors@npm:^1.3.0": +"es-errors@npm:^1.2.1, es-errors@npm:^1.3.0": version: 1.3.0 resolution: "es-errors@npm:1.3.0" checksum: 10c0/0a61325670072f98d8ae3b914edab3559b6caa980f08054a3b872052640d91da01d38df55df797fcc916389d77fc92b8d5906cf028f4db46d7e3003abecbca85 @@ -4259,9 +4279,18 @@ __metadata: linkType: hard "es-module-lexer@npm:^1.2.1": - version: 1.4.1 - resolution: "es-module-lexer@npm:1.4.1" - checksum: 10c0/b7260a138668554d3f0ddcc728cb4b60c2fa463f15545cf155ecbdd5450a1348952d58298a7f48642e900ee579f21d7f5304b6b3c61b3d9fc2d4b2109b5a9dff + version: 1.5.0 + resolution: "es-module-lexer@npm:1.5.0" + checksum: 10c0/d199853404f3381801eb102befb84a8fc48f93ed86b852c2461c2c4ad4bbbc91128f3d974ff9b8718628260ae3f36e661295ab3e419222868aa31269284e34c9 + languageName: node + linkType: hard + +"es-object-atoms@npm:^1.0.0": + version: 1.0.0 + resolution: "es-object-atoms@npm:1.0.0" + dependencies: + es-errors: "npm:^1.3.0" + checksum: 10c0/1fed3d102eb27ab8d983337bb7c8b159dd2a1e63ff833ec54eea1311c96d5b08223b433060ba240541ca8adba9eee6b0a60cdbf2f80634b784febc9cc8b687b4 languageName: node linkType: hard @@ -4440,11 +4469,11 @@ __metadata: linkType: hard "eslint-plugin-react-refresh@npm:^0.4.3": - version: 0.4.5 - resolution: "eslint-plugin-react-refresh@npm:0.4.5" + version: 0.4.6 + resolution: "eslint-plugin-react-refresh@npm:0.4.6" peerDependencies: eslint: ">=7" - checksum: 10c0/ea696811c6264d2efee10efe07f80aaae75ded66c941d8d5ce65e15e6c4bb8ad50ac225310ed04f35ed68d2d57937ba4c6f06d9306e78931d583648abf496a41 + checksum: 10c0/931d5623c7c694526e9d34f61af856bb1949a0b9b9b509da29cba6c3c68fd4e1e7e36d8a340f6aecfd22329d0425c7fbb2388dd7d24b0d05218067747f5d6fe3 languageName: node linkType: hard @@ -4667,15 +4696,15 @@ __metadata: linkType: hard "express@npm:^4.17.3": - version: 4.18.3 - resolution: "express@npm:4.18.3" + version: 4.19.2 + resolution: "express@npm:4.19.2" dependencies: accepts: "npm:~1.3.8" array-flatten: "npm:1.1.1" body-parser: "npm:1.20.2" content-disposition: "npm:0.5.4" content-type: "npm:~1.0.4" - cookie: "npm:0.5.0" + cookie: "npm:0.6.0" cookie-signature: "npm:1.0.6" debug: "npm:2.6.9" depd: "npm:2.0.0" @@ -4701,14 +4730,14 @@ __metadata: type-is: "npm:~1.6.18" utils-merge: "npm:1.0.1" vary: "npm:~1.1.2" - checksum: 10c0/0b9eeafbac549e3c67d92d083bf1773e358359f41ad142b92121935c6348d29079b75054555b3f62de39263fffc8ba06898b09fdd3e213e28e714c03c5d9f44c + checksum: 10c0/e82e2662ea9971c1407aea9fc3c16d6b963e55e3830cd0ef5e00b533feda8b770af4e3be630488ef8a752d7c75c4fcefb15892868eeaafe7353cb9e3e269fdcb languageName: node linkType: hard "fast-copy@npm:^3.0.0": - version: 3.0.1 - resolution: "fast-copy@npm:3.0.1" - checksum: 10c0/a8310dbcc4c94ed001dc3e0bbc3c3f0491bb04e6c17163abe441a54997ba06cdf1eb532c2f05e54777c6f072c84548c23ef0ecd54665cd611be1d42f37eca258 + version: 3.0.2 + resolution: "fast-copy@npm:3.0.2" + checksum: 10c0/02e8b9fd03c8c024d2987760ce126456a0e17470850b51e11a1c3254eed6832e4733ded2d93316c82bc0b36aeb991ad1ff48d1ba95effe7add7c3ab8d8eb554a languageName: node linkType: hard @@ -4754,9 +4783,9 @@ __metadata: linkType: hard "fast-redact@npm:^3.1.1": - version: 3.4.0 - resolution: "fast-redact@npm:3.4.0" - checksum: 10c0/4e2ba1de87a11a24d35a2a9b2f5736107df1d1740e97a6b3103a8db5134de2a32a19d41210e66470322b08352bff8743527d18b4003b0ee04ead51b4c2fcfb97 + version: 3.5.0 + resolution: "fast-redact@npm:3.5.0" + checksum: 10c0/7e2ce4aad6e7535e0775bf12bd3e4f2e53d8051d8b630e0fa9e67f68cb0b0e6070d2f7a94b1d0522ef07e32f7c7cda5755e2b677a6538f1e9070ca053c42343a languageName: node linkType: hard @@ -4810,15 +4839,6 @@ __metadata: languageName: node linkType: hard -"figures@npm:^3.2.0": - version: 3.2.0 - resolution: "figures@npm:3.2.0" - dependencies: - escape-string-regexp: "npm:^1.0.5" - checksum: 10c0/9c421646ede432829a50bc4e55c7a4eb4bcb7cc07b5bab2f471ef1ab9a344595bbebb6c5c21470093fbb730cd81bbca119624c40473a125293f656f49cb47629 - languageName: node - linkType: hard - "file-entry-cache@npm:^6.0.1": version: 6.0.1 resolution: "file-entry-cache@npm:6.0.1" @@ -4899,13 +4919,13 @@ __metadata: languageName: node linkType: hard -"follow-redirects@npm:^1.0.0, follow-redirects@npm:^1.15.4": - version: 1.15.5 - resolution: "follow-redirects@npm:1.15.5" +"follow-redirects@npm:^1.0.0, follow-redirects@npm:^1.15.6": + version: 1.15.6 + resolution: "follow-redirects@npm:1.15.6" peerDependenciesMeta: debug: optional: true - checksum: 10c0/418d71688ceaf109dfd6f85f747a0c75de30afe43a294caa211def77f02ef19865b547dfb73fde82b751e1cc507c06c754120b848fe5a7400b0a669766df7615 + checksum: 10c0/9ff767f0d7be6aa6870c82ac79cf0368cd73e01bbc00e9eb1c2a16fbb198ec105e3c9b6628bb98e9f3ac66fe29a957b9645bcb9a490bb7aa0d35f908b6b85071 languageName: node linkType: hard @@ -5145,7 +5165,7 @@ __metadata: languageName: node linkType: hard -"get-intrinsic@npm:^1.1.3, get-intrinsic@npm:^1.2.1, get-intrinsic@npm:^1.2.2, get-intrinsic@npm:^1.2.3, get-intrinsic@npm:^1.2.4": +"get-intrinsic@npm:^1.1.3, get-intrinsic@npm:^1.2.1, get-intrinsic@npm:^1.2.3, get-intrinsic@npm:^1.2.4": version: 1.2.4 resolution: "get-intrinsic@npm:1.2.4" dependencies: @@ -5191,11 +5211,11 @@ __metadata: linkType: hard "get-tsconfig@npm:^4.5.0": - version: 4.7.2 - resolution: "get-tsconfig@npm:4.7.2" + version: 4.7.3 + resolution: "get-tsconfig@npm:4.7.3" dependencies: resolve-pkg-maps: "npm:^1.0.0" - checksum: 10c0/169b2beababfbb16e8a0ae813ee59d3e14d4960231c816615161ab5be68ec07a394dce59695742ac84295e2efab8d9e89bcf3abaf5e253dfbec3496e01bb9a65 + checksum: 10c0/b15ca9d5d0887ebfccadc9fe88b6ff3827a5691ec90e7608a5e9c74bef959c14aba62f6bb88ac7f50322395731789a2cf654244f00e10f4f76349911b6846d6f languageName: node linkType: hard @@ -5225,17 +5245,17 @@ __metadata: linkType: hard "glob@npm:^10.2.2, glob@npm:^10.3.10": - version: 10.3.10 - resolution: "glob@npm:10.3.10" + version: 10.3.12 + resolution: "glob@npm:10.3.12" dependencies: foreground-child: "npm:^3.1.0" - jackspeak: "npm:^2.3.5" + jackspeak: "npm:^2.3.6" minimatch: "npm:^9.0.1" - minipass: "npm:^5.0.0 || ^6.0.2 || ^7.0.0" - path-scurry: "npm:^1.10.1" + minipass: "npm:^7.0.4" + path-scurry: "npm:^1.10.2" bin: glob: dist/esm/bin.mjs - checksum: 10c0/13d8a1feb7eac7945f8c8480e11cd4a44b24d26503d99a8d8ac8d5aefbf3e9802a2b6087318a829fad04cb4e829f25c5f4f1110c68966c498720dd261c7e344d + checksum: 10c0/f60cefdc1cf3f958b2bb5823e1b233727f04916d489dc4641d76914f016e6704421e06a83cbb68b0cb1cb9382298b7a88075b844ad2127fc9727ea22b18b0711 languageName: node linkType: hard @@ -5366,7 +5386,7 @@ __metadata: languageName: node linkType: hard -"graceful-fs@npm:^4.1.2, graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6, graceful-fs@npm:^4.2.9": +"graceful-fs@npm:^4.1.2, graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.11, graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6, graceful-fs@npm:^4.2.9": version: 4.2.11 resolution: "graceful-fs@npm:4.2.11" checksum: 10c0/386d011a553e02bc594ac2ca0bd6d9e4c22d7fa8cfbfc448a6d148c59ea881b092db9dbe3547ae4b88e55f1b01f7c4a2ecc53b310c042793e63aa44cf6c257f2 @@ -5415,7 +5435,7 @@ __metadata: languageName: node linkType: hard -"has-property-descriptors@npm:^1.0.0, has-property-descriptors@npm:^1.0.1, has-property-descriptors@npm:^1.0.2": +"has-property-descriptors@npm:^1.0.0, has-property-descriptors@npm:^1.0.2": version: 1.0.2 resolution: "has-property-descriptors@npm:1.0.2" dependencies: @@ -5438,7 +5458,7 @@ __metadata: languageName: node linkType: hard -"has-tostringtag@npm:^1.0.0, has-tostringtag@npm:^1.0.1, has-tostringtag@npm:^1.0.2": +"has-tostringtag@npm:^1.0.0, has-tostringtag@npm:^1.0.2": version: 1.0.2 resolution: "has-tostringtag@npm:1.0.2" dependencies: @@ -5475,12 +5495,12 @@ __metadata: languageName: node linkType: hard -"hasown@npm:^2.0.0, hasown@npm:^2.0.1": - version: 2.0.1 - resolution: "hasown@npm:2.0.1" +"hasown@npm:^2.0.0, hasown@npm:^2.0.1, hasown@npm:^2.0.2": + version: 2.0.2 + resolution: "hasown@npm:2.0.2" dependencies: function-bind: "npm:^1.1.2" - checksum: 10c0/9e27e70e8e4204f4124c8f99950d1ba2b1f5174864fd39ff26da190f9ea6488c1b3927dcc64981c26d1f637a971783c9489d62c829d393ea509e6f1ba20370bb + checksum: 10c0/3769d434703b8ac66b209a4cca0737519925bbdb61dd887f93a16372b14694c63ff4e797686d87c90f08168e81082248b9b028bad60d4da9e0d1148766f56eb9 languageName: node linkType: hard @@ -6030,6 +6050,15 @@ __metadata: languageName: node linkType: hard +"is-data-view@npm:^1.0.1": + version: 1.0.1 + resolution: "is-data-view@npm:1.0.1" + dependencies: + is-typed-array: "npm:^1.1.13" + checksum: 10c0/a3e6ec84efe303da859107aed9b970e018e2bee7ffcb48e2f8096921a493608134240e672a2072577e5f23a729846241d9634806e8a0e51d9129c56d5f65442d + languageName: node + linkType: hard + "is-date-object@npm:^1.0.1": version: 1.0.5 resolution: "is-date-object@npm:1.0.5" @@ -6355,7 +6384,7 @@ __metadata: languageName: node linkType: hard -"jackspeak@npm:^2.3.5": +"jackspeak@npm:^2.3.6": version: 2.3.6 resolution: "jackspeak@npm:2.3.6" dependencies: @@ -7048,8 +7077,8 @@ __metadata: linkType: hard "koa@npm:^2.14.2": - version: 2.15.0 - resolution: "koa@npm:2.15.0" + version: 2.15.3 + resolution: "koa@npm:2.15.3" dependencies: accepts: "npm:^1.3.5" cache-content-type: "npm:^1.0.0" @@ -7074,7 +7103,7 @@ __metadata: statuses: "npm:^1.5.0" type-is: "npm:^1.6.16" vary: "npm:^1.1.2" - checksum: 10c0/018daa5d3521621699e4228de9191849083c0356e1e4abda6d96aa44fa3ee1f6a67849040c2a0b681697d1431a8232cca1e532a7246fc785257bfdf1e6ccf43a + checksum: 10c0/1dca5027e06855dfc4144093fc678c445b5718c3a61b3b7840e3def999f3efcd0359665fb30d3f427890dfee12ebb1e7d01e210d2122a17240d2f3ceae12b2f2 languageName: node linkType: hard @@ -7296,7 +7325,7 @@ __metadata: languageName: node linkType: hard -"lru-cache@npm:^10.0.1, lru-cache@npm:^9.1.1 || ^10.0.0": +"lru-cache@npm:^10.0.1, lru-cache@npm:^10.2.0": version: 10.2.0 resolution: "lru-cache@npm:10.2.0" checksum: 10c0/c9847612aa2daaef102d30542a8d6d9b2c2bb36581c1bf0dc3ebf5e5f3352c772a749e604afae2e46873b930a9e9523743faac4e5b937c576ab29196774712ee @@ -7617,7 +7646,7 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:9.0.3, minimatch@npm:^9.0.1": +"minimatch@npm:9.0.3": version: 9.0.3 resolution: "minimatch@npm:9.0.3" dependencies: @@ -7635,6 +7664,15 @@ __metadata: languageName: node linkType: hard +"minimatch@npm:^9.0.1": + version: 9.0.4 + resolution: "minimatch@npm:9.0.4" + dependencies: + brace-expansion: "npm:^2.0.1" + checksum: 10c0/2c16f21f50e64922864e560ff97c587d15fd491f65d92a677a344e970fe62aafdbeafe648965fa96d33c061b4d0eabfe0213466203dd793367e7f28658cf6414 + languageName: node + linkType: hard + "minimatch@npm:~3.0.2": version: 3.0.8 resolution: "minimatch@npm:3.0.8" @@ -7768,7 +7806,7 @@ __metadata: languageName: node linkType: hard -"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3": +"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3, minipass@npm:^7.0.4": version: 7.0.4 resolution: "minipass@npm:7.0.4" checksum: 10c0/6c7370a6dfd257bf18222da581ba89a5eaedca10e158781232a8b5542a90547540b4b9b7e7f490e4cda43acfbd12e086f0453728ecf8c19e0ef6921bc5958ac5 @@ -7842,11 +7880,11 @@ __metadata: linkType: hard "nan@npm:^2.17.0": - version: 2.18.0 - resolution: "nan@npm:2.18.0" + version: 2.19.0 + resolution: "nan@npm:2.19.0" dependencies: node-gyp: "npm:latest" - checksum: 10c0/9209d80134fdb98c0afe35c1372d2b930a0a8d3c52706cb5e4257a27e9845c375f7a8daedadadec8d6403ca2eebb3b37d362ff5d1ec03249462abf65fef2a148 + checksum: 10c0/b8d05d75f92ee9d94affa50d0aa41b6c698254c848529452d7ab67c2e0d160a83f563bfe2cbd53e077944eceb48c757f83c93634c7c9ff404c9ec1ed4e5ced1a languageName: node linkType: hard @@ -7936,8 +7974,8 @@ __metadata: linkType: hard "node-gyp@npm:latest": - version: 10.0.1 - resolution: "node-gyp@npm:10.0.1" + version: 10.1.0 + resolution: "node-gyp@npm:10.1.0" dependencies: env-paths: "npm:^2.2.0" exponential-backoff: "npm:^3.1.1" @@ -7951,7 +7989,7 @@ __metadata: which: "npm:^4.0.0" bin: node-gyp: bin/node-gyp.js - checksum: 10c0/abddfff7d873312e4ed4a5fb75ce893a5c4fb69e7fcb1dfa71c28a6b92a7f1ef6b62790dffb39181b5a82728ba8f2f32d229cf8cbe66769fe02cea7db4a555aa + checksum: 10c0/9cc821111ca244a01fb7f054db7523ab0a0cd837f665267eb962eb87695d71fb1e681f9e21464cc2fd7c05530dc4c81b810bca1a88f7d7186909b74477491a3c languageName: node linkType: hard @@ -8120,37 +8158,36 @@ __metadata: linkType: hard "object.fromentries@npm:^2.0.7": - version: 2.0.7 - resolution: "object.fromentries@npm:2.0.7" + version: 2.0.8 + resolution: "object.fromentries@npm:2.0.8" dependencies: - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.2.0" - es-abstract: "npm:^1.22.1" - checksum: 10c0/071745c21f6fc9e6c914691f2532c1fb60ad967e5ddc52801d09958b5de926566299d07ae14466452a7efd29015f9145d6c09c573d93a0dc6f1683ee0ec2b93b + call-bind: "npm:^1.0.7" + define-properties: "npm:^1.2.1" + es-abstract: "npm:^1.23.2" + es-object-atoms: "npm:^1.0.0" + checksum: 10c0/cd4327e6c3369cfa805deb4cbbe919bfb7d3aeebf0bcaba291bb568ea7169f8f8cdbcabe2f00b40db0c20cd20f08e11b5f3a5a36fb7dd3fe04850c50db3bf83b languageName: node linkType: hard "object.groupby@npm:^1.0.1": - version: 1.0.2 - resolution: "object.groupby@npm:1.0.2" + version: 1.0.3 + resolution: "object.groupby@npm:1.0.3" dependencies: - array.prototype.filter: "npm:^1.0.3" - call-bind: "npm:^1.0.5" + call-bind: "npm:^1.0.7" define-properties: "npm:^1.2.1" - es-abstract: "npm:^1.22.3" - es-errors: "npm:^1.0.0" - checksum: 10c0/b6266b1cfec7eb784b8bbe0bca5dc4b371cf9dd3e601b0897d72fa97a5934273d8fb05b3fc5222204104dbec32b50e25ba27e05ad681f71fb739cc1c7e9b81b1 + es-abstract: "npm:^1.23.2" + checksum: 10c0/60d0455c85c736fbfeda0217d1a77525956f76f7b2495edeca9e9bbf8168a45783199e77b894d30638837c654d0cc410e0e02cbfcf445bc8de71c3da1ede6a9c languageName: node linkType: hard "object.values@npm:^1.1.7": - version: 1.1.7 - resolution: "object.values@npm:1.1.7" + version: 1.2.0 + resolution: "object.values@npm:1.2.0" dependencies: - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.2.0" - es-abstract: "npm:^1.22.1" - checksum: 10c0/e869d6a37fb7afdd0054dea49036d6ccebb84854a8848a093bbd1bc516f53e690bba88f0bc3e83fdfa74c601469ee6989c9b13359cda9604144c6e732fad3b6b + call-bind: "npm:^1.0.7" + define-properties: "npm:^1.2.1" + es-object-atoms: "npm:^1.0.0" + checksum: 10c0/15809dc40fd6c5529501324fec5ff08570b7d70fb5ebbe8e2b3901afec35cf2b3dc484d1210c6c642cd3e7e0a5e18dd1d6850115337fef46bdae14ab0cb18ac3 languageName: node linkType: hard @@ -8403,13 +8440,13 @@ __metadata: languageName: node linkType: hard -"path-scurry@npm:^1.10.1": - version: 1.10.1 - resolution: "path-scurry@npm:1.10.1" +"path-scurry@npm:^1.10.2": + version: 1.10.2 + resolution: "path-scurry@npm:1.10.2" dependencies: - lru-cache: "npm:^9.1.1 || ^10.0.0" + lru-cache: "npm:^10.2.0" minipass: "npm:^5.0.0 || ^6.0.2 || ^7.0.0" - checksum: 10c0/e5dc78a7348d25eec61ab166317e9e9c7b46818aa2c2b9006c507a6ff48c672d011292d9662527213e558f5652ce0afcc788663a061d8b59ab495681840c0c1e + checksum: 10c0/d723777fbf9627f201e64656680f66ebd940957eebacf780e6cce1c2919c29c116678b2d7dbf8821b3a2caa758d125f4444005ccec886a25c8f324504e48e601 languageName: node linkType: hard @@ -8428,9 +8465,9 @@ __metadata: linkType: hard "path-to-regexp@npm:^6.2.1": - version: 6.2.1 - resolution: "path-to-regexp@npm:6.2.1" - checksum: 10c0/7a73811ca703e5c199e5b50b9649ab8f6f7b458a37f7dff9ea338815203f5b1f95fe8cb24d4fdfe2eab5d67ce43562d92534330babca35cdf3231f966adb9360 + version: 6.2.2 + resolution: "path-to-regexp@npm:6.2.2" + checksum: 10c0/4b60852d3501fd05ca9dd08c70033d73844e5eca14e41f499f069afa8364f780f15c5098002f93bd42af8b3514de62ac6e82a53b5662de881d2b08c9ef21ea6b languageName: node linkType: hard @@ -8455,7 +8492,7 @@ __metadata: languageName: node linkType: hard -"pino-abstract-transport@npm:^1.0.0, pino-abstract-transport@npm:v1.1.0": +"pino-abstract-transport@npm:^1.0.0, pino-abstract-transport@npm:^1.1.0": version: 1.1.0 resolution: "pino-abstract-transport@npm:1.1.0" dependencies: @@ -8497,13 +8534,13 @@ __metadata: linkType: hard "pino@npm:^8.19.0": - version: 8.19.0 - resolution: "pino@npm:8.19.0" + version: 8.20.0 + resolution: "pino@npm:8.20.0" dependencies: atomic-sleep: "npm:^1.0.0" fast-redact: "npm:^3.1.1" on-exit-leak-free: "npm:^2.1.0" - pino-abstract-transport: "npm:v1.1.0" + pino-abstract-transport: "npm:^1.1.0" pino-std-serializers: "npm:^6.0.0" process-warning: "npm:^3.0.0" quick-format-unescaped: "npm:^4.0.3" @@ -8513,7 +8550,7 @@ __metadata: thread-stream: "npm:^2.0.0" bin: pino: bin.js - checksum: 10c0/53e6e9db91e451163e93294b0a7c5c8135742d58909dfc4a6fa1afc155b2b0dc44448ec3d057e08351951f9a3ea67e6ea8e72e952b64a1d889f4d5376cbd1a5d + checksum: 10c0/6b973474160e1fa01fa150de0f69b7db9c6c06ae15f992d369669751825c8f2af3bb5600348eaf9be65b4952326bbdfa226f51e425820eb511f0f594fbddbaa7 languageName: node linkType: hard @@ -8578,36 +8615,36 @@ __metadata: languageName: node linkType: hard -"postcss-modules-extract-imports@npm:^3.0.0": - version: 3.0.0 - resolution: "postcss-modules-extract-imports@npm:3.0.0" +"postcss-modules-extract-imports@npm:^3.1.0": + version: 3.1.0 + resolution: "postcss-modules-extract-imports@npm:3.1.0" peerDependencies: postcss: ^8.1.0 - checksum: 10c0/f8879d66d8162fb7a3fcd916d37574006c584ea509107b1cfb798a5e090175ef9470f601e46f0a305070d8ff2500e07489a5c1ac381c29a1dc1120e827ca7943 + checksum: 10c0/402084bcab376083c4b1b5111b48ec92974ef86066f366f0b2d5b2ac2b647d561066705ade4db89875a13cb175b33dd6af40d16d32b2ea5eaf8bac63bd2bf219 languageName: node linkType: hard -"postcss-modules-local-by-default@npm:^4.0.4": - version: 4.0.4 - resolution: "postcss-modules-local-by-default@npm:4.0.4" +"postcss-modules-local-by-default@npm:^4.0.5": + version: 4.0.5 + resolution: "postcss-modules-local-by-default@npm:4.0.5" dependencies: icss-utils: "npm:^5.0.0" postcss-selector-parser: "npm:^6.0.2" postcss-value-parser: "npm:^4.1.0" peerDependencies: postcss: ^8.1.0 - checksum: 10c0/9ebf464867eb10b29b73501b1466dcac8352ed852ef68ec23571f515daa74401d7ace9a6c72f354542081fdbb47d098c9bc6b05373b553a6e35779d072f967bb + checksum: 10c0/f4ad35abeb685ecb25f80c93d9fe23c8b89ee45ac4185f3560e701b4d7372f9b798577e79c5ed03b6d9c80bc923b001210c127c04ced781f43cda9e32b202a5b languageName: node linkType: hard -"postcss-modules-scope@npm:^3.1.1": - version: 3.1.1 - resolution: "postcss-modules-scope@npm:3.1.1" +"postcss-modules-scope@npm:^3.2.0": + version: 3.2.0 + resolution: "postcss-modules-scope@npm:3.2.0" dependencies: postcss-selector-parser: "npm:^6.0.4" peerDependencies: postcss: ^8.1.0 - checksum: 10c0/3ef6ac14fcda1581bc43e37622256bd87b99ea49c59b2aae648d057d57f5ecc634648cce9910166220a797567af674bc09246ccc010f1dd58d2863b805719109 + checksum: 10c0/a2f5ffe372169b3feb8628cd785eb748bf12e344cfa57bce9e5cdc4fa5adcdb40d36daa86bb35dad53427703b185772aad08825b5783f745fcb1b6039454a84b languageName: node linkType: hard @@ -8623,12 +8660,12 @@ __metadata: linkType: hard "postcss-selector-parser@npm:^6.0.2, postcss-selector-parser@npm:^6.0.4": - version: 6.0.15 - resolution: "postcss-selector-parser@npm:6.0.15" + version: 6.0.16 + resolution: "postcss-selector-parser@npm:6.0.16" dependencies: cssesc: "npm:^3.0.0" util-deprecate: "npm:^1.0.2" - checksum: 10c0/48b425d6cef497bcf6b7d136f6fd95cfca43026955e07ec9290d3c15457de3a862dbf251dd36f42c07a0d5b5ab6f31e41acefeff02528995a989b955505e440b + checksum: 10c0/0e11657cb3181aaf9ff67c2e59427c4df496b4a1b6a17063fae579813f80af79d444bf38f82eeb8b15b4679653fd3089e66ef0283f9aab01874d885e6cf1d2cf languageName: node linkType: hard @@ -8640,13 +8677,13 @@ __metadata: linkType: hard "postcss@npm:^8.4.29, postcss@npm:^8.4.33": - version: 8.4.35 - resolution: "postcss@npm:8.4.35" + version: 8.4.38 + resolution: "postcss@npm:8.4.38" dependencies: nanoid: "npm:^3.3.7" picocolors: "npm:^1.0.0" - source-map-js: "npm:^1.0.2" - checksum: 10c0/e8dd04e48001eb5857abc9475365bf08f4e508ddf9bc0b8525449a95d190f10d025acebc5b56ac2e94b3c7146790e4ae78989bb9633cb7ee20d1cc9b7dc909b2 + source-map-js: "npm:^1.2.0" + checksum: 10c0/955407b8f70cf0c14acf35dab3615899a2a60a26718a63c848cf3c29f2467b0533991b985a2b994430d890bd7ec2b1963e36352b0774a19143b5f591540f7c06 languageName: node linkType: hard @@ -8800,9 +8837,9 @@ __metadata: linkType: hard "pure-rand@npm:^6.0.0": - version: 6.0.4 - resolution: "pure-rand@npm:6.0.4" - checksum: 10c0/0fe7b12f25b10ea5b804598a6f37e4bcf645d2be6d44fe963741f014bf0095bdb6ff525106d6da6e76addc8142358fd380f1a9b8c62ea4d5516bf26a96a37c95 + version: 6.1.0 + resolution: "pure-rand@npm:6.1.0" + checksum: 10c0/1abe217897bf74dcb3a0c9aba3555fe975023147b48db540aa2faf507aee91c03bf54f6aef0eb2bf59cc259a16d06b28eca37f0dc426d94f4692aeff02fb0e65 languageName: node linkType: hard @@ -8816,11 +8853,11 @@ __metadata: linkType: hard "qs@npm:^6.5.2": - version: 6.11.2 - resolution: "qs@npm:6.11.2" + version: 6.12.1 + resolution: "qs@npm:6.12.1" dependencies: - side-channel: "npm:^1.0.4" - checksum: 10c0/4f95d4ff18ed480befcafa3390022817ffd3087fc65f146cceb40fc5edb9fa96cb31f648cae2fa96ca23818f0798bd63ad4ca369a0e22702fcd41379b3ab6571 + side-channel: "npm:^1.0.6" + checksum: 10c0/439e6d7c6583e7c69f2cab2c39c55b97db7ce576e4c7c469082b938b7fc8746e8d547baacb69b4cd2b6666484776c3f4840ad7163a4c5326300b0afa0acdd84b languageName: node linkType: hard @@ -8928,14 +8965,14 @@ __metadata: linkType: hard "react-toastify@npm:^10.0.4": - version: 10.0.4 - resolution: "react-toastify@npm:10.0.4" + version: 10.0.5 + resolution: "react-toastify@npm:10.0.5" dependencies: clsx: "npm:^2.1.0" peerDependencies: - react: ">=16" - react-dom: ">=16" - checksum: 10c0/3d31edf81e8b394fd0085615fd7ba9fb9546c7cdae56e5334df67b58d65450c73af14a8fc163f19ceed03cfee7a344d1af1489422536f52c9516ca45e9b61a37 + react: ">=18" + react-dom: ">=18" + checksum: 10c0/66c68ec3d6c017d9f32652d73bb925224921c6a80b629b9d481430d5b4fd504abb7a99995a64b9aef0fc31326c74f3cbe088b3287b978dd0c355079c4bbf4158 languageName: node linkType: hard @@ -9243,13 +9280,6 @@ __metadata: languageName: node linkType: hard -"run-async@npm:^3.0.0": - version: 3.0.0 - resolution: "run-async@npm:3.0.0" - checksum: 10c0/b18b562ae37c3020083dcaae29642e4cc360c824fbfb6b7d50d809a9d5227bb986152d09310255842c8dce40526e82ca768f02f00806c91ba92a8dfa6159cb85 - languageName: node - linkType: hard - "run-parallel@npm:^1.1.9": version: 1.2.0 resolution: "run-parallel@npm:1.2.0" @@ -9259,15 +9289,15 @@ __metadata: languageName: node linkType: hard -"safe-array-concat@npm:^1.1.0": - version: 1.1.0 - resolution: "safe-array-concat@npm:1.1.0" +"safe-array-concat@npm:^1.1.2": + version: 1.1.2 + resolution: "safe-array-concat@npm:1.1.2" dependencies: - call-bind: "npm:^1.0.5" - get-intrinsic: "npm:^1.2.2" + call-bind: "npm:^1.0.7" + get-intrinsic: "npm:^1.2.4" has-symbols: "npm:^1.0.3" isarray: "npm:^2.0.5" - checksum: 10c0/833d3d950fc7507a60075f9bfaf41ec6dac7c50c7a9d62b1e6b071ecc162185881f92e594ff95c1a18301c881352dd6fd236d56999d5819559db7b92da9c28af + checksum: 10c0/12f9fdb01c8585e199a347eacc3bae7b5164ae805cdc8c6707199dbad5b9e30001a50a43c4ee24dc9ea32dbb7279397850e9208a7e217f4d8b1cf5d90129dec9 languageName: node linkType: hard @@ -9545,16 +9575,16 @@ __metadata: linkType: hard "set-function-length@npm:^1.2.1": - version: 1.2.1 - resolution: "set-function-length@npm:1.2.1" + version: 1.2.2 + resolution: "set-function-length@npm:1.2.2" dependencies: - define-data-property: "npm:^1.1.2" + define-data-property: "npm:^1.1.4" es-errors: "npm:^1.3.0" function-bind: "npm:^1.1.2" - get-intrinsic: "npm:^1.2.3" + get-intrinsic: "npm:^1.2.4" gopd: "npm:^1.0.1" - has-property-descriptors: "npm:^1.0.1" - checksum: 10c0/1927e296599f2c04d210c1911f1600430a5e49e04a6d8bb03dca5487b95a574da9968813a2ced9a774bd3e188d4a6208352c8f64b8d4674cdb021dca21e190ca + has-property-descriptors: "npm:^1.0.2" + checksum: 10c0/82850e62f412a258b71e123d4ed3873fa9377c216809551192bb6769329340176f109c2eeae8c22a8d386c76739855f78e8716515c818bcaef384b51110f0f3c languageName: node linkType: hard @@ -9637,7 +9667,7 @@ __metadata: languageName: node linkType: hard -"side-channel@npm:^1.0.4": +"side-channel@npm:^1.0.4, side-channel@npm:^1.0.6": version: 1.0.6 resolution: "side-channel@npm:1.0.6" dependencies: @@ -9724,40 +9754,40 @@ __metadata: languageName: node linkType: hard -"socks-proxy-agent@npm:^8.0.1": - version: 8.0.2 - resolution: "socks-proxy-agent@npm:8.0.2" +"socks-proxy-agent@npm:^8.0.3": + version: 8.0.3 + resolution: "socks-proxy-agent@npm:8.0.3" dependencies: - agent-base: "npm:^7.0.2" + agent-base: "npm:^7.1.1" debug: "npm:^4.3.4" socks: "npm:^2.7.1" - checksum: 10c0/a842402fc9b8848a31367f2811ca3cd14c4106588b39a0901cd7a69029998adfc6456b0203617c18ed090542ad0c24ee4e9d4c75a0c4b75071e214227c177eb7 + checksum: 10c0/4950529affd8ccd6951575e21c1b7be8531b24d924aa4df3ee32df506af34b618c4e50d261f4cc603f1bfd8d426915b7d629966c8ce45b05fb5ad8c8b9a6459d languageName: node linkType: hard "socks@npm:^2.6.2, socks@npm:^2.7.1": - version: 2.8.1 - resolution: "socks@npm:2.8.1" + version: 2.8.3 + resolution: "socks@npm:2.8.3" dependencies: ip-address: "npm:^9.0.5" smart-buffer: "npm:^4.2.0" - checksum: 10c0/ac77b515c260473cc7c4452f09b20939e22510ce3ae48385c516d1d5784374d5cc75be3cb18ff66cc985a7f4f2ef8fef84e984c5ec70aad58355ed59241f40a8 + checksum: 10c0/d54a52bf9325165770b674a67241143a3d8b4e4c8884560c4e0e078aace2a728dffc7f70150660f51b85797c4e1a3b82f9b7aa25e0a0ceae1a243365da5c51a7 languageName: node linkType: hard "sonic-boom@npm:^3.0.0, sonic-boom@npm:^3.7.0": - version: 3.8.0 - resolution: "sonic-boom@npm:3.8.0" + version: 3.8.1 + resolution: "sonic-boom@npm:3.8.1" dependencies: atomic-sleep: "npm:^1.0.0" - checksum: 10c0/f3f61cb3fd5d4aad862dd957f22318ef85bf47d4f12ba27b915112908449f752dbdfc95a4739d2b4a9b2770e1e08d349adae9d1030fdab2a3d86128c6773a7f4 + checksum: 10c0/9bf338f86147db50e116484f74f2e29a321a12733e0cefab3087c80dd32bf4df3d7407dbcafc13bc39ac269d9dd61dd6ef952354b9503392d4e1e7414f8e360e languageName: node linkType: hard -"source-map-js@npm:^1.0.2": - version: 1.0.2 - resolution: "source-map-js@npm:1.0.2" - checksum: 10c0/32f2dfd1e9b7168f9a9715eb1b4e21905850f3b50cf02cf476e47e4eebe8e6b762b63a64357896aa29b37e24922b4282df0f492e0d2ace572b43d15525976ff8 +"source-map-js@npm:^1.2.0": + version: 1.2.0 + resolution: "source-map-js@npm:1.2.0" + checksum: 10c0/7e5f896ac10a3a50fe2898e5009c58ff0dc102dcb056ed27a354623a0ece8954d4b2649e1a1b2b52ef2e161d26f8859c7710350930751640e71e374fe2d321a4 languageName: node linkType: hard @@ -9996,36 +10026,37 @@ __metadata: languageName: node linkType: hard -"string.prototype.trim@npm:^1.2.8": - version: 1.2.8 - resolution: "string.prototype.trim@npm:1.2.8" +"string.prototype.trim@npm:^1.2.9": + version: 1.2.9 + resolution: "string.prototype.trim@npm:1.2.9" dependencies: - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.2.0" - es-abstract: "npm:^1.22.1" - checksum: 10c0/4f76c583908bcde9a71208ddff38f67f24c9ec8093631601666a0df8b52fad44dad2368c78895ce83eb2ae8e7068294cc96a02fc971ab234e4d5c9bb61ea4e34 + call-bind: "npm:^1.0.7" + define-properties: "npm:^1.2.1" + es-abstract: "npm:^1.23.0" + es-object-atoms: "npm:^1.0.0" + checksum: 10c0/dcef1a0fb61d255778155006b372dff8cc6c4394bc39869117e4241f41a2c52899c0d263ffc7738a1f9e61488c490b05c0427faa15151efad721e1a9fb2663c2 languageName: node linkType: hard -"string.prototype.trimend@npm:^1.0.7": - version: 1.0.7 - resolution: "string.prototype.trimend@npm:1.0.7" +"string.prototype.trimend@npm:^1.0.8": + version: 1.0.8 + resolution: "string.prototype.trimend@npm:1.0.8" dependencies: - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.2.0" - es-abstract: "npm:^1.22.1" - checksum: 10c0/53c24911c7c4d8d65f5ef5322de23a3d5b6b4db73273e05871d5ab4571ae5638f38f7f19d71d09116578fb060e5a145cc6a208af2d248c8baf7a34f44d32ce57 + call-bind: "npm:^1.0.7" + define-properties: "npm:^1.2.1" + es-object-atoms: "npm:^1.0.0" + checksum: 10c0/0a0b54c17c070551b38e756ae271865ac6cc5f60dabf2e7e343cceae7d9b02e1a1120a824e090e79da1b041a74464e8477e2da43e2775c85392be30a6f60963c languageName: node linkType: hard -"string.prototype.trimstart@npm:^1.0.7": - version: 1.0.7 - resolution: "string.prototype.trimstart@npm:1.0.7" +"string.prototype.trimstart@npm:^1.0.8": + version: 1.0.8 + resolution: "string.prototype.trimstart@npm:1.0.8" dependencies: - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.2.0" - es-abstract: "npm:^1.22.1" - checksum: 10c0/0bcf391b41ea16d4fda9c9953d0a7075171fe090d33b4cf64849af94944c50862995672ac03e0c5dba2940a213ad7f53515a668dac859ce22a0276289ae5cf4f + call-bind: "npm:^1.0.7" + define-properties: "npm:^1.2.1" + es-object-atoms: "npm:^1.0.0" + checksum: 10c0/d53af1899959e53c83b64a5fd120be93e067da740e7e75acb433849aa640782fb6c7d4cd5b84c954c84413745a3764df135a8afeb22908b86a835290788d8366 languageName: node linkType: hard @@ -10170,8 +10201,8 @@ __metadata: linkType: hard "tar@npm:^6.0.2, tar@npm:^6.1.11, tar@npm:^6.1.2": - version: 6.2.0 - resolution: "tar@npm:6.2.0" + version: 6.2.1 + resolution: "tar@npm:6.2.1" dependencies: chownr: "npm:^2.0.0" fs-minipass: "npm:^2.0.0" @@ -10179,7 +10210,7 @@ __metadata: minizlib: "npm:^2.1.1" mkdirp: "npm:^1.0.3" yallist: "npm:^4.0.0" - checksum: 10c0/02ca064a1a6b4521fef88c07d389ac0936730091f8c02d30ea60d472e0378768e870769ab9e986d87807bfee5654359cf29ff4372746cc65e30cbddc352660d8 + checksum: 10c0/a5eca3eb50bc11552d453488344e6507156b9193efd7635e98e867fab275d527af53d8866e2370cd09dfe74378a18111622ace35af6a608e5223a7d27fe99537 languageName: node linkType: hard @@ -10206,8 +10237,8 @@ __metadata: linkType: hard "terser@npm:^5.10.0, terser@npm:^5.26.0": - version: 5.28.1 - resolution: "terser@npm:5.28.1" + version: 5.30.3 + resolution: "terser@npm:5.30.3" dependencies: "@jridgewell/source-map": "npm:^0.3.3" acorn: "npm:^8.8.2" @@ -10215,7 +10246,7 @@ __metadata: source-map-support: "npm:~0.5.20" bin: terser: bin/terser - checksum: 10c0/e0d9a3cd260b4e35b49e828687658e36b0f50dce7cc2e18f024725846013ffa0e9eb8ac61a7a1bbf6684e6c14493ccf155a0f5937a47c746f534208f9000ac29 + checksum: 10c0/ab5a8afef2e7a3b12a0fd17f9ff984fe02aefa945985eb139ab9984280d523a1104021eda889a7f993b69a67574ceb8fd0db8b76e5efc6a7607246db51bcc0b6 languageName: node linkType: hard @@ -10349,11 +10380,11 @@ __metadata: linkType: hard "ts-api-utils@npm:^1.0.1": - version: 1.2.1 - resolution: "ts-api-utils@npm:1.2.1" + version: 1.3.0 + resolution: "ts-api-utils@npm:1.3.0" peerDependencies: typescript: ">=4.2.0" - checksum: 10c0/8ddb493e7ae581d3f57a2e469142feb60b420d4ad8366ab969fe8e36531f8f301f370676b47e8d97f28b5f5fd10d6f2d55f656943a8546ef95e35ce5cf117754 + checksum: 10c0/f54a0ba9ed56ce66baea90a3fa087a484002e807f28a8ccb2d070c75e76bde64bd0f6dce98b3802834156306050871b67eec325cb4e918015a360a3f0868c77c languageName: node linkType: hard @@ -10590,9 +10621,9 @@ __metadata: languageName: node linkType: hard -"typed-array-length@npm:^1.0.5": - version: 1.0.5 - resolution: "typed-array-length@npm:1.0.5" +"typed-array-length@npm:^1.0.6": + version: 1.0.6 + resolution: "typed-array-length@npm:1.0.6" dependencies: call-bind: "npm:^1.0.7" for-each: "npm:^0.3.3" @@ -10600,27 +10631,27 @@ __metadata: has-proto: "npm:^1.0.3" is-typed-array: "npm:^1.1.13" possible-typed-array-names: "npm:^1.0.0" - checksum: 10c0/5cc0f79196e70a92f8f40846cfa62b3de6be51e83f73655e137116cf65e3c29a288502b18cc8faf33c943c2470a4569009e1d6da338441649a2db2f135761ad5 + checksum: 10c0/74253d7dc488eb28b6b2711cf31f5a9dcefc9c41b0681fd1c178ed0a1681b4468581a3626d39cd4df7aee3d3927ab62be06aa9ca74e5baf81827f61641445b77 languageName: node linkType: hard "typescript@npm:^5.0.4": - version: 5.3.3 - resolution: "typescript@npm:5.3.3" + version: 5.4.5 + resolution: "typescript@npm:5.4.5" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 10c0/e33cef99d82573624fc0f854a2980322714986bc35b9cb4d1ce736ed182aeab78e2cb32b385efa493b2a976ef52c53e20d6c6918312353a91850e2b76f1ea44f + checksum: 10c0/2954022ada340fd3d6a9e2b8e534f65d57c92d5f3989a263754a78aba549f7e6529acc1921913560a4b816c46dce7df4a4d29f9f11a3dc0d4213bb76d043251e languageName: node linkType: hard "typescript@patch:typescript@npm%3A^5.0.4#optional!builtin": - version: 5.3.3 - resolution: "typescript@patch:typescript@npm%3A5.3.3#optional!builtin::version=5.3.3&hash=e012d7" + version: 5.4.5 + resolution: "typescript@patch:typescript@npm%3A5.4.5#optional!builtin::version=5.4.5&hash=d69c25" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 10c0/1d0a5f4ce496c42caa9a30e659c467c5686eae15d54b027ee7866744952547f1be1262f2d40de911618c242b510029d51d43ff605dba8fb740ec85ca2d3f9500 + checksum: 10c0/9cf4c053893bcf327d101b6c024a55baf05430dc30263f9adb1bf354aeffc11306fe1f23ba2f9a0209674359f16219b5b7d229e923477b94831d07d5a33a4217 languageName: node linkType: hard @@ -10823,8 +10854,8 @@ __metadata: linkType: hard "viem@npm:^2.7.15": - version: 2.7.19 - resolution: "viem@npm:2.7.19" + version: 2.9.17 + resolution: "viem@npm:2.9.17" dependencies: "@adraffy/ens-normalize": "npm:1.10.0" "@noble/curves": "npm:1.2.0" @@ -10839,7 +10870,7 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 10c0/aa7e8750eca7d02eab1819ec7d85ba2d3669c65b133c919dc34ea0052c236e75220e25d667a604dd76d36f92958d60a52d6772c58cf725435f728ca4c70ee9b7 + checksum: 10c0/e26843e0f143d110f0111071e6ef3f7bbdc47263c849db47e32c94637ebad1c7180dd386d3af9b485d79dd09b7f58e3b9fc96c9fb5a2e61979c3c5b8a48735af languageName: node linkType: hard @@ -10852,13 +10883,13 @@ __metadata: languageName: node linkType: hard -"watchpack@npm:^2.4.0": - version: 2.4.0 - resolution: "watchpack@npm:2.4.0" +"watchpack@npm:^2.4.1": + version: 2.4.1 + resolution: "watchpack@npm:2.4.1" dependencies: glob-to-regexp: "npm:^0.4.1" graceful-fs: "npm:^4.1.2" - checksum: 10c0/c5e35f9fb9338d31d2141d9835643c0f49b5f9c521440bb648181059e5940d93dd8ed856aa8a33fbcdd4e121dad63c7e8c15c063cf485429cd9d427be197fe62 + checksum: 10c0/c694de0a61004e587a8a0fdc9cfec20ee692c52032d9ab2c2e99969a37fdab9e6e1bd3164ed506f9a13f7c83e65563d563e0d6b87358470cdb7309b83db78683 languageName: node linkType: hard @@ -10903,9 +10934,9 @@ __metadata: languageName: node linkType: hard -"webpack-dev-middleware@npm:^5.3.1": - version: 5.3.3 - resolution: "webpack-dev-middleware@npm:5.3.3" +"webpack-dev-middleware@npm:^5.3.4": + version: 5.3.4 + resolution: "webpack-dev-middleware@npm:5.3.4" dependencies: colorette: "npm:^2.0.10" memfs: "npm:^3.4.3" @@ -10914,13 +10945,13 @@ __metadata: schema-utils: "npm:^4.0.0" peerDependencies: webpack: ^4.0.0 || ^5.0.0 - checksum: 10c0/378ceed430b61c0b0eccdbb55a97173aa36231bb88e20ad12bafb3d553e542708fa31f08474b9c68d4ac95174a047def9e426e193b7134be3736afa66a0d1708 + checksum: 10c0/257df7d6bc5494d1d3cb66bba70fbdf5a6e0423e39b6420f7631aeb52435afbfbff8410a62146dcdf3d2f945c62e03193aae2ac1194a2f7d5a2523b9d194e9e1 languageName: node linkType: hard "webpack-dev-server@npm:^4.15.1": - version: 4.15.1 - resolution: "webpack-dev-server@npm:4.15.1" + version: 4.15.2 + resolution: "webpack-dev-server@npm:4.15.2" dependencies: "@types/bonjour": "npm:^3.5.9" "@types/connect-history-api-fallback": "npm:^1.3.5" @@ -10950,7 +10981,7 @@ __metadata: serve-index: "npm:^1.9.1" sockjs: "npm:^0.3.24" spdy: "npm:^4.0.2" - webpack-dev-middleware: "npm:^5.3.1" + webpack-dev-middleware: "npm:^5.3.4" ws: "npm:^8.13.0" peerDependencies: webpack: ^4.37.0 || ^5.0.0 @@ -10961,7 +10992,7 @@ __metadata: optional: true bin: webpack-dev-server: bin/webpack-dev-server.js - checksum: 10c0/2cf3edf556dcafdfc938e0adeac3dadf97fb959ed66b88bdd70acdb0b77b0f25be5e2d4b30cca2da8732548451418cadf00eb09e751e7674ff914fd9ab646b26 + checksum: 10c0/625bd5b79360afcf98782c8b1fd710b180bb0e96d96b989defff550c546890010ceea82ffbecb2a0a23f7f018bc72f2dee7b3070f7b448fb0110df6657fb2904 languageName: node linkType: hard @@ -10984,24 +11015,24 @@ __metadata: linkType: hard "webpack@npm:^5.88.2, webpack@npm:^5.90.1": - version: 5.90.3 - resolution: "webpack@npm:5.90.3" + version: 5.91.0 + resolution: "webpack@npm:5.91.0" dependencies: "@types/eslint-scope": "npm:^3.7.3" "@types/estree": "npm:^1.0.5" - "@webassemblyjs/ast": "npm:^1.11.5" - "@webassemblyjs/wasm-edit": "npm:^1.11.5" - "@webassemblyjs/wasm-parser": "npm:^1.11.5" + "@webassemblyjs/ast": "npm:^1.12.1" + "@webassemblyjs/wasm-edit": "npm:^1.12.1" + "@webassemblyjs/wasm-parser": "npm:^1.12.1" acorn: "npm:^8.7.1" acorn-import-assertions: "npm:^1.9.0" browserslist: "npm:^4.21.10" chrome-trace-event: "npm:^1.0.2" - enhanced-resolve: "npm:^5.15.0" + enhanced-resolve: "npm:^5.16.0" es-module-lexer: "npm:^1.2.1" eslint-scope: "npm:5.1.1" events: "npm:^3.2.0" glob-to-regexp: "npm:^0.4.1" - graceful-fs: "npm:^4.2.9" + graceful-fs: "npm:^4.2.11" json-parse-even-better-errors: "npm:^2.3.1" loader-runner: "npm:^4.2.0" mime-types: "npm:^2.1.27" @@ -11009,14 +11040,14 @@ __metadata: schema-utils: "npm:^3.2.0" tapable: "npm:^2.1.1" terser-webpack-plugin: "npm:^5.3.10" - watchpack: "npm:^2.4.0" + watchpack: "npm:^2.4.1" webpack-sources: "npm:^3.2.3" peerDependenciesMeta: webpack-cli: optional: true bin: webpack: bin/webpack.js - checksum: 10c0/f737aa871cadbbae89833eb85387f1bf9ee0768f039100a3c8134f2fdcc78c3230ca775c373b1aa467b272f74c6831e119f7a8a1c14dcac97327212be9c93eeb + checksum: 10c0/74a3e0ea1c9a492accf035317f31769ffeaaab415811524b9f17bc7bf7012c5b6e1a9860df5ca6903f3ae2618727b801eb47d9351a2595dfffb25941d368b88c languageName: node linkType: hard @@ -11051,16 +11082,16 @@ __metadata: languageName: node linkType: hard -"which-typed-array@npm:^1.1.14, which-typed-array@npm:^1.1.2": - version: 1.1.14 - resolution: "which-typed-array@npm:1.1.14" +"which-typed-array@npm:^1.1.14, which-typed-array@npm:^1.1.15, which-typed-array@npm:^1.1.2": + version: 1.1.15 + resolution: "which-typed-array@npm:1.1.15" dependencies: - available-typed-arrays: "npm:^1.0.6" - call-bind: "npm:^1.0.5" + available-typed-arrays: "npm:^1.0.7" + call-bind: "npm:^1.0.7" for-each: "npm:^0.3.3" gopd: "npm:^1.0.1" - has-tostringtag: "npm:^1.0.1" - checksum: 10c0/0960f1e77807058819451b98c51d4cd72031593e8de990b24bd3fc22e176f5eee22921d68d852297c786aec117689f0423ed20aa4fde7ce2704d680677891f56 + has-tostringtag: "npm:^1.0.2" + checksum: 10c0/4465d5348c044032032251be54d8988270e69c6b7154f8fcb2a47ff706fe36f7624b3a24246b8d9089435a8f4ec48c1c1025c5d6b499456b9e5eff4f48212983 languageName: node linkType: hard @@ -11242,9 +11273,9 @@ __metadata: linkType: hard "ylru@npm:^1.2.0": - version: 1.3.2 - resolution: "ylru@npm:1.3.2" - checksum: 10c0/1fcdf0e6428fa4be71d8b1ae96ee6134d8c6194bd23e531b755b9d90bb9c555592415dc629501fe9036dfa410e2e71d0d093e5c91625df46d8e546a29e658ebe + version: 1.4.0 + resolution: "ylru@npm:1.4.0" + checksum: 10c0/eaadc38ed6d78d4fda49abed45cfdaf149bd334df761dbeadd3cff62936d25ffa94571f84c25b64a9a4b5efd8f489ee6fee3eaaf8e7b2886418a3bcb9ec84b84 languageName: node linkType: hard @@ -11263,14 +11294,14 @@ __metadata: linkType: hard "yup@npm:^1.2.0": - version: 1.3.3 - resolution: "yup@npm:1.3.3" + version: 1.4.0 + resolution: "yup@npm:1.4.0" dependencies: property-expr: "npm:^2.0.5" tiny-case: "npm:^1.0.3" toposort: "npm:^2.0.2" type-fest: "npm:^2.19.0" - checksum: 10c0/cc00e98af8617b779dd151d6a77779228cfe973a185c743628b2afdecda88c333187d058c1199518d696c15827ba9b757a6c57c1ace6766d970d3cd2368c3264 + checksum: 10c0/fe142141365eed0f78fb2e18bdd2f10bf101385dae12a5f9de14884448067bdca16a54b547fc0bffec04a098dd70b4519ff366422f3da006fd11a0717a7863ac languageName: node linkType: hard From 12064f95abb3125933eb55996abb978c4aeaad53 Mon Sep 17 00:00:00 2001 From: ludamad Date: Thu, 18 Apr 2024 10:25:16 -0400 Subject: [PATCH 014/102] feat: more robust spot shutdown + CI commandline (#5825) Github Actions runners are a game, and if you get assigned a runner that is going down, you lose. This includes some logic inspired by a github actions controller for kubernetes to bring down runners gracefully. also includes a ci.py script you can use: ./ci.py print("1. SSH into build machine") print("2. SSH into bench machine") print("3. Start/Stop spot machines") print("4. Manage Running Jobs") 4 has more subactions as well for viewing, cancelling, rerunning (including running spot as recommended for fail reruns) from commandline --- .github/workflows/ci.yml | 2 +- .github/workflows/setup-runner.yml | 14 +++- .github/workflows/start-spot.yml | 2 +- .github/workflows/stop-spot.yml | 2 +- ci.py | 101 ++++++++++++++++++++++++ scripts/ci/maybe_exit_spot.sh | 37 +++++++++ scripts/ci/spot_runner_graceful_exit.sh | 43 ++++++++++ 7 files changed, 194 insertions(+), 7 deletions(-) create mode 100755 ci.py create mode 100644 scripts/ci/maybe_exit_spot.sh create mode 100644 scripts/ci/spot_runner_graceful_exit.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8ad90c70469..1b5547c9488 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,7 +22,7 @@ jobs: with: runner_label: ${{ github.actor }}-x86 ebs_cache_size_gb: 256 - runner_concurrency: 50 + runner_concurrency: 20 subaction: ${{ github.event.inputs.runner_action || 'start' }} ec2_instance_type: m6a.32xlarge ec2_ami_id: ami-04d8422a9ba4de80f diff --git a/.github/workflows/setup-runner.yml b/.github/workflows/setup-runner.yml index c581738eace..4aa9f22ac8d 100644 --- a/.github/workflows/setup-runner.yml +++ b/.github/workflows/setup-runner.yml @@ -19,6 +19,7 @@ on: ec2_ami_id: required: true type: string + # how much time to add to shutdown when a job finishes or starts ec2_instance_ttl: required: true type: number @@ -57,7 +58,7 @@ jobs: group: start-builder-${{ inputs.runner_label }} steps: - name: Start EC2 runner - uses: AztecProtocol/ec2-action-builder@v0.13 + uses: AztecProtocol/ec2-action-builder@v0.14e with: github_token: ${{ secrets.GH_SELF_HOSTED_RUNNER_TOKEN }} aws_access_key_id: ${{ secrets.AWS_ACCESS_KEY_ID }} @@ -96,15 +97,20 @@ jobs: AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} run: ./scripts/attach_ebs_cache.sh ${{ inputs.runner_label }} ${{ inputs.ebs_cache_size_gb }} - - name: Configure and Restart Docker + - name: Configure Machine shell: bash run: | - # We need to restart after attaching disk cache - # Both only happen once, so we just make sure this happens once + # One-time config if ! [ -f /etc/docker/daemon.json ] ; then echo '{"default-address-pools":[{"base":"172.17.0.0/12","size":20}, {"base":"10.99.0.0/12","size":20}, {"base":"192.168.0.0/16","size":24}]}' > /etc/docker/daemon.json sudo service docker restart echo "Configured docker daemon for making many networks." + # Run maybe_exit_spot.sh every minute + cp scripts/ci/spot_runner_graceful_exit.sh /run/spot_runner_graceful_exit.sh + cp scripts/ci/maybe_exit_spot.sh /run/maybe_exit_spot.sh + chmod +x /run/spot_runner_graceful_exit.sh + chmod +x /run/maybe_exit_spot.sh + echo "* * * * * /run/maybe_exit_spot.sh" | crontab - else echo "Docker daemon already configured." fi diff --git a/.github/workflows/start-spot.yml b/.github/workflows/start-spot.yml index f6b532935fa..f3d84c1f557 100644 --- a/.github/workflows/start-spot.yml +++ b/.github/workflows/start-spot.yml @@ -8,7 +8,7 @@ jobs: with: runner_label: ${{ github.actor }}-x86 ebs_cache_size_gb: 256 - runner_concurrency: 50 + runner_concurrency: 20 subaction: start ec2_instance_type: m6a.32xlarge ec2_ami_id: ami-04d8422a9ba4de80f diff --git a/.github/workflows/stop-spot.yml b/.github/workflows/stop-spot.yml index 61ce3650066..750fca5a523 100644 --- a/.github/workflows/stop-spot.yml +++ b/.github/workflows/stop-spot.yml @@ -10,7 +10,7 @@ jobs: subaction: stop # not used: ebs_cache_size_gb: 128 - runner_concurrency: 50 + runner_concurrency: 20 ec2_instance_type: m6a.32xlarge ec2_ami_id: ami-0d8a9b0419ddb331a ec2_instance_ttl: 40 diff --git a/ci.py b/ci.py new file mode 100755 index 00000000000..f5127ec0759 --- /dev/null +++ b/ci.py @@ -0,0 +1,101 @@ +#!/usr/bin/env python3 +# ubuntu: apt install python3-blessed +from blessed import Terminal +import os, json, subprocess, sys + +term = Terminal() +if 'GITHUB_ACTOR' not in os.environ: + print("Make sure you have GITHUB_ACTOR in your environment variables e.g. .zshrc") + sys.exit(1) +GITHUB_ACTOR = os.environ['GITHUB_ACTOR'] + +def main(): + selection = -1 + with term.fullscreen(), term.cbreak(): + print(term.home + term.clear) + while selection not in ('1', '2', '3', '4', 'q'): + print(term.move_y(1) + "Please select an option:") + print("1. SSH into build machine") + print("2. SSH into bench machine") + print("3. Start/Stop spot machines") + print("4. Manage Running Jobs") + print("q. Quit") + with term.location(0, term.height - 1): + selection = term.inkey() + + if selection == '1': + ssh_into_machine('x86') + elif selection == '2': + ssh_into_machine('bench-x86') + elif selection == '3': + manage_spot_instances() + elif selection == '4': + manage_ci_workflows() + +def ssh_into_machine(suffix): + GITHUB_ACTOR = os.getenv('GITHUB_ACTOR', 'default_actor') + ssh_key_path = os.path.expanduser('~/.ssh/build_instance_key') + if not os.path.exists(ssh_key_path): + print("SSH key does not exist.") + return + + # Command to get the instance information + cmd = f'aws ec2 describe-instances --filters "Name=instance-state-name,Values=running" "Name=tag:Name,Values=aztec-packages-{GITHUB_ACTOR}-{suffix}" --output json --region us-east-2' + result = subprocess.run(cmd, shell=True, capture_output=True, text=True) + if result.returncode != 0: + print("Failed to get AWS instances:", result.stderr) + return + + # Parse the output to find the public IP address + try: + instances_data = json.loads(result.stdout) + instance = instances_data['Reservations'][0]['Instances'][0] + instance_ip = instance['PublicIpAddress'] + except (KeyError, IndexError, json.JSONDecodeError) as e: + print("Error parsing AWS CLI output:", e) + return + + # SSH command using the public IP + ssh_cmd = f"ssh -o StrictHostKeychecking=no -i {ssh_key_path} ubuntu@{instance_ip}" + print(f"Connecting to {instance_ip}. Consider delaying the impeding shutdown.") + ssh_process = subprocess.Popen(ssh_cmd, shell=True) + ssh_process.wait() # Wait for the SSH session to complete + +def manage_spot_instances(): + action = input("Enter 'start' to run or 'stop' to stop spot instances: ") + if action == 'start': + subprocess.run('gh workflow run start-spot.yml', shell=True) + elif action == 'stop': + subprocess.run('gh workflow run stop-spot.yml', shell=True) + +def manage_ci_workflows(): + # Retrieve the most recent workflow run + cmd = f"gh run list --workflow=ci.yml -u {GITHUB_ACTOR} --limit 5" + result = subprocess.run(cmd, shell=True, capture_output=True, text=True) + if result.returncode != 0 or not result.stdout.strip(): + print("Failed to retrieve workflow runs or no runs found.") + return + print("Most recent CI run details:") + print(result.stdout) + + action = input("Enter action 'cancel', 'rerun', 'rerun-all', 'force-cancel' or 'view' (default)") or 'view' + print(f"\nWill perform {action}") + run_id = input(f"Enter the run ID to {action}: ") + + if action.lower() == 'cancel': + subprocess.run(f"gh run cancel {run_id}", shell=True) + if action.lower() == 'rerun': + # needed so the spot runners still work + subprocess.run('gh workflow run start-spot.yml', shell=True) + subprocess.run(f"gh run rerun {run_id} --failed", shell=True) + elif action.lower() == 'rerun-all': + subprocess.run(f"gh run rerun {run_id}", shell=True) + elif action.lower() == 'force-cancel': + subprocess.run('gh api --method POST -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28" ' + + '/repos/AztecProtocol/aztec-packages/actions/runs/' + run_id + '/force-cancel', shell=True) + else: + subprocess.run(f"gh run watch {run_id}", shell=True) + +if __name__ == "__main__": + main() + diff --git a/scripts/ci/maybe_exit_spot.sh b/scripts/ci/maybe_exit_spot.sh new file mode 100644 index 00000000000..4ef4cdc7279 --- /dev/null +++ b/scripts/ci/maybe_exit_spot.sh @@ -0,0 +1,37 @@ +#!/bin/bash +set -eux + +MAX_WAIT_TIME=300 # Maximum wait time in seconds +WAIT_INTERVAL=10 # Interval between checks in seconds +elapsed_time=0 + +exec &> >(tee -a /run/.maybe-exit-log) + +# we have this in a minutely crontab for simplicity, but we only want one to run +if [ -f /run/.maybe-exit-spot-lock ] ; then + echo "Already running maybe_exit_spot.sh" + exit +fi + +exec >/run/.maybe-exit-spot-log + +cleanup() { + rm /run/.maybe-exit-spot-lock +} + +trap cleanup EXIT +touch /run/.maybe-exit-spot-lock + +# We wait to see if a runner comes up in +while ! pgrep Runner.Worker > /dev/null; do + if [ $elapsed_time -ge $MAX_WAIT_TIME ]; then + echo "Found no runner for $MAX_WAIT_TIME, shutting down now." + /run/spot_runner_graceful_exit.sh + shutdown now + exit + fi + + sleep $WAIT_INTERVAL + elapsed_time=$((elapsed_time + WAIT_INTERVAL)) +done +echo "System seems alive, doing nothing." \ No newline at end of file diff --git a/scripts/ci/spot_runner_graceful_exit.sh b/scripts/ci/spot_runner_graceful_exit.sh new file mode 100644 index 00000000000..3b45ca6735d --- /dev/null +++ b/scripts/ci/spot_runner_graceful_exit.sh @@ -0,0 +1,43 @@ +# Adapted from https://github.com/actions/actions-runner-controller/blob/master/runner/graceful-stop.sh +#!/bin/bash + +set -eu + +export RUNNER_ALLOW_RUNASROOT=1 +# This should be short so that the job is cancelled immediately, instead of hanging for 10 minutes or so and failing without any error message. +RUNNER_GRACEFUL_STOP_TIMEOUT=${RUNNER_GRACEFUL_STOP_TIMEOUT:-15} + +echo "Executing graceful shutdown of github action runners." + +# The below procedure atomically removes the runner from GitHub Actions service, +# to ensure that the runner is not running any job. +# This is required to not terminate the actions runner agent while running the job. +# If we didn't do this atomically, we might end up with a rare race where +# the runner agent is terminated while it was about to start a job. + +# glob for all our installed runner directories +for RUNNER_DIR in /run/*-ec2-* ; do + pushd $RUNNER_DIR + ./config.sh remove --token "$(cat $RUNNER_DIR/.runner-token)" || true & + popd +done +wait + +if pgrep Runner.Listener > /dev/null; then + # The below procedure fixes the runner to correctly notify the Actions service for the cancellation of this runner. + # It enables you to see `Error: The operation was canceled.` vs having it hang for 10 minutes or so. + kill -TERM $(pgrep Runner.Listener) + while pgrep Runner.Listener > /dev/null; do + sleep 1 + done +fi +echo "Cleaning up lingering runner registrations." +for RUNNER_DIR in /run/*-ec2-* ; do + pushd $RUNNER_DIR + while [ -f .runner ] ; do + ./config.sh remove --token "$(cat $RUNNER_DIR/.runner-token)" || true + sleep 1 + done + popd +done +echo "Graceful github runner stop completed." \ No newline at end of file From 741fdf16e7f0b3f116c724505afa8e604bc51bf1 Mon Sep 17 00:00:00 2001 From: Alex Gherghisan Date: Thu, 18 Apr 2024 15:42:07 +0100 Subject: [PATCH 015/102] feat: add TimeoutError (#5751) Adds `TimeoutError` and updates `MemoryFifo` to throw a `TimeoutError` when getting an item from the queue times out. Renames `errors` to just `error` to match the sub-module exported in `package.json` --- yarn-project/foundation/src/{errors => error}/index.ts | 5 +++++ yarn-project/foundation/src/fifo/memory_fifo.ts | 3 ++- yarn-project/foundation/src/index.ts | 2 +- yarn-project/foundation/src/sleep/index.ts | 2 +- yarn-project/foundation/src/sleep/sleep.test.ts | 2 +- 5 files changed, 10 insertions(+), 4 deletions(-) rename yarn-project/foundation/src/{errors => error}/index.ts (75%) diff --git a/yarn-project/foundation/src/errors/index.ts b/yarn-project/foundation/src/error/index.ts similarity index 75% rename from yarn-project/foundation/src/errors/index.ts rename to yarn-project/foundation/src/error/index.ts index 4da2608b451..2bc84be567f 100644 --- a/yarn-project/foundation/src/errors/index.ts +++ b/yarn-project/foundation/src/error/index.ts @@ -4,3 +4,8 @@ * can be used to handle cases where a process or task is terminated before completion. */ export class InterruptError extends Error {} + +/** + * An error thrown when an action times out. + */ +export class TimeoutError extends Error {} diff --git a/yarn-project/foundation/src/fifo/memory_fifo.ts b/yarn-project/foundation/src/fifo/memory_fifo.ts index 39c6a0b0d10..bcd0145fb58 100644 --- a/yarn-project/foundation/src/fifo/memory_fifo.ts +++ b/yarn-project/foundation/src/fifo/memory_fifo.ts @@ -1,3 +1,4 @@ +import { TimeoutError } from '../error/index.js'; import { createDebugLogger } from '../log/index.js'; /** @@ -46,7 +47,7 @@ export class MemoryFifo { const index = this.waiting.findIndex(r => r === resolve); if (index > -1) { this.waiting.splice(index, 1); - const err = new Error('Timeout getting item from queue.'); + const err = new TimeoutError('Timeout getting item from queue.'); reject(err); } }, timeout * 1000); diff --git a/yarn-project/foundation/src/index.ts b/yarn-project/foundation/src/index.ts index 7e06583f10d..55f05e503ab 100644 --- a/yarn-project/foundation/src/index.ts +++ b/yarn-project/foundation/src/index.ts @@ -6,7 +6,7 @@ export * as bigintBuffer from './bigint-buffer/index.js'; export * as collection from './collection/index.js'; export * as committable from './committable/index.js'; export * as crypto from './crypto/index.js'; -export * as errors from './errors/index.js'; +export * as errors from './error/index.js'; export * as ethAddress from './eth-address/index.js'; export * as fields from './fields/index.js'; export * as fifo from './fifo/index.js'; diff --git a/yarn-project/foundation/src/sleep/index.ts b/yarn-project/foundation/src/sleep/index.ts index 864cc0e019b..725e8fb4b22 100644 --- a/yarn-project/foundation/src/sleep/index.ts +++ b/yarn-project/foundation/src/sleep/index.ts @@ -1,4 +1,4 @@ -import { InterruptError } from '../errors/index.js'; +import { InterruptError } from '../error/index.js'; /** * InterruptibleSleep is a utility class that allows you to create an interruptible sleep function. diff --git a/yarn-project/foundation/src/sleep/sleep.test.ts b/yarn-project/foundation/src/sleep/sleep.test.ts index 0063a05bbf1..f23db2ef800 100644 --- a/yarn-project/foundation/src/sleep/sleep.test.ts +++ b/yarn-project/foundation/src/sleep/sleep.test.ts @@ -1,6 +1,6 @@ import { jest } from '@jest/globals'; -import { InterruptError } from '../errors/index.js'; +import { InterruptError } from '../error/index.js'; import { InterruptibleSleep } from './index.js'; describe('InterruptibleSleep', () => { From 2422891fa021cfb4c83b91849ff1f22baa93a4b9 Mon Sep 17 00:00:00 2001 From: Santiago Palladino Date: Thu, 18 Apr 2024 12:08:44 -0300 Subject: [PATCH 016/102] chore: Validate instance deployer address every time we request it (#5848) Prevents deep errors in e2e tests where we fail to find a publicly deployed contract because the address of the deployer does not match. --- .../protocol-contracts/src/instance-deployer/index.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/yarn-project/protocol-contracts/src/instance-deployer/index.ts b/yarn-project/protocol-contracts/src/instance-deployer/index.ts index 7a3101fa789..9b9935da037 100644 --- a/yarn-project/protocol-contracts/src/instance-deployer/index.ts +++ b/yarn-project/protocol-contracts/src/instance-deployer/index.ts @@ -5,7 +5,13 @@ import { ContractInstanceDeployerArtifact } from './artifact.js'; /** Returns the canonical deployment of the instance deployer contract. */ export function getCanonicalInstanceDeployer(): ProtocolContract { - return getCanonicalProtocolContract(ContractInstanceDeployerArtifact, 1); + const contract = getCanonicalProtocolContract(ContractInstanceDeployerArtifact, 1); + if (!contract.address.equals(InstanceDeployerAddress)) { + throw new Error( + `Incorrect address for contract deployer (got ${contract.address.toString()} but expected (${InstanceDeployerAddress.toString()}). Check DEPLOYER_CONTRACT_ADDRESS is set to the correct value in the constants files and run the protocol-contracts package tests.`, + ); + } + return contract; } export const InstanceDeployerAddress = AztecAddress.fromBigInt(DEPLOYER_CONTRACT_ADDRESS); From a821bccef7b1894140f0495510d7c6b4eefde821 Mon Sep 17 00:00:00 2001 From: Jean M <132435771+jeanmon@users.noreply.github.com> Date: Thu, 18 Apr 2024 17:40:15 +0200 Subject: [PATCH 017/102] feat(avm): CAST opcode implementation (#5477) Resolves #5466 --- barretenberg/cpp/pil/avm/avm_alu.pil | 59 ++++- barretenberg/cpp/pil/avm/avm_main.pil | 35 ++- .../ecc/fields/field_declarations.hpp | 12 + .../relations/generated/avm/avm_alu.hpp | 110 +++++++-- .../relations/generated/avm/avm_main.hpp | 214 ++++++++++-------- .../relations/generated/avm/declare_views.hpp | 7 + .../relations/generated/avm/perm_main_alu.hpp | 10 +- .../vm/avm_trace/avm_alu_trace.cpp | 87 ++++++- .../vm/avm_trace/avm_alu_trace.hpp | 7 +- .../barretenberg/vm/avm_trace/avm_common.hpp | 1 - .../vm/avm_trace/avm_deserialization.cpp | 2 + .../vm/avm_trace/avm_execution.cpp | 7 + .../vm/avm_trace/avm_mem_trace.cpp | 50 +++- .../vm/avm_trace/avm_mem_trace.hpp | 1 + .../barretenberg/vm/avm_trace/avm_opcode.cpp | 145 +----------- .../barretenberg/vm/avm_trace/avm_opcode.hpp | 2 - .../barretenberg/vm/avm_trace/avm_trace.cpp | 95 +++++++- .../barretenberg/vm/avm_trace/avm_trace.hpp | 4 + .../vm/generated/avm_circuit_builder.hpp | 18 +- .../barretenberg/vm/generated/avm_flavor.hpp | 208 ++++++++++++----- .../barretenberg/vm/generated/avm_prover.cpp | 8 + .../vm/generated/avm_verifier.cpp | 8 + .../barretenberg/vm/tests/avm_cast.test.cpp | 208 +++++++++++++++++ .../vm/tests/avm_execution.test.cpp | 41 ++++ 24 files changed, 995 insertions(+), 344 deletions(-) create mode 100644 barretenberg/cpp/src/barretenberg/vm/tests/avm_cast.test.cpp diff --git a/barretenberg/cpp/pil/avm/avm_alu.pil b/barretenberg/cpp/pil/avm/avm_alu.pil index 8e2a578c5df..cc39ef9ca7e 100644 --- a/barretenberg/cpp/pil/avm/avm_alu.pil +++ b/barretenberg/cpp/pil/avm/avm_alu.pil @@ -17,11 +17,13 @@ namespace avm_alu(256); pol commit op_div; pol commit op_not; pol commit op_eq; + pol commit op_cast; + pol commit op_cast_prev; // Predicate on whether op_cast is enabled at previous row pol commit alu_sel; // Predicate to activate the copy of intermediate registers to ALU table. pol commit op_lt; pol commit op_lte; pol commit cmp_sel; // Predicate if LT or LTE is set - pol commit rng_chk_sel; // Predicate representing a range check row. + pol commit rng_chk_sel; // Predicate representing a range check row used in LT/LTE. // Instruction tag (1: u8, 2: u16, 3: u32, 4: u64, 5: u128, 6: field) copied from Main table pol commit in_tag; @@ -59,7 +61,7 @@ namespace avm_alu(256); pol commit cf; // Compute predicate telling whether there is a row entry in the ALU table. - alu_sel = op_add + op_sub + op_mul + op_not + op_eq + op_lt + op_lte; + alu_sel = op_add + op_sub + op_mul + op_not + op_eq + op_cast + op_lt + op_lte; cmp_sel = op_lt + op_lte; // ========= Type Constraints ============================================= @@ -282,7 +284,7 @@ namespace avm_alu(256); // (x - y - 1) * q + (y - x) (1 - q) = result // If LT, then swap ia and ib else keep the same - pol INPUT_IA = op_lt * ib + op_lte * ia; + pol INPUT_IA = op_lt * ib + (op_lte + op_cast) * ia; pol INPUT_IB = op_lt * ia + op_lte * ib; pol commit borrow; @@ -290,7 +292,7 @@ namespace avm_alu(256); pol commit a_hi; // Check INPUT_IA is well formed from its lo and hi limbs #[INPUT_DECOMP_1] - INPUT_IA = (a_lo + 2 ** 128 * a_hi) * cmp_sel; + INPUT_IA = (a_lo + 2 ** 128 * a_hi) * (cmp_sel + op_cast); pol commit b_lo; pol commit b_hi; @@ -311,9 +313,9 @@ namespace avm_alu(256); // First condition is if borrow = 0, second condition is if borrow = 1 // This underflow check is done by the 128-bit check that is performed on each of these lo and hi limbs. #[SUB_LO_1] - (p_sub_a_lo - (53438638232309528389504892708671455232 - a_lo + p_a_borrow * 2 ** 128)) * cmp_sel = 0; + (p_sub_a_lo - (53438638232309528389504892708671455232 - a_lo + p_a_borrow * 2 ** 128)) * (cmp_sel + op_cast) = 0; #[SUB_HI_1] - (p_sub_a_hi - (64323764613183177041862057485226039389 - a_hi - p_a_borrow)) * cmp_sel = 0; + (p_sub_a_hi - (64323764613183177041862057485226039389 - a_hi - p_a_borrow)) * (cmp_sel + op_cast) = 0; pol commit p_sub_b_lo; pol commit p_sub_b_hi; @@ -432,11 +434,11 @@ namespace avm_alu(256); cmp_rng_ctr * ((1 - rng_chk_sel) * (1 - op_eq_diff_inv) + op_eq_diff_inv) - rng_chk_sel = 0; // We perform a range check if we have some range checks remaining or we are performing a comparison op - pol RNG_CHK_OP = rng_chk_sel + cmp_sel; + pol RNG_CHK_OP = rng_chk_sel + cmp_sel + op_cast + op_cast_prev; pol commit rng_chk_lookup_selector; #[RNG_CHK_LOOKUP_SELECTOR] - rng_chk_lookup_selector' = cmp_sel' + rng_chk_sel' + op_add' + op_sub' + op_mul' + op_mul * u128_tag; + rng_chk_lookup_selector' = cmp_sel' + rng_chk_sel' + op_add' + op_sub' + op_mul' + op_mul * u128_tag + op_cast' + op_cast_prev'; // Perform 128-bit range check on lo part #[LOWER_CMP_RNG_CHK] @@ -467,3 +469,44 @@ namespace avm_alu(256); (p_sub_b_lo' - res_lo) * rng_chk_sel'= 0; (p_sub_b_hi' - res_hi) * rng_chk_sel'= 0; + + // ========= CAST Operation Constraints =============================== + // We handle the input ia independently of its tag, i.e., we suppose it can take + // any value between 0 and p-1. + // We decompose the input ia in 8-bit/16-bit limbs and prove that the decomposition + // sums up to ia over the integers (i.e., no modulo p wrapping). To prove this, we + // re-use techniques above from LT/LTE opcode. The following relations are toggled for CAST: + // - #[INPUT_DECOMP_1] shows a = a_lo + 2 ** 128 * a_hi + // - #[SUB_LO_1] and #[SUB_LO_1] shows that the above does not overflow modulo p. + // - We toggle RNG_CHK_OP with op_cast to show that a_lo, a_hi are correctly decomposed + // over the 8/16-bit ALU registers in #[LOWER_CMP_RNG_CHK] and #[UPPER_CMP_RNG_CHK]. + // - The 128-bit range checks for a_lo, a_hi are activated in #[RNG_CHK_LOOKUP_SELECTOR]. + // - We copy p_sub_a_lo resp. p_sub_a_hi into next row in columns a_lo resp. a_hi so + // that decomposition into the 8/16-bit ALU registers and range checks are performed. + // Copy is done in #[OP_CAST_RNG_CHECK_P_SUB_A_LOW/HIGH] below. + // Activation of decomposition and range check is achieved by adding op_cast_prev in + // #[LOWER_CMP_RNG_CHK], #[UPPER_CMP_RNG_CHK] and #[RNG_CHK_LOOKUP_SELECTOR]. + // - Finally, the truncated result SUM_TAG is copied in ic as part of #[ALU_OP_CAST] below. + // - Note that the tag of return value must be constrained to be in_tag and is enforced in + // the main and memory traces. + // + // TODO: Potential optimization is to un-toggle all CAST relevant operations when ff_tag is + // enabled. In this case, ic = ia trivially. + // Another one is to activate range checks in a more granular way depending on the tag. + + #[OP_CAST_PREV_LINE] + op_cast_prev' = op_cast; + + #[ALU_OP_CAST] + op_cast * (SUM_TAG + ff_tag * ia - ic) = 0; + + #[OP_CAST_RNG_CHECK_P_SUB_A_LOW] + op_cast * (a_lo' - p_sub_a_lo) = 0; + + #[OP_CAST_RNG_CHECK_P_SUB_A_HIGH] + op_cast * (a_hi' - p_sub_a_hi) = 0; + + // 128-bit multiplication and CAST need two rows in ALU trace. We need to ensure + // that another ALU operation does not start in the second row. + #[TWO_LINE_OP_NO_OVERLAP] + (op_mul * ff_tag + op_cast) * alu_sel' = 0; \ No newline at end of file diff --git a/barretenberg/cpp/pil/avm/avm_main.pil b/barretenberg/cpp/pil/avm/avm_main.pil index ecc18fe6d83..f4ce7214edb 100644 --- a/barretenberg/cpp/pil/avm/avm_main.pil +++ b/barretenberg/cpp/pil/avm/avm_main.pil @@ -54,6 +54,8 @@ namespace avm_main(256); pol commit sel_op_or; // XOR pol commit sel_op_xor; + // CAST + pol commit sel_op_cast; // LT pol commit sel_op_lt; // LTE @@ -68,6 +70,7 @@ namespace avm_main(256); // Instruction memory tags read/write (1: u8, 2: u16, 3: u32, 4: u64, 5: u128, 6: field) pol commit r_in_tag; pol commit w_in_tag; + pol commit alu_in_tag; // Copy of r_in_tag or w_in_tag depending of the operation. It is sent to ALU trace. // Errors pol commit op_err; // Boolean flag pertaining to an operation error @@ -121,7 +124,8 @@ namespace avm_main(256); pol commit last; // Relations on type constraints - + // TODO: Very likely, we can remove these constraints as the selectors should be derived during + // opcode decomposition. sel_op_add * (1 - sel_op_add) = 0; sel_op_sub * (1 - sel_op_sub) = 0; sel_op_mul * (1 - sel_op_mul) = 0; @@ -131,6 +135,7 @@ namespace avm_main(256); sel_op_and * (1 - sel_op_and) = 0; sel_op_or * (1 - sel_op_or) = 0; sel_op_xor * (1 - sel_op_xor) = 0; + sel_op_cast * (1 - sel_op_cast) = 0; sel_op_lt * (1 - sel_op_lt) = 0; sel_op_lte * (1 - sel_op_lte) = 0; @@ -243,7 +248,8 @@ namespace avm_main(256); //===== CONTROL_FLOW_CONSISTENCY ============================================ pol INTERNAL_CALL_STACK_SELECTORS = (first + sel_internal_call + sel_internal_return + sel_halt); - pol OPCODE_SELECTORS = (sel_op_add + sel_op_sub + sel_op_div + sel_op_mul + sel_op_not + sel_op_eq + sel_op_and + sel_op_or + sel_op_xor); + pol OPCODE_SELECTORS = (sel_op_add + sel_op_sub + sel_op_div + sel_op_mul + sel_op_not + + sel_op_eq + sel_op_and + sel_op_or + sel_op_xor + sel_op_cast); // Program counter must increment if not jumping or returning #[PC_INCREMENT] @@ -287,6 +293,20 @@ namespace avm_main(256); #[MOV_MAIN_SAME_TAG] (sel_mov + sel_cmov) * (r_in_tag - w_in_tag) = 0; + //===== ALU CONSTRAINTS ===================================================== + // TODO: when division is moved to the alu, we will need to add the selector in the list below. + pol ALU_R_TAG_SEL = sel_op_add + sel_op_sub + sel_op_mul + sel_op_not + sel_op_eq + sel_op_lt + sel_op_lte; + pol ALU_W_TAG_SEL = sel_op_cast; + pol ALU_ALL_SEL = ALU_R_TAG_SEL + ALU_W_TAG_SEL; + + // Predicate to activate the copy of intermediate registers to ALU table. If tag_err == 1, + // the operation is not copied to the ALU table. + alu_sel = ALU_ALL_SEL * (1 - tag_err); + + // Dispatch the correct in_tag for alu + ALU_R_TAG_SEL * (alu_in_tag - r_in_tag) = 0; + ALU_W_TAG_SEL * (alu_in_tag - w_in_tag) = 0; + //====== Inter-table Constraints ============================================ #[INCL_MAIN_TAG_ERR] avm_mem.tag_err {avm_mem.clk} in tag_err {clk}; @@ -294,17 +314,14 @@ namespace avm_main(256); #[INCL_MEM_TAG_ERR] tag_err {clk} in avm_mem.tag_err {avm_mem.clk}; - // Predicate to activate the copy of intermediate registers to ALU table. If tag_err == 1, - // the operation is not copied to the ALU table. - // TODO: when division is moved to the alu, we will need to add the selector in the list below: - alu_sel = (sel_op_add + sel_op_sub + sel_op_mul + sel_op_not + sel_op_eq + sel_op_lt + sel_op_lte) * (1 - tag_err); - #[PERM_MAIN_ALU] alu_sel {clk, ia, ib, ic, sel_op_add, sel_op_sub, - sel_op_mul, sel_op_eq, sel_op_not, sel_op_lt, sel_op_lte, r_in_tag} + sel_op_mul, sel_op_eq, sel_op_not, sel_op_cast, + sel_op_lt, sel_op_lte, alu_in_tag} is avm_alu.alu_sel {avm_alu.clk, avm_alu.ia, avm_alu.ib, avm_alu.ic, avm_alu.op_add, avm_alu.op_sub, - avm_alu.op_mul, avm_alu.op_eq, avm_alu.op_not, avm_alu.op_lt, avm_alu.op_lte, avm_alu.in_tag}; + avm_alu.op_mul, avm_alu.op_eq, avm_alu.op_not, avm_alu.op_cast, + avm_alu.op_lt, avm_alu.op_lte, avm_alu.in_tag}; // Based on the boolean selectors, we derive the binary op id to lookup in the table; // TODO: Check if having 4 columns (op_id + 3 boolean selectors) is more optimal that just using the op_id diff --git a/barretenberg/cpp/src/barretenberg/ecc/fields/field_declarations.hpp b/barretenberg/cpp/src/barretenberg/ecc/fields/field_declarations.hpp index 87a10938677..35805403cde 100644 --- a/barretenberg/cpp/src/barretenberg/ecc/fields/field_declarations.hpp +++ b/barretenberg/cpp/src/barretenberg/ecc/fields/field_declarations.hpp @@ -119,6 +119,18 @@ template struct alignas(32) field { return static_cast(out.data[0]); } + constexpr explicit operator uint8_t() const + { + field out = from_montgomery_form(); + return static_cast(out.data[0]); + } + + constexpr explicit operator uint16_t() const + { + field out = from_montgomery_form(); + return static_cast(out.data[0]); + } + constexpr explicit operator uint32_t() const { field out = from_montgomery_form(); diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/avm_alu.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/avm_alu.hpp index 8682c27d4cf..ac09315024a 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/avm_alu.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/avm_alu.hpp @@ -12,6 +12,7 @@ template struct Avm_aluRow { FF avm_alu_a_lo{}; FF avm_alu_a_lo_shift{}; FF avm_alu_alu_sel{}; + FF avm_alu_alu_sel_shift{}; FF avm_alu_b_hi{}; FF avm_alu_b_hi_shift{}; FF avm_alu_b_lo{}; @@ -29,6 +30,10 @@ template struct Avm_aluRow { FF avm_alu_in_tag{}; FF avm_alu_op_add{}; FF avm_alu_op_add_shift{}; + FF avm_alu_op_cast{}; + FF avm_alu_op_cast_prev{}; + FF avm_alu_op_cast_prev_shift{}; + FF avm_alu_op_cast_shift{}; FF avm_alu_op_eq{}; FF avm_alu_op_eq_diff_inv{}; FF avm_alu_op_lt{}; @@ -172,6 +177,21 @@ inline std::string get_relation_label_avm_alu(int index) case 47: return "SHIFT_RELS_3"; + + case 49: + return "OP_CAST_PREV_LINE"; + + case 50: + return "ALU_OP_CAST"; + + case 51: + return "OP_CAST_RNG_CHECK_P_SUB_A_LOW"; + + case 52: + return "OP_CAST_RNG_CHECK_P_SUB_A_HIGH"; + + case 53: + return "TWO_LINE_OP_NO_OVERLAP"; } return std::to_string(index); } @@ -180,9 +200,9 @@ template class avm_aluImpl { public: using FF = FF_; - static constexpr std::array SUBRELATION_PARTIAL_LENGTHS{ - 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 5, 5, 5, 5, 6, 6, 8, 3, 4, 4, 5, 4, 4, - 3, 4, 3, 3, 4, 3, 6, 5, 3, 3, 3, 3, 4, 3, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, + static constexpr std::array SUBRELATION_PARTIAL_LENGTHS{ + 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 5, 5, 5, 5, 6, 6, 8, 3, 4, 4, 5, 4, 4, 3, 4, + 3, 3, 4, 3, 6, 5, 3, 3, 3, 3, 4, 3, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 2, 5, 3, 3, 4, }; template @@ -197,7 +217,8 @@ template class avm_aluImpl { Avm_DECLARE_VIEWS(0); auto tmp = (avm_alu_alu_sel - - ((((((avm_alu_op_add + avm_alu_op_sub) + avm_alu_op_mul) + avm_alu_op_not) + avm_alu_op_eq) + + (((((((avm_alu_op_add + avm_alu_op_sub) + avm_alu_op_mul) + avm_alu_op_not) + avm_alu_op_eq) + + avm_alu_op_cast) + avm_alu_op_lt) + avm_alu_op_lte)); tmp *= scaling_factor; @@ -478,8 +499,9 @@ template class avm_aluImpl { { Avm_DECLARE_VIEWS(23); - auto tmp = (((avm_alu_op_lt * avm_alu_ib) + (avm_alu_op_lte * avm_alu_ia)) - - ((avm_alu_a_lo + (avm_alu_a_hi * FF(uint256_t{ 0UL, 0UL, 1UL, 0UL }))) * avm_alu_cmp_sel)); + auto tmp = (((avm_alu_op_lt * avm_alu_ib) + ((avm_alu_op_lte + avm_alu_op_cast) * avm_alu_ia)) - + ((avm_alu_a_lo + (avm_alu_a_hi * FF(uint256_t{ 0UL, 0UL, 1UL, 0UL }))) * + (avm_alu_cmp_sel + avm_alu_op_cast))); tmp *= scaling_factor; std::get<23>(evals) += tmp; } @@ -507,7 +529,7 @@ template class avm_aluImpl { auto tmp = ((avm_alu_p_sub_a_lo - ((-avm_alu_a_lo + FF(uint256_t{ 4891460686036598784UL, 2896914383306846353UL, 0UL, 0UL })) + (avm_alu_p_a_borrow * FF(uint256_t{ 0UL, 0UL, 1UL, 0UL })))) * - avm_alu_cmp_sel); + (avm_alu_cmp_sel + avm_alu_op_cast)); tmp *= scaling_factor; std::get<26>(evals) += tmp; } @@ -518,7 +540,7 @@ template class avm_aluImpl { auto tmp = ((avm_alu_p_sub_a_hi - ((-avm_alu_a_hi + FF(uint256_t{ 13281191951274694749UL, 3486998266802970665UL, 0UL, 0UL })) - avm_alu_p_a_borrow)) * - avm_alu_cmp_sel); + (avm_alu_cmp_sel + avm_alu_op_cast)); tmp *= scaling_factor; std::get<27>(evals) += tmp; } @@ -626,10 +648,12 @@ template class avm_aluImpl { Avm_DECLARE_VIEWS(38); auto tmp = (avm_alu_rng_chk_lookup_selector_shift - - (((((avm_alu_cmp_sel_shift + avm_alu_rng_chk_sel_shift) + avm_alu_op_add_shift) + - avm_alu_op_sub_shift) + - avm_alu_op_mul_shift) + - (avm_alu_op_mul * avm_alu_u128_tag))); + (((((((avm_alu_cmp_sel_shift + avm_alu_rng_chk_sel_shift) + avm_alu_op_add_shift) + + avm_alu_op_sub_shift) + + avm_alu_op_mul_shift) + + (avm_alu_op_mul * avm_alu_u128_tag)) + + avm_alu_op_cast_shift) + + avm_alu_op_cast_prev_shift)); tmp *= scaling_factor; std::get<38>(evals) += tmp; } @@ -645,7 +669,7 @@ template class avm_aluImpl { (avm_alu_u16_r4 * FF(uint256_t{ 0UL, 65536UL, 0UL, 0UL }))) + (avm_alu_u16_r5 * FF(uint256_t{ 0UL, 4294967296UL, 0UL, 0UL }))) + (avm_alu_u16_r6 * FF(uint256_t{ 0UL, 281474976710656UL, 0UL, 0UL }))) * - (avm_alu_rng_chk_sel + avm_alu_cmp_sel))); + (((avm_alu_rng_chk_sel + avm_alu_cmp_sel) + avm_alu_op_cast) + avm_alu_op_cast_prev))); tmp *= scaling_factor; std::get<39>(evals) += tmp; } @@ -660,7 +684,7 @@ template class avm_aluImpl { (avm_alu_u16_r12 * FF(uint256_t{ 0UL, 65536UL, 0UL, 0UL }))) + (avm_alu_u16_r13 * FF(uint256_t{ 0UL, 4294967296UL, 0UL, 0UL }))) + (avm_alu_u16_r14 * FF(uint256_t{ 0UL, 281474976710656UL, 0UL, 0UL }))) * - (avm_alu_rng_chk_sel + avm_alu_cmp_sel))); + (((avm_alu_rng_chk_sel + avm_alu_cmp_sel) + avm_alu_op_cast) + avm_alu_op_cast_prev))); tmp *= scaling_factor; std::get<40>(evals) += tmp; } @@ -728,6 +752,64 @@ template class avm_aluImpl { tmp *= scaling_factor; std::get<48>(evals) += tmp; } + // Contribution 49 + { + Avm_DECLARE_VIEWS(49); + + auto tmp = (avm_alu_op_cast_prev_shift - avm_alu_op_cast); + tmp *= scaling_factor; + std::get<49>(evals) += tmp; + } + // Contribution 50 + { + Avm_DECLARE_VIEWS(50); + + auto tmp = + (avm_alu_op_cast * + (((((((avm_alu_u8_tag * avm_alu_u8_r0) + + (avm_alu_u16_tag * (avm_alu_u8_r0 + (avm_alu_u8_r1 * FF(256))))) + + (avm_alu_u32_tag * + ((avm_alu_u8_r0 + (avm_alu_u8_r1 * FF(256))) + (avm_alu_u16_r0 * FF(65536))))) + + (avm_alu_u64_tag * ((((avm_alu_u8_r0 + (avm_alu_u8_r1 * FF(256))) + (avm_alu_u16_r0 * FF(65536))) + + (avm_alu_u16_r1 * FF(4294967296UL))) + + (avm_alu_u16_r2 * FF(281474976710656UL))))) + + (avm_alu_u128_tag * + ((((((((avm_alu_u8_r0 + (avm_alu_u8_r1 * FF(256))) + (avm_alu_u16_r0 * FF(65536))) + + (avm_alu_u16_r1 * FF(4294967296UL))) + + (avm_alu_u16_r2 * FF(281474976710656UL))) + + (avm_alu_u16_r3 * FF(uint256_t{ 0UL, 1UL, 0UL, 0UL }))) + + (avm_alu_u16_r4 * FF(uint256_t{ 0UL, 65536UL, 0UL, 0UL }))) + + (avm_alu_u16_r5 * FF(uint256_t{ 0UL, 4294967296UL, 0UL, 0UL }))) + + (avm_alu_u16_r6 * FF(uint256_t{ 0UL, 281474976710656UL, 0UL, 0UL }))))) + + (avm_alu_ff_tag * avm_alu_ia)) - + avm_alu_ic)); + tmp *= scaling_factor; + std::get<50>(evals) += tmp; + } + // Contribution 51 + { + Avm_DECLARE_VIEWS(51); + + auto tmp = (avm_alu_op_cast * (avm_alu_a_lo_shift - avm_alu_p_sub_a_lo)); + tmp *= scaling_factor; + std::get<51>(evals) += tmp; + } + // Contribution 52 + { + Avm_DECLARE_VIEWS(52); + + auto tmp = (avm_alu_op_cast * (avm_alu_a_hi_shift - avm_alu_p_sub_a_hi)); + tmp *= scaling_factor; + std::get<52>(evals) += tmp; + } + // Contribution 53 + { + Avm_DECLARE_VIEWS(53); + + auto tmp = (((avm_alu_op_mul * avm_alu_ff_tag) + avm_alu_op_cast) * avm_alu_alu_sel_shift); + tmp *= scaling_factor; + std::get<53>(evals) += tmp; + } } }; diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/avm_main.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/avm_main.hpp index 74e611ac699..b9c4dfd14df 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/avm_main.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/avm_main.hpp @@ -7,6 +7,7 @@ namespace bb::Avm_vm { template struct Avm_mainRow { + FF avm_main_alu_in_tag{}; FF avm_main_alu_sel{}; FF avm_main_bin_op_id{}; FF avm_main_bin_sel{}; @@ -47,6 +48,7 @@ template struct Avm_mainRow { FF avm_main_sel_mov_b{}; FF avm_main_sel_op_add{}; FF avm_main_sel_op_and{}; + FF avm_main_sel_op_cast{}; FF avm_main_sel_op_div{}; FF avm_main_sel_op_eq{}; FF avm_main_sel_op_lt{}; @@ -63,52 +65,52 @@ template struct Avm_mainRow { inline std::string get_relation_label_avm_main(int index) { switch (index) { - case 32: + case 33: return "OUTPUT_U8"; - case 33: + case 34: return "SUBOP_DIVISION_FF"; - case 34: + case 35: return "SUBOP_DIVISION_ZERO_ERR1"; - case 35: + case 36: return "SUBOP_DIVISION_ZERO_ERR2"; - case 36: + case 37: return "SUBOP_ERROR_RELEVANT_OP"; - case 38: + case 39: return "RETURN_POINTER_INCREMENT"; - case 44: + case 45: return "RETURN_POINTER_DECREMENT"; - case 49: + case 50: return "PC_INCREMENT"; - case 50: + case 51: return "INTERNAL_RETURN_POINTER_CONSISTENCY"; - case 51: + case 52: return "CMOV_CONDITION_RES_1"; - case 52: + case 53: return "CMOV_CONDITION_RES_2"; - case 55: + case 56: return "MOV_SAME_VALUE_A"; - case 56: + case 57: return "MOV_SAME_VALUE_B"; - case 57: + case 58: return "MOV_MAIN_SAME_TAG"; - case 59: + case 62: return "BIN_SEL_1"; - case 60: + case 63: return "BIN_SEL_2"; } return std::to_string(index); @@ -118,9 +120,9 @@ template class avm_mainImpl { public: using FF = FF_; - static constexpr std::array SUBRELATION_PARTIAL_LENGTHS{ - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 5, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 3, 4, 4, 3, 3, 3, 3, 3, 3, 3, 2, + static constexpr std::array SUBRELATION_PARTIAL_LENGTHS{ + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 5, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 3, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, }; template @@ -206,7 +208,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(9); - auto tmp = (avm_main_sel_op_lt * (-avm_main_sel_op_lt + FF(1))); + auto tmp = (avm_main_sel_op_cast * (-avm_main_sel_op_cast + FF(1))); tmp *= scaling_factor; std::get<9>(evals) += tmp; } @@ -214,7 +216,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(10); - auto tmp = (avm_main_sel_op_lte * (-avm_main_sel_op_lte + FF(1))); + auto tmp = (avm_main_sel_op_lt * (-avm_main_sel_op_lt + FF(1))); tmp *= scaling_factor; std::get<10>(evals) += tmp; } @@ -222,7 +224,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(11); - auto tmp = (avm_main_sel_internal_call * (-avm_main_sel_internal_call + FF(1))); + auto tmp = (avm_main_sel_op_lte * (-avm_main_sel_op_lte + FF(1))); tmp *= scaling_factor; std::get<11>(evals) += tmp; } @@ -230,7 +232,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(12); - auto tmp = (avm_main_sel_internal_return * (-avm_main_sel_internal_return + FF(1))); + auto tmp = (avm_main_sel_internal_call * (-avm_main_sel_internal_call + FF(1))); tmp *= scaling_factor; std::get<12>(evals) += tmp; } @@ -238,7 +240,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(13); - auto tmp = (avm_main_sel_jump * (-avm_main_sel_jump + FF(1))); + auto tmp = (avm_main_sel_internal_return * (-avm_main_sel_internal_return + FF(1))); tmp *= scaling_factor; std::get<13>(evals) += tmp; } @@ -246,7 +248,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(14); - auto tmp = (avm_main_sel_halt * (-avm_main_sel_halt + FF(1))); + auto tmp = (avm_main_sel_jump * (-avm_main_sel_jump + FF(1))); tmp *= scaling_factor; std::get<14>(evals) += tmp; } @@ -254,7 +256,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(15); - auto tmp = (avm_main_sel_mov * (-avm_main_sel_mov + FF(1))); + auto tmp = (avm_main_sel_halt * (-avm_main_sel_halt + FF(1))); tmp *= scaling_factor; std::get<15>(evals) += tmp; } @@ -262,7 +264,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(16); - auto tmp = (avm_main_sel_cmov * (-avm_main_sel_cmov + FF(1))); + auto tmp = (avm_main_sel_mov * (-avm_main_sel_mov + FF(1))); tmp *= scaling_factor; std::get<16>(evals) += tmp; } @@ -270,7 +272,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(17); - auto tmp = (avm_main_op_err * (-avm_main_op_err + FF(1))); + auto tmp = (avm_main_sel_cmov * (-avm_main_sel_cmov + FF(1))); tmp *= scaling_factor; std::get<17>(evals) += tmp; } @@ -278,7 +280,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(18); - auto tmp = (avm_main_tag_err * (-avm_main_tag_err + FF(1))); + auto tmp = (avm_main_op_err * (-avm_main_op_err + FF(1))); tmp *= scaling_factor; std::get<18>(evals) += tmp; } @@ -286,7 +288,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(19); - auto tmp = (avm_main_id_zero * (-avm_main_id_zero + FF(1))); + auto tmp = (avm_main_tag_err * (-avm_main_tag_err + FF(1))); tmp *= scaling_factor; std::get<19>(evals) += tmp; } @@ -294,7 +296,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(20); - auto tmp = (avm_main_mem_op_a * (-avm_main_mem_op_a + FF(1))); + auto tmp = (avm_main_id_zero * (-avm_main_id_zero + FF(1))); tmp *= scaling_factor; std::get<20>(evals) += tmp; } @@ -302,7 +304,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(21); - auto tmp = (avm_main_mem_op_b * (-avm_main_mem_op_b + FF(1))); + auto tmp = (avm_main_mem_op_a * (-avm_main_mem_op_a + FF(1))); tmp *= scaling_factor; std::get<21>(evals) += tmp; } @@ -310,7 +312,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(22); - auto tmp = (avm_main_mem_op_c * (-avm_main_mem_op_c + FF(1))); + auto tmp = (avm_main_mem_op_b * (-avm_main_mem_op_b + FF(1))); tmp *= scaling_factor; std::get<22>(evals) += tmp; } @@ -318,7 +320,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(23); - auto tmp = (avm_main_mem_op_d * (-avm_main_mem_op_d + FF(1))); + auto tmp = (avm_main_mem_op_c * (-avm_main_mem_op_c + FF(1))); tmp *= scaling_factor; std::get<23>(evals) += tmp; } @@ -326,7 +328,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(24); - auto tmp = (avm_main_rwa * (-avm_main_rwa + FF(1))); + auto tmp = (avm_main_mem_op_d * (-avm_main_mem_op_d + FF(1))); tmp *= scaling_factor; std::get<24>(evals) += tmp; } @@ -334,7 +336,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(25); - auto tmp = (avm_main_rwb * (-avm_main_rwb + FF(1))); + auto tmp = (avm_main_rwa * (-avm_main_rwa + FF(1))); tmp *= scaling_factor; std::get<25>(evals) += tmp; } @@ -342,7 +344,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(26); - auto tmp = (avm_main_rwc * (-avm_main_rwc + FF(1))); + auto tmp = (avm_main_rwb * (-avm_main_rwb + FF(1))); tmp *= scaling_factor; std::get<26>(evals) += tmp; } @@ -350,7 +352,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(27); - auto tmp = (avm_main_rwd * (-avm_main_rwd + FF(1))); + auto tmp = (avm_main_rwc * (-avm_main_rwc + FF(1))); tmp *= scaling_factor; std::get<27>(evals) += tmp; } @@ -358,7 +360,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(28); - auto tmp = (avm_main_ind_op_a * (-avm_main_ind_op_a + FF(1))); + auto tmp = (avm_main_rwd * (-avm_main_rwd + FF(1))); tmp *= scaling_factor; std::get<28>(evals) += tmp; } @@ -366,7 +368,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(29); - auto tmp = (avm_main_ind_op_b * (-avm_main_ind_op_b + FF(1))); + auto tmp = (avm_main_ind_op_a * (-avm_main_ind_op_a + FF(1))); tmp *= scaling_factor; std::get<29>(evals) += tmp; } @@ -374,7 +376,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(30); - auto tmp = (avm_main_ind_op_c * (-avm_main_ind_op_c + FF(1))); + auto tmp = (avm_main_ind_op_b * (-avm_main_ind_op_b + FF(1))); tmp *= scaling_factor; std::get<30>(evals) += tmp; } @@ -382,7 +384,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(31); - auto tmp = (avm_main_ind_op_d * (-avm_main_ind_op_d + FF(1))); + auto tmp = (avm_main_ind_op_c * (-avm_main_ind_op_c + FF(1))); tmp *= scaling_factor; std::get<31>(evals) += tmp; } @@ -390,8 +392,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(32); - auto tmp = - (((avm_main_sel_op_eq + avm_main_sel_op_lte) + avm_main_sel_op_lt) * (avm_main_w_in_tag - FF(1))); + auto tmp = (avm_main_ind_op_d * (-avm_main_ind_op_d + FF(1))); tmp *= scaling_factor; std::get<32>(evals) += tmp; } @@ -400,7 +401,7 @@ template class avm_mainImpl { Avm_DECLARE_VIEWS(33); auto tmp = - ((avm_main_sel_op_div * (-avm_main_op_err + FF(1))) * ((avm_main_ic * avm_main_ib) - avm_main_ia)); + (((avm_main_sel_op_eq + avm_main_sel_op_lte) + avm_main_sel_op_lt) * (avm_main_w_in_tag - FF(1))); tmp *= scaling_factor; std::get<33>(evals) += tmp; } @@ -408,7 +409,8 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(34); - auto tmp = (avm_main_sel_op_div * (((avm_main_ib * avm_main_inv) - FF(1)) + avm_main_op_err)); + auto tmp = + ((avm_main_sel_op_div * (-avm_main_op_err + FF(1))) * ((avm_main_ic * avm_main_ib) - avm_main_ia)); tmp *= scaling_factor; std::get<34>(evals) += tmp; } @@ -416,7 +418,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(35); - auto tmp = ((avm_main_sel_op_div * avm_main_op_err) * (-avm_main_inv + FF(1))); + auto tmp = (avm_main_sel_op_div * (((avm_main_ib * avm_main_inv) - FF(1)) + avm_main_op_err)); tmp *= scaling_factor; std::get<35>(evals) += tmp; } @@ -424,7 +426,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(36); - auto tmp = (avm_main_op_err * (avm_main_sel_op_div - FF(1))); + auto tmp = ((avm_main_sel_op_div * avm_main_op_err) * (-avm_main_inv + FF(1))); tmp *= scaling_factor; std::get<36>(evals) += tmp; } @@ -432,7 +434,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(37); - auto tmp = (avm_main_sel_jump * (avm_main_pc_shift - avm_main_ia)); + auto tmp = (avm_main_op_err * (avm_main_sel_op_div - FF(1))); tmp *= scaling_factor; std::get<37>(evals) += tmp; } @@ -440,8 +442,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(38); - auto tmp = (avm_main_sel_internal_call * - (avm_main_internal_return_ptr_shift - (avm_main_internal_return_ptr + FF(1)))); + auto tmp = (avm_main_sel_jump * (avm_main_pc_shift - avm_main_ia)); tmp *= scaling_factor; std::get<38>(evals) += tmp; } @@ -449,7 +450,8 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(39); - auto tmp = (avm_main_sel_internal_call * (avm_main_internal_return_ptr - avm_main_mem_idx_b)); + auto tmp = (avm_main_sel_internal_call * + (avm_main_internal_return_ptr_shift - (avm_main_internal_return_ptr + FF(1)))); tmp *= scaling_factor; std::get<39>(evals) += tmp; } @@ -457,7 +459,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(40); - auto tmp = (avm_main_sel_internal_call * (avm_main_pc_shift - avm_main_ia)); + auto tmp = (avm_main_sel_internal_call * (avm_main_internal_return_ptr - avm_main_mem_idx_b)); tmp *= scaling_factor; std::get<40>(evals) += tmp; } @@ -465,7 +467,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(41); - auto tmp = (avm_main_sel_internal_call * ((avm_main_pc + FF(1)) - avm_main_ib)); + auto tmp = (avm_main_sel_internal_call * (avm_main_pc_shift - avm_main_ia)); tmp *= scaling_factor; std::get<41>(evals) += tmp; } @@ -473,7 +475,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(42); - auto tmp = (avm_main_sel_internal_call * (avm_main_rwb - FF(1))); + auto tmp = (avm_main_sel_internal_call * ((avm_main_pc + FF(1)) - avm_main_ib)); tmp *= scaling_factor; std::get<42>(evals) += tmp; } @@ -481,7 +483,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(43); - auto tmp = (avm_main_sel_internal_call * (avm_main_mem_op_b - FF(1))); + auto tmp = (avm_main_sel_internal_call * (avm_main_rwb - FF(1))); tmp *= scaling_factor; std::get<43>(evals) += tmp; } @@ -489,8 +491,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(44); - auto tmp = (avm_main_sel_internal_return * - (avm_main_internal_return_ptr_shift - (avm_main_internal_return_ptr - FF(1)))); + auto tmp = (avm_main_sel_internal_call * (avm_main_mem_op_b - FF(1))); tmp *= scaling_factor; std::get<44>(evals) += tmp; } @@ -498,7 +499,8 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(45); - auto tmp = (avm_main_sel_internal_return * ((avm_main_internal_return_ptr - FF(1)) - avm_main_mem_idx_a)); + auto tmp = (avm_main_sel_internal_return * + (avm_main_internal_return_ptr_shift - (avm_main_internal_return_ptr - FF(1)))); tmp *= scaling_factor; std::get<45>(evals) += tmp; } @@ -506,7 +508,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(46); - auto tmp = (avm_main_sel_internal_return * (avm_main_pc_shift - avm_main_ia)); + auto tmp = (avm_main_sel_internal_return * ((avm_main_internal_return_ptr - FF(1)) - avm_main_mem_idx_a)); tmp *= scaling_factor; std::get<46>(evals) += tmp; } @@ -514,7 +516,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(47); - auto tmp = (avm_main_sel_internal_return * avm_main_rwa); + auto tmp = (avm_main_sel_internal_return * (avm_main_pc_shift - avm_main_ia)); tmp *= scaling_factor; std::get<47>(evals) += tmp; } @@ -522,7 +524,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(48); - auto tmp = (avm_main_sel_internal_return * (avm_main_mem_op_a - FF(1))); + auto tmp = (avm_main_sel_internal_return * avm_main_rwa); tmp *= scaling_factor; std::get<48>(evals) += tmp; } @@ -530,15 +532,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(49); - auto tmp = - ((((-avm_main_first + FF(1)) * (-avm_main_sel_halt + FF(1))) * - ((((((((avm_main_sel_op_add + avm_main_sel_op_sub) + avm_main_sel_op_div) + avm_main_sel_op_mul) + - avm_main_sel_op_not) + - avm_main_sel_op_eq) + - avm_main_sel_op_and) + - avm_main_sel_op_or) + - avm_main_sel_op_xor)) * - (avm_main_pc_shift - (avm_main_pc + FF(1)))); + auto tmp = (avm_main_sel_internal_return * (avm_main_mem_op_a - FF(1))); tmp *= scaling_factor; std::get<49>(evals) += tmp; } @@ -546,10 +540,16 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(50); - auto tmp = ((-(((avm_main_first + avm_main_sel_internal_call) + avm_main_sel_internal_return) + - avm_main_sel_halt) + - FF(1)) * - (avm_main_internal_return_ptr_shift - avm_main_internal_return_ptr)); + auto tmp = + ((((-avm_main_first + FF(1)) * (-avm_main_sel_halt + FF(1))) * + (((((((((avm_main_sel_op_add + avm_main_sel_op_sub) + avm_main_sel_op_div) + avm_main_sel_op_mul) + + avm_main_sel_op_not) + + avm_main_sel_op_eq) + + avm_main_sel_op_and) + + avm_main_sel_op_or) + + avm_main_sel_op_xor) + + avm_main_sel_op_cast)) * + (avm_main_pc_shift - (avm_main_pc + FF(1)))); tmp *= scaling_factor; std::get<50>(evals) += tmp; } @@ -557,7 +557,10 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(51); - auto tmp = (avm_main_sel_cmov * (((avm_main_id * avm_main_inv) - FF(1)) + avm_main_id_zero)); + auto tmp = ((-(((avm_main_first + avm_main_sel_internal_call) + avm_main_sel_internal_return) + + avm_main_sel_halt) + + FF(1)) * + (avm_main_internal_return_ptr_shift - avm_main_internal_return_ptr)); tmp *= scaling_factor; std::get<51>(evals) += tmp; } @@ -565,7 +568,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(52); - auto tmp = ((avm_main_sel_cmov * avm_main_id_zero) * (-avm_main_inv + FF(1))); + auto tmp = (avm_main_sel_cmov * (((avm_main_id * avm_main_inv) - FF(1)) + avm_main_id_zero)); tmp *= scaling_factor; std::get<52>(evals) += tmp; } @@ -573,7 +576,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(53); - auto tmp = (avm_main_sel_mov_a - (avm_main_sel_mov + (avm_main_sel_cmov * (-avm_main_id_zero + FF(1))))); + auto tmp = ((avm_main_sel_cmov * avm_main_id_zero) * (-avm_main_inv + FF(1))); tmp *= scaling_factor; std::get<53>(evals) += tmp; } @@ -581,7 +584,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(54); - auto tmp = (avm_main_sel_mov_b - (avm_main_sel_cmov * avm_main_id_zero)); + auto tmp = (avm_main_sel_mov_a - (avm_main_sel_mov + (avm_main_sel_cmov * (-avm_main_id_zero + FF(1))))); tmp *= scaling_factor; std::get<54>(evals) += tmp; } @@ -589,7 +592,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(55); - auto tmp = (avm_main_sel_mov_a * (avm_main_ia - avm_main_ic)); + auto tmp = (avm_main_sel_mov_b - (avm_main_sel_cmov * avm_main_id_zero)); tmp *= scaling_factor; std::get<55>(evals) += tmp; } @@ -597,7 +600,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(56); - auto tmp = (avm_main_sel_mov_b * (avm_main_ib - avm_main_ic)); + auto tmp = (avm_main_sel_mov_a * (avm_main_ia - avm_main_ic)); tmp *= scaling_factor; std::get<56>(evals) += tmp; } @@ -605,7 +608,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(57); - auto tmp = ((avm_main_sel_mov + avm_main_sel_cmov) * (avm_main_r_in_tag - avm_main_w_in_tag)); + auto tmp = (avm_main_sel_mov_b * (avm_main_ib - avm_main_ic)); tmp *= scaling_factor; std::get<57>(evals) += tmp; } @@ -613,13 +616,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(58); - auto tmp = - (avm_main_alu_sel - - (((((((avm_main_sel_op_add + avm_main_sel_op_sub) + avm_main_sel_op_mul) + avm_main_sel_op_not) + - avm_main_sel_op_eq) + - avm_main_sel_op_lt) + - avm_main_sel_op_lte) * - (-avm_main_tag_err + FF(1)))); + auto tmp = ((avm_main_sel_mov + avm_main_sel_cmov) * (avm_main_r_in_tag - avm_main_w_in_tag)); tmp *= scaling_factor; std::get<58>(evals) += tmp; } @@ -627,7 +624,14 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(59); - auto tmp = (avm_main_bin_op_id - (avm_main_sel_op_or + (avm_main_sel_op_xor * FF(2)))); + auto tmp = + (avm_main_alu_sel - + ((((((((avm_main_sel_op_add + avm_main_sel_op_sub) + avm_main_sel_op_mul) + avm_main_sel_op_not) + + avm_main_sel_op_eq) + + avm_main_sel_op_lt) + + avm_main_sel_op_lte) + + avm_main_sel_op_cast) * + (-avm_main_tag_err + FF(1)))); tmp *= scaling_factor; std::get<59>(evals) += tmp; } @@ -635,10 +639,38 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(60); - auto tmp = (avm_main_bin_sel - ((avm_main_sel_op_and + avm_main_sel_op_or) + avm_main_sel_op_xor)); + auto tmp = (((((((avm_main_sel_op_add + avm_main_sel_op_sub) + avm_main_sel_op_mul) + avm_main_sel_op_not) + + avm_main_sel_op_eq) + + avm_main_sel_op_lt) + + avm_main_sel_op_lte) * + (avm_main_alu_in_tag - avm_main_r_in_tag)); tmp *= scaling_factor; std::get<60>(evals) += tmp; } + // Contribution 61 + { + Avm_DECLARE_VIEWS(61); + + auto tmp = (avm_main_sel_op_cast * (avm_main_alu_in_tag - avm_main_w_in_tag)); + tmp *= scaling_factor; + std::get<61>(evals) += tmp; + } + // Contribution 62 + { + Avm_DECLARE_VIEWS(62); + + auto tmp = (avm_main_bin_op_id - (avm_main_sel_op_or + (avm_main_sel_op_xor * FF(2)))); + tmp *= scaling_factor; + std::get<62>(evals) += tmp; + } + // Contribution 63 + { + Avm_DECLARE_VIEWS(63); + + auto tmp = (avm_main_bin_sel - ((avm_main_sel_op_and + avm_main_sel_op_or) + avm_main_sel_op_xor)); + tmp *= scaling_factor; + std::get<63>(evals) += tmp; + } } }; diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/declare_views.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/declare_views.hpp index 05c47520ab4..e427a1bf7be 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/declare_views.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/declare_views.hpp @@ -20,6 +20,8 @@ [[maybe_unused]] auto avm_alu_ic = View(new_term.avm_alu_ic); \ [[maybe_unused]] auto avm_alu_in_tag = View(new_term.avm_alu_in_tag); \ [[maybe_unused]] auto avm_alu_op_add = View(new_term.avm_alu_op_add); \ + [[maybe_unused]] auto avm_alu_op_cast = View(new_term.avm_alu_op_cast); \ + [[maybe_unused]] auto avm_alu_op_cast_prev = View(new_term.avm_alu_op_cast_prev); \ [[maybe_unused]] auto avm_alu_op_div = View(new_term.avm_alu_op_div); \ [[maybe_unused]] auto avm_alu_op_eq = View(new_term.avm_alu_op_eq); \ [[maybe_unused]] auto avm_alu_op_eq_diff_inv = View(new_term.avm_alu_op_eq_diff_inv); \ @@ -80,6 +82,7 @@ [[maybe_unused]] auto avm_byte_lookup_table_input_b = View(new_term.avm_byte_lookup_table_input_b); \ [[maybe_unused]] auto avm_byte_lookup_table_op_id = View(new_term.avm_byte_lookup_table_op_id); \ [[maybe_unused]] auto avm_byte_lookup_table_output = View(new_term.avm_byte_lookup_table_output); \ + [[maybe_unused]] auto avm_main_alu_in_tag = View(new_term.avm_main_alu_in_tag); \ [[maybe_unused]] auto avm_main_alu_sel = View(new_term.avm_main_alu_sel); \ [[maybe_unused]] auto avm_main_bin_op_id = View(new_term.avm_main_bin_op_id); \ [[maybe_unused]] auto avm_main_bin_sel = View(new_term.avm_main_bin_sel); \ @@ -124,6 +127,7 @@ [[maybe_unused]] auto avm_main_sel_mov_b = View(new_term.avm_main_sel_mov_b); \ [[maybe_unused]] auto avm_main_sel_op_add = View(new_term.avm_main_sel_op_add); \ [[maybe_unused]] auto avm_main_sel_op_and = View(new_term.avm_main_sel_op_and); \ + [[maybe_unused]] auto avm_main_sel_op_cast = View(new_term.avm_main_sel_op_cast); \ [[maybe_unused]] auto avm_main_sel_op_div = View(new_term.avm_main_sel_op_div); \ [[maybe_unused]] auto avm_main_sel_op_eq = View(new_term.avm_main_sel_op_eq); \ [[maybe_unused]] auto avm_main_sel_op_lt = View(new_term.avm_main_sel_op_lt); \ @@ -215,11 +219,14 @@ [[maybe_unused]] auto lookup_u16_14_counts = View(new_term.lookup_u16_14_counts); \ [[maybe_unused]] auto avm_alu_a_hi_shift = View(new_term.avm_alu_a_hi_shift); \ [[maybe_unused]] auto avm_alu_a_lo_shift = View(new_term.avm_alu_a_lo_shift); \ + [[maybe_unused]] auto avm_alu_alu_sel_shift = View(new_term.avm_alu_alu_sel_shift); \ [[maybe_unused]] auto avm_alu_b_hi_shift = View(new_term.avm_alu_b_hi_shift); \ [[maybe_unused]] auto avm_alu_b_lo_shift = View(new_term.avm_alu_b_lo_shift); \ [[maybe_unused]] auto avm_alu_cmp_rng_ctr_shift = View(new_term.avm_alu_cmp_rng_ctr_shift); \ [[maybe_unused]] auto avm_alu_cmp_sel_shift = View(new_term.avm_alu_cmp_sel_shift); \ [[maybe_unused]] auto avm_alu_op_add_shift = View(new_term.avm_alu_op_add_shift); \ + [[maybe_unused]] auto avm_alu_op_cast_prev_shift = View(new_term.avm_alu_op_cast_prev_shift); \ + [[maybe_unused]] auto avm_alu_op_cast_shift = View(new_term.avm_alu_op_cast_shift); \ [[maybe_unused]] auto avm_alu_op_mul_shift = View(new_term.avm_alu_op_mul_shift); \ [[maybe_unused]] auto avm_alu_op_sub_shift = View(new_term.avm_alu_op_sub_shift); \ [[maybe_unused]] auto avm_alu_p_sub_a_hi_shift = View(new_term.avm_alu_p_sub_a_hi_shift); \ diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_alu.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_alu.hpp index 0a45bb920d5..d79a11acf7c 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_alu.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_alu.hpp @@ -12,7 +12,7 @@ namespace bb { class perm_main_alu_permutation_settings { public: // This constant defines how many columns are bundled together to form each set. - constexpr static size_t COLUMNS_PER_SET = 12; + constexpr static size_t COLUMNS_PER_SET = 13; /** * @brief If this method returns true on a row of values, then the inverse polynomial at this index. Otherwise the @@ -59,9 +59,10 @@ class perm_main_alu_permutation_settings { in.avm_main_sel_op_mul, in.avm_main_sel_op_eq, in.avm_main_sel_op_not, + in.avm_main_sel_op_cast, in.avm_main_sel_op_lt, in.avm_main_sel_op_lte, - in.avm_main_r_in_tag, + in.avm_main_alu_in_tag, in.avm_alu_clk, in.avm_alu_ia, in.avm_alu_ib, @@ -71,6 +72,7 @@ class perm_main_alu_permutation_settings { in.avm_alu_op_mul, in.avm_alu_op_eq, in.avm_alu_op_not, + in.avm_alu_op_cast, in.avm_alu_op_lt, in.avm_alu_op_lte, in.avm_alu_in_tag); @@ -109,9 +111,10 @@ class perm_main_alu_permutation_settings { in.avm_main_sel_op_mul, in.avm_main_sel_op_eq, in.avm_main_sel_op_not, + in.avm_main_sel_op_cast, in.avm_main_sel_op_lt, in.avm_main_sel_op_lte, - in.avm_main_r_in_tag, + in.avm_main_alu_in_tag, in.avm_alu_clk, in.avm_alu_ia, in.avm_alu_ib, @@ -121,6 +124,7 @@ class perm_main_alu_permutation_settings { in.avm_alu_op_mul, in.avm_alu_op_eq, in.avm_alu_op_not, + in.avm_alu_op_cast, in.avm_alu_op_lt, in.avm_alu_op_lte, in.avm_alu_in_tag); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_alu_trace.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_alu_trace.cpp index f92dcb2668d..9935a74b840 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_alu_trace.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_alu_trace.cpp @@ -1,12 +1,4 @@ #include "avm_alu_trace.hpp" -#include "barretenberg/common/serialize.hpp" -#include "barretenberg/numeric/uint128/uint128.hpp" -#include "barretenberg/numeric/uint256/uint256.hpp" -#include "barretenberg/relations/generated/avm/avm_alu.hpp" -#include -#include -#include -#include namespace bb::avm_trace { @@ -608,7 +600,7 @@ FF AvmAluTraceBuilder::op_lt(FF const& a, FF const& b, AvmMemoryTag in_tag, uint std::vector rows = cmp_range_check_helper(row, hi_lo_limbs); // Append the rows to the alu_trace alu_trace.insert(alu_trace.end(), rows.begin(), rows.end()); - return { static_cast(c) }; + return FF{ static_cast(c) }; } /** @@ -662,6 +654,81 @@ FF AvmAluTraceBuilder::op_lte(FF const& a, FF const& b, AvmMemoryTag in_tag, uin // Update the row and add new rows with the correct hi_lo limbs std::vector rows = cmp_range_check_helper(row, hi_lo_limbs); alu_trace.insert(alu_trace.end(), rows.begin(), rows.end()); - return { static_cast(c) }; + return FF{ static_cast(c) }; } + +/** + * @brief Build ALU trace for the CAST opcode. + * + * @param a Input value to be casted. Tag of the input is not taken into account. + * @param in_tag Tag specifying the type for the input to be casted into. + * @param clk Clock referring to the operation in the main trace. + * @return The casted value as a finite field element. + */ +FF AvmAluTraceBuilder::op_cast(FF const& a, AvmMemoryTag in_tag, uint32_t clk) +{ + FF c; + + switch (in_tag) { + case AvmMemoryTag::U8: + c = FF(uint8_t(a)); + break; + case AvmMemoryTag::U16: + c = FF(uint16_t(a)); + break; + case AvmMemoryTag::U32: + c = FF(uint32_t(a)); + break; + case AvmMemoryTag::U64: + c = FF(uint64_t(a)); + break; + case AvmMemoryTag::U128: + c = FF(uint256_t::from_uint128(uint128_t(a))); + break; + case AvmMemoryTag::FF: + c = a; + break; + default: + c = 0; + break; + } + + // Get the decomposition of a + auto [a_lo, a_hi] = decompose(uint256_t(a)); + // Decomposition of p-a + auto [p_sub_a_lo, p_sub_a_hi, p_a_borrow] = gt_witness(FF::modulus, uint256_t(a)); + auto [u8_r0, u8_r1, u16_reg] = to_alu_slice_registers(uint256_t(a)); + + alu_trace.push_back(AvmAluTraceBuilder::AluTraceEntry{ + .alu_clk = clk, + .alu_op_cast = true, + .alu_ff_tag = in_tag == AvmMemoryTag::FF, + .alu_u8_tag = in_tag == AvmMemoryTag::U8, + .alu_u16_tag = in_tag == AvmMemoryTag::U16, + .alu_u32_tag = in_tag == AvmMemoryTag::U32, + .alu_u64_tag = in_tag == AvmMemoryTag::U64, + .alu_u128_tag = in_tag == AvmMemoryTag::U128, + .alu_ia = a, + .alu_ic = c, + .alu_u8_r0 = u8_r0, + .alu_u8_r1 = u8_r1, + .alu_u16_reg = u16_reg, + .hi_lo_limbs = { a_lo, a_hi, p_sub_a_lo, p_sub_a_hi }, + .p_a_borrow = p_a_borrow, + }); + + uint256_t sub = (p_sub_a_hi << 128) + p_sub_a_lo; + auto [sub_u8_r0, sub_u8_r1, sub_u16_reg] = to_alu_slice_registers(sub); + + alu_trace.push_back(AvmAluTraceBuilder::AluTraceEntry{ + .alu_op_cast_prev = true, + .alu_u8_r0 = sub_u8_r0, + .alu_u8_r1 = sub_u8_r1, + .alu_u16_reg = sub_u16_reg, + .hi_lo_limbs = { p_sub_a_lo, p_sub_a_hi }, + }); + + return c; +} + } // namespace bb::avm_trace diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_alu_trace.hpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_alu_trace.hpp index cb12ab925ed..7920aabd28e 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_alu_trace.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_alu_trace.hpp @@ -1,10 +1,6 @@ #pragma once #include "avm_common.hpp" -#include "barretenberg/numeric/uint128/uint128.hpp" -#include "barretenberg/numeric/uint256/uint256.hpp" -#include -#include namespace bb::avm_trace { @@ -21,6 +17,8 @@ class AvmAluTraceBuilder { bool alu_op_eq = false; bool alu_op_lt = false; bool alu_op_lte = false; + bool alu_op_cast = false; + bool alu_op_cast_prev = false; bool alu_ff_tag = false; bool alu_u8_tag = false; @@ -66,6 +64,7 @@ class AvmAluTraceBuilder { FF op_eq(FF const& a, FF const& b, AvmMemoryTag in_tag, uint32_t clk); FF op_lt(FF const& a, FF const& b, AvmMemoryTag in_tag, uint32_t clk); FF op_lte(FF const& a, FF const& b, AvmMemoryTag in_tag, uint32_t clk); + FF op_cast(FF const& a, AvmMemoryTag in_tag, uint32_t clk); bool is_range_check_required() const; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_common.hpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_common.hpp index a0261419281..e3c4e90d01b 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_common.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_common.hpp @@ -1,6 +1,5 @@ #pragma once -#include "barretenberg/relations/generated/avm/avm_binary.hpp" #include "barretenberg/stdlib_circuit_builders/circuit_builder_base.hpp" #include "barretenberg/vm/generated/avm_circuit_builder.hpp" #include diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_deserialization.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_deserialization.cpp index 2590e5e298a..9b9c4bd7b3e 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_deserialization.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_deserialization.cpp @@ -35,6 +35,8 @@ const std::unordered_map> OPCODE_WIRE_FORMAT = { OpCode::AND, three_operand_format }, { OpCode::OR, three_operand_format }, { OpCode::XOR, three_operand_format }, + // Compute - Type Conversions + { OpCode::CAST, { OperandType::INDIRECT, OperandType::TAG, OperandType::UINT32, OperandType::UINT32 } }, // Execution Environment - Calldata { OpCode::CALLDATACOPY, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32 } }, // Machine State - Internal Control Flow diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp index 1e018d647d6..e25d9ad1807 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp @@ -180,6 +180,13 @@ std::vector Execution::gen_trace(std::vector const& instructio std::get(inst.operands.at(4)), std::get(inst.operands.at(1))); break; + // Compute - Type Conversions + case OpCode::CAST: + trace_builder.op_cast(std::get(inst.operands.at(0)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + std::get(inst.operands.at(1))); + break; // Execution Environment - Calldata case OpCode::CALLDATACOPY: trace_builder.calldata_copy(std::get(inst.operands.at(0)), diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_mem_trace.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_mem_trace.cpp index 00b7b0bc1a6..af36d8df5da 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_mem_trace.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_mem_trace.cpp @@ -182,7 +182,7 @@ void AvmMemTraceBuilder::store_in_mem_trace( * @brief Handle a read memory operation specific to MOV opcode. Load the corresponding * value to the intermediate register ia. A memory trace entry for the load * operation is added. It is permissive in the sense that we do not enforce tag - * matching with against any instruction tag. In addition, the specific selector + * matching against any instruction tag. In addition, the specific selector * for MOV opcode is enabled. * * @param clk Main clock @@ -209,6 +209,21 @@ AvmMemTraceBuilder::MemEntry AvmMemTraceBuilder::read_and_load_mov_opcode(uint32 return mem_entry; } +/** + * @brief Handle a read memory operation specific to CMOV opcode. Load the corresponding + * values to the intermediate register ia, ib, id. Three memory trace entries for + * these load operations are added. They are permissive in the sense that we do not + * enforce tag matching against any instruction tag. In addition, the specific selector + * for CMOV opcode is enabled. + * + * @param clk Main clock + * @param a_addr Memory address of the first value candidate a. + * @param b_addr Memory address of the second value candidate b. + * @param cond_addr Memory address of the conditional value. + * + * @return Result of the read operation containing the value and the tag of the memory cell + * at the supplied address. + */ std::array AvmMemTraceBuilder::read_and_load_cmov_opcode(uint32_t clk, uint32_t a_addr, uint32_t b_addr, @@ -260,6 +275,39 @@ std::array AvmMemTraceBuilder::read_and_load_cm return { a_mem_entry, b_mem_entry, cond_mem_entry }; } +/** + * @brief Handle a read memory operation specific to CAST opcode. Load the corresponding + * value to the intermediate register ia. A memory trace entry for the load + * operation is added. It is permissive in the sense that we do not enforce tag + * matching against any instruction tag. The write instruction tag w_in_tag + * is passed and added in the memory trace entry. + * + * @param clk Main clock + * @param addr Memory address of the source offset + * @param w_in_tag Write instruction instruction tag (tag the value is casted to) + * + * @return Result of the read operation containing the value and the tag of the memory cell + * at the supplied address. + */ +AvmMemTraceBuilder::MemEntry AvmMemTraceBuilder::read_and_load_cast_opcode(uint32_t clk, + uint32_t addr, + AvmMemoryTag w_in_tag) +{ + MemEntry mem_entry = memory.contains(addr) ? memory.at(addr) : MemEntry{}; + + mem_trace.emplace_back(MemoryTraceEntry{ + .m_clk = clk, + .m_sub_clk = SUB_CLK_LOAD_A, + .m_addr = addr, + .m_val = mem_entry.val, + .m_tag = mem_entry.tag, + .r_in_tag = mem_entry.tag, + .w_in_tag = w_in_tag, + }); + + return mem_entry; +} + /** * @brief Handle a read memory operation and load the corresponding value to the * supplied intermediate register. A memory trace entry for the load operation diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_mem_trace.hpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_mem_trace.hpp index 31bc2e4b915..f71de0c4136 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_mem_trace.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_mem_trace.hpp @@ -92,6 +92,7 @@ class AvmMemTraceBuilder { uint32_t a_addr, uint32_t b_addr, uint32_t cond_addr); + MemEntry read_and_load_cast_opcode(uint32_t clk, uint32_t addr, AvmMemoryTag w_in_tag); MemRead read_and_load_from_memory( uint32_t clk, IntermRegister interm_reg, uint32_t addr, AvmMemoryTag r_in_tag, AvmMemoryTag w_in_tag); MemRead indirect_read_and_load_from_memory(uint32_t clk, IndirectRegister ind_reg, uint32_t addr); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_opcode.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_opcode.cpp index 05caf1ace28..df85cc684fa 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_opcode.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_opcode.cpp @@ -6,95 +6,8 @@ namespace bb::avm_trace { -const std::unordered_map Bytecode::OPERANDS_NUM = { - // Compute - // Compute - Arithmetic - { OpCode::ADD, 3 }, - { OpCode::SUB, 3 }, - { OpCode::MUL, 3 }, - { OpCode::DIV, 3 }, - { OpCode::FDIV, 3 }, - //// Compute - Comparators - //{OpCode::EQ, }, - //{OpCode::LT, }, - //{OpCode::LTE, }, - //// Compute - Bitwise - //{OpCode::AND, }, - //{OpCode::OR, }, - //{OpCode::XOR, }, - // { OpCode::NOT, 2 }, - //{OpCode::SHL, }, - //{OpCode::SHR, }, - //// Compute - Type Conversions - //{OpCode::CAST, }, - - //// Execution Environment - //{OpCode::ADDRESS, }, - //{OpCode::STORAGEADDRESS, }, - //{OpCode::SENDER, }, - //{OpCode::PORTAL, }, - //{OpCode::FEEPERL1GAS, }, - //{OpCode::FEEPERL2GAS, }, - //{OpCode::FEEPERDAGAS, }, - //{OpCode::CONTRACTCALLDEPTH, }, - //// Execution Environment - Globals - //{OpCode::CHAINID, }, - //{OpCode::VERSION, }, - //{OpCode::BLOCKNUMBER, }, - //{OpCode::TIMESTAMP, }, - //{OpCode::COINBASE, }, - //{OpCode::BLOCKL1GASLIMIT, }, - //{OpCode::BLOCKL2GASLIMIT, }, - //{OpCode::BLOCKDAGASLIMIT, }, - // Execution Environment - Calldata - { OpCode::CALLDATACOPY, 3 }, - - //// Machine State - // Machine State - Gas - //{ OpCode::L1GASLEFT, }, - //{ OpCode::L2GASLEFT, }, - //{ OpCode::DAGASLEFT, }, - //// Machine State - Internal Control Flow - { OpCode::JUMP, 1 }, - { OpCode::JUMPI, 1 }, - { OpCode::INTERNALCALL, 1 }, - { OpCode::INTERNALRETURN, 0 }, - - //// Machine State - Memory - { OpCode::SET, 5 }, - //{ OpCode::MOV, }, - //{ OpCode::CMOV, }, - - //// World State - //{ OpCode::SLOAD, }, // Public Storage - //{ OpCode::SSTORE, }, // Public Storage - //{ OpCode::NOTEHASHEXISTS, }, // Notes & Nullifiers - //{ OpCode::EMITNOTEHASH, }, // Notes & Nullifiers - //{ OpCode::NULLIFIEREXISTS, }, // Notes & Nullifiers - //{ OpCode::EMITNULLIFIER, }, // Notes & Nullifiers - //{ OpCode::L1TOL2MSGEXISTS, }, // Messages - //{ OpCode::HEADERMEMBER, }, - - //// Accrued Substate - //{ OpCode::EMITUNENCRYPTEDLOG, }, - //{ OpCode::SENDL2TOL1MSG, }, - - //// Control Flow - Contract Calls - //{ OpCode::CALL, }, - //{ OpCode::STATICCALL, }, - //{ OpCode::DELEGATECALL, }, - { OpCode::RETURN, 2 }, - // { OpCode::REVERT, }, - - //// Gadgets - //{ OpCode::KECCAK, }, - //{ OpCode::POSEIDON2, }, - //{ OpCode::SHA256, }, - //{ OpCode::PEDERSEN, }, -}; - /** - * @brief Test whether a given byte reprents a valid opcode. + * @brief Test whether a given byte represents a valid opcode. * * @param byte The input byte. * @return A boolean telling whether a corresponding opcode does match the input byte. @@ -104,62 +17,6 @@ bool Bytecode::is_valid(const uint8_t byte) return byte < static_cast(OpCode::LAST_OPCODE_SENTINEL); } -/** - * @brief A function returning whether a supplied opcode has an instruction tag as argument. - * - * @param op_code The opcode - * @return A boolean set to true if the corresponding instruction needs a tag as argument. - */ -bool Bytecode::has_in_tag(OpCode const op_code) -{ - switch (op_code) { - case OpCode::ADDRESS: - case OpCode::STORAGEADDRESS: - case OpCode::SENDER: - case OpCode::PORTAL: - case OpCode::FEEPERL1GAS: - case OpCode::FEEPERL2GAS: - case OpCode::FEEPERDAGAS: - case OpCode::CONTRACTCALLDEPTH: - case OpCode::CHAINID: - case OpCode::VERSION: - case OpCode::BLOCKNUMBER: - case OpCode::TIMESTAMP: - case OpCode::COINBASE: - case OpCode::BLOCKL1GASLIMIT: - case OpCode::BLOCKL2GASLIMIT: - case OpCode::BLOCKDAGASLIMIT: - case OpCode::CALLDATACOPY: - case OpCode::L1GASLEFT: - case OpCode::L2GASLEFT: - case OpCode::DAGASLEFT: - case OpCode::JUMP: - case OpCode::JUMPI: - case OpCode::INTERNALCALL: - case OpCode::INTERNALRETURN: - case OpCode::MOV: - case OpCode::CMOV: - case OpCode::SLOAD: - case OpCode::SSTORE: - case OpCode::NOTEHASHEXISTS: - case OpCode::EMITNOTEHASH: - case OpCode::NULLIFIEREXISTS: - case OpCode::EMITNULLIFIER: - case OpCode::L1TOL2MSGEXISTS: - case OpCode::HEADERMEMBER: - case OpCode::EMITUNENCRYPTEDLOG: - case OpCode::SENDL2TOL1MSG: - case OpCode::CALL: - case OpCode::STATICCALL: - case OpCode::RETURN: - case OpCode::REVERT: - case OpCode::FDIV: - return false; - default: - return true; - } -} - std::string to_hex(OpCode opcode) { std::ostringstream stream; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_opcode.hpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_opcode.hpp index 98adf14ab29..147cbbc36f1 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_opcode.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_opcode.hpp @@ -106,8 +106,6 @@ enum class OpCode : uint8_t { class Bytecode { public: static bool is_valid(uint8_t byte); - static bool has_in_tag(OpCode); - static const std::unordered_map OPERANDS_NUM; }; std::string to_hex(OpCode opcode); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp index a9e27af4127..9a449eb43e8 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp @@ -118,6 +118,7 @@ void AvmTraceBuilder::op_add( main_trace.push_back(Row{ .avm_main_clk = clk, + .avm_main_alu_in_tag = FF(static_cast(in_tag)), .avm_main_ia = a, .avm_main_ib = b, .avm_main_ic = c, @@ -181,6 +182,7 @@ void AvmTraceBuilder::op_sub( main_trace.push_back(Row{ .avm_main_clk = clk, + .avm_main_alu_in_tag = FF(static_cast(in_tag)), .avm_main_ia = a, .avm_main_ib = b, .avm_main_ic = c, @@ -244,6 +246,7 @@ void AvmTraceBuilder::op_mul( main_trace.push_back(Row{ .avm_main_clk = clk, + .avm_main_alu_in_tag = FF(static_cast(in_tag)), .avm_main_ia = a, .avm_main_ib = b, .avm_main_ic = c, @@ -390,6 +393,7 @@ void AvmTraceBuilder::op_not(uint8_t indirect, uint32_t a_offset, uint32_t dst_o main_trace.push_back(Row{ .avm_main_clk = clk, + .avm_main_alu_in_tag = FF(static_cast(in_tag)), .avm_main_ia = a, .avm_main_ic = c, .avm_main_ind_a = indirect_a_flag ? FF(a_offset) : FF(0), @@ -447,6 +451,7 @@ void AvmTraceBuilder::op_eq( main_trace.push_back(Row{ .avm_main_clk = clk, + .avm_main_alu_in_tag = FF(static_cast(in_tag)), .avm_main_ia = a, .avm_main_ib = b, .avm_main_ic = c, @@ -653,6 +658,7 @@ void AvmTraceBuilder::op_lt( main_trace.push_back(Row{ .avm_main_clk = clk, + .avm_main_alu_in_tag = FF(static_cast(in_tag)), .avm_main_ia = a, .avm_main_ib = b, .avm_main_ic = c, @@ -703,6 +709,7 @@ void AvmTraceBuilder::op_lte( main_trace.push_back(Row{ .avm_main_clk = clk, + .avm_main_alu_in_tag = FF(static_cast(in_tag)), .avm_main_ia = a, .avm_main_ib = b, .avm_main_ic = c, @@ -942,6 +949,73 @@ void AvmTraceBuilder::op_cmov( }); } +/** + * @brief Cast an element pointed by the address a_offset into type specified by dst_tag and + store the result in address given by dst_offset. + * + * @param indirect A byte encoding information about indirect/direct memory access. + * @param a_offset Offset of source memory cell. + * @param dst_offset Offset of destination memory cell. + * @param dst_tag Destination tag specifying the type the source value must be casted to. + */ +void AvmTraceBuilder::op_cast(uint8_t indirect, uint32_t a_offset, uint32_t dst_offset, AvmMemoryTag dst_tag) +{ + auto const clk = static_cast(main_trace.size()); + bool tag_match = true; + uint32_t direct_a_offset = a_offset; + uint32_t direct_dst_offset = dst_offset; + + bool indirect_a_flag = is_operand_indirect(indirect, 0); + bool indirect_dst_flag = is_operand_indirect(indirect, 1); + + if (indirect_a_flag) { + auto read_ind_a = mem_trace_builder.indirect_read_and_load_from_memory(clk, IndirectRegister::IND_A, a_offset); + direct_a_offset = uint32_t(read_ind_a.val); + tag_match = tag_match && read_ind_a.tag_match; + } + + if (indirect_dst_flag) { + auto read_ind_c = + mem_trace_builder.indirect_read_and_load_from_memory(clk, IndirectRegister::IND_C, dst_offset); + direct_dst_offset = uint32_t(read_ind_c.val); + tag_match = tag_match && read_ind_c.tag_match; + } + + // Reading from memory and loading into ia + auto memEntry = mem_trace_builder.read_and_load_cast_opcode(clk, direct_a_offset, dst_tag); + FF a = memEntry.val; + + // In case of a memory tag error, we do not perform the computation. + // Therefore, we do not create any entry in ALU table and store the value 0 as + // output (c) in memory. + FF c = tag_match ? alu_trace_builder.op_cast(a, dst_tag, clk) : FF(0); + + // Write into memory value c from intermediate register ic. + mem_trace_builder.write_into_memory(clk, IntermRegister::IC, direct_dst_offset, c, memEntry.tag, dst_tag); + + main_trace.push_back(Row{ + .avm_main_clk = clk, + .avm_main_alu_in_tag = FF(static_cast(dst_tag)), + .avm_main_ia = a, + .avm_main_ic = c, + .avm_main_ind_a = indirect_a_flag ? FF(a_offset) : FF(0), + .avm_main_ind_c = indirect_dst_flag ? FF(dst_offset) : FF(0), + .avm_main_ind_op_a = FF(static_cast(indirect_a_flag)), + .avm_main_ind_op_c = FF(static_cast(indirect_dst_flag)), + .avm_main_internal_return_ptr = FF(internal_return_ptr), + .avm_main_mem_idx_a = FF(direct_a_offset), + .avm_main_mem_idx_c = FF(direct_dst_offset), + .avm_main_mem_op_a = FF(1), + .avm_main_mem_op_c = FF(1), + .avm_main_pc = FF(pc++), + .avm_main_r_in_tag = FF(static_cast(memEntry.tag)), + .avm_main_rwc = FF(1), + .avm_main_sel_op_cast = FF(1), + .avm_main_tag_err = FF(static_cast(!tag_match)), + .avm_main_w_in_tag = FF(static_cast(dst_tag)), + }); +} + /** * @brief CALLDATACOPY opcode with direct or indirect memory access, i.e., * direct: M[dst_offset:dst_offset+copy_size] = calldata[cd_offset:cd_offset+copy_size] @@ -1441,6 +1515,8 @@ std::vector AvmTraceBuilder::finalize() dest.avm_alu_op_eq = FF(static_cast(src.alu_op_eq)); dest.avm_alu_op_lt = FF(static_cast(src.alu_op_lt)); dest.avm_alu_op_lte = FF(static_cast(src.alu_op_lte)); + dest.avm_alu_op_cast = FF(static_cast(src.alu_op_cast)); + dest.avm_alu_op_cast_prev = FF(static_cast(src.alu_op_cast_prev)); dest.avm_alu_cmp_sel = FF(static_cast(src.alu_op_lt) + static_cast(src.alu_op_lte)); dest.avm_alu_rng_chk_sel = FF(static_cast(src.rng_chk_sel)); @@ -1486,9 +1562,10 @@ std::vector AvmTraceBuilder::finalize() // multiplication over u128 is taking two lines. if (dest.avm_alu_op_add == FF(1) || dest.avm_alu_op_sub == FF(1) || dest.avm_alu_op_mul == FF(1) || dest.avm_alu_op_eq == FF(1) || dest.avm_alu_op_not == FF(1) || dest.avm_alu_op_lt == FF(1) || - dest.avm_alu_op_lte == FF(1)) { + dest.avm_alu_op_lte == FF(1) || dest.avm_alu_op_cast == FF(1)) { dest.avm_alu_alu_sel = FF(1); } + if (dest.avm_alu_cmp_sel == FF(1) || dest.avm_alu_rng_chk_sel == FF(1)) { dest.avm_alu_a_lo = FF(src.hi_lo_limbs.at(0)); dest.avm_alu_a_hi = FF(src.hi_lo_limbs.at(1)); @@ -1512,6 +1589,20 @@ std::vector AvmTraceBuilder::finalize() dest.avm_alu_rng_chk_lookup_selector = FF(1); } + if (dest.avm_alu_op_cast == FF(1)) { + dest.avm_alu_a_lo = FF(src.hi_lo_limbs.at(0)); + dest.avm_alu_a_hi = FF(src.hi_lo_limbs.at(1)); + dest.avm_alu_p_sub_a_lo = FF(src.hi_lo_limbs.at(2)); + dest.avm_alu_p_sub_a_hi = FF(src.hi_lo_limbs.at(3)); + dest.avm_alu_rng_chk_lookup_selector = FF(1); + } + + if (dest.avm_alu_op_cast_prev == FF(1)) { + dest.avm_alu_a_lo = FF(src.hi_lo_limbs.at(0)); + dest.avm_alu_a_hi = FF(src.hi_lo_limbs.at(1)); + dest.avm_alu_rng_chk_lookup_selector = FF(1); + } + // Multiplication over u128 expands over two rows. if (dest.avm_alu_op_mul == FF(1) && dest.avm_alu_u128_tag) { main_trace.at(i + 1).avm_alu_rng_chk_lookup_selector = FF(1); @@ -1523,7 +1614,7 @@ std::vector AvmTraceBuilder::finalize() if ((r.avm_main_sel_op_add == FF(1) || r.avm_main_sel_op_sub == FF(1) || r.avm_main_sel_op_mul == FF(1) || r.avm_main_sel_op_eq == FF(1) || r.avm_main_sel_op_not == FF(1) || r.avm_main_sel_op_lt || - r.avm_main_sel_op_lte) && + r.avm_main_sel_op_lte || r.avm_main_sel_op_cast == FF(1)) && r.avm_main_tag_err == FF(0)) { r.avm_main_alu_sel = FF(1); } diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.hpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.hpp index 9918144f5f3..71b1aabe368 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.hpp @@ -72,6 +72,10 @@ class AvmTraceBuilder { // is determined conditionally based on a conditional value determined by cond_offset. void op_cmov(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t cond_offset, uint32_t dst_offset); + // Cast an element pointed by the address a_offset into type specified by dst_tag and + // store the result in address given by dst_offset. + void op_cast(uint8_t indirect, uint32_t a_offset, uint32_t dst_offset, AvmMemoryTag dst_tag); + // Jump to a given program counter. void jump(uint32_t jmp_dest); diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.hpp index 4a163364de3..4bfaa9fa499 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.hpp @@ -69,6 +69,8 @@ template struct AvmFullRow { FF avm_alu_ic{}; FF avm_alu_in_tag{}; FF avm_alu_op_add{}; + FF avm_alu_op_cast{}; + FF avm_alu_op_cast_prev{}; FF avm_alu_op_div{}; FF avm_alu_op_eq{}; FF avm_alu_op_eq_diff_inv{}; @@ -129,6 +131,7 @@ template struct AvmFullRow { FF avm_byte_lookup_table_input_b{}; FF avm_byte_lookup_table_op_id{}; FF avm_byte_lookup_table_output{}; + FF avm_main_alu_in_tag{}; FF avm_main_alu_sel{}; FF avm_main_bin_op_id{}; FF avm_main_bin_sel{}; @@ -173,6 +176,7 @@ template struct AvmFullRow { FF avm_main_sel_mov_b{}; FF avm_main_sel_op_add{}; FF avm_main_sel_op_and{}; + FF avm_main_sel_op_cast{}; FF avm_main_sel_op_div{}; FF avm_main_sel_op_eq{}; FF avm_main_sel_op_lt{}; @@ -264,11 +268,14 @@ template struct AvmFullRow { FF lookup_u16_14_counts{}; FF avm_alu_a_hi_shift{}; FF avm_alu_a_lo_shift{}; + FF avm_alu_alu_sel_shift{}; FF avm_alu_b_hi_shift{}; FF avm_alu_b_lo_shift{}; FF avm_alu_cmp_rng_ctr_shift{}; FF avm_alu_cmp_sel_shift{}; FF avm_alu_op_add_shift{}; + FF avm_alu_op_cast_prev_shift{}; + FF avm_alu_op_cast_shift{}; FF avm_alu_op_mul_shift{}; FF avm_alu_op_sub_shift{}; FF avm_alu_p_sub_a_hi_shift{}; @@ -309,8 +316,8 @@ class AvmCircuitBuilder { using Polynomial = Flavor::Polynomial; using ProverPolynomials = Flavor::ProverPolynomials; - static constexpr size_t num_fixed_columns = 246; - static constexpr size_t num_polys = 211; + static constexpr size_t num_fixed_columns = 253; + static constexpr size_t num_polys = 215; std::vector rows; void set_trace(std::vector&& trace) { rows = std::move(trace); } @@ -344,6 +351,8 @@ class AvmCircuitBuilder { polys.avm_alu_ic[i] = rows[i].avm_alu_ic; polys.avm_alu_in_tag[i] = rows[i].avm_alu_in_tag; polys.avm_alu_op_add[i] = rows[i].avm_alu_op_add; + polys.avm_alu_op_cast[i] = rows[i].avm_alu_op_cast; + polys.avm_alu_op_cast_prev[i] = rows[i].avm_alu_op_cast_prev; polys.avm_alu_op_div[i] = rows[i].avm_alu_op_div; polys.avm_alu_op_eq[i] = rows[i].avm_alu_op_eq; polys.avm_alu_op_eq_diff_inv[i] = rows[i].avm_alu_op_eq_diff_inv; @@ -404,6 +413,7 @@ class AvmCircuitBuilder { polys.avm_byte_lookup_table_input_b[i] = rows[i].avm_byte_lookup_table_input_b; polys.avm_byte_lookup_table_op_id[i] = rows[i].avm_byte_lookup_table_op_id; polys.avm_byte_lookup_table_output[i] = rows[i].avm_byte_lookup_table_output; + polys.avm_main_alu_in_tag[i] = rows[i].avm_main_alu_in_tag; polys.avm_main_alu_sel[i] = rows[i].avm_main_alu_sel; polys.avm_main_bin_op_id[i] = rows[i].avm_main_bin_op_id; polys.avm_main_bin_sel[i] = rows[i].avm_main_bin_sel; @@ -448,6 +458,7 @@ class AvmCircuitBuilder { polys.avm_main_sel_mov_b[i] = rows[i].avm_main_sel_mov_b; polys.avm_main_sel_op_add[i] = rows[i].avm_main_sel_op_add; polys.avm_main_sel_op_and[i] = rows[i].avm_main_sel_op_and; + polys.avm_main_sel_op_cast[i] = rows[i].avm_main_sel_op_cast; polys.avm_main_sel_op_div[i] = rows[i].avm_main_sel_op_div; polys.avm_main_sel_op_eq[i] = rows[i].avm_main_sel_op_eq; polys.avm_main_sel_op_lt[i] = rows[i].avm_main_sel_op_lt; @@ -510,11 +521,14 @@ class AvmCircuitBuilder { polys.avm_alu_a_hi_shift = Polynomial(polys.avm_alu_a_hi.shifted()); polys.avm_alu_a_lo_shift = Polynomial(polys.avm_alu_a_lo.shifted()); + polys.avm_alu_alu_sel_shift = Polynomial(polys.avm_alu_alu_sel.shifted()); polys.avm_alu_b_hi_shift = Polynomial(polys.avm_alu_b_hi.shifted()); polys.avm_alu_b_lo_shift = Polynomial(polys.avm_alu_b_lo.shifted()); polys.avm_alu_cmp_rng_ctr_shift = Polynomial(polys.avm_alu_cmp_rng_ctr.shifted()); polys.avm_alu_cmp_sel_shift = Polynomial(polys.avm_alu_cmp_sel.shifted()); polys.avm_alu_op_add_shift = Polynomial(polys.avm_alu_op_add.shifted()); + polys.avm_alu_op_cast_prev_shift = Polynomial(polys.avm_alu_op_cast_prev.shifted()); + polys.avm_alu_op_cast_shift = Polynomial(polys.avm_alu_op_cast.shifted()); polys.avm_alu_op_mul_shift = Polynomial(polys.avm_alu_op_mul.shifted()); polys.avm_alu_op_sub_shift = Polynomial(polys.avm_alu_op_sub.shifted()); polys.avm_alu_p_sub_a_hi_shift = Polynomial(polys.avm_alu_p_sub_a_hi.shifted()); diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp index 4bb786ea4cb..bcdaabdbd6c 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp @@ -69,11 +69,11 @@ class AvmFlavor { using RelationSeparator = FF; static constexpr size_t NUM_PRECOMPUTED_ENTITIES = 2; - static constexpr size_t NUM_WITNESS_ENTITIES = 209; + static constexpr size_t NUM_WITNESS_ENTITIES = 213; static constexpr size_t NUM_WIRES = NUM_WITNESS_ENTITIES + NUM_PRECOMPUTED_ENTITIES; // We have two copies of the witness entities, so we subtract the number of fixed ones (they have no shift), one for // the unshifted and one for the shifted - static constexpr size_t NUM_ALL_ENTITIES = 246; + static constexpr size_t NUM_ALL_ENTITIES = 253; using GrandProductRelations = std::tuple, perm_main_bin_relation, @@ -191,6 +191,8 @@ class AvmFlavor { avm_alu_ic, avm_alu_in_tag, avm_alu_op_add, + avm_alu_op_cast, + avm_alu_op_cast_prev, avm_alu_op_div, avm_alu_op_eq, avm_alu_op_eq_diff_inv, @@ -251,6 +253,7 @@ class AvmFlavor { avm_byte_lookup_table_input_b, avm_byte_lookup_table_op_id, avm_byte_lookup_table_output, + avm_main_alu_in_tag, avm_main_alu_sel, avm_main_bin_op_id, avm_main_bin_sel, @@ -295,6 +298,7 @@ class AvmFlavor { avm_main_sel_mov_b, avm_main_sel_op_add, avm_main_sel_op_and, + avm_main_sel_op_cast, avm_main_sel_op_div, avm_main_sel_op_eq, avm_main_sel_op_lt, @@ -403,6 +407,8 @@ class AvmFlavor { avm_alu_ic, avm_alu_in_tag, avm_alu_op_add, + avm_alu_op_cast, + avm_alu_op_cast_prev, avm_alu_op_div, avm_alu_op_eq, avm_alu_op_eq_diff_inv, @@ -463,6 +469,7 @@ class AvmFlavor { avm_byte_lookup_table_input_b, avm_byte_lookup_table_op_id, avm_byte_lookup_table_output, + avm_main_alu_in_tag, avm_main_alu_sel, avm_main_bin_op_id, avm_main_bin_sel, @@ -507,6 +514,7 @@ class AvmFlavor { avm_main_sel_mov_b, avm_main_sel_op_add, avm_main_sel_op_and, + avm_main_sel_op_cast, avm_main_sel_op_div, avm_main_sel_op_eq, avm_main_sel_op_lt, @@ -620,6 +628,8 @@ class AvmFlavor { avm_alu_ic, avm_alu_in_tag, avm_alu_op_add, + avm_alu_op_cast, + avm_alu_op_cast_prev, avm_alu_op_div, avm_alu_op_eq, avm_alu_op_eq_diff_inv, @@ -680,6 +690,7 @@ class AvmFlavor { avm_byte_lookup_table_input_b, avm_byte_lookup_table_op_id, avm_byte_lookup_table_output, + avm_main_alu_in_tag, avm_main_alu_sel, avm_main_bin_op_id, avm_main_bin_sel, @@ -724,6 +735,7 @@ class AvmFlavor { avm_main_sel_mov_b, avm_main_sel_op_add, avm_main_sel_op_and, + avm_main_sel_op_cast, avm_main_sel_op_div, avm_main_sel_op_eq, avm_main_sel_op_lt, @@ -815,11 +827,14 @@ class AvmFlavor { lookup_u16_14_counts, avm_alu_a_hi_shift, avm_alu_a_lo_shift, + avm_alu_alu_sel_shift, avm_alu_b_hi_shift, avm_alu_b_lo_shift, avm_alu_cmp_rng_ctr_shift, avm_alu_cmp_sel_shift, avm_alu_op_add_shift, + avm_alu_op_cast_prev_shift, + avm_alu_op_cast_shift, avm_alu_op_mul_shift, avm_alu_op_sub_shift, avm_alu_p_sub_a_hi_shift, @@ -869,6 +884,8 @@ class AvmFlavor { avm_alu_ic, avm_alu_in_tag, avm_alu_op_add, + avm_alu_op_cast, + avm_alu_op_cast_prev, avm_alu_op_div, avm_alu_op_eq, avm_alu_op_eq_diff_inv, @@ -929,6 +946,7 @@ class AvmFlavor { avm_byte_lookup_table_input_b, avm_byte_lookup_table_op_id, avm_byte_lookup_table_output, + avm_main_alu_in_tag, avm_main_alu_sel, avm_main_bin_op_id, avm_main_bin_sel, @@ -973,6 +991,7 @@ class AvmFlavor { avm_main_sel_mov_b, avm_main_sel_op_add, avm_main_sel_op_and, + avm_main_sel_op_cast, avm_main_sel_op_div, avm_main_sel_op_eq, avm_main_sel_op_lt, @@ -1064,11 +1083,14 @@ class AvmFlavor { lookup_u16_14_counts, avm_alu_a_hi_shift, avm_alu_a_lo_shift, + avm_alu_alu_sel_shift, avm_alu_b_hi_shift, avm_alu_b_lo_shift, avm_alu_cmp_rng_ctr_shift, avm_alu_cmp_sel_shift, avm_alu_op_add_shift, + avm_alu_op_cast_prev_shift, + avm_alu_op_cast_shift, avm_alu_op_mul_shift, avm_alu_op_sub_shift, avm_alu_p_sub_a_hi_shift, @@ -1118,6 +1140,8 @@ class AvmFlavor { avm_alu_ic, avm_alu_in_tag, avm_alu_op_add, + avm_alu_op_cast, + avm_alu_op_cast_prev, avm_alu_op_div, avm_alu_op_eq, avm_alu_op_eq_diff_inv, @@ -1178,6 +1202,7 @@ class AvmFlavor { avm_byte_lookup_table_input_b, avm_byte_lookup_table_op_id, avm_byte_lookup_table_output, + avm_main_alu_in_tag, avm_main_alu_sel, avm_main_bin_op_id, avm_main_bin_sel, @@ -1222,6 +1247,7 @@ class AvmFlavor { avm_main_sel_mov_b, avm_main_sel_op_add, avm_main_sel_op_and, + avm_main_sel_op_cast, avm_main_sel_op_div, avm_main_sel_op_eq, avm_main_sel_op_lt, @@ -1314,44 +1340,84 @@ class AvmFlavor { }; RefVector get_to_be_shifted() { - return { avm_alu_a_hi, avm_alu_a_lo, - avm_alu_b_hi, avm_alu_b_lo, - avm_alu_cmp_rng_ctr, avm_alu_cmp_sel, - avm_alu_op_add, avm_alu_op_mul, - avm_alu_op_sub, avm_alu_p_sub_a_hi, - avm_alu_p_sub_a_lo, avm_alu_p_sub_b_hi, - avm_alu_p_sub_b_lo, avm_alu_rng_chk_lookup_selector, - avm_alu_rng_chk_sel, avm_alu_u16_r0, - avm_alu_u16_r1, avm_alu_u16_r2, - avm_alu_u16_r3, avm_alu_u16_r4, - avm_alu_u16_r5, avm_alu_u16_r6, - avm_alu_u8_r0, avm_alu_u8_r1, - avm_binary_acc_ia, avm_binary_acc_ib, - avm_binary_acc_ic, avm_binary_mem_tag_ctr, - avm_binary_op_id, avm_main_internal_return_ptr, - avm_main_pc, avm_mem_addr, - avm_mem_rw, avm_mem_tag, + return { avm_alu_a_hi, + avm_alu_a_lo, + avm_alu_alu_sel, + avm_alu_b_hi, + avm_alu_b_lo, + avm_alu_cmp_rng_ctr, + avm_alu_cmp_sel, + avm_alu_op_add, + avm_alu_op_cast_prev, + avm_alu_op_cast, + avm_alu_op_mul, + avm_alu_op_sub, + avm_alu_p_sub_a_hi, + avm_alu_p_sub_a_lo, + avm_alu_p_sub_b_hi, + avm_alu_p_sub_b_lo, + avm_alu_rng_chk_lookup_selector, + avm_alu_rng_chk_sel, + avm_alu_u16_r0, + avm_alu_u16_r1, + avm_alu_u16_r2, + avm_alu_u16_r3, + avm_alu_u16_r4, + avm_alu_u16_r5, + avm_alu_u16_r6, + avm_alu_u8_r0, + avm_alu_u8_r1, + avm_binary_acc_ia, + avm_binary_acc_ib, + avm_binary_acc_ic, + avm_binary_mem_tag_ctr, + avm_binary_op_id, + avm_main_internal_return_ptr, + avm_main_pc, + avm_mem_addr, + avm_mem_rw, + avm_mem_tag, avm_mem_val }; }; RefVector get_shifted() { - return { avm_alu_a_hi_shift, avm_alu_a_lo_shift, - avm_alu_b_hi_shift, avm_alu_b_lo_shift, - avm_alu_cmp_rng_ctr_shift, avm_alu_cmp_sel_shift, - avm_alu_op_add_shift, avm_alu_op_mul_shift, - avm_alu_op_sub_shift, avm_alu_p_sub_a_hi_shift, - avm_alu_p_sub_a_lo_shift, avm_alu_p_sub_b_hi_shift, - avm_alu_p_sub_b_lo_shift, avm_alu_rng_chk_lookup_selector_shift, - avm_alu_rng_chk_sel_shift, avm_alu_u16_r0_shift, - avm_alu_u16_r1_shift, avm_alu_u16_r2_shift, - avm_alu_u16_r3_shift, avm_alu_u16_r4_shift, - avm_alu_u16_r5_shift, avm_alu_u16_r6_shift, - avm_alu_u8_r0_shift, avm_alu_u8_r1_shift, - avm_binary_acc_ia_shift, avm_binary_acc_ib_shift, - avm_binary_acc_ic_shift, avm_binary_mem_tag_ctr_shift, - avm_binary_op_id_shift, avm_main_internal_return_ptr_shift, - avm_main_pc_shift, avm_mem_addr_shift, - avm_mem_rw_shift, avm_mem_tag_shift, + return { avm_alu_a_hi_shift, + avm_alu_a_lo_shift, + avm_alu_alu_sel_shift, + avm_alu_b_hi_shift, + avm_alu_b_lo_shift, + avm_alu_cmp_rng_ctr_shift, + avm_alu_cmp_sel_shift, + avm_alu_op_add_shift, + avm_alu_op_cast_prev_shift, + avm_alu_op_cast_shift, + avm_alu_op_mul_shift, + avm_alu_op_sub_shift, + avm_alu_p_sub_a_hi_shift, + avm_alu_p_sub_a_lo_shift, + avm_alu_p_sub_b_hi_shift, + avm_alu_p_sub_b_lo_shift, + avm_alu_rng_chk_lookup_selector_shift, + avm_alu_rng_chk_sel_shift, + avm_alu_u16_r0_shift, + avm_alu_u16_r1_shift, + avm_alu_u16_r2_shift, + avm_alu_u16_r3_shift, + avm_alu_u16_r4_shift, + avm_alu_u16_r5_shift, + avm_alu_u16_r6_shift, + avm_alu_u8_r0_shift, + avm_alu_u8_r1_shift, + avm_binary_acc_ia_shift, + avm_binary_acc_ib_shift, + avm_binary_acc_ic_shift, + avm_binary_mem_tag_ctr_shift, + avm_binary_op_id_shift, + avm_main_internal_return_ptr_shift, + avm_main_pc_shift, + avm_mem_addr_shift, + avm_mem_rw_shift, + avm_mem_tag_shift, avm_mem_val_shift }; }; }; @@ -1365,23 +1431,43 @@ class AvmFlavor { RefVector get_to_be_shifted() { - return { avm_alu_a_hi, avm_alu_a_lo, - avm_alu_b_hi, avm_alu_b_lo, - avm_alu_cmp_rng_ctr, avm_alu_cmp_sel, - avm_alu_op_add, avm_alu_op_mul, - avm_alu_op_sub, avm_alu_p_sub_a_hi, - avm_alu_p_sub_a_lo, avm_alu_p_sub_b_hi, - avm_alu_p_sub_b_lo, avm_alu_rng_chk_lookup_selector, - avm_alu_rng_chk_sel, avm_alu_u16_r0, - avm_alu_u16_r1, avm_alu_u16_r2, - avm_alu_u16_r3, avm_alu_u16_r4, - avm_alu_u16_r5, avm_alu_u16_r6, - avm_alu_u8_r0, avm_alu_u8_r1, - avm_binary_acc_ia, avm_binary_acc_ib, - avm_binary_acc_ic, avm_binary_mem_tag_ctr, - avm_binary_op_id, avm_main_internal_return_ptr, - avm_main_pc, avm_mem_addr, - avm_mem_rw, avm_mem_tag, + return { avm_alu_a_hi, + avm_alu_a_lo, + avm_alu_alu_sel, + avm_alu_b_hi, + avm_alu_b_lo, + avm_alu_cmp_rng_ctr, + avm_alu_cmp_sel, + avm_alu_op_add, + avm_alu_op_cast_prev, + avm_alu_op_cast, + avm_alu_op_mul, + avm_alu_op_sub, + avm_alu_p_sub_a_hi, + avm_alu_p_sub_a_lo, + avm_alu_p_sub_b_hi, + avm_alu_p_sub_b_lo, + avm_alu_rng_chk_lookup_selector, + avm_alu_rng_chk_sel, + avm_alu_u16_r0, + avm_alu_u16_r1, + avm_alu_u16_r2, + avm_alu_u16_r3, + avm_alu_u16_r4, + avm_alu_u16_r5, + avm_alu_u16_r6, + avm_alu_u8_r0, + avm_alu_u8_r1, + avm_binary_acc_ia, + avm_binary_acc_ib, + avm_binary_acc_ic, + avm_binary_mem_tag_ctr, + avm_binary_op_id, + avm_main_internal_return_ptr, + avm_main_pc, + avm_mem_addr, + avm_mem_rw, + avm_mem_tag, avm_mem_val }; }; @@ -1561,6 +1647,8 @@ class AvmFlavor { Base::avm_alu_ic = "AVM_ALU_IC"; Base::avm_alu_in_tag = "AVM_ALU_IN_TAG"; Base::avm_alu_op_add = "AVM_ALU_OP_ADD"; + Base::avm_alu_op_cast = "AVM_ALU_OP_CAST"; + Base::avm_alu_op_cast_prev = "AVM_ALU_OP_CAST_PREV"; Base::avm_alu_op_div = "AVM_ALU_OP_DIV"; Base::avm_alu_op_eq = "AVM_ALU_OP_EQ"; Base::avm_alu_op_eq_diff_inv = "AVM_ALU_OP_EQ_DIFF_INV"; @@ -1621,6 +1709,7 @@ class AvmFlavor { Base::avm_byte_lookup_table_input_b = "AVM_BYTE_LOOKUP_TABLE_INPUT_B"; Base::avm_byte_lookup_table_op_id = "AVM_BYTE_LOOKUP_TABLE_OP_ID"; Base::avm_byte_lookup_table_output = "AVM_BYTE_LOOKUP_TABLE_OUTPUT"; + Base::avm_main_alu_in_tag = "AVM_MAIN_ALU_IN_TAG"; Base::avm_main_alu_sel = "AVM_MAIN_ALU_SEL"; Base::avm_main_bin_op_id = "AVM_MAIN_BIN_OP_ID"; Base::avm_main_bin_sel = "AVM_MAIN_BIN_SEL"; @@ -1665,6 +1754,7 @@ class AvmFlavor { Base::avm_main_sel_mov_b = "AVM_MAIN_SEL_MOV_B"; Base::avm_main_sel_op_add = "AVM_MAIN_SEL_OP_ADD"; Base::avm_main_sel_op_and = "AVM_MAIN_SEL_OP_AND"; + Base::avm_main_sel_op_cast = "AVM_MAIN_SEL_OP_CAST"; Base::avm_main_sel_op_div = "AVM_MAIN_SEL_OP_DIV"; Base::avm_main_sel_op_eq = "AVM_MAIN_SEL_OP_EQ"; Base::avm_main_sel_op_lt = "AVM_MAIN_SEL_OP_LT"; @@ -1789,6 +1879,8 @@ class AvmFlavor { Commitment avm_alu_ic; Commitment avm_alu_in_tag; Commitment avm_alu_op_add; + Commitment avm_alu_op_cast; + Commitment avm_alu_op_cast_prev; Commitment avm_alu_op_div; Commitment avm_alu_op_eq; Commitment avm_alu_op_eq_diff_inv; @@ -1849,6 +1941,7 @@ class AvmFlavor { Commitment avm_byte_lookup_table_input_b; Commitment avm_byte_lookup_table_op_id; Commitment avm_byte_lookup_table_output; + Commitment avm_main_alu_in_tag; Commitment avm_main_alu_sel; Commitment avm_main_bin_op_id; Commitment avm_main_bin_sel; @@ -1893,6 +1986,7 @@ class AvmFlavor { Commitment avm_main_sel_mov_b; Commitment avm_main_sel_op_add; Commitment avm_main_sel_op_and; + Commitment avm_main_sel_op_cast; Commitment avm_main_sel_op_div; Commitment avm_main_sel_op_eq; Commitment avm_main_sel_op_lt; @@ -2017,6 +2111,8 @@ class AvmFlavor { avm_alu_ic = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_alu_in_tag = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_alu_op_add = deserialize_from_buffer(Transcript::proof_data, num_frs_read); + avm_alu_op_cast = deserialize_from_buffer(Transcript::proof_data, num_frs_read); + avm_alu_op_cast_prev = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_alu_op_div = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_alu_op_eq = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_alu_op_eq_diff_inv = deserialize_from_buffer(Transcript::proof_data, num_frs_read); @@ -2078,6 +2174,7 @@ class AvmFlavor { avm_byte_lookup_table_input_b = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_byte_lookup_table_op_id = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_byte_lookup_table_output = deserialize_from_buffer(Transcript::proof_data, num_frs_read); + avm_main_alu_in_tag = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_main_alu_sel = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_main_bin_op_id = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_main_bin_sel = deserialize_from_buffer(Transcript::proof_data, num_frs_read); @@ -2122,6 +2219,7 @@ class AvmFlavor { avm_main_sel_mov_b = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_main_sel_op_add = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_main_sel_op_and = deserialize_from_buffer(Transcript::proof_data, num_frs_read); + avm_main_sel_op_cast = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_main_sel_op_div = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_main_sel_op_eq = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_main_sel_op_lt = deserialize_from_buffer(Transcript::proof_data, num_frs_read); @@ -2250,6 +2348,8 @@ class AvmFlavor { serialize_to_buffer(avm_alu_ic, Transcript::proof_data); serialize_to_buffer(avm_alu_in_tag, Transcript::proof_data); serialize_to_buffer(avm_alu_op_add, Transcript::proof_data); + serialize_to_buffer(avm_alu_op_cast, Transcript::proof_data); + serialize_to_buffer(avm_alu_op_cast_prev, Transcript::proof_data); serialize_to_buffer(avm_alu_op_div, Transcript::proof_data); serialize_to_buffer(avm_alu_op_eq, Transcript::proof_data); serialize_to_buffer(avm_alu_op_eq_diff_inv, Transcript::proof_data); @@ -2310,6 +2410,7 @@ class AvmFlavor { serialize_to_buffer(avm_byte_lookup_table_input_b, Transcript::proof_data); serialize_to_buffer(avm_byte_lookup_table_op_id, Transcript::proof_data); serialize_to_buffer(avm_byte_lookup_table_output, Transcript::proof_data); + serialize_to_buffer(avm_main_alu_in_tag, Transcript::proof_data); serialize_to_buffer(avm_main_alu_sel, Transcript::proof_data); serialize_to_buffer(avm_main_bin_op_id, Transcript::proof_data); serialize_to_buffer(avm_main_bin_sel, Transcript::proof_data); @@ -2354,6 +2455,7 @@ class AvmFlavor { serialize_to_buffer(avm_main_sel_mov_b, Transcript::proof_data); serialize_to_buffer(avm_main_sel_op_add, Transcript::proof_data); serialize_to_buffer(avm_main_sel_op_and, Transcript::proof_data); + serialize_to_buffer(avm_main_sel_op_cast, Transcript::proof_data); serialize_to_buffer(avm_main_sel_op_div, Transcript::proof_data); serialize_to_buffer(avm_main_sel_op_eq, Transcript::proof_data); serialize_to_buffer(avm_main_sel_op_lt, Transcript::proof_data); diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp index 5c1cde78567..d5b48dee516 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp @@ -75,6 +75,8 @@ void AvmProver::execute_wire_commitments_round() witness_commitments.avm_alu_ic = commitment_key->commit(key->avm_alu_ic); witness_commitments.avm_alu_in_tag = commitment_key->commit(key->avm_alu_in_tag); witness_commitments.avm_alu_op_add = commitment_key->commit(key->avm_alu_op_add); + witness_commitments.avm_alu_op_cast = commitment_key->commit(key->avm_alu_op_cast); + witness_commitments.avm_alu_op_cast_prev = commitment_key->commit(key->avm_alu_op_cast_prev); witness_commitments.avm_alu_op_div = commitment_key->commit(key->avm_alu_op_div); witness_commitments.avm_alu_op_eq = commitment_key->commit(key->avm_alu_op_eq); witness_commitments.avm_alu_op_eq_diff_inv = commitment_key->commit(key->avm_alu_op_eq_diff_inv); @@ -136,6 +138,7 @@ void AvmProver::execute_wire_commitments_round() witness_commitments.avm_byte_lookup_table_input_b = commitment_key->commit(key->avm_byte_lookup_table_input_b); witness_commitments.avm_byte_lookup_table_op_id = commitment_key->commit(key->avm_byte_lookup_table_op_id); witness_commitments.avm_byte_lookup_table_output = commitment_key->commit(key->avm_byte_lookup_table_output); + witness_commitments.avm_main_alu_in_tag = commitment_key->commit(key->avm_main_alu_in_tag); witness_commitments.avm_main_alu_sel = commitment_key->commit(key->avm_main_alu_sel); witness_commitments.avm_main_bin_op_id = commitment_key->commit(key->avm_main_bin_op_id); witness_commitments.avm_main_bin_sel = commitment_key->commit(key->avm_main_bin_sel); @@ -180,6 +183,7 @@ void AvmProver::execute_wire_commitments_round() witness_commitments.avm_main_sel_mov_b = commitment_key->commit(key->avm_main_sel_mov_b); witness_commitments.avm_main_sel_op_add = commitment_key->commit(key->avm_main_sel_op_add); witness_commitments.avm_main_sel_op_and = commitment_key->commit(key->avm_main_sel_op_and); + witness_commitments.avm_main_sel_op_cast = commitment_key->commit(key->avm_main_sel_op_cast); witness_commitments.avm_main_sel_op_div = commitment_key->commit(key->avm_main_sel_op_div); witness_commitments.avm_main_sel_op_eq = commitment_key->commit(key->avm_main_sel_op_eq); witness_commitments.avm_main_sel_op_lt = commitment_key->commit(key->avm_main_sel_op_lt); @@ -256,6 +260,8 @@ void AvmProver::execute_wire_commitments_round() transcript->send_to_verifier(commitment_labels.avm_alu_ic, witness_commitments.avm_alu_ic); transcript->send_to_verifier(commitment_labels.avm_alu_in_tag, witness_commitments.avm_alu_in_tag); transcript->send_to_verifier(commitment_labels.avm_alu_op_add, witness_commitments.avm_alu_op_add); + transcript->send_to_verifier(commitment_labels.avm_alu_op_cast, witness_commitments.avm_alu_op_cast); + transcript->send_to_verifier(commitment_labels.avm_alu_op_cast_prev, witness_commitments.avm_alu_op_cast_prev); transcript->send_to_verifier(commitment_labels.avm_alu_op_div, witness_commitments.avm_alu_op_div); transcript->send_to_verifier(commitment_labels.avm_alu_op_eq, witness_commitments.avm_alu_op_eq); transcript->send_to_verifier(commitment_labels.avm_alu_op_eq_diff_inv, witness_commitments.avm_alu_op_eq_diff_inv); @@ -325,6 +331,7 @@ void AvmProver::execute_wire_commitments_round() witness_commitments.avm_byte_lookup_table_op_id); transcript->send_to_verifier(commitment_labels.avm_byte_lookup_table_output, witness_commitments.avm_byte_lookup_table_output); + transcript->send_to_verifier(commitment_labels.avm_main_alu_in_tag, witness_commitments.avm_main_alu_in_tag); transcript->send_to_verifier(commitment_labels.avm_main_alu_sel, witness_commitments.avm_main_alu_sel); transcript->send_to_verifier(commitment_labels.avm_main_bin_op_id, witness_commitments.avm_main_bin_op_id); transcript->send_to_verifier(commitment_labels.avm_main_bin_sel, witness_commitments.avm_main_bin_sel); @@ -372,6 +379,7 @@ void AvmProver::execute_wire_commitments_round() transcript->send_to_verifier(commitment_labels.avm_main_sel_mov_b, witness_commitments.avm_main_sel_mov_b); transcript->send_to_verifier(commitment_labels.avm_main_sel_op_add, witness_commitments.avm_main_sel_op_add); transcript->send_to_verifier(commitment_labels.avm_main_sel_op_and, witness_commitments.avm_main_sel_op_and); + transcript->send_to_verifier(commitment_labels.avm_main_sel_op_cast, witness_commitments.avm_main_sel_op_cast); transcript->send_to_verifier(commitment_labels.avm_main_sel_op_div, witness_commitments.avm_main_sel_op_div); transcript->send_to_verifier(commitment_labels.avm_main_sel_op_eq, witness_commitments.avm_main_sel_op_eq); transcript->send_to_verifier(commitment_labels.avm_main_sel_op_lt, witness_commitments.avm_main_sel_op_lt); diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp index f1b9bb2e4cd..a7b418bab60 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp @@ -70,6 +70,10 @@ bool AvmVerifier::verify_proof(const HonkProof& proof) commitments.avm_alu_ic = transcript->template receive_from_prover(commitment_labels.avm_alu_ic); commitments.avm_alu_in_tag = transcript->template receive_from_prover(commitment_labels.avm_alu_in_tag); commitments.avm_alu_op_add = transcript->template receive_from_prover(commitment_labels.avm_alu_op_add); + commitments.avm_alu_op_cast = + transcript->template receive_from_prover(commitment_labels.avm_alu_op_cast); + commitments.avm_alu_op_cast_prev = + transcript->template receive_from_prover(commitment_labels.avm_alu_op_cast_prev); commitments.avm_alu_op_div = transcript->template receive_from_prover(commitment_labels.avm_alu_op_div); commitments.avm_alu_op_eq = transcript->template receive_from_prover(commitment_labels.avm_alu_op_eq); commitments.avm_alu_op_eq_diff_inv = @@ -167,6 +171,8 @@ bool AvmVerifier::verify_proof(const HonkProof& proof) transcript->template receive_from_prover(commitment_labels.avm_byte_lookup_table_op_id); commitments.avm_byte_lookup_table_output = transcript->template receive_from_prover(commitment_labels.avm_byte_lookup_table_output); + commitments.avm_main_alu_in_tag = + transcript->template receive_from_prover(commitment_labels.avm_main_alu_in_tag); commitments.avm_main_alu_sel = transcript->template receive_from_prover(commitment_labels.avm_main_alu_sel); commitments.avm_main_bin_op_id = @@ -240,6 +246,8 @@ bool AvmVerifier::verify_proof(const HonkProof& proof) transcript->template receive_from_prover(commitment_labels.avm_main_sel_op_add); commitments.avm_main_sel_op_and = transcript->template receive_from_prover(commitment_labels.avm_main_sel_op_and); + commitments.avm_main_sel_op_cast = + transcript->template receive_from_prover(commitment_labels.avm_main_sel_op_cast); commitments.avm_main_sel_op_div = transcript->template receive_from_prover(commitment_labels.avm_main_sel_op_div); commitments.avm_main_sel_op_eq = diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_cast.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_cast.test.cpp new file mode 100644 index 00000000000..fbb35c11b5e --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_cast.test.cpp @@ -0,0 +1,208 @@ +#include "avm_common.test.hpp" +#include "barretenberg/vm/avm_trace/avm_common.hpp" +#include "barretenberg/vm/tests/helpers.test.hpp" +#include +#include + +namespace tests_avm { +using namespace bb::avm_trace; +using namespace testing; + +class AvmCastTests : public ::testing::Test { + public: + AvmTraceBuilder trace_builder; + + protected: + std::vector trace; + + // TODO(640): The Standard Honk on Grumpkin test suite fails unless the SRS is initialised for every test. + void SetUp() override { srs::init_crs_factory("../srs_db/ignition"); }; + + void gen_trace( + uint128_t const& a, uint32_t src_address, uint32_t dst_address, AvmMemoryTag src_tag, AvmMemoryTag dst_tag) + { + trace_builder.op_set(0, a, src_address, src_tag); + trace_builder.op_cast(0, src_address, dst_address, dst_tag); + trace_builder.return_op(0, 0, 0); + trace = trace_builder.finalize(); + } + + void validate_cast_trace(FF const& a, + FF const& cast_val, + uint32_t src_address, + uint32_t dst_address, + AvmMemoryTag src_tag, + AvmMemoryTag dst_tag + + ) + { + auto row = + std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_cast == FF(1); }); + ASSERT_TRUE(row != trace.end()); + + EXPECT_THAT(*row, + AllOf(Field("sel_op_cast", &Row::avm_main_sel_op_cast, 1), + Field("ia", &Row::avm_main_ia, a), + Field("ib", &Row::avm_main_ib, 0), + Field("ic", &Row::avm_main_ic, cast_val), + Field("r_in_tag", &Row::avm_main_r_in_tag, static_cast(src_tag)), + Field("w_in_tag", &Row::avm_main_w_in_tag, static_cast(dst_tag)), + Field("alu_in_tag", &Row::avm_main_alu_in_tag, static_cast(dst_tag)), + Field("op_a", &Row::avm_main_mem_op_a, 1), + Field("op_c", &Row::avm_main_mem_op_c, 1), + Field("rwa", &Row::avm_main_rwa, 0), + Field("rwc", &Row::avm_main_rwc, 1), + Field("mem_idx_a", &Row::avm_main_mem_idx_a, src_address), + Field("mem_idx_c", &Row::avm_main_mem_idx_c, dst_address), + Field("tag_err", &Row::avm_main_tag_err, 0), + Field("alu_sel", &Row::avm_main_alu_sel, 1), + Field("sel_rng_8", &Row::avm_main_sel_rng_8, 1), + Field("sel_rng_16", &Row::avm_main_sel_rng_16, 1))); + + // Find the corresponding Alu trace row + auto clk = row->avm_main_clk; + auto alu_row = std::ranges::find_if(trace.begin(), trace.end(), [clk](Row r) { return r.avm_alu_clk == clk; }); + ASSERT_TRUE(alu_row != trace.end()); + + EXPECT_THAT(*alu_row, + AllOf(Field("op_cast", &Row::avm_alu_op_cast, 1), + Field("alu_ia", &Row::avm_alu_ia, a), + Field("alu_ib", &Row::avm_alu_ib, 0), + Field("alu_ic", &Row::avm_alu_ic, cast_val), + Field("u8_tag", &Row::avm_alu_u8_tag, dst_tag == AvmMemoryTag::U8), + Field("u16_tag", &Row::avm_alu_u16_tag, dst_tag == AvmMemoryTag::U16), + Field("u32_tag", &Row::avm_alu_u32_tag, dst_tag == AvmMemoryTag::U32), + Field("u64_tag", &Row::avm_alu_u64_tag, dst_tag == AvmMemoryTag::U64), + Field("u128_tag", &Row::avm_alu_u128_tag, dst_tag == AvmMemoryTag::U128), + Field("ff_tag", &Row::avm_alu_ff_tag, dst_tag == AvmMemoryTag::FF), + Field("in_tag", &Row::avm_alu_in_tag, static_cast(dst_tag)), + Field("op_cast_prev", &Row::avm_alu_op_cast_prev, 0), + Field("lookup_selector", &Row::avm_alu_rng_chk_lookup_selector, 1), + Field("alu_sel", &Row::avm_alu_alu_sel, 1))); + + // Check that there is a second ALU row + auto alu_row_next = alu_row + 1; + EXPECT_THAT( + *alu_row_next, + AllOf(Field("op_cast", &Row::avm_alu_op_cast, 0), Field("op_cast_prev", &Row::avm_alu_op_cast_prev, 1))); + + validate_trace(std::move(trace)); + } +}; + +TEST_F(AvmCastTests, basicU8ToU16) +{ + gen_trace(237, 0, 1, AvmMemoryTag::U8, AvmMemoryTag::U16); + validate_cast_trace(237, 237, 0, 1, AvmMemoryTag::U8, AvmMemoryTag::U16); +} + +TEST_F(AvmCastTests, truncationU32ToU8) +{ + gen_trace(876123, 0, 1, AvmMemoryTag::U32, AvmMemoryTag::U8); + validate_cast_trace(876123, 91, 0, 1, AvmMemoryTag::U32, AvmMemoryTag::U8); +} + +TEST_F(AvmCastTests, sameAddressU16ToU8) +{ + gen_trace(1049, 23, 23, AvmMemoryTag::U16, AvmMemoryTag::U8); // M[23] = 1049 + validate_cast_trace(1049, 25, 23, 23, AvmMemoryTag::U16, AvmMemoryTag::U8); +} + +TEST_F(AvmCastTests, basicU64ToFF) +{ + gen_trace(987234987324233324UL, 0, 1, AvmMemoryTag::U64, AvmMemoryTag::FF); + validate_cast_trace(987234987324233324UL, 987234987324233324UL, 0, 1, AvmMemoryTag::U64, AvmMemoryTag::FF); +} + +TEST_F(AvmCastTests, sameTagU128) +{ + uint128_t a = 312; + a = a << 99; + gen_trace(a, 0, 1, AvmMemoryTag::U128, AvmMemoryTag::U128); + validate_cast_trace( + uint256_t::from_uint128(a), FF(uint256_t::from_uint128(a)), 0, 1, AvmMemoryTag::U128, AvmMemoryTag::U128); +} + +TEST_F(AvmCastTests, noTruncationFFToU32) +{ + gen_trace(UINT32_MAX, 4, 9, AvmMemoryTag::FF, AvmMemoryTag::U32); + validate_cast_trace(UINT32_MAX, UINT32_MAX, 4, 9, AvmMemoryTag::FF, AvmMemoryTag::U32); +} + +TEST_F(AvmCastTests, truncationFFToU16ModMinus1) +{ + trace_builder.calldata_copy(0, 0, 1, 0, { FF(FF::modulus - 1) }); + trace_builder.op_cast(0, 0, 1, AvmMemoryTag::U16); + trace_builder.return_op(0, 0, 0); + trace = trace_builder.finalize(); + + validate_cast_trace(FF::modulus - 1, 0, 0, 1, AvmMemoryTag::FF, AvmMemoryTag::U16); +} + +TEST_F(AvmCastTests, truncationFFToU16ModMinus2) +{ + trace_builder.calldata_copy(0, 0, 1, 0, { FF(FF::modulus_minus_two) }); + trace_builder.op_cast(0, 0, 1, AvmMemoryTag::U16); + trace_builder.return_op(0, 0, 0); + trace = trace_builder.finalize(); + + validate_cast_trace(FF::modulus_minus_two, UINT16_MAX, 0, 1, AvmMemoryTag::FF, AvmMemoryTag::U16); +} + +TEST_F(AvmCastTests, truncationU32ToU16) +{ + // 998877665 = OX3B89A9E1 + // Truncated to 16 bits: 0XA9E1 = 43489 + gen_trace(998877665UL, 0, 1, AvmMemoryTag::U32, AvmMemoryTag::U16); + validate_cast_trace(998877665UL, 43489, 0, 1, AvmMemoryTag::U32, AvmMemoryTag::U16); +} + +TEST_F(AvmCastTests, indirectAddrTruncationU64ToU8) +{ + // Indirect addresses. src:0 dst:1 + // Direct addresses. src:10 dst:11 + // Source value: 256'000'000'203 --> truncated to 203 + trace_builder.op_set(0, 10, 0, AvmMemoryTag::U32); + trace_builder.op_set(0, 11, 1, AvmMemoryTag::U32); + trace_builder.op_set(0, 256'000'000'203UL, 10, AvmMemoryTag::U64); + trace_builder.op_cast(3, 0, 1, AvmMemoryTag::U8); + trace_builder.return_op(0, 0, 0); + trace = trace_builder.finalize(); + + validate_cast_trace(256'000'000'203UL, 203, 10, 11, AvmMemoryTag::U64, AvmMemoryTag::U8); +} + +TEST_F(AvmCastTests, indirectAddrWrongResolutionU64ToU8) +{ + // Indirect addresses. src:5 dst:6 + // Direct addresses. src:10 dst:11 + trace_builder.op_set(0, 10, 5, AvmMemoryTag::U8); // Not an address type + trace_builder.op_set(0, 11, 6, AvmMemoryTag::U32); + trace_builder.op_set(0, 4234, 10, AvmMemoryTag::U64); + trace_builder.op_cast(3, 5, 6, AvmMemoryTag::U8); + trace_builder.return_op(0, 0, 0); + trace = trace_builder.finalize(); + + auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_cast == FF(1); }); + ASSERT_TRUE(row != trace.end()); + + EXPECT_THAT(*row, + AllOf(Field("sel_op_cast", &Row::avm_main_sel_op_cast, 1), + Field("r_in_tag", &Row::avm_main_r_in_tag, static_cast(AvmMemoryTag::U64)), + Field("w_in_tag", &Row::avm_main_w_in_tag, static_cast(AvmMemoryTag::U8)), + Field("alu_in_tag", &Row::avm_main_alu_in_tag, static_cast(AvmMemoryTag::U8)), + Field("op_a", &Row::avm_main_mem_op_a, 1), + Field("op_c", &Row::avm_main_mem_op_c, 1), + Field("ind_op_a", &Row::avm_main_ind_op_a, 1), + Field("ind_op_c", &Row::avm_main_ind_op_c, 1), + Field("ind_a", &Row::avm_main_ind_a, 5), + Field("ind_c", &Row::avm_main_ind_c, 6), + Field("rwa", &Row::avm_main_rwa, 0), + Field("rwc", &Row::avm_main_rwc, 1), + Field("alu_sel", &Row::avm_main_alu_sel, 0), // ALU trace not activated + Field("tag_err", &Row::avm_main_tag_err, 1))); // Error activated + + validate_trace(std::move(trace)); +} + +} // namespace tests_avm diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_execution.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_execution.test.cpp index f505eb16ce5..2639e9fb979 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_execution.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_execution.test.cpp @@ -607,6 +607,47 @@ TEST_F(AvmExecutionTests, indMovOpcode) gen_proof_and_validate(bytecode, std::move(trace), {}); } +// Positive test for SET and CAST opcodes +TEST_F(AvmExecutionTests, setAndCastOpcodes) +{ + std::string bytecode_hex = to_hex(OpCode::SET) + // opcode SET + "00" // Indirect flag + "02" // U16 + "B813" // val 47123 + "00000011" // dst_offset 17 + + to_hex(OpCode::CAST) + // opcode CAST + "00" // Indirect flag + "01" // U8 + "00000011" // addr a + "00000012" // addr casted a + + to_hex(OpCode::RETURN) + // opcode RETURN + "00" // Indirect flag + "00000000" // ret offset 0 + "00000000"; // ret size 0 + + auto bytecode = hex_to_bytes(bytecode_hex); + auto instructions = Deserialization::parse(bytecode); + + ASSERT_THAT(instructions, SizeIs(3)); + + // SUB + EXPECT_THAT(instructions.at(1), + AllOf(Field(&Instruction::op_code, OpCode::CAST), + Field(&Instruction::operands, + ElementsAre(VariantWith(0), + VariantWith(AvmMemoryTag::U8), + VariantWith(17), + VariantWith(18))))); + + auto trace = Execution::gen_trace(instructions); + + // Find the first row enabling the cast selector + auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_cast == 1; }); + EXPECT_EQ(row->avm_main_ic, 19); // 0XB813 --> 0X13 = 19 + + gen_proof_and_validate(bytecode, std::move(trace), {}); +} + // Negative test detecting an invalid opcode byte. TEST_F(AvmExecutionTests, invalidOpcode) { From bdb59cb4dc2c691798be3d1ef46d422f8fcd930d Mon Sep 17 00:00:00 2001 From: ludamad Date: Thu, 18 Apr 2024 11:45:53 -0400 Subject: [PATCH 018/102] chore(ci): Notify on ARM failures (#5847) --- .github/workflows/ci-arm.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/.github/workflows/ci-arm.yml b/.github/workflows/ci-arm.yml index f9f2929eedb..84e4cc7dda1 100644 --- a/.github/workflows/ci-arm.yml +++ b/.github/workflows/ci-arm.yml @@ -58,3 +58,18 @@ jobs: working-directory: ./yarn-project/end-to-end/ timeout-minutes: 15 run: earthly -P --no-output +uniswap-trade-on-l1-from-l2 --e2e_mode=cache + + notify: + needs: [e2e] + runs-on: ubuntu-latest + if: ${{ github.ref == 'refs/heads/master' && failure() }} + steps: + - name: Send notification to aztec3-ci channel if workflow failed on master + uses: slackapi/slack-github-action@v1.25.0 + with: + payload: | + { + "url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" + } + env: + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_NOTIFY_WORKFLOW_TRIGGER_URL }} From f9a843a00ff41ef39b958ae7f5a24bdbc1b1add2 Mon Sep 17 00:00:00 2001 From: PhilWindle <60546371+PhilWindle@users.noreply.github.com> Date: Thu, 18 Apr 2024 18:09:58 +0100 Subject: [PATCH 019/102] feat: Prove the public kernel circuits (#5778) This PR introduces public kernel proofs. --- yarn-project/prover-client/Dockerfile.test | 11 +- yarn-project/prover-client/package.json | 3 +- yarn-project/prover-client/src/bb/cli.ts | 29 +++- yarn-project/prover-client/src/bb/execute.ts | 26 +++ .../prover-client/src/mocks/fixtures.ts | 2 +- .../prover-client/src/mocks/test_context.ts | 153 ++++++++++++++++++ .../orchestrator/orchestrator_errors.test.ts | 137 ++++++++-------- .../orchestrator_failures.test.ts | 69 +++----- .../orchestrator_lifecycle.test.ts | 106 ++++++------ .../orchestrator_mixed_blocks.test.ts | 73 +++------ .../orchestrator_mixed_blocks_2.test.ts | 73 +++------ ...rchestrator_multi_public_functions.test.ts | 66 ++++++++ .../orchestrator_multiple_blocks.test.ts | 60 +++---- .../orchestrator_public_functions.test.ts | 110 +++---------- .../orchestrator_single_blocks.test.ts | 105 +++++------- .../src/prover/bb_prover.test.ts | 105 ------------ .../prover-client/src/prover/bb_prover.ts | 108 +++++++++---- .../src/prover/bb_prover_base_rollup.test.ts | 39 +++++ .../src/prover/bb_prover_full_rollup.test.ts | 62 +++++++ .../src/prover/bb_prover_parity.test.ts | 69 ++++++++ .../prover/bb_prover_public_kernel.test.ts | 91 +++++++++++ .../prover-client/src/prover/interface.ts | 47 +++++- .../src/prover/test_circuit_prover.ts | 44 +---- 23 files changed, 922 insertions(+), 666 deletions(-) create mode 100644 yarn-project/prover-client/src/mocks/test_context.ts create mode 100644 yarn-project/prover-client/src/orchestrator/orchestrator_multi_public_functions.test.ts delete mode 100644 yarn-project/prover-client/src/prover/bb_prover.test.ts create mode 100644 yarn-project/prover-client/src/prover/bb_prover_base_rollup.test.ts create mode 100644 yarn-project/prover-client/src/prover/bb_prover_full_rollup.test.ts create mode 100644 yarn-project/prover-client/src/prover/bb_prover_parity.test.ts create mode 100644 yarn-project/prover-client/src/prover/bb_prover_public_kernel.test.ts diff --git a/yarn-project/prover-client/Dockerfile.test b/yarn-project/prover-client/Dockerfile.test index f267727de46..173b71a893a 100644 --- a/yarn-project/prover-client/Dockerfile.test +++ b/yarn-project/prover-client/Dockerfile.test @@ -32,7 +32,16 @@ RUN ln -s /usr/src/yarn-project/node_modules /usr/src/node_modules ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true RUN ./bootstrap.sh -RUN cd prover-client && ACVM_WORKING_DIRECTORY='/tmp/acvm' BB_WORKING_DIRECTORY='/tmp/bb' yarn test + +# Generate the server protocol circuit verification keys and run the prover tests +RUN cd prover-client && \ + mkdir '/tmp/bb' && \ + ACVM_WORKING_DIRECTORY='/tmp/acvm' \ + BB_WORKING_DIRECTORY='/tmp/bb' \ + BB_BINARY_PATH='/usr/src/barretenberg/cpp/build/bin/bb' \ + ACVM_BINARY_PATH='/usr/src/noir/noir-repo/target/release/acvm' \ + LOG_LEVEL=info \ + yarn generate-and-test # Avoid pushing some huge container back to ecr. FROM scratch diff --git a/yarn-project/prover-client/package.json b/yarn-project/prover-client/package.json index ca938c16f86..989fd4ff340 100644 --- a/yarn-project/prover-client/package.json +++ b/yarn-project/prover-client/package.json @@ -20,7 +20,8 @@ "formatting": "run -T prettier --check ./src && run -T eslint ./src", "formatting:fix": "run -T eslint --fix ./src && run -T prettier -w ./src", "bb": "node --no-warnings ./dest/bb/index.js", - "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --passWithNoTests" + "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --passWithNoTests", + "generate-and-test": "yarn bb-cli write-server-vks && yarn test" }, "inherits": [ "../package.common.json" diff --git a/yarn-project/prover-client/src/bb/cli.ts b/yarn-project/prover-client/src/bb/cli.ts index 5358355d6ae..64a1b5d8be0 100644 --- a/yarn-project/prover-client/src/bb/cli.ts +++ b/yarn-project/prover-client/src/bb/cli.ts @@ -4,7 +4,7 @@ import { type ProtocolArtifact, ProtocolCircuitArtifacts } from '@aztec/noir-pro import { Command } from 'commander'; import * as fs from 'fs/promises'; -import { generateKeyForNoirCircuit } from './execute.js'; +import { generateAllServerVks, generateKeyForNoirCircuit } from './execute.js'; const { BB_WORKING_DIRECTORY, BB_BINARY_PATH } = process.env; @@ -26,7 +26,7 @@ export function getProgram(log: LogFn): Command { }); program - .command('write_pk') + .command('write-pk') .description('Generates the proving key for the specified circuit') .requiredOption( '-w, --working-directory ', @@ -42,7 +42,7 @@ export function getProgram(log: LogFn): Command { return; } try { - await fs.access(options.workingDirectory); + await fs.access(options.workingDirectory, fs.constants.W_OK); } catch (error) { log(`Working directory does not exist`); return; @@ -58,7 +58,7 @@ export function getProgram(log: LogFn): Command { }); program - .command('write_vk') + .command('write-vk') .description('Generates the verification key for the specified circuit') .requiredOption( '-w, --working-directory ', @@ -74,7 +74,7 @@ export function getProgram(log: LogFn): Command { return; } try { - await fs.access(options.workingDirectory); + await fs.access(options.workingDirectory, fs.constants.W_OK); } catch (error) { log(`Working directory does not exist`); return; @@ -88,5 +88,24 @@ export function getProgram(log: LogFn): Command { log, ); }); + + program + .command('write-server-vks') + .description('Generates all verification keys require for server protocol circuits') + .requiredOption( + '-w, --working-directory ', + 'The directory to use for writing the keys', + BB_WORKING_DIRECTORY, + ) + .requiredOption('-b, --bb-path ', 'The path to the BB binary', BB_BINARY_PATH) + .action(async options => { + try { + await fs.access(options.workingDirectory, fs.constants.W_OK); + } catch (error) { + log(`Working directory does not exist`); + return; + } + await generateAllServerVks(options.bbPath, options.workingDirectory, log); + }); return program; } diff --git a/yarn-project/prover-client/src/bb/execute.ts b/yarn-project/prover-client/src/bb/execute.ts index 87cfba93af7..ebf24b50c81 100644 --- a/yarn-project/prover-client/src/bb/execute.ts +++ b/yarn-project/prover-client/src/bb/execute.ts @@ -6,6 +6,8 @@ import { type NoirCompiledCircuit } from '@aztec/types/noir'; import * as proc from 'child_process'; import * as fs from 'fs/promises'; +import { BBNativeRollupProver, type BBProverConfig } from '../prover/bb_prover.js'; + export enum BB_RESULT { SUCCESS, FAILURE, @@ -256,3 +258,27 @@ export async function verifyProof( return { status: BB_RESULT.FAILURE, reason: `${error}` }; } } + +/** + * Used for generating all verification keys required by server protocol circuits + * @param pathToBB - The full path to the bb binary + * @param workingDirectory - The directory to be used for the keys + * @param log - A logging function + */ +export async function generateAllServerVks(pathToBB: string, workingDirectory: string, log: LogFn) { + const bbConfig: BBProverConfig = { + bbBinaryPath: pathToBB, + bbWorkingDirectory: workingDirectory, + + // These aren't needed for this + acvmBinaryPath: '', + acvmWorkingDirectory: '', + circuitFilter: [], + }; + // This will generate all of the server circuit verification keys for us + try { + await BBNativeRollupProver.generateVerificationKeys(bbConfig); + } catch (error) { + log(`Failed to generate verification keys: ${error}`); + } +} diff --git a/yarn-project/prover-client/src/mocks/fixtures.ts b/yarn-project/prover-client/src/mocks/fixtures.ts index 6d691fe4ce7..065c5296edf 100644 --- a/yarn-project/prover-client/src/mocks/fixtures.ts +++ b/yarn-project/prover-client/src/mocks/fixtures.ts @@ -44,7 +44,7 @@ const { } = process.env; // Determines if we have access to the bb binary and a tmp folder for temp files -export const getConfig = async (logger: DebugLogger) => { +export const getEnvironmentConfig = async (logger: DebugLogger) => { try { const expectedBBPath = BB_BINARY_PATH ? BB_BINARY_PATH diff --git a/yarn-project/prover-client/src/mocks/test_context.ts b/yarn-project/prover-client/src/mocks/test_context.ts new file mode 100644 index 00000000000..82d278906c1 --- /dev/null +++ b/yarn-project/prover-client/src/mocks/test_context.ts @@ -0,0 +1,153 @@ +import { type BlockProver, type ProcessedTx, type Tx, type TxValidator } from '@aztec/circuit-types'; +import { GlobalVariables, Header } from '@aztec/circuits.js'; +import { type DebugLogger } from '@aztec/foundation/log'; +import { openTmpStore } from '@aztec/kv-store/utils'; +import { + type ContractsDataSourcePublicDB, + type PublicExecution, + type PublicExecutionResult, + PublicExecutionResultBuilder, + type PublicExecutor, + PublicProcessor, + RealPublicKernelCircuitSimulator, + type SimulationProvider, + WASMSimulator, + type WorldStatePublicDB, +} from '@aztec/simulator'; +import { type MerkleTreeOperations, MerkleTrees } from '@aztec/world-state'; + +import * as fs from 'fs/promises'; +import { type MockProxy, mock } from 'jest-mock-extended'; + +import { ProvingOrchestrator } from '../orchestrator/orchestrator.js'; +import { type BBProverConfig } from '../prover/bb_prover.js'; +import { type CircuitProver } from '../prover/interface.js'; +import { TestCircuitProver } from '../prover/test_circuit_prover.js'; +import { getEnvironmentConfig, getSimulationProvider, makeGlobals } from './fixtures.js'; + +export class TestContext { + constructor( + public publicExecutor: MockProxy, + public publicContractsDB: MockProxy, + public publicWorldStateDB: MockProxy, + public publicProcessor: PublicProcessor, + public simulationProvider: SimulationProvider, + public globalVariables: GlobalVariables, + public actualDb: MerkleTreeOperations, + public prover: CircuitProver, + public orchestrator: ProvingOrchestrator, + public blockNumber: number, + public directoriesToCleanup: string[], + public logger: DebugLogger, + ) {} + + static async new( + logger: DebugLogger, + createProver: (bbConfig: BBProverConfig) => Promise = _ => + Promise.resolve(new TestCircuitProver(new WASMSimulator())), + blockNumber = 3, + ) { + const globalVariables = makeGlobals(blockNumber); + + const publicExecutor = mock(); + const publicContractsDB = mock(); + const publicWorldStateDB = mock(); + const publicKernel = new RealPublicKernelCircuitSimulator(new WASMSimulator()); + const actualDb = await MerkleTrees.new(openTmpStore()).then(t => t.asLatest()); + const processor = new PublicProcessor( + actualDb, + publicExecutor, + publicKernel, + GlobalVariables.empty(), + Header.empty(), + publicContractsDB, + publicWorldStateDB, + ); + + let localProver: CircuitProver; + const config = await getEnvironmentConfig(logger); + const simulationProvider = await getSimulationProvider({ + acvmWorkingDirectory: config?.acvmWorkingDirectory, + acvmBinaryPath: config?.expectedAcvmPath, + }); + if (!config) { + localProver = new TestCircuitProver(simulationProvider); + } else { + const bbConfig: BBProverConfig = { + acvmBinaryPath: config.expectedAcvmPath, + acvmWorkingDirectory: config.acvmWorkingDirectory, + bbBinaryPath: config.expectedBBPath, + bbWorkingDirectory: config.bbWorkingDirectory, + }; + localProver = await createProver(bbConfig); + } + + const orchestrator = await ProvingOrchestrator.new(actualDb, localProver); + + return new this( + publicExecutor, + publicContractsDB, + publicWorldStateDB, + processor, + simulationProvider, + globalVariables, + actualDb, + localProver, + orchestrator, + blockNumber, + [config?.directoryToCleanup ?? ''], + logger, + ); + } + + async cleanup() { + await this.orchestrator.stop(); + for (const dir of this.directoriesToCleanup.filter(x => x !== '')) { + await fs.rm(dir, { recursive: true, force: true }); + } + } + + public async processPublicFunctions( + txs: Tx[], + maxTransactions: number, + blockProver?: BlockProver, + txValidator?: TxValidator, + ) { + const defaultExecutorImplementation = (execution: PublicExecution, _1: GlobalVariables, _2?: number) => { + for (const tx of txs) { + for (const request of tx.enqueuedPublicFunctionCalls) { + if (execution.contractAddress.equals(request.contractAddress)) { + const result = PublicExecutionResultBuilder.fromPublicCallRequest({ request }).build(); + // result.unencryptedLogs = tx.unencryptedLogs.functionLogs[0]; + return Promise.resolve(result); + } + } + } + throw new Error(`Unexpected execution request: ${execution}`); + }; + return await this.processPublicFunctionsWithMockExecutorImplementation( + txs, + maxTransactions, + blockProver, + txValidator, + defaultExecutorImplementation, + ); + } + + public async processPublicFunctionsWithMockExecutorImplementation( + txs: Tx[], + maxTransactions: number, + blockProver?: BlockProver, + txValidator?: TxValidator, + executorMock?: ( + execution: PublicExecution, + globalVariables: GlobalVariables, + sideEffectCounter?: number, + ) => Promise, + ) { + if (executorMock) { + this.publicExecutor.simulate.mockImplementation(executorMock); + } + return await this.publicProcessor.process(txs, maxTransactions, blockProver, txValidator); + } +} diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator_errors.test.ts b/yarn-project/prover-client/src/orchestrator/orchestrator_errors.test.ts index 1cd597e61a9..42bb5a177d0 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator_errors.test.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator_errors.test.ts @@ -1,136 +1,115 @@ import { PROVING_STATUS } from '@aztec/circuit-types'; -import { Fr, type GlobalVariables } from '@aztec/circuits.js'; +import { Fr } from '@aztec/circuits.js'; import { createDebugLogger } from '@aztec/foundation/log'; -import { openTmpStore } from '@aztec/kv-store/utils'; -import { type MerkleTreeOperations, MerkleTrees } from '@aztec/world-state'; import { type MemDown, default as memdown } from 'memdown'; -import { - getConfig, - getSimulationProvider, - makeBloatedProcessedTx, - makeEmptyProcessedTestTx, - makeGlobals, -} from '../mocks/fixtures.js'; -import { TestCircuitProver } from '../prover/test_circuit_prover.js'; -import { ProvingOrchestrator } from './orchestrator.js'; +import { makeBloatedProcessedTx, makeEmptyProcessedTestTx } from '../mocks/fixtures.js'; +import { TestContext } from '../mocks/test_context.js'; export const createMemDown = () => (memdown as any)() as MemDown; -const logger = createDebugLogger('aztec:orchestrator-test'); +const logger = createDebugLogger('aztec:orchestrator-errors'); -describe('prover/orchestrator', () => { - let builder: ProvingOrchestrator; - let builderDb: MerkleTreeOperations; - - let prover: TestCircuitProver; - - let blockNumber: number; - - let globalVariables: GlobalVariables; +describe('prover/orchestrator/errors', () => { + let context: TestContext; beforeEach(async () => { - blockNumber = 3; - globalVariables = makeGlobals(blockNumber); - - const acvmConfig = await getConfig(logger); - const simulationProvider = await getSimulationProvider({ - acvmWorkingDirectory: acvmConfig?.acvmWorkingDirectory, - acvmBinaryPath: acvmConfig?.expectedAcvmPath, - }); - prover = new TestCircuitProver(simulationProvider); - - builderDb = await MerkleTrees.new(openTmpStore()).then(t => t.asLatest()); - builder = new ProvingOrchestrator(builderDb, prover, 1); + context = await TestContext.new(logger); }, 20_000); - describe('errors', () => { - beforeEach(async () => { - builder = await ProvingOrchestrator.new(builderDb, prover); - }); + afterEach(async () => { + await context.cleanup(); + }); - afterEach(async () => { - await builder.stop(); - }); + afterAll(async () => {}); + describe('errors', () => { it('throws if adding too many transactions', async () => { const txs = await Promise.all([ - makeBloatedProcessedTx(builderDb, 1), - makeBloatedProcessedTx(builderDb, 2), - makeBloatedProcessedTx(builderDb, 3), - makeBloatedProcessedTx(builderDb, 4), + makeBloatedProcessedTx(context.actualDb, 1), + makeBloatedProcessedTx(context.actualDb, 2), + makeBloatedProcessedTx(context.actualDb, 3), + makeBloatedProcessedTx(context.actualDb, 4), ]); - const blockTicket = await builder.startNewBlock( + const blockTicket = await context.orchestrator.startNewBlock( txs.length, - globalVariables, + context.globalVariables, [], - await makeEmptyProcessedTestTx(builderDb), + await makeEmptyProcessedTestTx(context.actualDb), ); for (const tx of txs) { - await builder.addNewTx(tx); + await context.orchestrator.addNewTx(tx); } - await expect(async () => await builder.addNewTx(await makeEmptyProcessedTestTx(builderDb))).rejects.toThrow( - 'Rollup not accepting further transactions', - ); + await expect( + async () => await context.orchestrator.addNewTx(await makeEmptyProcessedTestTx(context.actualDb)), + ).rejects.toThrow('Rollup not accepting further transactions'); const result = await blockTicket.provingPromise; expect(result.status).toBe(PROVING_STATUS.SUCCESS); - const finalisedBlock = await builder.finaliseBlock(); + const finalisedBlock = await context.orchestrator.finaliseBlock(); - expect(finalisedBlock.block.number).toEqual(blockNumber); + expect(finalisedBlock.block.number).toEqual(context.blockNumber); }, 30_000); it('throws if adding a transaction before start', async () => { - await expect(async () => await builder.addNewTx(await makeEmptyProcessedTestTx(builderDb))).rejects.toThrow( - `Invalid proving state, call startNewBlock before adding transactions`, - ); + await expect( + async () => await context.orchestrator.addNewTx(await makeEmptyProcessedTestTx(context.actualDb)), + ).rejects.toThrow(`Invalid proving state, call startNewBlock before adding transactions`); }, 1000); it('throws if completing a block before start', async () => { - await expect(async () => await builder.setBlockCompleted()).rejects.toThrow( + await expect(async () => await context.orchestrator.setBlockCompleted()).rejects.toThrow( 'Invalid proving state, call startNewBlock before adding transactions or completing the block', ); }, 1000); it('throws if finalising an incomplete block', async () => { - await expect(async () => await builder.finaliseBlock()).rejects.toThrow( + await expect(async () => await context.orchestrator.finaliseBlock()).rejects.toThrow( 'Invalid proving state, a block must be proven before it can be finalised', ); }, 1000); it('throws if finalising an already finalised block', async () => { - const txs = await Promise.all([makeEmptyProcessedTestTx(builderDb), makeEmptyProcessedTestTx(builderDb)]); + const txs = await Promise.all([ + makeEmptyProcessedTestTx(context.actualDb), + makeEmptyProcessedTestTx(context.actualDb), + ]); - const blockTicket = await builder.startNewBlock( + const blockTicket = await context.orchestrator.startNewBlock( txs.length, - globalVariables, + context.globalVariables, [], - await makeEmptyProcessedTestTx(builderDb), + await makeEmptyProcessedTestTx(context.actualDb), ); for (const tx of txs) { - await builder.addNewTx(tx); + await context.orchestrator.addNewTx(tx); } const result = await blockTicket.provingPromise; expect(result.status).toBe(PROVING_STATUS.SUCCESS); - const finalisedBlock = await builder.finaliseBlock(); - expect(finalisedBlock.block.number).toEqual(blockNumber); - await expect(async () => await builder.finaliseBlock()).rejects.toThrow('Block already finalised'); + const finalisedBlock = await context.orchestrator.finaliseBlock(); + expect(finalisedBlock.block.number).toEqual(context.blockNumber); + await expect(async () => await context.orchestrator.finaliseBlock()).rejects.toThrow('Block already finalised'); }, 60000); it('throws if adding to a cancelled block', async () => { - await builder.startNewBlock(2, globalVariables, [], await makeEmptyProcessedTestTx(builderDb)); + await context.orchestrator.startNewBlock( + 2, + context.globalVariables, + [], + await makeEmptyProcessedTestTx(context.actualDb), + ); - builder.cancelBlock(); + context.orchestrator.cancelBlock(); - await expect(async () => await builder.addNewTx(await makeEmptyProcessedTestTx(builderDb))).rejects.toThrow( - 'Rollup not accepting further transactions', - ); + await expect( + async () => await context.orchestrator.addNewTx(await makeEmptyProcessedTestTx(context.actualDb)), + ).rejects.toThrow('Rollup not accepting further transactions'); }, 10000); it.each([[-4], [0], [1], [3], [8.1], [7]] as const)( @@ -138,7 +117,12 @@ describe('prover/orchestrator', () => { async (blockSize: number) => { await expect( async () => - await builder.startNewBlock(blockSize, globalVariables, [], await makeEmptyProcessedTestTx(builderDb)), + await context.orchestrator.startNewBlock( + blockSize, + context.globalVariables, + [], + await makeEmptyProcessedTestTx(context.actualDb), + ), ).rejects.toThrow(`Length of txs for the block should be a power of two and at least two (got ${blockSize})`); }, ); @@ -148,7 +132,12 @@ describe('prover/orchestrator', () => { const l1ToL2Messages = new Array(100).fill(new Fr(0n)); await expect( async () => - await builder.startNewBlock(2, globalVariables, l1ToL2Messages, await makeEmptyProcessedTestTx(builderDb)), + await context.orchestrator.startNewBlock( + 2, + context.globalVariables, + l1ToL2Messages, + await makeEmptyProcessedTestTx(context.actualDb), + ), ).rejects.toThrow('Too many L1 to L2 messages'); }); }); diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator_failures.test.ts b/yarn-project/prover-client/src/orchestrator/orchestrator_failures.test.ts index 15c6210f44e..1b9b0e28614 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator_failures.test.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator_failures.test.ts @@ -1,57 +1,42 @@ -import { PROVING_STATUS, type ProcessedTx } from '@aztec/circuit-types'; -import { Fr, type GlobalVariables } from '@aztec/circuits.js'; +import { PROVING_STATUS } from '@aztec/circuit-types'; import { createDebugLogger } from '@aztec/foundation/log'; -import { openTmpStore } from '@aztec/kv-store/utils'; import { WASMSimulator } from '@aztec/simulator'; -import { type MerkleTreeOperations, MerkleTrees } from '@aztec/world-state'; import { jest } from '@jest/globals'; import { type MemDown, default as memdown } from 'memdown'; -import { getConfig, getSimulationProvider, makeEmptyProcessedTx, makeGlobals } from '../mocks/fixtures.js'; +import { makeEmptyProcessedTestTx } from '../mocks/fixtures.js'; +import { TestContext } from '../mocks/test_context.js'; import { type CircuitProver } from '../prover/index.js'; import { TestCircuitProver } from '../prover/test_circuit_prover.js'; import { ProvingOrchestrator } from './orchestrator.js'; export const createMemDown = () => (memdown as any)() as MemDown; -const logger = createDebugLogger('aztec:orchestrator-test'); +const logger = createDebugLogger('aztec:orchestrator-failures'); -describe('prover/orchestrator', () => { - let builder: ProvingOrchestrator; - let builderDb: MerkleTreeOperations; - - let prover: TestCircuitProver; - - let blockNumber: number; - - let globalVariables: GlobalVariables; - - const makeEmptyProcessedTestTx = (): Promise => { - return makeEmptyProcessedTx(builderDb, Fr.ZERO, Fr.ZERO); - }; +describe('prover/orchestrator/failures', () => { + let context: TestContext; + let orchestrator: ProvingOrchestrator; beforeEach(async () => { - blockNumber = 3; - globalVariables = makeGlobals(blockNumber); - - const acvmConfig = await getConfig(logger); - const simulationProvider = await getSimulationProvider({ - acvmWorkingDirectory: acvmConfig?.acvmWorkingDirectory, - acvmBinaryPath: acvmConfig?.expectedAcvmPath, - }); - prover = new TestCircuitProver(simulationProvider); - - builderDb = await MerkleTrees.new(openTmpStore()).then(t => t.asLatest()); - builder = new ProvingOrchestrator(builderDb, prover, 1); + context = await TestContext.new(logger); }, 20_000); + afterEach(async () => { + await context.cleanup(); + }); + describe('error handling', () => { let mockProver: CircuitProver; beforeEach(async () => { mockProver = new TestCircuitProver(new WASMSimulator()); - builder = await ProvingOrchestrator.new(builderDb, mockProver); + orchestrator = await ProvingOrchestrator.new(context.actualDb, mockProver); + }); + + afterEach(async () => { + await orchestrator.stop(); }); it.each([ @@ -90,29 +75,25 @@ describe('prover/orchestrator', () => { async (message: string, fn: () => void) => { fn(); const txs = await Promise.all([ - makeEmptyProcessedTestTx(), - makeEmptyProcessedTestTx(), - makeEmptyProcessedTestTx(), - makeEmptyProcessedTestTx(), + makeEmptyProcessedTestTx(context.actualDb), + makeEmptyProcessedTestTx(context.actualDb), + makeEmptyProcessedTestTx(context.actualDb), + makeEmptyProcessedTestTx(context.actualDb), ]); - const blockTicket = await builder.startNewBlock( + const blockTicket = await orchestrator.startNewBlock( txs.length, - globalVariables, + context.globalVariables, [], - await makeEmptyProcessedTestTx(), + await makeEmptyProcessedTestTx(context.actualDb), ); for (const tx of txs) { - await builder.addNewTx(tx); + await orchestrator.addNewTx(tx); } await expect(blockTicket.provingPromise).resolves.toEqual({ status: PROVING_STATUS.FAILURE, reason: message }); }, 60000, ); - - afterEach(async () => { - await builder.stop(); - }); }); }); diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator_lifecycle.test.ts b/yarn-project/prover-client/src/orchestrator/orchestrator_lifecycle.test.ts index 27108f89e67..bfffd42382f 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator_lifecycle.test.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator_lifecycle.test.ts @@ -3,74 +3,56 @@ import { type GlobalVariables, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP } from '@azte import { fr } from '@aztec/circuits.js/testing'; import { range } from '@aztec/foundation/array'; import { createDebugLogger } from '@aztec/foundation/log'; -import { openTmpStore } from '@aztec/kv-store/utils'; -import { type MerkleTreeOperations, MerkleTrees } from '@aztec/world-state'; import { type MemDown, default as memdown } from 'memdown'; -import { - getConfig, - getSimulationProvider, - makeBloatedProcessedTx, - makeEmptyProcessedTestTx, - makeGlobals, -} from '../mocks/fixtures.js'; -import { TestCircuitProver } from '../prover/test_circuit_prover.js'; -import { ProvingOrchestrator } from './orchestrator.js'; +import { makeBloatedProcessedTx, makeEmptyProcessedTestTx, makeGlobals } from '../mocks/fixtures.js'; +import { TestContext } from '../mocks/test_context.js'; export const createMemDown = () => (memdown as any)() as MemDown; -const logger = createDebugLogger('aztec:orchestrator-test'); +const logger = createDebugLogger('aztec:orchestrator-lifecycle'); -describe('prover/orchestrator', () => { - let builder: ProvingOrchestrator; - let builderDb: MerkleTreeOperations; - - let prover: TestCircuitProver; +describe('prover/orchestrator/lifecycle', () => { + let context: TestContext; beforeEach(async () => { - const acvmConfig = await getConfig(logger); - const simulationProvider = await getSimulationProvider({ - acvmWorkingDirectory: acvmConfig?.acvmWorkingDirectory, - acvmBinaryPath: acvmConfig?.expectedAcvmPath, - }); - prover = new TestCircuitProver(simulationProvider); - - builderDb = await MerkleTrees.new(openTmpStore()).then(t => t.asLatest()); - builder = new ProvingOrchestrator(builderDb, prover, 1); + context = await TestContext.new(logger); }, 20_000); - describe('lifecycle', () => { - beforeEach(async () => { - builder = await ProvingOrchestrator.new(builderDb, prover); - }); - - afterEach(async () => { - await builder.stop(); - }); + afterEach(async () => { + await context.cleanup(); + }); + describe('lifecycle', () => { it('cancels current block and switches to new ones', async () => { - const txs1 = await Promise.all([makeBloatedProcessedTx(builderDb, 1), makeBloatedProcessedTx(builderDb, 2)]); + const txs1 = await Promise.all([ + makeBloatedProcessedTx(context.actualDb, 1), + makeBloatedProcessedTx(context.actualDb, 2), + ]); - const txs2 = await Promise.all([makeBloatedProcessedTx(builderDb, 3), makeBloatedProcessedTx(builderDb, 4)]); + const txs2 = await Promise.all([ + makeBloatedProcessedTx(context.actualDb, 3), + makeBloatedProcessedTx(context.actualDb, 4), + ]); const globals1: GlobalVariables = makeGlobals(100); const globals2: GlobalVariables = makeGlobals(101); const l1ToL2Messages = range(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, 1 + 0x400).map(fr); - const blockTicket1 = await builder.startNewBlock( + const blockTicket1 = await context.orchestrator.startNewBlock( 2, globals1, l1ToL2Messages, - await makeEmptyProcessedTestTx(builderDb), + await makeEmptyProcessedTestTx(context.actualDb), ); - await builder.addNewTx(txs1[0]); - await builder.addNewTx(txs1[1]); + await context.orchestrator.addNewTx(txs1[0]); + await context.orchestrator.addNewTx(txs1[1]); // Now we cancel the block. The first block will come to a stop as and when current proofs complete - builder.cancelBlock(); + context.orchestrator.cancelBlock(); const result1 = await blockTicket1.provingPromise; @@ -80,55 +62,61 @@ describe('prover/orchestrator', () => { expect((result1 as ProvingFailure).reason).toBe('Proving cancelled'); } - await builderDb.rollback(); + await context.actualDb.rollback(); - const blockTicket2 = await builder.startNewBlock( + const blockTicket2 = await context.orchestrator.startNewBlock( 2, globals2, l1ToL2Messages, - await makeEmptyProcessedTestTx(builderDb), + await makeEmptyProcessedTestTx(context.actualDb), ); - await builder.addNewTx(txs2[0]); - await builder.addNewTx(txs2[1]); + await context.orchestrator.addNewTx(txs2[0]); + await context.orchestrator.addNewTx(txs2[1]); const result2 = await blockTicket2.provingPromise; expect(result2.status).toBe(PROVING_STATUS.SUCCESS); - const finalisedBlock = await builder.finaliseBlock(); + const finalisedBlock = await context.orchestrator.finaliseBlock(); expect(finalisedBlock.block.number).toEqual(101); }, 20000); it('automatically cancels an incomplete block when starting a new one', async () => { - const txs1 = await Promise.all([makeBloatedProcessedTx(builderDb, 1), makeBloatedProcessedTx(builderDb, 2)]); + const txs1 = await Promise.all([ + makeBloatedProcessedTx(context.actualDb, 1), + makeBloatedProcessedTx(context.actualDb, 2), + ]); - const txs2 = await Promise.all([makeBloatedProcessedTx(builderDb, 3), makeBloatedProcessedTx(builderDb, 4)]); + const txs2 = await Promise.all([ + makeBloatedProcessedTx(context.actualDb, 3), + makeBloatedProcessedTx(context.actualDb, 4), + ]); const globals1: GlobalVariables = makeGlobals(100); const globals2: GlobalVariables = makeGlobals(101); const l1ToL2Messages = range(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, 1 + 0x400).map(fr); - const blockTicket1 = await builder.startNewBlock( + const blockTicket1 = await context.orchestrator.startNewBlock( 2, globals1, l1ToL2Messages, - await makeEmptyProcessedTestTx(builderDb), + await makeEmptyProcessedTestTx(context.actualDb), ); - await builder.addNewTx(txs1[0]); + await context.orchestrator.addNewTx(txs1[0]); - await builderDb.rollback(); + await context.actualDb.rollback(); - const blockTicket2 = await builder.startNewBlock( + const blockTicket2 = await context.orchestrator.startNewBlock( 2, globals2, l1ToL2Messages, - await makeEmptyProcessedTestTx(builderDb), + await makeEmptyProcessedTestTx(context.actualDb), ); - await builder.addNewTx(txs2[0]); - await builder.addNewTx(txs2[1]); + await context.orchestrator.addNewTx(txs2[0]); + await context.orchestrator.addNewTx(txs2[1]); const result1 = await blockTicket1.provingPromise; expect(result1.status).toBe(PROVING_STATUS.FAILURE); @@ -136,9 +124,9 @@ describe('prover/orchestrator', () => { const result2 = await blockTicket2.provingPromise; expect(result2.status).toBe(PROVING_STATUS.SUCCESS); - const finalisedBlock = await builder.finaliseBlock(); + const finalisedBlock = await context.orchestrator.finaliseBlock(); expect(finalisedBlock.block.number).toEqual(101); - }, 20000); + }, 60000); }); }); diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator_mixed_blocks.test.ts b/yarn-project/prover-client/src/orchestrator/orchestrator_mixed_blocks.test.ts index 0277ae0664c..7191c868466 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator_mixed_blocks.test.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator_mixed_blocks.test.ts @@ -1,89 +1,58 @@ import { PROVING_STATUS } from '@aztec/circuit-types'; -import { type GlobalVariables, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP } from '@aztec/circuits.js'; +import { NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP } from '@aztec/circuits.js'; import { fr } from '@aztec/circuits.js/testing'; import { range } from '@aztec/foundation/array'; import { createDebugLogger } from '@aztec/foundation/log'; -import { openTmpStore } from '@aztec/kv-store/utils'; -import { type MerkleTreeOperations, MerkleTrees } from '@aztec/world-state'; import { type MemDown, default as memdown } from 'memdown'; -import { - getConfig, - getSimulationProvider, - makeBloatedProcessedTx, - makeEmptyProcessedTestTx, - makeGlobals, -} from '../mocks/fixtures.js'; -import { TestCircuitProver } from '../prover/test_circuit_prover.js'; -import { ProvingOrchestrator } from './orchestrator.js'; +import { makeBloatedProcessedTx, makeEmptyProcessedTestTx } from '../mocks/fixtures.js'; +import { TestContext } from '../mocks/test_context.js'; export const createMemDown = () => (memdown as any)() as MemDown; -const logger = createDebugLogger('aztec:orchestrator-test'); +const logger = createDebugLogger('aztec:orchestrator-mixed-blocks'); -describe('prover/orchestrator', () => { - let builder: ProvingOrchestrator; - let builderDb: MerkleTreeOperations; - - let prover: TestCircuitProver; - - let blockNumber: number; - - let globalVariables: GlobalVariables; +describe('prover/orchestrator/mixed-blocks', () => { + let context: TestContext; beforeEach(async () => { - blockNumber = 3; - globalVariables = makeGlobals(blockNumber); - - const acvmConfig = await getConfig(logger); - const simulationProvider = await getSimulationProvider({ - acvmWorkingDirectory: acvmConfig?.acvmWorkingDirectory, - acvmBinaryPath: acvmConfig?.expectedAcvmPath, - }); - prover = new TestCircuitProver(simulationProvider); - - builderDb = await MerkleTrees.new(openTmpStore()).then(t => t.asLatest()); - builder = new ProvingOrchestrator(builderDb, prover, 1); + context = await TestContext.new(logger); }, 20_000); - describe('blocks', () => { - beforeEach(async () => { - builder = await ProvingOrchestrator.new(builderDb, prover); - }); - - afterEach(async () => { - await builder.stop(); - }); + afterEach(async () => { + await context.cleanup(); + }); + describe('blocks', () => { it('builds an unbalanced L2 block', async () => { const txs = await Promise.all([ - makeBloatedProcessedTx(builderDb, 1), - makeBloatedProcessedTx(builderDb, 2), - makeBloatedProcessedTx(builderDb, 3), + makeBloatedProcessedTx(context.actualDb, 1), + makeBloatedProcessedTx(context.actualDb, 2), + makeBloatedProcessedTx(context.actualDb, 3), ]); const l1ToL2Messages = range(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, 1 + 0x400).map(fr); // this needs to be a 4 tx block that will need to be completed - const blockTicket = await builder.startNewBlock( + const blockTicket = await context.orchestrator.startNewBlock( 4, - globalVariables, + context.globalVariables, l1ToL2Messages, - await makeEmptyProcessedTestTx(builderDb), + await makeEmptyProcessedTestTx(context.actualDb), ); for (const tx of txs) { - await builder.addNewTx(tx); + await context.orchestrator.addNewTx(tx); } - await builder.setBlockCompleted(); + await context.orchestrator.setBlockCompleted(); const result = await blockTicket.provingPromise; expect(result.status).toBe(PROVING_STATUS.SUCCESS); - const finalisedBlock = await builder.finaliseBlock(); + const finalisedBlock = await context.orchestrator.finaliseBlock(); - expect(finalisedBlock.block.number).toEqual(blockNumber); + expect(finalisedBlock.block.number).toEqual(context.blockNumber); }, 60_000); }); }); diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator_mixed_blocks_2.test.ts b/yarn-project/prover-client/src/orchestrator/orchestrator_mixed_blocks_2.test.ts index 353dd87fa9a..63a32b713a7 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator_mixed_blocks_2.test.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator_mixed_blocks_2.test.ts @@ -1,5 +1,5 @@ import { MerkleTreeId, PROVING_STATUS } from '@aztec/circuit-types'; -import { type GlobalVariables, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP } from '@aztec/circuits.js'; +import { NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP } from '@aztec/circuits.js'; import { fr } from '@aztec/circuits.js/testing'; import { range } from '@aztec/foundation/array'; import { times } from '@aztec/foundation/collection'; @@ -9,94 +9,63 @@ import { type MerkleTreeOperations, MerkleTrees } from '@aztec/world-state'; import { type MemDown, default as memdown } from 'memdown'; -import { - getConfig, - getSimulationProvider, - makeBloatedProcessedTx, - makeEmptyProcessedTestTx, - makeGlobals, - updateExpectedTreesFromTxs, -} from '../mocks/fixtures.js'; -import { TestCircuitProver } from '../prover/test_circuit_prover.js'; -import { ProvingOrchestrator } from './orchestrator.js'; +import { makeBloatedProcessedTx, makeEmptyProcessedTestTx, updateExpectedTreesFromTxs } from '../mocks/fixtures.js'; +import { TestContext } from '../mocks/test_context.js'; export const createMemDown = () => (memdown as any)() as MemDown; -const logger = createDebugLogger('aztec:orchestrator-test'); +const logger = createDebugLogger('aztec:orchestrator-mixed-blocks-2'); -describe('prover/orchestrator', () => { - let builder: ProvingOrchestrator; - let builderDb: MerkleTreeOperations; +describe('prover/orchestrator/mixed-blocks', () => { + let context: TestContext; let expectsDb: MerkleTreeOperations; - let prover: TestCircuitProver; - - let blockNumber: number; - - let globalVariables: GlobalVariables; - beforeEach(async () => { - blockNumber = 3; - globalVariables = makeGlobals(blockNumber); - - const acvmConfig = await getConfig(logger); - const simulationProvider = await getSimulationProvider({ - acvmWorkingDirectory: acvmConfig?.acvmWorkingDirectory, - acvmBinaryPath: acvmConfig?.expectedAcvmPath, - }); - prover = new TestCircuitProver(simulationProvider); - - builderDb = await MerkleTrees.new(openTmpStore()).then(t => t.asLatest()); + context = await TestContext.new(logger); expectsDb = await MerkleTrees.new(openTmpStore()).then(t => t.asLatest()); - builder = new ProvingOrchestrator(builderDb, prover, 1); }, 20_000); - describe('blocks', () => { - beforeEach(async () => { - builder = await ProvingOrchestrator.new(builderDb, prover); - }); - - afterEach(async () => { - await builder.stop(); - }); + afterEach(async () => { + await context.cleanup(); + }); + describe('blocks', () => { it.each([ [0, 2], [1, 2], [4, 4], [5, 8], - [9, 16], ] as const)( 'builds an L2 block with %i bloated txs and %i txs total', async (bloatedCount: number, totalCount: number) => { - const noteHashTreeBefore = await builderDb.getTreeInfo(MerkleTreeId.NOTE_HASH_TREE); + const noteHashTreeBefore = await context.actualDb.getTreeInfo(MerkleTreeId.NOTE_HASH_TREE); const txs = [ - ...(await Promise.all(times(bloatedCount, (i: number) => makeBloatedProcessedTx(builderDb, i)))), - ...(await Promise.all(times(totalCount - bloatedCount, _ => makeEmptyProcessedTestTx(builderDb)))), + ...(await Promise.all(times(bloatedCount, (i: number) => makeBloatedProcessedTx(context.actualDb, i)))), + ...(await Promise.all(times(totalCount - bloatedCount, _ => makeEmptyProcessedTestTx(context.actualDb)))), ]; const l1ToL2Messages = range(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, 1 + 0x400).map(fr); - const blockTicket = await builder.startNewBlock( + const blockTicket = await context.orchestrator.startNewBlock( txs.length, - globalVariables, + context.globalVariables, l1ToL2Messages, - await makeEmptyProcessedTestTx(builderDb), + await makeEmptyProcessedTestTx(context.actualDb), ); for (const tx of txs) { - await builder.addNewTx(tx); + await context.orchestrator.addNewTx(tx); } const result = await blockTicket.provingPromise; expect(result.status).toBe(PROVING_STATUS.SUCCESS); - const finalisedBlock = await builder.finaliseBlock(); + const finalisedBlock = await context.orchestrator.finaliseBlock(); - expect(finalisedBlock.block.number).toEqual(blockNumber); + expect(finalisedBlock.block.number).toEqual(context.blockNumber); await updateExpectedTreesFromTxs(expectsDb, txs); - const noteHashTreeAfter = await builderDb.getTreeInfo(MerkleTreeId.NOTE_HASH_TREE); + const noteHashTreeAfter = await context.actualDb.getTreeInfo(MerkleTreeId.NOTE_HASH_TREE); if (bloatedCount > 0) { expect(noteHashTreeAfter.root).not.toEqual(noteHashTreeBefore.root); diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator_multi_public_functions.test.ts b/yarn-project/prover-client/src/orchestrator/orchestrator_multi_public_functions.test.ts new file mode 100644 index 00000000000..e1c18cf3dac --- /dev/null +++ b/yarn-project/prover-client/src/orchestrator/orchestrator_multi_public_functions.test.ts @@ -0,0 +1,66 @@ +import { PROVING_STATUS, mockTx } from '@aztec/circuit-types'; +import { times } from '@aztec/foundation/collection'; +import { createDebugLogger } from '@aztec/foundation/log'; + +import { type MemDown, default as memdown } from 'memdown'; + +import { makeEmptyProcessedTestTx } from '../mocks/fixtures.js'; +import { TestContext } from '../mocks/test_context.js'; + +export const createMemDown = () => (memdown as any)() as MemDown; + +const logger = createDebugLogger('aztec:orchestrator-multi-public-functions'); + +describe('prover/orchestrator/public-functions', () => { + let context: TestContext; + + beforeEach(async () => { + context = await TestContext.new(logger); + }, 20_000); + + afterEach(async () => { + await context.cleanup(); + }); + + describe('blocks with public functions', () => { + let testCount = 1; + it.each([[4, 2, 3]] as const)( + 'builds an L2 block with %i transactions each with %i revertible and %i non revertible', + async ( + numTransactions: number, + numberOfNonRevertiblePublicCallRequests: number, + numberOfRevertiblePublicCallRequests: number, + ) => { + const txs = times(numTransactions, (i: number) => + mockTx(100000 * testCount++ + 1000 * i, { + numberOfNonRevertiblePublicCallRequests, + numberOfRevertiblePublicCallRequests, + }), + ); + for (const tx of txs) { + tx.data.constants.historicalHeader = await context.actualDb.buildInitialHeader(); + } + + const blockTicket = await context.orchestrator.startNewBlock( + numTransactions, + context.globalVariables, + [], + await makeEmptyProcessedTestTx(context.actualDb), + ); + + const [processed, failed] = await context.processPublicFunctions(txs, numTransactions, context.orchestrator); + expect(processed.length).toBe(numTransactions); + expect(failed.length).toBe(0); + + await context.orchestrator.setBlockCompleted(); + + const result = await blockTicket.provingPromise; + expect(result.status).toBe(PROVING_STATUS.SUCCESS); + const finalisedBlock = await context.orchestrator.finaliseBlock(); + + expect(finalisedBlock.block.number).toEqual(context.blockNumber); + }, + 60_000, + ); + }); +}); diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator_multiple_blocks.test.ts b/yarn-project/prover-client/src/orchestrator/orchestrator_multiple_blocks.test.ts index 3a2be210c63..a84fa807929 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator_multiple_blocks.test.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator_multiple_blocks.test.ts @@ -1,58 +1,34 @@ import { PROVING_STATUS } from '@aztec/circuit-types'; import { createDebugLogger } from '@aztec/foundation/log'; -import { openTmpStore } from '@aztec/kv-store/utils'; -import { type MerkleTreeOperations, MerkleTrees } from '@aztec/world-state'; import { type MemDown, default as memdown } from 'memdown'; -import { - getConfig, - getSimulationProvider, - makeBloatedProcessedTx, - makeEmptyProcessedTestTx, - makeGlobals, -} from '../mocks/fixtures.js'; -import { TestCircuitProver } from '../prover/test_circuit_prover.js'; -import { ProvingOrchestrator } from './orchestrator.js'; +import { makeBloatedProcessedTx, makeEmptyProcessedTestTx, makeGlobals } from '../mocks/fixtures.js'; +import { TestContext } from '../mocks/test_context.js'; export const createMemDown = () => (memdown as any)() as MemDown; -const logger = createDebugLogger('aztec:orchestrator-test'); +const logger = createDebugLogger('aztec:orchestrator-multi-blocks'); -describe('prover/orchestrator', () => { - let builder: ProvingOrchestrator; - let builderDb: MerkleTreeOperations; - - let prover: TestCircuitProver; +describe('prover/orchestrator/multi-block', () => { + let context: TestContext; beforeEach(async () => { - const acvmConfig = await getConfig(logger); - const simulationProvider = await getSimulationProvider({ - acvmWorkingDirectory: acvmConfig?.acvmWorkingDirectory, - acvmBinaryPath: acvmConfig?.expectedAcvmPath, - }); - prover = new TestCircuitProver(simulationProvider); - - builderDb = await MerkleTrees.new(openTmpStore()).then(t => t.asLatest()); - builder = new ProvingOrchestrator(builderDb, prover, 1); + context = await TestContext.new(logger); }, 20_000); - describe('multiple blocks', () => { - beforeEach(async () => { - builder = await ProvingOrchestrator.new(builderDb, prover); - }); - - afterEach(async () => { - await builder.stop(); - }); + afterEach(async () => { + await context.cleanup(); + }); + describe('multiple blocks', () => { it('builds multiple blocks in sequence', async () => { const numBlocks = 5; - let header = await builderDb.buildInitialHeader(); + let header = await context.actualDb.buildInitialHeader(); for (let i = 0; i < numBlocks; i++) { - const tx = await makeBloatedProcessedTx(builderDb, i + 1); - const emptyTx = await makeEmptyProcessedTestTx(builderDb); + const tx = await makeBloatedProcessedTx(context.actualDb, i + 1); + const emptyTx = await makeEmptyProcessedTestTx(context.actualDb); tx.data.constants.historicalHeader = header; emptyTx.data.constants.historicalHeader = header; @@ -61,21 +37,21 @@ describe('prover/orchestrator', () => { const globals = makeGlobals(blockNum); // This will need to be a 2 tx block - const blockTicket = await builder.startNewBlock(2, globals, [], emptyTx); + const blockTicket = await context.orchestrator.startNewBlock(2, globals, [], emptyTx); - await builder.addNewTx(tx); + await context.orchestrator.addNewTx(tx); // we need to complete the block as we have not added a full set of txs - await builder.setBlockCompleted(); + await context.orchestrator.setBlockCompleted(); const result = await blockTicket.provingPromise; expect(result.status).toBe(PROVING_STATUS.SUCCESS); - const finalisedBlock = await builder.finaliseBlock(); + const finalisedBlock = await context.orchestrator.finaliseBlock(); expect(finalisedBlock.block.number).toEqual(blockNum); header = finalisedBlock.block.header; - await builderDb.commit(); + await context.actualDb.commit(); } }, 60_000); }); diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator_public_functions.test.ts b/yarn-project/prover-client/src/orchestrator/orchestrator_public_functions.test.ts index 5a1ccaea82d..9409ba9d41e 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator_public_functions.test.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator_public_functions.test.ts @@ -1,87 +1,28 @@ import { PROVING_STATUS, mockTx } from '@aztec/circuit-types'; -import { GlobalVariables, Header } from '@aztec/circuits.js'; import { createDebugLogger } from '@aztec/foundation/log'; -import { openTmpStore } from '@aztec/kv-store/utils'; -import { - type ContractsDataSourcePublicDB, - PublicExecutionResultBuilder, - type PublicExecutor, - type PublicKernelCircuitSimulator, - PublicProcessor, - RealPublicKernelCircuitSimulator, - WASMSimulator, - type WorldStatePublicDB, -} from '@aztec/simulator'; -import { type MerkleTreeOperations, MerkleTrees, type TreeInfo } from '@aztec/world-state'; -import { type MockProxy, mock } from 'jest-mock-extended'; import { type MemDown, default as memdown } from 'memdown'; -import { getConfig, getSimulationProvider, makeEmptyProcessedTestTx, makeGlobals } from '../mocks/fixtures.js'; -import { TestCircuitProver } from '../prover/test_circuit_prover.js'; -import { ProvingOrchestrator } from './orchestrator.js'; +import { makeEmptyProcessedTestTx } from '../mocks/fixtures.js'; +import { TestContext } from '../mocks/test_context.js'; export const createMemDown = () => (memdown as any)() as MemDown; -const logger = createDebugLogger('aztec:orchestrator-test'); +const logger = createDebugLogger('aztec:orchestrator-public-functions'); -describe('prover/orchestrator', () => { - let builder: ProvingOrchestrator; - let db: MockProxy; - let builderDb: MerkleTreeOperations; - let publicExecutor: MockProxy; - let publicContractsDB: MockProxy; - let publicWorldStateDB: MockProxy; - let publicKernel: PublicKernelCircuitSimulator; - let processor: PublicProcessor; - - let prover: TestCircuitProver; - - let blockNumber: number; - let testCount = 1; - - let globalVariables: GlobalVariables; - let root: Buffer; +describe('prover/orchestrator/public-functions', () => { + let context: TestContext; beforeEach(async () => { - blockNumber = 3; - globalVariables = makeGlobals(blockNumber); - - const acvmConfig = await getConfig(logger); - const simulationProvider = await getSimulationProvider({ - acvmWorkingDirectory: acvmConfig?.acvmWorkingDirectory, - acvmBinaryPath: acvmConfig?.expectedAcvmPath, - }); - prover = new TestCircuitProver(simulationProvider); - - builderDb = await MerkleTrees.new(openTmpStore()).then(t => t.asLatest()); - builder = new ProvingOrchestrator(builderDb, prover, 1); + context = await TestContext.new(logger); }, 20_000); - describe('blocks with public functions', () => { - beforeEach(async () => { - publicExecutor = mock(); - db = mock(); - root = Buffer.alloc(32, 5); - db.getTreeInfo.mockResolvedValue({ root } as TreeInfo); - publicContractsDB = mock(); - publicWorldStateDB = mock(); - builder = await ProvingOrchestrator.new(builderDb, prover); - publicKernel = new RealPublicKernelCircuitSimulator(new WASMSimulator()); - processor = new PublicProcessor( - db, - publicExecutor, - publicKernel, - GlobalVariables.empty(), - Header.empty(), - publicContractsDB, - publicWorldStateDB, - ); - }); + afterEach(async () => { + await context.cleanup(); + }); - afterEach(async () => { - await builder.stop(); - }); + describe('blocks with public functions', () => { + let testCount = 1; it.each([ [0, 4], @@ -97,41 +38,30 @@ describe('prover/orchestrator', () => { numberOfNonRevertiblePublicCallRequests, numberOfRevertiblePublicCallRequests, }); - tx.data.constants.historicalHeader = await builderDb.buildInitialHeader(); - - publicExecutor.simulate.mockImplementation(execution => { - for (const request of tx.enqueuedPublicFunctionCalls) { - if (execution.contractAddress.equals(request.contractAddress)) { - const result = PublicExecutionResultBuilder.fromPublicCallRequest({ request }).build(); - // result.unencryptedLogs = tx.unencryptedLogs.functionLogs[0]; - return Promise.resolve(result); - } - } - throw new Error(`Unexpected execution request: ${execution}`); - }); + tx.data.constants.historicalHeader = await context.actualDb.buildInitialHeader(); - const [processed, _] = await processor.process([tx], 1, undefined); + const [processed, _] = await context.processPublicFunctions([tx], 1, undefined); // This will need to be a 2 tx block - const blockTicket = await builder.startNewBlock( + const blockTicket = await context.orchestrator.startNewBlock( 2, - globalVariables, + context.globalVariables, [], - await makeEmptyProcessedTestTx(builderDb), + await makeEmptyProcessedTestTx(context.actualDb), ); for (const processedTx of processed) { - await builder.addNewTx(processedTx); + await context.orchestrator.addNewTx(processedTx); } // we need to complete the block as we have not added a full set of txs - await builder.setBlockCompleted(); + await context.orchestrator.setBlockCompleted(); const result = await blockTicket.provingPromise; expect(result.status).toBe(PROVING_STATUS.SUCCESS); - const finalisedBlock = await builder.finaliseBlock(); + const finalisedBlock = await context.orchestrator.finaliseBlock(); - expect(finalisedBlock.block.number).toEqual(blockNumber); + expect(finalisedBlock.block.number).toEqual(context.blockNumber); }, 60_000, ); diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator_single_blocks.test.ts b/yarn-project/prover-client/src/orchestrator/orchestrator_single_blocks.test.ts index 140a6d2278d..96f8f64b3df 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator_single_blocks.test.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator_single_blocks.test.ts @@ -1,5 +1,5 @@ import { PROVING_STATUS } from '@aztec/circuit-types'; -import { type GlobalVariables, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP } from '@aztec/circuits.js'; +import { NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP } from '@aztec/circuits.js'; import { fr } from '@aztec/circuits.js/testing'; import { range } from '@aztec/foundation/array'; import { createDebugLogger } from '@aztec/foundation/log'; @@ -9,132 +9,105 @@ import { type MerkleTreeOperations, MerkleTrees } from '@aztec/world-state'; import { type MemDown, default as memdown } from 'memdown'; -import { - getConfig, - getSimulationProvider, - makeBloatedProcessedTx, - makeEmptyProcessedTestTx, - makeGlobals, - updateExpectedTreesFromTxs, -} from '../mocks/fixtures.js'; -import { TestCircuitProver } from '../prover/test_circuit_prover.js'; -import { ProvingOrchestrator } from './orchestrator.js'; +import { makeBloatedProcessedTx, makeEmptyProcessedTestTx, updateExpectedTreesFromTxs } from '../mocks/fixtures.js'; +import { TestContext } from '../mocks/test_context.js'; export const createMemDown = () => (memdown as any)() as MemDown; -const logger = createDebugLogger('aztec:orchestrator-test'); +const logger = createDebugLogger('aztec:orchestrator-single-blocks'); -describe('prover/orchestrator', () => { - let builder: ProvingOrchestrator; - let builderDb: MerkleTreeOperations; +describe('prover/orchestrator/blocks', () => { + let context: TestContext; let expectsDb: MerkleTreeOperations; - let prover: TestCircuitProver; - - let blockNumber: number; - - let globalVariables: GlobalVariables; - beforeEach(async () => { - blockNumber = 3; - globalVariables = makeGlobals(blockNumber); - - const acvmConfig = await getConfig(logger); - const simulationProvider = await getSimulationProvider({ - acvmWorkingDirectory: acvmConfig?.acvmWorkingDirectory, - acvmBinaryPath: acvmConfig?.expectedAcvmPath, - }); - prover = new TestCircuitProver(simulationProvider); - - builderDb = await MerkleTrees.new(openTmpStore()).then(t => t.asLatest()); + context = await TestContext.new(logger); expectsDb = await MerkleTrees.new(openTmpStore()).then(t => t.asLatest()); - builder = new ProvingOrchestrator(builderDb, prover, 1); }, 20_000); - describe('blocks', () => { - beforeEach(async () => { - builder = await ProvingOrchestrator.new(builderDb, prover); - }); - - afterEach(async () => { - await builder.stop(); - }); + afterEach(async () => { + await context.cleanup(); + }); + describe('blocks', () => { it('builds an empty L2 block', async () => { - const txs = await Promise.all([makeEmptyProcessedTestTx(builderDb), makeEmptyProcessedTestTx(builderDb)]); + const txs = await Promise.all([ + makeEmptyProcessedTestTx(context.actualDb), + makeEmptyProcessedTestTx(context.actualDb), + ]); - const blockTicket = await builder.startNewBlock( + const blockTicket = await context.orchestrator.startNewBlock( txs.length, - globalVariables, + context.globalVariables, [], - await makeEmptyProcessedTestTx(builderDb), + await makeEmptyProcessedTestTx(context.actualDb), ); for (const tx of txs) { - await builder.addNewTx(tx); + await context.orchestrator.addNewTx(tx); } const result = await blockTicket.provingPromise; expect(result.status).toBe(PROVING_STATUS.SUCCESS); - const finalisedBlock = await builder.finaliseBlock(); + const finalisedBlock = await context.orchestrator.finaliseBlock(); - expect(finalisedBlock.block.number).toEqual(blockNumber); + expect(finalisedBlock.block.number).toEqual(context.blockNumber); }, 60_000); it('builds a block with 1 transaction', async () => { - const txs = await Promise.all([makeBloatedProcessedTx(builderDb, 1)]); + const txs = await Promise.all([makeBloatedProcessedTx(context.actualDb, 1)]); await updateExpectedTreesFromTxs(expectsDb, txs); // This will need to be a 2 tx block - const blockTicket = await builder.startNewBlock( + const blockTicket = await context.orchestrator.startNewBlock( 2, - globalVariables, + context.globalVariables, [], - await makeEmptyProcessedTestTx(builderDb), + await makeEmptyProcessedTestTx(context.actualDb), ); for (const tx of txs) { - await builder.addNewTx(tx); + await context.orchestrator.addNewTx(tx); } // we need to complete the block as we have not added a full set of txs - await builder.setBlockCompleted(); + await context.orchestrator.setBlockCompleted(); const result = await blockTicket.provingPromise; expect(result.status).toBe(PROVING_STATUS.SUCCESS); - const finalisedBlock = await builder.finaliseBlock(); + const finalisedBlock = await context.orchestrator.finaliseBlock(); - expect(finalisedBlock.block.number).toEqual(blockNumber); + expect(finalisedBlock.block.number).toEqual(context.blockNumber); }, 60_000); it('builds a block concurrently with transaction simulation', async () => { const txs = await Promise.all([ - makeBloatedProcessedTx(builderDb, 1), - makeBloatedProcessedTx(builderDb, 2), - makeBloatedProcessedTx(builderDb, 3), - makeBloatedProcessedTx(builderDb, 4), + makeBloatedProcessedTx(context.actualDb, 1), + makeBloatedProcessedTx(context.actualDb, 2), + makeBloatedProcessedTx(context.actualDb, 3), + makeBloatedProcessedTx(context.actualDb, 4), ]); const l1ToL2Messages = range(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, 1 + 0x400).map(fr); - const blockTicket = await builder.startNewBlock( + const blockTicket = await context.orchestrator.startNewBlock( txs.length, - globalVariables, + context.globalVariables, l1ToL2Messages, - await makeEmptyProcessedTestTx(builderDb), + await makeEmptyProcessedTestTx(context.actualDb), ); for (const tx of txs) { - await builder.addNewTx(tx); + await context.orchestrator.addNewTx(tx); await sleep(1000); } const result = await blockTicket.provingPromise; expect(result.status).toBe(PROVING_STATUS.SUCCESS); - const finalisedBlock = await builder.finaliseBlock(); + const finalisedBlock = await context.orchestrator.finaliseBlock(); - expect(finalisedBlock.block.number).toEqual(blockNumber); + expect(finalisedBlock.block.number).toEqual(context.blockNumber); }, 60_000); }); }); diff --git a/yarn-project/prover-client/src/prover/bb_prover.test.ts b/yarn-project/prover-client/src/prover/bb_prover.test.ts deleted file mode 100644 index ad8ddd160b0..00000000000 --- a/yarn-project/prover-client/src/prover/bb_prover.test.ts +++ /dev/null @@ -1,105 +0,0 @@ -import { PROVING_STATUS, makeEmptyProcessedTx } from '@aztec/circuit-types'; -import { Fr, type GlobalVariables, Header } from '@aztec/circuits.js'; -import { createDebugLogger } from '@aztec/foundation/log'; -import { openTmpStore } from '@aztec/kv-store/utils'; -import { type MerkleTreeOperations, MerkleTrees } from '@aztec/world-state'; - -import * as fs from 'fs/promises'; -import { type MemDown, default as memdown } from 'memdown'; - -import { getConfig, makeBloatedProcessedTx, makeGlobals } from '../mocks/fixtures.js'; -import { buildBaseRollupInput } from '../orchestrator/block-building-helpers.js'; -import { ProvingOrchestrator } from '../orchestrator/orchestrator.js'; -import { BBNativeRollupProver, type BBProverConfig } from './bb_prover.js'; - -export const createMemDown = () => (memdown as any)() as MemDown; - -const logger = createDebugLogger('aztec:bb-prover-test'); - -describe('prover/bb_prover', () => { - let builderDb: MerkleTreeOperations; - let prover: BBNativeRollupProver; - let directoryToCleanup: string | undefined; - - let blockNumber: number; - - let globalVariables: GlobalVariables; - - beforeAll(async () => { - const config = await getConfig(logger); - if (!config) { - throw new Error(`BB and ACVM binaries must be present to test the BB Prover`); - } - directoryToCleanup = config.directoryToCleanup; - const bbConfig: BBProverConfig = { - acvmBinaryPath: config.expectedAcvmPath, - acvmWorkingDirectory: config.acvmWorkingDirectory, - bbBinaryPath: config.expectedBBPath, - bbWorkingDirectory: config.bbWorkingDirectory, - }; - prover = await BBNativeRollupProver.new(bbConfig); - }, 60_000); - - beforeEach(async () => { - blockNumber = 3; - globalVariables = makeGlobals(blockNumber); - - builderDb = await MerkleTrees.new(openTmpStore()).then(t => t.asLatest()); - }, 60_000); - - afterAll(async () => { - if (directoryToCleanup) { - await fs.rm(directoryToCleanup, { recursive: true, force: true }); - } - }, 5000); - - it('proves the base rollup', async () => { - const txs = await Promise.all([makeBloatedProcessedTx(builderDb, 1)]); - - logger.verbose('Building base rollup inputs'); - const baseRollupInputs = []; - for (const tx of txs) { - baseRollupInputs.push(await buildBaseRollupInput(tx, globalVariables, builderDb)); - } - logger.verbose('Proving base rollups'); - const proofOutputs = await Promise.all(baseRollupInputs.map(inputs => prover.getBaseRollupProof(inputs))); - logger.verbose('Verifying base rollups'); - await expect( - Promise.all(proofOutputs.map(output => prover.verifyProof('BaseRollupArtifact', output[1]))), - ).resolves.not.toThrow(); - }, 600_000); - - it('proves all circuits', async () => { - const txs = await Promise.all([ - makeBloatedProcessedTx(builderDb, 1), - makeBloatedProcessedTx(builderDb, 2), - makeBloatedProcessedTx(builderDb, 3), - makeBloatedProcessedTx(builderDb, 4), - ]); - - const orchestrator = await ProvingOrchestrator.new(builderDb, prover); - - const provingTicket = await orchestrator.startNewBlock( - 4, - globalVariables, - [], - makeEmptyProcessedTx(Header.empty(), new Fr(1234), new Fr(1)), - ); - - for (const tx of txs) { - await orchestrator.addNewTx(tx); - } - - await orchestrator.setBlockCompleted(); - - const provingResult = await provingTicket.provingPromise; - - expect(provingResult.status).toBe(PROVING_STATUS.SUCCESS); - - const blockResult = await orchestrator.finaliseBlock(); - - await expect(prover.verifyProof('RootRollupArtifact', blockResult.proof)).resolves.not.toThrow(); - - await orchestrator.stop(); - }, 600_000); -}); diff --git a/yarn-project/prover-client/src/prover/bb_prover.ts b/yarn-project/prover-client/src/prover/bb_prover.ts index 73c450c1317..524343b27a3 100644 --- a/yarn-project/prover-client/src/prover/bb_prover.ts +++ b/yarn-project/prover-client/src/prover/bb_prover.ts @@ -1,5 +1,5 @@ /* eslint-disable require-await */ -import { type PublicKernelNonTailRequest, type PublicKernelTailRequest } from '@aztec/circuit-types'; +import { type PublicKernelNonTailRequest, type PublicKernelTailRequest, PublicKernelType } from '@aztec/circuit-types'; import { type BaseOrMergeRollupPublicInputs, type BaseParityInputs, @@ -26,6 +26,8 @@ import { convertBaseRollupOutputsFromWitnessMap, convertMergeRollupInputsToWitnessMap, convertMergeRollupOutputsFromWitnessMap, + convertPublicTailInputsToWitnessMap, + convertPublicTailOutputFromWitnessMap, convertRootParityInputsToWitnessMap, convertRootParityOutputsFromWitnessMap, convertRootRollupInputsToWitnessMap, @@ -37,7 +39,7 @@ import { type WitnessMap } from '@noir-lang/types'; import * as fs from 'fs/promises'; import { BB_RESULT, generateKeyForNoirCircuit, generateProof, verifyProof } from '../bb/execute.js'; -import { type CircuitProver } from './interface.js'; +import { type CircuitProver, KernelArtifactMapping } from './interface.js'; const logger = createDebugLogger('aztec:bb-prover'); @@ -46,14 +48,18 @@ export type BBProverConfig = { bbWorkingDirectory: string; acvmBinaryPath: string; acvmWorkingDirectory: string; + // list of circuits supported by this prover. defaults to all circuits if empty + circuitFilter?: ServerProtocolArtifact[]; }; /** * Prover implementation that uses barretenberg native proving */ export class BBNativeRollupProver implements CircuitProver { - private verificationKeyDirectories: Map = new Map(); - constructor(private config: BBProverConfig) {} + constructor( + private config: BBProverConfig, + private verificationKeyDirectories: Map, + ) {} static async new(config: BBProverConfig) { await fs.access(config.acvmBinaryPath, fs.constants.R_OK); @@ -63,9 +69,43 @@ export class BBNativeRollupProver implements CircuitProver { logger.info(`Using native BB at ${config.bbBinaryPath} and working directory ${config.bbWorkingDirectory}`); logger.info(`Using native ACVM at ${config.acvmBinaryPath} and working directory ${config.acvmWorkingDirectory}`); - const prover = new BBNativeRollupProver(config); - await prover.init(); - return prover; + const mappings = await BBNativeRollupProver.generateVerificationKeys(config); + + return new BBNativeRollupProver(config, mappings); + } + + public static async generateVerificationKeys(bbConfig: BBProverConfig) { + const promises = []; + const directories = new Map(); + for (const circuitName in ServerCircuitArtifacts) { + if (bbConfig.circuitFilter?.length && bbConfig.circuitFilter.findIndex((c: string) => c === circuitName) === -1) { + // circuit is not supported + continue; + } + const verificationKeyPromise = generateKeyForNoirCircuit( + bbConfig.bbBinaryPath, + bbConfig.bbWorkingDirectory, + circuitName, + ServerCircuitArtifacts[circuitName as ServerProtocolArtifact], + 'vk', + logger.debug, + ).then(result => { + if (result.status == BB_RESULT.FAILURE) { + const message = `Failed to generate verification key for circuit ${circuitName}, message: ${result.reason}`; + logger.error(message); + throw new Error(message); + } + if (result.status == BB_RESULT.ALREADY_PRESENT) { + logger.info(`Verification key for circuit ${circuitName} was already present at ${result.path!}`); + } else { + logger.info(`Generated verification key for circuit ${circuitName} at ${result.path!}`); + } + directories.set(circuitName as ServerProtocolArtifact, result.path!); + }); + promises.push(verificationKeyPromise); + } + await Promise.all(promises); + return directories; } /** @@ -152,29 +192,6 @@ export class BBNativeRollupProver implements CircuitProver { return Promise.resolve([result, proof]); } - private async init() { - const promises = []; - for (const circuitName in ServerCircuitArtifacts) { - const verificationKeyPromise = generateKeyForNoirCircuit( - this.config.bbBinaryPath, - this.config.bbWorkingDirectory, - circuitName, - ServerCircuitArtifacts[circuitName as ServerProtocolArtifact], - 'vk', - logger.debug, - ).then(result => { - if (result.status == BB_RESULT.FAILURE) { - logger.error(`Failed to generate verification key for circuit ${circuitName}`); - return; - } - logger.info(`Generated verification key for circuit ${circuitName} at ${result.path!}`); - this.verificationKeyDirectories.set(circuitName as ServerProtocolArtifact, result.path!); - }); - promises.push(verificationKeyPromise); - } - await Promise.all(promises); - } - public async createProof(witnessMap: WitnessMap, circuitType: ServerProtocolArtifact): Promise<[WitnessMap, Proof]> { // Create random directory to be used for temp files const bbWorkingDirectory = `${this.config.bbWorkingDirectory}/${randomBytes(8).toString('hex')}`; @@ -238,7 +255,11 @@ export class BBNativeRollupProver implements CircuitProver { await fs.writeFile(proofFileName, proof.buffer); - const result = await verifyProof(this.config.bbBinaryPath, proofFileName, verificationKeyPath!, logger.debug); + const logFunction = (message: string) => { + logger.debug(`${circuitType} BB out - ${message}`); + }; + + const result = await verifyProof(this.config.bbBinaryPath, proofFileName, verificationKeyPath!, logFunction); await fs.rm(bbWorkingDirectory, { recursive: true, force: true }); @@ -259,10 +280,27 @@ export class BBNativeRollupProver implements CircuitProver { await this.verifyProof(circuitType, proof); } - getPublicKernelProof(_: PublicKernelNonTailRequest): Promise<[PublicKernelCircuitPublicInputs, Proof]> { - throw new Error('Method not implemented.'); + public async getPublicKernelProof( + kernelRequest: PublicKernelNonTailRequest, + ): Promise<[PublicKernelCircuitPublicInputs, Proof]> { + const kernelOps = KernelArtifactMapping[kernelRequest.type]; + if (kernelOps === undefined) { + throw new Error(`Unable to prove kernel type ${PublicKernelType[kernelRequest.type]}`); + } + const witnessMap = kernelOps.convertInputs(kernelRequest.inputs); + + const [outputWitness, proof] = await this.createProof(witnessMap, kernelOps.artifact); + + const result = kernelOps.convertOutputs(outputWitness); + return Promise.resolve([result, proof]); } - getPublicTailProof(_: PublicKernelTailRequest): Promise<[KernelCircuitPublicInputs, Proof]> { - throw new Error('Method not implemented.'); + + public async getPublicTailProof(kernelRequest: PublicKernelTailRequest): Promise<[KernelCircuitPublicInputs, Proof]> { + const witnessMap = convertPublicTailInputsToWitnessMap(kernelRequest.inputs); + + const [outputWitness, proof] = await this.createProof(witnessMap, 'PublicKernelTailArtifact'); + + const result = convertPublicTailOutputFromWitnessMap(outputWitness); + return [result, proof]; } } diff --git a/yarn-project/prover-client/src/prover/bb_prover_base_rollup.test.ts b/yarn-project/prover-client/src/prover/bb_prover_base_rollup.test.ts new file mode 100644 index 00000000000..bd010508498 --- /dev/null +++ b/yarn-project/prover-client/src/prover/bb_prover_base_rollup.test.ts @@ -0,0 +1,39 @@ +import { createDebugLogger } from '@aztec/foundation/log'; + +import { type MemDown, default as memdown } from 'memdown'; + +import { makeBloatedProcessedTx } from '../mocks/fixtures.js'; +import { TestContext } from '../mocks/test_context.js'; +import { buildBaseRollupInput } from '../orchestrator/block-building-helpers.js'; +import { BBNativeRollupProver, type BBProverConfig } from './bb_prover.js'; + +export const createMemDown = () => (memdown as any)() as MemDown; + +const logger = createDebugLogger('aztec:bb-prover-base-rollup'); + +describe('prover/bb_prover/base-rollup', () => { + let context: TestContext; + + beforeAll(async () => { + const buildProver = (bbConfig: BBProverConfig) => { + bbConfig.circuitFilter = ['BaseRollupArtifact']; + return BBNativeRollupProver.new(bbConfig); + }; + context = await TestContext.new(logger, buildProver); + }, 60_000); + + afterAll(async () => { + await context.cleanup(); + }, 5000); + + it('proves the base rollup', async () => { + const tx = await makeBloatedProcessedTx(context.actualDb, 1); + + logger.verbose('Building base rollup inputs'); + const baseRollupInputs = await buildBaseRollupInput(tx, context.globalVariables, context.actualDb); + logger.verbose('Proving base rollups'); + const proofOutputs = await context.prover.getBaseRollupProof(baseRollupInputs); + logger.verbose('Verifying base rollups'); + await expect(context.prover.verifyProof('BaseRollupArtifact', proofOutputs[1])).resolves.not.toThrow(); + }, 200_000); +}); diff --git a/yarn-project/prover-client/src/prover/bb_prover_full_rollup.test.ts b/yarn-project/prover-client/src/prover/bb_prover_full_rollup.test.ts new file mode 100644 index 00000000000..3e77bdb45f8 --- /dev/null +++ b/yarn-project/prover-client/src/prover/bb_prover_full_rollup.test.ts @@ -0,0 +1,62 @@ +import { PROVING_STATUS, makeEmptyProcessedTx, mockTx } from '@aztec/circuit-types'; +import { Fr, Header } from '@aztec/circuits.js'; +import { times } from '@aztec/foundation/collection'; +import { createDebugLogger } from '@aztec/foundation/log'; + +import { type MemDown, default as memdown } from 'memdown'; + +import { TestContext } from '../mocks/test_context.js'; +import { BBNativeRollupProver } from './bb_prover.js'; + +export const createMemDown = () => (memdown as any)() as MemDown; + +const logger = createDebugLogger('aztec:bb-prover-full-rollup'); + +describe('prover/bb_prover/full-rollup', () => { + let context: TestContext; + + beforeAll(async () => { + context = await TestContext.new(logger, BBNativeRollupProver.new); + }, 60_000); + + afterAll(async () => { + await context.cleanup(); + }, 5000); + + it('proves all circuits', async () => { + const numTransactions = 4; + const txs = times(numTransactions, (i: number) => + mockTx(1000 * (i + 1), { + numberOfNonRevertiblePublicCallRequests: 2, + numberOfRevertiblePublicCallRequests: 1, + }), + ); + for (const tx of txs) { + tx.data.constants.historicalHeader = await context.actualDb.buildInitialHeader(); + } + + const provingTicket = await context.orchestrator.startNewBlock( + numTransactions, + context.globalVariables, + [], + makeEmptyProcessedTx(Header.empty(), new Fr(1234), new Fr(1)), + ); + + const [processed, failed] = await context.processPublicFunctions(txs, numTransactions, context.orchestrator); + + expect(processed.length).toBe(numTransactions); + expect(failed.length).toBe(0); + + await context.orchestrator.setBlockCompleted(); + + const provingResult = await provingTicket.provingPromise; + + expect(provingResult.status).toBe(PROVING_STATUS.SUCCESS); + + const blockResult = await context.orchestrator.finaliseBlock(); + + await expect(context.prover.verifyProof('RootRollupArtifact', blockResult.proof)).resolves.not.toThrow(); + + await context.orchestrator.stop(); + }, 600_000); +}); diff --git a/yarn-project/prover-client/src/prover/bb_prover_parity.test.ts b/yarn-project/prover-client/src/prover/bb_prover_parity.test.ts new file mode 100644 index 00000000000..58fafabdf3d --- /dev/null +++ b/yarn-project/prover-client/src/prover/bb_prover_parity.test.ts @@ -0,0 +1,69 @@ +import { + BaseParityInputs, + Fr, + NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, + NUM_BASE_PARITY_PER_ROOT_PARITY, + RootParityInput, + RootParityInputs, +} from '@aztec/circuits.js'; +import { makeTuple } from '@aztec/foundation/array'; +import { createDebugLogger } from '@aztec/foundation/log'; +import { type Tuple } from '@aztec/foundation/serialize'; + +import { type MemDown, default as memdown } from 'memdown'; + +import { TestContext } from '../mocks/test_context.js'; +import { BBNativeRollupProver, type BBProverConfig } from './bb_prover.js'; + +export const createMemDown = () => (memdown as any)() as MemDown; + +const logger = createDebugLogger('aztec:bb-prover-parity'); + +describe('prover/bb_prover/parity', () => { + let context: TestContext; + + beforeAll(async () => { + const buildProver = (bbConfig: BBProverConfig) => { + bbConfig.circuitFilter = ['BaseParityArtifact', 'RootParityArtifact']; + return BBNativeRollupProver.new(bbConfig); + }; + context = await TestContext.new(logger, buildProver); + }, 60_000); + + afterAll(async () => { + await context.cleanup(); + }, 5000); + + it('proves the parity circuits', async () => { + const l1ToL2Messages = makeTuple( + NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, + Fr.random, + ); + const baseParityInputs = Array.from({ length: NUM_BASE_PARITY_PER_ROOT_PARITY }, (_, i) => + BaseParityInputs.fromSlice(l1ToL2Messages, i), + ); + + // Generate the base parity proofs + const rootInputs = await Promise.all( + baseParityInputs.map(baseInputs => context.prover.getBaseParityProof(baseInputs)), + ); + + // Verify the base parity proofs + await expect( + Promise.all(rootInputs.map(input => context.prover.verifyProof('BaseParityArtifact', input[1]))), + ).resolves.not.toThrow(); + + // Now generate the root parity proof + const rootChildrenInputs = rootInputs.map(rootInput => { + const child: RootParityInput = new RootParityInput(rootInput[1], rootInput[0]); + return child; + }); + const rootParityInputs: RootParityInputs = new RootParityInputs( + rootChildrenInputs as Tuple, + ); + const rootOutput = await context.prover.getRootParityProof(rootParityInputs); + + // Verify the root parity proof + await expect(context.prover.verifyProof('RootParityArtifact', rootOutput[1])).resolves.not.toThrow(); + }, 100_000); +}); diff --git a/yarn-project/prover-client/src/prover/bb_prover_public_kernel.test.ts b/yarn-project/prover-client/src/prover/bb_prover_public_kernel.test.ts new file mode 100644 index 00000000000..d25675c41e9 --- /dev/null +++ b/yarn-project/prover-client/src/prover/bb_prover_public_kernel.test.ts @@ -0,0 +1,91 @@ +import { PublicKernelType, mockTx } from '@aztec/circuit-types'; +import { type Proof, makeEmptyProof } from '@aztec/circuits.js'; +import { createDebugLogger } from '@aztec/foundation/log'; +import { type ServerProtocolArtifact } from '@aztec/noir-protocol-circuits-types'; + +import { type MemDown, default as memdown } from 'memdown'; + +import { TestContext } from '../mocks/test_context.js'; +import { BBNativeRollupProver, type BBProverConfig } from './bb_prover.js'; + +export const createMemDown = () => (memdown as any)() as MemDown; + +const logger = createDebugLogger('aztec:bb-prover-public-kernel'); + +describe('prover/bb_prover/public-kernel', () => { + let context: TestContext; + + beforeAll(async () => { + const buildProver = (bbConfig: BBProverConfig) => { + bbConfig.circuitFilter = [ + 'PublicKernelAppLogicArtifact', + 'PublicKernelSetupArtifact', + 'PublicKernelTailArtifact', + 'PublicKernelTeardownArtifact', + ]; + return BBNativeRollupProver.new(bbConfig); + }; + context = await TestContext.new(logger, buildProver); + }, 60_000); + + afterAll(async () => { + await context.cleanup(); + }, 5000); + + it('proves the public kernel circuits', async () => { + const tx = mockTx(1000, { + numberOfNonRevertiblePublicCallRequests: 2, + numberOfRevertiblePublicCallRequests: 1, + }); + tx.data.constants.historicalHeader = await context.actualDb.buildInitialHeader(); + + const [processed, failed] = await context.processPublicFunctions([tx], 1, undefined); + + expect(processed.length).toBe(1); + expect(failed.length).toBe(0); + const processedTx = processed[0]; + expect(processedTx.publicKernelRequests.map(r => r.type)).toEqual([ + PublicKernelType.SETUP, + PublicKernelType.APP_LOGIC, + PublicKernelType.TEARDOWN, + PublicKernelType.TAIL, + ]); + + const getArtifactForPublicKernel = (type: PublicKernelType): ServerProtocolArtifact => { + switch (type) { + case PublicKernelType.NON_PUBLIC: + throw new Error(`Can't prove non-public kernels`); + case PublicKernelType.SETUP: + return 'PublicKernelSetupArtifact'; + case PublicKernelType.APP_LOGIC: + return 'PublicKernelAppLogicArtifact'; + case PublicKernelType.TEARDOWN: + return 'PublicKernelTeardownArtifact'; + case PublicKernelType.TAIL: + return 'PublicKernelTailArtifact'; + } + }; + + for (const request of processedTx.publicKernelRequests) { + const artifact = getArtifactForPublicKernel(request.type); + logger.verbose(`Proving kernel type: ${PublicKernelType[request.type]}`); + let proof: Proof = makeEmptyProof(); + if (request.type === PublicKernelType.TAIL) { + await expect( + context.prover.getPublicTailProof(request).then(result => { + proof = result[1]; + }), + ).resolves.not.toThrow(); + } else { + await expect( + context.prover.getPublicKernelProof(request).then(result => { + proof = result[1]; + }), + ).resolves.not.toThrow(); + } + + logger.verbose(`Verifying kernel type: ${PublicKernelType[request.type]}`); + await expect(context.prover.verifyProof(artifact, proof)).resolves.not.toThrow(); + } + }, 60_000); +}); diff --git a/yarn-project/prover-client/src/prover/interface.ts b/yarn-project/prover-client/src/prover/interface.ts index 93a3460d87d..7ed8dad98a9 100644 --- a/yarn-project/prover-client/src/prover/interface.ts +++ b/yarn-project/prover-client/src/prover/interface.ts @@ -1,4 +1,4 @@ -import { type PublicKernelNonTailRequest, type PublicKernelTailRequest } from '@aztec/circuit-types'; +import { type PublicKernelNonTailRequest, type PublicKernelTailRequest, PublicKernelType } from '@aztec/circuit-types'; import { type BaseOrMergeRollupPublicInputs, type BaseParityInputs, @@ -8,11 +8,51 @@ import { type ParityPublicInputs, type Proof, type PublicCircuitPublicInputs, + type PublicKernelCircuitPrivateInputs, type PublicKernelCircuitPublicInputs, type RootParityInputs, type RootRollupInputs, type RootRollupPublicInputs, } from '@aztec/circuits.js'; +import { + type ServerProtocolArtifact, + convertPublicInnerRollupInputsToWitnessMap, + convertPublicInnerRollupOutputFromWitnessMap, + convertPublicSetupRollupInputsToWitnessMap, + convertPublicSetupRollupOutputFromWitnessMap, + convertPublicTeardownRollupInputsToWitnessMap, + convertPublicTeardownRollupOutputFromWitnessMap, +} from '@aztec/noir-protocol-circuits-types'; + +import { type WitnessMap } from '@noir-lang/types'; + +export type PublicKernelProvingOps = { + artifact: ServerProtocolArtifact; + convertInputs: (inputs: PublicKernelCircuitPrivateInputs) => WitnessMap; + convertOutputs: (outputs: WitnessMap) => PublicKernelCircuitPublicInputs; +}; + +export type KernelTypeToArtifact = Record; + +export const KernelArtifactMapping: KernelTypeToArtifact = { + [PublicKernelType.NON_PUBLIC]: undefined, + [PublicKernelType.APP_LOGIC]: { + artifact: 'PublicKernelAppLogicArtifact', + convertInputs: convertPublicInnerRollupInputsToWitnessMap, + convertOutputs: convertPublicInnerRollupOutputFromWitnessMap, + }, + [PublicKernelType.SETUP]: { + artifact: 'PublicKernelSetupArtifact', + convertInputs: convertPublicSetupRollupInputsToWitnessMap, + convertOutputs: convertPublicSetupRollupOutputFromWitnessMap, + }, + [PublicKernelType.TEARDOWN]: { + artifact: 'PublicKernelTeardownArtifact', + convertInputs: convertPublicTeardownRollupInputsToWitnessMap, + convertOutputs: convertPublicTeardownRollupOutputFromWitnessMap, + }, + [PublicKernelType.TAIL]: undefined, +}; /** * Generates proofs for parity and rollup circuits. @@ -59,6 +99,11 @@ export interface CircuitProver { * @param kernelRequest - Object containing the details of the proof required */ getPublicTailProof(kernelRequest: PublicKernelTailRequest): Promise<[KernelCircuitPublicInputs, Proof]>; + + /** + * Verifies a circuit proof + */ + verifyProof(artifact: ServerProtocolArtifact, proof: Proof): Promise; } /** diff --git a/yarn-project/prover-client/src/prover/test_circuit_prover.ts b/yarn-project/prover-client/src/prover/test_circuit_prover.ts index d6fe74e938e..63a1f74a1c2 100644 --- a/yarn-project/prover-client/src/prover/test_circuit_prover.ts +++ b/yarn-project/prover-client/src/prover/test_circuit_prover.ts @@ -8,7 +8,6 @@ import { type MergeRollupInputs, type ParityPublicInputs, type Proof, - type PublicKernelCircuitPrivateInputs, type PublicKernelCircuitPublicInputs, type RootParityInputs, type RootRollupInputs, @@ -29,14 +28,8 @@ import { convertBaseParityOutputsFromWitnessMap, convertMergeRollupInputsToWitnessMap, convertMergeRollupOutputsFromWitnessMap, - convertPublicInnerRollupInputsToWitnessMap, - convertPublicInnerRollupOutputFromWitnessMap, - convertPublicSetupRollupInputsToWitnessMap, - convertPublicSetupRollupOutputFromWitnessMap, convertPublicTailInputsToWitnessMap, convertPublicTailOutputFromWitnessMap, - convertPublicTeardownRollupInputsToWitnessMap, - convertPublicTeardownRollupOutputFromWitnessMap, convertRootParityInputsToWitnessMap, convertRootParityOutputsFromWitnessMap, convertRootRollupInputsToWitnessMap, @@ -46,37 +39,7 @@ import { } from '@aztec/noir-protocol-circuits-types'; import { type SimulationProvider, WASMSimulator } from '@aztec/simulator'; -import { type WitnessMap } from '@noir-lang/types'; - -import { type CircuitProver } from './interface.js'; - -type PublicKernelProvingOps = { - artifact: ServerProtocolArtifact; - convertInputs: (inputs: PublicKernelCircuitPrivateInputs) => WitnessMap; - convertOutputs: (outputs: WitnessMap) => PublicKernelCircuitPublicInputs; -}; - -type KernelTypeToArtifact = Record; - -const KernelArtifactMapping: KernelTypeToArtifact = { - [PublicKernelType.NON_PUBLIC]: undefined, - [PublicKernelType.APP_LOGIC]: { - artifact: 'PublicKernelAppLogicArtifact', - convertInputs: convertPublicInnerRollupInputsToWitnessMap, - convertOutputs: convertPublicInnerRollupOutputFromWitnessMap, - }, - [PublicKernelType.SETUP]: { - artifact: 'PublicKernelSetupArtifact', - convertInputs: convertPublicSetupRollupInputsToWitnessMap, - convertOutputs: convertPublicSetupRollupOutputFromWitnessMap, - }, - [PublicKernelType.TEARDOWN]: { - artifact: 'PublicKernelTeardownArtifact', - convertInputs: convertPublicTeardownRollupInputsToWitnessMap, - convertOutputs: convertPublicTeardownRollupOutputFromWitnessMap, - }, - [PublicKernelType.TAIL]: undefined, -}; +import { type CircuitProver, KernelArtifactMapping } from './interface.js'; /** * A class for use in testing situations (e2e, unit test etc) @@ -201,4 +164,9 @@ export class TestCircuitProver implements CircuitProver { const result = convertPublicTailOutputFromWitnessMap(witness); return [result, makeEmptyProof()]; } + + // Not implemented for test circuits + public verifyProof(_1: ServerProtocolArtifact, _2: Proof): Promise { + throw new Error('Method not implemented.'); + } } From 8ff9767c213d172ee1568aeedaa7265ead7b5466 Mon Sep 17 00:00:00 2001 From: Santiago Palladino Date: Thu, 18 Apr 2024 15:29:36 -0300 Subject: [PATCH 020/102] chore: Check working copy is clean before extract-repo (#5851) This prevents bootstrap fast from downloading artifacts that do not match the source currently in the working copy. --- build-system/scripts/check_working_copy_clean | 21 +++++++++++++++++++ build-system/scripts/extract_repo | 5 +++++ 2 files changed, 26 insertions(+) create mode 100755 build-system/scripts/check_working_copy_clean diff --git a/build-system/scripts/check_working_copy_clean b/build-system/scripts/check_working_copy_clean new file mode 100755 index 00000000000..8adb9f90852 --- /dev/null +++ b/build-system/scripts/check_working_copy_clean @@ -0,0 +1,21 @@ +#!/usr/bin/env bash +# If this script fails (nonzero exit), then the working copy is not clean. + +[ -n "${BUILD_SYSTEM_DEBUG:-}" ] && set -x # conditionally trace +set -eu + +REPOSITORY=$1 + +# Get list of rebuild patterns, concat them with regex 'or' (|), and double escape \ for awk -v. +AWK_PATTERN=$(query_manifest rebuildPatterns $REPOSITORY | tr '\n' '|' | sed 's/\\/\\\\/g') +# Remove the trailing '|'. +AWK_PATTERN=${AWK_PATTERN%|} + +cd "$(git rev-parse --show-toplevel)" + +# Check if there is anything dirty in the local copy, if so, bail with non-zero exit code. +CHANGED_FILES=$(git status --porcelain | awk -v pattern="($AWK_PATTERN)" '$2 ~ pattern {print $2}') +if [ -n "$CHANGED_FILES" ]; then + echo $CHANGED_FILES + exit 1 +fi \ No newline at end of file diff --git a/build-system/scripts/extract_repo b/build-system/scripts/extract_repo index 9adadf2d62c..94d435962b3 100755 --- a/build-system/scripts/extract_repo +++ b/build-system/scripts/extract_repo @@ -7,6 +7,11 @@ set -eu REPOSITORY=$1 shift +if ! check_working_copy_clean $REPOSITORY; then + echo "The working copy for $REPOSITORY or one of its dependencies as listed in build manifest is not clean. Aborting extract_repo." + exit 1 +fi + IMAGE_COMMIT_URI=$(calculate_image_uri $REPOSITORY) if docker image ls --format "{{.Repository}}:{{.Tag}}" | grep -q -w "$IMAGE_COMMIT_URI$"; then echo -e "Image exists locally. No need to pull." From ec21fb8251c34d535fd0c5e08f354cfa22c25320 Mon Sep 17 00:00:00 2001 From: Santiago Palladino Date: Thu, 18 Apr 2024 19:31:43 -0300 Subject: [PATCH 021/102] chore: Revert "Check working copy is clean before extract-repo (#5851)" This reverts commit 8ff9767c213d172ee1568aeedaa7265ead7b5466. --- build-system/scripts/check_working_copy_clean | 21 ------------------- build-system/scripts/extract_repo | 5 ----- 2 files changed, 26 deletions(-) delete mode 100755 build-system/scripts/check_working_copy_clean diff --git a/build-system/scripts/check_working_copy_clean b/build-system/scripts/check_working_copy_clean deleted file mode 100755 index 8adb9f90852..00000000000 --- a/build-system/scripts/check_working_copy_clean +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env bash -# If this script fails (nonzero exit), then the working copy is not clean. - -[ -n "${BUILD_SYSTEM_DEBUG:-}" ] && set -x # conditionally trace -set -eu - -REPOSITORY=$1 - -# Get list of rebuild patterns, concat them with regex 'or' (|), and double escape \ for awk -v. -AWK_PATTERN=$(query_manifest rebuildPatterns $REPOSITORY | tr '\n' '|' | sed 's/\\/\\\\/g') -# Remove the trailing '|'. -AWK_PATTERN=${AWK_PATTERN%|} - -cd "$(git rev-parse --show-toplevel)" - -# Check if there is anything dirty in the local copy, if so, bail with non-zero exit code. -CHANGED_FILES=$(git status --porcelain | awk -v pattern="($AWK_PATTERN)" '$2 ~ pattern {print $2}') -if [ -n "$CHANGED_FILES" ]; then - echo $CHANGED_FILES - exit 1 -fi \ No newline at end of file diff --git a/build-system/scripts/extract_repo b/build-system/scripts/extract_repo index 94d435962b3..9adadf2d62c 100755 --- a/build-system/scripts/extract_repo +++ b/build-system/scripts/extract_repo @@ -7,11 +7,6 @@ set -eu REPOSITORY=$1 shift -if ! check_working_copy_clean $REPOSITORY; then - echo "The working copy for $REPOSITORY or one of its dependencies as listed in build manifest is not clean. Aborting extract_repo." - exit 1 -fi - IMAGE_COMMIT_URI=$(calculate_image_uri $REPOSITORY) if docker image ls --format "{{.Repository}}:{{.Tag}}" | grep -q -w "$IMAGE_COMMIT_URI$"; then echo -e "Image exists locally. No need to pull." From 4646a746068f8da8421be86e9ea25e3f18009d93 Mon Sep 17 00:00:00 2001 From: AztecBot Date: Fri, 19 Apr 2024 02:11:00 +0000 Subject: [PATCH 022/102] git subrepo push --branch=master barretenberg subrepo: subdir: "barretenberg" merged: "1b2ec21d9" upstream: origin: "https://github.com/AztecProtocol/barretenberg" branch: "master" commit: "1b2ec21d9" git-subrepo: version: "0.4.6" origin: "???" commit: "???" [skip ci] --- barretenberg/.gitrepo | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/barretenberg/.gitrepo b/barretenberg/.gitrepo index 107719b5a24..cc89e603d40 100644 --- a/barretenberg/.gitrepo +++ b/barretenberg/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = https://github.com/AztecProtocol/barretenberg branch = master - commit = ed310b6d7e43b47913afacb717513cd4ff2d57dd - parent = 3fb94c0cd5ffba20a99b97c0088ae5ef357c205d + commit = 1b2ec21d9f8372ec5d79a510273e043bd3d79bb2 + parent = ec21fb8251c34d535fd0c5e08f354cfa22c25320 method = merge cmdver = 0.4.6 From 8b33a58e095815d5b131ab3fbd668c4e88680e13 Mon Sep 17 00:00:00 2001 From: AztecBot Date: Fri, 19 Apr 2024 02:11:24 +0000 Subject: [PATCH 023/102] chore: replace relative paths to noir-protocol-circuits --- noir-projects/aztec-nr/aztec/Nargo.toml | 2 +- noir-projects/aztec-nr/tests/Nargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/Nargo.toml b/noir-projects/aztec-nr/aztec/Nargo.toml index 7a1f1af5863..2cbb43ab278 100644 --- a/noir-projects/aztec-nr/aztec/Nargo.toml +++ b/noir-projects/aztec-nr/aztec/Nargo.toml @@ -5,4 +5,4 @@ compiler_version = ">=0.18.0" type = "lib" [dependencies] -protocol_types = { path = "../../noir-protocol-circuits/crates/types" } +protocol_types = { git="https://github.com/AztecProtocol/aztec-packages", tag="aztec-packages-v0.35.1", directory="noir-projects/noir-protocol-circuits/crates/types" } diff --git a/noir-projects/aztec-nr/tests/Nargo.toml b/noir-projects/aztec-nr/tests/Nargo.toml index 13404b37324..dfed895aad0 100644 --- a/noir-projects/aztec-nr/tests/Nargo.toml +++ b/noir-projects/aztec-nr/tests/Nargo.toml @@ -6,4 +6,4 @@ type = "lib" [dependencies] aztec = { path = "../aztec" } -protocol_types = { path = "../../noir-protocol-circuits/crates/types" } +protocol_types = { git="https://github.com/AztecProtocol/aztec-packages", tag="aztec-packages-v0.35.1", directory="noir-projects/noir-protocol-circuits/crates/types" } From 473b24facca6abdeef516cba26227741f918ba10 Mon Sep 17 00:00:00 2001 From: AztecBot Date: Fri, 19 Apr 2024 02:11:25 +0000 Subject: [PATCH 024/102] git_subrepo.sh: Fix parent in .gitrepo file. [skip ci] --- noir-projects/aztec-nr/.gitrepo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noir-projects/aztec-nr/.gitrepo b/noir-projects/aztec-nr/.gitrepo index a2e45aaf6bc..55be2bd1a62 100644 --- a/noir-projects/aztec-nr/.gitrepo +++ b/noir-projects/aztec-nr/.gitrepo @@ -9,4 +9,4 @@ commit = b3b3b3c175697928e729895da32681c72e08912b method = merge cmdver = 0.4.6 - parent = b8d73dd57ffae1c5b63cb4bd7364c2038af49f50 + parent = 41559b0efc3968a2e36961c40828ee1c1a4cae4c From e14cffa74332f422ed23d7f306db696567278551 Mon Sep 17 00:00:00 2001 From: AztecBot Date: Fri, 19 Apr 2024 02:11:29 +0000 Subject: [PATCH 025/102] git subrepo push --branch=master noir-projects/aztec-nr subrepo: subdir: "noir-projects/aztec-nr" merged: "24dd2f628" upstream: origin: "https://github.com/AztecProtocol/aztec-nr" branch: "master" commit: "24dd2f628" git-subrepo: version: "0.4.6" origin: "???" commit: "???" [skip ci] --- noir-projects/aztec-nr/.gitrepo | 4 ++-- noir-projects/aztec-nr/aztec/Nargo.toml | 2 +- noir-projects/aztec-nr/tests/Nargo.toml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/noir-projects/aztec-nr/.gitrepo b/noir-projects/aztec-nr/.gitrepo index 55be2bd1a62..1db63baeb42 100644 --- a/noir-projects/aztec-nr/.gitrepo +++ b/noir-projects/aztec-nr/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = https://github.com/AztecProtocol/aztec-nr branch = master - commit = b3b3b3c175697928e729895da32681c72e08912b + commit = 24dd2f62869ceae261082ed6fc2a05adbe288b57 method = merge cmdver = 0.4.6 - parent = 41559b0efc3968a2e36961c40828ee1c1a4cae4c + parent = e7b29d130cdc03cbc1bb94b26740f2c8176c72bc diff --git a/noir-projects/aztec-nr/aztec/Nargo.toml b/noir-projects/aztec-nr/aztec/Nargo.toml index 2cbb43ab278..7a1f1af5863 100644 --- a/noir-projects/aztec-nr/aztec/Nargo.toml +++ b/noir-projects/aztec-nr/aztec/Nargo.toml @@ -5,4 +5,4 @@ compiler_version = ">=0.18.0" type = "lib" [dependencies] -protocol_types = { git="https://github.com/AztecProtocol/aztec-packages", tag="aztec-packages-v0.35.1", directory="noir-projects/noir-protocol-circuits/crates/types" } +protocol_types = { path = "../../noir-protocol-circuits/crates/types" } diff --git a/noir-projects/aztec-nr/tests/Nargo.toml b/noir-projects/aztec-nr/tests/Nargo.toml index dfed895aad0..13404b37324 100644 --- a/noir-projects/aztec-nr/tests/Nargo.toml +++ b/noir-projects/aztec-nr/tests/Nargo.toml @@ -6,4 +6,4 @@ type = "lib" [dependencies] aztec = { path = "../aztec" } -protocol_types = { git="https://github.com/AztecProtocol/aztec-packages", tag="aztec-packages-v0.35.1", directory="noir-projects/noir-protocol-circuits/crates/types" } +protocol_types = { path = "../../noir-protocol-circuits/crates/types" } From 27129e6d483e787abea5084c029e560d5d4b5b0e Mon Sep 17 00:00:00 2001 From: Alex Gherghisan Date: Fri, 19 Apr 2024 09:21:19 +0100 Subject: [PATCH 026/102] fix: MemoryFifo return null when empty and timeout 0 (#5753) `MemoryFifo.get(0)` rejects immediately with a `TimeoutError` if no items are available --- .../foundation/src/fifo/memory_fifo.ts | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/yarn-project/foundation/src/fifo/memory_fifo.ts b/yarn-project/foundation/src/fifo/memory_fifo.ts index bcd0145fb58..d7ef956d869 100644 --- a/yarn-project/foundation/src/fifo/memory_fifo.ts +++ b/yarn-project/foundation/src/fifo/memory_fifo.ts @@ -24,13 +24,17 @@ export class MemoryFifo { } /** - * Returns next item within the queue, or blocks until and item has been put into the queue. - * If given a timeout, the promise will reject if no item is received after `timeout` seconds. + * Returns next item within the queue, or blocks until an item has been put into the queue. + * + * If given a timeout, the promise will reject if no item is received after `timeoutSec` seconds. + * If the timeout is undefined (default), this call will block until an item is available or the queue is closed. + * If the timeout is 0 and there are no items available then the queue will immediately reject with a TimeoutError. + * * If the queue is flushing, `null` is returned. - * @param timeout - The timeout in seconds. + * @param timeoutSec - The timeout in seconds. * @returns A result promise. */ - public get(timeout?: number): Promise { + public get(timeoutSec?: number): Promise { if (this.items.length) { return Promise.resolve(this.items.shift()!); } @@ -39,10 +43,16 @@ export class MemoryFifo { return Promise.resolve(null); } + // if the caller doesn't want to wait for an item to be available + // immediately reject with a Timeout error + if (timeoutSec === 0) { + return Promise.reject(new TimeoutError('Timeout getting item from queue.')); + } + return new Promise((resolve, reject) => { this.waiting.push(resolve); - if (timeout) { + if (timeoutSec) { setTimeout(() => { const index = this.waiting.findIndex(r => r === resolve); if (index > -1) { @@ -50,7 +60,7 @@ export class MemoryFifo { const err = new TimeoutError('Timeout getting item from queue.'); reject(err); } - }, timeout * 1000); + }, timeoutSec * 1000); } }); } From afeef17e14054f8ee95a6244c1b165435fddaa50 Mon Sep 17 00:00:00 2001 From: Alex Gherghisan Date: Fri, 19 Apr 2024 09:44:51 +0100 Subject: [PATCH 027/102] feat: add promiseWithResolvers (#5808) Add new utility function to `@aztec/foundation` to helpt with hand-rolled promises. --- yarn-project/foundation/package.json | 3 +- yarn-project/foundation/src/promise/index.ts | 2 + .../foundation/src/promise/running-promise.ts | 47 ++++++++++++++ yarn-project/foundation/src/promise/utils.ts | 29 +++++++++ .../foundation/src/running-promise/index.ts | 61 +------------------ 5 files changed, 81 insertions(+), 61 deletions(-) create mode 100644 yarn-project/foundation/src/promise/index.ts create mode 100644 yarn-project/foundation/src/promise/running-promise.ts create mode 100644 yarn-project/foundation/src/promise/utils.ts diff --git a/yarn-project/foundation/package.json b/yarn-project/foundation/package.json index 04ceb11d013..df881ec593c 100644 --- a/yarn-project/foundation/package.json +++ b/yarn-project/foundation/package.json @@ -39,7 +39,8 @@ "./noir": "./dest/noir/index.js", "./testing": "./dest/testing/index.js", "./array": "./dest/array/index.js", - "./validation": "./dest/validation/index.js" + "./validation": "./dest/validation/index.js", + "./promise": "./dest/promise/index.js" }, "scripts": { "build": "yarn clean && tsc -b", diff --git a/yarn-project/foundation/src/promise/index.ts b/yarn-project/foundation/src/promise/index.ts new file mode 100644 index 00000000000..8a863fdd488 --- /dev/null +++ b/yarn-project/foundation/src/promise/index.ts @@ -0,0 +1,2 @@ +export * from './running-promise.js'; +export * from './utils.js'; diff --git a/yarn-project/foundation/src/promise/running-promise.ts b/yarn-project/foundation/src/promise/running-promise.ts new file mode 100644 index 00000000000..2c3c7f15c33 --- /dev/null +++ b/yarn-project/foundation/src/promise/running-promise.ts @@ -0,0 +1,47 @@ +import { InterruptibleSleep } from '../sleep/index.js'; + +/** + * RunningPromise is a utility class that helps manage the execution of an asynchronous function + * at a specified polling interval. It allows starting, stopping, and checking the status of the + * internally managed promise. The class also supports interrupting the polling process when stopped. + */ +export class RunningPromise { + private running = false; + private runningPromise = Promise.resolve(); + private interruptibleSleep = new InterruptibleSleep(); + + constructor(private fn: () => Promise, private pollingIntervalMS = 10000) {} + + /** + * Starts the running promise. + */ + public start() { + this.running = true; + + const poll = async () => { + while (this.running) { + await this.fn(); + await this.interruptibleSleep.sleep(this.pollingIntervalMS); + } + }; + this.runningPromise = poll(); + } + + /** + * Stops the running promise, resolves any pending interruptible sleep, + * and waits for the currently executing function to complete. + */ + async stop(): Promise { + this.running = false; + this.interruptibleSleep.interrupt(); + await this.runningPromise; + } + + /** + * Checks if the running promise is currently active. + * @returns True if the promise is running. + */ + public isRunning() { + return this.running; + } +} diff --git a/yarn-project/foundation/src/promise/utils.ts b/yarn-project/foundation/src/promise/utils.ts new file mode 100644 index 00000000000..fd48f3b0b99 --- /dev/null +++ b/yarn-project/foundation/src/promise/utils.ts @@ -0,0 +1,29 @@ +export type PromiseWithResolvers = { + promise: Promise; + resolve: (value: T) => void; + reject: (reason?: any) => void; +}; + +/** + * A polyfill for the Promise.withResolvers proposed API. + * @see https://github.com/tc39/proposal-promise-with-resolvers + * @returns A promise with resolvers. + */ +export function promiseWithResolvers(): PromiseWithResolvers { + // use ! operator to avoid TS error + let resolve!: (value: T) => void; + let reject!: (reason?: any) => void; + + // the ES spec guarantees that the promise executor is called synchronously + // so the resolve and reject functions will be defined + const promise = new Promise((res, rej) => { + resolve = res; + reject = rej; + }); + + return { + promise, + resolve, + reject, + }; +} diff --git a/yarn-project/foundation/src/running-promise/index.ts b/yarn-project/foundation/src/running-promise/index.ts index d362ebe2ad1..24ae1a30bed 100644 --- a/yarn-project/foundation/src/running-promise/index.ts +++ b/yarn-project/foundation/src/running-promise/index.ts @@ -1,60 +1 @@ -/** - * RunningPromise is a utility class that helps manage the execution of an asynchronous function - * at a specified polling interval. It allows starting, stopping, and checking the status of the - * internally managed promise. The class also supports interrupting the polling process when stopped. - */ -export class RunningPromise { - private running = false; - private runningPromise = Promise.resolve(); - private interruptPromise = Promise.resolve(); - private interruptResolve = () => {}; - constructor(private fn: () => Promise, private pollingInterval = 10000) {} - - /** - * Starts the running promise. - */ - public start() { - this.running = true; - this.interruptPromise = new Promise(resolve => (this.interruptResolve = resolve)); - - const poll = async () => { - while (this.running) { - await this.fn(); - await this.interruptibleSleep(this.pollingInterval); - } - }; - this.runningPromise = poll(); - } - - /** - * Stops the running promise, resolves any pending interruptible sleep, - * and waits for the currently executing function to complete. - */ - async stop(): Promise { - this.running = false; - this.interruptResolve(); - await this.runningPromise; - } - - /** - * A sleep function that can be interrupted before the specified time. - * The sleep duration is determined by 'timeInMs', and it can be terminated early if the 'interruptPromise' is resolved. - * @param timeInMs - The time in milliseconds. - */ - private async interruptibleSleep(timeInMs: number) { - let timeout!: NodeJS.Timeout; - const sleepPromise = new Promise(resolve => { - timeout = setTimeout(resolve, timeInMs); - }); - await Promise.race([sleepPromise, this.interruptPromise]); - clearTimeout(timeout); - } - - /** - * Checks if the running promise is currently active. - * @returns True if the promise is running. - */ - public isRunning() { - return this.running; - } -} +export * from '../promise/running-promise.js'; From 55ff1251c2c1c02ecbbaadfa38764c5847fee910 Mon Sep 17 00:00:00 2001 From: Santiago Palladino Date: Fri, 19 Apr 2024 05:52:09 -0300 Subject: [PATCH 028/102] fix: Temporarily exclude bytecode from class id computation (#5857) --- l1-contracts/src/core/libraries/ConstantsGen.sol | 2 +- .../noir-protocol-circuits/crates/types/src/constants.nr | 2 +- yarn-project/circuits.js/src/constants.gen.ts | 2 +- yarn-project/circuits.js/src/contract/artifact_hash.ts | 8 +++++--- .../contract/private_function_membership_proof.test.ts | 3 ++- .../unconstrained_function_membership_proof.test.ts | 3 ++- 6 files changed, 12 insertions(+), 8 deletions(-) diff --git a/l1-contracts/src/core/libraries/ConstantsGen.sol b/l1-contracts/src/core/libraries/ConstantsGen.sol index 6661fc67443..586ce6be731 100644 --- a/l1-contracts/src/core/libraries/ConstantsGen.sol +++ b/l1-contracts/src/core/libraries/ConstantsGen.sol @@ -89,7 +89,7 @@ library Constants { uint256 internal constant DEPLOYER_CONTRACT_INSTANCE_DEPLOYED_MAGIC_VALUE = 0x85864497636cf755ae7bde03f267ce01a520981c21c3682aaf82a631; uint256 internal constant DEPLOYER_CONTRACT_ADDRESS = - 0x1b5ecf3d26907648cf737f4304759b8c5850478e839e72f8ce1f5791b286e8f2; + 0x161b653b72ac5aa2982ce485b242b5c1e09afcbf27b89696f5a4e3151be37245; uint256 internal constant AZTEC_ADDRESS_LENGTH = 1; uint256 internal constant DIMENSION_GAS_SETTINGS_LENGTH = 3; uint256 internal constant GAS_FEES_LENGTH = 3; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr index e8e5f1cf2ee..cd982b40f1f 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr @@ -126,7 +126,7 @@ global REGISTERER_UNCONSTRAINED_FUNCTION_BROADCASTED_MAGIC_VALUE = 0xe7af8166354 // CONTRACT INSTANCE CONSTANTS // sha224sum 'struct ContractInstanceDeployed' global DEPLOYER_CONTRACT_INSTANCE_DEPLOYED_MAGIC_VALUE = 0x85864497636cf755ae7bde03f267ce01a520981c21c3682aaf82a631; -global DEPLOYER_CONTRACT_ADDRESS = 0x1b5ecf3d26907648cf737f4304759b8c5850478e839e72f8ce1f5791b286e8f2; +global DEPLOYER_CONTRACT_ADDRESS = 0x161b653b72ac5aa2982ce485b242b5c1e09afcbf27b89696f5a4e3151be37245; // LENGTH OF STRUCTS SERIALIZED TO FIELDS global AZTEC_ADDRESS_LENGTH = 1; diff --git a/yarn-project/circuits.js/src/constants.gen.ts b/yarn-project/circuits.js/src/constants.gen.ts index 6441113ed89..de9c6e4cc0e 100644 --- a/yarn-project/circuits.js/src/constants.gen.ts +++ b/yarn-project/circuits.js/src/constants.gen.ts @@ -74,7 +74,7 @@ export const REGISTERER_UNCONSTRAINED_FUNCTION_BROADCASTED_MAGIC_VALUE = 0xe7af816635466f128568edb04c9fa024f6c87fb9010fdbffa68b3d99n; export const DEPLOYER_CONTRACT_INSTANCE_DEPLOYED_MAGIC_VALUE = 0x85864497636cf755ae7bde03f267ce01a520981c21c3682aaf82a631n; -export const DEPLOYER_CONTRACT_ADDRESS = 0x1b5ecf3d26907648cf737f4304759b8c5850478e839e72f8ce1f5791b286e8f2n; +export const DEPLOYER_CONTRACT_ADDRESS = 0x161b653b72ac5aa2982ce485b242b5c1e09afcbf27b89696f5a4e3151be37245n; export const AZTEC_ADDRESS_LENGTH = 1; export const DIMENSION_GAS_SETTINGS_LENGTH = 3; export const GAS_FEES_LENGTH = 3; diff --git a/yarn-project/circuits.js/src/contract/artifact_hash.ts b/yarn-project/circuits.js/src/contract/artifact_hash.ts index efad51e999c..58be0f2437f 100644 --- a/yarn-project/circuits.js/src/contract/artifact_hash.ts +++ b/yarn-project/circuits.js/src/contract/artifact_hash.ts @@ -94,9 +94,11 @@ export function computeFunctionArtifactHash( | (Pick & { functionMetadataHash: Fr; selector: FunctionSelector }), ) { const selector = 'selector' in fn ? fn.selector : FunctionSelector.fromNameAndParameters(fn); - const bytecodeHash = sha256Fr(fn.bytecode).toBuffer(); - const metadataHash = 'functionMetadataHash' in fn ? fn.functionMetadataHash : computeFunctionMetadataHash(fn); - return sha256Fr(Buffer.concat([numToUInt8(VERSION), selector.toBuffer(), metadataHash.toBuffer(), bytecodeHash])); + // TODO(#5860): make bytecode part of artifact hash preimage again + // const bytecodeHash = sha256Fr(fn.bytecode).toBuffer(); + // const metadataHash = 'functionMetadataHash' in fn ? fn.functionMetadataHash : computeFunctionMetadataHash(fn); + // return sha256Fr(Buffer.concat([numToUInt8(VERSION), selector.toBuffer(), metadataHash.toBuffer(), bytecodeHash])); + return sha256Fr(Buffer.concat([numToUInt8(VERSION), selector.toBuffer()])); } export function computeFunctionMetadataHash(fn: FunctionArtifact) { diff --git a/yarn-project/circuits.js/src/contract/private_function_membership_proof.test.ts b/yarn-project/circuits.js/src/contract/private_function_membership_proof.test.ts index 19b85857f26..6909cd68c30 100644 --- a/yarn-project/circuits.js/src/contract/private_function_membership_proof.test.ts +++ b/yarn-project/circuits.js/src/contract/private_function_membership_proof.test.ts @@ -31,7 +31,8 @@ describe('private_function_membership_proof', () => { expect(isValidPrivateFunctionMembershipProof(fn, contractClass)).toBeTruthy(); }); - test.each([ + // TODO(#5860): Re-enable this test once noir non-determinism is addressed + test.skip.each([ 'artifactTreeSiblingPath', 'artifactMetadataHash', 'functionMetadataHash', diff --git a/yarn-project/circuits.js/src/contract/unconstrained_function_membership_proof.test.ts b/yarn-project/circuits.js/src/contract/unconstrained_function_membership_proof.test.ts index 35b983e08e2..e128aa7abb0 100644 --- a/yarn-project/circuits.js/src/contract/unconstrained_function_membership_proof.test.ts +++ b/yarn-project/circuits.js/src/contract/unconstrained_function_membership_proof.test.ts @@ -48,7 +48,8 @@ describe('unconstrained_function_membership_proof', () => { expect(isValidUnconstrainedFunctionMembershipProof(fn, contractClass)).toBeTruthy(); }); - test.each(['artifactTreeSiblingPath', 'artifactMetadataHash', 'functionMetadataHash'] as const)( + // TODO(#5860): Re-enable this test once noir non-determinism is addressed + test.skip.each(['artifactTreeSiblingPath', 'artifactMetadataHash', 'functionMetadataHash'] as const)( 'fails proof if %s is mangled', field => { const proof = createUnconstrainedFunctionMembershipProof(selector, artifact); From b61502f372e5b09d8bff138fdb74e3175b5186ff Mon Sep 17 00:00:00 2001 From: Facundo Date: Fri, 19 Apr 2024 11:37:04 +0100 Subject: [PATCH 029/102] chore: bump public call depth (#5845) --- l1-contracts/src/core/libraries/ConstantsGen.sol | 4 ++-- .../crates/types/src/abis/private_call_stack_item.nr | 2 +- .../types/src/abis/private_circuit_public_inputs.nr | 2 +- .../crates/types/src/abis/public_call_stack_item.nr | 4 ++-- .../crates/types/src/abis/public_circuit_public_inputs.nr | 2 +- .../noir-protocol-circuits/crates/types/src/constants.nr | 4 ++-- yarn-project/circuits.js/src/constants.gen.ts | 4 ++-- .../__snapshots__/private_call_stack_item.test.ts.snap | 4 ++-- .../private_circuit_public_inputs.test.ts.snap | 4 ++-- .../__snapshots__/public_call_stack_item.test.ts.snap | 8 +++++--- .../public_circuit_public_inputs.test.ts.snap | 4 ++-- .../src/structs/public_call_stack_item.test.ts | 6 ++++++ 12 files changed, 28 insertions(+), 20 deletions(-) diff --git a/l1-contracts/src/core/libraries/ConstantsGen.sol b/l1-contracts/src/core/libraries/ConstantsGen.sol index 586ce6be731..8f86070367e 100644 --- a/l1-contracts/src/core/libraries/ConstantsGen.sol +++ b/l1-contracts/src/core/libraries/ConstantsGen.sol @@ -18,7 +18,7 @@ library Constants { uint256 internal constant MAX_NEW_NOTE_HASHES_PER_CALL = 16; uint256 internal constant MAX_NEW_NULLIFIERS_PER_CALL = 16; uint256 internal constant MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL = 4; - uint256 internal constant MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL = 4; + uint256 internal constant MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL = 16; uint256 internal constant MAX_NEW_L2_TO_L1_MSGS_PER_CALL = 2; uint256 internal constant MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL = 16; uint256 internal constant MAX_PUBLIC_DATA_READS_PER_CALL = 16; @@ -31,7 +31,7 @@ library Constants { uint256 internal constant MAX_NEW_NOTE_HASHES_PER_TX = 64; uint256 internal constant MAX_NEW_NULLIFIERS_PER_TX = 64; uint256 internal constant MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX = 8; - uint256 internal constant MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX = 8; + uint256 internal constant MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX = 32; uint256 internal constant MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX = 32; uint256 internal constant MAX_PUBLIC_DATA_READS_PER_TX = 32; uint256 internal constant MAX_NEW_L2_TO_L1_MSGS_PER_TX = 2; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr index 45b7f67c493..4f353a7d7ac 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr @@ -85,6 +85,6 @@ fn empty_hash() { let hash = item.hash(); // Value from private_call_stack_item.test.ts "computes empty item hash" test - let test_data_empty_hash = 0x24185d8e88fe796dec6e400f3d6c7572cefd85cea80591f268f08a9350992c48; + let test_data_empty_hash = 0x2cbdfd59ceb55fcc4dbe43b9d6f052f5ca448ef5990b005b9927e578b1b69b6c; assert_eq(hash, test_data_empty_hash); } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr index 09fbc60463e..f60b8997987 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr @@ -216,6 +216,6 @@ fn empty_hash() { let inputs = PrivateCircuitPublicInputs::empty(); let hash = inputs.hash(); // Value from private_circuit_public_inputs.test.ts "computes empty item hash" test - let test_data_empty_hash = 0x24ea9ab3fc039778bef8e7212f6a09feec1019db19b449333b523a08b812ee88; + let test_data_empty_hash = 0x2c1ec6595f8d43f5fc983441bc75a84d2384008f5bd7a1d499da057130abe6cd; assert_eq(hash, test_data_empty_hash); } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_stack_item.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_stack_item.nr index 7bafc07b37d..ea5f4637f06 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_stack_item.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_stack_item.nr @@ -69,7 +69,7 @@ mod tests { let call_stack_item = PublicCallStackItem { contract_address, public_inputs, is_execution_request: true, function_data }; // Value from public_call_stack_item.test.ts "Computes a callstack item request hash" test - let test_data_call_stack_item_request_hash = 0x134d01b778664dbc1ffa953008ce28f72b0cb258533776f10df59a59d791e972; + let test_data_call_stack_item_request_hash = 0x23066ad690c088120f8397cfeb2ef5608d4517342c7ff9fcb713009933ef1c61; assert_eq(call_stack_item.hash(), test_data_call_stack_item_request_hash); } @@ -87,7 +87,7 @@ mod tests { let call_stack_item = PublicCallStackItem { contract_address, public_inputs, is_execution_request: false, function_data }; // Value from public_call_stack_item.test.ts "Computes a callstack item hash" test - let test_data_call_stack_item_hash = 0x0c0d60d424315af5f106a802b250c27c613a9ec1c0f583c6ad806cf22fe66a13; + let test_data_call_stack_item_hash = 0x1ef9292cf3383605672c06dd50a12c251aa1f037cd826c0fc70d8ee5324e88c4; assert_eq(call_stack_item.hash(), test_data_call_stack_item_hash); } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_circuit_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_circuit_public_inputs.nr index ca5dc4742f3..602daf873db 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_circuit_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_circuit_public_inputs.nr @@ -183,6 +183,6 @@ fn empty_hash() { let hash = inputs.hash(); // Value from public_circuit_public_inputs.test.ts "computes empty item hash" test - let test_data_empty_hash = 0x1092820bc987359300ff136abf020d58218e1b3484e03d756c76e81ac56ccbf7; + let test_data_empty_hash = 0x048912d56248af479f8d7ecedbba7092d27741b10075a989e040f8e3242a7a3f; assert_eq(hash, test_data_empty_hash); } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr index cd982b40f1f..2907f5cc264 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr @@ -25,7 +25,7 @@ global ARGS_LENGTH: u64 = 16; global MAX_NEW_NOTE_HASHES_PER_CALL: u64 = 16; global MAX_NEW_NULLIFIERS_PER_CALL: u64 = 16; global MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL: u64 = 4; -global MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL: u64 = 4; +global MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL: u64 = 16; global MAX_NEW_L2_TO_L1_MSGS_PER_CALL: u64 = 2; global MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL: u64 = 16; global MAX_PUBLIC_DATA_READS_PER_CALL: u64 = 16; @@ -40,7 +40,7 @@ global MAX_UNENCRYPTED_LOGS_PER_CALL: u64 = 4; // If modifying, update DEPLOYER_ global MAX_NEW_NOTE_HASHES_PER_TX: u64 = 64; global MAX_NEW_NULLIFIERS_PER_TX: u64 = 64; global MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX: u64 = 8; -global MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX: u64 = 8; +global MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX: u64 = 32; global MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX: u64 = 32; global MAX_PUBLIC_DATA_READS_PER_TX: u64 = 32; global MAX_NEW_L2_TO_L1_MSGS_PER_TX: u64 = 2; diff --git a/yarn-project/circuits.js/src/constants.gen.ts b/yarn-project/circuits.js/src/constants.gen.ts index de9c6e4cc0e..6b544ae99a3 100644 --- a/yarn-project/circuits.js/src/constants.gen.ts +++ b/yarn-project/circuits.js/src/constants.gen.ts @@ -4,7 +4,7 @@ export const ARGS_LENGTH = 16; export const MAX_NEW_NOTE_HASHES_PER_CALL = 16; export const MAX_NEW_NULLIFIERS_PER_CALL = 16; export const MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL = 4; -export const MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL = 4; +export const MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL = 16; export const MAX_NEW_L2_TO_L1_MSGS_PER_CALL = 2; export const MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL = 16; export const MAX_PUBLIC_DATA_READS_PER_CALL = 16; @@ -17,7 +17,7 @@ export const MAX_UNENCRYPTED_LOGS_PER_CALL = 4; export const MAX_NEW_NOTE_HASHES_PER_TX = 64; export const MAX_NEW_NULLIFIERS_PER_TX = 64; export const MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX = 8; -export const MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX = 8; +export const MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX = 32; export const MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX = 32; export const MAX_PUBLIC_DATA_READS_PER_TX = 32; export const MAX_NEW_L2_TO_L1_MSGS_PER_TX = 2; diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/private_call_stack_item.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/private_call_stack_item.test.ts.snap index 46d4e2bf80d..5ffb5c6d63d 100644 --- a/yarn-project/circuits.js/src/structs/__snapshots__/private_call_stack_item.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/__snapshots__/private_call_stack_item.test.ts.snap @@ -1,5 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`PrivateCallStackItem computes empty item hash 1`] = `Fr<0x24185d8e88fe796dec6e400f3d6c7572cefd85cea80591f268f08a9350992c48>`; +exports[`PrivateCallStackItem computes empty item hash 1`] = `Fr<0x2cbdfd59ceb55fcc4dbe43b9d6f052f5ca448ef5990b005b9927e578b1b69b6c>`; -exports[`PrivateCallStackItem computes hash 1`] = `Fr<0x2e5307580ef277146cc3c6a9d9210c6e317d9b6a033755f509e6161d0eaf576a>`; +exports[`PrivateCallStackItem computes hash 1`] = `Fr<0x13b91b02b88b9856b5ccb70b03484cd04e3621ade4db047514ce1ccb66ffea11>`; diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/private_circuit_public_inputs.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/private_circuit_public_inputs.test.ts.snap index 4e423c22442..13f20b93e6c 100644 --- a/yarn-project/circuits.js/src/structs/__snapshots__/private_circuit_public_inputs.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/__snapshots__/private_circuit_public_inputs.test.ts.snap @@ -1,5 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`PrivateCircuitPublicInputs computes empty inputs hash 1`] = `Fr<0x24ea9ab3fc039778bef8e7212f6a09feec1019db19b449333b523a08b812ee88>`; +exports[`PrivateCircuitPublicInputs computes empty inputs hash 1`] = `Fr<0x2c1ec6595f8d43f5fc983441bc75a84d2384008f5bd7a1d499da057130abe6cd>`; -exports[`PrivateCircuitPublicInputs hash matches snapshot 1`] = `Fr<0x144c861f88d1ba68fc7e72f7a578546207bbf785e4a23278601662d85cd25d12>`; +exports[`PrivateCircuitPublicInputs hash matches snapshot 1`] = `Fr<0x27af129fd883d6a50669a5cdd0c0ce91d67b6ddeccfe4df6cd3e5207f77e1cf1>`; diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/public_call_stack_item.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/public_call_stack_item.test.ts.snap index 230870d273c..a6d3353003d 100644 --- a/yarn-project/circuits.js/src/structs/__snapshots__/public_call_stack_item.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/__snapshots__/public_call_stack_item.test.ts.snap @@ -1,7 +1,9 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`PublicCallStackItem Computes a callstack item hash 1`] = `"0x0c0d60d424315af5f106a802b250c27c613a9ec1c0f583c6ad806cf22fe66a13"`; +exports[`PublicCallStackItem Computes a callstack item hash 1`] = `"0x1ef9292cf3383605672c06dd50a12c251aa1f037cd826c0fc70d8ee5324e88c4"`; -exports[`PublicCallStackItem Computes a callstack item request hash 1`] = `"0x134d01b778664dbc1ffa953008ce28f72b0cb258533776f10df59a59d791e972"`; +exports[`PublicCallStackItem Computes a callstack item request hash 1`] = `"0x23066ad690c088120f8397cfeb2ef5608d4517342c7ff9fcb713009933ef1c61"`; -exports[`PublicCallStackItem computes hash 1`] = `Fr<0x2c7d4c31cdb4762c88686417968228c7d102e205e89cb157a34365eef5bfb15c>`; +exports[`PublicCallStackItem computes empty item hash 1`] = `Fr<0x0eef6f20d1f73de870f781dad46a843966eb560e2b684752c82cd2bd45f97a34>`; + +exports[`PublicCallStackItem computes hash 1`] = `Fr<0x1571225ac99b706576b42ca98a76865ac6057c17bec38f22f6a78793d4b201b6>`; diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/public_circuit_public_inputs.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/public_circuit_public_inputs.test.ts.snap index 057d7b9aeac..d519cebd489 100644 --- a/yarn-project/circuits.js/src/structs/__snapshots__/public_circuit_public_inputs.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/__snapshots__/public_circuit_public_inputs.test.ts.snap @@ -1,5 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`PublicCircuitPublicInputs computes empty item hash 1`] = `Fr<0x1092820bc987359300ff136abf020d58218e1b3484e03d756c76e81ac56ccbf7>`; +exports[`PublicCircuitPublicInputs computes empty item hash 1`] = `Fr<0x048912d56248af479f8d7ecedbba7092d27741b10075a989e040f8e3242a7a3f>`; -exports[`PublicCircuitPublicInputs hash matches snapshot 1`] = `Fr<0x251dcf0ab2afb050857487a1545e99cc12ddd7655154f89b8aab1d7872845173>`; +exports[`PublicCircuitPublicInputs hash matches snapshot 1`] = `Fr<0x15e41ce024b6e97478b456f670cfdd712aefe2504fd5145116e9ab7a26672d02>`; diff --git a/yarn-project/circuits.js/src/structs/public_call_stack_item.test.ts b/yarn-project/circuits.js/src/structs/public_call_stack_item.test.ts index a7d87aabb79..2fc577a5b8c 100644 --- a/yarn-project/circuits.js/src/structs/public_call_stack_item.test.ts +++ b/yarn-project/circuits.js/src/structs/public_call_stack_item.test.ts @@ -21,6 +21,12 @@ describe('PublicCallStackItem', () => { expect(hash).toMatchSnapshot(); }); + it('computes empty item hash', () => { + const item = PublicCallStackItem.empty(); + const hash = item.hash(); + expect(hash).toMatchSnapshot(); + }); + it('Computes a callstack item request hash', () => { const callStack = PublicCallStackItem.empty(); From 67c2823e3bb302d4d7a28bca03de468c92336680 Mon Sep 17 00:00:00 2001 From: Facundo Date: Fri, 19 Apr 2024 11:56:50 +0100 Subject: [PATCH 030/102] chore: remove get_portal_address oracle (#5816) --- docs/docs/misc/migration_notes.md | 26 ++++++++++++++++++- .../aztec/src/context/private_context.nr | 2 +- noir-projects/aztec-nr/aztec/src/oracle.nr | 1 - .../aztec-nr/aztec/src/oracle/context.nr | 9 ------- .../contracts/test_contract/src/main.nr | 7 +++-- .../token_bridge_contract/src/main.nr | 10 +++++++ .../contracts/uniswap_contract/src/main.nr | 9 +++---- .../simulator/src/acvm/oracle/oracle.ts | 6 ----- .../simulator/src/acvm/oracle/typed_oracle.ts | 5 ---- .../src/client/private_execution.test.ts | 7 ++--- .../simulator/src/client/view_data_oracle.ts | 10 ------- .../src/public/public_execution_context.ts | 10 ------- 12 files changed, 45 insertions(+), 57 deletions(-) delete mode 100644 noir-projects/aztec-nr/aztec/src/oracle/context.nr diff --git a/docs/docs/misc/migration_notes.md b/docs/docs/misc/migration_notes.md index 7ccee0ee58f..e781e7e5069 100644 --- a/docs/docs/misc/migration_notes.md +++ b/docs/docs/misc/migration_notes.md @@ -6,7 +6,7 @@ keywords: [sandbox, cli, aztec, notes, migration, updating, upgrading] Aztec is in full-speed development. Literally every version breaks compatibility with the previous ones. This page attempts to target errors and difficulties you might encounter when upgrading, and how to resolve them. -## TBD +## 0.36.0 ### [Aztec.nr] Contract interfaces @@ -64,6 +64,30 @@ The `request_max_block_number` function has been renamed to `set_tx_max_block_nu + context.set_tx_max_block_number(value); ``` +### [Aztec.nr] Get portal address + +The `get_portal_address` oracle was removed. If you need to get the portal address of SomeContract, add the following methods to it + +``` +#[aztec(private)] +fn get_portal_address() -> EthAddress { + context.this_portal_address() +} + +#[aztec(public)] +fn get_portal_address_public() -> EthAddress { + context.this_portal_address() +} +``` + +and change the call to `get_portal_address` + +```diff +- let portal_address = get_portal_address(contract_address); ++ let portal_address = SomeContract::at(contract_address).get_portal_address().call(&mut context); +``` + + ### [Aztec.nr] Required gas limits for public-to-public calls When calling a public function from another public function using the `call_public_function` method, you must now specify how much gas you're allocating to the nested call. This will later allow you to limit the amount of gas consumed by the nested call, and handle any out of gas errors. diff --git a/noir-projects/aztec-nr/aztec/src/context/private_context.nr b/noir-projects/aztec-nr/aztec/src/context/private_context.nr index 0c744e60d32..33dd48fd262 100644 --- a/noir-projects/aztec-nr/aztec/src/context/private_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/private_context.nr @@ -4,7 +4,7 @@ use crate::{ hash::{hash_args_array, ArgsHasher}, oracle::{ arguments, returns, call_private_function::call_private_function_internal, - enqueue_public_function_call::enqueue_public_function_call_internal, context::get_portal_address, + enqueue_public_function_call::enqueue_public_function_call_internal, header::get_header_at, nullifier_key::{get_nullifier_key_pair, NullifierKeyPair} } }; diff --git a/noir-projects/aztec-nr/aztec/src/oracle.nr b/noir-projects/aztec-nr/aztec/src/oracle.nr index a8ad7838d6f..57415dc9575 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle.nr @@ -4,7 +4,6 @@ mod arguments; mod call_private_function; -mod context; mod get_contract_instance; mod get_l1_to_l2_membership_witness; mod get_nullifier_membership_witness; diff --git a/noir-projects/aztec-nr/aztec/src/oracle/context.nr b/noir-projects/aztec-nr/aztec/src/oracle/context.nr deleted file mode 100644 index 56e1b229549..00000000000 --- a/noir-projects/aztec-nr/aztec/src/oracle/context.nr +++ /dev/null @@ -1,9 +0,0 @@ -use dep::protocol_types::address::{AztecAddress, EthAddress}; - -#[oracle(getPortalContractAddress)] -fn _get_portal_address(_contract_address: AztecAddress) -> EthAddress {} - -unconstrained pub fn get_portal_address(contract_address: AztecAddress) -> EthAddress { - let portal_address = _get_portal_address(contract_address); - portal_address -} diff --git a/noir-projects/noir-contracts/contracts/test_contract/src/main.nr b/noir-projects/noir-contracts/contracts/test_contract/src/main.nr index 851b8e59ee6..e03a92b94d9 100644 --- a/noir-projects/noir-contracts/contracts/test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/test_contract/src/main.nr @@ -27,7 +27,7 @@ contract Test { }, deploy::deploy_contract as aztec_deploy_contract, oracle::{ - get_public_key::get_public_key as get_public_key_oracle, context::get_portal_address, + get_public_key::get_public_key as get_public_key_oracle, unsafe_rand::unsafe_rand }, log::emit_unencrypted_log_from_private @@ -54,10 +54,9 @@ contract Test { [pub_key.x, pub_key.y] } - // Get the portal contract address through an oracle call #[aztec(private)] - fn get_portal_contract_address(aztec_address: AztecAddress) -> EthAddress { - get_portal_address(aztec_address) + fn get_portal_contract_address() -> EthAddress { + context.this_portal_address() } // Get the address of the l1 portal for this contract (taken from the input context) diff --git a/noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr b/noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr index 32f9653915b..28226b5b10b 100644 --- a/noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr @@ -31,6 +31,16 @@ contract TokenBridge { } // docs:end:token_bridge_storage_and_constructor + #[aztec(private)] + fn get_portal_address() -> EthAddress { + context.this_portal_address() + } + + #[aztec(public)] + fn get_portal_address_public() -> EthAddress { + context.this_portal_address() + } + // docs:start:claim_public // Consumes a L1->L2 message and calls the token contract to mint the appropriate amount publicly #[aztec(public)] diff --git a/noir-projects/noir-contracts/contracts/uniswap_contract/src/main.nr b/noir-projects/noir-contracts/contracts/uniswap_contract/src/main.nr index 32a89fcc704..35d9e573379 100644 --- a/noir-projects/noir-contracts/contracts/uniswap_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/uniswap_contract/src/main.nr @@ -6,7 +6,6 @@ mod util; // Uses the token bridge contract, which tells which input token we need to talk to and handles the exit funds to L1 contract Uniswap { use dep::aztec::prelude::{FunctionSelector, AztecAddress, EthAddress, Map, PublicMutable}; - use dep::aztec::oracle::context::get_portal_address; use dep::aztec::context::gas::GasOpts; use dep::authwit::auth::{ @@ -65,8 +64,8 @@ contract Uniswap { Uniswap::at(context.this_address())._approve_bridge_and_exit_input_asset_to_L1(input_asset, input_asset_bridge, input_amount).call(&mut context); // Create swap message and send to Outbox for Uniswap Portal // this ensures the integrity of what the user originally intends to do on L1. - let input_asset_bridge_portal_address = get_portal_address(input_asset_bridge); - let output_asset_bridge_portal_address = get_portal_address(output_asset_bridge); + let input_asset_bridge_portal_address = TokenBridge::at(input_asset_bridge).get_portal_address_public().call(&mut context); + let output_asset_bridge_portal_address = TokenBridge::at(output_asset_bridge).get_portal_address_public().call(&mut context); // ensure portal exists - else funds might be lost assert( !input_asset_bridge_portal_address.is_zero(), "L1 portal address of input_asset's bridge is 0" @@ -123,8 +122,8 @@ contract Uniswap { // Create swap message and send to Outbox for Uniswap Portal // this ensures the integrity of what the user originally intends to do on L1. - let input_asset_bridge_portal_address = get_portal_address(input_asset_bridge); - let output_asset_bridge_portal_address = get_portal_address(output_asset_bridge); + let input_asset_bridge_portal_address = TokenBridge::at(input_asset_bridge).get_portal_address().call(&mut context); + let output_asset_bridge_portal_address = TokenBridge::at(output_asset_bridge).get_portal_address().call(&mut context); // ensure portal exists - else funds might be lost assert( !input_asset_bridge_portal_address.is_zero(), "L1 portal address of input_asset's bridge is 0" diff --git a/yarn-project/simulator/src/acvm/oracle/oracle.ts b/yarn-project/simulator/src/acvm/oracle/oracle.ts index fb3b35f028c..2b967a7c98b 100644 --- a/yarn-project/simulator/src/acvm/oracle/oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/oracle.ts @@ -271,12 +271,6 @@ export class Oracle { return message.toFields().map(toACVMField); } - async getPortalContractAddress([aztecAddress]: ACVMField[]): Promise { - const contractAddress = AztecAddress.fromString(aztecAddress); - const portalContactAddress = await this.typedOracle.getPortalContractAddress(contractAddress); - return toACVMField(portalContactAddress); - } - async storageRead([startStorageSlot]: ACVMField[], [numberOfElements]: ACVMField[]): Promise { const values = await this.typedOracle.storageRead(fromACVMField(startStorageSlot), +numberOfElements); return values.map(toACVMField); diff --git a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts index c362a04f8be..e0dd6ce24f4 100644 --- a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts @@ -18,7 +18,6 @@ import { } from '@aztec/circuits.js'; import { type FunctionSelector } from '@aztec/foundation/abi'; import { type AztecAddress } from '@aztec/foundation/aztec-address'; -import { type EthAddress } from '@aztec/foundation/eth-address'; import { Fr } from '@aztec/foundation/fields'; import { type ContractInstance } from '@aztec/types/contracts'; @@ -187,10 +186,6 @@ export abstract class TypedOracle { throw new OracleMethodNotAvailableError('getL1ToL2MembershipWitness'); } - getPortalContractAddress(_contractAddress: AztecAddress): Promise { - throw new OracleMethodNotAvailableError('getPortalContractAddress'); - } - storageRead(_startStorageSlot: Fr, _numberOfElements: number): Promise { throw new OracleMethodNotAvailableError('storageRead'); } diff --git a/yarn-project/simulator/src/client/private_execution.test.ts b/yarn-project/simulator/src/client/private_execution.test.ts index 512060e9948..9e2b8fe0d83 100644 --- a/yarn-project/simulator/src/client/private_execution.test.ts +++ b/yarn-project/simulator/src/client/private_execution.test.ts @@ -1041,16 +1041,13 @@ describe('Private Execution test suite', () => { describe('Context oracles', () => { it("Should be able to get and return the contract's portal contract address", async () => { const portalContractAddress = EthAddress.random(); - const aztecAddressToQuery = AztecAddress.random(); // Tweak the contract artifact so we can extract return values const artifact = getFunctionArtifact(TestContractArtifact, 'get_portal_contract_address'); - const args = [aztecAddressToQuery.toField()]; + const args: Fr[] = []; - // Overwrite the oracle return value - oracle.getPortalContractAddress.mockResolvedValue(portalContractAddress); - const result = await runSimulator({ artifact, args }); + const result = await runSimulator({ artifact, args, portalContractAddress }); expect(result.returnValues).toEqual([portalContractAddress.toField()]); }); diff --git a/yarn-project/simulator/src/client/view_data_oracle.ts b/yarn-project/simulator/src/client/view_data_oracle.ts index 2a76c346474..7ab30411eda 100644 --- a/yarn-project/simulator/src/client/view_data_oracle.ts +++ b/yarn-project/simulator/src/client/view_data_oracle.ts @@ -239,16 +239,6 @@ export class ViewDataOracle extends TypedOracle { return await this.db.getL1ToL2MembershipWitness(contractAddress, messageHash, secret); } - /** - * Retrieves the portal contract address associated with the given contract address. - * Throws an error if the input contract address is not found or invalid. - * @param contractAddress - The address of the contract whose portal address is to be fetched. - * @returns The portal contract address. - */ - public override getPortalContractAddress(contractAddress: AztecAddress) { - return this.db.getPortalContractAddress(contractAddress); - } - /** * Read the public storage data. * @param startStorageSlot - The starting storage slot. diff --git a/yarn-project/simulator/src/public/public_execution_context.ts b/yarn-project/simulator/src/public/public_execution_context.ts index ad2c77b0dc9..adf3e893484 100644 --- a/yarn-project/simulator/src/public/public_execution_context.ts +++ b/yarn-project/simulator/src/public/public_execution_context.ts @@ -136,16 +136,6 @@ export class PublicExecutionContext extends TypedOracle { return Fr.fromBuffer(log.hash()); } - /** - * Retrieves the portal contract address associated with the given contract address. - * Returns zero address if the input contract address is not found or invalid. - * @param contractAddress - The address of the contract whose portal address is to be fetched. - * @returns The portal contract address. - */ - public override async getPortalContractAddress(contractAddress: AztecAddress) { - return (await this.contractsDb.getPortalContractAddress(contractAddress)) ?? EthAddress.ZERO; - } - /** * Read the public storage data. * @param startStorageSlot - The starting storage slot. From ab9fe780e8a9fc3187a02b37ddbefa609d3bff8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Bene=C5=A1?= Date: Fri, 19 Apr 2024 14:58:59 +0200 Subject: [PATCH 031/102] refactor: integrate new key store (#5731) Fixes #5720 --- boxes/boxes/react/src/config.ts | 13 +- boxes/boxes/vanilla/src/index.ts | 7 +- boxes/contract-only/tests/node.test.ts | 35 -- .../how_to_compile_contract.md | 157 +++++++-- docs/docs/misc/migration_notes.md | 14 + .../src/core/libraries/ConstantsGen.sol | 6 +- l1-contracts/test/decoders/readme.md | 2 +- l1-contracts/test/fixtures/empty_block_0.json | 10 +- l1-contracts/test/fixtures/empty_block_1.json | 14 +- l1-contracts/test/fixtures/mixed_block_0.json | 10 +- l1-contracts/test/fixtures/mixed_block_1.json | 14 +- .../aztec-nr/address-note/src/address_note.nr | 12 +- .../aztec/src/context/private_context.nr | 33 +- noir-projects/aztec-nr/aztec/src/key.nr | 1 - .../aztec-nr/aztec/src/key/nullifier_key.nr | 8 - noir-projects/aztec-nr/aztec/src/lib.nr | 1 - .../aztec/src/oracle/get_public_key.nr | 5 +- .../aztec/src/oracle/nullifier_key.nr | 29 +- .../aztec/src/state_vars/private_mutable.nr | 2 +- .../aztec-nr/value-note/src/value_note.nr | 12 +- .../src/subscription_note.nr | 12 +- .../contracts/card_game_contract/src/cards.nr | 4 +- .../src/types/card_note.nr | 12 +- .../easy_private_voting_contract/src/main.nr | 4 +- .../src/ecdsa_public_key_note.nr | 12 +- .../src/public_key_note.nr | 12 +- .../src/main.nr | 4 +- .../src/types/token_note.nr | 12 +- .../contracts/token_contract/src/main.nr | 5 +- .../token_contract/src/types/token_note.nr | 12 +- .../src/private_kernel_init.nr | 6 +- .../private_validation_request_processor.nr | 18 +- .../crates/types/src/abis/function_data.nr | 2 +- .../abis/nullifier_key_validation_request.nr | 54 +-- .../types/src/abis/private_call_stack_item.nr | 2 +- .../src/abis/private_circuit_public_inputs.nr | 4 +- .../src/abis/public_circuit_public_inputs.nr | 2 +- .../crates/types/src/address/aztec_address.nr | 58 +--- .../types/src/address/public_keys_hash.nr | 16 +- .../crates/types/src/constants.nr | 9 +- .../crates/types/src/hash.nr | 4 +- .../types/src/tests/fixtures/contracts.nr | 16 +- .../types/src/transaction/tx_context.nr | 6 +- .../accounts/src/defaults/account_contract.ts | 5 +- .../src/defaults/account_interface.ts | 5 + yarn-project/accounts/src/ecdsa/index.ts | 15 +- yarn-project/accounts/src/schnorr/index.ts | 8 +- yarn-project/accounts/src/single_key/index.ts | 21 +- .../accounts/src/testing/configuration.ts | 43 ++- .../accounts/src/testing/create_account.ts | 17 +- yarn-project/aztec.js/src/account/contract.ts | 4 +- .../aztec.js/src/account/interface.ts | 3 + .../account_manager/deploy_account_method.ts | 7 +- .../aztec.js/src/account_manager/index.ts | 44 +-- yarn-project/aztec.js/src/api/wallet.ts | 8 +- .../aztec.js/src/contract/contract.ts | 15 +- .../aztec.js/src/contract/deploy_method.ts | 6 +- .../src/deployment/contract_deployer.ts | 7 +- yarn-project/aztec.js/src/index.ts | 9 +- .../aztec.js/src/wallet/account_wallet.ts | 4 + .../wallet/account_wallet_with_private_key.ts | 10 +- .../aztec.js/src/wallet/base_wallet.ts | 17 +- yarn-project/aztec.js/src/wallet/index.ts | 6 +- .../aztec.js/src/wallet/signerless_wallet.ts | 4 + yarn-project/aztec/src/cli/util.ts | 10 +- yarn-project/aztec/src/examples/token.ts | 13 +- .../circuit-types/src/interfaces/pxe.ts | 21 +- yarn-project/circuit-types/src/keys/index.ts | 1 - .../circuit-types/src/keys/key_store.ts | 133 +++++--- .../circuit-types/src/keys/new_key_store.ts | 101 ------ yarn-project/circuits.js/package.json | 1 + yarn-project/circuits.js/src/constants.gen.ts | 9 +- .../contract_address.test.ts.snap | 6 +- .../src/contract/contract_address.test.ts | 33 +- .../src/contract/contract_address.ts | 32 +- .../src/contract/contract_instance.ts | 14 +- yarn-project/circuits.js/src/keys/index.ts | 79 +++-- .../__snapshots__/function_data.test.ts.snap | 2 +- .../private_call_stack_item.test.ts.snap | 4 +- ...private_circuit_public_inputs.test.ts.snap | 4 +- .../public_circuit_public_inputs.test.ts.snap | 2 +- .../__snapshots__/tx_context.test.ts.snap | 2 +- .../src/structs/complete_address.test.ts | 3 +- .../src/structs/complete_address.ts | 55 ++-- .../src/structs/function_data.test.ts | 2 +- .../nullifier_key_validation_request.ts | 45 +-- .../public_circuit_public_inputs.test.ts | 6 +- .../src/structs/tx_context.test.ts | 2 +- .../circuits.js/src/tests/factories.ts | 8 +- yarn-project/cli/src/cmds/add_contract.ts | 9 +- yarn-project/cli/src/cmds/create_account.ts | 15 +- yarn-project/cli/src/cmds/deploy.ts | 11 +- yarn-project/cli/src/cmds/register_account.ts | 6 +- yarn-project/cli/src/cmds/send.ts | 8 +- yarn-project/cli/src/index.ts | 18 +- .../benchmarks/bench_process_history.test.ts | 8 +- .../benchmarks/bench_publish_rollup.test.ts | 8 +- .../src/benchmarks/bench_tx_size_fees.test.ts | 4 +- .../end-to-end/src/benchmarks/utils.ts | 12 +- .../src/composed/cli_docs_sandbox.test.ts | 2 +- .../src/composed/docs_examples.test.ts | 6 +- .../src/composed/e2e_persistence.test.ts | 26 +- .../src/composed/e2e_sandbox_example.test.ts | 2 +- .../composed/integration_l1_publisher.test.ts | 6 +- .../end-to-end/src/e2e_2_pxes.test.ts | 13 +- .../src/e2e_account_contracts.test.ts | 27 +- .../end-to-end/src/e2e_card_game.test.ts | 31 +- .../src/e2e_crowdfunding_and_claim.test.ts | 17 +- .../src/e2e_dapp_subscription.test.ts | 8 +- .../src/e2e_escrow_contract.test.ts | 17 +- .../e2e_multiple_accounts_1_enc_key.test.ts | 6 +- .../end-to-end/src/e2e_outbox.test.ts | 4 +- .../src/fixtures/snapshot_manager.ts | 9 +- yarn-project/end-to-end/src/fixtures/utils.ts | 8 +- .../src/flakey_e2e_account_init_fees.test.ts | 19 +- .../contract_class_registration.test.ts | 10 +- .../flakey_e2e_deploy_contract/deploy_test.ts | 11 +- .../flakey_e2e_deploy_contract/legacy.test.ts | 6 +- .../src/flakey_e2e_p2p_network.test.ts | 11 +- .../writing_an_account_contract.test.ts | 6 +- yarn-project/end-to-end/src/shared/browser.ts | 19 +- yarn-project/key-store/src/index.ts | 1 - yarn-project/key-store/src/key_pair.ts | 48 --- .../key-store/src/new_test_key_store.ts | 245 -------------- ...y_store.test.ts => test_key_store.test.ts} | 17 +- yarn-project/key-store/src/test_key_store.ts | 309 ++++++++++++++---- .../src/contract-interface-gen/typescript.ts | 12 +- .../__snapshots__/noir_test_gen.test.ts.snap | 4 +- .../nested-call-private-kernel-init.hex | 2 +- .../nested-call-private-kernel-inner.hex | 2 +- .../nested-call-private-kernel-ordering.hex | 2 +- .../src/type_conversion.ts | 18 +- .../protocol-contracts/src/gas-token/index.ts | 4 +- .../src/multi-call-entrypoint/index.ts | 4 +- .../src/protocol_contract.ts | 4 +- yarn-project/pxe/src/kernel_oracle/index.ts | 2 +- .../pxe/src/kernel_prover/hints_builder.ts | 2 +- .../src/note_processor/note_processor.test.ts | 32 +- .../pxe/src/note_processor/note_processor.ts | 20 +- .../pxe/src/pxe_service/create_pxe_service.ts | 2 - .../pxe/src/pxe_service/pxe_service.ts | 53 ++- .../src/pxe_service/test/pxe_service.test.ts | 5 +- .../src/pxe_service/test/pxe_test_suite.ts | 17 +- .../pxe/src/simulator_oracle/index.ts | 11 +- .../pxe/src/synchronizer/synchronizer.test.ts | 14 +- .../pxe/src/synchronizer/synchronizer.ts | 31 +- .../simulator/src/acvm/oracle/oracle.ts | 13 +- .../simulator/src/acvm/oracle/typed_oracle.ts | 23 +- .../simulator/src/client/db_oracle.ts | 12 +- .../src/client/private_execution.test.ts | 73 ++--- .../simulator/src/client/simulator.test.ts | 44 ++- .../client/unconstrained_execution.test.ts | 6 +- .../simulator/src/client/view_data_oracle.ts | 13 +- yarn-project/update-snapshots.sh | 6 +- 154 files changed, 1431 insertions(+), 1500 deletions(-) delete mode 100644 boxes/contract-only/tests/node.test.ts delete mode 100644 noir-projects/aztec-nr/aztec/src/key.nr delete mode 100644 noir-projects/aztec-nr/aztec/src/key/nullifier_key.nr delete mode 100644 yarn-project/circuit-types/src/keys/new_key_store.ts delete mode 100644 yarn-project/key-store/src/key_pair.ts delete mode 100644 yarn-project/key-store/src/new_test_key_store.ts rename yarn-project/key-store/src/{new_test_key_store.test.ts => test_key_store.test.ts} (85%) diff --git a/boxes/boxes/react/src/config.ts b/boxes/boxes/react/src/config.ts index 833f1649649..65a47ca03c9 100644 --- a/boxes/boxes/react/src/config.ts +++ b/boxes/boxes/react/src/config.ts @@ -1,9 +1,9 @@ -import { GrumpkinPrivateKey, GrumpkinScalar, createPXEClient } from '@aztec/aztec.js'; +import { Fr, createPXEClient, deriveMasterIncomingViewingSecretKey } from '@aztec/aztec.js'; import { BoxReactContractArtifact } from '../artifacts/BoxReact'; import { AccountManager } from '@aztec/aztec.js/account'; import { SingleKeyAccountContract } from '@aztec/accounts/single_key'; -const GRUMPKIN_KEY = GrumpkinScalar.random(); +const SECRET_KEY = Fr.random(); export class PrivateEnv { pxe; @@ -11,12 +11,13 @@ export class PrivateEnv { account: AccountManager; constructor( - private privateKey: GrumpkinPrivateKey, + private secretKey: Fr, private pxeURL: string, ) { this.pxe = createPXEClient(this.pxeURL); - this.accountContract = new SingleKeyAccountContract(privateKey); - this.account = new AccountManager(this.pxe, this.privateKey, this.accountContract); + const encryptionPrivateKey = deriveMasterIncomingViewingSecretKey(secretKey); + this.accountContract = new SingleKeyAccountContract(encryptionPrivateKey); + this.account = new AccountManager(this.pxe, this.secretKey, this.accountContract); } async getWallet() { @@ -25,7 +26,7 @@ export class PrivateEnv { } } -export const deployerEnv = new PrivateEnv(GRUMPKIN_KEY, process.env.PXE_URL || 'http://localhost:8080'); +export const deployerEnv = new PrivateEnv(SECRET_KEY, process.env.PXE_URL || 'http://localhost:8080'); const IGNORE_FUNCTIONS = ['constructor', 'compute_note_hash_and_nullifier']; export const filteredInterface = BoxReactContractArtifact.functions.filter(f => !IGNORE_FUNCTIONS.includes(f.name)); diff --git a/boxes/boxes/vanilla/src/index.ts b/boxes/boxes/vanilla/src/index.ts index ded51955e6d..3b9ce150046 100644 --- a/boxes/boxes/vanilla/src/index.ts +++ b/boxes/boxes/vanilla/src/index.ts @@ -1,12 +1,13 @@ -import { GrumpkinScalar, createPXEClient, AccountManager, Fr, Wallet } from '@aztec/aztec.js'; +import { createPXEClient, AccountManager, Fr, Wallet, deriveMasterIncomingViewingSecretKey } from '@aztec/aztec.js'; import { SingleKeyAccountContract } from '@aztec/accounts/single_key'; import { VanillaContract } from '../artifacts/Vanilla'; -const privateKey: GrumpkinScalar = GrumpkinScalar.random(); +const secretKey = Fr.random(); const pxe = createPXEClient(process.env.PXE_URL || 'http://localhost:8080'); -const account = new AccountManager(pxe, privateKey, new SingleKeyAccountContract(privateKey)); +const encryptionPrivateKey = deriveMasterIncomingViewingSecretKey(secretKey); +const account = new AccountManager(pxe, secretKey, new SingleKeyAccountContract(encryptionPrivateKey)); let contract: any = null; let wallet: Wallet | null = null; diff --git a/boxes/contract-only/tests/node.test.ts b/boxes/contract-only/tests/node.test.ts deleted file mode 100644 index 158476f897c..00000000000 --- a/boxes/contract-only/tests/node.test.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { createPXEClient, PXE, GrumpkinScalar, AccountManager, Wallet } from '@aztec/aztec.js'; -import { SingleKeyAccountContract } from '@aztec/accounts/single_key'; -import { derivePublicKey } from '@aztec/circuits.js'; - -describe('Account Tests', () => { - const pxeURL = process.env.PXE_URL || 'http://localhost:8080'; - let pxe: PXE; - let account: AccountManager; - let wallet: Wallet; - - const privateKey = GrumpkinScalar.fromString('0x1234'); - const expectedPublicKey = derivePublicKey(privateKey).toString(); - - test('Can start the PXE server', async () => { - pxe = createPXEClient(pxeURL); - const { chainId } = await pxe.getNodeInfo(); - expect(chainId).toBe(31337); - }); - - beforeEach(() => { - const accountContract = new SingleKeyAccountContract(privateKey); - account = new AccountManager(pxe, privateKey, accountContract); - }); - - test('Can create an account contract with a known address', async () => { - const publicKey = account.getCompleteAddress().publicKey.toString(); - expect(publicKey).toEqual(expectedPublicKey); - }); - - test('Can deploy a contract with a known address', async () => { - ({ wallet } = await (await account.deploy()).wait()); - const publicKey = wallet.getCompleteAddress().publicKey.toString(); - expect(publicKey).toEqual(expectedPublicKey); - }); -}); diff --git a/docs/docs/developers/contracts/compiling_contracts/how_to_compile_contract.md b/docs/docs/developers/contracts/compiling_contracts/how_to_compile_contract.md index 6135b4d8e1a..25f87f2d2e4 100644 --- a/docs/docs/developers/contracts/compiling_contracts/how_to_compile_contract.md +++ b/docs/docs/developers/contracts/compiling_contracts/how_to_compile_contract.md @@ -32,8 +32,8 @@ Below is typescript code generated from the [Token](https://github.com/AztecProt ```ts showLineNumbers export class TokenContract extends ContractBase { - private constructor(completeAddress: CompleteAddress, wallet: Wallet, portalContract = EthAddress.ZERO) { - super(completeAddress, TokenContractArtifact, wallet, portalContract); + private constructor(instance: ContractInstanceWithAddress, wallet: Wallet) { + super(instance, TokenContractArtifact, wallet); } /** @@ -49,15 +49,57 @@ export class TokenContract extends ContractBase { /** * Creates a tx to deploy a new instance of this contract. */ - public static deploy(pxe: PXE, admin: AztecAddressLike) { - return new DeployMethod(Point.ZERO, pxe, TokenContractArtifact, Array.from(arguments).slice(1)); + public static deploy( + wallet: Wallet, + admin: AztecAddressLike, + name: string, + symbol: string, + decimals: bigint | number, + ) { + return new DeployMethod( + Fr.ZERO, + wallet, + TokenContractArtifact, + TokenContract.at, + Array.from(arguments).slice(1), + ); } /** - * Creates a tx to deploy a new instance of this contract using the specified public key to derive the address. + * Creates a tx to deploy a new instance of this contract using the specified public keys hash to derive the address. */ - public static deployWithPublicKey(pxe: PXE, publicKey: PublicKey, admin: AztecAddressLike) { - return new DeployMethod(publicKey, pxe, TokenContractArtifact, Array.from(arguments).slice(2)); + public static deployWithPublicKeysHash( + publicKeysHash: Fr, + wallet: Wallet, + admin: AztecAddressLike, + name: string, + symbol: string, + decimals: bigint | number, + ) { + return new DeployMethod( + publicKeysHash, + wallet, + TokenContractArtifact, + TokenContract.at, + Array.from(arguments).slice(2), + ); + } + + /** + * Creates a tx to deploy a new instance of this contract using the specified constructor method. + */ + public static deployWithOpts( + opts: { publicKeysHash?: Fr; method?: M; wallet: Wallet }, + ...args: Parameters + ) { + return new DeployMethod( + opts.publicKeysHash ?? Fr.ZERO, + opts.wallet, + TokenContractArtifact, + TokenContract.at, + Array.from(arguments).slice(1), + opts.method ?? 'constructor', + ); } /** @@ -67,27 +109,90 @@ export class TokenContract extends ContractBase { return TokenContractArtifact; } - /** Type-safe wrappers for the public methods exposed by the contract. */ - public methods!: { - - /** balance_of_private(owner: struct) */ - balance_of_private: ((owner: AztecAddressLike) => ContractFunctionInteraction) & Pick; + public static get storage(): ContractStorageLayout< + | 'admin' + | 'minters' + | 'balances' + | 'total_supply' + | 'pending_shields' + | 'public_balances' + | 'symbol' + | 'name' + | 'decimals' + > { + return { + admin: { + slot: new Fr(1n), + typ: 'PublicMutable', + }, + minters: { + slot: new Fr(2n), + typ: 'Map>', + }, + balances: { + slot: new Fr(3n), + typ: 'BalancesMap', + }, + total_supply: { + slot: new Fr(4n), + typ: 'PublicMutable', + }, + pending_shields: { + slot: new Fr(5n), + typ: 'PrivateSet', + }, + public_balances: { + slot: new Fr(6n), + typ: 'Map>', + }, + symbol: { + slot: new Fr(7n), + typ: 'SharedImmutable', + }, + name: { + slot: new Fr(8n), + typ: 'SharedImmutable', + }, + decimals: { + slot: new Fr(9n), + typ: 'SharedImmutable', + }, + } as ContractStorageLayout< + | 'admin' + | 'minters' + | 'balances' + | 'total_supply' + | 'pending_shields' + | 'public_balances' + | 'symbol' + | 'name' + | 'decimals' + >; + } - /** balance_of_public(owner: struct) */ - balance_of_public: ((owner: AztecAddressLike) => ContractFunctionInteraction) & Pick; + public static get notes(): ContractNotes<'TransparentNote' | 'TokenNote'> { + const notes = this.artifact.outputs.globals.notes ? (this.artifact.outputs.globals.notes as any) : []; + return { + TransparentNote: { + id: new Fr(84114971101151129711410111011678111116101n), + }, + TokenNote: { + id: new Fr(8411110710111078111116101n), + }, + } as ContractNotes<'TransparentNote' | 'TokenNote'>; + } - /** shield(from: struct, amount: field, secret_hash: field, nonce: field) */ - shield: (( + /** Type-safe wrappers for the public methods exposed by the contract. */ + public override methods!: { + /** transfer_public(from: struct, to: struct, amount: field, nonce: field) */ + transfer_public: (( from: AztecAddressLike, + to: AztecAddressLike, amount: FieldLike, - secret_hash: FieldLike, nonce: FieldLike, ) => ContractFunctionInteraction) & Pick; - /** total_supply() */ - total_supply: (() => ContractFunctionInteraction) & Pick; - /** transfer(from: struct, to: struct, amount: field, nonce: field) */ transfer: (( from: AztecAddressLike, @@ -96,17 +201,9 @@ export class TokenContract extends ContractBase { nonce: FieldLike, ) => ContractFunctionInteraction) & Pick; + + ... - /** transfer_public(from: struct, to: struct, amount: field, nonce: field) */ - transfer_public: (( - from: AztecAddressLike, - to: AztecAddressLike, - amount: FieldLike, - nonce: FieldLike, - ) => ContractFunctionInteraction) & - Pick; - - ... }; } ``` diff --git a/docs/docs/misc/migration_notes.md b/docs/docs/misc/migration_notes.md index e781e7e5069..fe424ddb820 100644 --- a/docs/docs/misc/migration_notes.md +++ b/docs/docs/misc/migration_notes.md @@ -8,6 +8,20 @@ Aztec is in full-speed development. Literally every version breaks compatibility ## 0.36.0 +### [Aztec.nr] Oracles + +Oracle `get_nullifier_secret_key` was renamed to `get_app_nullifier_secret_key` and `request_nullifier_secret_key` function on PrivateContext was renamed as `request_app_nullifier_secret_key`. + +```diff +- let secret = get_nullifier_secret_key(self.owner); ++ let secret = get_app_nullifier_secret_key(self.owner); +``` + +```diff +- let secret = context.request_nullifier_secret_key(self.owner); ++ let secret = context.request_app_nullifier_secret_key(self.owner); +``` + ### [Aztec.nr] Contract interfaces It is now possible to import contracts on another contracts and use their automatic interfaces to perform calls. The interfaces have the same name as the contract, and are automatically exported. Parameters are automatically serialized (using the `Serialize` trait) and return values are automatically deserialized (using the `Deserialize` trait). Serialize and Deserialize methods have to conform to the standard ACVM serialization schema for the interface to work! diff --git a/l1-contracts/src/core/libraries/ConstantsGen.sol b/l1-contracts/src/core/libraries/ConstantsGen.sol index 8f86070367e..068ee6df4ef 100644 --- a/l1-contracts/src/core/libraries/ConstantsGen.sol +++ b/l1-contracts/src/core/libraries/ConstantsGen.sol @@ -89,7 +89,7 @@ library Constants { uint256 internal constant DEPLOYER_CONTRACT_INSTANCE_DEPLOYED_MAGIC_VALUE = 0x85864497636cf755ae7bde03f267ce01a520981c21c3682aaf82a631; uint256 internal constant DEPLOYER_CONTRACT_ADDRESS = - 0x161b653b72ac5aa2982ce485b242b5c1e09afcbf27b89696f5a4e3151be37245; + 0x1f47133752dfcd9604f2d89c631797a84ed207c1c51d08533226dafcc8bd8548; uint256 internal constant AZTEC_ADDRESS_LENGTH = 1; uint256 internal constant DIMENSION_GAS_SETTINGS_LENGTH = 3; uint256 internal constant GAS_FEES_LENGTH = 3; @@ -108,8 +108,8 @@ library Constants { uint256 internal constant L1_TO_L2_MESSAGE_LENGTH = 6; uint256 internal constant L2_TO_L1_MESSAGE_LENGTH = 2; uint256 internal constant MAX_BLOCK_NUMBER_LENGTH = 2; - uint256 internal constant NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH = 4; - uint256 internal constant NULLIFIER_KEY_VALIDATION_REQUEST_CONTEXT_LENGTH = 5; + uint256 internal constant NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH = 3; + uint256 internal constant NULLIFIER_KEY_VALIDATION_REQUEST_CONTEXT_LENGTH = 4; uint256 internal constant PARTIAL_STATE_REFERENCE_LENGTH = 6; uint256 internal constant READ_REQUEST_LENGTH = 2; uint256 internal constant SIDE_EFFECT_LENGTH = 2; diff --git a/l1-contracts/test/decoders/readme.md b/l1-contracts/test/decoders/readme.md index e59108d452d..85a4bb826de 100644 --- a/l1-contracts/test/decoders/readme.md +++ b/l1-contracts/test/decoders/readme.md @@ -2,4 +2,4 @@ To generate test data (also used in rollup test), run the `integration_l1_publisher.test.ts` in end-to-end, it will generate the test data in the fixtures folder. -It is generally set to NOT overwrite the existing data. But you can change the `OVERWRITE_TEST_DATA` to true before running the test. \ No newline at end of file +It is generally set to NOT overwrite the existing data. But you can change the `AZTEC_GENERATE_TEST_DATA` to true before running the test. \ No newline at end of file diff --git a/l1-contracts/test/fixtures/empty_block_0.json b/l1-contracts/test/fixtures/empty_block_0.json index 16e7729fc67..fd84965eea2 100644 --- a/l1-contracts/test/fixtures/empty_block_0.json +++ b/l1-contracts/test/fixtures/empty_block_0.json @@ -8,7 +8,7 @@ "l2ToL1Messages": [] }, "block": { - "archive": "0x2683d379c0ad62e225372f35b74366d8c3cd145a12dbbb2028456da89f889be1", + "archive": "0x188be890697072b6e002cfd2c0fff9b434ab0f8075ba55861be700daa8b5245e", "body": "0x00000000", "txsEffectsHash": "0x00df6b1c97b9e01113fa0363d9ff71c85addc74e92b22d433b2fb082d2493896", "decodedHeader": { @@ -23,8 +23,8 @@ "chainId": 31337, "timestamp": 0, "version": 1, - "coinbase": "0xd70b960abd35f82aac6df2d1ca6617b5bcd95ba5", - "feeRecipient": "0x0c67b9f94de6beccefc03b63ba448b53464348836ef20b3e6183c5d4f85653ee", + "coinbase": "0xa43e0eb6a43e0eb6a43e0eb6a43e0eb6a43e0eb6", + "feeRecipient": "0x15a9c4f4c75d79ce22330ca2cdb6c1a6ede1f6d94ba28016eeb25e5578913ccb", "gasFees": { "feePerDaGas": 0, "feePerL1Gas": 0, @@ -56,8 +56,8 @@ } } }, - "header": "0x05b0b6df52f1d47d0406318558052c89a174fbc9d615def82b3cc9ccc1937db800000001000000000000000000000000000000000000000000000000000000000000000100df6b1c97b9e01113fa0363d9ff71c85addc74e92b22d433b2fb082d249389600089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c31864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000001016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000000800bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278000001000572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000000800000000000000000000000000000000000000000000000000000000000007a69000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000d70b960abd35f82aac6df2d1ca6617b5bcd95ba50c67b9f94de6beccefc03b63ba448b53464348836ef20b3e6183c5d4f85653ee000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "publicInputsHash": "0x00ee6ce1f8afb6a9d9da7165bbff8d03d3f2e4ae6a65a9265ecbb7c600244a9c", + "header": "0x05b0b6df52f1d47d0406318558052c89a174fbc9d615def82b3cc9ccc1937db800000001000000000000000000000000000000000000000000000000000000000000000100df6b1c97b9e01113fa0363d9ff71c85addc74e92b22d433b2fb082d249389600089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c31864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000001016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000000800bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278000001000572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000000800000000000000000000000000000000000000000000000000000000000007a69000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000a43e0eb6a43e0eb6a43e0eb6a43e0eb6a43e0eb615a9c4f4c75d79ce22330ca2cdb6c1a6ede1f6d94ba28016eeb25e5578913ccb000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "publicInputsHash": "0x009a9a967263c733e1ab2c9d67836cd9145e691d0123896749c051deebaf766a", "numTxs": 0 } } \ No newline at end of file diff --git a/l1-contracts/test/fixtures/empty_block_1.json b/l1-contracts/test/fixtures/empty_block_1.json index 6eb046a8035..429eb428d2a 100644 --- a/l1-contracts/test/fixtures/empty_block_1.json +++ b/l1-contracts/test/fixtures/empty_block_1.json @@ -8,7 +8,7 @@ "l2ToL1Messages": [] }, "block": { - "archive": "0x0be67a10fc9ab9372e7fdfa4fcce95a3ed24d42fb6694ffcd3d418d504d8fef4", + "archive": "0x2d7fa58436f44491690fd5592307625dc21b12fcb7af369c9dc78d5985c0a0df", "body": "0x00000000", "txsEffectsHash": "0x00df6b1c97b9e01113fa0363d9ff71c85addc74e92b22d433b2fb082d2493896", "decodedHeader": { @@ -21,10 +21,10 @@ "globalVariables": { "blockNumber": 2, "chainId": 31337, - "timestamp": 1712912168, + "timestamp": 1713529904, "version": 1, - "coinbase": "0xd70b960abd35f82aac6df2d1ca6617b5bcd95ba5", - "feeRecipient": "0x0c67b9f94de6beccefc03b63ba448b53464348836ef20b3e6183c5d4f85653ee", + "coinbase": "0xa43e0eb6a43e0eb6a43e0eb6a43e0eb6a43e0eb6", + "feeRecipient": "0x15a9c4f4c75d79ce22330ca2cdb6c1a6ede1f6d94ba28016eeb25e5578913ccb", "gasFees": { "feePerDaGas": 0, "feePerL1Gas": 0, @@ -33,7 +33,7 @@ }, "lastArchive": { "nextAvailableLeafIndex": 2, - "root": "0x2683d379c0ad62e225372f35b74366d8c3cd145a12dbbb2028456da89f889be1" + "root": "0x188be890697072b6e002cfd2c0fff9b434ab0f8075ba55861be700daa8b5245e" }, "stateReference": { "l1ToL2MessageTree": { @@ -56,8 +56,8 @@ } } }, - "header": "0x2683d379c0ad62e225372f35b74366d8c3cd145a12dbbb2028456da89f889be100000002000000000000000000000000000000000000000000000000000000000000000100df6b1c97b9e01113fa0363d9ff71c85addc74e92b22d433b2fb082d249389600089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c31864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000002016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000001000bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278000001800572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000000c00000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000006618f728d70b960abd35f82aac6df2d1ca6617b5bcd95ba50c67b9f94de6beccefc03b63ba448b53464348836ef20b3e6183c5d4f85653ee000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "publicInputsHash": "0x00bb8af4db44612602143f2507b6f07f4dc5fdede045494a1467c4bea354bcae", + "header": "0x188be890697072b6e002cfd2c0fff9b434ab0f8075ba55861be700daa8b5245e00000002000000000000000000000000000000000000000000000000000000000000000100df6b1c97b9e01113fa0363d9ff71c85addc74e92b22d433b2fb082d249389600089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c31864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000002016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000001000bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278000001800572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000000c00000000000000000000000000000000000000000000000000000000000007a69000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000066226430a43e0eb6a43e0eb6a43e0eb6a43e0eb6a43e0eb615a9c4f4c75d79ce22330ca2cdb6c1a6ede1f6d94ba28016eeb25e5578913ccb000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "publicInputsHash": "0x00b00b3ab0a2b8665fa4ced9637ab3e2114446cd2975cf6fc544a0540200a0c7", "numTxs": 0 } } \ No newline at end of file diff --git a/l1-contracts/test/fixtures/mixed_block_0.json b/l1-contracts/test/fixtures/mixed_block_0.json index ad43a849a54..47e09affc4e 100644 --- a/l1-contracts/test/fixtures/mixed_block_0.json +++ b/l1-contracts/test/fixtures/mixed_block_0.json @@ -34,7 +34,7 @@ ] }, "block": { - "archive": "0x195de7b601a7882443a8b98043c504ef921f11a94dfa17ce1f5bc4461c685877", + "archive": "0x2fc3ac909751b968a209d4b189dcd536f28c90b18d40ab9c73b95abd044d2874", "body": "0x0000000400400000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000014100000000000000000000000000000000000000000000000000000000000001420000000000000000000000000000000000000000000000000000000000000143000000000000000000000000000000000000000000000000000000000000014400000000000000000000000000000000000000000000000000000000000001450000000000000000000000000000000000000000000000000000000000000146000000000000000000000000000000000000000000000000000000000000014700000000000000000000000000000000000000000000000000000000000001480000000000000000000000000000000000000000000000000000000000000149000000000000000000000000000000000000000000000000000000000000014a000000000000000000000000000000000000000000000000000000000000014b000000000000000000000000000000000000000000000000000000000000014c000000000000000000000000000000000000000000000000000000000000014d000000000000000000000000000000000000000000000000000000000000014e000000000000000000000000000000000000000000000000000000000000014f0000000000000000000000000000000000000000000000000000000000000150000000000000000000000000000000000000000000000000000000000000015100000000000000000000000000000000000000000000000000000000000001520000000000000000000000000000000000000000000000000000000000000153000000000000000000000000000000000000000000000000000000000000015400000000000000000000000000000000000000000000000000000000000001550000000000000000000000000000000000000000000000000000000000000156000000000000000000000000000000000000000000000000000000000000015700000000000000000000000000000000000000000000000000000000000001580000000000000000000000000000000000000000000000000000000000000159000000000000000000000000000000000000000000000000000000000000015a000000000000000000000000000000000000000000000000000000000000015b000000000000000000000000000000000000000000000000000000000000015c000000000000000000000000000000000000000000000000000000000000015d000000000000000000000000000000000000000000000000000000000000015e000000000000000000000000000000000000000000000000000000000000015f0000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000016100000000000000000000000000000000000000000000000000000000000001620000000000000000000000000000000000000000000000000000000000000163000000000000000000000000000000000000000000000000000000000000016400000000000000000000000000000000000000000000000000000000000001650000000000000000000000000000000000000000000000000000000000000166000000000000000000000000000000000000000000000000000000000000016700000000000000000000000000000000000000000000000000000000000001680000000000000000000000000000000000000000000000000000000000000169000000000000000000000000000000000000000000000000000000000000016a000000000000000000000000000000000000000000000000000000000000016b000000000000000000000000000000000000000000000000000000000000016c000000000000000000000000000000000000000000000000000000000000016d000000000000000000000000000000000000000000000000000000000000016e000000000000000000000000000000000000000000000000000000000000016f0000000000000000000000000000000000000000000000000000000000000170000000000000000000000000000000000000000000000000000000000000017100000000000000000000000000000000000000000000000000000000000001720000000000000000000000000000000000000000000000000000000000000173000000000000000000000000000000000000000000000000000000000000017400000000000000000000000000000000000000000000000000000000000001750000000000000000000000000000000000000000000000000000000000000176000000000000000000000000000000000000000000000000000000000000017700000000000000000000000000000000000000000000000000000000000001780000000000000000000000000000000000000000000000000000000000000179000000000000000000000000000000000000000000000000000000000000017a000000000000000000000000000000000000000000000000000000000000017b000000000000000000000000000000000000000000000000000000000000017c000000000000000000000000000000000000000000000000000000000000017d000000000000000000000000000000000000000000000000000000000000017e000000000000000000000000000000000000000000000000000000000000017f3f0000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000024100000000000000000000000000000000000000000000000000000000000002420000000000000000000000000000000000000000000000000000000000000243000000000000000000000000000000000000000000000000000000000000024400000000000000000000000000000000000000000000000000000000000002450000000000000000000000000000000000000000000000000000000000000246000000000000000000000000000000000000000000000000000000000000024700000000000000000000000000000000000000000000000000000000000002480000000000000000000000000000000000000000000000000000000000000249000000000000000000000000000000000000000000000000000000000000024a000000000000000000000000000000000000000000000000000000000000024b000000000000000000000000000000000000000000000000000000000000024c000000000000000000000000000000000000000000000000000000000000024d000000000000000000000000000000000000000000000000000000000000024e000000000000000000000000000000000000000000000000000000000000024f0000000000000000000000000000000000000000000000000000000000000250000000000000000000000000000000000000000000000000000000000000025100000000000000000000000000000000000000000000000000000000000002520000000000000000000000000000000000000000000000000000000000000253000000000000000000000000000000000000000000000000000000000000025400000000000000000000000000000000000000000000000000000000000002550000000000000000000000000000000000000000000000000000000000000256000000000000000000000000000000000000000000000000000000000000025700000000000000000000000000000000000000000000000000000000000002580000000000000000000000000000000000000000000000000000000000000259000000000000000000000000000000000000000000000000000000000000025a000000000000000000000000000000000000000000000000000000000000025b000000000000000000000000000000000000000000000000000000000000025c000000000000000000000000000000000000000000000000000000000000025d000000000000000000000000000000000000000000000000000000000000025e000000000000000000000000000000000000000000000000000000000000025f0000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000026100000000000000000000000000000000000000000000000000000000000002620000000000000000000000000000000000000000000000000000000000000263000000000000000000000000000000000000000000000000000000000000026400000000000000000000000000000000000000000000000000000000000002650000000000000000000000000000000000000000000000000000000000000266000000000000000000000000000000000000000000000000000000000000026700000000000000000000000000000000000000000000000000000000000002680000000000000000000000000000000000000000000000000000000000000269000000000000000000000000000000000000000000000000000000000000026a000000000000000000000000000000000000000000000000000000000000026b000000000000000000000000000000000000000000000000000000000000026c000000000000000000000000000000000000000000000000000000000000026d000000000000000000000000000000000000000000000000000000000000026e000000000000000000000000000000000000000000000000000000000000026f0000000000000000000000000000000000000000000000000000000000000270000000000000000000000000000000000000000000000000000000000000027100000000000000000000000000000000000000000000000000000000000002720000000000000000000000000000000000000000000000000000000000000273000000000000000000000000000000000000000000000000000000000000027400000000000000000000000000000000000000000000000000000000000002750000000000000000000000000000000000000000000000000000000000000276000000000000000000000000000000000000000000000000000000000000027700000000000000000000000000000000000000000000000000000000000002780000000000000000000000000000000000000000000000000000000000000279000000000000000000000000000000000000000000000000000000000000027a000000000000000000000000000000000000000000000000000000000000027b000000000000000000000000000000000000000000000000000000000000027c000000000000000000000000000000000000000000000000000000000000027d000000000000000000000000000000000000000000000000000000000000027e0200000000000000000000000000000000000000000000000000000000000003400000000000000000000000000000000000000000000000000000000000000341200000000000000000000000000000000000000000000000000000000000000540000000000000000000000000000000000000000000000000000000000000054a0000000000000000000000000000000000000000000000000000000000000541000000000000000000000000000000000000000000000000000000000000054b0000000000000000000000000000000000000000000000000000000000000542000000000000000000000000000000000000000000000000000000000000054c0000000000000000000000000000000000000000000000000000000000000543000000000000000000000000000000000000000000000000000000000000054d0000000000000000000000000000000000000000000000000000000000000544000000000000000000000000000000000000000000000000000000000000054e0000000000000000000000000000000000000000000000000000000000000545000000000000000000000000000000000000000000000000000000000000054f00000000000000000000000000000000000000000000000000000000000005460000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000000000000000000000000000054700000000000000000000000000000000000000000000000000000000000005510000000000000000000000000000000000000000000000000000000000000548000000000000000000000000000000000000000000000000000000000000055200000000000000000000000000000000000000000000000000000000000005490000000000000000000000000000000000000000000000000000000000000553000000000000000000000000000000000000000000000000000000000000054a0000000000000000000000000000000000000000000000000000000000000554000000000000000000000000000000000000000000000000000000000000054b0000000000000000000000000000000000000000000000000000000000000555000000000000000000000000000000000000000000000000000000000000054c0000000000000000000000000000000000000000000000000000000000000556000000000000000000000000000000000000000000000000000000000000054d0000000000000000000000000000000000000000000000000000000000000557000000000000000000000000000000000000000000000000000000000000054e0000000000000000000000000000000000000000000000000000000000000558000000000000000000000000000000000000000000000000000000000000054f00000000000000000000000000000000000000000000000000000000000005590000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000000000000000000000000000055a0000000000000000000000000000000000000000000000000000000000000551000000000000000000000000000000000000000000000000000000000000055b0000000000000000000000000000000000000000000000000000000000000552000000000000000000000000000000000000000000000000000000000000055c0000000000000000000000000000000000000000000000000000000000000553000000000000000000000000000000000000000000000000000000000000055d0000000000000000000000000000000000000000000000000000000000000554000000000000000000000000000000000000000000000000000000000000055e0000000000000000000000000000000000000000000000000000000000000555000000000000000000000000000000000000000000000000000000000000055f00000000000000000000000000000000000000000000000000000000000005560000000000000000000000000000000000000000000000000000000000000560000000000000000000000000000000000000000000000000000000000000055700000000000000000000000000000000000000000000000000000000000005610000000000000000000000000000000000000000000000000000000000000558000000000000000000000000000000000000000000000000000000000000056200000000000000000000000000000000000000000000000000000000000005590000000000000000000000000000000000000000000000000000000000000563000000000000000000000000000000000000000000000000000000000000055a0000000000000000000000000000000000000000000000000000000000000564000000000000000000000000000000000000000000000000000000000000055b0000000000000000000000000000000000000000000000000000000000000565000000000000000000000000000000000000000000000000000000000000055c0000000000000000000000000000000000000000000000000000000000000566000000000000000000000000000000000000000000000000000000000000055d0000000000000000000000000000000000000000000000000000000000000567000000000000000000000000000000000000000000000000000000000000055e0000000000000000000000000000000000000000000000000000000000000568000000000000000000000000000000000000000000000000000000000000055f0000000000000000000000000000000000000000000000000000000000000569000000000000000000400000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000018100000000000000000000000000000000000000000000000000000000000001820000000000000000000000000000000000000000000000000000000000000183000000000000000000000000000000000000000000000000000000000000018400000000000000000000000000000000000000000000000000000000000001850000000000000000000000000000000000000000000000000000000000000186000000000000000000000000000000000000000000000000000000000000018700000000000000000000000000000000000000000000000000000000000001880000000000000000000000000000000000000000000000000000000000000189000000000000000000000000000000000000000000000000000000000000018a000000000000000000000000000000000000000000000000000000000000018b000000000000000000000000000000000000000000000000000000000000018c000000000000000000000000000000000000000000000000000000000000018d000000000000000000000000000000000000000000000000000000000000018e000000000000000000000000000000000000000000000000000000000000018f0000000000000000000000000000000000000000000000000000000000000190000000000000000000000000000000000000000000000000000000000000019100000000000000000000000000000000000000000000000000000000000001920000000000000000000000000000000000000000000000000000000000000193000000000000000000000000000000000000000000000000000000000000019400000000000000000000000000000000000000000000000000000000000001950000000000000000000000000000000000000000000000000000000000000196000000000000000000000000000000000000000000000000000000000000019700000000000000000000000000000000000000000000000000000000000001980000000000000000000000000000000000000000000000000000000000000199000000000000000000000000000000000000000000000000000000000000019a000000000000000000000000000000000000000000000000000000000000019b000000000000000000000000000000000000000000000000000000000000019c000000000000000000000000000000000000000000000000000000000000019d000000000000000000000000000000000000000000000000000000000000019e000000000000000000000000000000000000000000000000000000000000019f00000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001a100000000000000000000000000000000000000000000000000000000000001a200000000000000000000000000000000000000000000000000000000000001a300000000000000000000000000000000000000000000000000000000000001a400000000000000000000000000000000000000000000000000000000000001a500000000000000000000000000000000000000000000000000000000000001a600000000000000000000000000000000000000000000000000000000000001a700000000000000000000000000000000000000000000000000000000000001a800000000000000000000000000000000000000000000000000000000000001a900000000000000000000000000000000000000000000000000000000000001aa00000000000000000000000000000000000000000000000000000000000001ab00000000000000000000000000000000000000000000000000000000000001ac00000000000000000000000000000000000000000000000000000000000001ad00000000000000000000000000000000000000000000000000000000000001ae00000000000000000000000000000000000000000000000000000000000001af00000000000000000000000000000000000000000000000000000000000001b000000000000000000000000000000000000000000000000000000000000001b100000000000000000000000000000000000000000000000000000000000001b200000000000000000000000000000000000000000000000000000000000001b300000000000000000000000000000000000000000000000000000000000001b400000000000000000000000000000000000000000000000000000000000001b500000000000000000000000000000000000000000000000000000000000001b600000000000000000000000000000000000000000000000000000000000001b700000000000000000000000000000000000000000000000000000000000001b800000000000000000000000000000000000000000000000000000000000001b900000000000000000000000000000000000000000000000000000000000001ba00000000000000000000000000000000000000000000000000000000000001bb00000000000000000000000000000000000000000000000000000000000001bc00000000000000000000000000000000000000000000000000000000000001bd00000000000000000000000000000000000000000000000000000000000001be00000000000000000000000000000000000000000000000000000000000001bf3f0000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000028100000000000000000000000000000000000000000000000000000000000002820000000000000000000000000000000000000000000000000000000000000283000000000000000000000000000000000000000000000000000000000000028400000000000000000000000000000000000000000000000000000000000002850000000000000000000000000000000000000000000000000000000000000286000000000000000000000000000000000000000000000000000000000000028700000000000000000000000000000000000000000000000000000000000002880000000000000000000000000000000000000000000000000000000000000289000000000000000000000000000000000000000000000000000000000000028a000000000000000000000000000000000000000000000000000000000000028b000000000000000000000000000000000000000000000000000000000000028c000000000000000000000000000000000000000000000000000000000000028d000000000000000000000000000000000000000000000000000000000000028e000000000000000000000000000000000000000000000000000000000000028f0000000000000000000000000000000000000000000000000000000000000290000000000000000000000000000000000000000000000000000000000000029100000000000000000000000000000000000000000000000000000000000002920000000000000000000000000000000000000000000000000000000000000293000000000000000000000000000000000000000000000000000000000000029400000000000000000000000000000000000000000000000000000000000002950000000000000000000000000000000000000000000000000000000000000296000000000000000000000000000000000000000000000000000000000000029700000000000000000000000000000000000000000000000000000000000002980000000000000000000000000000000000000000000000000000000000000299000000000000000000000000000000000000000000000000000000000000029a000000000000000000000000000000000000000000000000000000000000029b000000000000000000000000000000000000000000000000000000000000029c000000000000000000000000000000000000000000000000000000000000029d000000000000000000000000000000000000000000000000000000000000029e000000000000000000000000000000000000000000000000000000000000029f00000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000002a100000000000000000000000000000000000000000000000000000000000002a200000000000000000000000000000000000000000000000000000000000002a300000000000000000000000000000000000000000000000000000000000002a400000000000000000000000000000000000000000000000000000000000002a500000000000000000000000000000000000000000000000000000000000002a600000000000000000000000000000000000000000000000000000000000002a700000000000000000000000000000000000000000000000000000000000002a800000000000000000000000000000000000000000000000000000000000002a900000000000000000000000000000000000000000000000000000000000002aa00000000000000000000000000000000000000000000000000000000000002ab00000000000000000000000000000000000000000000000000000000000002ac00000000000000000000000000000000000000000000000000000000000002ad00000000000000000000000000000000000000000000000000000000000002ae00000000000000000000000000000000000000000000000000000000000002af00000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000002b100000000000000000000000000000000000000000000000000000000000002b200000000000000000000000000000000000000000000000000000000000002b300000000000000000000000000000000000000000000000000000000000002b400000000000000000000000000000000000000000000000000000000000002b500000000000000000000000000000000000000000000000000000000000002b600000000000000000000000000000000000000000000000000000000000002b700000000000000000000000000000000000000000000000000000000000002b800000000000000000000000000000000000000000000000000000000000002b900000000000000000000000000000000000000000000000000000000000002ba00000000000000000000000000000000000000000000000000000000000002bb00000000000000000000000000000000000000000000000000000000000002bc00000000000000000000000000000000000000000000000000000000000002bd00000000000000000000000000000000000000000000000000000000000002be0200000000000000000000000000000000000000000000000000000000000003800000000000000000000000000000000000000000000000000000000000000381200000000000000000000000000000000000000000000000000000000000000580000000000000000000000000000000000000000000000000000000000000058a0000000000000000000000000000000000000000000000000000000000000581000000000000000000000000000000000000000000000000000000000000058b0000000000000000000000000000000000000000000000000000000000000582000000000000000000000000000000000000000000000000000000000000058c0000000000000000000000000000000000000000000000000000000000000583000000000000000000000000000000000000000000000000000000000000058d0000000000000000000000000000000000000000000000000000000000000584000000000000000000000000000000000000000000000000000000000000058e0000000000000000000000000000000000000000000000000000000000000585000000000000000000000000000000000000000000000000000000000000058f00000000000000000000000000000000000000000000000000000000000005860000000000000000000000000000000000000000000000000000000000000590000000000000000000000000000000000000000000000000000000000000058700000000000000000000000000000000000000000000000000000000000005910000000000000000000000000000000000000000000000000000000000000588000000000000000000000000000000000000000000000000000000000000059200000000000000000000000000000000000000000000000000000000000005890000000000000000000000000000000000000000000000000000000000000593000000000000000000000000000000000000000000000000000000000000058a0000000000000000000000000000000000000000000000000000000000000594000000000000000000000000000000000000000000000000000000000000058b0000000000000000000000000000000000000000000000000000000000000595000000000000000000000000000000000000000000000000000000000000058c0000000000000000000000000000000000000000000000000000000000000596000000000000000000000000000000000000000000000000000000000000058d0000000000000000000000000000000000000000000000000000000000000597000000000000000000000000000000000000000000000000000000000000058e0000000000000000000000000000000000000000000000000000000000000598000000000000000000000000000000000000000000000000000000000000058f00000000000000000000000000000000000000000000000000000000000005990000000000000000000000000000000000000000000000000000000000000590000000000000000000000000000000000000000000000000000000000000059a0000000000000000000000000000000000000000000000000000000000000591000000000000000000000000000000000000000000000000000000000000059b0000000000000000000000000000000000000000000000000000000000000592000000000000000000000000000000000000000000000000000000000000059c0000000000000000000000000000000000000000000000000000000000000593000000000000000000000000000000000000000000000000000000000000059d0000000000000000000000000000000000000000000000000000000000000594000000000000000000000000000000000000000000000000000000000000059e0000000000000000000000000000000000000000000000000000000000000595000000000000000000000000000000000000000000000000000000000000059f000000000000000000000000000000000000000000000000000000000000059600000000000000000000000000000000000000000000000000000000000005a0000000000000000000000000000000000000000000000000000000000000059700000000000000000000000000000000000000000000000000000000000005a1000000000000000000000000000000000000000000000000000000000000059800000000000000000000000000000000000000000000000000000000000005a2000000000000000000000000000000000000000000000000000000000000059900000000000000000000000000000000000000000000000000000000000005a3000000000000000000000000000000000000000000000000000000000000059a00000000000000000000000000000000000000000000000000000000000005a4000000000000000000000000000000000000000000000000000000000000059b00000000000000000000000000000000000000000000000000000000000005a5000000000000000000000000000000000000000000000000000000000000059c00000000000000000000000000000000000000000000000000000000000005a6000000000000000000000000000000000000000000000000000000000000059d00000000000000000000000000000000000000000000000000000000000005a7000000000000000000000000000000000000000000000000000000000000059e00000000000000000000000000000000000000000000000000000000000005a8000000000000000000000000000000000000000000000000000000000000059f00000000000000000000000000000000000000000000000000000000000005a90000000000000000004000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000001c100000000000000000000000000000000000000000000000000000000000001c200000000000000000000000000000000000000000000000000000000000001c300000000000000000000000000000000000000000000000000000000000001c400000000000000000000000000000000000000000000000000000000000001c500000000000000000000000000000000000000000000000000000000000001c600000000000000000000000000000000000000000000000000000000000001c700000000000000000000000000000000000000000000000000000000000001c800000000000000000000000000000000000000000000000000000000000001c900000000000000000000000000000000000000000000000000000000000001ca00000000000000000000000000000000000000000000000000000000000001cb00000000000000000000000000000000000000000000000000000000000001cc00000000000000000000000000000000000000000000000000000000000001cd00000000000000000000000000000000000000000000000000000000000001ce00000000000000000000000000000000000000000000000000000000000001cf00000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000001d100000000000000000000000000000000000000000000000000000000000001d200000000000000000000000000000000000000000000000000000000000001d300000000000000000000000000000000000000000000000000000000000001d400000000000000000000000000000000000000000000000000000000000001d500000000000000000000000000000000000000000000000000000000000001d600000000000000000000000000000000000000000000000000000000000001d700000000000000000000000000000000000000000000000000000000000001d800000000000000000000000000000000000000000000000000000000000001d900000000000000000000000000000000000000000000000000000000000001da00000000000000000000000000000000000000000000000000000000000001db00000000000000000000000000000000000000000000000000000000000001dc00000000000000000000000000000000000000000000000000000000000001dd00000000000000000000000000000000000000000000000000000000000001de00000000000000000000000000000000000000000000000000000000000001df00000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000001e100000000000000000000000000000000000000000000000000000000000001e200000000000000000000000000000000000000000000000000000000000001e300000000000000000000000000000000000000000000000000000000000001e400000000000000000000000000000000000000000000000000000000000001e500000000000000000000000000000000000000000000000000000000000001e600000000000000000000000000000000000000000000000000000000000001e700000000000000000000000000000000000000000000000000000000000001e800000000000000000000000000000000000000000000000000000000000001e900000000000000000000000000000000000000000000000000000000000001ea00000000000000000000000000000000000000000000000000000000000001eb00000000000000000000000000000000000000000000000000000000000001ec00000000000000000000000000000000000000000000000000000000000001ed00000000000000000000000000000000000000000000000000000000000001ee00000000000000000000000000000000000000000000000000000000000001ef00000000000000000000000000000000000000000000000000000000000001f000000000000000000000000000000000000000000000000000000000000001f100000000000000000000000000000000000000000000000000000000000001f200000000000000000000000000000000000000000000000000000000000001f300000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000000000000000001f500000000000000000000000000000000000000000000000000000000000001f600000000000000000000000000000000000000000000000000000000000001f700000000000000000000000000000000000000000000000000000000000001f800000000000000000000000000000000000000000000000000000000000001f900000000000000000000000000000000000000000000000000000000000001fa00000000000000000000000000000000000000000000000000000000000001fb00000000000000000000000000000000000000000000000000000000000001fc00000000000000000000000000000000000000000000000000000000000001fd00000000000000000000000000000000000000000000000000000000000001fe00000000000000000000000000000000000000000000000000000000000001ff3f00000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000002c100000000000000000000000000000000000000000000000000000000000002c200000000000000000000000000000000000000000000000000000000000002c300000000000000000000000000000000000000000000000000000000000002c400000000000000000000000000000000000000000000000000000000000002c500000000000000000000000000000000000000000000000000000000000002c600000000000000000000000000000000000000000000000000000000000002c700000000000000000000000000000000000000000000000000000000000002c800000000000000000000000000000000000000000000000000000000000002c900000000000000000000000000000000000000000000000000000000000002ca00000000000000000000000000000000000000000000000000000000000002cb00000000000000000000000000000000000000000000000000000000000002cc00000000000000000000000000000000000000000000000000000000000002cd00000000000000000000000000000000000000000000000000000000000002ce00000000000000000000000000000000000000000000000000000000000002cf00000000000000000000000000000000000000000000000000000000000002d000000000000000000000000000000000000000000000000000000000000002d100000000000000000000000000000000000000000000000000000000000002d200000000000000000000000000000000000000000000000000000000000002d300000000000000000000000000000000000000000000000000000000000002d400000000000000000000000000000000000000000000000000000000000002d500000000000000000000000000000000000000000000000000000000000002d600000000000000000000000000000000000000000000000000000000000002d700000000000000000000000000000000000000000000000000000000000002d800000000000000000000000000000000000000000000000000000000000002d900000000000000000000000000000000000000000000000000000000000002da00000000000000000000000000000000000000000000000000000000000002db00000000000000000000000000000000000000000000000000000000000002dc00000000000000000000000000000000000000000000000000000000000002dd00000000000000000000000000000000000000000000000000000000000002de00000000000000000000000000000000000000000000000000000000000002df00000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000002e100000000000000000000000000000000000000000000000000000000000002e200000000000000000000000000000000000000000000000000000000000002e300000000000000000000000000000000000000000000000000000000000002e400000000000000000000000000000000000000000000000000000000000002e500000000000000000000000000000000000000000000000000000000000002e600000000000000000000000000000000000000000000000000000000000002e700000000000000000000000000000000000000000000000000000000000002e800000000000000000000000000000000000000000000000000000000000002e900000000000000000000000000000000000000000000000000000000000002ea00000000000000000000000000000000000000000000000000000000000002eb00000000000000000000000000000000000000000000000000000000000002ec00000000000000000000000000000000000000000000000000000000000002ed00000000000000000000000000000000000000000000000000000000000002ee00000000000000000000000000000000000000000000000000000000000002ef00000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000002f100000000000000000000000000000000000000000000000000000000000002f200000000000000000000000000000000000000000000000000000000000002f300000000000000000000000000000000000000000000000000000000000002f400000000000000000000000000000000000000000000000000000000000002f500000000000000000000000000000000000000000000000000000000000002f600000000000000000000000000000000000000000000000000000000000002f700000000000000000000000000000000000000000000000000000000000002f800000000000000000000000000000000000000000000000000000000000002f900000000000000000000000000000000000000000000000000000000000002fa00000000000000000000000000000000000000000000000000000000000002fb00000000000000000000000000000000000000000000000000000000000002fc00000000000000000000000000000000000000000000000000000000000002fd00000000000000000000000000000000000000000000000000000000000002fe0200000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000003c12000000000000000000000000000000000000000000000000000000000000005c000000000000000000000000000000000000000000000000000000000000005ca00000000000000000000000000000000000000000000000000000000000005c100000000000000000000000000000000000000000000000000000000000005cb00000000000000000000000000000000000000000000000000000000000005c200000000000000000000000000000000000000000000000000000000000005cc00000000000000000000000000000000000000000000000000000000000005c300000000000000000000000000000000000000000000000000000000000005cd00000000000000000000000000000000000000000000000000000000000005c400000000000000000000000000000000000000000000000000000000000005ce00000000000000000000000000000000000000000000000000000000000005c500000000000000000000000000000000000000000000000000000000000005cf00000000000000000000000000000000000000000000000000000000000005c600000000000000000000000000000000000000000000000000000000000005d000000000000000000000000000000000000000000000000000000000000005c700000000000000000000000000000000000000000000000000000000000005d100000000000000000000000000000000000000000000000000000000000005c800000000000000000000000000000000000000000000000000000000000005d200000000000000000000000000000000000000000000000000000000000005c900000000000000000000000000000000000000000000000000000000000005d300000000000000000000000000000000000000000000000000000000000005ca00000000000000000000000000000000000000000000000000000000000005d400000000000000000000000000000000000000000000000000000000000005cb00000000000000000000000000000000000000000000000000000000000005d500000000000000000000000000000000000000000000000000000000000005cc00000000000000000000000000000000000000000000000000000000000005d600000000000000000000000000000000000000000000000000000000000005cd00000000000000000000000000000000000000000000000000000000000005d700000000000000000000000000000000000000000000000000000000000005ce00000000000000000000000000000000000000000000000000000000000005d800000000000000000000000000000000000000000000000000000000000005cf00000000000000000000000000000000000000000000000000000000000005d900000000000000000000000000000000000000000000000000000000000005d000000000000000000000000000000000000000000000000000000000000005da00000000000000000000000000000000000000000000000000000000000005d100000000000000000000000000000000000000000000000000000000000005db00000000000000000000000000000000000000000000000000000000000005d200000000000000000000000000000000000000000000000000000000000005dc00000000000000000000000000000000000000000000000000000000000005d300000000000000000000000000000000000000000000000000000000000005dd00000000000000000000000000000000000000000000000000000000000005d400000000000000000000000000000000000000000000000000000000000005de00000000000000000000000000000000000000000000000000000000000005d500000000000000000000000000000000000000000000000000000000000005df00000000000000000000000000000000000000000000000000000000000005d600000000000000000000000000000000000000000000000000000000000005e000000000000000000000000000000000000000000000000000000000000005d700000000000000000000000000000000000000000000000000000000000005e100000000000000000000000000000000000000000000000000000000000005d800000000000000000000000000000000000000000000000000000000000005e200000000000000000000000000000000000000000000000000000000000005d900000000000000000000000000000000000000000000000000000000000005e300000000000000000000000000000000000000000000000000000000000005da00000000000000000000000000000000000000000000000000000000000005e400000000000000000000000000000000000000000000000000000000000005db00000000000000000000000000000000000000000000000000000000000005e500000000000000000000000000000000000000000000000000000000000005dc00000000000000000000000000000000000000000000000000000000000005e600000000000000000000000000000000000000000000000000000000000005dd00000000000000000000000000000000000000000000000000000000000005e700000000000000000000000000000000000000000000000000000000000005de00000000000000000000000000000000000000000000000000000000000005e800000000000000000000000000000000000000000000000000000000000005df00000000000000000000000000000000000000000000000000000000000005e9000000000000000000400000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020100000000000000000000000000000000000000000000000000000000000002020000000000000000000000000000000000000000000000000000000000000203000000000000000000000000000000000000000000000000000000000000020400000000000000000000000000000000000000000000000000000000000002050000000000000000000000000000000000000000000000000000000000000206000000000000000000000000000000000000000000000000000000000000020700000000000000000000000000000000000000000000000000000000000002080000000000000000000000000000000000000000000000000000000000000209000000000000000000000000000000000000000000000000000000000000020a000000000000000000000000000000000000000000000000000000000000020b000000000000000000000000000000000000000000000000000000000000020c000000000000000000000000000000000000000000000000000000000000020d000000000000000000000000000000000000000000000000000000000000020e000000000000000000000000000000000000000000000000000000000000020f0000000000000000000000000000000000000000000000000000000000000210000000000000000000000000000000000000000000000000000000000000021100000000000000000000000000000000000000000000000000000000000002120000000000000000000000000000000000000000000000000000000000000213000000000000000000000000000000000000000000000000000000000000021400000000000000000000000000000000000000000000000000000000000002150000000000000000000000000000000000000000000000000000000000000216000000000000000000000000000000000000000000000000000000000000021700000000000000000000000000000000000000000000000000000000000002180000000000000000000000000000000000000000000000000000000000000219000000000000000000000000000000000000000000000000000000000000021a000000000000000000000000000000000000000000000000000000000000021b000000000000000000000000000000000000000000000000000000000000021c000000000000000000000000000000000000000000000000000000000000021d000000000000000000000000000000000000000000000000000000000000021e000000000000000000000000000000000000000000000000000000000000021f0000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000022100000000000000000000000000000000000000000000000000000000000002220000000000000000000000000000000000000000000000000000000000000223000000000000000000000000000000000000000000000000000000000000022400000000000000000000000000000000000000000000000000000000000002250000000000000000000000000000000000000000000000000000000000000226000000000000000000000000000000000000000000000000000000000000022700000000000000000000000000000000000000000000000000000000000002280000000000000000000000000000000000000000000000000000000000000229000000000000000000000000000000000000000000000000000000000000022a000000000000000000000000000000000000000000000000000000000000022b000000000000000000000000000000000000000000000000000000000000022c000000000000000000000000000000000000000000000000000000000000022d000000000000000000000000000000000000000000000000000000000000022e000000000000000000000000000000000000000000000000000000000000022f0000000000000000000000000000000000000000000000000000000000000230000000000000000000000000000000000000000000000000000000000000023100000000000000000000000000000000000000000000000000000000000002320000000000000000000000000000000000000000000000000000000000000233000000000000000000000000000000000000000000000000000000000000023400000000000000000000000000000000000000000000000000000000000002350000000000000000000000000000000000000000000000000000000000000236000000000000000000000000000000000000000000000000000000000000023700000000000000000000000000000000000000000000000000000000000002380000000000000000000000000000000000000000000000000000000000000239000000000000000000000000000000000000000000000000000000000000023a000000000000000000000000000000000000000000000000000000000000023b000000000000000000000000000000000000000000000000000000000000023c000000000000000000000000000000000000000000000000000000000000023d000000000000000000000000000000000000000000000000000000000000023e000000000000000000000000000000000000000000000000000000000000023f3f0000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000030100000000000000000000000000000000000000000000000000000000000003020000000000000000000000000000000000000000000000000000000000000303000000000000000000000000000000000000000000000000000000000000030400000000000000000000000000000000000000000000000000000000000003050000000000000000000000000000000000000000000000000000000000000306000000000000000000000000000000000000000000000000000000000000030700000000000000000000000000000000000000000000000000000000000003080000000000000000000000000000000000000000000000000000000000000309000000000000000000000000000000000000000000000000000000000000030a000000000000000000000000000000000000000000000000000000000000030b000000000000000000000000000000000000000000000000000000000000030c000000000000000000000000000000000000000000000000000000000000030d000000000000000000000000000000000000000000000000000000000000030e000000000000000000000000000000000000000000000000000000000000030f0000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000031100000000000000000000000000000000000000000000000000000000000003120000000000000000000000000000000000000000000000000000000000000313000000000000000000000000000000000000000000000000000000000000031400000000000000000000000000000000000000000000000000000000000003150000000000000000000000000000000000000000000000000000000000000316000000000000000000000000000000000000000000000000000000000000031700000000000000000000000000000000000000000000000000000000000003180000000000000000000000000000000000000000000000000000000000000319000000000000000000000000000000000000000000000000000000000000031a000000000000000000000000000000000000000000000000000000000000031b000000000000000000000000000000000000000000000000000000000000031c000000000000000000000000000000000000000000000000000000000000031d000000000000000000000000000000000000000000000000000000000000031e000000000000000000000000000000000000000000000000000000000000031f0000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000032100000000000000000000000000000000000000000000000000000000000003220000000000000000000000000000000000000000000000000000000000000323000000000000000000000000000000000000000000000000000000000000032400000000000000000000000000000000000000000000000000000000000003250000000000000000000000000000000000000000000000000000000000000326000000000000000000000000000000000000000000000000000000000000032700000000000000000000000000000000000000000000000000000000000003280000000000000000000000000000000000000000000000000000000000000329000000000000000000000000000000000000000000000000000000000000032a000000000000000000000000000000000000000000000000000000000000032b000000000000000000000000000000000000000000000000000000000000032c000000000000000000000000000000000000000000000000000000000000032d000000000000000000000000000000000000000000000000000000000000032e000000000000000000000000000000000000000000000000000000000000032f0000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000033100000000000000000000000000000000000000000000000000000000000003320000000000000000000000000000000000000000000000000000000000000333000000000000000000000000000000000000000000000000000000000000033400000000000000000000000000000000000000000000000000000000000003350000000000000000000000000000000000000000000000000000000000000336000000000000000000000000000000000000000000000000000000000000033700000000000000000000000000000000000000000000000000000000000003380000000000000000000000000000000000000000000000000000000000000339000000000000000000000000000000000000000000000000000000000000033a000000000000000000000000000000000000000000000000000000000000033b000000000000000000000000000000000000000000000000000000000000033c000000000000000000000000000000000000000000000000000000000000033d000000000000000000000000000000000000000000000000000000000000033e0200000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000401200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000060a0000000000000000000000000000000000000000000000000000000000000601000000000000000000000000000000000000000000000000000000000000060b0000000000000000000000000000000000000000000000000000000000000602000000000000000000000000000000000000000000000000000000000000060c0000000000000000000000000000000000000000000000000000000000000603000000000000000000000000000000000000000000000000000000000000060d0000000000000000000000000000000000000000000000000000000000000604000000000000000000000000000000000000000000000000000000000000060e0000000000000000000000000000000000000000000000000000000000000605000000000000000000000000000000000000000000000000000000000000060f00000000000000000000000000000000000000000000000000000000000006060000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000060700000000000000000000000000000000000000000000000000000000000006110000000000000000000000000000000000000000000000000000000000000608000000000000000000000000000000000000000000000000000000000000061200000000000000000000000000000000000000000000000000000000000006090000000000000000000000000000000000000000000000000000000000000613000000000000000000000000000000000000000000000000000000000000060a0000000000000000000000000000000000000000000000000000000000000614000000000000000000000000000000000000000000000000000000000000060b0000000000000000000000000000000000000000000000000000000000000615000000000000000000000000000000000000000000000000000000000000060c0000000000000000000000000000000000000000000000000000000000000616000000000000000000000000000000000000000000000000000000000000060d0000000000000000000000000000000000000000000000000000000000000617000000000000000000000000000000000000000000000000000000000000060e0000000000000000000000000000000000000000000000000000000000000618000000000000000000000000000000000000000000000000000000000000060f00000000000000000000000000000000000000000000000000000000000006190000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000061a0000000000000000000000000000000000000000000000000000000000000611000000000000000000000000000000000000000000000000000000000000061b0000000000000000000000000000000000000000000000000000000000000612000000000000000000000000000000000000000000000000000000000000061c0000000000000000000000000000000000000000000000000000000000000613000000000000000000000000000000000000000000000000000000000000061d0000000000000000000000000000000000000000000000000000000000000614000000000000000000000000000000000000000000000000000000000000061e0000000000000000000000000000000000000000000000000000000000000615000000000000000000000000000000000000000000000000000000000000061f00000000000000000000000000000000000000000000000000000000000006160000000000000000000000000000000000000000000000000000000000000620000000000000000000000000000000000000000000000000000000000000061700000000000000000000000000000000000000000000000000000000000006210000000000000000000000000000000000000000000000000000000000000618000000000000000000000000000000000000000000000000000000000000062200000000000000000000000000000000000000000000000000000000000006190000000000000000000000000000000000000000000000000000000000000623000000000000000000000000000000000000000000000000000000000000061a0000000000000000000000000000000000000000000000000000000000000624000000000000000000000000000000000000000000000000000000000000061b0000000000000000000000000000000000000000000000000000000000000625000000000000000000000000000000000000000000000000000000000000061c0000000000000000000000000000000000000000000000000000000000000626000000000000000000000000000000000000000000000000000000000000061d0000000000000000000000000000000000000000000000000000000000000627000000000000000000000000000000000000000000000000000000000000061e0000000000000000000000000000000000000000000000000000000000000628000000000000000000000000000000000000000000000000000000000000061f00000000000000000000000000000000000000000000000000000000000006290000000000000000", "txsEffectsHash": "0x0097a976d5a0b2aa3ea4f9a657d4a8534ed793f49287da441c5d301adfd10d2a", "decodedHeader": { @@ -49,8 +49,8 @@ "chainId": 31337, "timestamp": 0, "version": 1, - "coinbase": "0xcb433ad76e9fe9c41059c27d265df41d9acbf5ff", - "feeRecipient": "0x232da3781f3971d8f6cb0246fd911a893453ef41346cbc81b495f4d887f9a1e3", + "coinbase": "0xa23e0eb6a23e0eb6a23e0eb6a23e0eb6a23e0eb6", + "feeRecipient": "0x09cd9129799990baa63ca94680ef6ce915fbd462e83f04298c9f4a4ee339198d", "gasFees": { "feePerDaGas": 0, "feePerL1Gas": 0, @@ -82,8 +82,8 @@ } } }, - "header": "0x05b0b6df52f1d47d0406318558052c89a174fbc9d615def82b3cc9ccc1937db80000000100000000000000000000000000000000000000000000000000000000000000020097a976d5a0b2aa3ea4f9a657d4a8534ed793f49287da441c5d301adfd10d2a00089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c00198704eb051da0e43ff1a9b3285f168389ba3dd93f8ec1f75f6cafcadbaeb61864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f80000000100d944282e11bdcfa5e8f2b55fe80db4c586087bfc10e0bbba5724d30b8c15e2e0000010001c16141039343d4d403501e66deecff1b024bd76794820a43dc3424087813a20000018028d06967b6a4a1cc3c799fb6f008b63a2ffecd5034b81aa10792a6659f8aca22000000c00000000000000000000000000000000000000000000000000000000000007a69000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000cb433ad76e9fe9c41059c27d265df41d9acbf5ff232da3781f3971d8f6cb0246fd911a893453ef41346cbc81b495f4d887f9a1e3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "publicInputsHash": "0x00e815938884265d230edf2de3b24aa1a8edf2e7fc0fcb65ed15cc6464a33afd", + "header": "0x05b0b6df52f1d47d0406318558052c89a174fbc9d615def82b3cc9ccc1937db80000000100000000000000000000000000000000000000000000000000000000000000020097a976d5a0b2aa3ea4f9a657d4a8534ed793f49287da441c5d301adfd10d2a00089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c00198704eb051da0e43ff1a9b3285f168389ba3dd93f8ec1f75f6cafcadbaeb61864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f80000000100d944282e11bdcfa5e8f2b55fe80db4c586087bfc10e0bbba5724d30b8c15e2e0000010001c16141039343d4d403501e66deecff1b024bd76794820a43dc3424087813a20000018028d06967b6a4a1cc3c799fb6f008b63a2ffecd5034b81aa10792a6659f8aca22000000c00000000000000000000000000000000000000000000000000000000000007a69000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000a23e0eb6a23e0eb6a23e0eb6a23e0eb6a23e0eb609cd9129799990baa63ca94680ef6ce915fbd462e83f04298c9f4a4ee339198d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "publicInputsHash": "0x0067a977a266ee76cce895807fd89aa1cf1e7b52eab7d6654525717dfa128280", "numTxs": 4 } } \ No newline at end of file diff --git a/l1-contracts/test/fixtures/mixed_block_1.json b/l1-contracts/test/fixtures/mixed_block_1.json index bfae6182e66..2ae589fa74b 100644 --- a/l1-contracts/test/fixtures/mixed_block_1.json +++ b/l1-contracts/test/fixtures/mixed_block_1.json @@ -34,7 +34,7 @@ ] }, "block": { - "archive": "0x1935c3506395eb1b6bc63839e01cd3aa2ca13a5b4ee3de54a1d42dcb00a7f856", + "archive": "0x1522dedf40c124b28514c6ac2843ff249cab1b29cddb95e06eb05987ef013b1a", "body": "0x0000000400400000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000024100000000000000000000000000000000000000000000000000000000000002420000000000000000000000000000000000000000000000000000000000000243000000000000000000000000000000000000000000000000000000000000024400000000000000000000000000000000000000000000000000000000000002450000000000000000000000000000000000000000000000000000000000000246000000000000000000000000000000000000000000000000000000000000024700000000000000000000000000000000000000000000000000000000000002480000000000000000000000000000000000000000000000000000000000000249000000000000000000000000000000000000000000000000000000000000024a000000000000000000000000000000000000000000000000000000000000024b000000000000000000000000000000000000000000000000000000000000024c000000000000000000000000000000000000000000000000000000000000024d000000000000000000000000000000000000000000000000000000000000024e000000000000000000000000000000000000000000000000000000000000024f0000000000000000000000000000000000000000000000000000000000000250000000000000000000000000000000000000000000000000000000000000025100000000000000000000000000000000000000000000000000000000000002520000000000000000000000000000000000000000000000000000000000000253000000000000000000000000000000000000000000000000000000000000025400000000000000000000000000000000000000000000000000000000000002550000000000000000000000000000000000000000000000000000000000000256000000000000000000000000000000000000000000000000000000000000025700000000000000000000000000000000000000000000000000000000000002580000000000000000000000000000000000000000000000000000000000000259000000000000000000000000000000000000000000000000000000000000025a000000000000000000000000000000000000000000000000000000000000025b000000000000000000000000000000000000000000000000000000000000025c000000000000000000000000000000000000000000000000000000000000025d000000000000000000000000000000000000000000000000000000000000025e000000000000000000000000000000000000000000000000000000000000025f0000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000026100000000000000000000000000000000000000000000000000000000000002620000000000000000000000000000000000000000000000000000000000000263000000000000000000000000000000000000000000000000000000000000026400000000000000000000000000000000000000000000000000000000000002650000000000000000000000000000000000000000000000000000000000000266000000000000000000000000000000000000000000000000000000000000026700000000000000000000000000000000000000000000000000000000000002680000000000000000000000000000000000000000000000000000000000000269000000000000000000000000000000000000000000000000000000000000026a000000000000000000000000000000000000000000000000000000000000026b000000000000000000000000000000000000000000000000000000000000026c000000000000000000000000000000000000000000000000000000000000026d000000000000000000000000000000000000000000000000000000000000026e000000000000000000000000000000000000000000000000000000000000026f0000000000000000000000000000000000000000000000000000000000000270000000000000000000000000000000000000000000000000000000000000027100000000000000000000000000000000000000000000000000000000000002720000000000000000000000000000000000000000000000000000000000000273000000000000000000000000000000000000000000000000000000000000027400000000000000000000000000000000000000000000000000000000000002750000000000000000000000000000000000000000000000000000000000000276000000000000000000000000000000000000000000000000000000000000027700000000000000000000000000000000000000000000000000000000000002780000000000000000000000000000000000000000000000000000000000000279000000000000000000000000000000000000000000000000000000000000027a000000000000000000000000000000000000000000000000000000000000027b000000000000000000000000000000000000000000000000000000000000027c000000000000000000000000000000000000000000000000000000000000027d000000000000000000000000000000000000000000000000000000000000027e000000000000000000000000000000000000000000000000000000000000027f3f0000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000003420000000000000000000000000000000000000000000000000000000000000343000000000000000000000000000000000000000000000000000000000000034400000000000000000000000000000000000000000000000000000000000003450000000000000000000000000000000000000000000000000000000000000346000000000000000000000000000000000000000000000000000000000000034700000000000000000000000000000000000000000000000000000000000003480000000000000000000000000000000000000000000000000000000000000349000000000000000000000000000000000000000000000000000000000000034a000000000000000000000000000000000000000000000000000000000000034b000000000000000000000000000000000000000000000000000000000000034c000000000000000000000000000000000000000000000000000000000000034d000000000000000000000000000000000000000000000000000000000000034e000000000000000000000000000000000000000000000000000000000000034f0000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000000000035100000000000000000000000000000000000000000000000000000000000003520000000000000000000000000000000000000000000000000000000000000353000000000000000000000000000000000000000000000000000000000000035400000000000000000000000000000000000000000000000000000000000003550000000000000000000000000000000000000000000000000000000000000356000000000000000000000000000000000000000000000000000000000000035700000000000000000000000000000000000000000000000000000000000003580000000000000000000000000000000000000000000000000000000000000359000000000000000000000000000000000000000000000000000000000000035a000000000000000000000000000000000000000000000000000000000000035b000000000000000000000000000000000000000000000000000000000000035c000000000000000000000000000000000000000000000000000000000000035d000000000000000000000000000000000000000000000000000000000000035e000000000000000000000000000000000000000000000000000000000000035f0000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000036100000000000000000000000000000000000000000000000000000000000003620000000000000000000000000000000000000000000000000000000000000363000000000000000000000000000000000000000000000000000000000000036400000000000000000000000000000000000000000000000000000000000003650000000000000000000000000000000000000000000000000000000000000366000000000000000000000000000000000000000000000000000000000000036700000000000000000000000000000000000000000000000000000000000003680000000000000000000000000000000000000000000000000000000000000369000000000000000000000000000000000000000000000000000000000000036a000000000000000000000000000000000000000000000000000000000000036b000000000000000000000000000000000000000000000000000000000000036c000000000000000000000000000000000000000000000000000000000000036d000000000000000000000000000000000000000000000000000000000000036e000000000000000000000000000000000000000000000000000000000000036f0000000000000000000000000000000000000000000000000000000000000370000000000000000000000000000000000000000000000000000000000000037100000000000000000000000000000000000000000000000000000000000003720000000000000000000000000000000000000000000000000000000000000373000000000000000000000000000000000000000000000000000000000000037400000000000000000000000000000000000000000000000000000000000003750000000000000000000000000000000000000000000000000000000000000376000000000000000000000000000000000000000000000000000000000000037700000000000000000000000000000000000000000000000000000000000003780000000000000000000000000000000000000000000000000000000000000379000000000000000000000000000000000000000000000000000000000000037a000000000000000000000000000000000000000000000000000000000000037b000000000000000000000000000000000000000000000000000000000000037c000000000000000000000000000000000000000000000000000000000000037d000000000000000000000000000000000000000000000000000000000000037e0200000000000000000000000000000000000000000000000000000000000004400000000000000000000000000000000000000000000000000000000000000441200000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000064a0000000000000000000000000000000000000000000000000000000000000641000000000000000000000000000000000000000000000000000000000000064b0000000000000000000000000000000000000000000000000000000000000642000000000000000000000000000000000000000000000000000000000000064c0000000000000000000000000000000000000000000000000000000000000643000000000000000000000000000000000000000000000000000000000000064d0000000000000000000000000000000000000000000000000000000000000644000000000000000000000000000000000000000000000000000000000000064e0000000000000000000000000000000000000000000000000000000000000645000000000000000000000000000000000000000000000000000000000000064f00000000000000000000000000000000000000000000000000000000000006460000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000000064700000000000000000000000000000000000000000000000000000000000006510000000000000000000000000000000000000000000000000000000000000648000000000000000000000000000000000000000000000000000000000000065200000000000000000000000000000000000000000000000000000000000006490000000000000000000000000000000000000000000000000000000000000653000000000000000000000000000000000000000000000000000000000000064a0000000000000000000000000000000000000000000000000000000000000654000000000000000000000000000000000000000000000000000000000000064b0000000000000000000000000000000000000000000000000000000000000655000000000000000000000000000000000000000000000000000000000000064c0000000000000000000000000000000000000000000000000000000000000656000000000000000000000000000000000000000000000000000000000000064d0000000000000000000000000000000000000000000000000000000000000657000000000000000000000000000000000000000000000000000000000000064e0000000000000000000000000000000000000000000000000000000000000658000000000000000000000000000000000000000000000000000000000000064f00000000000000000000000000000000000000000000000000000000000006590000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000000065a0000000000000000000000000000000000000000000000000000000000000651000000000000000000000000000000000000000000000000000000000000065b0000000000000000000000000000000000000000000000000000000000000652000000000000000000000000000000000000000000000000000000000000065c0000000000000000000000000000000000000000000000000000000000000653000000000000000000000000000000000000000000000000000000000000065d0000000000000000000000000000000000000000000000000000000000000654000000000000000000000000000000000000000000000000000000000000065e0000000000000000000000000000000000000000000000000000000000000655000000000000000000000000000000000000000000000000000000000000065f00000000000000000000000000000000000000000000000000000000000006560000000000000000000000000000000000000000000000000000000000000660000000000000000000000000000000000000000000000000000000000000065700000000000000000000000000000000000000000000000000000000000006610000000000000000000000000000000000000000000000000000000000000658000000000000000000000000000000000000000000000000000000000000066200000000000000000000000000000000000000000000000000000000000006590000000000000000000000000000000000000000000000000000000000000663000000000000000000000000000000000000000000000000000000000000065a0000000000000000000000000000000000000000000000000000000000000664000000000000000000000000000000000000000000000000000000000000065b0000000000000000000000000000000000000000000000000000000000000665000000000000000000000000000000000000000000000000000000000000065c0000000000000000000000000000000000000000000000000000000000000666000000000000000000000000000000000000000000000000000000000000065d0000000000000000000000000000000000000000000000000000000000000667000000000000000000000000000000000000000000000000000000000000065e0000000000000000000000000000000000000000000000000000000000000668000000000000000000000000000000000000000000000000000000000000065f0000000000000000000000000000000000000000000000000000000000000669000000000000000000400000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000028100000000000000000000000000000000000000000000000000000000000002820000000000000000000000000000000000000000000000000000000000000283000000000000000000000000000000000000000000000000000000000000028400000000000000000000000000000000000000000000000000000000000002850000000000000000000000000000000000000000000000000000000000000286000000000000000000000000000000000000000000000000000000000000028700000000000000000000000000000000000000000000000000000000000002880000000000000000000000000000000000000000000000000000000000000289000000000000000000000000000000000000000000000000000000000000028a000000000000000000000000000000000000000000000000000000000000028b000000000000000000000000000000000000000000000000000000000000028c000000000000000000000000000000000000000000000000000000000000028d000000000000000000000000000000000000000000000000000000000000028e000000000000000000000000000000000000000000000000000000000000028f0000000000000000000000000000000000000000000000000000000000000290000000000000000000000000000000000000000000000000000000000000029100000000000000000000000000000000000000000000000000000000000002920000000000000000000000000000000000000000000000000000000000000293000000000000000000000000000000000000000000000000000000000000029400000000000000000000000000000000000000000000000000000000000002950000000000000000000000000000000000000000000000000000000000000296000000000000000000000000000000000000000000000000000000000000029700000000000000000000000000000000000000000000000000000000000002980000000000000000000000000000000000000000000000000000000000000299000000000000000000000000000000000000000000000000000000000000029a000000000000000000000000000000000000000000000000000000000000029b000000000000000000000000000000000000000000000000000000000000029c000000000000000000000000000000000000000000000000000000000000029d000000000000000000000000000000000000000000000000000000000000029e000000000000000000000000000000000000000000000000000000000000029f00000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000002a100000000000000000000000000000000000000000000000000000000000002a200000000000000000000000000000000000000000000000000000000000002a300000000000000000000000000000000000000000000000000000000000002a400000000000000000000000000000000000000000000000000000000000002a500000000000000000000000000000000000000000000000000000000000002a600000000000000000000000000000000000000000000000000000000000002a700000000000000000000000000000000000000000000000000000000000002a800000000000000000000000000000000000000000000000000000000000002a900000000000000000000000000000000000000000000000000000000000002aa00000000000000000000000000000000000000000000000000000000000002ab00000000000000000000000000000000000000000000000000000000000002ac00000000000000000000000000000000000000000000000000000000000002ad00000000000000000000000000000000000000000000000000000000000002ae00000000000000000000000000000000000000000000000000000000000002af00000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000002b100000000000000000000000000000000000000000000000000000000000002b200000000000000000000000000000000000000000000000000000000000002b300000000000000000000000000000000000000000000000000000000000002b400000000000000000000000000000000000000000000000000000000000002b500000000000000000000000000000000000000000000000000000000000002b600000000000000000000000000000000000000000000000000000000000002b700000000000000000000000000000000000000000000000000000000000002b800000000000000000000000000000000000000000000000000000000000002b900000000000000000000000000000000000000000000000000000000000002ba00000000000000000000000000000000000000000000000000000000000002bb00000000000000000000000000000000000000000000000000000000000002bc00000000000000000000000000000000000000000000000000000000000002bd00000000000000000000000000000000000000000000000000000000000002be00000000000000000000000000000000000000000000000000000000000002bf3f0000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000038100000000000000000000000000000000000000000000000000000000000003820000000000000000000000000000000000000000000000000000000000000383000000000000000000000000000000000000000000000000000000000000038400000000000000000000000000000000000000000000000000000000000003850000000000000000000000000000000000000000000000000000000000000386000000000000000000000000000000000000000000000000000000000000038700000000000000000000000000000000000000000000000000000000000003880000000000000000000000000000000000000000000000000000000000000389000000000000000000000000000000000000000000000000000000000000038a000000000000000000000000000000000000000000000000000000000000038b000000000000000000000000000000000000000000000000000000000000038c000000000000000000000000000000000000000000000000000000000000038d000000000000000000000000000000000000000000000000000000000000038e000000000000000000000000000000000000000000000000000000000000038f0000000000000000000000000000000000000000000000000000000000000390000000000000000000000000000000000000000000000000000000000000039100000000000000000000000000000000000000000000000000000000000003920000000000000000000000000000000000000000000000000000000000000393000000000000000000000000000000000000000000000000000000000000039400000000000000000000000000000000000000000000000000000000000003950000000000000000000000000000000000000000000000000000000000000396000000000000000000000000000000000000000000000000000000000000039700000000000000000000000000000000000000000000000000000000000003980000000000000000000000000000000000000000000000000000000000000399000000000000000000000000000000000000000000000000000000000000039a000000000000000000000000000000000000000000000000000000000000039b000000000000000000000000000000000000000000000000000000000000039c000000000000000000000000000000000000000000000000000000000000039d000000000000000000000000000000000000000000000000000000000000039e000000000000000000000000000000000000000000000000000000000000039f00000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000003a100000000000000000000000000000000000000000000000000000000000003a200000000000000000000000000000000000000000000000000000000000003a300000000000000000000000000000000000000000000000000000000000003a400000000000000000000000000000000000000000000000000000000000003a500000000000000000000000000000000000000000000000000000000000003a600000000000000000000000000000000000000000000000000000000000003a700000000000000000000000000000000000000000000000000000000000003a800000000000000000000000000000000000000000000000000000000000003a900000000000000000000000000000000000000000000000000000000000003aa00000000000000000000000000000000000000000000000000000000000003ab00000000000000000000000000000000000000000000000000000000000003ac00000000000000000000000000000000000000000000000000000000000003ad00000000000000000000000000000000000000000000000000000000000003ae00000000000000000000000000000000000000000000000000000000000003af00000000000000000000000000000000000000000000000000000000000003b000000000000000000000000000000000000000000000000000000000000003b100000000000000000000000000000000000000000000000000000000000003b200000000000000000000000000000000000000000000000000000000000003b300000000000000000000000000000000000000000000000000000000000003b400000000000000000000000000000000000000000000000000000000000003b500000000000000000000000000000000000000000000000000000000000003b600000000000000000000000000000000000000000000000000000000000003b700000000000000000000000000000000000000000000000000000000000003b800000000000000000000000000000000000000000000000000000000000003b900000000000000000000000000000000000000000000000000000000000003ba00000000000000000000000000000000000000000000000000000000000003bb00000000000000000000000000000000000000000000000000000000000003bc00000000000000000000000000000000000000000000000000000000000003bd00000000000000000000000000000000000000000000000000000000000003be0200000000000000000000000000000000000000000000000000000000000004800000000000000000000000000000000000000000000000000000000000000481200000000000000000000000000000000000000000000000000000000000000680000000000000000000000000000000000000000000000000000000000000068a0000000000000000000000000000000000000000000000000000000000000681000000000000000000000000000000000000000000000000000000000000068b0000000000000000000000000000000000000000000000000000000000000682000000000000000000000000000000000000000000000000000000000000068c0000000000000000000000000000000000000000000000000000000000000683000000000000000000000000000000000000000000000000000000000000068d0000000000000000000000000000000000000000000000000000000000000684000000000000000000000000000000000000000000000000000000000000068e0000000000000000000000000000000000000000000000000000000000000685000000000000000000000000000000000000000000000000000000000000068f00000000000000000000000000000000000000000000000000000000000006860000000000000000000000000000000000000000000000000000000000000690000000000000000000000000000000000000000000000000000000000000068700000000000000000000000000000000000000000000000000000000000006910000000000000000000000000000000000000000000000000000000000000688000000000000000000000000000000000000000000000000000000000000069200000000000000000000000000000000000000000000000000000000000006890000000000000000000000000000000000000000000000000000000000000693000000000000000000000000000000000000000000000000000000000000068a0000000000000000000000000000000000000000000000000000000000000694000000000000000000000000000000000000000000000000000000000000068b0000000000000000000000000000000000000000000000000000000000000695000000000000000000000000000000000000000000000000000000000000068c0000000000000000000000000000000000000000000000000000000000000696000000000000000000000000000000000000000000000000000000000000068d0000000000000000000000000000000000000000000000000000000000000697000000000000000000000000000000000000000000000000000000000000068e0000000000000000000000000000000000000000000000000000000000000698000000000000000000000000000000000000000000000000000000000000068f00000000000000000000000000000000000000000000000000000000000006990000000000000000000000000000000000000000000000000000000000000690000000000000000000000000000000000000000000000000000000000000069a0000000000000000000000000000000000000000000000000000000000000691000000000000000000000000000000000000000000000000000000000000069b0000000000000000000000000000000000000000000000000000000000000692000000000000000000000000000000000000000000000000000000000000069c0000000000000000000000000000000000000000000000000000000000000693000000000000000000000000000000000000000000000000000000000000069d0000000000000000000000000000000000000000000000000000000000000694000000000000000000000000000000000000000000000000000000000000069e0000000000000000000000000000000000000000000000000000000000000695000000000000000000000000000000000000000000000000000000000000069f000000000000000000000000000000000000000000000000000000000000069600000000000000000000000000000000000000000000000000000000000006a0000000000000000000000000000000000000000000000000000000000000069700000000000000000000000000000000000000000000000000000000000006a1000000000000000000000000000000000000000000000000000000000000069800000000000000000000000000000000000000000000000000000000000006a2000000000000000000000000000000000000000000000000000000000000069900000000000000000000000000000000000000000000000000000000000006a3000000000000000000000000000000000000000000000000000000000000069a00000000000000000000000000000000000000000000000000000000000006a4000000000000000000000000000000000000000000000000000000000000069b00000000000000000000000000000000000000000000000000000000000006a5000000000000000000000000000000000000000000000000000000000000069c00000000000000000000000000000000000000000000000000000000000006a6000000000000000000000000000000000000000000000000000000000000069d00000000000000000000000000000000000000000000000000000000000006a7000000000000000000000000000000000000000000000000000000000000069e00000000000000000000000000000000000000000000000000000000000006a8000000000000000000000000000000000000000000000000000000000000069f00000000000000000000000000000000000000000000000000000000000006a90000000000000000004000000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000002c100000000000000000000000000000000000000000000000000000000000002c200000000000000000000000000000000000000000000000000000000000002c300000000000000000000000000000000000000000000000000000000000002c400000000000000000000000000000000000000000000000000000000000002c500000000000000000000000000000000000000000000000000000000000002c600000000000000000000000000000000000000000000000000000000000002c700000000000000000000000000000000000000000000000000000000000002c800000000000000000000000000000000000000000000000000000000000002c900000000000000000000000000000000000000000000000000000000000002ca00000000000000000000000000000000000000000000000000000000000002cb00000000000000000000000000000000000000000000000000000000000002cc00000000000000000000000000000000000000000000000000000000000002cd00000000000000000000000000000000000000000000000000000000000002ce00000000000000000000000000000000000000000000000000000000000002cf00000000000000000000000000000000000000000000000000000000000002d000000000000000000000000000000000000000000000000000000000000002d100000000000000000000000000000000000000000000000000000000000002d200000000000000000000000000000000000000000000000000000000000002d300000000000000000000000000000000000000000000000000000000000002d400000000000000000000000000000000000000000000000000000000000002d500000000000000000000000000000000000000000000000000000000000002d600000000000000000000000000000000000000000000000000000000000002d700000000000000000000000000000000000000000000000000000000000002d800000000000000000000000000000000000000000000000000000000000002d900000000000000000000000000000000000000000000000000000000000002da00000000000000000000000000000000000000000000000000000000000002db00000000000000000000000000000000000000000000000000000000000002dc00000000000000000000000000000000000000000000000000000000000002dd00000000000000000000000000000000000000000000000000000000000002de00000000000000000000000000000000000000000000000000000000000002df00000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000002e100000000000000000000000000000000000000000000000000000000000002e200000000000000000000000000000000000000000000000000000000000002e300000000000000000000000000000000000000000000000000000000000002e400000000000000000000000000000000000000000000000000000000000002e500000000000000000000000000000000000000000000000000000000000002e600000000000000000000000000000000000000000000000000000000000002e700000000000000000000000000000000000000000000000000000000000002e800000000000000000000000000000000000000000000000000000000000002e900000000000000000000000000000000000000000000000000000000000002ea00000000000000000000000000000000000000000000000000000000000002eb00000000000000000000000000000000000000000000000000000000000002ec00000000000000000000000000000000000000000000000000000000000002ed00000000000000000000000000000000000000000000000000000000000002ee00000000000000000000000000000000000000000000000000000000000002ef00000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000002f100000000000000000000000000000000000000000000000000000000000002f200000000000000000000000000000000000000000000000000000000000002f300000000000000000000000000000000000000000000000000000000000002f400000000000000000000000000000000000000000000000000000000000002f500000000000000000000000000000000000000000000000000000000000002f600000000000000000000000000000000000000000000000000000000000002f700000000000000000000000000000000000000000000000000000000000002f800000000000000000000000000000000000000000000000000000000000002f900000000000000000000000000000000000000000000000000000000000002fa00000000000000000000000000000000000000000000000000000000000002fb00000000000000000000000000000000000000000000000000000000000002fc00000000000000000000000000000000000000000000000000000000000002fd00000000000000000000000000000000000000000000000000000000000002fe00000000000000000000000000000000000000000000000000000000000002ff3f00000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000003c100000000000000000000000000000000000000000000000000000000000003c200000000000000000000000000000000000000000000000000000000000003c300000000000000000000000000000000000000000000000000000000000003c400000000000000000000000000000000000000000000000000000000000003c500000000000000000000000000000000000000000000000000000000000003c600000000000000000000000000000000000000000000000000000000000003c700000000000000000000000000000000000000000000000000000000000003c800000000000000000000000000000000000000000000000000000000000003c900000000000000000000000000000000000000000000000000000000000003ca00000000000000000000000000000000000000000000000000000000000003cb00000000000000000000000000000000000000000000000000000000000003cc00000000000000000000000000000000000000000000000000000000000003cd00000000000000000000000000000000000000000000000000000000000003ce00000000000000000000000000000000000000000000000000000000000003cf00000000000000000000000000000000000000000000000000000000000003d000000000000000000000000000000000000000000000000000000000000003d100000000000000000000000000000000000000000000000000000000000003d200000000000000000000000000000000000000000000000000000000000003d300000000000000000000000000000000000000000000000000000000000003d400000000000000000000000000000000000000000000000000000000000003d500000000000000000000000000000000000000000000000000000000000003d600000000000000000000000000000000000000000000000000000000000003d700000000000000000000000000000000000000000000000000000000000003d800000000000000000000000000000000000000000000000000000000000003d900000000000000000000000000000000000000000000000000000000000003da00000000000000000000000000000000000000000000000000000000000003db00000000000000000000000000000000000000000000000000000000000003dc00000000000000000000000000000000000000000000000000000000000003dd00000000000000000000000000000000000000000000000000000000000003de00000000000000000000000000000000000000000000000000000000000003df00000000000000000000000000000000000000000000000000000000000003e000000000000000000000000000000000000000000000000000000000000003e100000000000000000000000000000000000000000000000000000000000003e200000000000000000000000000000000000000000000000000000000000003e300000000000000000000000000000000000000000000000000000000000003e400000000000000000000000000000000000000000000000000000000000003e500000000000000000000000000000000000000000000000000000000000003e600000000000000000000000000000000000000000000000000000000000003e700000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000000000000000003e900000000000000000000000000000000000000000000000000000000000003ea00000000000000000000000000000000000000000000000000000000000003eb00000000000000000000000000000000000000000000000000000000000003ec00000000000000000000000000000000000000000000000000000000000003ed00000000000000000000000000000000000000000000000000000000000003ee00000000000000000000000000000000000000000000000000000000000003ef00000000000000000000000000000000000000000000000000000000000003f000000000000000000000000000000000000000000000000000000000000003f100000000000000000000000000000000000000000000000000000000000003f200000000000000000000000000000000000000000000000000000000000003f300000000000000000000000000000000000000000000000000000000000003f400000000000000000000000000000000000000000000000000000000000003f500000000000000000000000000000000000000000000000000000000000003f600000000000000000000000000000000000000000000000000000000000003f700000000000000000000000000000000000000000000000000000000000003f800000000000000000000000000000000000000000000000000000000000003f900000000000000000000000000000000000000000000000000000000000003fa00000000000000000000000000000000000000000000000000000000000003fb00000000000000000000000000000000000000000000000000000000000003fc00000000000000000000000000000000000000000000000000000000000003fd00000000000000000000000000000000000000000000000000000000000003fe0200000000000000000000000000000000000000000000000000000000000004c000000000000000000000000000000000000000000000000000000000000004c12000000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000006ca00000000000000000000000000000000000000000000000000000000000006c100000000000000000000000000000000000000000000000000000000000006cb00000000000000000000000000000000000000000000000000000000000006c200000000000000000000000000000000000000000000000000000000000006cc00000000000000000000000000000000000000000000000000000000000006c300000000000000000000000000000000000000000000000000000000000006cd00000000000000000000000000000000000000000000000000000000000006c400000000000000000000000000000000000000000000000000000000000006ce00000000000000000000000000000000000000000000000000000000000006c500000000000000000000000000000000000000000000000000000000000006cf00000000000000000000000000000000000000000000000000000000000006c600000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000006c700000000000000000000000000000000000000000000000000000000000006d100000000000000000000000000000000000000000000000000000000000006c800000000000000000000000000000000000000000000000000000000000006d200000000000000000000000000000000000000000000000000000000000006c900000000000000000000000000000000000000000000000000000000000006d300000000000000000000000000000000000000000000000000000000000006ca00000000000000000000000000000000000000000000000000000000000006d400000000000000000000000000000000000000000000000000000000000006cb00000000000000000000000000000000000000000000000000000000000006d500000000000000000000000000000000000000000000000000000000000006cc00000000000000000000000000000000000000000000000000000000000006d600000000000000000000000000000000000000000000000000000000000006cd00000000000000000000000000000000000000000000000000000000000006d700000000000000000000000000000000000000000000000000000000000006ce00000000000000000000000000000000000000000000000000000000000006d800000000000000000000000000000000000000000000000000000000000006cf00000000000000000000000000000000000000000000000000000000000006d900000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000006da00000000000000000000000000000000000000000000000000000000000006d100000000000000000000000000000000000000000000000000000000000006db00000000000000000000000000000000000000000000000000000000000006d200000000000000000000000000000000000000000000000000000000000006dc00000000000000000000000000000000000000000000000000000000000006d300000000000000000000000000000000000000000000000000000000000006dd00000000000000000000000000000000000000000000000000000000000006d400000000000000000000000000000000000000000000000000000000000006de00000000000000000000000000000000000000000000000000000000000006d500000000000000000000000000000000000000000000000000000000000006df00000000000000000000000000000000000000000000000000000000000006d600000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000006d700000000000000000000000000000000000000000000000000000000000006e100000000000000000000000000000000000000000000000000000000000006d800000000000000000000000000000000000000000000000000000000000006e200000000000000000000000000000000000000000000000000000000000006d900000000000000000000000000000000000000000000000000000000000006e300000000000000000000000000000000000000000000000000000000000006da00000000000000000000000000000000000000000000000000000000000006e400000000000000000000000000000000000000000000000000000000000006db00000000000000000000000000000000000000000000000000000000000006e500000000000000000000000000000000000000000000000000000000000006dc00000000000000000000000000000000000000000000000000000000000006e600000000000000000000000000000000000000000000000000000000000006dd00000000000000000000000000000000000000000000000000000000000006e700000000000000000000000000000000000000000000000000000000000006de00000000000000000000000000000000000000000000000000000000000006e800000000000000000000000000000000000000000000000000000000000006df00000000000000000000000000000000000000000000000000000000000006e9000000000000000000400000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000030100000000000000000000000000000000000000000000000000000000000003020000000000000000000000000000000000000000000000000000000000000303000000000000000000000000000000000000000000000000000000000000030400000000000000000000000000000000000000000000000000000000000003050000000000000000000000000000000000000000000000000000000000000306000000000000000000000000000000000000000000000000000000000000030700000000000000000000000000000000000000000000000000000000000003080000000000000000000000000000000000000000000000000000000000000309000000000000000000000000000000000000000000000000000000000000030a000000000000000000000000000000000000000000000000000000000000030b000000000000000000000000000000000000000000000000000000000000030c000000000000000000000000000000000000000000000000000000000000030d000000000000000000000000000000000000000000000000000000000000030e000000000000000000000000000000000000000000000000000000000000030f0000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000031100000000000000000000000000000000000000000000000000000000000003120000000000000000000000000000000000000000000000000000000000000313000000000000000000000000000000000000000000000000000000000000031400000000000000000000000000000000000000000000000000000000000003150000000000000000000000000000000000000000000000000000000000000316000000000000000000000000000000000000000000000000000000000000031700000000000000000000000000000000000000000000000000000000000003180000000000000000000000000000000000000000000000000000000000000319000000000000000000000000000000000000000000000000000000000000031a000000000000000000000000000000000000000000000000000000000000031b000000000000000000000000000000000000000000000000000000000000031c000000000000000000000000000000000000000000000000000000000000031d000000000000000000000000000000000000000000000000000000000000031e000000000000000000000000000000000000000000000000000000000000031f0000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000032100000000000000000000000000000000000000000000000000000000000003220000000000000000000000000000000000000000000000000000000000000323000000000000000000000000000000000000000000000000000000000000032400000000000000000000000000000000000000000000000000000000000003250000000000000000000000000000000000000000000000000000000000000326000000000000000000000000000000000000000000000000000000000000032700000000000000000000000000000000000000000000000000000000000003280000000000000000000000000000000000000000000000000000000000000329000000000000000000000000000000000000000000000000000000000000032a000000000000000000000000000000000000000000000000000000000000032b000000000000000000000000000000000000000000000000000000000000032c000000000000000000000000000000000000000000000000000000000000032d000000000000000000000000000000000000000000000000000000000000032e000000000000000000000000000000000000000000000000000000000000032f0000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000033100000000000000000000000000000000000000000000000000000000000003320000000000000000000000000000000000000000000000000000000000000333000000000000000000000000000000000000000000000000000000000000033400000000000000000000000000000000000000000000000000000000000003350000000000000000000000000000000000000000000000000000000000000336000000000000000000000000000000000000000000000000000000000000033700000000000000000000000000000000000000000000000000000000000003380000000000000000000000000000000000000000000000000000000000000339000000000000000000000000000000000000000000000000000000000000033a000000000000000000000000000000000000000000000000000000000000033b000000000000000000000000000000000000000000000000000000000000033c000000000000000000000000000000000000000000000000000000000000033d000000000000000000000000000000000000000000000000000000000000033e000000000000000000000000000000000000000000000000000000000000033f3f0000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040100000000000000000000000000000000000000000000000000000000000004020000000000000000000000000000000000000000000000000000000000000403000000000000000000000000000000000000000000000000000000000000040400000000000000000000000000000000000000000000000000000000000004050000000000000000000000000000000000000000000000000000000000000406000000000000000000000000000000000000000000000000000000000000040700000000000000000000000000000000000000000000000000000000000004080000000000000000000000000000000000000000000000000000000000000409000000000000000000000000000000000000000000000000000000000000040a000000000000000000000000000000000000000000000000000000000000040b000000000000000000000000000000000000000000000000000000000000040c000000000000000000000000000000000000000000000000000000000000040d000000000000000000000000000000000000000000000000000000000000040e000000000000000000000000000000000000000000000000000000000000040f0000000000000000000000000000000000000000000000000000000000000410000000000000000000000000000000000000000000000000000000000000041100000000000000000000000000000000000000000000000000000000000004120000000000000000000000000000000000000000000000000000000000000413000000000000000000000000000000000000000000000000000000000000041400000000000000000000000000000000000000000000000000000000000004150000000000000000000000000000000000000000000000000000000000000416000000000000000000000000000000000000000000000000000000000000041700000000000000000000000000000000000000000000000000000000000004180000000000000000000000000000000000000000000000000000000000000419000000000000000000000000000000000000000000000000000000000000041a000000000000000000000000000000000000000000000000000000000000041b000000000000000000000000000000000000000000000000000000000000041c000000000000000000000000000000000000000000000000000000000000041d000000000000000000000000000000000000000000000000000000000000041e000000000000000000000000000000000000000000000000000000000000041f0000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000042100000000000000000000000000000000000000000000000000000000000004220000000000000000000000000000000000000000000000000000000000000423000000000000000000000000000000000000000000000000000000000000042400000000000000000000000000000000000000000000000000000000000004250000000000000000000000000000000000000000000000000000000000000426000000000000000000000000000000000000000000000000000000000000042700000000000000000000000000000000000000000000000000000000000004280000000000000000000000000000000000000000000000000000000000000429000000000000000000000000000000000000000000000000000000000000042a000000000000000000000000000000000000000000000000000000000000042b000000000000000000000000000000000000000000000000000000000000042c000000000000000000000000000000000000000000000000000000000000042d000000000000000000000000000000000000000000000000000000000000042e000000000000000000000000000000000000000000000000000000000000042f0000000000000000000000000000000000000000000000000000000000000430000000000000000000000000000000000000000000000000000000000000043100000000000000000000000000000000000000000000000000000000000004320000000000000000000000000000000000000000000000000000000000000433000000000000000000000000000000000000000000000000000000000000043400000000000000000000000000000000000000000000000000000000000004350000000000000000000000000000000000000000000000000000000000000436000000000000000000000000000000000000000000000000000000000000043700000000000000000000000000000000000000000000000000000000000004380000000000000000000000000000000000000000000000000000000000000439000000000000000000000000000000000000000000000000000000000000043a000000000000000000000000000000000000000000000000000000000000043b000000000000000000000000000000000000000000000000000000000000043c000000000000000000000000000000000000000000000000000000000000043d000000000000000000000000000000000000000000000000000000000000043e0200000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000501200000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000070a0000000000000000000000000000000000000000000000000000000000000701000000000000000000000000000000000000000000000000000000000000070b0000000000000000000000000000000000000000000000000000000000000702000000000000000000000000000000000000000000000000000000000000070c0000000000000000000000000000000000000000000000000000000000000703000000000000000000000000000000000000000000000000000000000000070d0000000000000000000000000000000000000000000000000000000000000704000000000000000000000000000000000000000000000000000000000000070e0000000000000000000000000000000000000000000000000000000000000705000000000000000000000000000000000000000000000000000000000000070f00000000000000000000000000000000000000000000000000000000000007060000000000000000000000000000000000000000000000000000000000000710000000000000000000000000000000000000000000000000000000000000070700000000000000000000000000000000000000000000000000000000000007110000000000000000000000000000000000000000000000000000000000000708000000000000000000000000000000000000000000000000000000000000071200000000000000000000000000000000000000000000000000000000000007090000000000000000000000000000000000000000000000000000000000000713000000000000000000000000000000000000000000000000000000000000070a0000000000000000000000000000000000000000000000000000000000000714000000000000000000000000000000000000000000000000000000000000070b0000000000000000000000000000000000000000000000000000000000000715000000000000000000000000000000000000000000000000000000000000070c0000000000000000000000000000000000000000000000000000000000000716000000000000000000000000000000000000000000000000000000000000070d0000000000000000000000000000000000000000000000000000000000000717000000000000000000000000000000000000000000000000000000000000070e0000000000000000000000000000000000000000000000000000000000000718000000000000000000000000000000000000000000000000000000000000070f00000000000000000000000000000000000000000000000000000000000007190000000000000000000000000000000000000000000000000000000000000710000000000000000000000000000000000000000000000000000000000000071a0000000000000000000000000000000000000000000000000000000000000711000000000000000000000000000000000000000000000000000000000000071b0000000000000000000000000000000000000000000000000000000000000712000000000000000000000000000000000000000000000000000000000000071c0000000000000000000000000000000000000000000000000000000000000713000000000000000000000000000000000000000000000000000000000000071d0000000000000000000000000000000000000000000000000000000000000714000000000000000000000000000000000000000000000000000000000000071e0000000000000000000000000000000000000000000000000000000000000715000000000000000000000000000000000000000000000000000000000000071f00000000000000000000000000000000000000000000000000000000000007160000000000000000000000000000000000000000000000000000000000000720000000000000000000000000000000000000000000000000000000000000071700000000000000000000000000000000000000000000000000000000000007210000000000000000000000000000000000000000000000000000000000000718000000000000000000000000000000000000000000000000000000000000072200000000000000000000000000000000000000000000000000000000000007190000000000000000000000000000000000000000000000000000000000000723000000000000000000000000000000000000000000000000000000000000071a0000000000000000000000000000000000000000000000000000000000000724000000000000000000000000000000000000000000000000000000000000071b0000000000000000000000000000000000000000000000000000000000000725000000000000000000000000000000000000000000000000000000000000071c0000000000000000000000000000000000000000000000000000000000000726000000000000000000000000000000000000000000000000000000000000071d0000000000000000000000000000000000000000000000000000000000000727000000000000000000000000000000000000000000000000000000000000071e0000000000000000000000000000000000000000000000000000000000000728000000000000000000000000000000000000000000000000000000000000071f00000000000000000000000000000000000000000000000000000000000007290000000000000000", "txsEffectsHash": "0x001f86cec051421edd80056cd49b7bf9034751ec5b14e4c120fdc4427f5bba63", "decodedHeader": { @@ -47,10 +47,10 @@ "globalVariables": { "blockNumber": 2, "chainId": 31337, - "timestamp": 1712912131, + "timestamp": 1713529803, "version": 1, - "coinbase": "0xcb433ad76e9fe9c41059c27d265df41d9acbf5ff", - "feeRecipient": "0x232da3781f3971d8f6cb0246fd911a893453ef41346cbc81b495f4d887f9a1e3", + "coinbase": "0xa23e0eb6a23e0eb6a23e0eb6a23e0eb6a23e0eb6", + "feeRecipient": "0x09cd9129799990baa63ca94680ef6ce915fbd462e83f04298c9f4a4ee339198d", "gasFees": { "feePerDaGas": 0, "feePerL1Gas": 0, @@ -59,7 +59,7 @@ }, "lastArchive": { "nextAvailableLeafIndex": 2, - "root": "0x195de7b601a7882443a8b98043c504ef921f11a94dfa17ce1f5bc4461c685877" + "root": "0x2fc3ac909751b968a209d4b189dcd536f28c90b18d40ab9c73b95abd044d2874" }, "stateReference": { "l1ToL2MessageTree": { @@ -82,8 +82,8 @@ } } }, - "header": "0x195de7b601a7882443a8b98043c504ef921f11a94dfa17ce1f5bc4461c685877000000020000000000000000000000000000000000000000000000000000000000000002001f86cec051421edd80056cd49b7bf9034751ec5b14e4c120fdc4427f5bba6300212ff46db74e06c26240f9a92fb6fea84709380935d657361bbd5bcb89193700a5a7c9f331ce6832a69dc81873ed87de7ceeaaed2af1d595cb14ca9616eddd2e0232573b292e99cb24c082c3ef340d619341ab76aa1e9dff1ab1914963452d0000002024c6dc6d357aad01e10fe1adb877bb28b1df97375b874116e488086ca76e5f9600000200268020a622156e2beac47431b0cd70e1c81fef9a6aa3c365bfcbed9aa7301c5e000002802ecba8caa69552bb0d9bdf0d13eb328aeb6f166a1509678d9bfa9970971d69ab000001400000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000006618f703cb433ad76e9fe9c41059c27d265df41d9acbf5ff232da3781f3971d8f6cb0246fd911a893453ef41346cbc81b495f4d887f9a1e3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "publicInputsHash": "0x0018e52830d20f62abe9ccc5b87f998f69f73a0947b789bed500cb90da337d39", + "header": "0x2fc3ac909751b968a209d4b189dcd536f28c90b18d40ab9c73b95abd044d2874000000020000000000000000000000000000000000000000000000000000000000000002001f86cec051421edd80056cd49b7bf9034751ec5b14e4c120fdc4427f5bba6300212ff46db74e06c26240f9a92fb6fea84709380935d657361bbd5bcb89193700a5a7c9f331ce6832a69dc81873ed87de7ceeaaed2af1d595cb14ca9616eddd2e0232573b292e99cb24c082c3ef340d619341ab76aa1e9dff1ab1914963452d0000002024c6dc6d357aad01e10fe1adb877bb28b1df97375b874116e488086ca76e5f9600000200268020a622156e2beac47431b0cd70e1c81fef9a6aa3c365bfcbed9aa7301c5e000002802ecba8caa69552bb0d9bdf0d13eb328aeb6f166a1509678d9bfa9970971d69ab000001400000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000662263cba23e0eb6a23e0eb6a23e0eb6a23e0eb6a23e0eb609cd9129799990baa63ca94680ef6ce915fbd462e83f04298c9f4a4ee339198d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "publicInputsHash": "0x000587c30ef90e65a291fa5b6632b54e235c8adfd16ff10791f82d688c7d387f", "numTxs": 4 } } \ No newline at end of file diff --git a/noir-projects/aztec-nr/address-note/src/address_note.nr b/noir-projects/aztec-nr/address-note/src/address_note.nr index 048cd2f5033..440cfdf3b6f 100644 --- a/noir-projects/aztec-nr/address-note/src/address_note.nr +++ b/noir-projects/aztec-nr/address-note/src/address_note.nr @@ -4,7 +4,7 @@ use dep::aztec::log::emit_encrypted_log; use dep::aztec::{ protocol_types::{address::AztecAddress, traits::Empty}, note::{note_header::NoteHeader, note_interface::NoteInterface, utils::compute_note_hash_for_consumption}, - oracle::{unsafe_rand::unsafe_rand, nullifier_key::get_nullifier_secret_key, get_public_key::get_public_key}, + oracle::{unsafe_rand::unsafe_rand, nullifier_key::get_app_nullifier_secret_key, get_public_key::get_public_key}, hash::pedersen_hash, context::PrivateContext }; @@ -23,23 +23,21 @@ impl NoteInterface for AddressNote { fn compute_nullifier(self, context: &mut PrivateContext) -> Field { let note_hash_for_nullify = compute_note_hash_for_consumption(self); - let secret = context.request_nullifier_secret_key(self.owner); + let secret = context.request_app_nullifier_secret_key(self.owner); // TODO(#1205) Should use a non-zero generator index. pedersen_hash([ note_hash_for_nullify, - secret.low, - secret.high, + secret, ],0) } fn compute_nullifier_without_context(self) -> Field { let note_hash_for_nullify = compute_note_hash_for_consumption(self); - let secret = get_nullifier_secret_key(self.owner); + let secret = get_app_nullifier_secret_key(self.owner); // TODO(#1205) Should use a non-zero generator index. pedersen_hash([ note_hash_for_nullify, - secret.low, - secret.high, + secret, ],0) } diff --git a/noir-projects/aztec-nr/aztec/src/context/private_context.nr b/noir-projects/aztec-nr/aztec/src/context/private_context.nr index 33dd48fd262..691e491b13b 100644 --- a/noir-projects/aztec-nr/aztec/src/context/private_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/private_context.nr @@ -1,11 +1,10 @@ use crate::{ context::{inputs::PrivateContextInputs, interface::ContextInterface}, - key::nullifier_key::validate_nullifier_key_against_address, messaging::process_l1_to_l2_message, - hash::{hash_args_array, ArgsHasher}, + messaging::process_l1_to_l2_message, hash::{hash_args_array, ArgsHasher}, oracle::{ arguments, returns, call_private_function::call_private_function_internal, enqueue_public_function_call::enqueue_public_function_call_internal, - header::get_header_at, nullifier_key::{get_nullifier_key_pair, NullifierKeyPair} + header::get_header_at, nullifier_key::{get_nullifier_keys, NullifierKeys} } }; use dep::protocol_types::{ @@ -71,7 +70,7 @@ struct PrivateContext { // encrypted_logs_preimages: Vec, // unencrypted_logs_preimages: Vec, - nullifier_key: Option, + nullifier_key: Option, } impl ContextInterface for PrivateContext { @@ -220,24 +219,24 @@ impl PrivateContext { self.side_effect_counter = self.side_effect_counter + 1; } - pub fn request_nullifier_secret_key(&mut self, account: AztecAddress) -> GrumpkinPrivateKey { - let key_pair = if self.nullifier_key.is_none() { - let key_pair = get_nullifier_key_pair(account); - validate_nullifier_key_against_address(account, key_pair.public_key); - let request = NullifierKeyValidationRequest { public_key: key_pair.public_key, secret_key: key_pair.secret_key }; + pub fn request_app_nullifier_secret_key(&mut self, account: AztecAddress) -> Field { + let keys = if self.nullifier_key.is_none() { + let keys = get_nullifier_keys(account); + let request = NullifierKeyValidationRequest { + master_nullifier_public_key: keys.master_nullifier_public_key, + app_nullifier_secret_key: keys.app_nullifier_secret_key + }; self.nullifier_key_validation_requests.push(request); - self.nullifier_key = Option::some(key_pair); - key_pair + self.nullifier_key = Option::some(keys); + keys } else { - let key_pair = self.nullifier_key.unwrap_unchecked(); + let keys = self.nullifier_key.unwrap_unchecked(); // If MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL is larger than 1, need to update the way the key pair is cached. assert(MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL == 1); - assert( - key_pair.account == account, "Cannot query nullifier key for more than one account per call" - ); - key_pair + assert(keys.account == account, "Cannot query nullifier key for more than one account per call"); + keys }; - key_pair.secret_key + keys.app_nullifier_secret_key } // docs:start:context_message_portal diff --git a/noir-projects/aztec-nr/aztec/src/key.nr b/noir-projects/aztec-nr/aztec/src/key.nr deleted file mode 100644 index 3ea8deca754..00000000000 --- a/noir-projects/aztec-nr/aztec/src/key.nr +++ /dev/null @@ -1 +0,0 @@ -mod nullifier_key; diff --git a/noir-projects/aztec-nr/aztec/src/key/nullifier_key.nr b/noir-projects/aztec-nr/aztec/src/key/nullifier_key.nr deleted file mode 100644 index 7154a1917d8..00000000000 --- a/noir-projects/aztec-nr/aztec/src/key/nullifier_key.nr +++ /dev/null @@ -1,8 +0,0 @@ -use dep::protocol_types::{address::AztecAddress, grumpkin_point::GrumpkinPoint}; - -pub fn validate_nullifier_key_against_address( - _address: AztecAddress, - _nullifier_public_key: GrumpkinPoint -) { - // TODO: Nullifier public key should be part of the address. -} diff --git a/noir-projects/aztec-nr/aztec/src/lib.nr b/noir-projects/aztec-nr/aztec/src/lib.nr index 077381daa93..81390fb52eb 100644 --- a/noir-projects/aztec-nr/aztec/src/lib.nr +++ b/noir-projects/aztec-nr/aztec/src/lib.nr @@ -3,7 +3,6 @@ mod deploy; mod hash; mod history; mod initializer; -mod key; mod log; mod messaging; mod note; diff --git a/noir-projects/aztec-nr/aztec/src/oracle/get_public_key.nr b/noir-projects/aztec-nr/aztec/src/oracle/get_public_key.nr index abb7167dee9..a509e8c1b54 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/get_public_key.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/get_public_key.nr @@ -12,8 +12,9 @@ pub fn get_public_key(address: AztecAddress) -> GrumpkinPoint { let pub_key = GrumpkinPoint::new(result[0], result[1]); let partial_address = PartialAddress::from_field(result[2]); - let calculated_address = AztecAddress::compute(PublicKeysHash::compute(pub_key), partial_address); - assert(calculated_address.eq(address)); + // TODO(#5830): disabling the following constraint until we update the oracle according to the new key scheme + // let calculated_address = AztecAddress::compute(PublicKeysHash::compute(pub_key), partial_address); + // assert(calculated_address.eq(address)); pub_key } diff --git a/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr b/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr index c3429d4f811..0926fca65e6 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr @@ -1,27 +1,28 @@ use dep::protocol_types::{address::AztecAddress, grumpkin_point::GrumpkinPoint, grumpkin_private_key::GrumpkinPrivateKey}; -struct NullifierKeyPair { +// Nullifier keys pertaining to a specific account +struct NullifierKeys { account: AztecAddress, - public_key: GrumpkinPoint, - secret_key: GrumpkinPrivateKey, + master_nullifier_public_key: GrumpkinPoint, + app_nullifier_secret_key: Field, } -#[oracle(getNullifierKeyPair)] -fn get_nullifier_key_pair_oracle(_account: AztecAddress) -> [Field; 4] {} +#[oracle(getNullifierKeys)] +fn get_nullifier_keys_oracle(_account: AztecAddress) -> [Field; 3] {} -unconstrained fn get_nullifier_key_pair_internal(account: AztecAddress) -> NullifierKeyPair { - let result = get_nullifier_key_pair_oracle(account); - NullifierKeyPair { +unconstrained fn get_nullifier_keys_internal(account: AztecAddress) -> NullifierKeys { + let result = get_nullifier_keys_oracle(account); + NullifierKeys { account, - public_key: GrumpkinPoint { x: result[0], y: result[1] }, - secret_key: GrumpkinPrivateKey { high: result[2], low: result[3] } + master_nullifier_public_key: GrumpkinPoint { x: result[0], y: result[1] }, + app_nullifier_secret_key: result[2], } } -pub fn get_nullifier_key_pair(account: AztecAddress) -> NullifierKeyPair { - get_nullifier_key_pair_internal(account) +pub fn get_nullifier_keys(account: AztecAddress) -> NullifierKeys { + get_nullifier_keys_internal(account) } -pub fn get_nullifier_secret_key(account: AztecAddress) -> GrumpkinPrivateKey { - get_nullifier_key_pair_internal(account).secret_key +pub fn get_app_nullifier_secret_key(account: AztecAddress) -> Field { + get_nullifier_keys_internal(account).app_nullifier_secret_key } diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable.nr b/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable.nr index e19528b978c..06942a2cbd0 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable.nr @@ -5,7 +5,7 @@ use crate::note::{ lifecycle::{create_note, destroy_note}, note_getter::{get_note, view_notes}, note_interface::NoteInterface, note_viewer_options::NoteViewerOptions }; -use crate::oracle::{nullifier_key::get_nullifier_secret_key, notes::check_nullifier_exists}; +use crate::oracle::notes::check_nullifier_exists; use crate::state_vars::storage::Storage; // docs:start:struct diff --git a/noir-projects/aztec-nr/value-note/src/value_note.nr b/noir-projects/aztec-nr/value-note/src/value_note.nr index 4598c1ab17b..8875209b9de 100644 --- a/noir-projects/aztec-nr/value-note/src/value_note.nr +++ b/noir-projects/aztec-nr/value-note/src/value_note.nr @@ -1,7 +1,7 @@ use dep::aztec::{ protocol_types::{address::AztecAddress, traits::{Deserialize, Serialize}}, note::{note_header::NoteHeader, note_interface::NoteInterface, utils::compute_note_hash_for_consumption}, - oracle::{unsafe_rand::unsafe_rand, nullifier_key::get_nullifier_secret_key, get_public_key::get_public_key}, + oracle::{unsafe_rand::unsafe_rand, nullifier_key::get_app_nullifier_secret_key, get_public_key::get_public_key}, log::emit_encrypted_log, hash::pedersen_hash, context::PrivateContext }; @@ -21,12 +21,11 @@ impl NoteInterface for ValueNote { fn compute_nullifier(self, context: &mut PrivateContext) -> Field { let note_hash_for_nullify = compute_note_hash_for_consumption(self); - let secret = context.request_nullifier_secret_key(self.owner); + let secret = context.request_app_nullifier_secret_key(self.owner); // TODO(#1205) Should use a non-zero generator index. pedersen_hash([ note_hash_for_nullify, - secret.low, - secret.high, + secret, ],0) } @@ -34,12 +33,11 @@ impl NoteInterface for ValueNote { fn compute_nullifier_without_context(self) -> Field { let note_hash_for_nullify = compute_note_hash_for_consumption(self); - let secret = get_nullifier_secret_key(self.owner); + let secret = get_app_nullifier_secret_key(self.owner); // TODO(#1205) Should use a non-zero generator index. pedersen_hash([ note_hash_for_nullify, - secret.low, - secret.high, + secret, ],0) } diff --git a/noir-projects/noir-contracts/contracts/app_subscription_contract/src/subscription_note.nr b/noir-projects/noir-contracts/contracts/app_subscription_contract/src/subscription_note.nr index c541c92ae39..dc984c37338 100644 --- a/noir-projects/noir-contracts/contracts/app_subscription_contract/src/subscription_note.nr +++ b/noir-projects/noir-contracts/contracts/app_subscription_contract/src/subscription_note.nr @@ -1,7 +1,7 @@ use dep::aztec::prelude::{AztecAddress, PrivateContext, NoteHeader, emit_encrypted_log, NoteInterface}; use dep::aztec::{ note::utils::compute_note_hash_for_consumption, hash::pedersen_hash, - oracle::{nullifier_key::get_nullifier_secret_key, get_public_key::get_public_key} + oracle::{nullifier_key::get_app_nullifier_secret_key, get_public_key::get_public_key} }; global SUBSCRIPTION_NOTE_LEN: Field = 3; @@ -18,23 +18,21 @@ struct SubscriptionNote { impl NoteInterface for SubscriptionNote { fn compute_nullifier(self, context: &mut PrivateContext) -> Field { let unique_siloed_note_hash = compute_note_hash_for_consumption(self); - let secret = context.request_nullifier_secret_key(self.owner); + let secret = context.request_app_nullifier_secret_key(self.owner); // TODO(#1205) Should use a non-zero generator index. pedersen_hash([ unique_siloed_note_hash, - secret.low, - secret.high, + secret, ],0) } fn compute_nullifier_without_context(self) -> Field { let unique_siloed_note_hash = compute_note_hash_for_consumption(self); - let secret = get_nullifier_secret_key(self.owner); + let secret = get_app_nullifier_secret_key(self.owner); // TODO(#1205) Should use a non-zero generator index. pedersen_hash([ unique_siloed_note_hash, - secret.low, - secret.high, + secret, ],0) } diff --git a/noir-projects/noir-contracts/contracts/card_game_contract/src/cards.nr b/noir-projects/noir-contracts/contracts/card_game_contract/src/cards.nr index 51f914b567a..e46fb7e8407 100644 --- a/noir-projects/noir-contracts/contracts/card_game_contract/src/cards.nr +++ b/noir-projects/noir-contracts/contracts/card_game_contract/src/cards.nr @@ -172,8 +172,8 @@ pub fn get_pack_cards( context: &mut PrivateContext ) -> [Card; PACK_CARDS] { // generate pseudo randomness deterministically from 'seed' and user secret - let secret = context.request_nullifier_secret_key(owner); - let mix = secret.high + secret.low + seed; + let secret = context.request_app_nullifier_secret_key(owner); + let mix = secret + seed; let random_bytes = std::hash::sha256_slice(mix.to_le_bytes(32)); let mut cards = [Card::from_field(0); PACK_CARDS]; diff --git a/noir-projects/noir-contracts/contracts/docs_example_contract/src/types/card_note.nr b/noir-projects/noir-contracts/contracts/docs_example_contract/src/types/card_note.nr index f66b855485a..617b24ef025 100644 --- a/noir-projects/noir-contracts/contracts/docs_example_contract/src/types/card_note.nr +++ b/noir-projects/noir-contracts/contracts/docs_example_contract/src/types/card_note.nr @@ -1,7 +1,7 @@ use dep::aztec::prelude::{AztecAddress, NoteInterface, NoteHeader, PrivateContext, emit_encrypted_log}; use dep::aztec::{ note::{utils::compute_note_hash_for_consumption}, - oracle::{nullifier_key::get_nullifier_secret_key, get_public_key::get_public_key}, + oracle::{nullifier_key::get_app_nullifier_secret_key, get_public_key::get_public_key}, hash::pedersen_hash, protocol_types::traits::Empty }; @@ -27,21 +27,19 @@ impl CardNote { impl NoteInterface for CardNote { fn compute_nullifier(self, context: &mut PrivateContext) -> Field { let note_hash_for_nullify = compute_note_hash_for_consumption(self); - let secret = context.request_nullifier_secret_key(self.owner); + let secret = context.request_app_nullifier_secret_key(self.owner); pedersen_hash([ note_hash_for_nullify, - secret.high, - secret.low, + secret, ],0) } fn compute_nullifier_without_context(self) -> Field { let note_hash_for_nullify = compute_note_hash_for_consumption(self); - let secret = get_nullifier_secret_key(self.owner); + let secret = get_app_nullifier_secret_key(self.owner); pedersen_hash([ note_hash_for_nullify, - secret.high, - secret.low, + secret, ],0) } diff --git a/noir-projects/noir-contracts/contracts/easy_private_voting_contract/src/main.nr b/noir-projects/noir-contracts/contracts/easy_private_voting_contract/src/main.nr index 634acdb45bd..6924ca2b328 100644 --- a/noir-projects/noir-contracts/contracts/easy_private_voting_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/easy_private_voting_contract/src/main.nr @@ -27,8 +27,8 @@ contract EasyPrivateVoting { // docs:start:cast_vote #[aztec(private)] // annotation to mark function as private and expose private context fn cast_vote(candidate: Field) { - let secret = context.request_nullifier_secret_key(context.msg_sender()); // get secret key of caller of function - let nullifier = dep::std::hash::pedersen_hash([context.msg_sender().to_field(), secret.low, secret.high]); // compute nullifier with this secret key so others can't descrypt it + let secret = context.request_app_nullifier_secret_key(context.msg_sender()); // get secret key of caller of function + let nullifier = dep::std::hash::pedersen_hash([context.msg_sender().to_field(), secret]); // derive nullifier from sender and secret context.push_new_nullifier(nullifier, 0); // push nullifier EasyPrivateVoting::at(context.this_address()).add_to_tally_public(candidate).enqueue(&mut context); } diff --git a/noir-projects/noir-contracts/contracts/ecdsa_account_contract/src/ecdsa_public_key_note.nr b/noir-projects/noir-contracts/contracts/ecdsa_account_contract/src/ecdsa_public_key_note.nr index cd25fa907da..22144f965af 100644 --- a/noir-projects/noir-contracts/contracts/ecdsa_account_contract/src/ecdsa_public_key_note.nr +++ b/noir-projects/noir-contracts/contracts/ecdsa_account_contract/src/ecdsa_public_key_note.nr @@ -5,7 +5,7 @@ use dep::aztec::prelude::{ use dep::aztec::{ note::utils::compute_note_hash_for_consumption, - oracle::{nullifier_key::get_nullifier_secret_key, get_public_key::get_public_key}, + oracle::{nullifier_key::get_app_nullifier_secret_key, get_public_key::get_public_key}, hash::pedersen_hash }; @@ -68,23 +68,21 @@ impl NoteInterface for EcdsaPublicKeyNote { fn compute_nullifier(self, context: &mut PrivateContext) -> Field { let unique_siloed_note_hash = compute_note_hash_for_consumption(self); - let secret = context.request_nullifier_secret_key(self.owner); + let secret = context.request_app_nullifier_secret_key(self.owner); // TODO(#1205) Should use a non-zero generator index. pedersen_hash([ unique_siloed_note_hash, - secret.low, - secret.high, + secret, ],0) } fn compute_nullifier_without_context(self) -> Field { let unique_siloed_note_hash = compute_note_hash_for_consumption(self); - let secret = get_nullifier_secret_key(self.owner); + let secret = get_app_nullifier_secret_key(self.owner); // TODO(#1205) Should use a non-zero generator index. pedersen_hash([ unique_siloed_note_hash, - secret.low, - secret.high, + secret, ],0) } diff --git a/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/public_key_note.nr b/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/public_key_note.nr index f78ad778189..39d25636db7 100644 --- a/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/public_key_note.nr +++ b/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/public_key_note.nr @@ -1,7 +1,7 @@ use dep::aztec::prelude::{AztecAddress, NoteHeader, NoteInterface, PrivateContext, emit_encrypted_log}; use dep::aztec::{ note::utils::compute_note_hash_for_consumption, hash::pedersen_hash, - oracle::{nullifier_key::get_nullifier_secret_key, get_public_key::get_public_key} + oracle::{nullifier_key::get_app_nullifier_secret_key, get_public_key::get_public_key} }; global PUBLIC_KEY_NOTE_LEN: Field = 3; @@ -18,23 +18,21 @@ struct PublicKeyNote { impl NoteInterface for PublicKeyNote { fn compute_nullifier(self, context: &mut PrivateContext) -> Field { let unique_siloed_note_hash = compute_note_hash_for_consumption(self); - let secret = context.request_nullifier_secret_key(self.owner); + let secret = context.request_app_nullifier_secret_key(self.owner); // TODO(#1205) Should use a non-zero generator index. pedersen_hash([ unique_siloed_note_hash, - secret.low, - secret.high, + secret, ],0) } fn compute_nullifier_without_context(self) -> Field { let unique_siloed_note_hash = compute_note_hash_for_consumption(self); - let secret = get_nullifier_secret_key(self.owner); + let secret = get_app_nullifier_secret_key(self.owner); // TODO(#1205) Should use a non-zero generator index. pedersen_hash([ unique_siloed_note_hash, - secret.low, - secret.high, + secret, ],0) } diff --git a/noir-projects/noir-contracts/contracts/schnorr_single_key_account_contract/src/main.nr b/noir-projects/noir-contracts/contracts/schnorr_single_key_account_contract/src/main.nr index 9803ed4f15e..bb6aad4b787 100644 --- a/noir-projects/noir-contracts/contracts/schnorr_single_key_account_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/schnorr_single_key_account_contract/src/main.nr @@ -45,7 +45,9 @@ contract SchnorrSingleKeyAccount { #[contract_library_method] fn is_valid_impl(context: &mut PrivateContext, outer_hash: Field) -> bool { let witness = get_auth_witness(outer_hash); - assert(recover_address(outer_hash, witness).eq(context.this_address())); + // TODO(#5830): the following is currently broken because we are no longer able to compute public keys hash + // in recover_address(...) just from user public key. + // assert(recover_address(outer_hash, witness).eq(context.this_address())); true } } diff --git a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr index 765f9203368..3bd6b23d854 100644 --- a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr +++ b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr @@ -1,6 +1,6 @@ use dep::aztec::prelude::{AztecAddress, NoteHeader, NoteInterface, PrivateContext, emit_encrypted_log}; use dep::aztec::{note::utils::compute_note_hash_for_consumption, hash::pedersen_hash}; -use dep::aztec::oracle::{unsafe_rand::unsafe_rand, nullifier_key::get_nullifier_secret_key, get_public_key::get_public_key}; +use dep::aztec::oracle::{unsafe_rand::unsafe_rand, nullifier_key::get_app_nullifier_secret_key, get_public_key::get_public_key}; trait OwnedNote { fn new(amount: U128, owner: AztecAddress) -> Self; @@ -26,24 +26,22 @@ impl NoteInterface for TokenNote { // docs:start:nullifier fn compute_nullifier(self, context: &mut PrivateContext) -> Field { let note_hash_for_nullify = compute_note_hash_for_consumption(self); - let secret = context.request_nullifier_secret_key(self.owner); + let secret = context.request_app_nullifier_secret_key(self.owner); // TODO(#1205) Should use a non-zero generator index. pedersen_hash([ note_hash_for_nullify, - secret.low, - secret.high, + secret, ],0) } // docs:end:nullifier fn compute_nullifier_without_context(self) -> Field { let note_hash_for_nullify = compute_note_hash_for_consumption(self); - let secret = get_nullifier_secret_key(self.owner); + let secret = get_app_nullifier_secret_key(self.owner); // TODO(#1205) Should use a non-zero generator index. pedersen_hash([ note_hash_for_nullify, - secret.low, - secret.high, + secret, ],0) } diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/main.nr b/noir-projects/noir-contracts/contracts/token_contract/src/main.nr index 7978fe76412..cc892421ece 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/main.nr @@ -14,10 +14,7 @@ contract Token { use dep::compressed_string::FieldCompressedString; - use dep::aztec::prelude::{ - NoteGetterOptions, NoteHeader, Map, PublicMutable, SharedImmutable, PrivateSet, - FunctionSelector, AztecAddress - }; + use dep::aztec::prelude::{NoteGetterOptions, Map, PublicMutable, SharedImmutable, PrivateSet, AztecAddress}; use dep::aztec::hash::compute_secret_hash; // docs:start:import_authwit diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr b/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr index 9a336e4baa9..cd76d49659c 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr @@ -3,7 +3,7 @@ use dep::aztec::prelude::{ PrivateSet, Map, emit_encrypted_log }; use dep::aztec::{note::utils::compute_note_hash_for_consumption, hash::pedersen_hash}; -use dep::aztec::oracle::{unsafe_rand::unsafe_rand, nullifier_key::get_nullifier_secret_key, get_public_key::get_public_key}; +use dep::aztec::oracle::{unsafe_rand::unsafe_rand, nullifier_key::get_app_nullifier_secret_key, get_public_key::get_public_key}; trait OwnedNote { fn new(amount: U128, owner: AztecAddress) -> Self; @@ -29,24 +29,22 @@ impl NoteInterface for TokenNote { // docs:start:nullifier fn compute_nullifier(self, context: &mut PrivateContext) -> Field { let note_hash_for_nullify = compute_note_hash_for_consumption(self); - let secret = context.request_nullifier_secret_key(self.owner); + let secret = context.request_app_nullifier_secret_key(self.owner); // TODO(#1205) Should use a non-zero generator index. pedersen_hash([ note_hash_for_nullify, - secret.low, - secret.high, + secret, ],0) } // docs:end:nullifier fn compute_nullifier_without_context(self) -> Field { let note_hash_for_nullify = compute_note_hash_for_consumption(self); - let secret = get_nullifier_secret_key(self.owner); + let secret = get_app_nullifier_secret_key(self.owner); // TODO(#1205) Should use a non-zero generator index. pedersen_hash([ note_hash_for_nullify, - secret.low, - secret.high, + secret, ],0) } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_init.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_init.nr index 3c6784bdc6b..3f9677da95b 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_init.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_init.nr @@ -547,7 +547,7 @@ mod tests { fn propagate_nullifier_key_validation_requests() { let mut builder = PrivateKernelInitInputsBuilder::new(); - let request = NullifierKeyValidationRequest { public_key: GrumpkinPoint { x: 1, y: 2 }, secret_key: GrumpkinPrivateKey { high: 3, low: 4 } }; + let request = NullifierKeyValidationRequest { master_nullifier_public_key: GrumpkinPoint { x: 1, y: 2 }, app_nullifier_secret_key: 3 }; builder.private_call.public_inputs.nullifier_key_validation_requests.push(request); let public_inputs = builder.execute(); @@ -555,8 +555,8 @@ mod tests { assert_eq(array_length(public_inputs.validation_requests.nullifier_key_validation_requests), 1); let request_context = public_inputs.validation_requests.nullifier_key_validation_requests[0]; - assert_eq(request_context.public_key, request.public_key); - assert_eq(request_context.secret_key, request.secret_key); + assert_eq(request_context.master_nullifier_public_key, request.master_nullifier_public_key); + assert_eq(request_context.app_nullifier_secret_key, request.app_nullifier_secret_key); assert_eq( request_context.contract_address, builder.private_call.public_inputs.call_context.storage_contract_address ); diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/private_validation_request_processor.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/private_validation_request_processor.nr index 469a4d6d9bf..0f82c12f557 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/private_validation_request_processor.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/private_validation_request_processor.nr @@ -1,9 +1,10 @@ +use dep::std::hash::poseidon2::Poseidon2::hash as poseidon2_hash; use crate::{nullifier_read_request_reset::NullifierReadRequestHints, reset::read_request::reset_read_requests}; use dep::types::{ abis::{side_effect::{SideEffect, SideEffectLinkedToNoteHash}, validation_requests::ValidationRequests}, constants::{ MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_NOTE_HASH_READ_REQUESTS_PER_TX, - MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX + MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, GENERATOR_INDEX__NSK_M }, grumpkin_private_key::GrumpkinPrivateKey, keys::compute_siloed_nullifier_secret_key, traits::is_empty @@ -61,15 +62,20 @@ impl PrivateValidationRequestProcessor { for i in 0..MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX { let request = requests[i]; if !is_empty(request) { - let master_secret_key = self.master_nullifier_secret_keys[i]; - let computed_public_key = master_secret_key.derive_public_key(); + let master_nullifier_secret_key = self.master_nullifier_secret_keys[i]; + // First we check that derived public key matches master nullifier public key from request + let master_nullifier_public_key = master_nullifier_secret_key.derive_public_key(); assert( - computed_public_key.eq(request.public_key), "Cannot derive nullifier public key from the master key." + master_nullifier_public_key.eq(request.master_nullifier_public_key), "Failed to derive matching master nullifier public key from the secret key." ); - let computed_secret_key = compute_siloed_nullifier_secret_key(master_secret_key, request.contract_address); + // Then we check that siloing the master secret key with the contract address gives the app nullifier secret key + let app_nullifier_secret_key_preimage = [ + master_nullifier_secret_key.high, master_nullifier_secret_key.low, request.contract_address.to_field(), GENERATOR_INDEX__NSK_M + ]; + let app_nullifier_secret_key = poseidon2_hash(app_nullifier_secret_key_preimage, app_nullifier_secret_key_preimage.len()); assert( - computed_secret_key.eq(request.secret_key), "Cannot derive siloed secret key from the master key." + app_nullifier_secret_key.eq(request.app_nullifier_secret_key), "Failed to derive matching app nullifier secret key from the secret key." ); } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/function_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/function_data.nr index 6e6632bccd0..2a4148182ca 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/function_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/function_data.nr @@ -65,7 +65,7 @@ fn empty_hash() { let data = FunctionData::empty(); let hash = data.hash(); - // Value from function_data.test.ts "computes empty item hash" test + // Value from function_data.test.ts "computes empty function data hash" test let test_data_empty_hash = 0x27b1d0839a5b23baf12a8d195b18ac288fcf401afb2f70b8a4b529ede5fa9fed; assert_eq(hash, test_data_empty_hash); } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier_key_validation_request.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier_key_validation_request.nr index a522dace348..1a08e9f7a2f 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier_key_validation_request.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier_key_validation_request.nr @@ -7,22 +7,22 @@ use crate::{ }; struct NullifierKeyValidationRequest { - public_key: GrumpkinPoint, - secret_key: GrumpkinPrivateKey, + master_nullifier_public_key: GrumpkinPoint, + app_nullifier_secret_key: Field, // not a GrumpkinScalar because it's output of poseidon2 } impl Eq for NullifierKeyValidationRequest { fn eq(self, request: NullifierKeyValidationRequest) -> bool { - (request.public_key.eq(self.public_key)) - & (request.secret_key.eq(self.secret_key)) + (request.master_nullifier_public_key.eq(self.master_nullifier_public_key)) + & (request.app_nullifier_secret_key.eq(self.app_nullifier_secret_key)) } } impl Empty for NullifierKeyValidationRequest { fn empty() -> Self { NullifierKeyValidationRequest { - public_key: GrumpkinPoint::zero(), - secret_key: GrumpkinPrivateKey::zero(), + master_nullifier_public_key: GrumpkinPoint::zero(), + app_nullifier_secret_key: 0, } } } @@ -30,10 +30,9 @@ impl Empty for NullifierKeyValidationRequest { impl Serialize for NullifierKeyValidationRequest { fn serialize(self) -> [Field; NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH] { [ - self.public_key.x, - self.public_key.y, - self.secret_key.high, - self.secret_key.low, + self.master_nullifier_public_key.x, + self.master_nullifier_public_key.y, + self.app_nullifier_secret_key, ] } } @@ -41,28 +40,32 @@ impl Serialize for NullifierKeyValidati impl Deserialize for NullifierKeyValidationRequest { fn deserialize(fields: [Field; NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH]) -> Self { Self { - public_key: GrumpkinPoint::new(fields[0], fields[1]), - secret_key: GrumpkinPrivateKey::new(fields[2], fields[3]), + master_nullifier_public_key: GrumpkinPoint::new(fields[0], fields[1]), + app_nullifier_secret_key: fields[2], } } } impl NullifierKeyValidationRequest { pub fn to_context(self, contract_address: AztecAddress) -> NullifierKeyValidationRequestContext { - NullifierKeyValidationRequestContext { public_key: self.public_key, secret_key: self.secret_key, contract_address } + NullifierKeyValidationRequestContext { + master_nullifier_public_key: self.master_nullifier_public_key, + app_nullifier_secret_key: self.app_nullifier_secret_key, + contract_address + } } } struct NullifierKeyValidationRequestContext { - public_key: GrumpkinPoint, - secret_key: GrumpkinPrivateKey, + master_nullifier_public_key: GrumpkinPoint, + app_nullifier_secret_key: Field, contract_address: AztecAddress, } impl Eq for NullifierKeyValidationRequestContext { fn eq(self, request: NullifierKeyValidationRequestContext) -> bool { - (request.public_key.eq(self.public_key)) - & (request.secret_key.eq(self.secret_key)) + (request.master_nullifier_public_key.eq(self.master_nullifier_public_key)) + & (request.app_nullifier_secret_key.eq(self.app_nullifier_secret_key)) & (request.contract_address.eq(self.contract_address)) } } @@ -70,8 +73,8 @@ impl Eq for NullifierKeyValidationRequestContext { impl Empty for NullifierKeyValidationRequestContext { fn empty() -> Self { NullifierKeyValidationRequestContext { - public_key: GrumpkinPoint::zero(), - secret_key: GrumpkinPrivateKey::zero(), + master_nullifier_public_key: GrumpkinPoint::zero(), + app_nullifier_secret_key: 0, contract_address: AztecAddress::zero(), } } @@ -80,10 +83,9 @@ impl Empty for NullifierKeyValidationRequestContext { impl Serialize for NullifierKeyValidationRequestContext { fn serialize(self) -> [Field; NULLIFIER_KEY_VALIDATION_REQUEST_CONTEXT_LENGTH] { [ - self.public_key.x, - self.public_key.y, - self.secret_key.high, - self.secret_key.low, + self.master_nullifier_public_key.x, + self.master_nullifier_public_key.y, + self.app_nullifier_secret_key, self.contract_address.to_field(), ] } @@ -92,9 +94,9 @@ impl Serialize for NullifierKey impl Deserialize for NullifierKeyValidationRequestContext { fn deserialize(fields: [Field; NULLIFIER_KEY_VALIDATION_REQUEST_CONTEXT_LENGTH]) -> Self { Self { - public_key: GrumpkinPoint::new(fields[0], fields[1]), - secret_key: GrumpkinPrivateKey::new(fields[2], fields[3]), - contract_address: AztecAddress::from_field(fields[4]), + master_nullifier_public_key: GrumpkinPoint::new(fields[0], fields[1]), + app_nullifier_secret_key: fields[2], + contract_address: AztecAddress::from_field(fields[3]), } } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr index 4f353a7d7ac..87a2ffcb2c6 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr @@ -85,6 +85,6 @@ fn empty_hash() { let hash = item.hash(); // Value from private_call_stack_item.test.ts "computes empty item hash" test - let test_data_empty_hash = 0x2cbdfd59ceb55fcc4dbe43b9d6f052f5ca448ef5990b005b9927e578b1b69b6c; + let test_data_empty_hash = 0x2826eee20026ba6fb21916387c4dfa7843cbce1fdcff508132812be5e544f286; assert_eq(hash, test_data_empty_hash); } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr index f60b8997987..50a0b517681 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr @@ -215,7 +215,7 @@ fn serialization_of_empty() { fn empty_hash() { let inputs = PrivateCircuitPublicInputs::empty(); let hash = inputs.hash(); - // Value from private_circuit_public_inputs.test.ts "computes empty item hash" test - let test_data_empty_hash = 0x2c1ec6595f8d43f5fc983441bc75a84d2384008f5bd7a1d499da057130abe6cd; + // Value from private_circuit_public_inputs.test.ts "computes empty inputs hash" test + let test_data_empty_hash = 0x265dcde577695a65f00acc24d861e65e9486526ec2b9f9bab9493476f73e4bc9; assert_eq(hash, test_data_empty_hash); } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_circuit_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_circuit_public_inputs.nr index 602daf873db..f4b2c4d3a2e 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_circuit_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_circuit_public_inputs.nr @@ -182,7 +182,7 @@ fn empty_hash() { let inputs = PublicCircuitPublicInputs::empty(); let hash = inputs.hash(); - // Value from public_circuit_public_inputs.test.ts "computes empty item hash" test + // Value from public_circuit_public_inputs.test.ts "computes empty inputs hash" test let test_data_empty_hash = 0x048912d56248af479f8d7ecedbba7092d27741b10075a989e040f8e3242a7a3f; assert_eq(hash, test_data_empty_hash); } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr b/noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr index 86a1fb4549d..c96342721a6 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr @@ -1,9 +1,10 @@ use crate::{ crate::address::{eth_address::EthAddress, partial_address::PartialAddress, public_keys_hash::PublicKeysHash}, - constants::{AZTEC_ADDRESS_LENGTH, GENERATOR_INDEX__CONTRACT_ADDRESS}, + constants::{AZTEC_ADDRESS_LENGTH, GENERATOR_INDEX__CONTRACT_ADDRESS_V1}, contract_class_id::ContractClassId, hash::pedersen_hash, grumpkin_point::GrumpkinPoint, traits::{Empty, FromField, ToField, Serialize, Deserialize}, utils }; +use dep::std::hash::poseidon2::Poseidon2::hash as poseidon2_hash; // Aztec address struct AztecAddress { @@ -53,31 +54,10 @@ impl AztecAddress { Self { inner: 0 } } - pub fn compute_from_public_key( - pub_key: GrumpkinPoint, - contract_class_id: ContractClassId, - salt: Field, - initialization_hash: Field, - portal_contract_address: EthAddress, - deployer: AztecAddress - ) -> AztecAddress { - AztecAddress::compute( - PublicKeysHash::compute(pub_key), - PartialAddress::compute( - contract_class_id, - salt, - initialization_hash, - portal_contract_address, - deployer - ) - ) - } - pub fn compute(pub_keys_hash: PublicKeysHash, partial_address: PartialAddress) -> AztecAddress { AztecAddress::from_field( - pedersen_hash( - [pub_keys_hash.to_field(), partial_address.to_field()], - GENERATOR_INDEX__CONTRACT_ADDRESS + poseidon2_hash( + [pub_keys_hash.to_field(), partial_address.to_field(), GENERATOR_INDEX__CONTRACT_ADDRESS_V1], 3 ) ) } @@ -96,35 +76,13 @@ impl AztecAddress { } } -#[test] -fn compute_address() { - let point = GrumpkinPoint { x: 1, y: 2 }; - let contract_address_salt = 3; - let contract_class_id = ContractClassId::from_field(4); - let initialization_hash = 5; - let portal_contract_address = EthAddress::from_field(6); - let deployer = AztecAddress::from_field(7); - - let address = AztecAddress::compute_from_public_key( - point, - contract_class_id, - contract_address_salt, - initialization_hash, - portal_contract_address, - deployer - ); - - let expected_computed_address_from_preimage = 0x027ea2b41ced2ec9a98305984e96dd28518536a4628883ccdc06e38aa8997220; - assert(address.to_field() == expected_computed_address_from_preimage); -} - #[test] fn compute_address_from_partial_and_pubkey() { - let point = GrumpkinPoint { x: 1, y: 2 }; - let partial_address = PartialAddress::from_field(3); + let pub_keys_hash = PublicKeysHash::from_field(1); + let partial_address = PartialAddress::from_field(2); - let address = AztecAddress::compute(PublicKeysHash::compute(point), partial_address); - let expected_computed_address_from_partial_and_pubkey = 0x0447f893197175723deb223696e2e96dbba1e707ee8507766373558877e74197; + let address = AztecAddress::compute(pub_keys_hash, partial_address); + let expected_computed_address_from_partial_and_pubkey = 0x1b6ead051e7b42665064ca6cf1ec77da0a36d86e00d1ff6e44077966c0c3a9fa; assert(address.to_field() == expected_computed_address_from_partial_and_pubkey); } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/address/public_keys_hash.nr b/noir-projects/noir-protocol-circuits/crates/types/src/address/public_keys_hash.nr index ff75e878f4e..dfe3023abb2 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/address/public_keys_hash.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/address/public_keys_hash.nr @@ -37,6 +37,7 @@ impl PublicKeysHash { Self { inner: field } } + // TODO(#5830): update this pub fn compute(public_key: GrumpkinPoint) -> Self { PublicKeysHash::from_field( pedersen_hash( @@ -58,10 +59,11 @@ impl PublicKeysHash { } } -#[test] -fn compute_public_keys_hash() { - let point = GrumpkinPoint { x: 1, y: 2 }; - let actual = PublicKeysHash::compute(point); - let expected_public_keys_hash = 0x1923a6246e305720b6aaf751fde0342613e93c82e455c3831e28375c16dd40d8; - assert(actual.to_field() == expected_public_keys_hash); -} +// TODO(#5830): re-enable this test once the compute function is updated +// #[test] +// fn compute_public_keys_hash() { +// let point = GrumpkinPoint { x: 1, y: 2 }; +// let actual = PublicKeysHash::compute(point); +// let expected_public_keys_hash = 0x22d83a089d7650514c2de24cd30185a414d943eaa19817c67bffe2c3183006a3; +// assert(actual.to_field() == expected_public_keys_hash); +// } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr index 2907f5cc264..a089d51d2d3 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr @@ -126,7 +126,7 @@ global REGISTERER_UNCONSTRAINED_FUNCTION_BROADCASTED_MAGIC_VALUE = 0xe7af8166354 // CONTRACT INSTANCE CONSTANTS // sha224sum 'struct ContractInstanceDeployed' global DEPLOYER_CONTRACT_INSTANCE_DEPLOYED_MAGIC_VALUE = 0x85864497636cf755ae7bde03f267ce01a520981c21c3682aaf82a631; -global DEPLOYER_CONTRACT_ADDRESS = 0x161b653b72ac5aa2982ce485b242b5c1e09afcbf27b89696f5a4e3151be37245; +global DEPLOYER_CONTRACT_ADDRESS = 0x1f47133752dfcd9604f2d89c631797a84ed207c1c51d08533226dafcc8bd8548; // LENGTH OF STRUCTS SERIALIZED TO FIELDS global AZTEC_ADDRESS_LENGTH = 1; @@ -147,8 +147,8 @@ global APPEND_ONLY_TREE_SNAPSHOT_LENGTH = 2; global L1_TO_L2_MESSAGE_LENGTH: u64 = 6; global L2_TO_L1_MESSAGE_LENGTH: u64 = 2; global MAX_BLOCK_NUMBER_LENGTH: u64 = 2; // 1 for the option flag, 1 for the value -global NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH = 4; -global NULLIFIER_KEY_VALIDATION_REQUEST_CONTEXT_LENGTH = 5; +global NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH = 3; +global NULLIFIER_KEY_VALIDATION_REQUEST_CONTEXT_LENGTH = 4; global PARTIAL_STATE_REFERENCE_LENGTH: u64 = 6; global READ_REQUEST_LENGTH = 2; global SIDE_EFFECT_LENGTH = 2; @@ -204,7 +204,7 @@ global GENERATOR_INDEX__FUNCTION_LEAF = 11; global GENERATOR_INDEX__CONTRACT_DEPLOYMENT_DATA = 12; global GENERATOR_INDEX__CONSTRUCTOR = 13; global GENERATOR_INDEX__CONSTRUCTOR_ARGS = 14; -global GENERATOR_INDEX__CONTRACT_ADDRESS = 15; +global GENERATOR_INDEX__CONTRACT_ADDRESS_V1 = 15; global GENERATOR_INDEX__CONTRACT_LEAF = 16; global GENERATOR_INDEX__CALL_CONTEXT = 17; global GENERATOR_INDEX__CALL_STACK_ITEM = 18; @@ -237,4 +237,3 @@ global GENERATOR_INDEX__IVSK_M = 48; global GENERATOR_INDEX__OVSK_M = 49; global GENERATOR_INDEX__TSK_M = 50; global GENERATOR_INDEX__PUBLIC_KEYS_HASH = 51; -global GENERATOR_INDEX__CONTRACT_ADDRESS_V1 = 52; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr b/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr index 8721314a68b..f43ee8f9b5c 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr @@ -8,9 +8,7 @@ use crate::traits::is_empty; use crate::utils::{uint256::U256, field::field_from_bytes_32_trunc}; use crate::constants::{ FUNCTION_TREE_HEIGHT, GENERATOR_INDEX__SILOED_NOTE_HASH, GENERATOR_INDEX__OUTER_NULLIFIER, - GENERATOR_INDEX__VK, GENERATOR_INDEX__CONSTRUCTOR, GENERATOR_INDEX__PARTIAL_ADDRESS, - GENERATOR_INDEX__CONTRACT_ADDRESS, GENERATOR_INDEX__NOTE_HASH_NONCE, - GENERATOR_INDEX__UNIQUE_NOTE_HASH + GENERATOR_INDEX__VK, GENERATOR_INDEX__NOTE_HASH_NONCE, GENERATOR_INDEX__UNIQUE_NOTE_HASH }; use crate::traits::Hash; use crate::messaging::l2_to_l1_message::L2ToL1Message; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures/contracts.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures/contracts.nr index 6aa8598dc16..5a78d4382f6 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures/contracts.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures/contracts.nr @@ -22,13 +22,13 @@ global default_contract = ContractData { artifact_hash: 0x0000000000000000000000000000000000000000000000000000000000003039, public_bytecode_commitment: 0x129a3438653fe147133b2c274757920e37896305e7664c8c1eb380be3efd5fed, private_functions_root: 0x19a3cc0b714976fb35d58b684ba36e86f82bac8b87517904a2727e5113fb4cba, - address: AztecAddress { inner: 0x25de5f29a6d515e67d0ac85f399098acd03c5d4a4884b8c560aee68014715ef1 }, - partial_address: PartialAddress { inner: 0x1420f3a4c4a589be4ea00c0a131dc00127d566725b21dcd1fb421a724710e66b }, + address: AztecAddress { inner: 0x2d941148ee5adeece35991d32acbcf4200742991c61990dee965bedf729d21a9 }, + partial_address: PartialAddress { inner: 0x23a6933a485200a8d34b9929d61868c9635793f878d67ce86a1b1355c0ab0d47 }, portal_contract_address: EthAddress { inner: 0x0000000000000000000000000000000000005ba0 }, contract_class_id: ContractClassId { inner: 0x0ce2a998337b1e6da1ac1d802a8bb9e10b7d705d210e61efb9642855009814a6 }, public_keys_hash: PublicKeysHash { inner: 0x000000000000000000000000000000000000000000000000000000000000b26e }, - salted_initialization_hash: SaltedInitializationHash { inner: 0x2003637d02f08887d36dc2f27dd961f51f17e0a8a43dc0268dfcefcd96efc3a4 }, - deployer: AztecAddress { inner: 0x0000000000000000000000000000000000000000000000000000000000000000 }, + salted_initialization_hash: SaltedInitializationHash { inner: 0x0b095458845137ebf1e6061c8c0ba1d907241a3b56dc1d3e73d2fea78f04a036 }, + deployer: AztecAddress { inner: 0x0000000000000000000000000000000000000000000000000000000000000000 } }; // taken from __snapshots__/noir_test_gen.test.ts.snap @@ -37,11 +37,11 @@ global parent_contract = ContractData { artifact_hash: 0x00000000000000000000000000000000000000000000000000000000000004bc, public_bytecode_commitment: 0x1435ed970b275bebf95de3df53f23f3d2e97c9b54cf442bb03a3fa17a0ee3cd7, private_functions_root: 0x2c1c949cb226995de94b7b8b5aeaab440739f2dfeb06d358441f60932cf243a7, - address: AztecAddress { inner: 0x178916e52e64b3880e7f837ab30e58222b2971f0150cbc16060bb3589fd96e23 }, - partial_address: PartialAddress { inner: 0x009a6e74b3cebfe0351ceec448d722aa973c1c9da63bbf9f902f1896f3fa1832 }, + address: AztecAddress { inner: 0x24692d7dbb532557c7466e8782d1fe99077e4787570414bd1a5e8fa5300caad8 }, + partial_address: PartialAddress { inner: 0x127bbd73a3cf497fb2d85342571695d894985b449a9343eec55485e9cbc514f8 }, portal_contract_address: EthAddress { inner: 0x0000000000000000000000000000000000000913 }, contract_class_id: ContractClassId { inner: 0x1f1f963a350e2c883cc6730c19fc5d5b47a40694d805cbb0720fa76fe295df90 }, public_keys_hash: PublicKeysHash { inner: 0x00000000000000000000000000000000000000000000000000000000000011c1 }, - salted_initialization_hash: SaltedInitializationHash { inner: 0x275e153c147f9cb61a5e7b354e81484696d6a54ffc251dcf4ed8276ab24868d2 }, - deployer: AztecAddress { inner: 0x0000000000000000000000000000000000000000000000000000000000000000 }, + salted_initialization_hash: SaltedInitializationHash { inner: 0x04643e65513869350552499ed3412df59540dffe3cd698203deee8900b53bcec }, + deployer: AztecAddress { inner: 0x0000000000000000000000000000000000000000000000000000000000000000 } }; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/transaction/tx_context.nr b/noir-projects/noir-protocol-circuits/crates/types/src/transaction/tx_context.nr index abb6f9fba04..69cc22add13 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/transaction/tx_context.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/transaction/tx_context.nr @@ -79,10 +79,10 @@ fn serialization_of_empty() { #[test] fn empty_hash() { - let inputs = TxContext::empty(); - let hash = inputs.hash(); + let context = TxContext::empty(); + let hash = context.hash(); - // Value from tx_context.test.ts "computes empty item hash" test + // Value from tx_context.test.ts "computes empty context hash" test let test_data_empty_hash = 0x200569267c0f73ac89aaa414239398db9445dd4ad3a8cf37015cd55b8d4c5e8d; assert_eq(hash, test_data_empty_hash); } diff --git a/yarn-project/accounts/src/defaults/account_contract.ts b/yarn-project/accounts/src/defaults/account_contract.ts index f2842c9ac0f..dc3b2330059 100644 --- a/yarn-project/accounts/src/defaults/account_contract.ts +++ b/yarn-project/accounts/src/defaults/account_contract.ts @@ -1,5 +1,6 @@ import { type AccountContract, type AccountInterface, type AuthWitnessProvider } from '@aztec/aztec.js/account'; import { type CompleteAddress } from '@aztec/circuit-types'; +import { type Fr } from '@aztec/circuits.js'; import { type ContractArtifact } from '@aztec/foundation/abi'; import { type NodeInfo } from '@aztec/types/interfaces'; @@ -19,7 +20,7 @@ export abstract class DefaultAccountContract implements AccountContract { return this.artifact; } - getInterface(address: CompleteAddress, nodeInfo: NodeInfo): AccountInterface { - return new DefaultAccountInterface(this.getAuthWitnessProvider(address), address, nodeInfo); + getInterface(address: CompleteAddress, publicKeysHash: Fr, nodeInfo: NodeInfo): AccountInterface { + return new DefaultAccountInterface(this.getAuthWitnessProvider(address), address, publicKeysHash, nodeInfo); } } diff --git a/yarn-project/accounts/src/defaults/account_interface.ts b/yarn-project/accounts/src/defaults/account_interface.ts index 5d7fa311c6e..f32e96aa208 100644 --- a/yarn-project/accounts/src/defaults/account_interface.ts +++ b/yarn-project/accounts/src/defaults/account_interface.ts @@ -17,6 +17,7 @@ export class DefaultAccountInterface implements AccountInterface { constructor( private authWitnessProvider: AuthWitnessProvider, private address: CompleteAddress, + private publicKeysHash: Fr, nodeInfo: Pick, ) { this.entrypoint = new DefaultAccountEntrypoint( @@ -37,6 +38,10 @@ export class DefaultAccountInterface implements AccountInterface { return this.authWitnessProvider.createAuthWit(messageHash); } + getPublicKeysHash(): Fr { + return this.publicKeysHash; + } + getCompleteAddress(): CompleteAddress { return this.address; } diff --git a/yarn-project/accounts/src/ecdsa/index.ts b/yarn-project/accounts/src/ecdsa/index.ts index 4efcf941dcc..b27891f23dc 100644 --- a/yarn-project/accounts/src/ecdsa/index.ts +++ b/yarn-project/accounts/src/ecdsa/index.ts @@ -6,8 +6,8 @@ */ import { AccountManager, type Salt } from '@aztec/aztec.js/account'; import { type AccountWallet, getWallet } from '@aztec/aztec.js/wallet'; -import { type GrumpkinPrivateKey, type PXE } from '@aztec/circuit-types'; -import { type AztecAddress } from '@aztec/circuits.js'; +import { type PXE } from '@aztec/circuit-types'; +import { type AztecAddress, type Fr } from '@aztec/circuits.js'; import { EcdsaAccountContract } from './account_contract.js'; @@ -17,17 +17,12 @@ export { EcdsaAccountContract }; /** * Creates an Account that relies on an ECDSA signing key for authentication. * @param pxe - An PXE server instance. - * @param encryptionPrivateKey - Grumpkin key used for note encryption. + * @param secretKey - Secret key used to derive all the keystore keys. * @param signingPrivateKey - Secp256k1 key used for signing transactions. * @param salt - Deployment salt. */ -export function getEcdsaAccount( - pxe: PXE, - encryptionPrivateKey: GrumpkinPrivateKey, - signingPrivateKey: Buffer, - salt?: Salt, -): AccountManager { - return new AccountManager(pxe, encryptionPrivateKey, new EcdsaAccountContract(signingPrivateKey), salt); +export function getEcdsaAccount(pxe: PXE, secretKey: Fr, signingPrivateKey: Buffer, salt?: Salt): AccountManager { + return new AccountManager(pxe, secretKey, new EcdsaAccountContract(signingPrivateKey), salt); } /** diff --git a/yarn-project/accounts/src/schnorr/index.ts b/yarn-project/accounts/src/schnorr/index.ts index 7e752fce6ac..1053606041b 100644 --- a/yarn-project/accounts/src/schnorr/index.ts +++ b/yarn-project/accounts/src/schnorr/index.ts @@ -7,7 +7,7 @@ import { AccountManager, type Salt } from '@aztec/aztec.js/account'; import { type AccountWallet, getWallet } from '@aztec/aztec.js/wallet'; import { type GrumpkinPrivateKey, type PXE } from '@aztec/circuit-types'; -import { type AztecAddress } from '@aztec/circuits.js'; +import { type AztecAddress, type Fr } from '@aztec/circuits.js'; import { SchnorrAccountContract } from './account_contract.js'; @@ -18,17 +18,17 @@ export { SchnorrAccountContractArtifact } from './artifact.js'; /** * Creates an Account Manager that relies on a Grumpkin signing key for authentication. * @param pxe - An PXE server instance. - * @param encryptionPrivateKey - Grumpkin key used for note encryption. + * @param secretKey - Secret key used to derive all the keystore keys. * @param signingPrivateKey - Grumpkin key used for signing transactions. * @param salt - Deployment salt. */ export function getSchnorrAccount( pxe: PXE, - encryptionPrivateKey: GrumpkinPrivateKey, + secretKey: Fr, signingPrivateKey: GrumpkinPrivateKey, salt?: Salt, ): AccountManager { - return new AccountManager(pxe, encryptionPrivateKey, new SchnorrAccountContract(signingPrivateKey), salt); + return new AccountManager(pxe, secretKey, new SchnorrAccountContract(signingPrivateKey), salt); } /** diff --git a/yarn-project/accounts/src/single_key/index.ts b/yarn-project/accounts/src/single_key/index.ts index 1293f97fd6d..f29ed18a7e6 100644 --- a/yarn-project/accounts/src/single_key/index.ts +++ b/yarn-project/accounts/src/single_key/index.ts @@ -7,7 +7,8 @@ import { AccountManager, type Salt } from '@aztec/aztec.js/account'; import { type AccountWallet, getWallet } from '@aztec/aztec.js/wallet'; import { type GrumpkinPrivateKey, type PXE } from '@aztec/circuit-types'; -import { type AztecAddress } from '@aztec/circuits.js'; +import { type AztecAddress, type Fr, GeneratorIndex } from '@aztec/circuits.js'; +import { sha512ToGrumpkinScalar } from '@aztec/foundation/crypto'; import { SingleKeyAccountContract } from './account_contract.js'; @@ -18,20 +19,12 @@ export { SchnorrSingleKeyAccountContractArtifact as SingleKeyAccountContractArti /** * Creates an Account that uses the same Grumpkin key for encryption and authentication. * @param pxe - An PXE server instance. - * @param encryptionAndSigningPrivateKey - Grumpkin key used for note encryption and signing transactions. - * @param salt - Deployment salt . + * @param secretKey - Secret key used to derive all the keystore keys (in this case also used to get signing key). + * @param salt - Deployment salt. */ -export function getSingleKeyAccount( - pxe: PXE, - encryptionAndSigningPrivateKey: GrumpkinPrivateKey, - salt?: Salt, -): AccountManager { - return new AccountManager( - pxe, - encryptionAndSigningPrivateKey, - new SingleKeyAccountContract(encryptionAndSigningPrivateKey), - salt, - ); +export function getSingleKeyAccount(pxe: PXE, secretKey: Fr, salt?: Salt): AccountManager { + const encryptionPrivateKey = sha512ToGrumpkinScalar([secretKey, GeneratorIndex.IVSK_M]); + return new AccountManager(pxe, secretKey, new SingleKeyAccountContract(encryptionPrivateKey), salt); } /** diff --git a/yarn-project/accounts/src/testing/configuration.ts b/yarn-project/accounts/src/testing/configuration.ts index a7e9b2c160b..7fc376ddd70 100644 --- a/yarn-project/accounts/src/testing/configuration.ts +++ b/yarn-project/accounts/src/testing/configuration.ts @@ -1,16 +1,22 @@ import { generatePublicKey } from '@aztec/aztec.js'; -import { type AccountWalletWithPrivateKey } from '@aztec/aztec.js/wallet'; +import { type AccountWalletWithSecretKey } from '@aztec/aztec.js/wallet'; import { type PXE } from '@aztec/circuit-types'; -import { Fr, GrumpkinScalar } from '@aztec/foundation/fields'; +import { GeneratorIndex } from '@aztec/circuits.js/constants'; +import { sha512ToGrumpkinScalar } from '@aztec/foundation/crypto'; +import { Fr } from '@aztec/foundation/fields'; import { getSchnorrAccount } from '../schnorr/index.js'; -export const INITIAL_TEST_ENCRYPTION_KEYS = [ - GrumpkinScalar.fromString('2153536ff6628eee01cf4024889ff977a18d9fa61d0e414422f7681cf085c281'), - GrumpkinScalar.fromString('aebd1b4be76efa44f5ee655c20bf9ea60f7ae44b9a7fd1fd9f189c7a0b0cdae'), - GrumpkinScalar.fromString('0f6addf0da06c33293df974a565b03d1ab096090d907d98055a8b7f4954e120c'), +export const INITIAL_TEST_SECRET_KEYS = [ + Fr.fromString('2153536ff6628eee01cf4024889ff977a18d9fa61d0e414422f7681cf085c281'), + Fr.fromString('aebd1b4be76efa44f5ee655c20bf9ea60f7ae44b9a7fd1fd9f189c7a0b0cdae'), + Fr.fromString('0f6addf0da06c33293df974a565b03d1ab096090d907d98055a8b7f4954e120c'), ]; +export const INITIAL_TEST_ENCRYPTION_KEYS = INITIAL_TEST_SECRET_KEYS.map(secretKey => + sha512ToGrumpkinScalar([secretKey, GeneratorIndex.IVSK_M]), +); +// TODO(#5837): come up with a standard signing key derivation scheme instead of using ivsk_m as signing keys here export const INITIAL_TEST_SIGNING_KEYS = INITIAL_TEST_ENCRYPTION_KEYS; export const INITIAL_TEST_ACCOUNT_SALTS = [Fr.ZERO, Fr.ZERO, Fr.ZERO]; @@ -20,9 +26,9 @@ export const INITIAL_TEST_ACCOUNT_SALTS = [Fr.ZERO, Fr.ZERO, Fr.ZERO]; * @param pxe - PXE instance. * @returns A set of AccountWallet implementations for each of the initial accounts. */ -export function getInitialTestAccountsWallets(pxe: PXE): Promise { +export function getInitialTestAccountsWallets(pxe: PXE): Promise { return Promise.all( - INITIAL_TEST_ENCRYPTION_KEYS.map((encryptionKey, i) => + INITIAL_TEST_SECRET_KEYS.map((encryptionKey, i) => getSchnorrAccount(pxe, encryptionKey!, INITIAL_TEST_SIGNING_KEYS[i]!, INITIAL_TEST_ACCOUNT_SALTS[i]).getWallet(), ), ); @@ -33,15 +39,18 @@ export function getInitialTestAccountsWallets(pxe: PXE): Promise { +export async function getDeployedTestAccountsWallets(pxe: PXE): Promise { const registeredAccounts = await pxe.getRegisteredAccounts(); return Promise.all( - INITIAL_TEST_ENCRYPTION_KEYS.filter(initialKey => { - const publicKey = generatePublicKey(initialKey); + INITIAL_TEST_SECRET_KEYS.filter(initialSecretKey => { + const initialEncryptionKey = sha512ToGrumpkinScalar([initialSecretKey, GeneratorIndex.IVSK_M]); + const publicKey = generatePublicKey(initialEncryptionKey); return registeredAccounts.find(registered => registered.publicKey.equals(publicKey)) != undefined; - }).map((encryptionKey, i) => - getSchnorrAccount(pxe, encryptionKey!, INITIAL_TEST_SIGNING_KEYS[i]!, INITIAL_TEST_ACCOUNT_SALTS[i]).getWallet(), - ), + }).map(secretKey => { + const signingKey = sha512ToGrumpkinScalar([secretKey, GeneratorIndex.IVSK_M]); + // TODO(#5726): use actual salt here instead of hardcoding Fr.ZERO + return getSchnorrAccount(pxe, secretKey, signingKey, Fr.ZERO).getWallet(); + }), ); } @@ -51,11 +60,11 @@ export async function getDeployedTestAccountsWallets(pxe: PXE): Promise { - const account = getSchnorrAccount(pxe, privateKey, INITIAL_TEST_SIGNING_KEYS[i], INITIAL_TEST_ACCOUNT_SALTS[i]); + const accounts = INITIAL_TEST_SECRET_KEYS.map((secretKey, i) => { + const account = getSchnorrAccount(pxe, secretKey, INITIAL_TEST_SIGNING_KEYS[i], INITIAL_TEST_ACCOUNT_SALTS[i]); return { account, - privateKey, + secretKey, }; }); // Attempt to get as much parallelism as possible diff --git a/yarn-project/accounts/src/testing/create_account.ts b/yarn-project/accounts/src/testing/create_account.ts index 9b409740b6c..262fb29e07b 100644 --- a/yarn-project/accounts/src/testing/create_account.ts +++ b/yarn-project/accounts/src/testing/create_account.ts @@ -1,6 +1,7 @@ -import { type AccountWalletWithPrivateKey } from '@aztec/aztec.js/wallet'; +import { type AccountWalletWithSecretKey } from '@aztec/aztec.js/wallet'; import { type PXE } from '@aztec/circuit-types'; -import { GrumpkinScalar } from '@aztec/circuits.js'; +import { Fr, GeneratorIndex } from '@aztec/circuits.js'; +import { sha512ToGrumpkinScalar } from '@aztec/foundation/crypto'; import { getSchnorrAccount } from '../schnorr/index.js'; @@ -9,8 +10,10 @@ import { getSchnorrAccount } from '../schnorr/index.js'; * @param pxe - PXE. * @returns - A wallet for a fresh account. */ -export function createAccount(pxe: PXE): Promise { - return getSchnorrAccount(pxe, GrumpkinScalar.random(), GrumpkinScalar.random()).waitSetup(); +export function createAccount(pxe: PXE): Promise { + const secretKey = Fr.random(); + const signingKey = sha512ToGrumpkinScalar([secretKey, GeneratorIndex.IVSK_M]); + return getSchnorrAccount(pxe, secretKey, signingKey).waitSetup(); } /** @@ -19,12 +22,14 @@ export function createAccount(pxe: PXE): Promise { * @param numberOfAccounts - How many accounts to create. * @returns The created account wallets. */ -export async function createAccounts(pxe: PXE, numberOfAccounts = 1): Promise { +export async function createAccounts(pxe: PXE, numberOfAccounts = 1): Promise { const accounts = []; // Prepare deployments for (let i = 0; i < numberOfAccounts; ++i) { - const account = getSchnorrAccount(pxe, GrumpkinScalar.random(), GrumpkinScalar.random()); + const secretKey = Fr.random(); + const signingKey = sha512ToGrumpkinScalar([secretKey, GeneratorIndex.IVSK_M]); + const account = getSchnorrAccount(pxe, secretKey, signingKey); // Unfortunately the function below is not stateless and we call it here because it takes a long time to run and // the results get stored within the account object. By calling it here we increase the probability of all the // accounts being deployed in the same block because it makes the deploy() method basically instant. diff --git a/yarn-project/aztec.js/src/account/contract.ts b/yarn-project/aztec.js/src/account/contract.ts index 6c49a3b5cf0..6ae607d386b 100644 --- a/yarn-project/aztec.js/src/account/contract.ts +++ b/yarn-project/aztec.js/src/account/contract.ts @@ -1,4 +1,5 @@ import { type CompleteAddress } from '@aztec/circuit-types'; +import { type Fr } from '@aztec/circuits.js'; import { type ContractArtifact } from '@aztec/foundation/abi'; import { type NodeInfo } from '@aztec/types/interfaces'; @@ -25,10 +26,11 @@ export interface AccountContract { * The account interface is responsible for assembling tx requests given requested function calls, and * for creating signed auth witnesses given action identifiers (message hashes). * @param address - Address where this account contract is deployed. + * @param publicKeysHash - Hash of the public keys used to authorize actions. * @param nodeInfo - Info on the chain where it is deployed. * @returns An account interface instance for creating tx requests and authorizing actions. */ - getInterface(address: CompleteAddress, nodeInfo: NodeInfo): AccountInterface; + getInterface(address: CompleteAddress, publicKeysHash: Fr, nodeInfo: NodeInfo): AccountInterface; /** * Returns the auth witness provider for the given address. diff --git a/yarn-project/aztec.js/src/account/interface.ts b/yarn-project/aztec.js/src/account/interface.ts index 5a5ab2cf28e..555fce8cbbc 100644 --- a/yarn-project/aztec.js/src/account/interface.ts +++ b/yarn-project/aztec.js/src/account/interface.ts @@ -42,6 +42,9 @@ export interface AccountInterface extends AuthWitnessProvider, EntrypointInterfa /** Returns the complete address for this account. */ getCompleteAddress(): CompleteAddress; + /** Returns the public keys hash for this account. */ + getPublicKeysHash(): Fr; + /** Returns the address for this account. */ getAddress(): AztecAddress; diff --git a/yarn-project/aztec.js/src/account_manager/deploy_account_method.ts b/yarn-project/aztec.js/src/account_manager/deploy_account_method.ts index d9ea44b96d8..10a5404c3bd 100644 --- a/yarn-project/aztec.js/src/account_manager/deploy_account_method.ts +++ b/yarn-project/aztec.js/src/account_manager/deploy_account_method.ts @@ -1,5 +1,4 @@ -import { type PublicKey } from '@aztec/circuit-types'; -import { FunctionData } from '@aztec/circuits.js'; +import { type Fr, FunctionData } from '@aztec/circuits.js'; import { type ContractArtifact, type FunctionArtifact, @@ -23,7 +22,7 @@ export class DeployAccountMethod extends DeployMethod { constructor( authWitnessProvider: AuthWitnessProvider, - publicKey: PublicKey, + publicKeysHash: Fr, wallet: Wallet, artifact: ContractArtifact, args: any[] = [], @@ -31,7 +30,7 @@ export class DeployAccountMethod extends DeployMethod { feePaymentNameOrArtifact?: string | FunctionArtifact, ) { super( - publicKey, + publicKeysHash, wallet, artifact, (address, wallet) => Contract.at(address, artifact, wallet), diff --git a/yarn-project/aztec.js/src/account_manager/index.ts b/yarn-project/aztec.js/src/account_manager/index.ts index 251e7d40bb3..549855a4d97 100644 --- a/yarn-project/aztec.js/src/account_manager/index.ts +++ b/yarn-project/aztec.js/src/account_manager/index.ts @@ -1,5 +1,5 @@ -import { CompleteAddress, type GrumpkinPrivateKey, type PXE } from '@aztec/circuit-types'; -import { type PublicKey, getContractInstanceFromDeployParams } from '@aztec/circuits.js'; +import { CompleteAddress, type PXE } from '@aztec/circuit-types'; +import { deriveKeys, getContractInstanceFromDeployParams } from '@aztec/circuits.js'; import { Fr } from '@aztec/foundation/fields'; import { type ContractInstanceWithAddress } from '@aztec/types/contracts'; @@ -10,8 +10,7 @@ import { type DeployOptions } from '../contract/deploy_method.js'; import { DefaultWaitOpts, type WaitOpts } from '../contract/sent_tx.js'; import { DefaultMultiCallEntrypoint } from '../entrypoint/default_multi_call_entrypoint.js'; import { waitForAccountSynch } from '../utils/account.js'; -import { generatePublicKey } from '../utils/index.js'; -import { AccountWalletWithPrivateKey, SignerlessWallet } from '../wallet/index.js'; +import { AccountWalletWithSecretKey, SignerlessWallet } from '../wallet/index.js'; import { DeployAccountMethod } from './deploy_account_method.js'; import { DeployAccountSentTx } from './deploy_account_sent_tx.js'; @@ -31,23 +30,18 @@ export class AccountManager { // TODO(@spalladino): Does it make sense to have both completeAddress and instance? private completeAddress?: CompleteAddress; private instance?: ContractInstanceWithAddress; - private encryptionPublicKey?: PublicKey; + private publicKeysHash?: Fr; private deployMethod?: DeployAccountMethod; - constructor( - private pxe: PXE, - private encryptionPrivateKey: GrumpkinPrivateKey, - private accountContract: AccountContract, - salt?: Salt, - ) { + constructor(private pxe: PXE, private secretKey: Fr, private accountContract: AccountContract, salt?: Salt) { this.salt = salt !== undefined ? new Fr(salt) : Fr.random(); } - protected getEncryptionPublicKey() { - if (!this.encryptionPublicKey) { - this.encryptionPublicKey = generatePublicKey(this.encryptionPrivateKey); + protected getPublicKeysHash() { + if (!this.publicKeysHash) { + this.publicKeysHash = deriveKeys(this.secretKey).publicKeysHash; } - return this.encryptionPublicKey; + return this.publicKeysHash; } /** @@ -57,7 +51,7 @@ export class AccountManager { public async getAccount(): Promise { const nodeInfo = await this.pxe.getNodeInfo(); const completeAddress = this.getCompleteAddress(); - return this.accountContract.getInterface(completeAddress, nodeInfo); + return this.accountContract.getInterface(completeAddress, this.getPublicKeysHash(), nodeInfo); } /** @@ -67,9 +61,8 @@ export class AccountManager { */ public getCompleteAddress(): CompleteAddress { if (!this.completeAddress) { - const encryptionPublicKey = generatePublicKey(this.encryptionPrivateKey); const instance = this.getInstance(); - this.completeAddress = CompleteAddress.fromPublicKeyAndInstance(encryptionPublicKey, instance); + this.completeAddress = CompleteAddress.fromSecretKeyAndInstance(this.secretKey, instance); } return this.completeAddress; } @@ -81,11 +74,10 @@ export class AccountManager { */ public getInstance(): ContractInstanceWithAddress { if (!this.instance) { - const encryptionPublicKey = generatePublicKey(this.encryptionPrivateKey); this.instance = getContractInstanceFromDeployParams(this.accountContract.getContractArtifact(), { constructorArgs: this.accountContract.getDeploymentArgs(), salt: this.salt, - publicKey: encryptionPublicKey, + publicKeysHash: this.getPublicKeysHash(), }); } return this.instance; @@ -96,9 +88,9 @@ export class AccountManager { * instances to be interacted with from this account. * @returns A Wallet instance. */ - public async getWallet(): Promise { + public async getWallet(): Promise { const entrypoint = await this.getAccount(); - return new AccountWalletWithPrivateKey(this.pxe, entrypoint, this.encryptionPrivateKey, this.salt); + return new AccountWalletWithSecretKey(this.pxe, entrypoint, this.secretKey, this.salt); } /** @@ -108,7 +100,7 @@ export class AccountManager { * @param opts - Options to wait for the account to be synched. * @returns A Wallet instance. */ - public async register(opts: WaitOpts = DefaultWaitOpts): Promise { + public async register(opts: WaitOpts = DefaultWaitOpts): Promise { await this.#register(); await this.pxe.registerContract({ artifact: this.accountContract.getContractArtifact(), @@ -133,7 +125,7 @@ export class AccountManager { ); } await this.#register(); - const encryptionPublicKey = this.getEncryptionPublicKey(); + const encryptionPublicKey = this.getPublicKeysHash(); const { chainId, protocolVersion } = await this.pxe.getNodeInfo(); const deployWallet = new SignerlessWallet(this.pxe, new DefaultMultiCallEntrypoint(chainId, protocolVersion)); @@ -185,7 +177,7 @@ export class AccountManager { * @param opts - Options to wait for the tx to be mined. * @returns A Wallet instance. */ - public async waitSetup(opts: WaitOpts = DefaultWaitOpts): Promise { + public async waitSetup(opts: WaitOpts = DefaultWaitOpts): Promise { await (this.isDeployable() ? this.deploy().wait(opts) : this.register()); return this.getWallet(); } @@ -199,6 +191,6 @@ export class AccountManager { async #register(): Promise { const completeAddress = this.getCompleteAddress(); - await this.pxe.registerAccount(this.encryptionPrivateKey, completeAddress.partialAddress); + await this.pxe.registerAccount(this.secretKey, completeAddress.partialAddress); } } diff --git a/yarn-project/aztec.js/src/api/wallet.ts b/yarn-project/aztec.js/src/api/wallet.ts index f9026e6a8ff..9f406fa3af3 100644 --- a/yarn-project/aztec.js/src/api/wallet.ts +++ b/yarn-project/aztec.js/src/api/wallet.ts @@ -1 +1,7 @@ -export { AccountWallet, AccountWalletWithPrivateKey, SignerlessWallet, Wallet, getWallet } from '../wallet/index.js'; +export { + AccountWallet, + AccountWalletWithSecretKey as AccountWalletWithSecretKey, + SignerlessWallet, + Wallet, + getWallet, +} from '../wallet/index.js'; diff --git a/yarn-project/aztec.js/src/contract/contract.ts b/yarn-project/aztec.js/src/contract/contract.ts index 36b4c831a4b..333335a35d2 100644 --- a/yarn-project/aztec.js/src/contract/contract.ts +++ b/yarn-project/aztec.js/src/contract/contract.ts @@ -1,7 +1,6 @@ -import { type PublicKey } from '@aztec/circuit-types'; import { type ContractArtifact } from '@aztec/foundation/abi'; import { type AztecAddress } from '@aztec/foundation/aztec-address'; -import { Point } from '@aztec/foundation/fields'; +import { Fr } from '@aztec/foundation/fields'; import { type Wallet } from '../account/index.js'; import { ContractBase } from './contract_base.js'; @@ -40,25 +39,25 @@ export class Contract extends ContractBase { */ public static deploy(wallet: Wallet, artifact: ContractArtifact, args: any[], constructorName?: string) { const postDeployCtor = (address: AztecAddress, wallet: Wallet) => Contract.at(address, artifact, wallet); - return new DeployMethod(Point.ZERO, wallet, artifact, postDeployCtor, args, constructorName); + return new DeployMethod(Fr.ZERO, wallet, artifact, postDeployCtor, args, constructorName); } /** - * Creates a tx to deploy a new instance of a contract using the specified public key to derive the address. - * @param publicKey - Public key for deriving the address. + * Creates a tx to deploy a new instance of a contract using the specified public keys hash to derive the address. + * @param publicKeysHash - Hash of public keys to use for deriving the address. * @param wallet - The wallet for executing the deployment. * @param artifact - Build artifact of the contract. * @param args - Arguments for the constructor. * @param constructorName - The name of the constructor function to call. */ - public static deployWithPublicKey( - publicKey: PublicKey, + public static deployWithPublicKeysHash( + publicKeysHash: Fr, wallet: Wallet, artifact: ContractArtifact, args: any[], constructorName?: string, ) { const postDeployCtor = (address: AztecAddress, wallet: Wallet) => Contract.at(address, artifact, wallet); - return new DeployMethod(publicKey, wallet, artifact, postDeployCtor, args, constructorName); + return new DeployMethod(publicKeysHash, wallet, artifact, postDeployCtor, args, constructorName); } } diff --git a/yarn-project/aztec.js/src/contract/deploy_method.ts b/yarn-project/aztec.js/src/contract/deploy_method.ts index 54ef3025e2b..6c7d632afa9 100644 --- a/yarn-project/aztec.js/src/contract/deploy_method.ts +++ b/yarn-project/aztec.js/src/contract/deploy_method.ts @@ -1,4 +1,4 @@ -import { type FunctionCall, type PublicKey, type Tx, type TxExecutionRequest } from '@aztec/circuit-types'; +import { type FunctionCall, type Tx, type TxExecutionRequest } from '@aztec/circuit-types'; import { AztecAddress, computePartialAddress, @@ -59,7 +59,7 @@ export class DeployMethod extends Bas private log = createDebugLogger('aztec:js:deploy_method'); constructor( - private publicKey: PublicKey, + private publicKeysHash: Fr, protected wallet: Wallet, private artifact: ContractArtifact, private postDeployCtor: (address: AztecAddress, wallet: Wallet) => Promise, @@ -210,7 +210,7 @@ export class DeployMethod extends Bas constructorArgs: this.args, salt: options.contractAddressSalt, portalAddress: options.portalContract, - publicKey: this.publicKey, + publicKeysHash: this.publicKeysHash, constructorArtifact: this.constructorArtifact, deployer: options.universalDeploy ? AztecAddress.ZERO : this.wallet.getAddress(), }); diff --git a/yarn-project/aztec.js/src/deployment/contract_deployer.ts b/yarn-project/aztec.js/src/deployment/contract_deployer.ts index bd0f04ea74f..bc9519d0b0a 100644 --- a/yarn-project/aztec.js/src/deployment/contract_deployer.ts +++ b/yarn-project/aztec.js/src/deployment/contract_deployer.ts @@ -1,7 +1,6 @@ -import { type PublicKey } from '@aztec/circuit-types'; import { type AztecAddress } from '@aztec/circuits.js'; import { type ContractArtifact } from '@aztec/foundation/abi'; -import { Point } from '@aztec/foundation/fields'; +import { Fr } from '@aztec/foundation/fields'; import { type Wallet } from '../account/wallet.js'; import { DeployMethod } from '../contract/deploy_method.js'; @@ -15,7 +14,7 @@ export class ContractDeployer { constructor( private artifact: ContractArtifact, private wallet: Wallet, - private publicKey?: PublicKey, + private publicKeysHash?: Fr, private constructorName?: string, ) {} @@ -31,7 +30,7 @@ export class ContractDeployer { public deploy(...args: any[]) { const postDeployCtor = (address: AztecAddress, wallet: Wallet) => Contract.at(address, this.artifact, wallet); return new DeployMethod( - this.publicKey ?? Point.ZERO, + this.publicKeysHash ?? Fr.ZERO, this.wallet, this.artifact, postDeployCtor, diff --git a/yarn-project/aztec.js/src/index.ts b/yarn-project/aztec.js/src/index.ts index 0e15250516d..fc91aa829b5 100644 --- a/yarn-project/aztec.js/src/index.ts +++ b/yarn-project/aztec.js/src/index.ts @@ -58,7 +58,7 @@ export { AuthWitnessProvider } from './account/index.js'; export { AccountContract } from './account/index.js'; export { AccountManager } from './account_manager/index.js'; -export { AccountWalletWithPrivateKey, AccountWallet, Wallet, SignerlessWallet } from './wallet/index.js'; +export { AccountWalletWithSecretKey, AccountWallet, Wallet, SignerlessWallet } from './wallet/index.js'; // // TODO https://github.com/AztecProtocol/aztec-packages/issues/2632 --> FunctionSelector might not need to be exposed // // here once the issue is resolved. @@ -77,6 +77,13 @@ export { export { computeMessageSecretHash } from '@aztec/circuits.js/hash'; +export { + computeAppNullifierSecretKey, + deriveKeys, + deriveMasterIncomingViewingSecretKey, + deriveMasterNullifierSecretKey, +} from '@aztec/circuits.js/keys'; + export { Grumpkin, Schnorr } from '@aztec/circuits.js/barretenberg'; export { diff --git a/yarn-project/aztec.js/src/wallet/account_wallet.ts b/yarn-project/aztec.js/src/wallet/account_wallet.ts index 803d07010eb..a1f7cea1848 100644 --- a/yarn-project/aztec.js/src/wallet/account_wallet.ts +++ b/yarn-project/aztec.js/src/wallet/account_wallet.ts @@ -16,6 +16,10 @@ export class AccountWallet extends BaseWallet { super(pxe); } + getPublicKeysHash(): Fr { + return this.account.getPublicKeysHash(); + } + createTxExecutionRequest(exec: ExecutionRequestInit): Promise { return this.account.createTxExecutionRequest(exec); } diff --git a/yarn-project/aztec.js/src/wallet/account_wallet_with_private_key.ts b/yarn-project/aztec.js/src/wallet/account_wallet_with_private_key.ts index d21bddf3e85..792b44e60d9 100644 --- a/yarn-project/aztec.js/src/wallet/account_wallet_with_private_key.ts +++ b/yarn-project/aztec.js/src/wallet/account_wallet_with_private_key.ts @@ -1,5 +1,5 @@ import { type PXE } from '@aztec/circuit-types'; -import { type GrumpkinPrivateKey } from '@aztec/circuits.js'; +import { type Fr } from '@aztec/circuits.js'; import { type Salt } from '../account/index.js'; import { type AccountInterface } from '../account/interface.js'; @@ -10,11 +10,11 @@ import { AccountWallet } from './account_wallet.js'; * implementing the wallet interface but useful for testing purposes or exporting * an account to another pxe. */ -export class AccountWalletWithPrivateKey extends AccountWallet { +export class AccountWalletWithSecretKey extends AccountWallet { constructor( pxe: PXE, account: AccountInterface, - private encryptionPrivateKey: GrumpkinPrivateKey, + private secretKey: Fr, /** Deployment salt for this account contract. */ public readonly salt: Salt, ) { @@ -22,7 +22,7 @@ export class AccountWalletWithPrivateKey extends AccountWallet { } /** Returns the encryption private key associated with this account. */ - public getEncryptionPrivateKey() { - return this.encryptionPrivateKey; + public getSecretKey() { + return this.secretKey; } } diff --git a/yarn-project/aztec.js/src/wallet/base_wallet.ts b/yarn-project/aztec.js/src/wallet/base_wallet.ts index 70106a6da67..eeacdb4f23a 100644 --- a/yarn-project/aztec.js/src/wallet/base_wallet.ts +++ b/yarn-project/aztec.js/src/wallet/base_wallet.ts @@ -15,13 +15,7 @@ import { type TxHash, type TxReceipt, } from '@aztec/circuit-types'; -import { - type AztecAddress, - type CompleteAddress, - type Fr, - type GrumpkinPrivateKey, - type PartialAddress, -} from '@aztec/circuits.js'; +import { type AztecAddress, type CompleteAddress, type Fr, type PartialAddress } from '@aztec/circuits.js'; import { type ContractArtifact } from '@aztec/foundation/abi'; import { type ContractClassWithId, type ContractInstanceWithAddress } from '@aztec/types/contracts'; import { type NodeInfo } from '@aztec/types/interfaces'; @@ -38,6 +32,8 @@ export abstract class BaseWallet implements Wallet { abstract getCompleteAddress(): CompleteAddress; + abstract getPublicKeysHash(): Fr; + abstract getChainId(): Fr; abstract getVersion(): Fr; @@ -72,8 +68,8 @@ export abstract class BaseWallet implements Wallet { addCapsule(capsule: Fr[]): Promise { return this.pxe.addCapsule(capsule); } - registerAccount(privKey: GrumpkinPrivateKey, partialAddress: PartialAddress): Promise { - return this.pxe.registerAccount(privKey, partialAddress); + registerAccount(secretKey: Fr, partialAddress: PartialAddress): Promise { + return this.pxe.registerAccount(secretKey, partialAddress); } registerRecipient(account: CompleteAddress): Promise { return this.pxe.registerRecipient(account); @@ -84,6 +80,9 @@ export abstract class BaseWallet implements Wallet { getRegisteredAccount(address: AztecAddress): Promise { return this.pxe.getRegisteredAccount(address); } + getRegisteredAccountPublicKeysHash(address: AztecAddress): Promise { + return this.pxe.getRegisteredAccountPublicKeysHash(address); + } getRecipients(): Promise { return this.pxe.getRecipients(); } diff --git a/yarn-project/aztec.js/src/wallet/index.ts b/yarn-project/aztec.js/src/wallet/index.ts index 08e8cb27c41..ad92b67fdd0 100644 --- a/yarn-project/aztec.js/src/wallet/index.ts +++ b/yarn-project/aztec.js/src/wallet/index.ts @@ -25,7 +25,11 @@ export async function getWallet( if (!completeAddress) { throw new Error(`Account ${address} not found`); } + const publicKeysHash = await pxe.getRegisteredAccountPublicKeysHash(address); + if (!publicKeysHash) { + throw new Error(`Public keys hash for account ${address} not found`); + } const nodeInfo = await pxe.getNodeInfo(); - const entrypoint = accountContract.getInterface(completeAddress, nodeInfo); + const entrypoint = accountContract.getInterface(completeAddress, publicKeysHash, nodeInfo); return new AccountWallet(pxe, entrypoint); } diff --git a/yarn-project/aztec.js/src/wallet/signerless_wallet.ts b/yarn-project/aztec.js/src/wallet/signerless_wallet.ts index 062c4491956..2af55f279a8 100644 --- a/yarn-project/aztec.js/src/wallet/signerless_wallet.ts +++ b/yarn-project/aztec.js/src/wallet/signerless_wallet.ts @@ -31,6 +31,10 @@ export class SignerlessWallet extends BaseWallet { throw new Error('Method not implemented.'); } + getPublicKeysHash(): Fr { + throw new Error('Method not implemented.'); + } + getCompleteAddress(): CompleteAddress { throw new Error('Method not implemented.'); } diff --git a/yarn-project/aztec/src/cli/util.ts b/yarn-project/aztec/src/cli/util.ts index 21e79359da2..1a14868638b 100644 --- a/yarn-project/aztec/src/cli/util.ts +++ b/yarn-project/aztec/src/cli/util.ts @@ -1,11 +1,11 @@ import { type ArchiverConfig } from '@aztec/archiver'; import { type AztecNodeConfig } from '@aztec/aztec-node'; -import { type AccountManager } from '@aztec/aztec.js'; +import { type AccountManager, type Fr } from '@aztec/aztec.js'; import { type L1ContractAddresses, l1ContractsNames } from '@aztec/ethereum'; import { EthAddress } from '@aztec/foundation/eth-address'; import { type LogFn, createConsoleLogger } from '@aztec/foundation/log'; import { type P2PConfig } from '@aztec/p2p'; -import { type GrumpkinScalar, type PXEService, type PXEServiceConfig } from '@aztec/pxe'; +import { type PXEService, type PXEServiceConfig } from '@aztec/pxe'; /** * Checks if the object has l1Contracts property @@ -107,9 +107,9 @@ export async function createAccountLogs( */ account: AccountManager; /** - * The private key of the account + * The secret key of the account */ - privateKey: GrumpkinScalar; + secretKey: Fr; }[], pxe: PXEService, ) { @@ -120,7 +120,7 @@ export async function createAccountLogs( if (registeredAccounts.find(a => a.equals(completeAddress))) { accountLogStrings.push(` Address: ${completeAddress.address.toString()}\n`); accountLogStrings.push(` Partial Address: ${completeAddress.partialAddress.toString()}\n`); - accountLogStrings.push(` Private Key: ${account.privateKey.toString()}\n`); + accountLogStrings.push(` Secret Key: ${account.secretKey.toString()}\n`); accountLogStrings.push(` Public Key: ${completeAddress.publicKey.toString()}\n\n`); } } diff --git a/yarn-project/aztec/src/examples/token.ts b/yarn-project/aztec/src/examples/token.ts index c4ec9f29023..01702d9d5d1 100644 --- a/yarn-project/aztec/src/examples/token.ts +++ b/yarn-project/aztec/src/examples/token.ts @@ -1,20 +1,13 @@ import { getSingleKeyAccount } from '@aztec/accounts/single_key'; -import { - type AccountWallet, - Fr, - GrumpkinScalar, - Note, - computeMessageSecretHash, - createPXEClient, -} from '@aztec/aztec.js'; +import { type AccountWallet, Fr, Note, computeMessageSecretHash, createPXEClient } from '@aztec/aztec.js'; import { ExtendedNote } from '@aztec/circuit-types'; import { createDebugLogger } from '@aztec/foundation/log'; import { TokenContract } from '@aztec/noir-contracts.js/Token'; const logger = createDebugLogger('aztec:http-rpc-client'); -export const alicePrivateKey = GrumpkinScalar.random(); -export const bobPrivateKey = GrumpkinScalar.random(); +export const alicePrivateKey = Fr.random(); +export const bobPrivateKey = Fr.random(); const url = 'http://localhost:8080'; diff --git a/yarn-project/circuit-types/src/interfaces/pxe.ts b/yarn-project/circuit-types/src/interfaces/pxe.ts index ab72749fe78..0eba3e00512 100644 --- a/yarn-project/circuit-types/src/interfaces/pxe.ts +++ b/yarn-project/circuit-types/src/interfaces/pxe.ts @@ -1,10 +1,4 @@ -import { - type AztecAddress, - type CompleteAddress, - type Fr, - type GrumpkinPrivateKey, - type PartialAddress, -} from '@aztec/circuits.js'; +import { type AztecAddress, type CompleteAddress, type Fr, type PartialAddress } from '@aztec/circuits.js'; import { type ContractArtifact } from '@aztec/foundation/abi'; import { type ContractClassWithId, type ContractInstanceWithAddress } from '@aztec/types/contracts'; import { type NodeInfo } from '@aztec/types/interfaces'; @@ -61,11 +55,11 @@ export interface PXE { * the chain and store those that correspond to the registered account. Will do nothing if the * account is already registered. * - * @param privKey - Private key of the corresponding user master public key. + * @param secretKey - Secret key of the corresponding user master public key. * @param partialAddress - The partial address of the account contract corresponding to the account being registered. * @returns The complete address of the account. */ - registerAccount(privKey: GrumpkinPrivateKey, partialAddress: PartialAddress): Promise; + registerAccount(secretKey: Fr, partialAddress: PartialAddress): Promise; /** * Registers a recipient in PXE. This is required when sending encrypted notes to @@ -96,6 +90,15 @@ export interface PXE { */ getRegisteredAccount(address: AztecAddress): Promise; + /** + * Retrieves the public keys hash of the account corresponding to the provided aztec address. + * + * @param address - The address of account. + * @returns The public keys hash of the requested account if found. + * TODO(#5834): refactor complete address and merge with getRegisteredAccount? + */ + getRegisteredAccountPublicKeysHash(address: AztecAddress): Promise; + /** * Retrieves the recipients added to this PXE Service. * @returns An array of recipients registered on this PXE Service. diff --git a/yarn-project/circuit-types/src/keys/index.ts b/yarn-project/circuit-types/src/keys/index.ts index be16aca18e4..f137b0d567a 100644 --- a/yarn-project/circuit-types/src/keys/index.ts +++ b/yarn-project/circuit-types/src/keys/index.ts @@ -1,3 +1,2 @@ export * from './key_pair.js'; export * from './key_store.js'; -export * from './new_key_store.js'; diff --git a/yarn-project/circuit-types/src/keys/key_store.ts b/yarn-project/circuit-types/src/keys/key_store.ts index 3cf2c960d59..55c69f0facb 100644 --- a/yarn-project/circuit-types/src/keys/key_store.ts +++ b/yarn-project/circuit-types/src/keys/key_store.ts @@ -1,74 +1,119 @@ -import { type AztecAddress, type GrumpkinPrivateKey, type PublicKey } from '@aztec/circuits.js'; +import { + type AztecAddress, + type Fr, + type GrumpkinPrivateKey, + type PartialAddress, + type PublicKey, +} from '@aztec/circuits.js'; /** * Represents a secure storage for managing keys. - * Provides functionality to create and retrieve accounts, private and public keys, - * TODO(#5627): 💣💣💣 */ export interface KeyStore { /** - * Adds a new account with a randomly generated key pair. - * The account will have its own private and public key pair, which can be used for signing transactions. + * Creates a new account from a randomly generated secret key. * @returns A promise that resolves to the newly created account's AztecAddress. */ - createAccount(): Promise; + createAccount(): Promise; /** - * Adds an account to the key store from the provided private key. - * @param curve - The curve to use for generating the public key. - * @param privKey - The private key of the account. - * @returns - The account's public key. + * Adds an account to the key store from the provided secret key. + * @param sk - The secret key of the account. + * @param partialAddress - The partial address of the account. + * @returns The account's address. */ - addAccount(privKey: GrumpkinPrivateKey): Promise; + addAccount(sk: Fr, partialAddress: PartialAddress): Promise; /** - * Retrieves the public keys of all accounts stored. - * The returned addresses are instances of `PublicKey` and can be used for subsequent operations - * such as signing transactions or fetching public/private keys. - * @returns A Promise that resolves to an array of public keys instances. + * Retrieves addresses of accounts stored in the key store. + * @returns A Promise that resolves to an array of account addresses. */ - getAccounts(): Promise; + getAccounts(): Promise; /** - * Retrieves the private key of the account associated with the specified AztecAddress. - * Throws an error if the provided address is not found in the list of registered accounts. - * @param pubKey - The AztecAddress instance representing the account for which the private key is requested. - * @returns A Promise that resolves to a Buffer containing the private key. - * @deprecated We should not require a keystore to expose private keys in plain. + * Gets the master nullifier public key for a given account. + * @throws If the account does not exist in the key store. + * @param account - The account address for which to retrieve the master nullifier public key. + * @returns The master nullifier public key for the account. */ - getAccountPrivateKey(pubKey: PublicKey): Promise; + getMasterNullifierPublicKey(account: AztecAddress): Promise; /** - * Retrieves the nullifier secret key of the account associated with the specified AztecAddress. - * Throws an error if the provided public key is not found in the list of registered accounts. - * @param pubKey - The public key of the account for which the secret key is requested. - * @returns A Promise that resolves to the nullifier secret key. + * Gets the master incoming viewing public key for a given account. + * @throws If the account does not exist in the key store. + * @param account - The account address for which to retrieve the master incoming viewing public key. + * @returns The master incoming viewing public key for the account. */ - getNullifierSecretKey(pubKey: PublicKey): Promise; + getMasterIncomingViewingPublicKey(account: AztecAddress): Promise; /** - * Retrieves the nullifier secret key of the specified nullifier public key. - * Throws an error if the provided public key is not associated with any of the registered accounts. - * - * @param nullifierPubKey - The nullifier public key. - * @returns A Promise that resolves to the nullifier secret key. + * Retrieves the master outgoing viewing key. + * @throws If the account does not exist in the key store. + * @param account - The account to retrieve the master outgoing viewing key for. + * @returns A Promise that resolves to the master outgoing viewing key. */ - getNullifierSecretKeyFromPublicKey(nullifierPubKey: PublicKey): Promise; + getMasterOutgoingViewingPublicKey(account: AztecAddress): Promise; /** - * Retrieves the nullifier public key of the account associated with the specified AztecAddress. - * Throws an error if the provided public key is not found in the list of registered accounts. - * @param pubKey - The public key of the account for which the nullifier public key is requested. - * @returns A Promise that resolves to the nullifier public key. + * Retrieves the master tagging key. + * @throws If the account does not exist in the key store. + * @param account - The account to retrieve the master tagging key for. + * @returns A Promise that resolves to the master tagging key. */ - getNullifierPublicKey(pubKey: PublicKey): Promise; + getMasterTaggingPublicKey(account: AztecAddress): Promise; /** - * Retrieves the nullifier secret key for use in a specific contract. - * Throws an error if the provided public key is not found in the list of registered accounts. - * @param pubKey - The public key of the account for which the private key is requested. - * @param contractAddress - The address of the contract requesting the nullifier key. - * @returns A Promise that resolves to the nullifier secret key. + * Retrieves application nullifier secret key. + * @throws If the account does not exist in the key store. + * @param account - The account to retrieve the application nullifier secret key for. + * @param app - The application address to retrieve the nullifier secret key for. + * @returns A Promise that resolves to the application nullifier secret key. */ - getSiloedNullifierSecretKey(pubKey: PublicKey, contractAddress: AztecAddress): Promise; + getAppNullifierSecretKey(account: AztecAddress, app: AztecAddress): Promise; + + /** + * Retrieves application incoming viewing secret key. + * @throws If the account does not exist in the key store. + * @param account - The account to retrieve the application incoming viewing secret key for. + * @param app - The application address to retrieve the incoming viewing secret key for. + * @returns A Promise that resolves to the application incoming viewing secret key. + */ + getAppIncomingViewingSecretKey(account: AztecAddress, app: AztecAddress): Promise; + + /** + * Retrieves application outgoing viewing secret key. + * @throws If the account does not exist in the key store. + * @param account - The account to retrieve the application outgoing viewing secret key for. + * @param app - The application address to retrieve the outgoing viewing secret key for. + * @returns A Promise that resolves to the application outgoing viewing secret key. + */ + getAppOutgoingViewingSecretKey(account: AztecAddress, app: AztecAddress): Promise; + + /** + * Retrieves the master nullifier secret key (nsk_m) corresponding to the specified master nullifier public key + * (Npk_m). + * @throws If the provided public key is not associated with any of the registered accounts. + * @param masterNullifierPublicKey - The master nullifier public key to get secret key for. + * @returns A Promise that resolves to the master nullifier secret key. + * @dev Used when feeding the master nullifier secret key to the kernel circuit for nullifier keys verification. + */ + getMasterNullifierSecretKeyForPublicKey(masterNullifierPublicKey: PublicKey): Promise; + + /** + * Retrieves the master incoming viewing secret key (ivsk_m) corresponding to the specified master incoming viewing + * public key (Ivpk_m). + * @throws If the provided public key is not associated with any of the registered accounts. + * @param masterIncomingViewingPublicKey - The master nullifier public key to get secret key for. + * @returns A Promise that resolves to the master nullifier secret key. + * @dev Used when feeding the master nullifier secret key to the kernel circuit for nullifier keys verification. + */ + getMasterIncomingViewingSecretKeyForPublicKey(masterIncomingViewingPublicKey: PublicKey): Promise; + + /** + * Retrieves public keys hash of the account + * @throws If the provided account address is not associated with any of the registered accounts. + * @param account - The account address to get public keys hash for. + * @returns A Promise that resolves to the public keys hash. + */ + getPublicKeysHash(account: AztecAddress): Promise; } diff --git a/yarn-project/circuit-types/src/keys/new_key_store.ts b/yarn-project/circuit-types/src/keys/new_key_store.ts deleted file mode 100644 index 8f586feb9c3..00000000000 --- a/yarn-project/circuit-types/src/keys/new_key_store.ts +++ /dev/null @@ -1,101 +0,0 @@ -import { - type AztecAddress, - type Fr, - type GrumpkinPrivateKey, - type PartialAddress, - type PublicKey, -} from '@aztec/circuits.js'; - -/** - * Represents a secure storage for managing keys. - */ -export interface NewKeyStore { - /** - * Creates a new account from a randomly generated secret key. - * @returns A promise that resolves to the newly created account's AztecAddress. - */ - createAccount(): Promise; - - /** - * Adds an account to the key store from the provided secret key. - * @param sk - The secret key of the account. - * @param partialAddress - The partial address of the account. - * @returns The account's address. - */ - addAccount(sk: Fr, partialAddress: PartialAddress): Promise; - - /** - * Retrieves addresses of accounts stored in the key store. - * @returns A Promise that resolves to an array of account addresses. - */ - getAccounts(): Promise; - - /** - * Gets the master nullifier public key for a given account. - * @throws If the account does not exist in the key store. - * @param account - The account address for which to retrieve the master nullifier public key. - * @returns The master nullifier public key for the account. - */ - getMasterNullifierPublicKey(account: AztecAddress): Promise; - - /** - * Gets the master incoming viewing public key for a given account. - * @throws If the account does not exist in the key store. - * @param account - The account address for which to retrieve the master incoming viewing public key. - * @returns The master incoming viewing public key for the account. - */ - getMasterIncomingViewingPublicKey(account: AztecAddress): Promise; - - /** - * Retrieves the master outgoing viewing key. - * @throws If the account does not exist in the key store. - * @param account - The account to retrieve the master outgoing viewing key for. - * @returns A Promise that resolves to the master outgoing viewing key. - */ - getMasterOutgoingViewingPublicKey(account: AztecAddress): Promise; - - /** - * Retrieves the master tagging key. - * @throws If the account does not exist in the key store. - * @param account - The account to retrieve the master tagging key for. - * @returns A Promise that resolves to the master tagging key. - */ - getMasterTaggingPublicKey(account: AztecAddress): Promise; - - /** - * Retrieves application nullifier secret key. - * @throws If the account does not exist in the key store. - * @param account - The account to retrieve the application nullifier secret key for. - * @param app - The application address to retrieve the nullifier secret key for. - * @returns A Promise that resolves to the application nullifier secret key. - */ - getAppNullifierSecretKey(account: AztecAddress, app: AztecAddress): Promise; - - /** - * Retrieves application incoming viewing secret key. - * @throws If the account does not exist in the key store. - * @param account - The account to retrieve the application incoming viewing secret key for. - * @param app - The application address to retrieve the incoming viewing secret key for. - * @returns A Promise that resolves to the application incoming viewing secret key. - */ - getAppIncomingViewingSecretKey(account: AztecAddress, app: AztecAddress): Promise; - - /** - * Retrieves application outgoing viewing secret key. - * @throws If the account does not exist in the key store. - * @param account - The account to retrieve the application outgoing viewing secret key for. - * @param app - The application address to retrieve the outgoing viewing secret key for. - * @returns A Promise that resolves to the application outgoing viewing secret key. - */ - getAppOutgoingViewingSecretKey(account: AztecAddress, app: AztecAddress): Promise; - - /** - * Retrieves the master nullifier secret key (nsk_m) corresponding to the specified master nullifier public key - * (Npk_m). - * @throws If the provided public key is not associated with any of the registered accounts. - * @param masterNullifierPublicKey - The master nullifier public key to get secret key for. - * @returns A Promise that resolves to the master nullifier secret key. - * @dev Used when feeding the master nullifier secret key to the kernel circuit for nullifier keys verification. - */ - getMasterNullifierSecretKeyForPublicKey(masterNullifierPublicKey: PublicKey): Promise; -} diff --git a/yarn-project/circuits.js/package.json b/yarn-project/circuits.js/package.json index ecb0883e920..e3ef5ffd921 100644 --- a/yarn-project/circuits.js/package.json +++ b/yarn-project/circuits.js/package.json @@ -9,6 +9,7 @@ "exports": { ".": "./dest/index.js", "./hash": "./dest/hash/index.js", + "./keys": "./dest/keys/index.js", "./barretenberg": "./dest/barretenberg/index.js", "./testing": "./dest/tests/index.js", "./testing/fixtures": "./dest/tests/fixtures.js", diff --git a/yarn-project/circuits.js/src/constants.gen.ts b/yarn-project/circuits.js/src/constants.gen.ts index 6b544ae99a3..754d6b5b5dc 100644 --- a/yarn-project/circuits.js/src/constants.gen.ts +++ b/yarn-project/circuits.js/src/constants.gen.ts @@ -74,7 +74,7 @@ export const REGISTERER_UNCONSTRAINED_FUNCTION_BROADCASTED_MAGIC_VALUE = 0xe7af816635466f128568edb04c9fa024f6c87fb9010fdbffa68b3d99n; export const DEPLOYER_CONTRACT_INSTANCE_DEPLOYED_MAGIC_VALUE = 0x85864497636cf755ae7bde03f267ce01a520981c21c3682aaf82a631n; -export const DEPLOYER_CONTRACT_ADDRESS = 0x161b653b72ac5aa2982ce485b242b5c1e09afcbf27b89696f5a4e3151be37245n; +export const DEPLOYER_CONTRACT_ADDRESS = 0x1f47133752dfcd9604f2d89c631797a84ed207c1c51d08533226dafcc8bd8548n; export const AZTEC_ADDRESS_LENGTH = 1; export const DIMENSION_GAS_SETTINGS_LENGTH = 3; export const GAS_FEES_LENGTH = 3; @@ -93,8 +93,8 @@ export const APPEND_ONLY_TREE_SNAPSHOT_LENGTH = 2; export const L1_TO_L2_MESSAGE_LENGTH = 6; export const L2_TO_L1_MESSAGE_LENGTH = 2; export const MAX_BLOCK_NUMBER_LENGTH = 2; -export const NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH = 4; -export const NULLIFIER_KEY_VALIDATION_REQUEST_CONTEXT_LENGTH = 5; +export const NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH = 3; +export const NULLIFIER_KEY_VALIDATION_REQUEST_CONTEXT_LENGTH = 4; export const PARTIAL_STATE_REFERENCE_LENGTH = 6; export const READ_REQUEST_LENGTH = 2; export const SIDE_EFFECT_LENGTH = 2; @@ -169,7 +169,7 @@ export enum GeneratorIndex { CONTRACT_DEPLOYMENT_DATA = 12, CONSTRUCTOR = 13, CONSTRUCTOR_ARGS = 14, - CONTRACT_ADDRESS = 15, + CONTRACT_ADDRESS_V1 = 15, CONTRACT_LEAF = 16, CALL_CONTEXT = 17, CALL_STACK_ITEM = 18, @@ -198,5 +198,4 @@ export enum GeneratorIndex { OVSK_M = 49, TSK_M = 50, PUBLIC_KEYS_HASH = 51, - CONTRACT_ADDRESS_V1 = 52, } diff --git a/yarn-project/circuits.js/src/contract/__snapshots__/contract_address.test.ts.snap b/yarn-project/circuits.js/src/contract/__snapshots__/contract_address.test.ts.snap index cef9ff11261..ee1d1bf8cb9 100644 --- a/yarn-project/circuits.js/src/contract/__snapshots__/contract_address.test.ts.snap +++ b/yarn-project/circuits.js/src/contract/__snapshots__/contract_address.test.ts.snap @@ -1,10 +1,10 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`ContractAddress Address from partial matches Noir 1`] = `"0x0447f893197175723deb223696e2e96dbba1e707ee8507766373558877e74197"`; +exports[`ContractAddress Address from partial matches Noir 1`] = `"0x1b6ead051e7b42665064ca6cf1ec77da0a36d86e00d1ff6e44077966c0c3a9fa"`; -exports[`ContractAddress Public key hash matches Noir 1`] = `"0x1923a6246e305720b6aaf751fde0342613e93c82e455c3831e28375c16dd40d8"`; +exports[`ContractAddress Public key hash matches Noir 1`] = `"0x22d83a089d7650514c2de24cd30185a414d943eaa19817c67bffe2c3183006a3"`; -exports[`ContractAddress computeContractAddressFromInstance 1`] = `"0x027ea2b41ced2ec9a98305984e96dd28518536a4628883ccdc06e38aa8997220"`; +exports[`ContractAddress computeContractAddressFromInstance 1`] = `"0x1b61d59f21fcb9653c56b86f5e45f2d0b69dcbb7efebfbcda6f53eb7abaaa4eb"`; exports[`ContractAddress computeInitializationHash 1`] = `Fr<0x109865e4b959adba34b722e72a69baaf9ee78e31bb1042318f0d91006ed86780>`; diff --git a/yarn-project/circuits.js/src/contract/contract_address.test.ts b/yarn-project/circuits.js/src/contract/contract_address.test.ts index 47a98c80071..7551c55394a 100644 --- a/yarn-project/circuits.js/src/contract/contract_address.test.ts +++ b/yarn-project/circuits.js/src/contract/contract_address.test.ts @@ -1,14 +1,13 @@ import { ABIParameterVisibility, type FunctionAbi, FunctionType } from '@aztec/foundation/abi'; -import { Fr, Point } from '@aztec/foundation/fields'; +import { Fr } from '@aztec/foundation/fields'; import { setupCustomSnapshotSerializers, updateInlineTestData } from '@aztec/foundation/testing'; -import { AztecAddress, EthAddress } from '../index.js'; +import { AztecAddress, EthAddress, deriveKeys } from '../index.js'; import { computeContractAddressFromInstance, computeContractAddressFromPartial, computeInitializationHash, computePartialAddress, - computePublicKeysHash, computeSaltedInitializationHash, } from './contract_address.js'; @@ -54,15 +53,16 @@ describe('ContractAddress', () => { }); it('computeContractAddressFromInstance', () => { - const publicKey = new Point(new Fr(1n), new Fr(2n)); + const secretKey = new Fr(2n); const salt = new Fr(3n); const contractClassId = new Fr(4n); const initializationHash = new Fr(5n); const portalContractAddress = EthAddress.fromField(new Fr(6n)); const deployer = AztecAddress.fromField(new Fr(7)); + const publicKeysHash = deriveKeys(secretKey).publicKeysHash; const address = computeContractAddressFromInstance({ - publicKeysHash: computePublicKeysHash(publicKey), + publicKeysHash, salt, contractClassId, initializationHash, @@ -73,17 +73,18 @@ describe('ContractAddress', () => { expect(address).toMatchSnapshot(); - // Run with AZTEC_GENERATE_TEST_DATA=1 to update noir test data - updateInlineTestData( - 'noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr', - 'expected_computed_address_from_preimage', - address.toString(), - ); + // TODO(#5834): the following was removed from aztec_address.nr, should it be re-introduced? + // // Run with AZTEC_GENERATE_TEST_DATA=1 to update noir test data + // updateInlineTestData( + // 'noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr', + // 'expected_computed_address_from_preimage', + // address.toString(), + // ); }); it('Public key hash matches Noir', () => { - const publicKey = new Point(new Fr(1n), new Fr(2n)); - const hash = computePublicKeysHash(publicKey).toString(); + const secretKey = new Fr(2n); + const hash = deriveKeys(secretKey).publicKeysHash.toString(); expect(hash).toMatchSnapshot(); // Run with AZTEC_GENERATE_TEST_DATA=1 to update noir test data @@ -95,9 +96,9 @@ describe('ContractAddress', () => { }); it('Address from partial matches Noir', () => { - const publicKey = new Point(new Fr(1n), new Fr(2n)); - const partialAddress = new Fr(3n); - const address = computeContractAddressFromPartial({ publicKey, partialAddress }).toString(); + const publicKeysHash = new Fr(1n); + const partialAddress = new Fr(2n); + const address = computeContractAddressFromPartial({ publicKeysHash, partialAddress }).toString(); expect(address).toMatchSnapshot(); // Run with AZTEC_GENERATE_TEST_DATA=1 to update noir test data diff --git a/yarn-project/circuits.js/src/contract/contract_address.ts b/yarn-project/circuits.js/src/contract/contract_address.ts index 695ef983a54..11a58dbf24a 100644 --- a/yarn-project/circuits.js/src/contract/contract_address.ts +++ b/yarn-project/circuits.js/src/contract/contract_address.ts @@ -1,12 +1,12 @@ import { type FunctionAbi, FunctionSelector, encodeArguments } from '@aztec/foundation/abi'; import { AztecAddress } from '@aztec/foundation/aztec-address'; -import { pedersenHash } from '@aztec/foundation/crypto'; +import { pedersenHash, poseidon2Hash } from '@aztec/foundation/crypto'; import { Fr } from '@aztec/foundation/fields'; import { type ContractInstance } from '@aztec/types/contracts'; import { GeneratorIndex } from '../constants.gen.js'; import { computeVarArgsHash } from '../hash/hash.js'; -import { type PublicKey } from '../types/public_key.js'; +import { deriveKeys } from '../keys/index.js'; // TODO(@spalladino): Review all generator indices in this file @@ -15,7 +15,7 @@ import { type PublicKey } from '../types/public_key.js'; * ``` * salted_initialization_hash = pedersen([salt, initialization_hash, deployer, portal_contract_address as Field], GENERATOR__SALTED_INITIALIZATION_HASH) * partial_address = pedersen([contract_class_id, salted_initialization_hash], GENERATOR__CONTRACT_PARTIAL_ADDRESS_V1) - * address = pedersen([public_keys_hash, partial_address], GENERATOR__CONTRACT_ADDRESS_V1) + * address = poseidon2Hash([public_keys_hash, partial_address, GENERATOR__CONTRACT_ADDRESS_V1]) * ``` * @param instance - A contract instance for which to calculate the deployment address. */ @@ -25,8 +25,8 @@ export function computeContractAddressFromInstance( | ({ contractClassId: Fr; saltedInitializationHash: Fr } & Pick), ): AztecAddress { const partialAddress = computePartialAddress(instance); - const publicKeyHash = instance.publicKeysHash; - return computeContractAddressFromPartial({ partialAddress, publicKeyHash }); + const publicKeysHash = instance.publicKeysHash; + return computeContractAddressFromPartial({ partialAddress, publicKeysHash }); } /** @@ -60,30 +60,18 @@ export function computeSaltedInitializationHash( } /** - * Computes a contract address from its partial address and the pubkeys hash. + * Computes a contract address from its partial address and public keys hash. * @param args - The hash of the public keys or the plain public key to be hashed, along with the partial address. - * @returns The partially constructed contract address. + * @returns The contract address. */ export function computeContractAddressFromPartial( - args: ({ publicKeyHash: Fr } | { publicKey: PublicKey }) & { partialAddress: Fr }, + args: ({ publicKeysHash: Fr } | { secretKey: Fr }) & { partialAddress: Fr }, ): AztecAddress { - const publicKeyHash = 'publicKey' in args ? computePublicKeysHash(args.publicKey) : args.publicKeyHash; - const result = pedersenHash([publicKeyHash, args.partialAddress], GeneratorIndex.CONTRACT_ADDRESS); + const publicKeysHash = 'secretKey' in args ? deriveKeys(args.secretKey).publicKeysHash : args.publicKeysHash; + const result = poseidon2Hash([publicKeysHash, args.partialAddress, GeneratorIndex.CONTRACT_ADDRESS_V1]); return AztecAddress.fromField(result); } -/** - * Computes the hash of a set of public keys to be used for computing the deployment address of a contract. - * @param publicKey - Single public key (for now!). - * @returns The hash of the public keys. - */ -export function computePublicKeysHash(publicKey: PublicKey | undefined): Fr { - if (!publicKey) { - return Fr.ZERO; - } - return pedersenHash([publicKey.x, publicKey.y], GeneratorIndex.PARTIAL_ADDRESS); -} - /** * Computes the initialization hash for an instance given its constructor function and arguments. * @param initFn - Constructor function or empty if no initialization is expected. diff --git a/yarn-project/circuits.js/src/contract/contract_instance.ts b/yarn-project/circuits.js/src/contract/contract_instance.ts index 4b3e135b3e7..3a300c06dcd 100644 --- a/yarn-project/circuits.js/src/contract/contract_instance.ts +++ b/yarn-project/circuits.js/src/contract/contract_instance.ts @@ -1,17 +1,12 @@ import { type ContractArtifact, type FunctionArtifact, getDefaultInitializer } from '@aztec/foundation/abi'; import { AztecAddress } from '@aztec/foundation/aztec-address'; import { EthAddress } from '@aztec/foundation/eth-address'; -import { Fr, Point } from '@aztec/foundation/fields'; +import { Fr } from '@aztec/foundation/fields'; import { type ContractInstance, type ContractInstanceWithAddress } from '@aztec/types/contracts'; import { getContractClassFromArtifact } from '../contract/contract_class.js'; import { computeContractClassId } from '../contract/contract_class_id.js'; -import { type PublicKey } from '../types/public_key.js'; -import { - computeContractAddressFromInstance, - computeInitializationHash, - computePublicKeysHash, -} from './contract_address.js'; +import { computeContractAddressFromInstance, computeInitializationHash } from './contract_address.js'; /** * Generates a Contract Instance from the deployment params. @@ -25,14 +20,13 @@ export function getContractInstanceFromDeployParams( constructorArtifact?: FunctionArtifact | string; constructorArgs?: any[]; salt?: Fr; - publicKey?: PublicKey; + publicKeysHash?: Fr; portalAddress?: EthAddress; deployer?: AztecAddress; }, ): ContractInstanceWithAddress { const args = opts.constructorArgs ?? []; const salt = opts.salt ?? Fr.random(); - const publicKey = opts.publicKey ?? Point.ZERO; const portalContractAddress = opts.portalAddress ?? EthAddress.ZERO; const constructorArtifact = getConstructorArtifact(artifact, opts.constructorArtifact); const deployer = opts.deployer ?? AztecAddress.ZERO; @@ -40,7 +34,7 @@ export function getContractInstanceFromDeployParams( const contractClass = getContractClassFromArtifact(artifact); const contractClassId = computeContractClassId(contractClass); const initializationHash = computeInitializationHash(constructorArtifact, args); - const publicKeysHash = computePublicKeysHash(publicKey); + const publicKeysHash = opts.publicKeysHash ?? Fr.ZERO; const instance: ContractInstance = { contractClassId, diff --git a/yarn-project/circuits.js/src/keys/index.ts b/yarn-project/circuits.js/src/keys/index.ts index 9d48a2a2783..21ec5c6b460 100644 --- a/yarn-project/circuits.js/src/keys/index.ts +++ b/yarn-project/circuits.js/src/keys/index.ts @@ -1,41 +1,66 @@ import { type AztecAddress } from '@aztec/foundation/aztec-address'; -import { pedersenHash } from '@aztec/foundation/crypto'; -import { Fr, GrumpkinScalar } from '@aztec/foundation/fields'; +import { poseidon2Hash, sha512ToGrumpkinScalar } from '@aztec/foundation/crypto'; +import { type Fr, type GrumpkinScalar } from '@aztec/foundation/fields'; import { Grumpkin } from '../barretenberg/crypto/grumpkin/index.js'; +import { GeneratorIndex } from '../constants.gen.js'; import { type GrumpkinPrivateKey } from '../types/grumpkin_private_key.js'; -/** - * Derives the public key of a secret key. - */ -export function derivePublicKey(secretKey: GrumpkinPrivateKey) { - const grumpkin = new Grumpkin(); - return grumpkin.mul(grumpkin.generator(), secretKey); +export function computeAppNullifierSecretKey(masterNullifierSecretKey: GrumpkinPrivateKey, app: AztecAddress): Fr { + return poseidon2Hash([masterNullifierSecretKey.high, masterNullifierSecretKey.low, app, GeneratorIndex.NSK_M]); } -/** - * Derives a new secret key from a secret key and an index. - */ -function deriveSecretKey(secretKey: GrumpkinPrivateKey, index: Fr): GrumpkinPrivateKey { - // TODO: Temporary hack. Should replace it with a secure way to derive the secret key. - // Match the way keys are derived in noir-protocol-circuits/crates/types/src/keys.nr - const hash = pedersenHash([secretKey.high, secretKey.low, index]); - return new GrumpkinScalar(hash.toBuffer()); +export function deriveMasterNullifierSecretKey(secretKey: Fr): GrumpkinScalar { + return sha512ToGrumpkinScalar([secretKey, GeneratorIndex.NSK_M]); } -/** - * Computes the nullifier secret key from seed secret key. - */ -export function computeNullifierSecretKey(seedSecretKey: GrumpkinPrivateKey): GrumpkinPrivateKey { - return deriveSecretKey(seedSecretKey, new Fr(1)); +export function deriveMasterIncomingViewingSecretKey(secretKey: Fr): GrumpkinScalar { + return sha512ToGrumpkinScalar([secretKey, GeneratorIndex.IVSK_M]); +} + +export function deriveSigningKey(secretKey: Fr): GrumpkinScalar { + // TODO(#5837): come up with a standard signing key derivation scheme instead of using ivsk_m as signing keys here + return sha512ToGrumpkinScalar([secretKey, GeneratorIndex.IVSK_M]); } /** - * Computes the nullifier secret key for a contract. + * Computes secret and public keys and public keys hash from a secret key. + * @param secretKey - The secret key to derive keys from. + * @returns The derived keys. */ -export function computeSiloedNullifierSecretKey( - nullifierSecretKey: GrumpkinPrivateKey, - contractAddress: AztecAddress, -): GrumpkinPrivateKey { - return deriveSecretKey(nullifierSecretKey, contractAddress); +export function deriveKeys(secretKey: Fr) { + const curve = new Grumpkin(); + // First we derive master secret keys - we use sha512 here because this derivation will never take place + // in a circuit + const masterNullifierSecretKey = deriveMasterNullifierSecretKey(secretKey); + const masterIncomingViewingSecretKey = deriveMasterIncomingViewingSecretKey(secretKey); + const masterOutgoingViewingSecretKey = sha512ToGrumpkinScalar([secretKey, GeneratorIndex.OVSK_M]); + const masterTaggingSecretKey = sha512ToGrumpkinScalar([secretKey, GeneratorIndex.TSK_M]); + + // Then we derive master public keys + const masterNullifierPublicKey = curve.mul(curve.generator(), masterNullifierSecretKey); + const masterIncomingViewingPublicKey = curve.mul(curve.generator(), masterIncomingViewingSecretKey); + const masterOutgoingViewingPublicKey = curve.mul(curve.generator(), masterOutgoingViewingSecretKey); + const masterTaggingPublicKey = curve.mul(curve.generator(), masterTaggingSecretKey); + + // We hash the public keys to get the public keys hash + const publicKeysHash = poseidon2Hash([ + masterNullifierPublicKey, + masterIncomingViewingPublicKey, + masterOutgoingViewingPublicKey, + masterTaggingPublicKey, + GeneratorIndex.PUBLIC_KEYS_HASH, + ]); + + return { + masterNullifierSecretKey, + masterIncomingViewingSecretKey, + masterOutgoingViewingSecretKey, + masterTaggingSecretKey, + masterNullifierPublicKey, + masterIncomingViewingPublicKey, + masterOutgoingViewingPublicKey, + masterTaggingPublicKey, + publicKeysHash, + }; } diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/function_data.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/function_data.test.ts.snap index f0abf4311e2..db45ccb85d2 100644 --- a/yarn-project/circuits.js/src/structs/__snapshots__/function_data.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/__snapshots__/function_data.test.ts.snap @@ -1,3 +1,3 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`FunctionData computes empty inputs hash 1`] = `Fr<0x27b1d0839a5b23baf12a8d195b18ac288fcf401afb2f70b8a4b529ede5fa9fed>`; +exports[`FunctionData computes empty function data hash 1`] = `Fr<0x27b1d0839a5b23baf12a8d195b18ac288fcf401afb2f70b8a4b529ede5fa9fed>`; diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/private_call_stack_item.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/private_call_stack_item.test.ts.snap index 5ffb5c6d63d..a66f2803864 100644 --- a/yarn-project/circuits.js/src/structs/__snapshots__/private_call_stack_item.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/__snapshots__/private_call_stack_item.test.ts.snap @@ -1,5 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`PrivateCallStackItem computes empty item hash 1`] = `Fr<0x2cbdfd59ceb55fcc4dbe43b9d6f052f5ca448ef5990b005b9927e578b1b69b6c>`; +exports[`PrivateCallStackItem computes empty item hash 1`] = `Fr<0x2826eee20026ba6fb21916387c4dfa7843cbce1fdcff508132812be5e544f286>`; -exports[`PrivateCallStackItem computes hash 1`] = `Fr<0x13b91b02b88b9856b5ccb70b03484cd04e3621ade4db047514ce1ccb66ffea11>`; +exports[`PrivateCallStackItem computes hash 1`] = `Fr<0x28222ff70df9ed6dbdc2d36cfb59599a9281dbe05d8ba6b50f168ad844db6fd9>`; diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/private_circuit_public_inputs.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/private_circuit_public_inputs.test.ts.snap index 13f20b93e6c..b3a2831c1dd 100644 --- a/yarn-project/circuits.js/src/structs/__snapshots__/private_circuit_public_inputs.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/__snapshots__/private_circuit_public_inputs.test.ts.snap @@ -1,5 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`PrivateCircuitPublicInputs computes empty inputs hash 1`] = `Fr<0x2c1ec6595f8d43f5fc983441bc75a84d2384008f5bd7a1d499da057130abe6cd>`; +exports[`PrivateCircuitPublicInputs computes empty inputs hash 1`] = `Fr<0x265dcde577695a65f00acc24d861e65e9486526ec2b9f9bab9493476f73e4bc9>`; -exports[`PrivateCircuitPublicInputs hash matches snapshot 1`] = `Fr<0x27af129fd883d6a50669a5cdd0c0ce91d67b6ddeccfe4df6cd3e5207f77e1cf1>`; +exports[`PrivateCircuitPublicInputs hash matches snapshot 1`] = `Fr<0x1c33182dc9780bb0b5b05314ba465dddf21ef16465e977f8093895541efe11f2>`; diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/public_circuit_public_inputs.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/public_circuit_public_inputs.test.ts.snap index d519cebd489..b3fd8d646cd 100644 --- a/yarn-project/circuits.js/src/structs/__snapshots__/public_circuit_public_inputs.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/__snapshots__/public_circuit_public_inputs.test.ts.snap @@ -1,5 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`PublicCircuitPublicInputs computes empty item hash 1`] = `Fr<0x048912d56248af479f8d7ecedbba7092d27741b10075a989e040f8e3242a7a3f>`; +exports[`PublicCircuitPublicInputs computes empty inputs hash 1`] = `Fr<0x048912d56248af479f8d7ecedbba7092d27741b10075a989e040f8e3242a7a3f>`; exports[`PublicCircuitPublicInputs hash matches snapshot 1`] = `Fr<0x15e41ce024b6e97478b456f670cfdd712aefe2504fd5145116e9ab7a26672d02>`; diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/tx_context.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/tx_context.test.ts.snap index 981e17e3f15..a27ef5d7eb7 100644 --- a/yarn-project/circuits.js/src/structs/__snapshots__/tx_context.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/__snapshots__/tx_context.test.ts.snap @@ -1,3 +1,3 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`TxContext computes empty hash 1`] = `Fr<0x200569267c0f73ac89aaa414239398db9445dd4ad3a8cf37015cd55b8d4c5e8d>`; +exports[`TxContext computes empty context hash 1`] = `Fr<0x200569267c0f73ac89aaa414239398db9445dd4ad3a8cf37015cd55b8d4c5e8d>`; diff --git a/yarn-project/circuits.js/src/structs/complete_address.test.ts b/yarn-project/circuits.js/src/structs/complete_address.test.ts index afe57420f59..e8ce620e5e4 100644 --- a/yarn-project/circuits.js/src/structs/complete_address.test.ts +++ b/yarn-project/circuits.js/src/structs/complete_address.test.ts @@ -4,7 +4,8 @@ import { Fr, Point } from '@aztec/foundation/fields'; import { CompleteAddress } from './complete_address.js'; describe('CompleteAddress', () => { - it('refuses to add an account with incorrect address for given partial address and pubkey', () => { + // TODO(#5834): re-enable or remove this test + it.skip('refuses to add an account with incorrect address for given partial address and pubkey', () => { expect(() => CompleteAddress.create(AztecAddress.random(), Point.random(), Fr.random())).toThrow( /cannot be derived/, ); diff --git a/yarn-project/circuits.js/src/structs/complete_address.ts b/yarn-project/circuits.js/src/structs/complete_address.ts index 40794fbe5d4..f4465685ca0 100644 --- a/yarn-project/circuits.js/src/structs/complete_address.ts +++ b/yarn-project/circuits.js/src/structs/complete_address.ts @@ -1,10 +1,9 @@ import { AztecAddress } from '@aztec/foundation/aztec-address'; -import { Fr, GrumpkinScalar, Point } from '@aztec/foundation/fields'; +import { Fr, Point } from '@aztec/foundation/fields'; import { BufferReader } from '@aztec/foundation/serialize'; -import { Grumpkin } from '../barretenberg/index.js'; import { computeContractAddressFromPartial, computePartialAddress } from '../contract/contract_address.js'; -import { type GrumpkinPrivateKey } from '../types/grumpkin_private_key.js'; +import { deriveKeys } from '../keys/index.js'; import { type PartialAddress } from '../types/partial_address.js'; import { type PublicKey } from '../types/public_key.js'; @@ -34,49 +33,53 @@ export class CompleteAddress { static create(address: AztecAddress, publicKey: PublicKey, partialAddress: PartialAddress) { const completeAddress = new CompleteAddress(address, publicKey, partialAddress); - completeAddress.validate(); + // TODO(#5834): re-enable validation + // completeAddress.validate(); return completeAddress; } static random() { + // TODO(#5834): the following should be cleaned up + const secretKey = Fr.random(); const partialAddress = Fr.random(); - const publicKey = Point.random(); - const address = computeContractAddressFromPartial({ publicKey, partialAddress }); + const address = computeContractAddressFromPartial({ secretKey, partialAddress }); + const publicKey = deriveKeys(secretKey).masterIncomingViewingPublicKey; return new CompleteAddress(address, publicKey, partialAddress); } - static fromRandomPrivateKey() { - const privateKey = GrumpkinScalar.random(); + static fromRandomSecretKey() { + const secretKey = Fr.random(); const partialAddress = Fr.random(); - return { privateKey, completeAddress: CompleteAddress.fromPrivateKeyAndPartialAddress(privateKey, partialAddress) }; + return { secretKey, completeAddress: CompleteAddress.fromSecretKeyAndPartialAddress(secretKey, partialAddress) }; } - static fromPrivateKeyAndPartialAddress(privateKey: GrumpkinPrivateKey, partialAddress: Fr): CompleteAddress { - const grumpkin = new Grumpkin(); - const publicKey = grumpkin.mul(Grumpkin.generator, privateKey); - const address = computeContractAddressFromPartial({ publicKey, partialAddress }); + static fromSecretKeyAndPartialAddress(secretKey: Fr, partialAddress: Fr): CompleteAddress { + const address = computeContractAddressFromPartial({ secretKey, partialAddress }); + const publicKey = deriveKeys(secretKey).masterIncomingViewingPublicKey; return new CompleteAddress(address, publicKey, partialAddress); } - static fromPublicKeyAndInstance( - publicKey: PublicKey, + static fromSecretKeyAndInstance( + secretKey: Fr, instance: Parameters[0], ): CompleteAddress { const partialAddress = computePartialAddress(instance); - const address = computeContractAddressFromPartial({ publicKey, partialAddress }); + const address = computeContractAddressFromPartial({ secretKey, partialAddress }); + const publicKey = deriveKeys(secretKey).masterIncomingViewingPublicKey; return new CompleteAddress(address, publicKey, partialAddress); } - /** Throws if the address is not correctly derived from the public key and partial address.*/ - public validate() { - const expectedAddress = computeContractAddressFromPartial(this); - const address = this.address; - if (!expectedAddress.equals(address)) { - throw new Error( - `Address cannot be derived from pubkey and partial address (received ${address.toString()}, derived ${expectedAddress.toString()})`, - ); - } - } + // TODO(#5834): re-enable validation + // /** Throws if the address is not correctly derived from the public key and partial address.*/ + // public validate() { + // const expectedAddress = computeContractAddressFromPartial(this); + // const address = this.address; + // if (!expectedAddress.equals(address)) { + // throw new Error( + // `Address cannot be derived from pubkey and partial address (received ${address.toString()}, derived ${expectedAddress.toString()})`, + // ); + // } + // } /** * Gets a readable string representation of a the complete address. diff --git a/yarn-project/circuits.js/src/structs/function_data.test.ts b/yarn-project/circuits.js/src/structs/function_data.test.ts index 12ab5a5cd1b..c39c0a030d3 100644 --- a/yarn-project/circuits.js/src/structs/function_data.test.ts +++ b/yarn-project/circuits.js/src/structs/function_data.test.ts @@ -24,7 +24,7 @@ describe('FunctionData', () => { expect(fields.length).toBe(FUNCTION_DATA_LENGTH); }); - it('computes empty inputs hash', () => { + it('computes empty function data hash', () => { const data = FunctionData.empty(); const hash = data.hash(); expect(hash).toMatchSnapshot(); diff --git a/yarn-project/circuits.js/src/structs/nullifier_key_validation_request.ts b/yarn-project/circuits.js/src/structs/nullifier_key_validation_request.ts index 93844400528..c145e0d2e82 100644 --- a/yarn-project/circuits.js/src/structs/nullifier_key_validation_request.ts +++ b/yarn-project/circuits.js/src/structs/nullifier_key_validation_request.ts @@ -1,12 +1,11 @@ import { AztecAddress } from '@aztec/foundation/aztec-address'; -import { type Fr, GrumpkinScalar, Point } from '@aztec/foundation/fields'; +import { Fr, Point } from '@aztec/foundation/fields'; import { BufferReader, FieldReader, serializeToBuffer } from '@aztec/foundation/serialize'; import { NULLIFIER_KEY_VALIDATION_REQUEST_CONTEXT_LENGTH, NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH, } from '../constants.gen.js'; -import { type GrumpkinPrivateKey } from '../types/grumpkin_private_key.js'; /** * Request for validating a nullifier key pair used in the app. @@ -14,26 +13,26 @@ import { type GrumpkinPrivateKey } from '../types/grumpkin_private_key.js'; export class NullifierKeyValidationRequest { constructor( /** - * Public key of the nullifier key. + * Public key of the nullifier key (Npk_m). */ - public readonly publicKey: Point, + public readonly masterNullifierPublicKey: Point, /** - * Secret key of the nullifier key. + * App-siloed nullifier secret key (nsk_app*). */ - public readonly secretKey: GrumpkinPrivateKey, + public readonly appNullifierSecretKey: Fr, ) {} toBuffer() { - return serializeToBuffer(this.publicKey, this.secretKey); + return serializeToBuffer(this.masterNullifierPublicKey, this.appNullifierSecretKey); } static fromBuffer(buffer: Buffer | BufferReader) { const reader = BufferReader.asReader(buffer); - return new NullifierKeyValidationRequest(Point.fromBuffer(reader), GrumpkinScalar.fromBuffer(reader)); + return new NullifierKeyValidationRequest(Point.fromBuffer(reader), Fr.fromBuffer(reader)); } toFields(): Fr[] { - const fields = [this.publicKey.toFields(), this.secretKey.high, this.secretKey.low].flat(); + const fields = [this.masterNullifierPublicKey.toFields(), this.appNullifierSecretKey].flat(); if (fields.length !== NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH) { throw new Error( `Invalid number of fields for NullifierKeyValidationRequest. Expected ${NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH}, got ${fields.length}`, @@ -44,15 +43,15 @@ export class NullifierKeyValidationRequest { static fromFields(fields: Fr[] | FieldReader): NullifierKeyValidationRequest { const reader = FieldReader.asReader(fields); - return new NullifierKeyValidationRequest(Point.fromFields(reader), reader.readFq()); + return new NullifierKeyValidationRequest(Point.fromFields(reader), reader.readField()); } isEmpty() { - return this.publicKey.isZero() && this.secretKey.isZero(); + return this.masterNullifierPublicKey.isZero() && this.appNullifierSecretKey.isZero(); } static empty() { - return new NullifierKeyValidationRequest(Point.ZERO, GrumpkinScalar.ZERO); + return new NullifierKeyValidationRequest(Point.ZERO, Fr.ZERO); } } @@ -62,13 +61,13 @@ export class NullifierKeyValidationRequest { export class NullifierKeyValidationRequestContext { constructor( /** - * Public key of the nullifier key. + * Public key of the nullifier key (Npk_m). */ - public readonly publicKey: Point, + public readonly masterNullifierPublicKey: Point, /** - * Secret key of the nullifier key. + * App-siloed nullifier secret key (nsk_app*). */ - public readonly secretKey: GrumpkinPrivateKey, + public readonly appNullifierSecretKey: Fr, /** * The storage contract address the nullifier key is for. */ @@ -76,20 +75,20 @@ export class NullifierKeyValidationRequestContext { ) {} toBuffer() { - return serializeToBuffer(this.publicKey, this.secretKey, this.contractAddress); + return serializeToBuffer(this.masterNullifierPublicKey, this.appNullifierSecretKey, this.contractAddress); } static fromBuffer(buffer: Buffer | BufferReader) { const reader = BufferReader.asReader(buffer); return new NullifierKeyValidationRequestContext( Point.fromBuffer(reader), - GrumpkinScalar.fromBuffer(reader), + Fr.fromBuffer(reader), AztecAddress.fromBuffer(reader), ); } toFields(): Fr[] { - const fields = [this.publicKey.toFields(), this.secretKey.high, this.secretKey.low, this.contractAddress].flat(); + const fields = [this.masterNullifierPublicKey.toFields(), this.appNullifierSecretKey, this.contractAddress].flat(); if (fields.length !== NULLIFIER_KEY_VALIDATION_REQUEST_CONTEXT_LENGTH) { throw new Error( `Invalid number of fields for NullifierKeyValidationRequestContext. Expected ${NULLIFIER_KEY_VALIDATION_REQUEST_CONTEXT_LENGTH}, got ${fields.length}`, @@ -102,16 +101,18 @@ export class NullifierKeyValidationRequestContext { const reader = FieldReader.asReader(fields); return new NullifierKeyValidationRequestContext( Point.fromFields(reader), - reader.readFq(), + reader.readField(), AztecAddress.fromFields(reader), ); } isEmpty() { - return this.publicKey.isZero() && this.secretKey.isZero() && this.contractAddress.isZero(); + return ( + this.masterNullifierPublicKey.isZero() && this.appNullifierSecretKey.isZero() && this.contractAddress.isZero() + ); } static empty() { - return new NullifierKeyValidationRequestContext(Point.ZERO, GrumpkinScalar.ZERO, AztecAddress.ZERO); + return new NullifierKeyValidationRequestContext(Point.ZERO, Fr.ZERO, AztecAddress.ZERO); } } diff --git a/yarn-project/circuits.js/src/structs/public_circuit_public_inputs.test.ts b/yarn-project/circuits.js/src/structs/public_circuit_public_inputs.test.ts index 71fbc0fc141..bfca12ab0f6 100644 --- a/yarn-project/circuits.js/src/structs/public_circuit_public_inputs.test.ts +++ b/yarn-project/circuits.js/src/structs/public_circuit_public_inputs.test.ts @@ -32,9 +32,9 @@ describe('PublicCircuitPublicInputs', () => { expect(hash).toMatchSnapshot(); }); - it('computes empty item hash', () => { - const item = PublicCircuitPublicInputs.empty(); - const hash = item.hash(); + it('computes empty inputs hash', () => { + const inputs = PublicCircuitPublicInputs.empty(); + const hash = inputs.hash(); expect(hash).toMatchSnapshot(); // Run with AZTEC_GENERATE_TEST_DATA=1 to update noir test data diff --git a/yarn-project/circuits.js/src/structs/tx_context.test.ts b/yarn-project/circuits.js/src/structs/tx_context.test.ts index 940770dac82..d6c09627e59 100644 --- a/yarn-project/circuits.js/src/structs/tx_context.test.ts +++ b/yarn-project/circuits.js/src/structs/tx_context.test.ts @@ -25,7 +25,7 @@ describe('TxContext', () => { expect(fields.length).toBe(TX_CONTEXT_DATA_LENGTH); }); - it('computes empty hash', () => { + it('computes empty context hash', () => { const tc = TxContext.empty(); expect(tc.isEmpty()).toBe(true); diff --git a/yarn-project/circuits.js/src/tests/factories.ts b/yarn-project/circuits.js/src/tests/factories.ts index d6d99d49a5a..389329b678f 100644 --- a/yarn-project/circuits.js/src/tests/factories.ts +++ b/yarn-project/circuits.js/src/tests/factories.ts @@ -213,7 +213,7 @@ function makeReadRequestContext(n: number): ReadRequestContext { * @returns A NullifierKeyValidationRequest. */ function makeNullifierKeyValidationRequest(seed: number): NullifierKeyValidationRequest { - return new NullifierKeyValidationRequest(makePoint(seed), makeGrumpkinPrivateKey(seed + 2)); + return new NullifierKeyValidationRequest(makePoint(seed), fr(seed + 2)); } /** @@ -222,11 +222,7 @@ function makeNullifierKeyValidationRequest(seed: number): NullifierKeyValidation * @returns A NullifierKeyValidationRequestContext. */ function makeNullifierKeyValidationRequestContext(seed: number): NullifierKeyValidationRequestContext { - return new NullifierKeyValidationRequestContext( - makePoint(seed), - makeGrumpkinPrivateKey(seed + 2), - makeAztecAddress(seed + 4), - ); + return new NullifierKeyValidationRequestContext(makePoint(seed), fr(seed + 2), makeAztecAddress(seed + 4)); } /** diff --git a/yarn-project/cli/src/cmds/add_contract.ts b/yarn-project/cli/src/cmds/add_contract.ts index 36b2a9fcbf4..2c29aedf3f8 100644 --- a/yarn-project/cli/src/cmds/add_contract.ts +++ b/yarn-project/cli/src/cmds/add_contract.ts @@ -2,11 +2,10 @@ import { AztecAddress, type ContractInstanceWithAddress, EthAddress, - type Fr, - type Point, + Fr, getContractClassFromArtifact, } from '@aztec/aztec.js'; -import { computeContractAddressFromInstance, computePublicKeysHash } from '@aztec/circuits.js/contract'; +import { computeContractAddressFromInstance } from '@aztec/circuits.js/contract'; import { type DebugLogger, type LogFn } from '@aztec/foundation/log'; import { createCompatibleClient } from '../client.js'; @@ -18,7 +17,7 @@ export async function addContract( address: AztecAddress, initializationHash: Fr, salt: Fr, - publicKey: Point | undefined, + publicKeysHash: Fr | undefined, portalContract: EthAddress | undefined, deployer: AztecAddress | undefined, debugLogger: DebugLogger, @@ -31,7 +30,7 @@ export async function addContract( initializationHash, contractClassId: getContractClassFromArtifact(artifact).id, portalContractAddress: portalContract ?? EthAddress.ZERO, - publicKeysHash: computePublicKeysHash(publicKey), + publicKeysHash: publicKeysHash ?? Fr.ZERO, // TODO(https://github.com/AztecProtocol/aztec-packages/issues/5862) address, deployer: deployer ?? AztecAddress.ZERO, }; diff --git a/yarn-project/cli/src/cmds/create_account.ts b/yarn-project/cli/src/cmds/create_account.ts index 0b3ecbb3166..f0dc92fdf37 100644 --- a/yarn-project/cli/src/cmds/create_account.ts +++ b/yarn-project/cli/src/cmds/create_account.ts @@ -1,21 +1,22 @@ import { getSchnorrAccount } from '@aztec/accounts/schnorr'; -import { GrumpkinScalar } from '@aztec/aztec.js'; -import { type Fq, Fr } from '@aztec/foundation/fields'; +import { deriveKeys } from '@aztec/circuits.js'; +import { Fr } from '@aztec/foundation/fields'; import { type DebugLogger, type LogFn } from '@aztec/foundation/log'; import { createCompatibleClient } from '../client.js'; export async function createAccount( rpcUrl: string, - privateKey: Fq, + secretKey: Fr, wait: boolean, debugLogger: DebugLogger, log: LogFn, ) { const client = await createCompatibleClient(rpcUrl, debugLogger); - const actualPrivateKey = privateKey ?? GrumpkinScalar.random(); + const actualSecretKey = secretKey ?? Fr.random(); - const account = getSchnorrAccount(client, actualPrivateKey, actualPrivateKey, Fr.ZERO); + const signingKey = deriveKeys(actualSecretKey).masterIncomingViewingSecretKey; + const account = getSchnorrAccount(client, actualSecretKey, signingKey, Fr.ZERO); const { address, publicKey, partialAddress } = account.getCompleteAddress(); const tx = account.deploy(); const txHash = await tx.getTxHash(); @@ -30,8 +31,8 @@ export async function createAccount( log(`\nNew account:\n`); log(`Address: ${address.toString()}`); log(`Public key: ${publicKey.toString()}`); - if (!privateKey) { - log(`Private key: ${actualPrivateKey.toString()}`); + if (!secretKey) { + log(`Secret key: ${actualSecretKey.toString()}`); } log(`Partial address: ${partialAddress.toString()}`); } diff --git a/yarn-project/cli/src/cmds/deploy.ts b/yarn-project/cli/src/cmds/deploy.ts index 904418fa629..91b64afaf34 100644 --- a/yarn-project/cli/src/cmds/deploy.ts +++ b/yarn-project/cli/src/cmds/deploy.ts @@ -1,5 +1,6 @@ import { getSchnorrAccount } from '@aztec/accounts/schnorr'; -import { ContractDeployer, type EthAddress, type Fq, Fr, type Point } from '@aztec/aztec.js'; +import { ContractDeployer, type EthAddress, Fr } from '@aztec/aztec.js'; +import { deriveKeys } from '@aztec/circuits.js'; import { getInitializer } from '@aztec/foundation/abi'; import { type DebugLogger, type LogFn } from '@aztec/foundation/log'; @@ -12,11 +13,10 @@ export async function deploy( artifactPath: string, json: boolean, rpcUrl: string, - publicKey: Point | undefined, rawArgs: any[], portalAddress: EthAddress, salt: Fr, - privateKey: Fq, + secretKey: Fr, initializer: string | undefined, wait: boolean, debugLogger: DebugLogger, @@ -35,8 +35,9 @@ export async function deploy( ); } - const wallet = await getSchnorrAccount(client, privateKey, privateKey, Fr.ZERO).getWallet(); - const deployer = new ContractDeployer(contractArtifact, wallet, publicKey, initializer); + const keys = deriveKeys(secretKey); + const wallet = await getSchnorrAccount(client, secretKey, keys.masterIncomingViewingSecretKey, Fr.ZERO).getWallet(); + const deployer = new ContractDeployer(contractArtifact, wallet, keys.publicKeysHash, initializer); let args = []; if (rawArgs.length > 0) { diff --git a/yarn-project/cli/src/cmds/register_account.ts b/yarn-project/cli/src/cmds/register_account.ts index cf5dc168cb9..868bd04721d 100644 --- a/yarn-project/cli/src/cmds/register_account.ts +++ b/yarn-project/cli/src/cmds/register_account.ts @@ -1,18 +1,18 @@ -import { type Fq, type Fr } from '@aztec/foundation/fields'; +import { type Fr } from '@aztec/foundation/fields'; import { type DebugLogger, type LogFn } from '@aztec/foundation/log'; import { createCompatibleClient } from '../client.js'; export async function registerAccount( rpcUrl: string, - privateKey: Fq, + secretKey: Fr, partialAddress: Fr, debugLogger: DebugLogger, log: LogFn, ) { const client = await createCompatibleClient(rpcUrl, debugLogger); - const { address, publicKey } = await client.registerAccount(privateKey, partialAddress); + const { address, publicKey } = await client.registerAccount(secretKey, partialAddress); log(`\nRegistered account:\n`); log(`Address: ${address.toString()}`); diff --git a/yarn-project/cli/src/cmds/send.ts b/yarn-project/cli/src/cmds/send.ts index 07f9c9c08a8..be3c4eea600 100644 --- a/yarn-project/cli/src/cmds/send.ts +++ b/yarn-project/cli/src/cmds/send.ts @@ -1,5 +1,6 @@ import { getSchnorrAccount } from '@aztec/accounts/schnorr'; -import { type AztecAddress, Contract, type Fq, Fr } from '@aztec/aztec.js'; +import { type AztecAddress, Contract, Fr } from '@aztec/aztec.js'; +import { deriveKeys } from '@aztec/circuits.js'; import { type DebugLogger, type LogFn } from '@aztec/foundation/log'; import { createCompatibleClient } from '../client.js'; @@ -10,7 +11,7 @@ export async function send( functionArgsIn: any[], contractArtifactPath: string, contractAddress: AztecAddress, - privateKey: Fq, + secretKey: Fr, rpcUrl: string, wait: boolean, debugLogger: DebugLogger, @@ -19,7 +20,8 @@ export async function send( const { functionArgs, contractArtifact } = await prepTx(contractArtifactPath, functionName, functionArgsIn); const client = await createCompatibleClient(rpcUrl, debugLogger); - const wallet = await getSchnorrAccount(client, privateKey, privateKey, Fr.ZERO).getWallet(); + const signingKey = deriveKeys(secretKey).masterIncomingViewingSecretKey; + const wallet = await getSchnorrAccount(client, secretKey, signingKey, Fr.ZERO).getWallet(); const contract = await Contract.at(contractAddress, contractArtifact, wallet); const tx = contract.methods[functionName](...functionArgs).send(); log(`\nTransaction hash: ${(await tx.getTxHash()).toString()}`); diff --git a/yarn-project/cli/src/index.ts b/yarn-project/cli/src/index.ts index 607ebb9f44f..fc9daa45fbf 100644 --- a/yarn-project/cli/src/index.ts +++ b/yarn-project/cli/src/index.ts @@ -159,11 +159,6 @@ export function getProgram(log: LogFn, debugLogger: DebugLogger): Command { .option('--initializer ', 'The contract initializer function to call') .option('-a, --args ', 'Contract constructor arguments', []) .addOption(pxeOption) - .option( - '-k, --public-key ', - 'Optional encryption public key for this address. Set this value only if this contract is expected to receive private notes, which will be encrypted using this public key.', - parsePublicKey, - ) .option( '-p, --portal-address ', 'Optional L1 portal address to link the contract to.', @@ -180,20 +175,21 @@ export function getProgram(log: LogFn, debugLogger: DebugLogger): Command { // https://github.com/tj/commander.js#other-option-types-negatable-boolean-and-booleanvalue .option('--no-wait', 'Skip waiting for the contract to be deployed. Print the hash of deployment transaction') .action( - async ( - artifactPath, - { json, rpcUrl, publicKey, args: rawArgs, portalAddress, salt, wait, privateKey, initializer }, - ) => { + async (artifactPath, { json, rpcUrl, args: rawArgs, portalAddress, salt, wait, privateKey, initializer }) => { + // TODO(#5726): everywhere here in CLI we consume private key instead of secret key --> we should accept + // secret key everywhere and derive the rest. Also unlike before the keys change the public key is now always + // derived and set for the contract. We should allow setting zero public key again. Remove the hack on the next + // line. + const secretKey = Fr.fromBufferReduce(privateKey.toBuffer()); const { deploy } = await import('./cmds/deploy.js'); await deploy( artifactPath, json, rpcUrl, - publicKey, rawArgs, portalAddress, salt, - privateKey, + secretKey, initializer, wait, debugLogger, diff --git a/yarn-project/end-to-end/src/benchmarks/bench_process_history.test.ts b/yarn-project/end-to-end/src/benchmarks/bench_process_history.test.ts index 69eabf8532d..9654c018449 100644 --- a/yarn-project/end-to-end/src/benchmarks/bench_process_history.test.ts +++ b/yarn-project/end-to-end/src/benchmarks/bench_process_history.test.ts @@ -1,5 +1,5 @@ import { type AztecNodeConfig, AztecNodeService } from '@aztec/aztec-node'; -import { AztecAddress, Fr, GrumpkinScalar, INITIAL_L2_BLOCK_NUM, elapsed, sleep } from '@aztec/aztec.js'; +import { AztecAddress, Fr, INITIAL_L2_BLOCK_NUM, elapsed, sleep } from '@aztec/aztec.js'; import { BENCHMARK_HISTORY_BLOCK_SIZE, BENCHMARK_HISTORY_CHAIN_LENGTHS, @@ -79,12 +79,12 @@ describe('benchmarks/process_history', () => { // Register the owner account and wait until it's synced so we measure how much time it took context.logger.info(`Registering owner account on new pxe`); const partialAddress = context.wallet.getCompleteAddress().partialAddress; - const privateKey = context.wallet.getEncryptionPrivateKey(); - await waitRegisteredAccountSynced(pxe, privateKey, partialAddress); + const secretKey = context.wallet.getSecretKey(); + await waitRegisteredAccountSynced(pxe, secretKey, partialAddress); // Repeat for another account that didn't receive any notes for them, so we measure trial-decrypts context.logger.info(`Registering fresh account on new pxe`); - await waitRegisteredAccountSynced(pxe, GrumpkinScalar.random(), Fr.random()); + await waitRegisteredAccountSynced(pxe, Fr.random(), Fr.random()); // Stop the external node and pxe await pxe.stop(); diff --git a/yarn-project/end-to-end/src/benchmarks/bench_publish_rollup.test.ts b/yarn-project/end-to-end/src/benchmarks/bench_publish_rollup.test.ts index 70f8157877e..542bbfeeb5e 100644 --- a/yarn-project/end-to-end/src/benchmarks/bench_publish_rollup.test.ts +++ b/yarn-project/end-to-end/src/benchmarks/bench_publish_rollup.test.ts @@ -1,5 +1,5 @@ import { AztecNodeService } from '@aztec/aztec-node'; -import { AztecAddress, Fr, GrumpkinScalar } from '@aztec/aztec.js'; +import { AztecAddress, Fr } from '@aztec/aztec.js'; import { BENCHMARK_BLOCK_SIZES } from '@aztec/circuit-types/stats'; import { type BenchmarkingContract } from '@aztec/noir-contracts.js/Benchmarking'; import { type SequencerClient } from '@aztec/sequencer-client'; @@ -46,12 +46,12 @@ describe('benchmarks/publish_rollup', () => { // Register the owner account and wait until it's synced so we measure how much time it took context.logger.info(`Registering owner account on new pxe`); const partialAddress = context.wallet.getCompleteAddress().partialAddress; - const privateKey = context.wallet.getEncryptionPrivateKey(); - await waitRegisteredAccountSynced(pxe, privateKey, partialAddress); + const secretKey = context.wallet.getSecretKey(); + await waitRegisteredAccountSynced(pxe, secretKey, partialAddress); // Repeat for another account that didn't receive any notes for them, so we measure trial-decrypts context.logger.info(`Registering fresh account on new pxe`); - await waitRegisteredAccountSynced(pxe, GrumpkinScalar.random(), Fr.random()); + await waitRegisteredAccountSynced(pxe, Fr.random(), Fr.random()); // Stop the external node and pxe await pxe.stop(); diff --git a/yarn-project/end-to-end/src/benchmarks/bench_tx_size_fees.test.ts b/yarn-project/end-to-end/src/benchmarks/bench_tx_size_fees.test.ts index c2bbcc8ceb8..1deb698f41e 100644 --- a/yarn-project/end-to-end/src/benchmarks/bench_tx_size_fees.test.ts +++ b/yarn-project/end-to-end/src/benchmarks/bench_tx_size_fees.test.ts @@ -1,5 +1,5 @@ import { - type AccountWalletWithPrivateKey, + type AccountWalletWithSecretKey, type AztecAddress, type EthAddress, type FeePaymentMethod, @@ -19,7 +19,7 @@ import { publicDeployAccounts, setup } from '../fixtures/utils.js'; jest.setTimeout(50_000); describe('benchmarks/tx_size_fees', () => { - let aliceWallet: AccountWalletWithPrivateKey; + let aliceWallet: AccountWalletWithSecretKey; let bobAddress: AztecAddress; let sequencerAddress: AztecAddress; let gas: GasTokenContract; diff --git a/yarn-project/end-to-end/src/benchmarks/utils.ts b/yarn-project/end-to-end/src/benchmarks/utils.ts index 5392e85227c..7463c24fd7a 100644 --- a/yarn-project/end-to-end/src/benchmarks/utils.ts +++ b/yarn-project/end-to-end/src/benchmarks/utils.ts @@ -2,7 +2,7 @@ import { type AztecNodeConfig, type AztecNodeService } from '@aztec/aztec-node'; import { type AztecNode, BatchCall, - type GrumpkinScalar, + type Fr, INITIAL_L2_BLOCK_NUM, type PXE, type PartialAddress, @@ -119,16 +119,12 @@ export async function waitNewPXESynced( /** * Registers a new account in a pxe and waits until it's synced all its notes. * @param pxe - PXE where to register the account. - * @param privateKey - Private key of the account to register. + * @param secretKey - Secret key of the account to register. * @param partialAddress - Partial address of the account to register. */ -export async function waitRegisteredAccountSynced( - pxe: PXE, - privateKey: GrumpkinScalar, - partialAddress: PartialAddress, -) { +export async function waitRegisteredAccountSynced(pxe: PXE, secretKey: Fr, partialAddress: PartialAddress) { const l2Block = await pxe.getBlockNumber(); - const { publicKey } = await pxe.registerAccount(privateKey, partialAddress); + const { publicKey } = await pxe.registerAccount(secretKey, partialAddress); const isAccountSynced = async () => (await pxe.getSyncStatus()).notes[publicKey.toString()] === l2Block; await retryUntil(isAccountSynced, 'pxe-notes-sync'); } diff --git a/yarn-project/end-to-end/src/composed/cli_docs_sandbox.test.ts b/yarn-project/end-to-end/src/composed/cli_docs_sandbox.test.ts index 446330a461e..09f026b561f 100644 --- a/yarn-project/end-to-end/src/composed/cli_docs_sandbox.test.ts +++ b/yarn-project/end-to-end/src/composed/cli_docs_sandbox.test.ts @@ -201,7 +201,7 @@ Partial address: 0x01e5e7b2abbfb98a93b7549ae80faa6886f8ea8e8f412416fb330b565fd2b expect(foundPartialAddress).toBeDefined(); }); - it('creates an account, gets account, deploys, checks deployed, view method, sending a tx... [SEQUENTIAL]', async () => { + it.skip('creates an account, gets account, deploys, checks deployed, view method, sending a tx... [SEQUENTIAL]', async () => { // Test create-account let docs = ` // docs:start:create-account diff --git a/yarn-project/end-to-end/src/composed/docs_examples.test.ts b/yarn-project/end-to-end/src/composed/docs_examples.test.ts index 07512e92217..42aada0f881 100644 --- a/yarn-project/end-to-end/src/composed/docs_examples.test.ts +++ b/yarn-project/end-to-end/src/composed/docs_examples.test.ts @@ -1,6 +1,6 @@ // docs:start:create_account_imports import { getSchnorrAccount } from '@aztec/accounts/schnorr'; -import { GrumpkinScalar, createPXEClient } from '@aztec/aztec.js'; +import { Fr, GrumpkinScalar, createPXEClient } from '@aztec/aztec.js'; // docs:end:create_account_imports // docs:start:import_contract import { Contract } from '@aztec/aztec.js'; @@ -14,13 +14,13 @@ describe('docs_examples', () => { it('deploys and interacts with a token contract', async () => { // docs:start:define_account_vars const PXE_URL = process.env.PXE_URL || 'http://localhost:8080'; - const encryptionPrivateKey = GrumpkinScalar.random(); + const secretKey = Fr.random(); const signingPrivateKey = GrumpkinScalar.random(); const pxe = createPXEClient(PXE_URL); // docs:end:define_account_vars // docs:start:create_wallet - const wallet = await getSchnorrAccount(pxe, encryptionPrivateKey, signingPrivateKey).waitSetup(); + const wallet = await getSchnorrAccount(pxe, secretKey, signingPrivateKey).waitSetup(); // docs:end:create_wallet // docs:start:deploy_contract diff --git a/yarn-project/end-to-end/src/composed/e2e_persistence.test.ts b/yarn-project/end-to-end/src/composed/e2e_persistence.test.ts index 8138ea8f0a7..15bb02259a3 100644 --- a/yarn-project/end-to-end/src/composed/e2e_persistence.test.ts +++ b/yarn-project/end-to-end/src/composed/e2e_persistence.test.ts @@ -9,7 +9,7 @@ import { waitForAccountSynch, } from '@aztec/aztec.js'; import { type Salt } from '@aztec/aztec.js/account'; -import { type AztecAddress, type CompleteAddress, Fq, Fr } from '@aztec/circuits.js'; +import { type AztecAddress, type CompleteAddress, Fr, deriveSigningKey } from '@aztec/circuits.js'; import { type DeployL1Contracts } from '@aztec/ethereum'; import { TokenContract } from '@aztec/noir-contracts.js/Token'; @@ -39,7 +39,7 @@ describe('Aztec persistence', () => { // the test contract and account deploying it let contractInstance: ContractInstanceWithAddress; let contractAddress: AztecAddress; - let ownerPrivateKey: Fq; + let ownerSecretKey: Fr; let ownerAddress: CompleteAddress; let ownerSalt: Salt; @@ -59,8 +59,8 @@ describe('Aztec persistence', () => { const initialContext = await setup(0, { dataDirectory }, { dataDirectory }); deployL1ContractsValues = initialContext.deployL1ContractsValues; - ownerPrivateKey = Fq.random(); - const ownerWallet = await getUnsafeSchnorrAccount(initialContext.pxe, ownerPrivateKey, Fr.ZERO).waitSetup(); + ownerSecretKey = Fr.random(); + const ownerWallet = await getUnsafeSchnorrAccount(initialContext.pxe, ownerSecretKey, Fr.ZERO).waitSetup(); ownerAddress = ownerWallet.getCompleteAddress(); ownerSalt = ownerWallet.salt; @@ -106,7 +106,8 @@ describe('Aztec persistence', () => { beforeEach(async () => { context = await contextSetup(); - ownerWallet = await getUnsafeSchnorrWallet(context.pxe, ownerAddress.address, ownerPrivateKey); + const signingKey = deriveSigningKey(ownerSecretKey); + ownerWallet = await getUnsafeSchnorrWallet(context.pxe, ownerAddress.address, signingKey); contract = await TokenContract.at(contractAddress, ownerWallet); }, timeout); @@ -146,7 +147,7 @@ describe('Aztec persistence', () => { }); it('allows spending of private notes', async () => { - const otherWallet = await getUnsafeSchnorrAccount(context.pxe, Fq.random(), Fr.ZERO).waitSetup(); + const otherWallet = await getUnsafeSchnorrAccount(context.pxe, Fr.random(), Fr.ZERO).waitSetup(); const initialOwnerBalance = await contract.methods.balance_of_private(ownerWallet.getAddress()).simulate(); @@ -194,7 +195,7 @@ describe('Aztec persistence', () => { it('pxe does not know of the deployed contract', async () => { await context.pxe.registerRecipient(ownerAddress); - const wallet = await getUnsafeSchnorrAccount(context.pxe, Fq.random(), Fr.ZERO).waitSetup(); + const wallet = await getUnsafeSchnorrAccount(context.pxe, Fr.random(), Fr.ZERO).waitSetup(); await expect(TokenContract.at(contractAddress, wallet)).rejects.toThrow(/has not been registered/); }); @@ -205,7 +206,7 @@ describe('Aztec persistence', () => { }); await context.pxe.registerRecipient(ownerAddress); - const wallet = await getUnsafeSchnorrAccount(context.pxe, Fq.random(), Fr.ZERO).waitSetup(); + const wallet = await getUnsafeSchnorrAccount(context.pxe, Fr.random(), Fr.ZERO).waitSetup(); const contract = await TokenContract.at(contractAddress, wallet); await expect(contract.methods.balance_of_private(ownerAddress.address).simulate()).resolves.toEqual(0n); }); @@ -216,7 +217,7 @@ describe('Aztec persistence', () => { instance: contractInstance, }); - const wallet = await getUnsafeSchnorrAccount(context.pxe, Fq.random(), Fr.ZERO).waitSetup(); + const wallet = await getUnsafeSchnorrAccount(context.pxe, Fr.random(), Fr.ZERO).waitSetup(); const contract = await TokenContract.at(contractAddress, wallet); await expect(contract.methods.total_supply().simulate()).resolves.toBeGreaterThan(0n); @@ -228,7 +229,7 @@ describe('Aztec persistence', () => { instance: contractInstance, }); - const ownerAccount = getUnsafeSchnorrAccount(context.pxe, ownerPrivateKey, ownerSalt); + const ownerAccount = getUnsafeSchnorrAccount(context.pxe, ownerSecretKey, ownerSalt); await ownerAccount.register(); const ownerWallet = await ownerAccount.getWallet(); const contract = await TokenContract.at(contractAddress, ownerWallet); @@ -259,7 +260,7 @@ describe('Aztec persistence', () => { instance: contractInstance, }); - const ownerAccount = getUnsafeSchnorrAccount(temporaryContext.pxe, ownerPrivateKey, ownerSalt); + const ownerAccount = getUnsafeSchnorrAccount(temporaryContext.pxe, ownerSecretKey, ownerSalt); await ownerAccount.register(); const ownerWallet = await ownerAccount.getWallet(); @@ -287,7 +288,8 @@ describe('Aztec persistence', () => { beforeEach(async () => { context = await setup(0, { dataDirectory, deployL1ContractsValues }, { dataDirectory }); - ownerWallet = await getUnsafeSchnorrWallet(context.pxe, ownerAddress.address, ownerPrivateKey); + const signingKey = deriveSigningKey(ownerSecretKey); + ownerWallet = await getUnsafeSchnorrWallet(context.pxe, ownerAddress.address, signingKey); contract = await TokenContract.at(contractAddress, ownerWallet); await waitForAccountSynch(context.pxe, ownerAddress, { interval: 0.1, timeout: 5 }); diff --git a/yarn-project/end-to-end/src/composed/e2e_sandbox_example.test.ts b/yarn-project/end-to-end/src/composed/e2e_sandbox_example.test.ts index f336bf40c77..bbc794b8096 100644 --- a/yarn-project/end-to-end/src/composed/e2e_sandbox_example.test.ts +++ b/yarn-project/end-to-end/src/composed/e2e_sandbox_example.test.ts @@ -194,7 +194,7 @@ describe('e2e_sandbox_example', () => { .map(() => getSchnorrAccount( pxe, - GrumpkinScalar.random(), // encryption private key + Fr.random(), // secret key GrumpkinScalar.random(), // signing private key ), ); diff --git a/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts b/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts index 3ee53ecbc72..b72df9815b3 100644 --- a/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts +++ b/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts @@ -101,8 +101,8 @@ describe('L1Publisher integration', () => { let coinbase: EthAddress; let feeRecipient: AztecAddress; - // To overwrite the test data, set this to true and run the tests. - const OVERWRITE_TEST_DATA = !!process.env.OVERWRITE_TEST_DATA; + // To update the test data, run "export AZTEC_GENERATE_TEST_DATA=1" in shell and run the tests again + const AZTEC_GENERATE_TEST_DATA = !!process.env.AZTEC_GENERATE_TEST_DATA; beforeEach(async () => { deployerAccount = privateKeyToAccount(deployerPK); @@ -232,7 +232,7 @@ describe('L1Publisher integration', () => { recipientAddress: AztecAddress, deployerAddress: `0x${string}`, ) => { - if (!OVERWRITE_TEST_DATA) { + if (!AZTEC_GENERATE_TEST_DATA) { return; } // Path relative to the package.json in the end-to-end folder diff --git a/yarn-project/end-to-end/src/e2e_2_pxes.test.ts b/yarn-project/end-to-end/src/e2e_2_pxes.test.ts index 3fac2ce5b74..ce6e676d3ad 100644 --- a/yarn-project/end-to-end/src/e2e_2_pxes.test.ts +++ b/yarn-project/end-to-end/src/e2e_2_pxes.test.ts @@ -5,7 +5,6 @@ import { type DebugLogger, ExtendedNote, Fr, - GrumpkinScalar, Note, type PXE, type Wallet, @@ -245,13 +244,13 @@ describe('e2e_2_pxes', () => { }); it('permits migrating an account from one PXE to another', async () => { - const privateKey = GrumpkinScalar.random(); - const account = getUnsafeSchnorrAccount(pxeA, privateKey, Fr.random()); + const secretKey = Fr.random(); + const account = getUnsafeSchnorrAccount(pxeA, secretKey, Fr.random()); const completeAddress = account.getCompleteAddress(); const wallet = await account.waitSetup(); await expect(wallet.isAccountStateSynchronized(completeAddress.address)).resolves.toBe(true); - const accountOnB = getUnsafeSchnorrAccount(pxeB, privateKey, account.salt); + const accountOnB = getUnsafeSchnorrAccount(pxeB, secretKey, account.salt); const walletOnB = await accountOnB.getWallet(); // need to register first otherwise the new PXE won't know about the account @@ -302,13 +301,13 @@ describe('e2e_2_pxes', () => { const transferAmount2 = 323n; // setup an account that is shared across PXEs - const sharedPrivateKey = GrumpkinScalar.random(); - const sharedAccountOnA = getUnsafeSchnorrAccount(pxeA, sharedPrivateKey, Fr.random()); + const sharedSecretKey = Fr.random(); + const sharedAccountOnA = getUnsafeSchnorrAccount(pxeA, sharedSecretKey, Fr.random()); const sharedAccountAddress = sharedAccountOnA.getCompleteAddress(); const sharedWalletOnA = await sharedAccountOnA.waitSetup(); await expect(sharedWalletOnA.isAccountStateSynchronized(sharedAccountAddress.address)).resolves.toBe(true); - const sharedAccountOnB = getUnsafeSchnorrAccount(pxeB, sharedPrivateKey, sharedAccountOnA.salt); + const sharedAccountOnB = getUnsafeSchnorrAccount(pxeB, sharedSecretKey, sharedAccountOnA.salt); await sharedAccountOnB.register(); const sharedWalletOnB = await sharedAccountOnB.getWallet(); diff --git a/yarn-project/end-to-end/src/e2e_account_contracts.test.ts b/yarn-project/end-to-end/src/e2e_account_contracts.test.ts index 89e8de6aa4a..93fee9d8589 100644 --- a/yarn-project/end-to-end/src/e2e_account_contracts.test.ts +++ b/yarn-project/end-to-end/src/e2e_account_contracts.test.ts @@ -20,17 +20,14 @@ import { setup } from './fixtures/utils.js'; function itShouldBehaveLikeAnAccountContract( getAccountContract: (encryptionKey: GrumpkinPrivateKey) => AccountContract, - walletSetup: ( - pxe: PXE, - encryptionPrivateKey: GrumpkinPrivateKey, - accountContract: AccountContract, - ) => Promise, + walletSetup: (pxe: PXE, secretKey: Fr, accountContract: AccountContract) => Promise, walletAt: (pxe: PXE, accountContract: AccountContract, address: CompleteAddress) => Promise, ) { describe(`behaves like an account contract`, () => { let child: ChildContract; let wallet: Wallet; - let encryptionPrivateKey: GrumpkinPrivateKey; + let secretKey: Fr; + let signingKey: GrumpkinPrivateKey; let pxe: PXE; let logger: DebugLogger; @@ -38,9 +35,10 @@ function itShouldBehaveLikeAnAccountContract( beforeEach(async () => { ({ logger, pxe, teardown } = await setup(0)); - encryptionPrivateKey = GrumpkinScalar.random(); + secretKey = Fr.random(); + signingKey = GrumpkinScalar.random(); - wallet = await walletSetup(pxe, encryptionPrivateKey, getAccountContract(encryptionPrivateKey)); + wallet = await walletSetup(pxe, secretKey, getAccountContract(signingKey)); child = await ChildContract.deploy(wallet).send().deployed(); }, 60_000); @@ -58,7 +56,8 @@ function itShouldBehaveLikeAnAccountContract( expect(storedValue).toEqual(new Fr(42n)); }, 60_000); - it('fails to call a function using an invalid signature', async () => { + // TODO(#5830): re-enable this test + it.skip('fails to call a function using an invalid signature', async () => { const accountAddress = wallet.getCompleteAddress(); const invalidWallet = await walletAt(pxe, getAccountContract(GrumpkinScalar.random()), accountAddress); const childWithInvalidWallet = await ChildContract.at(child.address, invalidWallet); @@ -68,14 +67,18 @@ function itShouldBehaveLikeAnAccountContract( } describe('e2e_account_contracts', () => { - const walletSetup = async (pxe: PXE, encryptionPrivateKey: GrumpkinPrivateKey, accountContract: AccountContract) => { - const account = new AccountManager(pxe, encryptionPrivateKey, accountContract); + const walletSetup = async (pxe: PXE, secretKey: Fr, accountContract: AccountContract) => { + const account = new AccountManager(pxe, secretKey, accountContract); return await account.waitSetup(); }; const walletAt = async (pxe: PXE, accountContract: AccountContract, address: CompleteAddress) => { const nodeInfo = await pxe.getNodeInfo(); - const entrypoint = accountContract.getInterface(address, nodeInfo); + const publicKeysHash = await pxe.getRegisteredAccountPublicKeysHash(address.address); + if (!publicKeysHash) { + throw new Error(`Public keys hash for account ${address.address} not found`); + } + const entrypoint = accountContract.getInterface(address, publicKeysHash, nodeInfo); return new AccountWallet(pxe, entrypoint); }; diff --git a/yarn-project/end-to-end/src/e2e_card_game.test.ts b/yarn-project/end-to-end/src/e2e_card_game.test.ts index 61d2f2399c4..6342654d9ed 100644 --- a/yarn-project/end-to-end/src/e2e_card_game.test.ts +++ b/yarn-project/end-to-end/src/e2e_card_game.test.ts @@ -1,5 +1,5 @@ import { getSchnorrAccount } from '@aztec/accounts/schnorr'; -import { INITIAL_TEST_ENCRYPTION_KEYS } from '@aztec/accounts/testing'; +import { INITIAL_TEST_SECRET_KEYS } from '@aztec/accounts/testing'; import { type AccountWallet, AztecAddress, @@ -7,9 +7,10 @@ import { GrumpkinScalar, type PXE, type Wallet, - generatePublicKey, + computeAppNullifierSecretKey, + deriveKeys, + deriveMasterNullifierSecretKey, } from '@aztec/aztec.js'; -import { computeNullifierSecretKey, computeSiloedNullifierSecretKey } from '@aztec/circuits.js'; import { toBufferLE } from '@aztec/foundation/bigint-buffer'; import { sha256 } from '@aztec/foundation/crypto'; import { CardGameContract } from '@aztec/noir-contracts.js/CardGame'; @@ -56,7 +57,7 @@ function unwrapOptions(options: NoirOption[]): T[] { const PACK_CARDS = 3; const GAME_ID = 42; -const PLAYER_ENCRYPTION_KEYS = INITIAL_TEST_ENCRYPTION_KEYS; +const PLAYER_SECRET_KEYS = INITIAL_TEST_SECRET_KEYS; describe('e2e_card_game', () => { let pxe: PXE; @@ -64,7 +65,7 @@ describe('e2e_card_game', () => { let teardown: () => Promise; let wallets: AccountWallet[]; - let nullifierSecretKeys: GrumpkinScalar[]; + let masterNullifierSecretKeys: GrumpkinScalar[]; let firstPlayerWallet: Wallet; let secondPlayerWallet: Wallet; @@ -79,9 +80,11 @@ describe('e2e_card_game', () => { let contractAsThirdPlayer: CardGameContract; const getPackedCards = (accountIndex: number, seed: bigint): Card[] => { - const nullifierKey = nullifierSecretKeys[accountIndex]; - const secret = computeSiloedNullifierSecretKey(nullifierKey, contract.address); - const mix = secret.high.add(secret.low).toBigInt() + seed; + // First we get the app nullifier secret key for the account + const masterNullifierSecretKey = masterNullifierSecretKeys[accountIndex]; + const appNullifierSecretKey = computeAppNullifierSecretKey(masterNullifierSecretKey, contract.address); + // Then we compute the mix from it and hash it to get the random bytes the same way as in the contract + const mix = appNullifierSecretKey.toBigInt() + seed; const randomBytes = sha256(toBufferLE(mix, 32)); const cards: Card[] = []; for (let i = 0; i < PACK_CARDS; ++i) { @@ -98,8 +101,8 @@ describe('e2e_card_game', () => { const preRegisteredAccounts = await pxe.getRegisteredAccounts(); - const toRegister = PLAYER_ENCRYPTION_KEYS.filter(key => { - const publicKey = generatePublicKey(key); + const secretKeysToRegister = INITIAL_TEST_SECRET_KEYS.filter(key => { + const publicKey = deriveKeys(key).masterIncomingViewingPublicKey; return ( preRegisteredAccounts.find(preRegisteredAccount => { return preRegisteredAccount.publicKey.equals(publicKey); @@ -107,9 +110,9 @@ describe('e2e_card_game', () => { ); }); - for (let i = 0; i < toRegister.length; i++) { - logger.info(`Deploying account contract ${i}/${toRegister.length}...`); - const encryptionPrivateKey = toRegister[i]; + for (let i = 0; i < secretKeysToRegister.length; i++) { + logger.info(`Deploying account contract ${i}/${secretKeysToRegister.length}...`); + const encryptionPrivateKey = secretKeysToRegister[i]; const account = getSchnorrAccount(pxe, encryptionPrivateKey, GrumpkinScalar.random()); const wallet = await account.waitSetup({ interval: 0.1 }); wallets.push(wallet); @@ -119,7 +122,7 @@ describe('e2e_card_game', () => { [firstPlayerWallet, secondPlayerWallet, thirdPlayerWallet] = wallets; [firstPlayer, secondPlayer, thirdPlayer] = wallets.map(a => a.getAddress()); - nullifierSecretKeys = PLAYER_ENCRYPTION_KEYS.map(pk => computeNullifierSecretKey(pk)); + masterNullifierSecretKeys = PLAYER_SECRET_KEYS.map(sk => deriveMasterNullifierSecretKey(sk)); }, 100_000); beforeEach(async () => { diff --git a/yarn-project/end-to-end/src/e2e_crowdfunding_and_claim.test.ts b/yarn-project/end-to-end/src/e2e_crowdfunding_and_claim.test.ts index d694dc453d5..f697a02251f 100644 --- a/yarn-project/end-to-end/src/e2e_crowdfunding_and_claim.test.ts +++ b/yarn-project/end-to-end/src/e2e_crowdfunding_and_claim.test.ts @@ -5,12 +5,11 @@ import { type DebugLogger, ExtendedNote, Fr, - GrumpkinScalar, Note, type PXE, type TxHash, computeMessageSecretHash, - generatePublicKey, + deriveKeys, } from '@aztec/aztec.js'; import { computePartialAddress } from '@aztec/circuits.js'; import { InclusionProofsContract } from '@aztec/noir-contracts.js'; @@ -49,8 +48,8 @@ describe('e2e_crowdfunding_and_claim', () => { let crowdfundingContract: CrowdfundingContract; let claimContract: ClaimContract; - let crowdfundingPrivateKey; - let crowdfundingPublicKey; + let crowdfundingSecretKey; + let crowdfundingPublicKeysHash; let pxe: PXE; let cheatCodes: CheatCodes; let deadline: number; // end of crowdfunding period @@ -106,18 +105,18 @@ describe('e2e_crowdfunding_and_claim', () => { .deployed(); logger.info(`Reward Token deployed to ${rewardToken.address}`); - crowdfundingPrivateKey = GrumpkinScalar.random(); - crowdfundingPublicKey = generatePublicKey(crowdfundingPrivateKey); + crowdfundingSecretKey = Fr.random(); + crowdfundingPublicKeysHash = deriveKeys(crowdfundingSecretKey).publicKeysHash; - const crowdfundingDeployment = CrowdfundingContract.deployWithPublicKey( - crowdfundingPublicKey, + const crowdfundingDeployment = CrowdfundingContract.deployWithPublicKeysHash( + crowdfundingPublicKeysHash, operatorWallet, donationToken.address, operatorWallet.getAddress(), deadline, ); const crowdfundingInstance = crowdfundingDeployment.getInstance(); - await pxe.registerAccount(crowdfundingPrivateKey, computePartialAddress(crowdfundingInstance)); + await pxe.registerAccount(crowdfundingSecretKey, computePartialAddress(crowdfundingInstance)); crowdfundingContract = await crowdfundingDeployment.send().deployed(); logger.info(`Crowdfunding contract deployed at ${crowdfundingContract.address}`); diff --git a/yarn-project/end-to-end/src/e2e_dapp_subscription.test.ts b/yarn-project/end-to-end/src/e2e_dapp_subscription.test.ts index a5398f9506b..251e27734bc 100644 --- a/yarn-project/end-to-end/src/e2e_dapp_subscription.test.ts +++ b/yarn-project/end-to-end/src/e2e_dapp_subscription.test.ts @@ -1,5 +1,5 @@ import { - type AccountWalletWithPrivateKey, + type AccountWalletWithSecretKey, type AztecAddress, type AztecNode, type DebugLogger, @@ -32,8 +32,8 @@ describe('e2e_dapp_subscription', () => { let pxe: PXE; let logger: DebugLogger; - let aliceWallet: AccountWalletWithPrivateKey; - let bobWallet: AccountWalletWithPrivateKey; + let aliceWallet: AccountWalletWithSecretKey; + let bobWallet: AccountWalletWithSecretKey; let aliceAddress: AztecAddress; // Dapp subscriber. let bobAddress: AztecAddress; // Dapp owner. let sequencerAddress: AztecAddress; @@ -69,7 +69,7 @@ describe('e2e_dapp_subscription', () => { expect(GAS_SETTINGS.getFeeLimit().toBigInt()).toEqual(MAX_FEE); - let wallets: AccountWalletWithPrivateKey[]; + let wallets: AccountWalletWithSecretKey[]; let aztecNode: AztecNode; let deployL1ContractsValues: DeployL1Contracts; ({ wallets, aztecNode, deployL1ContractsValues, logger, pxe } = await setup(3, {}, {}, true)); diff --git a/yarn-project/end-to-end/src/e2e_escrow_contract.test.ts b/yarn-project/end-to-end/src/e2e_escrow_contract.test.ts index ef80dcffca8..de4f2f48152 100644 --- a/yarn-project/end-to-end/src/e2e_escrow_contract.test.ts +++ b/yarn-project/end-to-end/src/e2e_escrow_contract.test.ts @@ -5,13 +5,10 @@ import { type DebugLogger, ExtendedNote, Fr, - type GrumpkinPrivateKey, - GrumpkinScalar, Note, type PXE, - type PublicKey, computeMessageSecretHash, - generatePublicKey, + deriveKeys, } from '@aztec/aztec.js'; import { computePartialAddress } from '@aztec/circuits.js'; import { EscrowContract } from '@aztec/noir-contracts.js/Escrow'; @@ -32,8 +29,8 @@ describe('e2e_escrow_contract', () => { let owner: AztecAddress; let recipient: AztecAddress; - let escrowPrivateKey: GrumpkinPrivateKey; - let escrowPublicKey: PublicKey; + let escrowSecretKey: Fr; + let escrowPublicKeysHash: Fr; beforeEach(async () => { // Setup environment @@ -48,11 +45,11 @@ describe('e2e_escrow_contract', () => { // Generate private key for escrow contract, register key in pxe service, and deploy // Note that we need to register it first if we want to emit an encrypted note for it in the constructor - escrowPrivateKey = GrumpkinScalar.random(); - escrowPublicKey = generatePublicKey(escrowPrivateKey); - const escrowDeployment = EscrowContract.deployWithPublicKey(escrowPublicKey, wallet, owner); + escrowSecretKey = Fr.random(); + escrowPublicKeysHash = deriveKeys(escrowSecretKey).publicKeysHash; + const escrowDeployment = EscrowContract.deployWithPublicKeysHash(escrowPublicKeysHash, wallet, owner); const escrowInstance = escrowDeployment.getInstance(); - await pxe.registerAccount(escrowPrivateKey, computePartialAddress(escrowInstance)); + await pxe.registerAccount(escrowSecretKey, computePartialAddress(escrowInstance)); escrowContract = await escrowDeployment.send().deployed(); logger.info(`Escrow contract deployed at ${escrowContract.address}`); diff --git a/yarn-project/end-to-end/src/e2e_multiple_accounts_1_enc_key.test.ts b/yarn-project/end-to-end/src/e2e_multiple_accounts_1_enc_key.test.ts index b9b25a2f6ac..599a69d8956 100644 --- a/yarn-project/end-to-end/src/e2e_multiple_accounts_1_enc_key.test.ts +++ b/yarn-project/end-to-end/src/e2e_multiple_accounts_1_enc_key.test.ts @@ -11,7 +11,7 @@ import { type PXE, type Wallet, computeMessageSecretHash, - generatePublicKey, + deriveKeys, } from '@aztec/aztec.js'; import { TokenContract } from '@aztec/noir-contracts.js/Token'; @@ -33,7 +33,7 @@ describe('e2e_multiple_accounts_1_enc_key', () => { beforeEach(async () => { ({ teardown, aztecNode, pxe, logger } = await setup(0)); - const encryptionPrivateKey = GrumpkinScalar.random(); + const encryptionPrivateKey = Fr.random(); for (let i = 0; i < numAccounts; i++) { logger.info(`Deploying account contract ${i}/3...`); @@ -47,7 +47,7 @@ describe('e2e_multiple_accounts_1_enc_key', () => { logger.info('Account contracts deployed'); // Verify that all accounts use the same encryption key - const encryptionPublicKey = generatePublicKey(encryptionPrivateKey); + const encryptionPublicKey = deriveKeys(encryptionPrivateKey).masterIncomingViewingPublicKey; for (const account of accounts) { expect(account.publicKey).toEqual(encryptionPublicKey); diff --git a/yarn-project/end-to-end/src/e2e_outbox.test.ts b/yarn-project/end-to-end/src/e2e_outbox.test.ts index 2158f292164..9d613efa09f 100644 --- a/yarn-project/end-to-end/src/e2e_outbox.test.ts +++ b/yarn-project/end-to-end/src/e2e_outbox.test.ts @@ -1,5 +1,5 @@ import { - type AccountWalletWithPrivateKey, + type AccountWalletWithSecretKey, type AztecNode, BatchCall, type DeployL1Contracts, @@ -24,7 +24,7 @@ describe('E2E Outbox Tests', () => { let aztecNode: AztecNode; const merkleSha256 = new SHA256(); let contract: TestContract; - let wallets: AccountWalletWithPrivateKey[]; + let wallets: AccountWalletWithSecretKey[]; let deployL1ContractsValues: DeployL1Contracts; beforeEach(async () => { diff --git a/yarn-project/end-to-end/src/fixtures/snapshot_manager.ts b/yarn-project/end-to-end/src/fixtures/snapshot_manager.ts index c917320e4b3..9fe93aafd77 100644 --- a/yarn-project/end-to-end/src/fixtures/snapshot_manager.ts +++ b/yarn-project/end-to-end/src/fixtures/snapshot_manager.ts @@ -6,6 +6,7 @@ import { type CompleteAddress, type DebugLogger, EthCheatCodes, + Fr, GrumpkinPrivateKey, type Wallet, } from '@aztec/aztec.js'; @@ -282,14 +283,14 @@ export const addAccounts = (numberOfAccounts: number, logger: DebugLogger) => async ({ pxe }: SubsystemsContext) => { // Generate account keys. - const accountKeys: [GrumpkinPrivateKey, GrumpkinPrivateKey][] = Array.from({ length: numberOfAccounts }).map(_ => [ - GrumpkinPrivateKey.random(), + const accountKeys: [Fr, GrumpkinPrivateKey][] = Array.from({ length: numberOfAccounts }).map(_ => [ + Fr.random(), GrumpkinPrivateKey.random(), ]); logger.verbose('Simulating account deployment...'); - const accountManagers = await asyncMap(accountKeys, async ([encPk, signPk]) => { - const account = getSchnorrAccount(pxe, encPk, signPk, 1); + const accountManagers = await asyncMap(accountKeys, async ([secretKey, signPk]) => { + const account = getSchnorrAccount(pxe, secretKey, signPk, 1); // Unfortunately the function below is not stateless and we call it here because it takes a long time to run and // the results get stored within the account object. By calling it here we increase the probability of all the // accounts being deployed in the same block because it makes the deploy() method basically instant. diff --git a/yarn-project/end-to-end/src/fixtures/utils.ts b/yarn-project/end-to-end/src/fixtures/utils.ts index 5708bb4b5af..fd42cf1e688 100644 --- a/yarn-project/end-to-end/src/fixtures/utils.ts +++ b/yarn-project/end-to-end/src/fixtures/utils.ts @@ -2,7 +2,7 @@ import { SchnorrAccountContractArtifact } from '@aztec/accounts/schnorr'; import { createAccounts, getDeployedTestAccountsWallets } from '@aztec/accounts/testing'; import { type AztecNodeConfig, AztecNodeService, getConfigEnvVars } from '@aztec/aztec-node'; import { - type AccountWalletWithPrivateKey, + type AccountWalletWithSecretKey, type AztecAddress, type AztecNode, BatchCall, @@ -190,7 +190,7 @@ export async function setupPXEService( /** * The wallets to be used. */ - wallets: AccountWalletWithPrivateKey[]; + wallets: AccountWalletWithSecretKey[]; /** * Logger instance named as the current test. */ @@ -305,9 +305,9 @@ export type EndToEndContext = { /** The Aztec Node configuration. */ config: AztecNodeConfig; /** The first wallet to be used. */ - wallet: AccountWalletWithPrivateKey; + wallet: AccountWalletWithSecretKey; /** The wallets to be used. */ - wallets: AccountWalletWithPrivateKey[]; + wallets: AccountWalletWithSecretKey[]; /** Logger instance named as the current test. */ logger: DebugLogger; /** The cheat codes. */ diff --git a/yarn-project/end-to-end/src/flakey_e2e_account_init_fees.test.ts b/yarn-project/end-to-end/src/flakey_e2e_account_init_fees.test.ts index 9f0d16ed810..0abceba6d0c 100644 --- a/yarn-project/end-to-end/src/flakey_e2e_account_init_fees.test.ts +++ b/yarn-project/end-to-end/src/flakey_e2e_account_init_fees.test.ts @@ -13,7 +13,7 @@ import { TxStatus, type Wallet, computeMessageSecretHash, - generatePublicKey, + deriveKeys, } from '@aztec/aztec.js'; import { type AztecAddress, CompleteAddress, DimensionGasSettings, Fq, GasSettings } from '@aztec/circuits.js'; import { @@ -59,7 +59,7 @@ describe('e2e_fees_account_init', () => { let bananaPublicBalances: BalancesFn; let bananaPrivateBalances: BalancesFn; - let bobsPrivateEncryptionKey: Fq; + let bobsSecretKey: Fr; let bobsPrivateSigningKey: Fq; let bobsAccountManager: AccountManager; let bobsAddress: AztecAddress; @@ -129,9 +129,9 @@ describe('e2e_fees_account_init', () => { gasSettings = new GasSettings(individualGasSettings, individualGasSettings, individualGasSettings, new Fr(5)); maxFee = 3n * 3n + 5n; actualFee = 1n; - bobsPrivateEncryptionKey = Fq.random(); + bobsSecretKey = Fr.random(); bobsPrivateSigningKey = Fq.random(); - bobsAccountManager = getSchnorrAccount(ctx.pxe, bobsPrivateEncryptionKey, bobsPrivateSigningKey, Fr.random()); + bobsAccountManager = getSchnorrAccount(ctx.pxe, bobsSecretKey, bobsPrivateSigningKey, Fr.random()); bobsAddress = bobsAccountManager.getCompleteAddress().address; }); @@ -289,15 +289,20 @@ describe('e2e_fees_account_init', () => { const instance = bobsAccountManager.getInstance(); // and gives the public keys to alice - const encPubKey = generatePublicKey(bobsPrivateEncryptionKey); const signingPubKey = new Schnorr().computePublicKey(bobsPrivateSigningKey); - const completeAddress = CompleteAddress.fromPublicKeyAndInstance(encPubKey, instance); + const completeAddress = CompleteAddress.fromSecretKeyAndInstance(bobsSecretKey, instance); // alice registers the keys in the PXE await ctx.pxe.registerRecipient(completeAddress); // and deploys bob's account, paying the fee from her balance - const tx = await SchnorrAccountContract.deployWithPublicKey(encPubKey, alice, signingPubKey.x, signingPubKey.y) + const publicKeysHash = deriveKeys(bobsSecretKey).publicKeysHash; + const tx = await SchnorrAccountContract.deployWithPublicKeysHash( + publicKeysHash, + alice, + signingPubKey.x, + signingPubKey.y, + ) .send({ contractAddressSalt: instance.salt, skipClassRegistration: true, diff --git a/yarn-project/end-to-end/src/flakey_e2e_deploy_contract/contract_class_registration.test.ts b/yarn-project/end-to-end/src/flakey_e2e_deploy_contract/contract_class_registration.test.ts index 5ce50aa7369..7c723d2ad0b 100644 --- a/yarn-project/end-to-end/src/flakey_e2e_deploy_contract/contract_class_registration.test.ts +++ b/yarn-project/end-to-end/src/flakey_e2e_deploy_contract/contract_class_registration.test.ts @@ -19,7 +19,7 @@ import { deployInstance, registerContractClass, } from '@aztec/aztec.js/deployment'; -import { type ContractClassIdPreimage, Point } from '@aztec/circuits.js'; +import { type ContractClassIdPreimage } from '@aztec/circuits.js'; import { FunctionSelector, FunctionType } from '@aztec/foundation/abi'; import { writeTestData } from '@aztec/foundation/testing'; import { StatefulTestContract } from '@aztec/noir-contracts.js'; @@ -97,11 +97,11 @@ describe('e2e_deploy_contract contract class registration', () => { const initArgs = [wallet.getAddress(), 42] as StatefulContractCtorArgs; const salt = Fr.random(); const portalAddress = EthAddress.random(); - const publicKey = Point.random(); + const publicKeysHash = Fr.random(); const instance = getContractInstanceFromDeployParams(artifact, { constructorArgs: initArgs, salt, - publicKey, + publicKeysHash, portalAddress, constructorArtifact: opts.constructorName, deployer: opts.deployer, @@ -123,13 +123,13 @@ describe('e2e_deploy_contract contract class registration', () => { constructorName: opts.constructorName, salt: instance.salt, portalAddress: instance.portalContractAddress, - publicKey, + publicKeysHash, initArgs, deployer: opts.deployer, }); expect(registered.address).toEqual(instance.address); const contract = await StatefulTestContract.at(instance.address, wallet); - return { contract, initArgs, instance, publicKey }; + return { contract, initArgs, instance, publicKeysHash }; }; describe('using a private constructor', () => { diff --git a/yarn-project/end-to-end/src/flakey_e2e_deploy_contract/deploy_test.ts b/yarn-project/end-to-end/src/flakey_e2e_deploy_contract/deploy_test.ts index 192853b4786..cb659cf3695 100644 --- a/yarn-project/end-to-end/src/flakey_e2e_deploy_contract/deploy_test.ts +++ b/yarn-project/end-to-end/src/flakey_e2e_deploy_contract/deploy_test.ts @@ -14,7 +14,6 @@ import { createDebugLogger, getContractInstanceFromDeployParams, } from '@aztec/aztec.js'; -import { type Point } from '@aztec/circuits.js'; import { type StatefulTestContract } from '@aztec/noir-contracts.js'; import { SnapshotManager, addAccounts } from '../fixtures/snapshot_manager.js'; @@ -64,19 +63,19 @@ export class DeployTest { contractArtifact: ContractArtifactClass, opts: { salt?: Fr; - publicKey?: Point; + publicKeysHash?: Fr; portalAddress?: EthAddress; initArgs?: any[]; constructorName?: string; deployer?: AztecAddress; } = {}, ): Promise { - const { salt, publicKey, portalAddress, initArgs, constructorName, deployer } = opts; + const { salt, publicKeysHash, portalAddress, initArgs, constructorName, deployer } = opts; const instance = getContractInstanceFromDeployParams(contractArtifact.artifact, { constructorArgs: initArgs ?? [], constructorArtifact: constructorName, salt, - publicKey, + publicKeysHash, portalAddress, deployer, }); @@ -86,8 +85,8 @@ export class DeployTest { async registerRandomAccount(): Promise { const pxe = this.pxe; - const { completeAddress: owner, privateKey } = CompleteAddress.fromRandomPrivateKey(); - await pxe.registerAccount(privateKey, owner.partialAddress); + const { completeAddress: owner, secretKey } = CompleteAddress.fromRandomSecretKey(); + await pxe.registerAccount(secretKey, owner.partialAddress); return owner.address; } } diff --git a/yarn-project/end-to-end/src/flakey_e2e_deploy_contract/legacy.test.ts b/yarn-project/end-to-end/src/flakey_e2e_deploy_contract/legacy.test.ts index 5bb33ab2cad..ae9e823f52f 100644 --- a/yarn-project/end-to-end/src/flakey_e2e_deploy_contract/legacy.test.ts +++ b/yarn-project/end-to-end/src/flakey_e2e_deploy_contract/legacy.test.ts @@ -34,13 +34,13 @@ describe('e2e_deploy_contract legacy', () => { */ it('should deploy a test contract', async () => { const salt = Fr.random(); - const publicKey = wallet.getCompleteAddress().publicKey; + const publicKeysHash = wallet.getPublicKeysHash(); const deploymentData = getContractInstanceFromDeployParams(TestContractArtifact, { salt, - publicKey, + publicKeysHash, deployer: wallet.getAddress(), }); - const deployer = new ContractDeployer(TestContractArtifact, wallet, publicKey); + const deployer = new ContractDeployer(TestContractArtifact, wallet, publicKeysHash); const receipt = await deployer.deploy().send({ contractAddressSalt: salt }).wait({ wallet }); expect(receipt.contract.address).toEqual(deploymentData.address); expect(await pxe.getContractInstance(deploymentData.address)).toBeDefined(); diff --git a/yarn-project/end-to-end/src/flakey_e2e_p2p_network.test.ts b/yarn-project/end-to-end/src/flakey_e2e_p2p_network.test.ts index 812350b4015..c4d001c06bb 100644 --- a/yarn-project/end-to-end/src/flakey_e2e_p2p_network.test.ts +++ b/yarn-project/end-to-end/src/flakey_e2e_p2p_network.test.ts @@ -5,13 +5,12 @@ import { CompleteAddress, type DebugLogger, Fr, - Grumpkin, GrumpkinScalar, type SentTx, TxStatus, } from '@aztec/aztec.js'; import { BootstrapNode, type P2PConfig, createLibP2PPeerId } from '@aztec/p2p'; -import { ConstantKeyPair, type PXEService, createPXEService, getPXEServiceConfig as getRpcConfig } from '@aztec/pxe'; +import { type PXEService, createPXEService, getPXEServiceConfig as getRpcConfig } from '@aztec/pxe'; import { mnemonicToAccount } from 'viem/accounts'; @@ -121,7 +120,7 @@ describe('e2e_p2p_network', () => { const submitTxsTo = async (pxe: PXEService, account: AztecAddress, numTxs: number) => { const txs: SentTx[] = []; for (let i = 0; i < numTxs; i++) { - const tx = getSchnorrAccount(pxe, GrumpkinScalar.random(), GrumpkinScalar.random(), Fr.random()).deploy(); + const tx = getSchnorrAccount(pxe, Fr.random(), GrumpkinScalar.random(), Fr.random()).deploy(); logger.info(`Tx sent with hash ${await tx.getTxHash()}`); const receipt = await tx.getReceipt(); expect(receipt).toEqual( @@ -144,9 +143,9 @@ describe('e2e_p2p_network', () => { const rpcConfig = getRpcConfig(); const pxeService = await createPXEService(node, rpcConfig, true); - const keyPair = ConstantKeyPair.random(new Grumpkin()); - const completeAddress = CompleteAddress.fromPrivateKeyAndPartialAddress(keyPair.getPrivateKey(), Fr.random()); - await pxeService.registerAccount(keyPair.getPrivateKey(), completeAddress.partialAddress); + const secretKey = Fr.random(); + const completeAddress = CompleteAddress.fromSecretKeyAndPartialAddress(secretKey, Fr.random()); + await pxeService.registerAccount(secretKey, completeAddress.partialAddress); const txs = await submitTxsTo(pxeService, completeAddress.address, numTxs); return { diff --git a/yarn-project/end-to-end/src/guides/writing_an_account_contract.test.ts b/yarn-project/end-to-end/src/guides/writing_an_account_contract.test.ts index 31919be4385..d708dc1fc69 100644 --- a/yarn-project/end-to-end/src/guides/writing_an_account_contract.test.ts +++ b/yarn-project/end-to-end/src/guides/writing_an_account_contract.test.ts @@ -56,8 +56,8 @@ describe('guides/writing_an_account_contract', () => { it('works', async () => { const { pxe, logger } = context; // docs:start:account-contract-deploy - const encryptionPrivateKey = GrumpkinScalar.random(); - const account = new AccountManager(pxe, encryptionPrivateKey, new SchnorrHardcodedKeyAccountContract()); + const secretKey = Fr.random(); + const account = new AccountManager(pxe, secretKey, new SchnorrHardcodedKeyAccountContract()); const wallet = await account.waitSetup(); const address = wallet.getCompleteAddress().address; // docs:end:account-contract-deploy @@ -94,7 +94,7 @@ describe('guides/writing_an_account_contract', () => { // docs:start:account-contract-fails const wrongKey = GrumpkinScalar.random(); const wrongAccountContract = new SchnorrHardcodedKeyAccountContract(wrongKey); - const wrongAccount = new AccountManager(pxe, encryptionPrivateKey, wrongAccountContract, account.salt); + const wrongAccount = new AccountManager(pxe, secretKey, wrongAccountContract, account.salt); const wrongWallet = await wrongAccount.getWallet(); const tokenWithWrongWallet = token.withWallet(wrongWallet); diff --git a/yarn-project/end-to-end/src/shared/browser.ts b/yarn-project/end-to-end/src/shared/browser.ts index 81681ed6c6a..516bd3aa87e 100644 --- a/yarn-project/end-to-end/src/shared/browser.ts +++ b/yarn-project/end-to-end/src/shared/browser.ts @@ -119,11 +119,11 @@ export const browserTestSuite = ( it('Creates an account', async () => { const result = await page.evaluate( - async (rpcUrl, privateKeyString) => { - const { GrumpkinScalar, createPXEClient: createPXEClient, getUnsafeSchnorrAccount } = window.AztecJs; + async (rpcUrl, secretKeyString) => { + const { Fr, createPXEClient, getUnsafeSchnorrAccount } = window.AztecJs; const pxe = createPXEClient(rpcUrl!); - const privateKey = GrumpkinScalar.fromString(privateKeyString); - const account = getUnsafeSchnorrAccount(pxe, privateKey); + const secretKey = Fr.fromString(secretKeyString); + const account = getUnsafeSchnorrAccount(pxe, secretKey); await account.waitSetup(); const completeAddress = account.getCompleteAddress(); const addressString = completeAddress.address.toString(); @@ -190,7 +190,7 @@ export const browserTestSuite = ( getUnsafeSchnorrAccount, } = window.AztecJs; const pxe = createPXEClient(rpcUrl!); - const newReceiverAccount = await getUnsafeSchnorrAccount(pxe, AztecJs.GrumpkinScalar.random()).waitSetup(); + const newReceiverAccount = await getUnsafeSchnorrAccount(pxe, AztecJs.Fr.random()).waitSetup(); const receiverAddress = newReceiverAccount.getCompleteAddress().address; const [wallet] = await getDeployedTestAccountsWallets(pxe); const contract = await Contract.at(AztecAddress.fromString(contractAddress), TokenContractArtifact, wallet); @@ -217,12 +217,13 @@ export const browserTestSuite = ( createPXEClient, getSchnorrAccount, Contract, + deriveKeys, Fr, ExtendedNote, Note, computeMessageSecretHash, getDeployedTestAccountsWallets, - INITIAL_TEST_ENCRYPTION_KEYS, + INITIAL_TEST_SECRET_KEYS, INITIAL_TEST_SIGNING_KEYS, INITIAL_TEST_ACCOUNT_SALTS, Buffer, @@ -239,16 +240,18 @@ export const browserTestSuite = ( if (!knownAccounts.length) { const newAccount = await getSchnorrAccount( pxe, - INITIAL_TEST_ENCRYPTION_KEYS[0], + INITIAL_TEST_SECRET_KEYS[0], INITIAL_TEST_SIGNING_KEYS[0], INITIAL_TEST_ACCOUNT_SALTS[0], ).waitSetup(); knownAccounts.push(newAccount); } const owner = knownAccounts[0]; + // TODO(#5726): this is messy, maybe we should expose publicKeysHash on account + const publicKeysHash = deriveKeys(INITIAL_TEST_SECRET_KEYS[0]).publicKeysHash; const ownerAddress = owner.getAddress(); const tx = new DeployMethod( - owner.getCompleteAddress().publicKey, + publicKeysHash, owner, TokenContractArtifact, (a: AztecJs.AztecAddress) => Contract.at(a, TokenContractArtifact, owner), diff --git a/yarn-project/key-store/src/index.ts b/yarn-project/key-store/src/index.ts index f5449026656..e4ae5ce271c 100644 --- a/yarn-project/key-store/src/index.ts +++ b/yarn-project/key-store/src/index.ts @@ -1,2 +1 @@ -export * from './key_pair.js'; export * from './test_key_store.js'; diff --git a/yarn-project/key-store/src/key_pair.ts b/yarn-project/key-store/src/key_pair.ts deleted file mode 100644 index 0202652cbc0..00000000000 --- a/yarn-project/key-store/src/key_pair.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { type KeyPair, type PublicKey } from '@aztec/circuit-types'; -import { type GrumpkinPrivateKey, GrumpkinScalar } from '@aztec/circuits.js'; -import { type Grumpkin } from '@aztec/circuits.js/barretenberg'; - -/** - * The ConstantKeyPair class is an implementation of the KeyPair interface, which allows generation and management of - * a constant public and private key pair. It provides methods for creating a random instance of the key pair, - * retrieving the public key, getting the private key. This class ensures the persistence and consistency of - * the generated keys, making it suitable for cryptographic operations where constant key pairs are required. - */ -export class ConstantKeyPair implements KeyPair { - /** - * Generate a random ConstantKeyPair instance using the . - * The random private key is generated using 32 random bytes, and the corresponding public key is calculated - * by multiplying the Grumpkin generator point with the private key. This function provides an efficient - * way of generating unique key pairs for cryptographic purposes. - * - * @param curve - The curve used for elliptic curve cryptography operations. - * @returns A randomly generated ConstantKeyPair instance. - */ - public static random(curve: Grumpkin) { - const privateKey = GrumpkinScalar.random(); - const publicKey = curve.mul(curve.generator(), privateKey); - return new ConstantKeyPair(publicKey, privateKey); - } - - /** - * Creates a new instance from a private key. - * @param curve - The curve used for elliptic curve cryptography operations. - * @param signer - The signer to be used on the account. - * @param privateKey - The private key. - * @returns A new instance. - */ - public static fromPrivateKey(curve: Grumpkin, privateKey: GrumpkinPrivateKey) { - const publicKey = curve.mul(curve.generator(), privateKey); - return new ConstantKeyPair(publicKey, privateKey); - } - - constructor(private publicKey: PublicKey, private privateKey: GrumpkinPrivateKey) {} - - public getPublicKey(): PublicKey { - return this.publicKey; - } - - public getPrivateKey(): GrumpkinPrivateKey { - return this.privateKey; - } -} diff --git a/yarn-project/key-store/src/new_test_key_store.ts b/yarn-project/key-store/src/new_test_key_store.ts deleted file mode 100644 index 23d2028c495..00000000000 --- a/yarn-project/key-store/src/new_test_key_store.ts +++ /dev/null @@ -1,245 +0,0 @@ -import { type NewKeyStore, type PublicKey } from '@aztec/circuit-types'; -import { - AztecAddress, - Fr, - GeneratorIndex, - type GrumpkinPrivateKey, - GrumpkinScalar, - type PartialAddress, - Point, -} from '@aztec/circuits.js'; -import { type Grumpkin } from '@aztec/circuits.js/barretenberg'; -import { poseidon2Hash, sha512ToGrumpkinScalar } from '@aztec/foundation/crypto'; -import { type AztecKVStore, type AztecMap } from '@aztec/kv-store'; - -/** - * TestKeyStore is an implementation of the KeyStore interface, used for managing key pairs in a testing environment. - * It should be utilized in testing scenarios where secure key management is not required, and ease-of-use is prioritized. - */ -export class NewTestKeyStore implements NewKeyStore { - #keys: AztecMap; - - constructor(private curve: Grumpkin, database: AztecKVStore) { - this.#keys = database.openMap('key_store'); - } - - /** - * Creates a new account from a randomly generated secret key. - * @returns A promise that resolves to the newly created account's AztecAddress. - */ - public createAccount(): Promise { - const sk = Fr.random(); - const partialAddress = Fr.random(); - return this.addAccount(sk, partialAddress); - } - - /** - * Adds an account to the key store from the provided secret key. - * @param sk - The secret key of the account. - * @param partialAddress - The partial address of the account. - * @returns The account's address. - */ - public async addAccount(sk: Fr, partialAddress: PartialAddress): Promise { - // First we derive master secret keys - we use sha512 here because this derivation will never take place - // in a circuit - const masterNullifierSecretKey = sha512ToGrumpkinScalar([sk, GeneratorIndex.NSK_M]); - const masterIncomingViewingSecretKey = sha512ToGrumpkinScalar([sk, GeneratorIndex.IVSK_M]); - const masterOutgoingViewingSecretKey = sha512ToGrumpkinScalar([sk, GeneratorIndex.OVSK_M]); - const masterTaggingSecretKey = sha512ToGrumpkinScalar([sk, GeneratorIndex.TSK_M]); - - // Then we derive master public keys - const masterNullifierPublicKey = this.curve.mul(this.curve.generator(), masterNullifierSecretKey); - const masterIncomingViewingPublicKey = this.curve.mul(this.curve.generator(), masterIncomingViewingSecretKey); - const masterOutgoingViewingPublicKey = this.curve.mul(this.curve.generator(), masterOutgoingViewingSecretKey); - const masterTaggingPublicKey = this.curve.mul(this.curve.generator(), masterTaggingSecretKey); - - // We hash the public keys to get the public keys hash - const publicKeysHash = poseidon2Hash([ - masterNullifierPublicKey, - masterIncomingViewingPublicKey, - masterOutgoingViewingPublicKey, - masterTaggingPublicKey, - GeneratorIndex.PUBLIC_KEYS_HASH, - ]); - - // We hash the partial address and the public keys hash to get the account address - // TODO(#5726): Should GeneratorIndex.CONTRACT_ADDRESS be removed given that we introduced CONTRACT_ADDRESS_V1? - // TODO(#5726): Move the following line to AztecAddress class? - const accountAddressFr = poseidon2Hash([partialAddress, publicKeysHash, GeneratorIndex.CONTRACT_ADDRESS_V1]); - const accountAddress = AztecAddress.fromField(accountAddressFr); - - // We store all the public and secret keys in the database - await this.#keys.set(`${accountAddress.toString()}-nsk_m`, masterNullifierSecretKey.toBuffer()); - await this.#keys.set(`${accountAddress.toString()}-ivsk_m`, masterIncomingViewingSecretKey.toBuffer()); - await this.#keys.set(`${accountAddress.toString()}-ovsk_m`, masterOutgoingViewingSecretKey.toBuffer()); - await this.#keys.set(`${accountAddress.toString()}-tsk_m`, masterTaggingSecretKey.toBuffer()); - - await this.#keys.set(`${accountAddress.toString()}-npk_m`, masterNullifierPublicKey.toBuffer()); - await this.#keys.set(`${accountAddress.toString()}-ivpk_m`, masterIncomingViewingPublicKey.toBuffer()); - await this.#keys.set(`${accountAddress.toString()}-ovpk_m`, masterOutgoingViewingPublicKey.toBuffer()); - await this.#keys.set(`${accountAddress.toString()}-tpk_m`, masterTaggingPublicKey.toBuffer()); - - // At last, we return the newly derived account address - return Promise.resolve(accountAddress); - } - - /** - * Retrieves addresses of accounts stored in the key store. - * @returns A Promise that resolves to an array of account addresses. - */ - public getAccounts(): Promise { - const allMapKeys = Array.from(this.#keys.keys()); - // We return account addresses based on the map keys that end with '-nsk_m' - const accounts = allMapKeys.filter(key => key.endsWith('-nsk_m')).map(key => key.split('-')[0]); - return Promise.resolve(accounts.map(account => AztecAddress.fromString(account))); - } - - /** - * Gets the master nullifier public key for a given account. - * @throws If the account does not exist in the key store. - * @param account - The account address for which to retrieve the master nullifier public key. - * @returns The master nullifier public key for the account. - */ - public getMasterNullifierPublicKey(account: AztecAddress): Promise { - const masterNullifierPublicKeyBuffer = this.#keys.get(`${account.toString()}-npk_m`); - if (!masterNullifierPublicKeyBuffer) { - throw new Error(`Account ${account.toString()} does not exist.`); - } - return Promise.resolve(Point.fromBuffer(masterNullifierPublicKeyBuffer)); - } - - /** - * Gets the master incoming viewing public key for a given account. - * @throws If the account does not exist in the key store. - * @param account - The account address for which to retrieve the master incoming viewing public key. - * @returns The master incoming viewing public key for the account. - */ - public getMasterIncomingViewingPublicKey(account: AztecAddress): Promise { - const masterIncomingViewingPublicKeyBuffer = this.#keys.get(`${account.toString()}-ivpk_m`); - if (!masterIncomingViewingPublicKeyBuffer) { - throw new Error(`Account ${account.toString()} does not exist.`); - } - return Promise.resolve(Point.fromBuffer(masterIncomingViewingPublicKeyBuffer)); - } - - /** - * Retrieves the master outgoing viewing public key. - * @throws If the account does not exist in the key store. - * @param account - The account to retrieve the master outgoing viewing key for. - * @returns A Promise that resolves to the master outgoing viewing key. - */ - public getMasterOutgoingViewingPublicKey(account: AztecAddress): Promise { - const masterOutgoingViewingPublicKeyBuffer = this.#keys.get(`${account.toString()}-ovpk_m`); - if (!masterOutgoingViewingPublicKeyBuffer) { - throw new Error(`Account ${account.toString()} does not exist.`); - } - return Promise.resolve(Point.fromBuffer(masterOutgoingViewingPublicKeyBuffer)); - } - - /** - * Retrieves the master tagging public key. - * @throws If the account does not exist in the key store. - * @param account - The account to retrieve the master tagging key for. - * @returns A Promise that resolves to the master tagging key. - */ - public getMasterTaggingPublicKey(account: AztecAddress): Promise { - const masterTaggingPublicKeyBuffer = this.#keys.get(`${account.toString()}-tpk_m`); - if (!masterTaggingPublicKeyBuffer) { - throw new Error(`Account ${account.toString()} does not exist.`); - } - return Promise.resolve(Point.fromBuffer(masterTaggingPublicKeyBuffer)); - } - - /** - * Retrieves application nullifier secret key. - * @throws If the account does not exist in the key store. - * @param account - The account to retrieve the application nullifier secret key for. - * @param app - The application address to retrieve the nullifier secret key for. - * @returns A Promise that resolves to the application nullifier secret key. - */ - public getAppNullifierSecretKey(account: AztecAddress, app: AztecAddress): Promise { - const masterNullifierSecretKeyBuffer = this.#keys.get(`${account.toString()}-nsk_m`); - if (!masterNullifierSecretKeyBuffer) { - throw new Error(`Account ${account.toString()} does not exist.`); - } - const masterNullifierSecretKey = GrumpkinScalar.fromBuffer(masterNullifierSecretKeyBuffer); - - return Promise.resolve( - poseidon2Hash([masterNullifierSecretKey.high, masterNullifierSecretKey.low, app, GeneratorIndex.NSK_M]), - ); - } - - /** - * Retrieves application incoming viewing secret key. - * @throws If the account does not exist in the key store. - * @param account - The account to retrieve the application incoming viewing secret key for. - * @param app - The application address to retrieve the incoming viewing secret key for. - * @returns A Promise that resolves to the application incoming viewing secret key. - */ - public getAppIncomingViewingSecretKey(account: AztecAddress, app: AztecAddress): Promise { - const masterIncomingViewingSecretKeyBuffer = this.#keys.get(`${account.toString()}-ivsk_m`); - if (!masterIncomingViewingSecretKeyBuffer) { - throw new Error(`Account ${account.toString()} does not exist.`); - } - const masterIncomingViewingSecretKey = GrumpkinScalar.fromBuffer(masterIncomingViewingSecretKeyBuffer); - - return Promise.resolve( - poseidon2Hash([ - masterIncomingViewingSecretKey.high, - masterIncomingViewingSecretKey.low, - app, - GeneratorIndex.IVSK_M, - ]), - ); - } - - /** - * Retrieves application outgoing viewing secret key. - * @throws If the account does not exist in the key store. - * @param account - The account to retrieve the application outgoing viewing secret key for. - * @param app - The application address to retrieve the outgoing viewing secret key for. - * @returns A Promise that resolves to the application outgoing viewing secret key. - */ - public getAppOutgoingViewingSecretKey(account: AztecAddress, app: AztecAddress): Promise { - const masterOutgoingViewingSecretKeyBuffer = this.#keys.get(`${account.toString()}-ovsk_m`); - if (!masterOutgoingViewingSecretKeyBuffer) { - throw new Error(`Account ${account.toString()} does not exist.`); - } - const masterOutgoingViewingSecretKey = GrumpkinScalar.fromBuffer(masterOutgoingViewingSecretKeyBuffer); - - return Promise.resolve( - poseidon2Hash([ - masterOutgoingViewingSecretKey.high, - masterOutgoingViewingSecretKey.low, - app, - GeneratorIndex.OVSK_M, - ]), - ); - } - - /** - * Retrieves the master nullifier secret key (nsk_m) corresponding to the specified master nullifier public key - * (Npk_m). - * @throws If the provided public key is not associated with any of the registered accounts. - * @param masterNullifierPublicKey - The master nullifier public key to get secret key for. - * @returns A Promise that resolves to the master nullifier secret key. - * @dev Used when feeding the master nullifier secret key to the kernel circuit for nullifier keys verification. - */ - public getMasterNullifierSecretKeyForPublicKey(masterNullifierPublicKey: PublicKey): Promise { - // We iterate over the map keys to find the account address that corresponds to the provided public key - for (const [key, value] of this.#keys.entries()) { - if (value.equals(masterNullifierPublicKey.toBuffer())) { - // We extract the account address from the map key - const accountAddress = key.split('-')[0]; - // We fetch the secret key and return it - const masterNullifierSecretKeyBuffer = this.#keys.get(`${accountAddress.toString()}-nsk_m`); - if (!masterNullifierSecretKeyBuffer) { - throw new Error(`Could not find master nullifier secret key for account ${accountAddress.toString()}`); - } - return Promise.resolve(GrumpkinScalar.fromBuffer(masterNullifierSecretKeyBuffer)); - } - } - - throw new Error(`Could not find master nullifier secret key for public key ${masterNullifierPublicKey.toString()}`); - } -} diff --git a/yarn-project/key-store/src/new_test_key_store.test.ts b/yarn-project/key-store/src/test_key_store.test.ts similarity index 85% rename from yarn-project/key-store/src/new_test_key_store.test.ts rename to yarn-project/key-store/src/test_key_store.test.ts index c67347242a8..61647e0097c 100644 --- a/yarn-project/key-store/src/new_test_key_store.test.ts +++ b/yarn-project/key-store/src/test_key_store.test.ts @@ -1,13 +1,11 @@ import { AztecAddress, Fr } from '@aztec/circuits.js'; -import { Grumpkin } from '@aztec/circuits.js/barretenberg'; import { openTmpStore } from '@aztec/kv-store/utils'; -import { NewTestKeyStore } from './new_test_key_store.js'; +import { TestKeyStore } from './test_key_store.js'; -describe('NewTestKeyStore', () => { +describe('TestKeyStore', () => { it('Adds account and returns keys', async () => { - const db = openTmpStore(); - const keyStore = new NewTestKeyStore(new Grumpkin(), db); + const keyStore = new TestKeyStore(openTmpStore()); // Arbitrary fixed values const sk = new Fr(8923n); @@ -15,7 +13,7 @@ describe('NewTestKeyStore', () => { const accountAddress = await keyStore.addAccount(sk, partialAddress); expect(accountAddress.toString()).toMatchInlineSnapshot( - `"0x0ba7834252d19c4f09d29303c269f303f40ae3d2043f921ed0bf8c0709926d4e"`, + `"0x1a8a9a1d91cbb353d8df4f1bbfd0283f7fc63766f671edd9443a1270a7b2a954"`, ); const masterNullifierPublicKey = await keyStore.getMasterNullifierPublicKey(accountAddress); @@ -38,6 +36,11 @@ describe('NewTestKeyStore', () => { `"0x076429010fdebfa522b053267f654a4c5daf18589915d96f7e5001d63ea2033f27f915f254560c84450aa38e93c3162be52492d05b316e75f542e3b302117360"`, ); + const publicKeysHash = await keyStore.getPublicKeysHash(accountAddress); + expect(publicKeysHash.toString()).toMatchInlineSnapshot( + `"0x1ba15945655812587b5c16a6a8125193c901c2c31a4ac4edaed202726c0d4c89"`, + ); + // Arbitrary app contract address const appAddress = AztecAddress.fromBigInt(624n); @@ -59,7 +62,7 @@ describe('NewTestKeyStore', () => { // Returned accounts are as expected const accounts = await keyStore.getAccounts(); expect(accounts.toString()).toMatchInlineSnapshot( - `"0x0ba7834252d19c4f09d29303c269f303f40ae3d2043f921ed0bf8c0709926d4e"`, + `"0x1a8a9a1d91cbb353d8df4f1bbfd0283f7fc63766f671edd9443a1270a7b2a954"`, ); // Manages to find master nullifer secret key for pub key diff --git a/yarn-project/key-store/src/test_key_store.ts b/yarn-project/key-store/src/test_key_store.ts index 4af7e2c2dfa..c2755aecf0e 100644 --- a/yarn-project/key-store/src/test_key_store.ts +++ b/yarn-project/key-store/src/test_key_store.ts @@ -1,96 +1,295 @@ -import { type KeyPair, type KeyStore, type PublicKey } from '@aztec/circuit-types'; +import { type KeyStore, type PublicKey } from '@aztec/circuit-types'; import { - type AztecAddress, + AztecAddress, + Fr, + GeneratorIndex, type GrumpkinPrivateKey, GrumpkinScalar, + type PartialAddress, Point, - computeNullifierSecretKey, - computeSiloedNullifierSecretKey, - derivePublicKey, + computeAppNullifierSecretKey, + deriveKeys, } from '@aztec/circuits.js'; -import { type Grumpkin } from '@aztec/circuits.js/barretenberg'; +import { poseidon2Hash } from '@aztec/foundation/crypto'; import { type AztecKVStore, type AztecMap } from '@aztec/kv-store'; -import { ConstantKeyPair } from './key_pair.js'; - /** * TestKeyStore is an implementation of the KeyStore interface, used for managing key pairs in a testing environment. * It should be utilized in testing scenarios where secure key management is not required, and ease-of-use is prioritized. - * TODO(#5627): 💣💣💣 */ export class TestKeyStore implements KeyStore { #keys: AztecMap; - constructor(private curve: Grumpkin, database: AztecKVStore) { + constructor(database: AztecKVStore) { this.#keys = database.openMap('key_store'); } - public async addAccount(privKey: GrumpkinPrivateKey): Promise { - const keyPair = ConstantKeyPair.fromPrivateKey(this.curve, privKey); - await this.#keys.setIfNotExists(keyPair.getPublicKey().toString(), keyPair.getPrivateKey().toBuffer()); - return keyPair.getPublicKey(); + /** + * Creates a new account from a randomly generated secret key. + * @returns A promise that resolves to the newly created account's AztecAddress. + */ + public createAccount(): Promise { + const sk = Fr.random(); + const partialAddress = Fr.random(); + return this.addAccount(sk, partialAddress); } - public async createAccount(): Promise { - const keyPair = ConstantKeyPair.random(this.curve); - await this.#keys.set(keyPair.getPublicKey().toString(), keyPair.getPrivateKey().toBuffer()); - return keyPair.getPublicKey(); + /** + * Adds an account to the key store from the provided secret key. + * @param sk - The secret key of the account. + * @param partialAddress - The partial address of the account. + * @returns The account's address. + */ + public async addAccount(sk: Fr, partialAddress: PartialAddress): Promise { + const { + publicKeysHash, + masterNullifierSecretKey, + masterIncomingViewingSecretKey, + masterOutgoingViewingSecretKey, + masterTaggingSecretKey, + masterNullifierPublicKey, + masterIncomingViewingPublicKey, + masterOutgoingViewingPublicKey, + masterTaggingPublicKey, + } = deriveKeys(sk); + + // We hash the partial address and the public keys hash to get the account address + // TODO(#5726): Move the following line to AztecAddress class? + const accountAddressFr = poseidon2Hash([publicKeysHash, partialAddress, GeneratorIndex.CONTRACT_ADDRESS_V1]); + const accountAddress = AztecAddress.fromField(accountAddressFr); + + // We save the keys to db + await this.#keys.set(`${accountAddress.toString()}-public_keys_hash`, publicKeysHash.toBuffer()); + + await this.#keys.set(`${accountAddress.toString()}-nsk_m`, masterNullifierSecretKey.toBuffer()); + await this.#keys.set(`${accountAddress.toString()}-ivsk_m`, masterIncomingViewingSecretKey.toBuffer()); + await this.#keys.set(`${accountAddress.toString()}-ovsk_m`, masterOutgoingViewingSecretKey.toBuffer()); + await this.#keys.set(`${accountAddress.toString()}-tsk_m`, masterTaggingSecretKey.toBuffer()); + + await this.#keys.set(`${accountAddress.toString()}-npk_m`, masterNullifierPublicKey.toBuffer()); + await this.#keys.set(`${accountAddress.toString()}-ivpk_m`, masterIncomingViewingPublicKey.toBuffer()); + await this.#keys.set(`${accountAddress.toString()}-ovpk_m`, masterOutgoingViewingPublicKey.toBuffer()); + await this.#keys.set(`${accountAddress.toString()}-tpk_m`, masterTaggingPublicKey.toBuffer()); + + // At last, we return the newly derived account address + return Promise.resolve(accountAddress); } - public getAccounts(): Promise { - const range = Array.from(this.#keys.keys()); - return Promise.resolve(range.map(key => Point.fromString(key))); + /** + * Retrieves addresses of accounts stored in the key store. + * @returns A Promise that resolves to an array of account addresses. + */ + public getAccounts(): Promise { + const allMapKeys = Array.from(this.#keys.keys()); + // We return account addresses based on the map keys that end with '-nsk_m' + const accounts = allMapKeys.filter(key => key.endsWith('-nsk_m')).map(key => key.split('-')[0]); + return Promise.resolve(accounts.map(account => AztecAddress.fromString(account))); } - public getAccountPrivateKey(pubKey: PublicKey): Promise { - const account = this.getAccount(pubKey); - return Promise.resolve(account.getPrivateKey()); + /** + * Gets the master nullifier public key for a given account. + * @throws If the account does not exist in the key store. + * @param account - The account address for which to retrieve the master nullifier public key. + * @returns The master nullifier public key for the account. + */ + public async getMasterNullifierPublicKey(account: AztecAddress): Promise { + const masterNullifierPublicKeyBuffer = this.#keys.get(`${account.toString()}-npk_m`); + if (!masterNullifierPublicKeyBuffer) { + throw new Error( + `Account ${account.toString()} does not exist. Registered accounts: ${await this.getAccounts()}.`, + ); + } + return Promise.resolve(Point.fromBuffer(masterNullifierPublicKeyBuffer)); } - public async getNullifierSecretKey(pubKey: PublicKey) { - const privateKey = await this.getAccountPrivateKey(pubKey); - return computeNullifierSecretKey(privateKey); + /** + * Gets the master incoming viewing public key for a given account. + * @throws If the account does not exist in the key store. + * @param account - The account address for which to retrieve the master incoming viewing public key. + * @returns The master incoming viewing public key for the account. + */ + public async getMasterIncomingViewingPublicKey(account: AztecAddress): Promise { + const masterIncomingViewingPublicKeyBuffer = this.#keys.get(`${account.toString()}-ivpk_m`); + if (!masterIncomingViewingPublicKeyBuffer) { + throw new Error( + `Account ${account.toString()} does not exist. Registered accounts: ${await this.getAccounts()}.`, + ); + } + return Promise.resolve(Point.fromBuffer(masterIncomingViewingPublicKeyBuffer)); } - public async getNullifierSecretKeyFromPublicKey(nullifierPubKey: PublicKey) { - const accounts = await this.getAccounts(); - for (let i = 0; i < accounts.length; ++i) { - const accountPublicKey = accounts[i]; - const privateKey = await this.getAccountPrivateKey(accountPublicKey); - const secretKey = computeNullifierSecretKey(privateKey); - const publicKey = derivePublicKey(secretKey); - if (publicKey.equals(nullifierPubKey)) { - return secretKey; - } + /** + * Retrieves the master outgoing viewing public key. + * @throws If the account does not exist in the key store. + * @param account - The account to retrieve the master outgoing viewing key for. + * @returns A Promise that resolves to the master outgoing viewing key. + */ + public async getMasterOutgoingViewingPublicKey(account: AztecAddress): Promise { + const masterOutgoingViewingPublicKeyBuffer = this.#keys.get(`${account.toString()}-ovpk_m`); + if (!masterOutgoingViewingPublicKeyBuffer) { + throw new Error( + `Account ${account.toString()} does not exist. Registered accounts: ${await this.getAccounts()}.`, + ); } - throw new Error('Unknown nullifier public key.'); + return Promise.resolve(Point.fromBuffer(masterOutgoingViewingPublicKeyBuffer)); } - public async getNullifierPublicKey(pubKey: PublicKey) { - const secretKey = await this.getNullifierSecretKey(pubKey); - return derivePublicKey(secretKey); + /** + * Retrieves the master tagging public key. + * @throws If the account does not exist in the key store. + * @param account - The account to retrieve the master tagging key for. + * @returns A Promise that resolves to the master tagging key. + */ + public async getMasterTaggingPublicKey(account: AztecAddress): Promise { + const masterTaggingPublicKeyBuffer = this.#keys.get(`${account.toString()}-tpk_m`); + if (!masterTaggingPublicKeyBuffer) { + throw new Error( + `Account ${account.toString()} does not exist. Registered accounts: ${await this.getAccounts()}.`, + ); + } + return Promise.resolve(Point.fromBuffer(masterTaggingPublicKeyBuffer)); } - public async getSiloedNullifierSecretKey(pubKey: PublicKey, contractAddress: AztecAddress) { - const secretKey = await this.getNullifierSecretKey(pubKey); - return computeSiloedNullifierSecretKey(secretKey, contractAddress); + /** + * Retrieves application nullifier secret key. + * @throws If the account does not exist in the key store. + * @param account - The account to retrieve the application nullifier secret key for. + * @param app - The application address to retrieve the nullifier secret key for. + * @returns A Promise that resolves to the application nullifier secret key. + */ + public async getAppNullifierSecretKey(account: AztecAddress, app: AztecAddress): Promise { + const masterNullifierSecretKeyBuffer = this.#keys.get(`${account.toString()}-nsk_m`); + if (!masterNullifierSecretKeyBuffer) { + throw new Error( + `Account ${account.toString()} does not exist. Registered accounts: ${await this.getAccounts()}.`, + ); + } + const masterNullifierSecretKey = GrumpkinScalar.fromBuffer(masterNullifierSecretKeyBuffer); + const appNullifierSecretKey = computeAppNullifierSecretKey(masterNullifierSecretKey, app); + return Promise.resolve(appNullifierSecretKey); + } + + /** + * Retrieves application incoming viewing secret key. + * @throws If the account does not exist in the key store. + * @param account - The account to retrieve the application incoming viewing secret key for. + * @param app - The application address to retrieve the incoming viewing secret key for. + * @returns A Promise that resolves to the application incoming viewing secret key. + */ + public async getAppIncomingViewingSecretKey(account: AztecAddress, app: AztecAddress): Promise { + const masterIncomingViewingSecretKeyBuffer = this.#keys.get(`${account.toString()}-ivsk_m`); + if (!masterIncomingViewingSecretKeyBuffer) { + throw new Error( + `Account ${account.toString()} does not exist. Registered accounts: ${await this.getAccounts()}.`, + ); + } + const masterIncomingViewingSecretKey = GrumpkinScalar.fromBuffer(masterIncomingViewingSecretKeyBuffer); + + return Promise.resolve( + poseidon2Hash([ + masterIncomingViewingSecretKey.high, + masterIncomingViewingSecretKey.low, + app, + GeneratorIndex.IVSK_M, + ]), + ); + } + + /** + * Retrieves application outgoing viewing secret key. + * @throws If the account does not exist in the key store. + * @param account - The account to retrieve the application outgoing viewing secret key for. + * @param app - The application address to retrieve the outgoing viewing secret key for. + * @returns A Promise that resolves to the application outgoing viewing secret key. + */ + public async getAppOutgoingViewingSecretKey(account: AztecAddress, app: AztecAddress): Promise { + const masterOutgoingViewingSecretKeyBuffer = this.#keys.get(`${account.toString()}-ovsk_m`); + if (!masterOutgoingViewingSecretKeyBuffer) { + throw new Error( + `Account ${account.toString()} does not exist. Registered accounts: ${await this.getAccounts()}.`, + ); + } + const masterOutgoingViewingSecretKey = GrumpkinScalar.fromBuffer(masterOutgoingViewingSecretKeyBuffer); + + return Promise.resolve( + poseidon2Hash([ + masterOutgoingViewingSecretKey.high, + masterOutgoingViewingSecretKey.low, + app, + GeneratorIndex.OVSK_M, + ]), + ); + } + + /** + * Retrieves the master nullifier secret key (nsk_m) corresponding to the specified master nullifier public key + * (Npk_m). + * @throws If the provided public key is not associated with any of the registered accounts. + * @param masterNullifierPublicKey - The master nullifier public key to get secret key for. + * @returns A Promise that resolves to the master nullifier secret key. + * @dev Used when feeding the master nullifier secret key to the kernel circuit for nullifier keys verification. + */ + public getMasterNullifierSecretKeyForPublicKey(masterNullifierPublicKey: PublicKey): Promise { + // We iterate over the map keys to find the account address that corresponds to the provided public key + for (const [key, value] of this.#keys.entries()) { + if (value.equals(masterNullifierPublicKey.toBuffer())) { + // We extract the account address from the map key + const accountAddress = key.split('-')[0]; + // We fetch the secret key and return it + const masterNullifierSecretKeyBuffer = this.#keys.get(`${accountAddress.toString()}-nsk_m`); + if (!masterNullifierSecretKeyBuffer) { + throw new Error(`Could not find master nullifier secret key for account ${accountAddress.toString()}`); + } + return Promise.resolve(GrumpkinScalar.fromBuffer(masterNullifierSecretKeyBuffer)); + } + } + + throw new Error(`Could not find master nullifier secret key for public key ${masterNullifierPublicKey.toString()}`); + } + + /** + * Retrieves the master incoming viewing secret key (ivsk_m) corresponding to the specified master incoming viewing + * public key (Ivpk_m). + * @throws If the provided public key is not associated with any of the registered accounts. + * @param masterIncomingViewingPublicKey - The master nullifier public key to get secret key for. + * @returns A Promise that resolves to the master nullifier secret key. + * @dev Used when feeding the master nullifier secret key to the kernel circuit for nullifier keys verification. + */ + public getMasterIncomingViewingSecretKeyForPublicKey( + masterIncomingViewingPublicKey: PublicKey, + ): Promise { + // We iterate over the map keys to find the account address that corresponds to the provided public key + for (const [key, value] of this.#keys.entries()) { + if (value.equals(masterIncomingViewingPublicKey.toBuffer())) { + // We extract the account address from the map key + const accountAddress = key.split('-')[0]; + // We fetch the secret key and return it + const masterIncomingViewingSecretKeyBuffer = this.#keys.get(`${accountAddress.toString()}-ivsk_m`); + if (!masterIncomingViewingSecretKeyBuffer) { + throw new Error(`Could not find master incoming viewing secret key for account ${accountAddress.toString()}`); + } + return Promise.resolve(GrumpkinScalar.fromBuffer(masterIncomingViewingSecretKeyBuffer)); + } + } + + throw new Error( + `Could not find master incoming viewing secret key for public key ${masterIncomingViewingPublicKey.toString()}`, + ); } /** - * Retrieve the KeyPair object associated with a given pub key. - * Searches through the 'accounts' array for a matching public key and returns the corresponding account (KeyPair). - * Throws an error if no matching account is found in the 'accounts'. - * - * @param pubKey - The public key of the account to retrieve. - * @returns The KeyPair object associated with the provided key. + * Retrieves public keys hash of the account + * @throws If the provided account address is not associated with any of the registered accounts. + * @param account - The account address to get public keys hash for. + * @returns A Promise that resolves to the public keys hash. */ - private getAccount(pubKey: PublicKey): KeyPair { - const privKey = this.#keys.get(pubKey.toString()); - if (!privKey) { + public async getPublicKeysHash(account: AztecAddress): Promise { + const publicKeysHashBuffer = this.#keys.get(`${account.toString()}-public_keys_hash`); + if (!publicKeysHashBuffer) { throw new Error( - 'Unknown account.\nSee docs for context: https://docs.aztec.network/developers/debugging/aztecnr-errors#could-not-process-note-because-of-error-unknown-account-skipping-note', + `Account ${account.toString()} does not exist. Registered accounts: ${await this.getAccounts()}.`, ); } - return ConstantKeyPair.fromPrivateKey(this.curve, GrumpkinScalar.fromBuffer(privKey)); + return Promise.resolve(Fr.fromBuffer(publicKeysHashBuffer)); } } diff --git a/yarn-project/noir-compiler/src/contract-interface-gen/typescript.ts b/yarn-project/noir-compiler/src/contract-interface-gen/typescript.ts index 04f1af32ed4..b86a32dcbdb 100644 --- a/yarn-project/noir-compiler/src/contract-interface-gen/typescript.ts +++ b/yarn-project/noir-compiler/src/contract-interface-gen/typescript.ts @@ -89,25 +89,25 @@ function generateDeploy(input: ContractArtifact) { * Creates a tx to deploy a new instance of this contract. */ public static deploy(wallet: Wallet, ${args}) { - return new DeployMethod<${contractName}>(Point.ZERO, wallet, ${artifactName}, ${contractName}.at, Array.from(arguments).slice(1)); + return new DeployMethod<${contractName}>(Fr.ZERO, wallet, ${artifactName}, ${contractName}.at, Array.from(arguments).slice(1)); } /** - * Creates a tx to deploy a new instance of this contract using the specified public key to derive the address. + * Creates a tx to deploy a new instance of this contract using the specified public keys hash to derive the address. */ - public static deployWithPublicKey(publicKey: PublicKey, wallet: Wallet, ${args}) { - return new DeployMethod<${contractName}>(publicKey, wallet, ${artifactName}, ${contractName}.at, Array.from(arguments).slice(2)); + public static deployWithPublicKeysHash(publicKeysHash: Fr, wallet: Wallet, ${args}) { + return new DeployMethod<${contractName}>(publicKeysHash, wallet, ${artifactName}, ${contractName}.at, Array.from(arguments).slice(2)); } /** * Creates a tx to deploy a new instance of this contract using the specified constructor method. */ public static deployWithOpts( - opts: { publicKey?: PublicKey; method?: M; wallet: Wallet }, + opts: { publicKeysHash?: Fr; method?: M; wallet: Wallet }, ...args: Parameters<${contractName}['methods'][M]> ) { return new DeployMethod<${contractName}>( - opts.publicKey ?? Point.ZERO, + opts.publicKeysHash ?? Fr.ZERO, opts.wallet, ${artifactName}, ${contractName}.at, diff --git a/yarn-project/noir-protocol-circuits-types/src/__snapshots__/noir_test_gen.test.ts.snap b/yarn-project/noir-protocol-circuits-types/src/__snapshots__/noir_test_gen.test.ts.snap index cd7b3714098..f2476be262e 100644 --- a/yarn-project/noir-protocol-circuits-types/src/__snapshots__/noir_test_gen.test.ts.snap +++ b/yarn-project/noir-protocol-circuits-types/src/__snapshots__/noir_test_gen.test.ts.snap @@ -4366,7 +4366,7 @@ exports[`Data generation for noir tests Computes contract info for defaultContra artifact_hash: 0x0000000000000000000000000000000000000000000000000000000000003039, public_bytecode_commitment: 0x129a3438653fe147133b2c274757920e37896305e7664c8c1eb380be3efd5fed, private_functions_root: 0x19a3cc0b714976fb35d58b684ba36e86f82bac8b87517904a2727e5113fb4cba, - address: AztecAddress { inner: 0x17f7ff235e2548b437b7ef33cdf96c99346753b27d22787c1aa5287cdbad39ee }, + address: AztecAddress { inner: 0x2d941148ee5adeece35991d32acbcf4200742991c61990dee965bedf729d21a9 }, partial_address: PartialAddress { inner: 0x23a6933a485200a8d34b9929d61868c9635793f878d67ce86a1b1355c0ab0d47 }, portal_contract_address: EthAddress { inner: 0x0000000000000000000000000000000000005ba0 }, contract_class_id: ContractClassId { inner: 0x0ce2a998337b1e6da1ac1d802a8bb9e10b7d705d210e61efb9642855009814a6 }, @@ -4382,7 +4382,7 @@ exports[`Data generation for noir tests Computes contract info for parentContrac artifact_hash: 0x00000000000000000000000000000000000000000000000000000000000004bc, public_bytecode_commitment: 0x1435ed970b275bebf95de3df53f23f3d2e97c9b54cf442bb03a3fa17a0ee3cd7, private_functions_root: 0x2c1c949cb226995de94b7b8b5aeaab440739f2dfeb06d358441f60932cf243a7, - address: AztecAddress { inner: 0x1a20abed0eeb77fbcf0dd6ba6e9d9fd18b649277b9aea88014e1e9e39646b1b3 }, + address: AztecAddress { inner: 0x24692d7dbb532557c7466e8782d1fe99077e4787570414bd1a5e8fa5300caad8 }, partial_address: PartialAddress { inner: 0x127bbd73a3cf497fb2d85342571695d894985b449a9343eec55485e9cbc514f8 }, portal_contract_address: EthAddress { inner: 0x0000000000000000000000000000000000000913 }, contract_class_id: ContractClassId { inner: 0x1f1f963a350e2c883cc6730c19fc5d5b47a40694d805cbb0720fa76fe295df90 }, diff --git a/yarn-project/noir-protocol-circuits-types/src/fixtures/nested-call-private-kernel-init.hex b/yarn-project/noir-protocol-circuits-types/src/fixtures/nested-call-private-kernel-init.hex index 35212bb487c..77e9dca1224 100644 --- a/yarn-project/noir-protocol-circuits-types/src/fixtures/nested-call-private-kernel-init.hex +++ b/yarn-project/noir-protocol-circuits-types/src/fixtures/nested-call-private-kernel-init.hex @@ -1 +1 @@ -1166f8313bdcd368a148663939fd38eb6a6500a577435b5a433ff0357ca8b15937889ba10104fe385bb1c80a41d917a6f6061312dc211638616c9da820eb5bca522bc8996500000000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000013b9aca0005f5e10000000000000000000000000000000000000000000000000000000000000000013b9aca0005f5e10000000000000000000000000000000000000000000000000000000000000000013b9aca0005f5e100000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000011166f8313bdcd368a148663939fd38eb6a6500a577435b5a433ff0357ca8b15937889ba10100000000000000000000000000000000000000000000000000000000000000001166f8313bdcd368a148663939fd38eb6a6500a577435b5a433ff0357ca8b159000000000000000000000000000000000000000037889ba135a4e90035a4e90035a4e9000000000000013b9aca0005f5e10000000000000000000000000000000000000000000000000000000000000000013b9aca0005f5e10000000000000000000000000000000000000000000000000000000000000000013b9aca0005f5e10000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000004fe385bb1c80a41d917a6f6061312dc211638616c9da820eb5bca522bc89965000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001019e4c3aa9b03aa5bf974d1954b5e219db2b0e1d42a4ed9f095c102eb2157d7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000000016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000000000bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278000000800572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000011019e4c3aa9b03aa5bf974d1954b5e219db2b0e1d42a4ed9f095c102eb2157d71166f8313bdcd368a148663939fd38eb6a6500a577435b5a433ff0357ca8b15900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000800000000740000000f00000003515f3109623eb3c25aa5b16a1a79fd558bac7a7ce62c4560a8c537c77ce80dd339128d1d37b6582ee9e6df9567efb64313471dfa18f520f9ce53161b50dbf7731bc5f900000003515f322bc4cce83a486a92c92fd59bd84e0f92595baa639fc2ed86b00ffa0dfded2a092a669a3bdb7a273a015eda494457cc7ed5236f26cee330c290d45a33b9daa94800000003515f332729426c008c085a81bd34d8ef12dd31e80130339ef99d50013a89e4558eee6d0fa4ffe2ee7b7b62eb92608b2251ac31396a718f9b34978888789042b790a30100000003515f342be6b6824a913eb7a57b03cb1ee7bfb4de02f2f65fe8a4e97baa7766ddb353a82a8a25c49dc63778cd9fe96173f12a2bc77f3682f4c4448f98f1df82c75234a100000003515f351f85760d6ab567465aadc2f180af9eae3800e6958fec96aef53fd8a7b195d7c000c6267a0dd5cfc22b3fe804f53e266069c0e36f51885baec1e7e67650c62e170000000c515f41524954484d455449430d9d0f8ece2aa12012fa21e6e5c859e97bd5704e5c122064a66051294bc5e04213f61f54a0ebdf6fee4d4a6ecf693478191de0c2899bcd8e86a636c8d3eff43400000003515f43224a99d02c86336737c8dd5b746c40d2be6aead8393889a76a18d664029096e90f7fe81adcc92a74350eada9622ac453f49ebac24a066a1f83b394df54dfa0130000000c515f46495845445f42415345060e8a013ed289c2f9fd7473b04f6594b138ddb4b4cf6b901622a14088f04b8d2c83ff74fce56e3d5573b99c7b26d85d5046ce0c6559506acb7a675e7713eb3a00000007515f4c4f4749430721a91cb8da4b917e054f72147e1760cfe0ef3d45090ac0f4961d84ec1996961a25e787b26bd8b50b1a99450f77a424a83513c2b33af268cd253b0587ff50c700000003515f4d05dbd8623b8652511e1eb38d38887a69eceb082f807514f09e127237c5213b401b9325b48c6c225968002318095f89d0ef9cf629b2b7f0172e03bc39aacf6ed800000007515f52414e474504b57a3805e41df328f5ca9aefa40fad5917391543b7b65c6476e60b8f72e9ad07c92f3b3e11c8feae96dedc4b14a6226ef3201244f37cfc1ee5b96781f48d2b000000075349474d415f3125001d1954a18571eaa007144c5a567bb0d2be4def08a8be918b8c05e3b27d312c59ed41e09e144eab5de77ca89a2fd783be702a47c951d3112e3de02ce6e47c000000075349474d415f3223994e6a23618e60fa01c449a7ab88378709197e186d48d604bfb6931ffb15ad11c5ec7a0700570f80088fd5198ab5d5c227f2ad2a455a6edeec024156bb7beb000000075349474d415f3300cda5845f23468a13275d18bddae27c6bb189cf9aa95b6a03a0cb6688c7e8d829639b45cf8607c525cc400b55ebf90205f2f378626dc3406cc59b2d1b474fba000000075349474d415f342d299e7928496ea2d37f10b43afd6a80c90a33b483090d18069ffa275eedb2fc2f82121e8de43dc036d99b478b6227ceef34248939987a19011f065d8b5cef5c0000000010000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f1568448ac2259bbec7694d6670a15177bd0304d71700aa7fea107740a077d0411dae27cc7fe2af345f160253be3875d449a7e9ba6bd68747d87d4e7054b8111527b1d0839a5b23baf12a8d195b18ac288fcf401afb2f70b8a4b529ede5fa9fed19ffad41d477b4d4077d3edfe7eaf592f3b332d915dc68b41f2f1f370ebed632000000000000000000000000000000000000000000000000000000000000000027b1d0839a5b23baf12a8d195b18ac288fcf401afb2f70b8a4b529ede5fa9fed21dbfd1d029bf447152fcf89e355c334610d1632436ba170f738107266a715500bcd1f91cf7bdd471d0a30c58c4706f3fdab3807a954b8f5b5e3bfec87d001bb06e62084ee7b602fe9abc15632dda3269f56fb0c6e12519a2eb2ec897091919d03c9e2e67178ac638746f068907e6677b4cc7a9592ef234ab6ab518f17efffa000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 \ No newline at end of file +0d27622958018fb0d6eddd432d5ab189772cb5a403cb80cfc1f9a9dc37cff37937889ba10107cc8d92c6d80f5119f3fa271649fbf9e8a9d3d92ee4790145cdf8bb984c86e600000000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000013b9aca0005f5e10000000000000000000000000000000000000000000000000000000000000000013b9aca0005f5e10000000000000000000000000000000000000000000000000000000000000000013b9aca0005f5e100000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010d27622958018fb0d6eddd432d5ab189772cb5a403cb80cfc1f9a9dc37cff37937889ba10100000000000000000000000000000000000000000000000000000000000000000d27622958018fb0d6eddd432d5ab189772cb5a403cb80cfc1f9a9dc37cff379000000000000000000000000000000000000000037889ba135a4e90035a4e90035a4e9000000000000013b9aca0005f5e10000000000000000000000000000000000000000000000000000000000000000013b9aca0005f5e10000000000000000000000000000000000000000000000000000000000000000013b9aca0005f5e10000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000007cc8d92c6d80f5119f3fa271649fbf9e8a9d3d92ee4790145cdf8bb984c86e60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008cc9e9f9c7e273402be86892aac8530b0b573a44d53b847042d2bf25393327b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000000016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000000000bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278000000800572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007a69000000000000000000000000000000000000000000000000000000000000000108cc9e9f9c7e273402be86892aac8530b0b573a44d53b847042d2bf25393327b0d27622958018fb0d6eddd432d5ab189772cb5a403cb80cfc1f9a9dc37cff37900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000800000000740000000f00000003515f3109623eb3c25aa5b16a1a79fd558bac7a7ce62c4560a8c537c77ce80dd339128d1d37b6582ee9e6df9567efb64313471dfa18f520f9ce53161b50dbf7731bc5f900000003515f322bc4cce83a486a92c92fd59bd84e0f92595baa639fc2ed86b00ffa0dfded2a092a669a3bdb7a273a015eda494457cc7ed5236f26cee330c290d45a33b9daa94800000003515f332729426c008c085a81bd34d8ef12dd31e80130339ef99d50013a89e4558eee6d0fa4ffe2ee7b7b62eb92608b2251ac31396a718f9b34978888789042b790a30100000003515f342be6b6824a913eb7a57b03cb1ee7bfb4de02f2f65fe8a4e97baa7766ddb353a82a8a25c49dc63778cd9fe96173f12a2bc77f3682f4c4448f98f1df82c75234a100000003515f351f85760d6ab567465aadc2f180af9eae3800e6958fec96aef53fd8a7b195d7c000c6267a0dd5cfc22b3fe804f53e266069c0e36f51885baec1e7e67650c62e170000000c515f41524954484d455449430d9d0f8ece2aa12012fa21e6e5c859e97bd5704e5c122064a66051294bc5e04213f61f54a0ebdf6fee4d4a6ecf693478191de0c2899bcd8e86a636c8d3eff43400000003515f43224a99d02c86336737c8dd5b746c40d2be6aead8393889a76a18d664029096e90f7fe81adcc92a74350eada9622ac453f49ebac24a066a1f83b394df54dfa0130000000c515f46495845445f42415345060e8a013ed289c2f9fd7473b04f6594b138ddb4b4cf6b901622a14088f04b8d2c83ff74fce56e3d5573b99c7b26d85d5046ce0c6559506acb7a675e7713eb3a00000007515f4c4f4749430721a91cb8da4b917e054f72147e1760cfe0ef3d45090ac0f4961d84ec1996961a25e787b26bd8b50b1a99450f77a424a83513c2b33af268cd253b0587ff50c700000003515f4d05dbd8623b8652511e1eb38d38887a69eceb082f807514f09e127237c5213b401b9325b48c6c225968002318095f89d0ef9cf629b2b7f0172e03bc39aacf6ed800000007515f52414e474504b57a3805e41df328f5ca9aefa40fad5917391543b7b65c6476e60b8f72e9ad07c92f3b3e11c8feae96dedc4b14a6226ef3201244f37cfc1ee5b96781f48d2b000000075349474d415f3125001d1954a18571eaa007144c5a567bb0d2be4def08a8be918b8c05e3b27d312c59ed41e09e144eab5de77ca89a2fd783be702a47c951d3112e3de02ce6e47c000000075349474d415f3223994e6a23618e60fa01c449a7ab88378709197e186d48d604bfb6931ffb15ad11c5ec7a0700570f80088fd5198ab5d5c227f2ad2a455a6edeec024156bb7beb000000075349474d415f3300cda5845f23468a13275d18bddae27c6bb189cf9aa95b6a03a0cb6688c7e8d829639b45cf8607c525cc400b55ebf90205f2f378626dc3406cc59b2d1b474fba000000075349474d415f342d299e7928496ea2d37f10b43afd6a80c90a33b483090d18069ffa275eedb2fc2f82121e8de43dc036d99b478b6227ceef34248939987a19011f065d8b5cef5c0000000010000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f1d2910fa7478af96ba0f336875a93c7f5f1e2eba63d9925014ad4ef5779f64ad1dae27cc7fe2af345f160253be3875d449a7e9ba6bd68747d87d4e7054b81115000000000000000000000000000000000000000000000000000000000000000019ffad41d477b4d4077d3edfe7eaf592f3b332d915dc68b41f2f1f370ebed632000000000000000000000000000000000000000000000000000000000000000027b1d0839a5b23baf12a8d195b18ac288fcf401afb2f70b8a4b529ede5fa9fed21dbfd1d029bf447152fcf89e355c334610d1632436ba170f738107266a715500bcd1f91cf7bdd471d0a30c58c4706f3fdab3807a954b8f5b5e3bfec87d001bb06e62084ee7b602fe9abc15632dda3269f56fb0c6e12519a2eb2ec897091919d03c9e2e67178ac638746f068907e6677b4cc7a9592ef234ab6ab518f17efffa000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 \ No newline at end of file diff --git a/yarn-project/noir-protocol-circuits-types/src/fixtures/nested-call-private-kernel-inner.hex b/yarn-project/noir-protocol-circuits-types/src/fixtures/nested-call-private-kernel-inner.hex index 3b12c7db785..15c347b813e 100644 --- a/yarn-project/noir-protocol-circuits-types/src/fixtures/nested-call-private-kernel-inner.hex +++ b/yarn-project/noir-protocol-circuits-types/src/fixtures/nested-call-private-kernel-inner.hex @@ -1 +1 @@ -0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000001000000bd300000bd400000bd500000bd600000bd700000bd800000bd900000bda00000bdb00000bdc00000bdd00000bde00000bdf00000be000000be100000be20000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001cbfe3e489299947cef42ee1812ff6b238b856ae13f95437b82ce86f44fe4fb600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000008184e3ae016e6a45c309f1d04c50823f260cc02e2f4b5c9d8bf7cd10d8dc1c6e3304faeaac4852e3721a5f76646d8f1bcf4e1cf8e6f4795a6a0053d7540aff67900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000eed5cdbaafbbc794dbfae12e568d38ba22a9c222066df87fd213f7c5240117e000000030000000000000000000000000000000000000000000000000000000000000001007710847c110c9d1d2feb57e05a986dfb30c2d33811a9d05c76c9657af34d0700089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c31864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f8000000030234676c856daf7c0bf73f0e9a3980387c0a78cceb1be03d3b9542ad31ebfa1d80000018000d1d7b14ec97e9e3332c3eb5734202d6e3a0c76b3a7de8a05a857d7c885ae0e000002000572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000001000000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000661e94db0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000013b9aca0005f5e10000000000000000000000000000000000000000000000000000000000000000013b9aca0005f5e10000000000000000000000000000000000000000000000000000000000000000013b9aca0005f5e100000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000002a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000800000000740000000f00000003515f3109623eb3c25aa5b16a1a79fd558bac7a7ce62c4560a8c537c77ce80dd339128d1d37b6582ee9e6df9567efb64313471dfa18f520f9ce53161b50dbf7731bc5f900000003515f322bc4cce83a486a92c92fd59bd84e0f92595baa639fc2ed86b00ffa0dfded2a092a669a3bdb7a273a015eda494457cc7ed5236f26cee330c290d45a33b9daa94800000003515f332729426c008c085a81bd34d8ef12dd31e80130339ef99d50013a89e4558eee6d0fa4ffe2ee7b7b62eb92608b2251ac31396a718f9b34978888789042b790a30100000003515f342be6b6824a913eb7a57b03cb1ee7bfb4de02f2f65fe8a4e97baa7766ddb353a82a8a25c49dc63778cd9fe96173f12a2bc77f3682f4c4448f98f1df82c75234a100000003515f351f85760d6ab567465aadc2f180af9eae3800e6958fec96aef53fd8a7b195d7c000c6267a0dd5cfc22b3fe804f53e266069c0e36f51885baec1e7e67650c62e170000000c515f41524954484d455449430d9d0f8ece2aa12012fa21e6e5c859e97bd5704e5c122064a66051294bc5e04213f61f54a0ebdf6fee4d4a6ecf693478191de0c2899bcd8e86a636c8d3eff43400000003515f43224a99d02c86336737c8dd5b746c40d2be6aead8393889a76a18d664029096e90f7fe81adcc92a74350eada9622ac453f49ebac24a066a1f83b394df54dfa0130000000c515f46495845445f42415345060e8a013ed289c2f9fd7473b04f6594b138ddb4b4cf6b901622a14088f04b8d2c83ff74fce56e3d5573b99c7b26d85d5046ce0c6559506acb7a675e7713eb3a00000007515f4c4f4749430721a91cb8da4b917e054f72147e1760cfe0ef3d45090ac0f4961d84ec1996961a25e787b26bd8b50b1a99450f77a424a83513c2b33af268cd253b0587ff50c700000003515f4d05dbd8623b8652511e1eb38d38887a69eceb082f807514f09e127237c5213b401b9325b48c6c225968002318095f89d0ef9cf629b2b7f0172e03bc39aacf6ed800000007515f52414e474504b57a3805e41df328f5ca9aefa40fad5917391543b7b65c6476e60b8f72e9ad07c92f3b3e11c8feae96dedc4b14a6226ef3201244f37cfc1ee5b96781f48d2b000000075349474d415f3125001d1954a18571eaa007144c5a567bb0d2be4def08a8be918b8c05e3b27d312c59ed41e09e144eab5de77ca89a2fd783be702a47c951d3112e3de02ce6e47c000000075349474d415f3223994e6a23618e60fa01c449a7ab88378709197e186d48d604bfb6931ffb15ad11c5ec7a0700570f80088fd5198ab5d5c227f2ad2a455a6edeec024156bb7beb000000075349474d415f3300cda5845f23468a13275d18bddae27c6bb189cf9aa95b6a03a0cb6688c7e8d829639b45cf8607c525cc400b55ebf90205f2f378626dc3406cc59b2d1b474fba000000075349474d415f342d299e7928496ea2d37f10b43afd6a80c90a33b483090d18069ffa275eedb2fc2f82121e8de43dc036d99b478b6227ceef34248939987a19011f065d8b5cef5c0000000010000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f0000000020a37986ee9aa91cfe3a609b350e6d266999461b635ca0420b884b08d50f4d1009c5c0728c89546b73fe3b9aa402e0ae562ce934b88235b388c690e5b0f20e8218cae2fa2e3faf92d1536361e486b34baad26a22d1253b821563a5a1003b20df15d54e8dde4393f502819821390cfd31ba0c912e86fbc2da32922256c53255f60906bca101304faeaac4852e3721a5f76646d8f1bcf4e1cf8e6f4795a6a0053d7540aff67915d54e8dde4393f502819821390cfd31ba0c912e86fbc2da32922256c53255f600000000000000000000000000000000000000000906bca135a4e90035a4e90035a4e9000000000000033b9aca0005f5e10000000000000000000000000000000000000000000000000000000000000000013b9aca0005f5e10000000000000000000000000000000000000000000000000000000000000000013b9aca0005f5e1000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000002898402da2fa95f47c47763fe5b171ff3155bd31e5af88d9823bccb26b6701542451ab56341b4067780469e41818b47f8fd45f4bd186f22ba4b4a1bb5d45a42d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040eed5cdbaafbbc794dbfae12e568d38ba22a9c222066df87fd213f7c5240117e000000030000000000000000000000000000000000000000000000000000000000000001007710847c110c9d1d2feb57e05a986dfb30c2d33811a9d05c76c9657af34d0700089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c31864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f8000000030234676c856daf7c0bf73f0e9a3980387c0a78cceb1be03d3b9542ad31ebfa1d80000018000d1d7b14ec97e9e3332c3eb5734202d6e3a0c76b3a7de8a05a857d7c885ae0e000002000572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000001000000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000661e94db000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000800000000740000000f00000003515f3109623eb3c25aa5b16a1a79fd558bac7a7ce62c4560a8c537c77ce80dd339128d1d37b6582ee9e6df9567efb64313471dfa18f520f9ce53161b50dbf7731bc5f900000003515f322bc4cce83a486a92c92fd59bd84e0f92595baa639fc2ed86b00ffa0dfded2a092a669a3bdb7a273a015eda494457cc7ed5236f26cee330c290d45a33b9daa94800000003515f332729426c008c085a81bd34d8ef12dd31e80130339ef99d50013a89e4558eee6d0fa4ffe2ee7b7b62eb92608b2251ac31396a718f9b34978888789042b790a30100000003515f342be6b6824a913eb7a57b03cb1ee7bfb4de02f2f65fe8a4e97baa7766ddb353a82a8a25c49dc63778cd9fe96173f12a2bc77f3682f4c4448f98f1df82c75234a100000003515f351f85760d6ab567465aadc2f180af9eae3800e6958fec96aef53fd8a7b195d7c000c6267a0dd5cfc22b3fe804f53e266069c0e36f51885baec1e7e67650c62e170000000c515f41524954484d455449430d9d0f8ece2aa12012fa21e6e5c859e97bd5704e5c122064a66051294bc5e04213f61f54a0ebdf6fee4d4a6ecf693478191de0c2899bcd8e86a636c8d3eff43400000003515f43224a99d02c86336737c8dd5b746c40d2be6aead8393889a76a18d664029096e90f7fe81adcc92a74350eada9622ac453f49ebac24a066a1f83b394df54dfa0130000000c515f46495845445f42415345060e8a013ed289c2f9fd7473b04f6594b138ddb4b4cf6b901622a14088f04b8d2c83ff74fce56e3d5573b99c7b26d85d5046ce0c6559506acb7a675e7713eb3a00000007515f4c4f4749430721a91cb8da4b917e054f72147e1760cfe0ef3d45090ac0f4961d84ec1996961a25e787b26bd8b50b1a99450f77a424a83513c2b33af268cd253b0587ff50c700000003515f4d05dbd8623b8652511e1eb38d38887a69eceb082f807514f09e127237c5213b401b9325b48c6c225968002318095f89d0ef9cf629b2b7f0172e03bc39aacf6ed800000007515f52414e474504b57a3805e41df328f5ca9aefa40fad5917391543b7b65c6476e60b8f72e9ad07c92f3b3e11c8feae96dedc4b14a6226ef3201244f37cfc1ee5b96781f48d2b000000075349474d415f3125001d1954a18571eaa007144c5a567bb0d2be4def08a8be918b8c05e3b27d312c59ed41e09e144eab5de77ca89a2fd783be702a47c951d3112e3de02ce6e47c000000075349474d415f3223994e6a23618e60fa01c449a7ab88378709197e186d48d604bfb6931ffb15ad11c5ec7a0700570f80088fd5198ab5d5c227f2ad2a455a6edeec024156bb7beb000000075349474d415f3300cda5845f23468a13275d18bddae27c6bb189cf9aa95b6a03a0cb6688c7e8d829639b45cf8607c525cc400b55ebf90205f2f378626dc3406cc59b2d1b474fba000000075349474d415f342d299e7928496ea2d37f10b43afd6a80c90a33b483090d18069ffa275eedb2fc2f82121e8de43dc036d99b478b6227ceef34248939987a19011f065d8b5cef5c0000000010000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f0de7a2fe9b5384b7142877d9ee77fb5bf7073902e711504a1ec4c7039b3ba35b2904908a7e8e4b61c07ee8c119b09ca8dc00cc6787e3dc5c4100c845d94b19cc27b1d0839a5b23baf12a8d195b18ac288fcf401afb2f70b8a4b529ede5fa9fed0ad428a44324ce02cf0c67cb517de63f73072ab8ab5295a9c1f394057bc9719500000000000000000000000000000000000000000000000000000000000000002452a14c748981acff167dba9088770b6c2c2dc34677295a1974f2c247236ba11e904e4d0a67667f8faaa89198f5e89684e213bc99a83c3b20888d5854d3dd320bcd1f91cf7bdd471d0a30c58c4706f3fdab3807a954b8f5b5e3bfec87d001bb06e62084ee7b602fe9abc15632dda3269f56fb0c6e12519a2eb2ec897091919d03c9e2e67178ac638746f068907e6677b4cc7a9592ef234ab6ab518f17efffa000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 \ No newline at end of file +0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000001000000bd300000bd400000bd500000bd600000bd700000bd800000bd900000bda00000bdb00000bdc00000bdd00000bde00000bdf00000be000000be100000be200000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013daceb117f1e04877221d14fc7403b63cf3850b153e8b6d155f83480c84674d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000008157bd672caa283c59831ddc26b03a29b01584331348e47656a8fbdeee87cd0962fdd03d17aec998c95b7d7bb2bf86e09a8ab19dbd72ff3cf36b0c03d03d17caa000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009b1e8feb235295c8b2c5cde8be3e0567ca1ec56b136b45b22f2ae64ab10343200000003000000000000000000000000000000000000000000000000000000000000000100cc62a4e0963228e1dc61a8d492a3ce5efe102a59f183d57d3c4c02365cc10d00089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c31864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f8000000030224d964eca00bbde1241ab70a698c277212bd33ac6318a14b746deff8a24587300000180023288a057e2a3458890dba31a91b8ef338433fb54a32e0952b4ab78073ebcb1000002000572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000001000000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000662114850000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000013b9aca0005f5e10000000000000000000000000000000000000000000000000000000000000000013b9aca0005f5e10000000000000000000000000000000000000000000000000000000000000000013b9aca0005f5e100000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000002a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000800000000740000000f00000003515f3109623eb3c25aa5b16a1a79fd558bac7a7ce62c4560a8c537c77ce80dd339128d1d37b6582ee9e6df9567efb64313471dfa18f520f9ce53161b50dbf7731bc5f900000003515f322bc4cce83a486a92c92fd59bd84e0f92595baa639fc2ed86b00ffa0dfded2a092a669a3bdb7a273a015eda494457cc7ed5236f26cee330c290d45a33b9daa94800000003515f332729426c008c085a81bd34d8ef12dd31e80130339ef99d50013a89e4558eee6d0fa4ffe2ee7b7b62eb92608b2251ac31396a718f9b34978888789042b790a30100000003515f342be6b6824a913eb7a57b03cb1ee7bfb4de02f2f65fe8a4e97baa7766ddb353a82a8a25c49dc63778cd9fe96173f12a2bc77f3682f4c4448f98f1df82c75234a100000003515f351f85760d6ab567465aadc2f180af9eae3800e6958fec96aef53fd8a7b195d7c000c6267a0dd5cfc22b3fe804f53e266069c0e36f51885baec1e7e67650c62e170000000c515f41524954484d455449430d9d0f8ece2aa12012fa21e6e5c859e97bd5704e5c122064a66051294bc5e04213f61f54a0ebdf6fee4d4a6ecf693478191de0c2899bcd8e86a636c8d3eff43400000003515f43224a99d02c86336737c8dd5b746c40d2be6aead8393889a76a18d664029096e90f7fe81adcc92a74350eada9622ac453f49ebac24a066a1f83b394df54dfa0130000000c515f46495845445f42415345060e8a013ed289c2f9fd7473b04f6594b138ddb4b4cf6b901622a14088f04b8d2c83ff74fce56e3d5573b99c7b26d85d5046ce0c6559506acb7a675e7713eb3a00000007515f4c4f4749430721a91cb8da4b917e054f72147e1760cfe0ef3d45090ac0f4961d84ec1996961a25e787b26bd8b50b1a99450f77a424a83513c2b33af268cd253b0587ff50c700000003515f4d05dbd8623b8652511e1eb38d38887a69eceb082f807514f09e127237c5213b401b9325b48c6c225968002318095f89d0ef9cf629b2b7f0172e03bc39aacf6ed800000007515f52414e474504b57a3805e41df328f5ca9aefa40fad5917391543b7b65c6476e60b8f72e9ad07c92f3b3e11c8feae96dedc4b14a6226ef3201244f37cfc1ee5b96781f48d2b000000075349474d415f3125001d1954a18571eaa007144c5a567bb0d2be4def08a8be918b8c05e3b27d312c59ed41e09e144eab5de77ca89a2fd783be702a47c951d3112e3de02ce6e47c000000075349474d415f3223994e6a23618e60fa01c449a7ab88378709197e186d48d604bfb6931ffb15ad11c5ec7a0700570f80088fd5198ab5d5c227f2ad2a455a6edeec024156bb7beb000000075349474d415f3300cda5845f23468a13275d18bddae27c6bb189cf9aa95b6a03a0cb6688c7e8d829639b45cf8607c525cc400b55ebf90205f2f378626dc3406cc59b2d1b474fba000000075349474d415f342d299e7928496ea2d37f10b43afd6a80c90a33b483090d18069ffa275eedb2fc2f82121e8de43dc036d99b478b6227ceef34248939987a19011f065d8b5cef5c0000000010000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f000000001e6b568badd4d62a636485e905dac7ebd6a3c6741ccdd70533395de789c7c88f2459707154b6cab4215fb7972c3e724ac296d7af4e7f94fbe442e7ead473da2e2a478a56fb98bf3ddf5ae94552a21ca9ae89e8ea803152f2954c71ee1f1febcd1edec315c79a4e7ab031346e957408fd653f7f4e491c955f8403ec871ace71ec0906bca1012fdd03d17aec998c95b7d7bb2bf86e09a8ab19dbd72ff3cf36b0c03d03d17caa1edec315c79a4e7ab031346e957408fd653f7f4e491c955f8403ec871ace71ec00000000000000000000000000000000000000000906bca135a4e90035a4e90035a4e9000000000000033b9aca0005f5e10000000000000000000000000000000000000000000000000000000000000000013b9aca0005f5e10000000000000000000000000000000000000000000000000000000000000000013b9aca0005f5e1000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000002898402da2fa95f47c47763fe5b171ff3155bd31e5af88d9823bccb26b6701542451ab56341b4067780469e41818b47f8fd45f4bd186f22ba4b4a1bb5d45a42d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000409b1e8feb235295c8b2c5cde8be3e0567ca1ec56b136b45b22f2ae64ab10343200000003000000000000000000000000000000000000000000000000000000000000000100cc62a4e0963228e1dc61a8d492a3ce5efe102a59f183d57d3c4c02365cc10d00089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c31864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f8000000030224d964eca00bbde1241ab70a698c277212bd33ac6318a14b746deff8a24587300000180023288a057e2a3458890dba31a91b8ef338433fb54a32e0952b4ab78073ebcb1000002000572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000001000000000000000000000000000000000000000000000000000000000000007a69000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000066211485000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000800000000740000000f00000003515f3109623eb3c25aa5b16a1a79fd558bac7a7ce62c4560a8c537c77ce80dd339128d1d37b6582ee9e6df9567efb64313471dfa18f520f9ce53161b50dbf7731bc5f900000003515f322bc4cce83a486a92c92fd59bd84e0f92595baa639fc2ed86b00ffa0dfded2a092a669a3bdb7a273a015eda494457cc7ed5236f26cee330c290d45a33b9daa94800000003515f332729426c008c085a81bd34d8ef12dd31e80130339ef99d50013a89e4558eee6d0fa4ffe2ee7b7b62eb92608b2251ac31396a718f9b34978888789042b790a30100000003515f342be6b6824a913eb7a57b03cb1ee7bfb4de02f2f65fe8a4e97baa7766ddb353a82a8a25c49dc63778cd9fe96173f12a2bc77f3682f4c4448f98f1df82c75234a100000003515f351f85760d6ab567465aadc2f180af9eae3800e6958fec96aef53fd8a7b195d7c000c6267a0dd5cfc22b3fe804f53e266069c0e36f51885baec1e7e67650c62e170000000c515f41524954484d455449430d9d0f8ece2aa12012fa21e6e5c859e97bd5704e5c122064a66051294bc5e04213f61f54a0ebdf6fee4d4a6ecf693478191de0c2899bcd8e86a636c8d3eff43400000003515f43224a99d02c86336737c8dd5b746c40d2be6aead8393889a76a18d664029096e90f7fe81adcc92a74350eada9622ac453f49ebac24a066a1f83b394df54dfa0130000000c515f46495845445f42415345060e8a013ed289c2f9fd7473b04f6594b138ddb4b4cf6b901622a14088f04b8d2c83ff74fce56e3d5573b99c7b26d85d5046ce0c6559506acb7a675e7713eb3a00000007515f4c4f4749430721a91cb8da4b917e054f72147e1760cfe0ef3d45090ac0f4961d84ec1996961a25e787b26bd8b50b1a99450f77a424a83513c2b33af268cd253b0587ff50c700000003515f4d05dbd8623b8652511e1eb38d38887a69eceb082f807514f09e127237c5213b401b9325b48c6c225968002318095f89d0ef9cf629b2b7f0172e03bc39aacf6ed800000007515f52414e474504b57a3805e41df328f5ca9aefa40fad5917391543b7b65c6476e60b8f72e9ad07c92f3b3e11c8feae96dedc4b14a6226ef3201244f37cfc1ee5b96781f48d2b000000075349474d415f3125001d1954a18571eaa007144c5a567bb0d2be4def08a8be918b8c05e3b27d312c59ed41e09e144eab5de77ca89a2fd783be702a47c951d3112e3de02ce6e47c000000075349474d415f3223994e6a23618e60fa01c449a7ab88378709197e186d48d604bfb6931ffb15ad11c5ec7a0700570f80088fd5198ab5d5c227f2ad2a455a6edeec024156bb7beb000000075349474d415f3300cda5845f23468a13275d18bddae27c6bb189cf9aa95b6a03a0cb6688c7e8d829639b45cf8607c525cc400b55ebf90205f2f378626dc3406cc59b2d1b474fba000000075349474d415f342d299e7928496ea2d37f10b43afd6a80c90a33b483090d18069ffa275eedb2fc2f82121e8de43dc036d99b478b6227ceef34248939987a19011f065d8b5cef5c0000000010000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f1cdaa2eb61b6efb48b22c9ef5bf3ee4b109df74054dfb6d5ab845c70a8397008265f771f4a6725790024cd25130aba2b529badd70c776209735034054e5d03b00000000000000000000000000000000000000000000000000000000000000000212ece512924f2d5704d8e364125acf1ac78d11e30ba58192837e098670e695d00000000000000000000000000000000000000000000000000000000000000002452a14c748981acff167dba9088770b6c2c2dc34677295a1974f2c247236ba11e904e4d0a67667f8faaa89198f5e89684e213bc99a83c3b20888d5854d3dd320bcd1f91cf7bdd471d0a30c58c4706f3fdab3807a954b8f5b5e3bfec87d001bb06e62084ee7b602fe9abc15632dda3269f56fb0c6e12519a2eb2ec897091919d03c9e2e67178ac638746f068907e6677b4cc7a9592ef234ab6ab518f17efffa000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 \ No newline at end of file diff --git a/yarn-project/noir-protocol-circuits-types/src/fixtures/nested-call-private-kernel-ordering.hex b/yarn-project/noir-protocol-circuits-types/src/fixtures/nested-call-private-kernel-ordering.hex index 157f363bcb6..c1231be5208 100644 --- a/yarn-project/noir-protocol-circuits-types/src/fixtures/nested-call-private-kernel-ordering.hex +++ b/yarn-project/noir-protocol-circuits-types/src/fixtures/nested-call-private-kernel-ordering.hex @@ -1 +1 @@ -0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000001000000bd300000bd400000bd500000bd600000bd700000bd800000bd900000bda00000bdb00000bdc00000bdd00000bde00000bdf00000be000000be100000be2000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022a0c845d11f6ab935270159fcf81cf8fc6c19ba959855941ea0a910dfccb0aa000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000026fd8601b83cf50cefc8fd01a8f4f257818b236b4b05a4d655d1e250617cca4700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000239e2829a14b926fda5538c945938ffb2d69bca6532cf8d9ef8cb03654928c21000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011ad338c82a5771b8c493d4fdd310e05a947584891295750cc1267bc96bbd0cde0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004c86d02eb4dc898abeefc07e126614d7342bc55f1bb250a211861dfe87f8e30000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013c000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000000016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000000000bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278000000800572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b0000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000013b9aca0005f5e10000000000000000000000000000000000000000000000000000000000000000013b9aca0005f5e10000000000000000000000000000000000000000000000000000000000000000013b9aca0005f5e100000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000002a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000800000000740000000f00000003515f3109623eb3c25aa5b16a1a79fd558bac7a7ce62c4560a8c537c77ce80dd339128d1d37b6582ee9e6df9567efb64313471dfa18f520f9ce53161b50dbf7731bc5f900000003515f322bc4cce83a486a92c92fd59bd84e0f92595baa639fc2ed86b00ffa0dfded2a092a669a3bdb7a273a015eda494457cc7ed5236f26cee330c290d45a33b9daa94800000003515f332729426c008c085a81bd34d8ef12dd31e80130339ef99d50013a89e4558eee6d0fa4ffe2ee7b7b62eb92608b2251ac31396a718f9b34978888789042b790a30100000003515f342be6b6824a913eb7a57b03cb1ee7bfb4de02f2f65fe8a4e97baa7766ddb353a82a8a25c49dc63778cd9fe96173f12a2bc77f3682f4c4448f98f1df82c75234a100000003515f351f85760d6ab567465aadc2f180af9eae3800e6958fec96aef53fd8a7b195d7c000c6267a0dd5cfc22b3fe804f53e266069c0e36f51885baec1e7e67650c62e170000000c515f41524954484d455449430d9d0f8ece2aa12012fa21e6e5c859e97bd5704e5c122064a66051294bc5e04213f61f54a0ebdf6fee4d4a6ecf693478191de0c2899bcd8e86a636c8d3eff43400000003515f43224a99d02c86336737c8dd5b746c40d2be6aead8393889a76a18d664029096e90f7fe81adcc92a74350eada9622ac453f49ebac24a066a1f83b394df54dfa0130000000c515f46495845445f42415345060e8a013ed289c2f9fd7473b04f6594b138ddb4b4cf6b901622a14088f04b8d2c83ff74fce56e3d5573b99c7b26d85d5046ce0c6559506acb7a675e7713eb3a00000007515f4c4f4749430721a91cb8da4b917e054f72147e1760cfe0ef3d45090ac0f4961d84ec1996961a25e787b26bd8b50b1a99450f77a424a83513c2b33af268cd253b0587ff50c700000003515f4d05dbd8623b8652511e1eb38d38887a69eceb082f807514f09e127237c5213b401b9325b48c6c225968002318095f89d0ef9cf629b2b7f0172e03bc39aacf6ed800000007515f52414e474504b57a3805e41df328f5ca9aefa40fad5917391543b7b65c6476e60b8f72e9ad07c92f3b3e11c8feae96dedc4b14a6226ef3201244f37cfc1ee5b96781f48d2b000000075349474d415f3125001d1954a18571eaa007144c5a567bb0d2be4def08a8be918b8c05e3b27d312c59ed41e09e144eab5de77ca89a2fd783be702a47c951d3112e3de02ce6e47c000000075349474d415f3223994e6a23618e60fa01c449a7ab88378709197e186d48d604bfb6931ffb15ad11c5ec7a0700570f80088fd5198ab5d5c227f2ad2a455a6edeec024156bb7beb000000075349474d415f3300cda5845f23468a13275d18bddae27c6bb189cf9aa95b6a03a0cb6688c7e8d829639b45cf8607c525cc400b55ebf90205f2f378626dc3406cc59b2d1b474fba000000075349474d415f342d299e7928496ea2d37f10b43afd6a80c90a33b483090d18069ffa275eedb2fc2f82121e8de43dc036d99b478b6227ceef34248939987a19011f065d8b5cef5c0000000010000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f000000002013d0ff20211fe37493ef7ae818718fe839086139dccdf57e3d07f2d179e0802ad66b73a8b9536005aacaca6c565759426bcacd052db1d07f4fa5912f5731b52c52764f15c29eb4d74bd670e65ac533b62d805ac395adba6d7e074e991116a522a0c845d11f6ab935270159fcf81cf8fc6c19ba959855941ea0a910dfccb0aa0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f000000100000001100000012000000130000001400000015000000160000001700000018000000190000001a0000001b0000001c0000001d0000001e0000001f000000200000002100000022000000230000002400000025000000260000002700000028000000290000002a0000002b0000002c0000002d0000002e0000002f000000300000003100000032000000330000003400000035000000360000003700000038000000390000003a0000003b0000003c0000003d0000003e0000003f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000026fd8601b83cf50cefc8fd01a8f4f257818b236b4b05a4d655d1e250617cca4700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000239e2829a14b926fda5538c945938ffb2d69bca6532cf8d9ef8cb03654928c21000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011ad338c82a5771b8c493d4fdd310e05a947584891295750cc1267bc96bbd0cde00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f000000100000001100000012000000130000001400000015000000160000001700000018000000190000001a0000001b0000001c0000001d0000001e0000001f000000200000002100000022000000230000002400000025000000260000002700000028000000290000002a0000002b0000002c0000002d0000002e0000002f000000300000003100000032000000330000003400000035000000360000003700000038000000390000003a0000003b0000003c0000003d0000003e0000003f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000080000000000000008000000000000000800000000000000080000000000000008000000000000000800000000000000080000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004c86d02eb4dc898abeefc07e126614d7342bc55f1bb250a211861dfe87f8e30000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000020000000300000004000000050000000600000007000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000200000003000000040000000500000006000000070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 \ No newline at end of file +0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000001000000bd300000bd400000bd500000bd600000bd700000bd800000bd900000bda00000bdb00000bdc00000bdd00000bde00000bdf00000be000000be100000be200000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ccd0272c6e45c4b05c1a84a83653d65c96e887eb2ebc63452743d3c7e1808660000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000158f5201c0037cd8557264add6c5043e596acc241ab0265661024a83ff299338000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001df4db6b8a78745d88326f389fa82444a7f96b95d7cc911f4c95ac9d28a8c42f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012e1e9a2149619391c5951865799264d481dd20fa0441ba2e432f0c49bcb65d02000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d8b9d32dadd05ec8b3e708f735d6beb18a96f084d747a0060dcc71b81f07c90000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013c000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000000016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000000000bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278000000800572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b0000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000013b9aca0005f5e10000000000000000000000000000000000000000000000000000000000000000013b9aca0005f5e10000000000000000000000000000000000000000000000000000000000000000013b9aca0005f5e100000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000002a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000800000000740000000f00000003515f3109623eb3c25aa5b16a1a79fd558bac7a7ce62c4560a8c537c77ce80dd339128d1d37b6582ee9e6df9567efb64313471dfa18f520f9ce53161b50dbf7731bc5f900000003515f322bc4cce83a486a92c92fd59bd84e0f92595baa639fc2ed86b00ffa0dfded2a092a669a3bdb7a273a015eda494457cc7ed5236f26cee330c290d45a33b9daa94800000003515f332729426c008c085a81bd34d8ef12dd31e80130339ef99d50013a89e4558eee6d0fa4ffe2ee7b7b62eb92608b2251ac31396a718f9b34978888789042b790a30100000003515f342be6b6824a913eb7a57b03cb1ee7bfb4de02f2f65fe8a4e97baa7766ddb353a82a8a25c49dc63778cd9fe96173f12a2bc77f3682f4c4448f98f1df82c75234a100000003515f351f85760d6ab567465aadc2f180af9eae3800e6958fec96aef53fd8a7b195d7c000c6267a0dd5cfc22b3fe804f53e266069c0e36f51885baec1e7e67650c62e170000000c515f41524954484d455449430d9d0f8ece2aa12012fa21e6e5c859e97bd5704e5c122064a66051294bc5e04213f61f54a0ebdf6fee4d4a6ecf693478191de0c2899bcd8e86a636c8d3eff43400000003515f43224a99d02c86336737c8dd5b746c40d2be6aead8393889a76a18d664029096e90f7fe81adcc92a74350eada9622ac453f49ebac24a066a1f83b394df54dfa0130000000c515f46495845445f42415345060e8a013ed289c2f9fd7473b04f6594b138ddb4b4cf6b901622a14088f04b8d2c83ff74fce56e3d5573b99c7b26d85d5046ce0c6559506acb7a675e7713eb3a00000007515f4c4f4749430721a91cb8da4b917e054f72147e1760cfe0ef3d45090ac0f4961d84ec1996961a25e787b26bd8b50b1a99450f77a424a83513c2b33af268cd253b0587ff50c700000003515f4d05dbd8623b8652511e1eb38d38887a69eceb082f807514f09e127237c5213b401b9325b48c6c225968002318095f89d0ef9cf629b2b7f0172e03bc39aacf6ed800000007515f52414e474504b57a3805e41df328f5ca9aefa40fad5917391543b7b65c6476e60b8f72e9ad07c92f3b3e11c8feae96dedc4b14a6226ef3201244f37cfc1ee5b96781f48d2b000000075349474d415f3125001d1954a18571eaa007144c5a567bb0d2be4def08a8be918b8c05e3b27d312c59ed41e09e144eab5de77ca89a2fd783be702a47c951d3112e3de02ce6e47c000000075349474d415f3223994e6a23618e60fa01c449a7ab88378709197e186d48d604bfb6931ffb15ad11c5ec7a0700570f80088fd5198ab5d5c227f2ad2a455a6edeec024156bb7beb000000075349474d415f3300cda5845f23468a13275d18bddae27c6bb189cf9aa95b6a03a0cb6688c7e8d829639b45cf8607c525cc400b55ebf90205f2f378626dc3406cc59b2d1b474fba000000075349474d415f342d299e7928496ea2d37f10b43afd6a80c90a33b483090d18069ffa275eedb2fc2f82121e8de43dc036d99b478b6227ceef34248939987a19011f065d8b5cef5c0000000010000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f000000002f0906b34e42aa88c9ac829fda9637a69992c1151d0ad73d3f38ad4e243d2afa0492d22613f2fee8cf576e977f7889a85d51ea07d50324a2ac6041bd7ee93c980a80ec0bbad4f3728d52a045a5dc34074944fb4306b4e2995d69cbc0c9954e370ccd0272c6e45c4b05c1a84a83653d65c96e887eb2ebc63452743d3c7e1808660000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f000000100000001100000012000000130000001400000015000000160000001700000018000000190000001a0000001b0000001c0000001d0000001e0000001f000000200000002100000022000000230000002400000025000000260000002700000028000000290000002a0000002b0000002c0000002d0000002e0000002f000000300000003100000032000000330000003400000035000000360000003700000038000000390000003a0000003b0000003c0000003d0000003e0000003f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000158f5201c0037cd8557264add6c5043e596acc241ab0265661024a83ff299338000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001df4db6b8a78745d88326f389fa82444a7f96b95d7cc911f4c95ac9d28a8c42f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012e1e9a2149619391c5951865799264d481dd20fa0441ba2e432f0c49bcb65d0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f000000100000001100000012000000130000001400000015000000160000001700000018000000190000001a0000001b0000001c0000001d0000001e0000001f000000200000002100000022000000230000002400000025000000260000002700000028000000290000002a0000002b0000002c0000002d0000002e0000002f000000300000003100000032000000330000003400000035000000360000003700000038000000390000003a0000003b0000003c0000003d0000003e0000003f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000008000000000000000800000000000000080000000000000008000000000000000800000000000000080000000000000008000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d8b9d32dadd05ec8b3e708f735d6beb18a96f084d747a0060dcc71b81f07c90000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000020000000300000004000000050000000600000007000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000200000003000000040000000500000006000000070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 \ No newline at end of file diff --git a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts index d69b24594e0..15877cde1c9 100644 --- a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts +++ b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts @@ -124,7 +124,6 @@ import { type GasFees as GasFeesNoir, type Gas as GasNoir, type GasSettings as GasSettingsNoir, - type GrumpkinPrivateKey as GrumpkinPrivateKeyNoir, type L2ToL1Message as L2ToL1MessageNoir, type MaxBlockNumber as MaxBlockNumberNoir, type AztecAddress as NoirAztecAddress, @@ -154,6 +153,7 @@ import { type PrivateKernelInnerCircuitPrivateInputs as PrivateKernelInnerCircui import { type PrivateKernelTailToPublicCircuitPrivateInputs as PrivateKernelTailToPublicCircuitPrivateInputsNoir } from './types/private_kernel_tail_to_public_types.js'; import { type CombinedAccumulatedData as CombinedAccumulatedDataNoir, + type GrumpkinPrivateKey as GrumpkinPrivateKeyNoir, type NullifierReadRequestHints as NullifierReadRequestHintsNoir, type NullifierSettledReadHint as NullifierSettledReadHintNoir, type PendingReadHint as PendingReadHintNoir, @@ -657,8 +657,8 @@ export function mapNullifierKeyValidationRequestToNoir( request: NullifierKeyValidationRequest, ): NullifierKeyValidationRequestNoir { return { - public_key: mapPointToNoir(request.publicKey), - secret_key: mapGrumpkinPrivateKeyToNoir(request.secretKey), + master_nullifier_public_key: mapPointToNoir(request.masterNullifierPublicKey), + app_nullifier_secret_key: mapFieldToNoir(request.appNullifierSecretKey), }; } @@ -671,8 +671,8 @@ export function mapNullifierKeyValidationRequestFromNoir( request: NullifierKeyValidationRequestNoir, ): NullifierKeyValidationRequest { return new NullifierKeyValidationRequest( - mapPointFromNoir(request.public_key), - mapGrumpkinPrivateKeyFromNoir(request.secret_key), + mapPointFromNoir(request.master_nullifier_public_key), + mapFieldFromNoir(request.app_nullifier_secret_key), ); } @@ -685,8 +685,8 @@ export function mapNullifierKeyValidationRequestContextToNoir( request: NullifierKeyValidationRequestContext, ): NullifierKeyValidationRequestContextNoir { return { - public_key: mapPointToNoir(request.publicKey), - secret_key: mapGrumpkinPrivateKeyToNoir(request.secretKey), + master_nullifier_public_key: mapPointToNoir(request.masterNullifierPublicKey), + app_nullifier_secret_key: mapFieldToNoir(request.appNullifierSecretKey), contract_address: mapAztecAddressToNoir(request.contractAddress), }; } @@ -700,8 +700,8 @@ export function mapNullifierKeyValidationRequestContextFromNoir( request: NullifierKeyValidationRequestContextNoir, ): NullifierKeyValidationRequestContext { return new NullifierKeyValidationRequestContext( - mapPointFromNoir(request.public_key), - mapGrumpkinPrivateKeyFromNoir(request.secret_key), + mapPointFromNoir(request.master_nullifier_public_key), + mapFieldFromNoir(request.app_nullifier_secret_key), mapAztecAddressFromNoir(request.contract_address), ); } diff --git a/yarn-project/protocol-contracts/src/gas-token/index.ts b/yarn-project/protocol-contracts/src/gas-token/index.ts index d38126bf262..b31573a235c 100644 --- a/yarn-project/protocol-contracts/src/gas-token/index.ts +++ b/yarn-project/protocol-contracts/src/gas-token/index.ts @@ -1,11 +1,11 @@ -import { type AztecAddress, type EthAddress, Point } from '@aztec/circuits.js'; +import { type AztecAddress, type EthAddress } from '@aztec/circuits.js'; import { type ProtocolContract, getCanonicalProtocolContract } from '../protocol_contract.js'; import { GasTokenArtifact } from './artifact.js'; /** Returns the canonical deployment of the gas token. */ export function getCanonicalGasToken(l1Bridge: EthAddress): ProtocolContract { - return getCanonicalProtocolContract(GasTokenArtifact, 1, [], Point.ZERO, l1Bridge); + return getCanonicalProtocolContract(GasTokenArtifact, 1, [], l1Bridge); } export function getCanonicalGasTokenAddress(l1Bridge: EthAddress): AztecAddress { diff --git a/yarn-project/protocol-contracts/src/multi-call-entrypoint/index.ts b/yarn-project/protocol-contracts/src/multi-call-entrypoint/index.ts index 1d33cee36ed..160f408ee26 100644 --- a/yarn-project/protocol-contracts/src/multi-call-entrypoint/index.ts +++ b/yarn-project/protocol-contracts/src/multi-call-entrypoint/index.ts @@ -1,10 +1,10 @@ -import { type AztecAddress, EthAddress, Point } from '@aztec/circuits.js'; +import { type AztecAddress, EthAddress } from '@aztec/circuits.js'; import { type ProtocolContract, getCanonicalProtocolContract } from '../protocol_contract.js'; import { MultiCallEntrypointArtifact } from './artifact.js'; export function getCanonicalMultiCallEntrypointContract(): ProtocolContract { - return getCanonicalProtocolContract(MultiCallEntrypointArtifact, 1, [], Point.ZERO, EthAddress.ZERO); + return getCanonicalProtocolContract(MultiCallEntrypointArtifact, 1, [], EthAddress.ZERO); } export function getCanonicalMultiCallEntrypointAddress(): AztecAddress { diff --git a/yarn-project/protocol-contracts/src/protocol_contract.ts b/yarn-project/protocol-contracts/src/protocol_contract.ts index 8286373e9da..2ce2b31c064 100644 --- a/yarn-project/protocol-contracts/src/protocol_contract.ts +++ b/yarn-project/protocol-contracts/src/protocol_contract.ts @@ -5,7 +5,7 @@ import { getContractInstanceFromDeployParams, } from '@aztec/circuits.js'; import { type ContractArtifact } from '@aztec/foundation/abi'; -import { Fr, Point } from '@aztec/foundation/fields'; +import { Fr } from '@aztec/foundation/fields'; import { type ContractClassWithId, type ContractInstanceWithAddress } from '@aztec/types/contracts'; /** Represents a canonical contract in the protocol. */ @@ -25,7 +25,6 @@ export function getCanonicalProtocolContract( artifact: ContractArtifact, salt: Fr | number | bigint, constructorArgs: any[] = [], - publicKey: Point = Point.ZERO, portalAddress = EthAddress.ZERO, ): ProtocolContract { // TODO(@spalladino): This computes the contract class from the artifact twice. @@ -33,7 +32,6 @@ export function getCanonicalProtocolContract( const instance = getContractInstanceFromDeployParams(artifact, { constructorArgs, salt: new Fr(salt), - publicKey, portalAddress, }); return { diff --git a/yarn-project/pxe/src/kernel_oracle/index.ts b/yarn-project/pxe/src/kernel_oracle/index.ts index a1948244093..aadf7993072 100644 --- a/yarn-project/pxe/src/kernel_oracle/index.ts +++ b/yarn-project/pxe/src/kernel_oracle/index.ts @@ -62,6 +62,6 @@ export class KernelOracle implements ProvingDataOracle { } public getMasterNullifierSecretKey(nullifierPublicKey: Point) { - return this.keyStore.getNullifierSecretKeyFromPublicKey(nullifierPublicKey); + return this.keyStore.getMasterNullifierSecretKeyForPublicKey(nullifierPublicKey); } } diff --git a/yarn-project/pxe/src/kernel_prover/hints_builder.ts b/yarn-project/pxe/src/kernel_prover/hints_builder.ts index dea4ae58b96..57e3155f042 100644 --- a/yarn-project/pxe/src/kernel_prover/hints_builder.ts +++ b/yarn-project/pxe/src/kernel_prover/hints_builder.ts @@ -148,7 +148,7 @@ export class HintsBuilder { if (request.isEmpty()) { break; } - keys[i] = await this.oracle.getMasterNullifierSecretKey(request.publicKey); + keys[i] = await this.oracle.getMasterNullifierSecretKey(request.masterNullifierPublicKey); } return keys; } diff --git a/yarn-project/pxe/src/note_processor/note_processor.test.ts b/yarn-project/pxe/src/note_processor/note_processor.test.ts index ab6345be4b4..b182e5caeb5 100644 --- a/yarn-project/pxe/src/note_processor/note_processor.test.ts +++ b/yarn-project/pxe/src/note_processor/note_processor.test.ts @@ -4,17 +4,22 @@ import { EncryptedL2BlockL2Logs, EncryptedL2Log, EncryptedTxL2Logs, - type KeyPair, type KeyStore, type L1NotePayload, L2Block, TaggedNote, } from '@aztec/circuit-types'; -import { Fr, INITIAL_L2_BLOCK_NUM, MAX_NEW_NOTE_HASHES_PER_TX } from '@aztec/circuits.js'; +import { + Fr, + type GrumpkinPrivateKey, + INITIAL_L2_BLOCK_NUM, + MAX_NEW_NOTE_HASHES_PER_TX, + type PublicKey, + deriveKeys, +} from '@aztec/circuits.js'; import { Grumpkin } from '@aztec/circuits.js/barretenberg'; import { pedersenHash } from '@aztec/foundation/crypto'; import { Point } from '@aztec/foundation/fields'; -import { ConstantKeyPair } from '@aztec/key-store'; import { openTmpStore } from '@aztec/kv-store/utils'; import { type AcirSimulator } from '@aztec/simulator'; @@ -29,12 +34,11 @@ import { NoteProcessor } from './note_processor.js'; const TXS_PER_BLOCK = 4; describe('Note Processor', () => { - let grumpkin: Grumpkin; + const grumpkin = new Grumpkin(); let database: PxeDatabase; let aztecNode: ReturnType>; let addNotesSpy: any; let noteProcessor: NoteProcessor; - let owner: KeyPair; let keyStore: MockProxy; let simulator: MockProxy; const firstBlockNum = 123; @@ -42,6 +46,9 @@ describe('Note Processor', () => { const firstBlockDataStartIndex = (firstBlockNum - 1) * numCommitmentsPerBlock; const firstBlockDataEndIndex = firstBlockNum * numCommitmentsPerBlock; + let ownerMasterIncomingViewingSecretKey: GrumpkinPrivateKey; + let ownerMasterIncomingViewingPublicKey: PublicKey; + // ownedData: [tx1, tx2, ...], the numbers in each tx represents the indices of the note hashes the account owns. const createEncryptedLogsAndOwnedL1NotePayloads = (ownedData: number[][], ownedNotes: TaggedNote[]) => { const newNotes: TaggedNote[] = []; @@ -57,7 +64,7 @@ describe('Note Processor', () => { const logs: EncryptedFunctionL2Logs[] = []; for (let noteIndex = 0; noteIndex < MAX_NEW_NOTE_HASHES_PER_TX; ++noteIndex) { const isOwner = ownedDataIndices.includes(noteIndex); - const publicKey = isOwner ? owner.getPublicKey() : Point.random(); + const publicKey = isOwner ? ownerMasterIncomingViewingPublicKey : Point.random(); const note = (isOwner && ownedNotes[usedOwnedNote]) || TaggedNote.random(); usedOwnedNote += note === ownedNotes[usedOwnedNote] ? 1 : 0; newNotes.push(note); @@ -114,8 +121,11 @@ describe('Note Processor', () => { }; beforeAll(() => { - grumpkin = new Grumpkin(); - owner = ConstantKeyPair.random(grumpkin); + const ownerSk = Fr.random(); + const allOwnerKeys = deriveKeys(ownerSk); + + ownerMasterIncomingViewingSecretKey = allOwnerKeys.masterIncomingViewingSecretKey; + ownerMasterIncomingViewingPublicKey = allOwnerKeys.masterIncomingViewingPublicKey; }); beforeEach(() => { @@ -125,9 +135,9 @@ describe('Note Processor', () => { aztecNode = mock(); keyStore = mock(); simulator = mock(); - keyStore.getAccountPrivateKey.mockResolvedValue(owner.getPrivateKey()); + keyStore.getMasterIncomingViewingSecretKeyForPublicKey.mockResolvedValue(ownerMasterIncomingViewingSecretKey); noteProcessor = new NoteProcessor( - owner.getPublicKey(), + ownerMasterIncomingViewingPublicKey, keyStore, database, aztecNode, @@ -237,7 +247,7 @@ describe('Note Processor', () => { await noteProcessor.process(blocks, encryptedLogsArr); const newNoteProcessor = new NoteProcessor( - owner.getPublicKey(), + ownerMasterIncomingViewingPublicKey, keyStore, database, aztecNode, diff --git a/yarn-project/pxe/src/note_processor/note_processor.ts b/yarn-project/pxe/src/note_processor/note_processor.ts index e8955b5e243..4a1c66481eb 100644 --- a/yarn-project/pxe/src/note_processor/note_processor.ts +++ b/yarn-project/pxe/src/note_processor/note_processor.ts @@ -49,7 +49,7 @@ export class NoteProcessor { /** * The public counterpart to the private key to be used in note decryption. */ - public readonly publicKey: PublicKey, + public readonly masterIncomingViewingPublicKey: PublicKey, private keyStore: KeyStore, private db: PxeDatabase, private node: AztecNode, @@ -78,7 +78,7 @@ export class NoteProcessor { } private getSyncedToBlock(): number { - return this.db.getSynchedBlockNumberForPublicKey(this.publicKey) ?? this.startingBlock - 1; + return this.db.getSynchedBlockNumberForPublicKey(this.masterIncomingViewingPublicKey) ?? this.startingBlock - 1; } /** @@ -116,7 +116,9 @@ export class NoteProcessor { // We are using set for `userPertainingTxIndices` to avoid duplicates. This would happen in case there were // multiple encrypted logs in a tx pertaining to a user. const noteDaos: NoteDao[] = []; - const privateKey = await this.keyStore.getAccountPrivateKey(this.publicKey); + const secretKey = await this.keyStore.getMasterIncomingViewingSecretKeyForPublicKey( + this.masterIncomingViewingPublicKey, + ); // Iterate over all the encrypted logs and try decrypting them. If successful, store the note. for (let indexOfTxInABlock = 0; indexOfTxInABlock < txLogs.length; ++indexOfTxInABlock) { @@ -130,7 +132,7 @@ export class NoteProcessor { for (const functionLogs of txFunctionLogs) { for (const log of functionLogs.logs) { this.stats.seen++; - const taggedNote = TaggedNote.fromEncryptedBuffer(log.data, privateKey, curve); + const taggedNote = TaggedNote.fromEncryptedBuffer(log.data, secretKey, curve); if (taggedNote?.notePayload) { const { notePayload: payload } = taggedNote; // We have successfully decrypted the data. @@ -138,7 +140,7 @@ export class NoteProcessor { try { const noteDao = await produceNoteDao( this.simulator, - this.publicKey, + this.masterIncomingViewingPublicKey, payload, txHash, newNoteHashes, @@ -152,7 +154,7 @@ export class NoteProcessor { this.stats.deferred++; this.log.warn(e.message); const deferredNoteDao = new DeferredNoteDao( - this.publicKey, + this.masterIncomingViewingPublicKey, payload.note, payload.contractAddress, payload.storageSlot, @@ -182,7 +184,7 @@ export class NoteProcessor { await this.processDeferredNotes(deferredNoteDaos); const syncedToBlock = l2Blocks[l2Blocks.length - 1].number; - await this.db.setSynchedBlockNumberForPublicKey(this.publicKey, syncedToBlock); + await this.db.setSynchedBlockNumberForPublicKey(this.masterIncomingViewingPublicKey, syncedToBlock); this.log.debug(`Synched block ${syncedToBlock}`); } @@ -212,7 +214,7 @@ export class NoteProcessor { const newNullifiers: Fr[] = blocksAndNotes.flatMap(b => b.block.body.txEffects.flatMap(txEffect => txEffect.nullifiers), ); - const removedNotes = await this.db.removeNullifiedNotes(newNullifiers, this.publicKey); + const removedNotes = await this.db.removeNullifiedNotes(newNullifiers, this.masterIncomingViewingPublicKey); removedNotes.forEach(noteDao => { this.log.verbose( `Removed note for contract ${noteDao.contractAddress} at slot ${ @@ -260,7 +262,7 @@ export class NoteProcessor { try { const noteDao = await produceNoteDao( this.simulator, - this.publicKey, + this.masterIncomingViewingPublicKey, payload, txHash, newNoteHashes, diff --git a/yarn-project/pxe/src/pxe_service/create_pxe_service.ts b/yarn-project/pxe/src/pxe_service/create_pxe_service.ts index 7daead96c66..2fc3b4c9b93 100644 --- a/yarn-project/pxe/src/pxe_service/create_pxe_service.ts +++ b/yarn-project/pxe/src/pxe_service/create_pxe_service.ts @@ -1,5 +1,4 @@ import { type AztecNode } from '@aztec/circuit-types'; -import { Grumpkin } from '@aztec/circuits.js/barretenberg'; import { randomBytes } from '@aztec/foundation/crypto'; import { TestKeyStore } from '@aztec/key-store'; import { AztecLmdbStore } from '@aztec/kv-store/lmdb'; @@ -38,7 +37,6 @@ export async function createPXEService( const l1Contracts = await aztecNode.getL1ContractAddresses(); const keyStore = new TestKeyStore( - new Grumpkin(), await initStoreForRollup(AztecLmdbStore.open(keyStorePath), l1Contracts.rollupAddress), ); const db = new KVPxeDatabase(await initStoreForRollup(AztecLmdbStore.open(pxeDbPath), l1Contracts.rollupAddress)); diff --git a/yarn-project/pxe/src/pxe_service/pxe_service.ts b/yarn-project/pxe/src/pxe_service/pxe_service.ts index 9f1d341533d..5f90b66be33 100644 --- a/yarn-project/pxe/src/pxe_service/pxe_service.ts +++ b/yarn-project/pxe/src/pxe_service/pxe_service.ts @@ -31,7 +31,6 @@ import { CallRequest, CompleteAddress, FunctionData, - type GrumpkinPrivateKey, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, type PartialAddress, type PrivateKernelTailCircuitPublicInputs, @@ -110,7 +109,8 @@ export class PXEService implements PXE { } private async restoreNoteProcessors() { - const publicKeys = await this.keyStore.getAccounts(); + const accounts = await this.keyStore.getAccounts(); + const publicKeys = accounts.map(async account => await this.keyStore.getMasterIncomingViewingPublicKey(account)); const publicKeysSet = new Set(publicKeys.map(k => k.toString())); const registeredAddresses = await this.db.getCompleteAddresses(); @@ -170,27 +170,36 @@ export class PXEService implements PXE { return artifact && getContractClassFromArtifact(artifact); } - public async registerAccount(privKey: GrumpkinPrivateKey, partialAddress: PartialAddress): Promise { - const completeAddress = CompleteAddress.fromPrivateKeyAndPartialAddress(privKey, partialAddress); - const wasAdded = await this.db.addCompleteAddress(completeAddress); - if (wasAdded) { - const pubKey = await this.keyStore.addAccount(privKey); - this.synchronizer.addAccount(pubKey, this.keyStore, this.config.l2StartingBlock); + public async registerAccount(secretKey: Fr, partialAddress: PartialAddress): Promise { + const accounts = await this.keyStore.getAccounts(); + const account = await this.keyStore.addAccount(secretKey, partialAddress); + const completeAddress = new CompleteAddress( + account, + await this.keyStore.getMasterIncomingViewingPublicKey(account), + partialAddress, + ); + if (accounts.includes(account)) { + this.log.info(`Account:\n "${completeAddress.address.toString()}"\n already registered.`); + return completeAddress; + } else { + const masterIncomingViewingPublicKey = await this.keyStore.getMasterIncomingViewingPublicKey(account); + this.synchronizer.addAccount(masterIncomingViewingPublicKey, this.keyStore, this.config.l2StartingBlock); this.log.info(`Registered account ${completeAddress.address.toString()}`); this.log.debug(`Registered account\n ${completeAddress.toReadableString()}`); - } else { - this.log.info(`Account:\n "${completeAddress.address.toString()}"\n already registered.`); } + + await this.db.addCompleteAddress(completeAddress); return completeAddress; } public async getRegisteredAccounts(): Promise { // Get complete addresses of both the recipients and the accounts - const addresses = await this.db.getCompleteAddresses(); + const completeAddresses = await this.db.getCompleteAddresses(); // Filter out the addresses not corresponding to accounts - const accountPubKeys = await this.keyStore.getAccounts(); - const accounts = addresses.filter(address => accountPubKeys.find(pubKey => pubKey.equals(address.publicKey))); - return accounts; + const accounts = await this.keyStore.getAccounts(); + return completeAddresses.filter(completeAddress => + accounts.find(address => address.equals(completeAddress.address)), + ); } public async getRegisteredAccount(address: AztecAddress): Promise { @@ -199,6 +208,14 @@ export class PXEService implements PXE { return Promise.resolve(account); } + public async getRegisteredAccountPublicKeysHash(address: AztecAddress): Promise { + const accounts = await this.keyStore.getAccounts(); + if (!accounts.some(account => account.equals(address))) { + return undefined; + } + return this.keyStore.getPublicKeysHash(address); + } + public async registerRecipient(recipient: CompleteAddress): Promise { const wasAdded = await this.db.addCompleteAddress(recipient); if (wasAdded) { @@ -210,10 +227,12 @@ export class PXEService implements PXE { public async getRecipients(): Promise { // Get complete addresses of both the recipients and the accounts - const addresses = await this.db.getCompleteAddresses(); + const completeAddresses = await this.db.getCompleteAddresses(); // Filter out the addresses corresponding to accounts - const accountPubKeys = await this.keyStore.getAccounts(); - const recipients = addresses.filter(address => !accountPubKeys.find(pubKey => pubKey.equals(address.publicKey))); + const accounts = await this.keyStore.getAccounts(); + const recipients = completeAddresses.filter( + completeAddress => !accounts.find(account => account.equals(completeAddress.address)), + ); return recipients; } diff --git a/yarn-project/pxe/src/pxe_service/test/pxe_service.test.ts b/yarn-project/pxe/src/pxe_service/test/pxe_service.test.ts index bbef70b77ba..6bff5763494 100644 --- a/yarn-project/pxe/src/pxe_service/test/pxe_service.test.ts +++ b/yarn-project/pxe/src/pxe_service/test/pxe_service.test.ts @@ -1,5 +1,4 @@ import { type AztecNode, type PXE, TxEffect, mockTx } from '@aztec/circuit-types'; -import { Grumpkin } from '@aztec/circuits.js/barretenberg'; import { INITIAL_L2_BLOCK_NUM } from '@aztec/circuits.js/constants'; import { type L1ContractAddresses } from '@aztec/ethereum'; import { EthAddress } from '@aztec/foundation/eth-address'; @@ -16,7 +15,7 @@ import { pxeTestSuite } from './pxe_test_suite.js'; function createPXEService(): Promise { const kvStore = openTmpStore(); - const keyStore = new TestKeyStore(new Grumpkin(), kvStore); + const keyStore = new TestKeyStore(kvStore); const node = mock(); const db = new KVPxeDatabase(kvStore); const config: PXEServiceConfig = { l2BlockPollingIntervalMS: 100, l2StartingBlock: INITIAL_L2_BLOCK_NUM }; @@ -49,7 +48,7 @@ describe('PXEService', () => { beforeEach(() => { const kvStore = openTmpStore(); - keyStore = new TestKeyStore(new Grumpkin(), kvStore); + keyStore = new TestKeyStore(kvStore); node = mock(); db = new KVPxeDatabase(kvStore); config = { l2BlockPollingIntervalMS: 100, l2StartingBlock: INITIAL_L2_BLOCK_NUM }; diff --git a/yarn-project/pxe/src/pxe_service/test/pxe_test_suite.ts b/yarn-project/pxe/src/pxe_service/test/pxe_test_suite.ts index 39c3e395ca4..af5d40a371c 100644 --- a/yarn-project/pxe/src/pxe_service/test/pxe_test_suite.ts +++ b/yarn-project/pxe/src/pxe_service/test/pxe_test_suite.ts @@ -16,8 +16,6 @@ import { TxContext, getContractClassFromArtifact, } from '@aztec/circuits.js'; -import { Grumpkin } from '@aztec/circuits.js/barretenberg'; -import { ConstantKeyPair } from '@aztec/key-store'; export const pxeTestSuite = (testName: string, pxeSetup: () => Promise) => { describe(testName, () => { @@ -28,10 +26,9 @@ export const pxeTestSuite = (testName: string, pxeSetup: () => Promise) => }, 120_000); it('registers an account and returns it as an account only and not as a recipient', async () => { - const keyPair = ConstantKeyPair.random(new Grumpkin()); - const completeAddress = CompleteAddress.fromPrivateKeyAndPartialAddress(keyPair.getPrivateKey(), Fr.random()); - - await pxe.registerAccount(keyPair.getPrivateKey(), completeAddress.partialAddress); + const randomSecretKey = Fr.random(); + const randomPartialAddress = Fr.random(); + const completeAddress = await pxe.registerAccount(randomSecretKey, randomPartialAddress); // Check that the account is correctly registered using the getAccounts and getRecipients methods const accounts = await pxe.getRegisteredAccounts(); @@ -65,11 +62,11 @@ export const pxeTestSuite = (testName: string, pxeSetup: () => Promise) => }); it('does not throw when registering the same account twice (just ignores the second attempt)', async () => { - const keyPair = ConstantKeyPair.random(new Grumpkin()); - const completeAddress = CompleteAddress.fromPrivateKeyAndPartialAddress(keyPair.getPrivateKey(), Fr.random()); + const randomSecretKey = Fr.random(); + const randomPartialAddress = Fr.random(); - await pxe.registerAccount(keyPair.getPrivateKey(), completeAddress.partialAddress); - await pxe.registerAccount(keyPair.getPrivateKey(), completeAddress.partialAddress); + await pxe.registerAccount(randomSecretKey, randomPartialAddress); + await pxe.registerAccount(randomSecretKey, randomPartialAddress); }); it('cannot register a recipient with the same aztec address but different pub key or partial address', async () => { diff --git a/yarn-project/pxe/src/simulator_oracle/index.ts b/yarn-project/pxe/src/simulator_oracle/index.ts index d5ba6c1a032..da0891190f6 100644 --- a/yarn-project/pxe/src/simulator_oracle/index.ts +++ b/yarn-project/pxe/src/simulator_oracle/index.ts @@ -20,7 +20,7 @@ import { import { computeL1ToL2MessageNullifier } from '@aztec/circuits.js/hash'; import { type FunctionArtifactWithDebugMetadata, getFunctionArtifactWithDebugMetadata } from '@aztec/foundation/abi'; import { createDebugLogger } from '@aztec/foundation/log'; -import { type DBOracle, type KeyPair, MessageLoadOracleInputs } from '@aztec/simulator'; +import { type DBOracle, MessageLoadOracleInputs, type NullifierKeys } from '@aztec/simulator'; import { type ContractInstance } from '@aztec/types/contracts'; import { type ContractDataOracle } from '../contract_data_oracle/index.js'; @@ -38,11 +38,10 @@ export class SimulatorOracle implements DBOracle { private log = createDebugLogger('aztec:pxe:simulator_oracle'), ) {} - async getNullifierKeyPair(accountAddress: AztecAddress, contractAddress: AztecAddress): Promise { - const accountPublicKey = (await this.db.getCompleteAddress(accountAddress))!.publicKey; - const publicKey = await this.keyStore.getNullifierPublicKey(accountPublicKey); - const secretKey = await this.keyStore.getSiloedNullifierSecretKey(accountPublicKey, contractAddress); - return { publicKey, secretKey }; + async getNullifierKeys(accountAddress: AztecAddress, contractAddress: AztecAddress): Promise { + const masterNullifierPublicKey = await this.keyStore.getMasterNullifierPublicKey(accountAddress); + const appNullifierSecretKey = await this.keyStore.getAppNullifierSecretKey(accountAddress, contractAddress); + return { masterNullifierPublicKey, appNullifierSecretKey }; } async getCompleteAddress(address: AztecAddress): Promise { diff --git a/yarn-project/pxe/src/synchronizer/synchronizer.test.ts b/yarn-project/pxe/src/synchronizer/synchronizer.test.ts index 79fa9b9bd19..f8deb8b8ca3 100644 --- a/yarn-project/pxe/src/synchronizer/synchronizer.test.ts +++ b/yarn-project/pxe/src/synchronizer/synchronizer.test.ts @@ -1,6 +1,5 @@ import { type AztecNode, L2Block } from '@aztec/circuit-types'; -import { CompleteAddress, Fr, GrumpkinScalar, type Header, INITIAL_L2_BLOCK_NUM } from '@aztec/circuits.js'; -import { Grumpkin } from '@aztec/circuits.js/barretenberg'; +import { CompleteAddress, Fr, type Header, INITIAL_L2_BLOCK_NUM } from '@aztec/circuits.js'; import { makeHeader } from '@aztec/circuits.js/testing'; import { randomInt } from '@aztec/foundation/crypto'; import { SerialQueue } from '@aztec/foundation/fifo'; @@ -127,11 +126,14 @@ describe('Synchronizer', () => { expect(await synchronizer.isGlobalStateSynchronized()).toBe(true); // Manually adding account to database so that we can call synchronizer.isAccountStateSynchronized - const keyStore = new TestKeyStore(new Grumpkin(), openTmpStore()); + const keyStore = new TestKeyStore(openTmpStore()); const addAddress = async (startingBlockNum: number) => { - const privateKey = GrumpkinScalar.random(); - await keyStore.addAccount(privateKey); - const completeAddress = CompleteAddress.fromPrivateKeyAndPartialAddress(privateKey, Fr.random()); + const secretKey = Fr.random(); + const partialAddress = Fr.random(); + const accountAddress = await keyStore.addAccount(secretKey, partialAddress); + const masterIncomingViewingPublicKey = await keyStore.getMasterIncomingViewingPublicKey(accountAddress); + + const completeAddress = new CompleteAddress(accountAddress, masterIncomingViewingPublicKey, partialAddress); await database.addCompleteAddress(completeAddress); synchronizer.addAccount(completeAddress.publicKey, keyStore, startingBlockNum); return completeAddress; diff --git a/yarn-project/pxe/src/synchronizer/synchronizer.ts b/yarn-project/pxe/src/synchronizer/synchronizer.ts index 940571d4779..dc7f1890877 100644 --- a/yarn-project/pxe/src/synchronizer/synchronizer.ts +++ b/yarn-project/pxe/src/synchronizer/synchronizer.ts @@ -198,7 +198,7 @@ export class Synchronizer { } this.log.debug( - `Catching up note processor ${noteProcessor.publicKey.toString()} by processing ${ + `Catching up note processor ${noteProcessor.masterIncomingViewingPublicKey.toString()} by processing ${ blocks.length - index } blocks`, ); @@ -206,16 +206,19 @@ export class Synchronizer { if (noteProcessor.status.syncedToBlock === toBlockNumber) { // Note processor caught up, move it to `noteProcessors` from `noteProcessorsToCatchUp`. - this.log.debug(`Note processor for ${noteProcessor.publicKey.toString()} has caught up`, { - eventName: 'note-processor-caught-up', - publicKey: noteProcessor.publicKey.toString(), - duration: noteProcessor.timer.ms(), - dbSize: this.db.estimateSize(), - ...noteProcessor.stats, - } satisfies NoteProcessorCaughtUpStats); + this.log.debug( + `Note processor for ${noteProcessor.masterIncomingViewingPublicKey.toString()} has caught up`, + { + eventName: 'note-processor-caught-up', + publicKey: noteProcessor.masterIncomingViewingPublicKey.toString(), + duration: noteProcessor.timer.ms(), + dbSize: this.db.estimateSize(), + ...noteProcessor.stats, + } satisfies NoteProcessorCaughtUpStats, + ); this.noteProcessorsToCatchUp = this.noteProcessorsToCatchUp.filter( - np => !np.publicKey.equals(noteProcessor.publicKey), + np => !np.masterIncomingViewingPublicKey.equals(noteProcessor.masterIncomingViewingPublicKey), ); this.noteProcessors.push(noteProcessor); } @@ -260,7 +263,7 @@ export class Synchronizer { * @returns A promise that resolves once the account is added to the Synchronizer. */ public addAccount(publicKey: PublicKey, keyStore: KeyStore, startingBlock: number) { - const predicate = (x: NoteProcessor) => x.publicKey.equals(publicKey); + const predicate = (x: NoteProcessor) => x.masterIncomingViewingPublicKey.equals(publicKey); const processor = this.noteProcessors.find(predicate) ?? this.noteProcessorsToCatchUp.find(predicate); if (processor) { return; @@ -282,7 +285,7 @@ export class Synchronizer { if (!completeAddress) { throw new Error(`Checking if account is synched is not possible for ${account} because it is not registered.`); } - const findByPublicKey = (x: NoteProcessor) => x.publicKey.equals(completeAddress.publicKey); + const findByPublicKey = (x: NoteProcessor) => x.masterIncomingViewingPublicKey.equals(completeAddress.publicKey); const processor = this.noteProcessors.find(findByPublicKey) ?? this.noteProcessorsToCatchUp.find(findByPublicKey); if (!processor) { throw new Error( @@ -315,7 +318,9 @@ export class Synchronizer { const lastBlockNumber = this.getSynchedBlockNumber(); return { blocks: lastBlockNumber, - notes: Object.fromEntries(this.noteProcessors.map(n => [n.publicKey.toString(), n.status.syncedToBlock])), + notes: Object.fromEntries( + this.noteProcessors.map(n => [n.masterIncomingViewingPublicKey.toString(), n.status.syncedToBlock]), + ), }; } @@ -345,7 +350,7 @@ export class Synchronizer { // to be safe, try each note processor in case the deferred notes are for different accounts. for (const processor of this.noteProcessors) { const decodedNotes = await processor.decodeDeferredNotes( - deferredNotes.filter(n => n.publicKey.equals(processor.publicKey)), + deferredNotes.filter(n => n.publicKey.equals(processor.masterIncomingViewingPublicKey)), ); newNotes.push(...decodedNotes); } diff --git a/yarn-project/simulator/src/acvm/oracle/oracle.ts b/yarn-project/simulator/src/acvm/oracle/oracle.ts index 2b967a7c98b..f1271b791dd 100644 --- a/yarn-project/simulator/src/acvm/oracle/oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/oracle.ts @@ -42,13 +42,14 @@ export class Oracle { return unpacked.map(toACVMField); } - async getNullifierKeyPair([accountAddress]: ACVMField[]): Promise { - const { publicKey, secretKey } = await this.typedOracle.getNullifierKeyPair(fromACVMField(accountAddress)); + async getNullifierKeys([accountAddress]: ACVMField[]): Promise { + const { masterNullifierPublicKey, appNullifierSecretKey } = await this.typedOracle.getNullifierKeys( + fromACVMField(accountAddress), + ); return [ - toACVMField(publicKey.x), - toACVMField(publicKey.y), - toACVMField(secretKey.high), - toACVMField(secretKey.low), + toACVMField(masterNullifierPublicKey.x), + toACVMField(masterNullifierPublicKey.y), + toACVMField(appNullifierSecretKey), ]; } diff --git a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts index e0dd6ce24f4..70f57233af1 100644 --- a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts @@ -10,7 +10,6 @@ import { type UnencryptedL2Log, } from '@aztec/circuit-types'; import { - type GrumpkinPrivateKey, type Header, type L1_TO_L2_MSG_TREE_HEIGHT, type PrivateCallStackItem, @@ -21,18 +20,12 @@ import { type AztecAddress } from '@aztec/foundation/aztec-address'; import { Fr } from '@aztec/foundation/fields'; import { type ContractInstance } from '@aztec/types/contracts'; -/** - * A pair of public key and secret key. - */ -export interface KeyPair { - /** - * Public key. - */ - publicKey: PublicKey; - /** - * Secret Key. - */ - secretKey: GrumpkinPrivateKey; +/** Nullifier keys which both correspond to the same master nullifier secret key. */ +export interface NullifierKeys { + /** Master nullifier public key. */ + masterNullifierPublicKey: PublicKey; + /** App nullifier secret key. */ + appNullifierSecretKey: Fr; } /** @@ -96,8 +89,8 @@ export abstract class TypedOracle { throw new OracleMethodNotAvailableError('unpackReturns'); } - getNullifierKeyPair(_accountAddress: AztecAddress): Promise { - throw new OracleMethodNotAvailableError('getNullifierKeyPair'); + getNullifierKeys(_accountAddress: AztecAddress): Promise { + throw new OracleMethodNotAvailableError('getNullifierKeys'); } getPublicKeyAndPartialAddress(_address: AztecAddress): Promise { diff --git a/yarn-project/simulator/src/client/db_oracle.ts b/yarn-project/simulator/src/client/db_oracle.ts index 4338f4c3a9b..3c3d5126814 100644 --- a/yarn-project/simulator/src/client/db_oracle.ts +++ b/yarn-project/simulator/src/client/db_oracle.ts @@ -12,7 +12,7 @@ import { type EthAddress } from '@aztec/foundation/eth-address'; import { type Fr } from '@aztec/foundation/fields'; import { type ContractInstance } from '@aztec/types/contracts'; -import { type KeyPair, type NoteData } from '../acvm/index.js'; +import { type NoteData, type NullifierKeys } from '../acvm/index.js'; import { type CommitmentsDB } from '../public/db.js'; /** @@ -66,16 +66,14 @@ export interface DBOracle extends CommitmentsDB { popCapsule(): Promise; /** - * Retrieve the nullifier key pair associated with a specific account. - * The function only allows access to the secret keys of the transaction creator, - * and throws an error if the address does not match the account address of the key pair. + * Retrieve nullifier keys associated with a specific account and app/contract address. * * @param accountAddress - The account address. * @param contractAddress - The contract address. - * @returns A Promise that resolves to the nullifier key pair. - * @throws An Error if the input address does not match the account address of the key pair. + * @returns A Promise that resolves to nullifier keys of a requested account and contract. + * @throws An error if the account is not registered in the database. */ - getNullifierKeyPair(accountAddress: AztecAddress, contractAddress: AztecAddress): Promise; + getNullifierKeys(accountAddress: AztecAddress, contractAddress: AztecAddress): Promise; /** * Retrieves a set of notes stored in the database for a given contract address and storage slot. diff --git a/yarn-project/simulator/src/client/private_execution.test.ts b/yarn-project/simulator/src/client/private_execution.test.ts index 9e2b8fe0d83..a605f2d9876 100644 --- a/yarn-project/simulator/src/client/private_execution.test.ts +++ b/yarn-project/simulator/src/client/private_execution.test.ts @@ -5,16 +5,17 @@ import { CompleteAddress, FunctionData, GasSettings, + type GrumpkinPrivateKey, Header, L1_TO_L2_MSG_TREE_HEIGHT, NOTE_HASH_TREE_HEIGHT, PartialStateReference, PublicCallRequest, + type PublicKey, StateReference, TxContext, - computeNullifierSecretKey, - computeSiloedNullifierSecretKey, - derivePublicKey, + computeAppNullifierSecretKey, + deriveKeys, getContractInstanceFromDeployParams, nonEmptySideEffects, sideEffectArrayToValueArray, @@ -33,7 +34,7 @@ import { AztecAddress } from '@aztec/foundation/aztec-address'; import { times } from '@aztec/foundation/collection'; import { pedersenHash, randomInt } from '@aztec/foundation/crypto'; import { EthAddress } from '@aztec/foundation/eth-address'; -import { Fr, GrumpkinScalar } from '@aztec/foundation/fields'; +import { Fr } from '@aztec/foundation/fields'; import { type DebugLogger, createDebugLogger } from '@aztec/foundation/log'; import { type FieldsOf } from '@aztec/foundation/types'; import { openTmpStore } from '@aztec/kv-store/utils'; @@ -51,7 +52,7 @@ import { jest } from '@jest/globals'; import { type MockProxy, mock } from 'jest-mock-extended'; import { toFunctionSelector } from 'viem'; -import { type KeyPair, MessageLoadOracleInputs } from '../acvm/index.js'; +import { MessageLoadOracleInputs } from '../acvm/index.js'; import { buildL1ToL2Message } from '../test/utils.js'; import { computeSlotForMapping } from '../utils.js'; import { type DBOracle } from './db_oracle.js'; @@ -70,14 +71,17 @@ describe('Private Execution test suite', () => { let logger: DebugLogger; const defaultContractAddress = AztecAddress.random(); - const ownerPk = GrumpkinScalar.fromString('2dcc5485a58316776299be08c78fa3788a1a7961ae30dc747fb1be17692a8d32'); - const recipientPk = GrumpkinScalar.fromString('0c9ed344548e8f9ba8aa3c9f8651eaa2853130f6c1e9c050ccf198f7ea18a7ec'); + const ownerSk = Fr.fromString('2dcc5485a58316776299be08c78fa3788a1a7961ae30dc747fb1be17692a8d32'); + const recipientSk = Fr.fromString('0c9ed344548e8f9ba8aa3c9f8651eaa2853130f6c1e9c050ccf198f7ea18a7ec'); let owner: AztecAddress; let recipient: AztecAddress; let ownerCompleteAddress: CompleteAddress; let recipientCompleteAddress: CompleteAddress; - let ownerNullifierKeyPair: KeyPair; - let recipientNullifierKeyPair: KeyPair; + + let ownerMasterNullifierPublicKey: PublicKey; + let recipientMasterNullifierPublicKey: PublicKey; + let ownerMasterNullifierSecretKey: GrumpkinPrivateKey; + let recipientMasterNullifierSecretKey: GrumpkinPrivateKey; const treeHeights: { [name: string]: number } = { noteHash: NOTE_HASH_TREE_HEIGHT, @@ -167,39 +171,38 @@ describe('Private Execution test suite', () => { beforeAll(() => { logger = createDebugLogger('aztec:test:private_execution'); - ownerCompleteAddress = CompleteAddress.fromPrivateKeyAndPartialAddress(ownerPk, Fr.random()); - recipientCompleteAddress = CompleteAddress.fromPrivateKeyAndPartialAddress(recipientPk, Fr.random()); + const ownerPartialAddress = Fr.random(); + ownerCompleteAddress = CompleteAddress.fromSecretKeyAndPartialAddress(ownerSk, ownerPartialAddress); - owner = ownerCompleteAddress.address; - recipient = recipientCompleteAddress.address; + const allOwnerKeys = deriveKeys(ownerSk); + ownerMasterNullifierPublicKey = allOwnerKeys.masterNullifierPublicKey; + ownerMasterNullifierSecretKey = allOwnerKeys.masterNullifierSecretKey; - const ownerNullifierSecretKey = computeNullifierSecretKey(ownerPk); - ownerNullifierKeyPair = { - secretKey: ownerNullifierSecretKey, - publicKey: derivePublicKey(ownerNullifierSecretKey), - }; + const recipientPartialAddress = Fr.random(); + recipientCompleteAddress = CompleteAddress.fromSecretKeyAndPartialAddress(recipientSk, recipientPartialAddress); - const recipientNullifierSecretKey = computeNullifierSecretKey(recipientPk); - recipientNullifierKeyPair = { - secretKey: recipientNullifierSecretKey, - publicKey: derivePublicKey(recipientNullifierSecretKey), - }; + const allRecipientKeys = deriveKeys(recipientSk); + recipientMasterNullifierPublicKey = allRecipientKeys.masterNullifierPublicKey; + recipientMasterNullifierSecretKey = allRecipientKeys.masterNullifierSecretKey; + + owner = ownerCompleteAddress.address; + recipient = recipientCompleteAddress.address; }); beforeEach(() => { trees = {}; oracle = mock(); - oracle.getNullifierKeyPair.mockImplementation((accountAddress: AztecAddress, contractAddress: AztecAddress) => { + oracle.getNullifierKeys.mockImplementation((accountAddress: AztecAddress, contractAddress: AztecAddress) => { if (accountAddress.equals(ownerCompleteAddress.address)) { return Promise.resolve({ - publicKey: ownerNullifierKeyPair.publicKey, - secretKey: computeSiloedNullifierSecretKey(ownerNullifierKeyPair.secretKey, contractAddress), + masterNullifierPublicKey: ownerMasterNullifierPublicKey, + appNullifierSecretKey: computeAppNullifierSecretKey(ownerMasterNullifierSecretKey, contractAddress), }); } if (accountAddress.equals(recipientCompleteAddress.address)) { return Promise.resolve({ - publicKey: recipientNullifierKeyPair.publicKey, - secretKey: computeSiloedNullifierSecretKey(recipientNullifierKeyPair.secretKey, contractAddress), + masterNullifierPublicKey: recipientMasterNullifierPublicKey, + appNullifierSecretKey: computeAppNullifierSecretKey(recipientMasterNullifierSecretKey, contractAddress), }); } throw new Error(`Unknown address ${accountAddress}`); @@ -902,14 +905,9 @@ describe('Private Execution test suite', () => { expect(result.returnValues).toEqual([new Fr(amountToTransfer)]); const nullifier = result.callStackItem.publicInputs.newNullifiers[0]; - const siloedNullifierSecretKey = computeSiloedNullifierSecretKey( - ownerNullifierKeyPair.secretKey, - contractAddress, - ); const expectedNullifier = pedersenHash([ innerNoteHash, - siloedNullifierSecretKey.low, - siloedNullifierSecretKey.high, + computeAppNullifierSecretKey(ownerMasterNullifierSecretKey, contractAddress), ]); expect(nullifier.value).toEqual(expectedNullifier); }); @@ -977,14 +975,9 @@ describe('Private Execution test suite', () => { expect(execGetThenNullify.returnValues).toEqual([new Fr(amountToTransfer)]); const nullifier = execGetThenNullify.callStackItem.publicInputs.newNullifiers[0]; - const siloedNullifierSecretKey = computeSiloedNullifierSecretKey( - ownerNullifierKeyPair.secretKey, - contractAddress, - ); const expectedNullifier = pedersenHash([ innerNoteHash, - siloedNullifierSecretKey.low, - siloedNullifierSecretKey.high, + computeAppNullifierSecretKey(ownerMasterNullifierSecretKey, contractAddress), ]); expect(nullifier.value).toEqual(expectedNullifier); }); diff --git a/yarn-project/simulator/src/client/simulator.test.ts b/yarn-project/simulator/src/client/simulator.test.ts index 4bb3dc3d3f3..c22244d2881 100644 --- a/yarn-project/simulator/src/client/simulator.test.ts +++ b/yarn-project/simulator/src/client/simulator.test.ts @@ -1,5 +1,5 @@ -import { type AztecNode, Note } from '@aztec/circuit-types'; -import { CompleteAddress } from '@aztec/circuits.js'; +import { type AztecNode, CompleteAddress, Note } from '@aztec/circuit-types'; +import { computeAppNullifierSecretKey, deriveKeys } from '@aztec/circuits.js'; import { computeUniqueCommitment, siloNoteHash } from '@aztec/circuits.js/hash'; import { ABIParameterVisibility, @@ -8,7 +8,7 @@ import { } from '@aztec/foundation/abi'; import { AztecAddress } from '@aztec/foundation/aztec-address'; import { pedersenHash } from '@aztec/foundation/crypto'; -import { Fr, GrumpkinScalar, Point } from '@aztec/foundation/fields'; +import { Fr } from '@aztec/foundation/fields'; import { TokenContractArtifact } from '@aztec/noir-contracts.js/Token'; import { type MockProxy, mock } from 'jest-mock-extended'; @@ -21,18 +21,30 @@ describe('Simulator', () => { let node: MockProxy; let simulator: AcirSimulator; - const ownerPk = GrumpkinScalar.fromString('2dcc5485a58316776299be08c78fa3788a1a7961ae30dc747fb1be17692a8d32'); - const ownerCompleteAddress = CompleteAddress.fromPrivateKeyAndPartialAddress(ownerPk, Fr.random()); - const owner = ownerCompleteAddress.address; - const ownerNullifierSecretKey = GrumpkinScalar.random(); - const ownerNullifierPublicKey = Point.random(); + let owner: AztecAddress; + let contractAddress: AztecAddress; + let appNullifierSecretKey: Fr; beforeEach(() => { + const ownerSk = Fr.fromString('2dcc5485a58316776299be08c78fa3788a1a7961ae30dc747fb1be17692a8d32'); + const allOwnerKeys = deriveKeys(ownerSk); + + const ownerMasterNullifierPublicKey = allOwnerKeys.masterNullifierPublicKey; + const ownerMasterNullifierSecretKey = allOwnerKeys.masterNullifierSecretKey; + + contractAddress = AztecAddress.random(); + + const ownerPartialAddress = Fr.random(); + const ownerCompleteAddress = CompleteAddress.fromSecretKeyAndPartialAddress(ownerSk, ownerPartialAddress); + owner = ownerCompleteAddress.address; + + appNullifierSecretKey = computeAppNullifierSecretKey(ownerMasterNullifierSecretKey, contractAddress); + oracle = mock(); node = mock(); - oracle.getNullifierKeyPair.mockResolvedValue({ - secretKey: ownerNullifierSecretKey, - publicKey: ownerNullifierPublicKey, + oracle.getNullifierKeys.mockResolvedValue({ + masterNullifierPublicKey: ownerMasterNullifierPublicKey, + appNullifierSecretKey, }); oracle.getCompleteAddress.mockResolvedValue(ownerCompleteAddress); @@ -41,10 +53,9 @@ describe('Simulator', () => { describe('computeNoteHashAndNullifier', () => { const artifact = getFunctionArtifact(TokenContractArtifact, 'compute_note_hash_and_nullifier'); - const contractAddress = AztecAddress.random(); const nonce = Fr.random(); const storageSlot = Fr.random(); - const noteTypeId = new Fr(8411110710111078111116101n); // TokenNote + const noteTypeId = new Fr(8411110710111078111116101n); // TODO(#5833): This can be imported from artifact now const createNote = (amount = 123n) => new Note([new Fr(amount), owner.toField(), Fr.random()]); @@ -56,11 +67,8 @@ describe('Simulator', () => { const innerNoteHash = pedersenHash([storageSlot, tokenNoteHash]); const siloedNoteHash = siloNoteHash(contractAddress, innerNoteHash); const uniqueSiloedNoteHash = computeUniqueCommitment(nonce, siloedNoteHash); - const innerNullifier = pedersenHash([ - uniqueSiloedNoteHash, - ownerNullifierSecretKey.low, - ownerNullifierSecretKey.high, - ]); + // TODO(#5832): all the pedersen hashes in notes should be replaced with poseidon2 + const innerNullifier = pedersenHash([uniqueSiloedNoteHash, appNullifierSecretKey]); const result = await simulator.computeNoteHashAndNullifier(contractAddress, nonce, storageSlot, noteTypeId, note); diff --git a/yarn-project/simulator/src/client/unconstrained_execution.test.ts b/yarn-project/simulator/src/client/unconstrained_execution.test.ts index dea57f9e00b..fe099451a6f 100644 --- a/yarn-project/simulator/src/client/unconstrained_execution.test.ts +++ b/yarn-project/simulator/src/client/unconstrained_execution.test.ts @@ -2,7 +2,7 @@ import { type AztecNode, type FunctionCall, Note } from '@aztec/circuit-types'; import { CompleteAddress, FunctionData, Header } from '@aztec/circuits.js'; import { FunctionSelector, encodeArguments } from '@aztec/foundation/abi'; import { AztecAddress } from '@aztec/foundation/aztec-address'; -import { Fr, GrumpkinScalar } from '@aztec/foundation/fields'; +import { Fr } from '@aztec/foundation/fields'; import { StatefulTestContractArtifact } from '@aztec/noir-contracts.js/StatefulTest'; import { mock } from 'jest-mock-extended'; @@ -21,7 +21,7 @@ describe('Unconstrained Execution test suite', () => { }); describe('private token contract', () => { - const ownerPk = GrumpkinScalar.fromString('2dcc5485a58316776299be08c78fa3788a1a7961ae30dc747fb1be17692a8d32'); + const ownerSecretKey = Fr.fromString('2dcc5485a58316776299be08c78fa3788a1a7961ae30dc747fb1be17692a8d32'); let owner: AztecAddress; @@ -30,7 +30,7 @@ describe('Unconstrained Execution test suite', () => { }; beforeEach(() => { - const ownerCompleteAddress = CompleteAddress.fromPrivateKeyAndPartialAddress(ownerPk, Fr.random()); + const ownerCompleteAddress = CompleteAddress.fromSecretKeyAndPartialAddress(ownerSecretKey, Fr.random()); owner = ownerCompleteAddress.address; oracle.getCompleteAddress.mockImplementation((address: AztecAddress) => { diff --git a/yarn-project/simulator/src/client/view_data_oracle.ts b/yarn-project/simulator/src/client/view_data_oracle.ts index 7ab30411eda..b4c02039175 100644 --- a/yarn-project/simulator/src/client/view_data_oracle.ts +++ b/yarn-project/simulator/src/client/view_data_oracle.ts @@ -14,7 +14,7 @@ import { Fr } from '@aztec/foundation/fields'; import { createDebugLogger } from '@aztec/foundation/log'; import { type ContractInstance } from '@aztec/types/contracts'; -import { type NoteData, TypedOracle } from '../acvm/index.js'; +import { type NoteData, type NullifierKeys, TypedOracle } from '../acvm/index.js'; import { type DBOracle } from './db_oracle.js'; import { pickNotes } from './pick_notes.js'; @@ -35,11 +35,14 @@ export class ViewDataOracle extends TypedOracle { } /** - * Return the nullifier key pair of an account to use in a specific contract. - * @param account - The account address of the nullifier key. + * Retrieve nullifier keys associated with a specific account and app/contract address. + * + * @param accountAddress - The account address. + * @returns A Promise that resolves to nullifier keys of a requested account and contract. + * @throws An error if the account is not registered in the database. */ - public override getNullifierKeyPair(account: AztecAddress) { - return this.db.getNullifierKeyPair(account, this.contractAddress); + public override getNullifierKeys(account: AztecAddress): Promise { + return this.db.getNullifierKeys(account, this.contractAddress); } /** diff --git a/yarn-project/update-snapshots.sh b/yarn-project/update-snapshots.sh index 56ee3cf087f..888886de1da 100755 --- a/yarn-project/update-snapshots.sh +++ b/yarn-project/update-snapshots.sh @@ -4,8 +4,10 @@ set -e yarn build:fast -OVERWRITE_TEST_DATA=1 yarn workspace @aztec/end-to-end test integration_l1_publisher.test.ts -AZTEC_GENERATE_TEST_DATA=1 yarn workspace @aztec/end-to-end test e2e_nested_contract -t 'performs nested calls' +export AZTEC_GENERATE_TEST_DATA=1 + +yarn workspace @aztec/end-to-end test integration_l1_publisher.test.ts +yarn workspace @aztec/end-to-end test e2e_nested_contract -t 'performs nested calls' yarn workspace @aztec/circuits.js test -u yarn workspace @aztec/noir-protocol-circuits-types test -u From e7d2aff3a1922dc685bc859901dffdb83933dff2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Fri, 19 Apr 2024 10:29:46 -0300 Subject: [PATCH 032/102] chore: refactor e2e tests to use the new simulate fn (#5854) With https://github.com/AztecProtocol/aztec-packages/pull/5762 we can now use `simulate()` to directly get values out of contract calls (i.e. https://github.com/AztecProtocol/aztec-packages/issues/2665). This PR refactors some e2e tests that relied on events to get values out and replaces those with proper `simulate()` calls. Co-authored-by: ludamad --- .../contracts/auth_contract/src/main.nr | 21 ++------ .../contracts/test_contract/src/main.nr | 14 ++--- .../end-to-end/src/e2e_auth_contract.test.ts | 53 ++++++++----------- .../end-to-end/src/e2e_note_getter.test.ts | 30 ++--------- 4 files changed, 37 insertions(+), 81 deletions(-) diff --git a/noir-projects/noir-contracts/contracts/auth_contract/src/main.nr b/noir-projects/noir-contracts/contracts/auth_contract/src/main.nr index a8025208c60..36df4cbeb45 100644 --- a/noir-projects/noir-contracts/contracts/auth_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/auth_contract/src/main.nr @@ -33,32 +33,21 @@ contract Auth { } #[aztec(public)] - fn get_authorized() { - // We emit logs because we cannot otherwise return these values - emit_unencrypted_log( - &mut context, - storage.authorized.get_current_value_in_public() - ); + fn get_authorized() -> AztecAddress { + storage.authorized.get_current_value_in_public() } #[aztec(public)] - fn get_scheduled_authorized() { - // We emit logs because we cannot otherwise return these values - emit_unencrypted_log( - &mut context, - storage.authorized.get_scheduled_value_in_public().0 - ); + fn get_scheduled_authorized() -> AztecAddress { + storage.authorized.get_scheduled_value_in_public().0 } #[aztec(private)] - fn do_private_authorized_thing(value: Field) { + fn do_private_authorized_thing() { // Reading a value from authorized in private automatically adds an extra validity condition: the base rollup // circuit will reject this tx if included in a block past the block horizon, which is as far as the circuit can // guarantee the value will not change from some historical value (due to CHANGE_AUTHORIZED_DELAY_BLOCKS). let authorized = storage.authorized.get_current_value_in_private(); assert_eq(authorized, context.msg_sender(), "caller is not authorized"); - - // We emit logs because we cannot otherwise return these values - emit_unencrypted_log_from_private(&mut context, value); } } diff --git a/noir-projects/noir-contracts/contracts/test_contract/src/main.nr b/noir-projects/noir-contracts/contracts/test_contract/src/main.nr index e03a92b94d9..3e6b04baf2d 100644 --- a/noir-projects/noir-contracts/contracts/test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/test_contract/src/main.nr @@ -95,7 +95,7 @@ contract Test { } #[aztec(private)] - fn call_get_notes(storage_slot: Field, active_or_nullified: bool) { + fn call_get_notes(storage_slot: Field, active_or_nullified: bool) -> Field { assert( storage_slot != storage.example_constant.get_storage_slot(), "this storage slot is reserved for example_constant" ); @@ -107,14 +107,11 @@ contract Test { let opt_notes: [Option; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL] = get_notes(&mut context, storage_slot, options); - // We can't get the return value of a private function from the outside world in an end to end test, so we - // expose it via an unecrypted log instead. - let value = opt_notes[0].unwrap().value; - emit_unencrypted_log_from_private(&mut context, value); + opt_notes[0].unwrap().value } #[aztec(private)] - fn call_get_notes_many(storage_slot: Field, active_or_nullified: bool) { + fn call_get_notes_many(storage_slot: Field, active_or_nullified: bool) -> [Field; 2] { assert( storage_slot != storage.example_constant.get_storage_slot(), "this storage slot is reserved for example_constant" ); @@ -126,10 +123,7 @@ contract Test { let opt_notes: [Option; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL] = get_notes(&mut context, storage_slot, options); - // We can't get the return value of a private function from the outside world in an end to end test, so we - // expose it via an unecrypted log instead. - emit_unencrypted_log_from_private(&mut context, opt_notes[0].unwrap().value); - emit_unencrypted_log_from_private(&mut context, opt_notes[1].unwrap().value); + [opt_notes[0].unwrap().value, opt_notes[1].unwrap().value] } unconstrained fn call_view_notes(storage_slot: Field, active_or_nullified: bool) -> pub Field { diff --git a/yarn-project/end-to-end/src/e2e_auth_contract.test.ts b/yarn-project/end-to-end/src/e2e_auth_contract.test.ts index b2568365140..099885c1c9a 100644 --- a/yarn-project/end-to-end/src/e2e_auth_contract.test.ts +++ b/yarn-project/end-to-end/src/e2e_auth_contract.test.ts @@ -1,4 +1,4 @@ -import { type AccountWallet, AztecAddress, type ContractFunctionInteraction, Fr, type PXE } from '@aztec/aztec.js'; +import { type AccountWallet, AztecAddress, Fr, type PXE } from '@aztec/aztec.js'; import { AuthContract } from '@aztec/noir-contracts.js'; import { jest } from '@jest/globals'; @@ -19,7 +19,6 @@ describe('e2e_auth_contract', () => { let contract: AuthContract; - const VALUE = 3; const DELAY = 5; beforeAll(async () => { @@ -48,40 +47,30 @@ describe('e2e_auth_contract', () => { } } - async function assertLoggedAddress(interaction: ContractFunctionInteraction, address: AztecAddress) { - const logs = await pxe.getUnencryptedLogs({ txHash: (await interaction.send().wait()).txHash }); - expect(AztecAddress.fromBuffer(logs.logs[0].log.data)).toEqual(address); - } - - async function assertLoggedNumber(interaction: ContractFunctionInteraction, value: number) { - const logs = await pxe.getUnencryptedLogs({ txHash: (await interaction.send().wait()).txHash }); - expect(Fr.fromBuffer(logs.logs[0].log.data)).toEqual(new Fr(value)); - } - it('authorized is unset initially', async () => { - await assertLoggedAddress(contract.methods.get_authorized(), AztecAddress.ZERO); + expect(await contract.methods.get_authorized().simulate()).toEqual(AztecAddress.ZERO); }); it('admin sets authorized', async () => { await contract.withWallet(admin).methods.set_authorized(authorized.getAddress()).send().wait(); - await assertLoggedAddress(contract.methods.get_scheduled_authorized(), authorized.getAddress()); + expect(await contract.methods.get_scheduled_authorized().simulate()).toEqual(authorized.getAddress()); }); it('authorized is not yet set, cannot use permission', async () => { - await assertLoggedAddress(contract.methods.get_authorized(), AztecAddress.ZERO); + expect(await contract.methods.get_authorized().simulate()).toEqual(AztecAddress.ZERO); - await expect( - contract.withWallet(authorized).methods.do_private_authorized_thing(VALUE).send().wait(), - ).rejects.toThrow('caller is not authorized'); + await expect(contract.withWallet(authorized).methods.do_private_authorized_thing().send().wait()).rejects.toThrow( + 'caller is not authorized', + ); }); it('after a while the scheduled change is effective and can be used with max block restriction', async () => { await mineBlocks(DELAY); // This gets us past the block of change - await assertLoggedAddress(contract.methods.get_authorized(), authorized.getAddress()); + expect(await contract.methods.get_authorized().simulate()).toEqual(authorized.getAddress()); - const interaction = contract.withWallet(authorized).methods.do_private_authorized_thing(VALUE); + const interaction = contract.withWallet(authorized).methods.do_private_authorized_thing(); const tx = await interaction.prove(); @@ -94,32 +83,36 @@ describe('e2e_auth_contract', () => { expect(tx.data.forRollup!.rollupValidationRequests.maxBlockNumber.isSome).toEqual(true); expect(tx.data.forRollup!.rollupValidationRequests.maxBlockNumber.value).toEqual(new Fr(expectedMaxBlockNumber)); - await assertLoggedNumber(interaction, VALUE); + expect((await interaction.send().wait()).status).toEqual('mined'); }); it('a new authorized address is set but not immediately effective, the previous one retains permissions', async () => { await contract.withWallet(admin).methods.set_authorized(other.getAddress()).send().wait(); - await assertLoggedAddress(contract.methods.get_authorized(), authorized.getAddress()); + expect(await contract.methods.get_authorized().simulate()).toEqual(authorized.getAddress()); - await assertLoggedAddress(contract.methods.get_scheduled_authorized(), other.getAddress()); + expect(await contract.methods.get_scheduled_authorized().simulate()).toEqual(other.getAddress()); - await expect(contract.withWallet(other).methods.do_private_authorized_thing(VALUE).send().wait()).rejects.toThrow( + await expect(contract.withWallet(other).methods.do_private_authorized_thing().send().wait()).rejects.toThrow( 'caller is not authorized', ); - await assertLoggedNumber(contract.withWallet(authorized).methods.do_private_authorized_thing(VALUE), VALUE); + expect((await contract.withWallet(authorized).methods.do_private_authorized_thing().send().wait()).status).toEqual( + 'mined', + ); }); it('after some time the scheduled change is made effective', async () => { await mineBlocks(DELAY); // This gets us past the block of change - await assertLoggedAddress(contract.methods.get_authorized(), other.getAddress()); + expect(await contract.methods.get_authorized().simulate()).toEqual(other.getAddress()); - await expect( - contract.withWallet(authorized).methods.do_private_authorized_thing(VALUE).send().wait(), - ).rejects.toThrow('caller is not authorized'); + await expect(contract.withWallet(authorized).methods.do_private_authorized_thing().send().wait()).rejects.toThrow( + 'caller is not authorized', + ); - await assertLoggedNumber(contract.withWallet(other).methods.do_private_authorized_thing(VALUE), VALUE); + expect((await contract.withWallet(other).methods.do_private_authorized_thing().send().wait()).status).toEqual( + 'mined', + ); }); }); diff --git a/yarn-project/end-to-end/src/e2e_note_getter.test.ts b/yarn-project/end-to-end/src/e2e_note_getter.test.ts index 54a2084be58..c7deb286a92 100644 --- a/yarn-project/end-to-end/src/e2e_note_getter.test.ts +++ b/yarn-project/end-to-end/src/e2e_note_getter.test.ts @@ -1,4 +1,4 @@ -import { type AztecAddress, Comparator, Fr, type Wallet, toBigInt } from '@aztec/aztec.js'; +import { type AztecAddress, Comparator, Fr, type Wallet } from '@aztec/aztec.js'; import { DocsExampleContract, TestContract } from '@aztec/noir-contracts.js'; import { setup } from './fixtures/utils.js'; @@ -168,7 +168,7 @@ describe('e2e_note_getter', () => { async function assertNoteIsReturned(storageSlot: number, expectedValue: number, activeOrNullified: boolean) { const viewNotesResult = await contract.methods.call_view_notes(storageSlot, activeOrNullified).simulate(); - const getNotesResult = await callGetNotes(storageSlot, activeOrNullified); + const getNotesResult = await contract.methods.call_get_notes(storageSlot, activeOrNullified).simulate(); expect(viewNotesResult).toEqual(getNotesResult); expect(viewNotesResult).toEqual(BigInt(expectedValue)); @@ -183,28 +183,6 @@ describe('e2e_note_getter', () => { ); } - async function callGetNotes(storageSlot: number, activeOrNullified: boolean): Promise { - // call_get_notes exposes the return value via an event since we cannot use simulate() with it. - const tx = contract.methods.call_get_notes(storageSlot, activeOrNullified).send(); - await tx.wait(); - - const logs = (await tx.getUnencryptedLogs()).logs; - expect(logs.length).toBe(1); - - return toBigInt(logs[0].log.data); - } - - async function callGetNotesMany(storageSlot: number, activeOrNullified: boolean): Promise> { - // call_get_notes_many exposes the return values via event since we cannot use simulate() with it. - const tx = contract.methods.call_get_notes_many(storageSlot, activeOrNullified).send(); - await tx.wait(); - - const logs = (await tx.getUnencryptedLogs()).logs; - expect(logs.length).toBe(2); - - return [toBigInt(logs[0].log.data), toBigInt(logs[1].log.data)]; - } - describe('active note only', () => { const activeOrNullified = false; @@ -250,7 +228,9 @@ describe('e2e_note_getter', () => { const viewNotesManyResult = await contract.methods .call_view_notes_many(storageSlot, activeOrNullified) .simulate(); - const getNotesManyResult = await callGetNotesMany(storageSlot, activeOrNullified); + const getNotesManyResult = await contract.methods + .call_get_notes_many(storageSlot, activeOrNullified) + .simulate(); // We can't be sure in which order the notes will be returned, so we simply sort them to test equality. Note // however that both view_notes and get_notes get the exact same result. From a0a9668d933907a89f21077fd700b6d2f44e6c74 Mon Sep 17 00:00:00 2001 From: Alex Gherghisan Date: Fri, 19 Apr 2024 14:40:28 +0100 Subject: [PATCH 033/102] feat: add proving queue (#5754) Extracts the proving queue out of the orchestrator --- .../prover-client/src/mocks/test_context.ts | 12 +- .../src/orchestrator/orchestrator.ts | 555 ++++++++---------- .../orchestrator/orchestrator_errors.test.ts | 6 +- .../orchestrator_failures.test.ts | 12 +- .../orchestrator_lifecycle.test.ts | 6 +- .../orchestrator_mixed_blocks.test.ts | 4 - .../orchestrator_mixed_blocks_2.test.ts | 4 - ...rchestrator_multi_public_functions.test.ts | 4 - .../orchestrator_multiple_blocks.test.ts | 4 - .../orchestrator_public_functions.test.ts | 4 - .../orchestrator_single_blocks.test.ts | 4 - .../src/orchestrator/tx-proving-state.ts | 16 + .../prover-pool/circuit-prover-agent.test.ts | 85 +++ .../src/prover-pool/circuit-prover-agent.ts | 107 ++++ .../prover-pool/memory-proving-queue.test.ts | 70 +++ .../src/prover-pool/memory-proving-queue.ts | 86 +++ .../src/prover-pool/prover-agent.ts | 15 + .../src/prover-pool/prover-pool.ts | 47 ++ .../src/prover-pool/proving-queue.ts | 23 + .../src/prover-pool/proving-request.ts | 81 +++ .../src/prover/bb_prover_base_rollup.test.ts | 6 +- .../src/prover/bb_prover_full_rollup.test.ts | 8 +- .../src/prover/bb_prover_parity.test.ts | 6 +- .../prover/bb_prover_public_kernel.test.ts | 6 +- .../prover-client/src/tx-prover/tx-prover.ts | 20 +- 25 files changed, 797 insertions(+), 394 deletions(-) create mode 100644 yarn-project/prover-client/src/prover-pool/circuit-prover-agent.test.ts create mode 100644 yarn-project/prover-client/src/prover-pool/circuit-prover-agent.ts create mode 100644 yarn-project/prover-client/src/prover-pool/memory-proving-queue.test.ts create mode 100644 yarn-project/prover-client/src/prover-pool/memory-proving-queue.ts create mode 100644 yarn-project/prover-client/src/prover-pool/prover-agent.ts create mode 100644 yarn-project/prover-client/src/prover-pool/prover-pool.ts create mode 100644 yarn-project/prover-client/src/prover-pool/proving-queue.ts create mode 100644 yarn-project/prover-client/src/prover-pool/proving-request.ts diff --git a/yarn-project/prover-client/src/mocks/test_context.ts b/yarn-project/prover-client/src/mocks/test_context.ts index 82d278906c1..42ecc4985c0 100644 --- a/yarn-project/prover-client/src/mocks/test_context.ts +++ b/yarn-project/prover-client/src/mocks/test_context.ts @@ -20,6 +20,8 @@ import * as fs from 'fs/promises'; import { type MockProxy, mock } from 'jest-mock-extended'; import { ProvingOrchestrator } from '../orchestrator/orchestrator.js'; +import { CircuitProverAgent } from '../prover-pool/circuit-prover-agent.js'; +import { ProverPool } from '../prover-pool/prover-pool.js'; import { type BBProverConfig } from '../prover/bb_prover.js'; import { type CircuitProver } from '../prover/interface.js'; import { TestCircuitProver } from '../prover/test_circuit_prover.js'; @@ -35,6 +37,7 @@ export class TestContext { public globalVariables: GlobalVariables, public actualDb: MerkleTreeOperations, public prover: CircuitProver, + public proverPool: ProverPool, public orchestrator: ProvingOrchestrator, public blockNumber: number, public directoriesToCleanup: string[], @@ -43,6 +46,7 @@ export class TestContext { static async new( logger: DebugLogger, + proverCount = 4, createProver: (bbConfig: BBProverConfig) => Promise = _ => Promise.resolve(new TestCircuitProver(new WASMSimulator())), blockNumber = 3, @@ -82,7 +86,10 @@ export class TestContext { localProver = await createProver(bbConfig); } - const orchestrator = await ProvingOrchestrator.new(actualDb, localProver); + const proverPool = new ProverPool(proverCount, i => new CircuitProverAgent(localProver, 10, `${i}`)); + const orchestrator = new ProvingOrchestrator(actualDb, proverPool.queue); + + await proverPool.start(); return new this( publicExecutor, @@ -93,6 +100,7 @@ export class TestContext { globalVariables, actualDb, localProver, + proverPool, orchestrator, blockNumber, [config?.directoryToCleanup ?? ''], @@ -101,7 +109,7 @@ export class TestContext { } async cleanup() { - await this.orchestrator.stop(); + await this.proverPool.stop(); for (const dir of this.directoriesToCleanup.filter(x => x !== '')) { await fs.rm(dir, { recursive: true, force: true }); } diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator.ts b/yarn-project/prover-client/src/orchestrator/orchestrator.ts index 88ae37c05d0..743d1319d32 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator.ts @@ -31,16 +31,20 @@ import { } from '@aztec/circuits.js'; import { makeTuple } from '@aztec/foundation/array'; import { padArrayEnd } from '@aztec/foundation/collection'; -import { MemoryFifo } from '@aztec/foundation/fifo'; import { createDebugLogger } from '@aztec/foundation/log'; +import { promiseWithResolvers } from '@aztec/foundation/promise'; import { type Tuple } from '@aztec/foundation/serialize'; -import { sleep } from '@aztec/foundation/sleep'; -import { elapsed } from '@aztec/foundation/timer'; +import { Timer } from '@aztec/foundation/timer'; import { type MerkleTreeOperations } from '@aztec/world-state'; import { inspect } from 'util'; -import { type CircuitProver } from '../prover/index.js'; +import { type ProvingQueue } from '../prover-pool/proving-queue.js'; +import { + type ProvingRequest, + type ProvingRequestPublicInputs, + ProvingRequestType, +} from '../prover-pool/proving-request.js'; import { buildBaseRollupInput, createMergeRollupInputs, @@ -67,71 +71,17 @@ const logger = createDebugLogger('aztec:prover:proving-orchestrator'); * The proving implementation is determined by the provided prover. This could be for example a local prover or a remote prover pool. */ -const SLEEP_TIME = 50; -const MAX_CONCURRENT_JOBS = 64; - -enum PROMISE_RESULT { - SLEEP, - OPERATIONS, -} - const KernelTypesWithoutFunctions: Set = new Set([ PublicKernelType.NON_PUBLIC, PublicKernelType.TAIL, ]); -/** - * Enums and structs to communicate the type of work required in each request. - */ -export enum PROVING_JOB_TYPE { - STATE_UPDATE, - BASE_ROLLUP, - MERGE_ROLLUP, - ROOT_ROLLUP, - BASE_PARITY, - ROOT_PARITY, - PUBLIC_KERNEL, - PUBLIC_VM, -} - -export type ProvingJob = { - type: PROVING_JOB_TYPE; - operation: () => Promise; -}; - /** * The orchestrator, managing the flow of recursive proving operations required to build the rollup proof tree. */ export class ProvingOrchestrator { private provingState: ProvingState | undefined = undefined; - private jobQueue: MemoryFifo = new MemoryFifo(); - private jobProcessPromise?: Promise; - private stopped = false; - constructor( - private db: MerkleTreeOperations, - private prover: CircuitProver, - private maxConcurrentJobs = MAX_CONCURRENT_JOBS, - ) {} - - // Constructs and starts a new orchestrator - public static async new(db: MerkleTreeOperations, prover: CircuitProver) { - const orchestrator = new ProvingOrchestrator(db, prover); - await orchestrator.start(); - return Promise.resolve(orchestrator); - } - - // Starts the proving job queue - public start() { - this.jobProcessPromise = this.processJobQueue(); - return Promise.resolve(); - } - - // Stops the proving job queue - public async stop() { - this.stopped = true; - this.jobQueue.cancel(); - await this.jobProcessPromise; - } + constructor(private db: MerkleTreeOperations, private queue: ProvingQueue) {} /** * Starts off a new block @@ -185,26 +135,28 @@ export class ProvingOrchestrator { // Update the local trees to include the new l1 to l2 messages await this.db.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2MessagesPadded); - let provingState: ProvingState | undefined = undefined; - - const promise = new Promise((resolve, reject) => { - provingState = new ProvingState( - numTxs, - resolve, - reject, - globalVariables, - l1ToL2MessagesPadded, - baseParityInputs.length, - emptyTx, - messageTreeSnapshot, - newL1ToL2MessageTreeRootSiblingPath, - ); - }).catch((reason: string) => ({ status: PROVING_STATUS.FAILURE, reason } as const)); + const { promise: _promise, resolve, reject } = promiseWithResolvers(); + const promise = _promise.catch( + (reason): ProvingResult => ({ + status: PROVING_STATUS.FAILURE, + reason, + }), + ); + + const provingState = new ProvingState( + numTxs, + resolve, + reject, + globalVariables, + l1ToL2MessagesPadded, + baseParityInputs.length, + emptyTx, + messageTreeSnapshot, + newL1ToL2MessageTreeRootSiblingPath, + ); for (let i = 0; i < baseParityInputs.length; i++) { - this.enqueueJob(provingState, PROVING_JOB_TYPE.BASE_PARITY, () => - this.runBaseParityCircuit(provingState, baseParityInputs[i], i), - ); + this.enqueueBaseParityCircuit(provingState, baseParityInputs[i], i); } this.provingState = provingState; @@ -258,6 +210,7 @@ export class ProvingOrchestrator { * Cancel any further proving of the block */ public cancelBlock() { + this.queue.cancelAll(); this.provingState?.cancel(); } @@ -331,16 +284,14 @@ export class ProvingOrchestrator { if (!numPublicKernels) { // no public functions, go straight to the base rollup logger.debug(`Enqueueing base rollup for tx ${txIndex}`); - this.enqueueJob(provingState, PROVING_JOB_TYPE.BASE_ROLLUP, () => - this.runBaseRollup(provingState, BigInt(txIndex), txProvingState), - ); + this.enqueueBaseRollup(provingState, BigInt(txIndex), txProvingState); return; } // Enqueue all of the VM proving requests // Rather than handle the Kernel Tail as a special case here, we will just handle it inside executeVM for (let i = 0; i < numPublicKernels; i++) { logger.debug(`Enqueueing public VM ${i} for tx ${txIndex}`); - this.enqueueJob(provingState, PROVING_JOB_TYPE.PUBLIC_VM, () => this.executeVM(provingState, txIndex, i)); + this.enqueueVM(provingState, txIndex, i); } } @@ -350,26 +301,89 @@ export class ProvingOrchestrator { * @param jobType - The type of job to be queued * @param job - The actual job, returns a promise notifying of the job's completion */ - private enqueueJob(provingState: ProvingState | undefined, jobType: PROVING_JOB_TYPE, job: () => Promise) { + private enqueueJob( + provingState: ProvingState | undefined, + request: T, + callback: (output: ProvingRequestPublicInputs[T['type']], proof: Proof) => void | Promise, + ) { if (!provingState?.verifyState()) { - logger.debug(`Not enqueueing job, proving state invalid`); + logger.debug(`Not enqueuing job type ${ProvingRequestType[request.type]}, state no longer valid`); return; } // We use a 'safeJob'. We don't want promise rejections in the proving pool, we want to capture the error here // and reject the proving job whilst keeping the event loop free of rejections const safeJob = async () => { try { - await job(); + const timer = new Timer(); + const [publicInputs, proof] = await this.queue.prove(request); + const duration = timer.ms(); + + const inputSize = 'toBuffer' in request.inputs ? request.inputs.toBuffer().length : 0; + const outputSize = 'toBuffer' in publicInputs ? publicInputs.toBuffer().length : 0; + const circuitName = this.getCircuitNameFromRequest(request); + const stats: CircuitSimulationStats | undefined = circuitName + ? { + eventName: 'circuit-simulation', + circuitName, + duration, + inputSize, + outputSize, + } + : undefined; + + logger.debug(`Simulated ${ProvingRequestType[request.type]} circuit duration=${duration}ms`, stats); + + if (!provingState?.verifyState()) { + logger.debug(`State no longer valid, discarding result of job type ${ProvingRequestType[request.type]}`); + return; + } + + await callback(publicInputs, proof); } catch (err) { - logger.error(`Error thrown when proving job type ${PROVING_JOB_TYPE[jobType]}: ${err}`); + logger.error(`Error thrown when proving job type ${ProvingRequestType[request.type]}: ${err}`); provingState!.reject(`${err}`); } }; - const provingJob: ProvingJob = { - type: jobType, - operation: safeJob, - }; - this.jobQueue.put(provingJob); + + // let the callstack unwind before adding the job to the queue + setImmediate(safeJob); + } + + private getCircuitNameFromRequest(request: ProvingRequest): CircuitSimulationStats['circuitName'] | null { + switch (request.type) { + case ProvingRequestType.PUBLIC_VM: + return null; + case ProvingRequestType.PUBLIC_KERNEL_NON_TAIL: + switch (request.kernelType) { + case PublicKernelType.SETUP: + return 'public-kernel-setup'; + case PublicKernelType.APP_LOGIC: + return 'public-kernel-app-logic'; + case PublicKernelType.TEARDOWN: + return 'public-kernel-teardown'; + default: + return null; + } + case ProvingRequestType.PUBLIC_KERNEL_TAIL: + switch (request.kernelType) { + case PublicKernelType.TAIL: + return 'public-kernel-tail'; + default: + return null; + } + case ProvingRequestType.BASE_ROLLUP: + return 'base-rollup'; + case ProvingRequestType.MERGE_ROLLUP: + return 'merge-rollup'; + case ProvingRequestType.ROOT_ROLLUP: + return 'root-rollup'; + case ProvingRequestType.BASE_PARITY: + return 'base-parity'; + case ProvingRequestType.ROOT_PARITY: + return 'root-parity'; + default: + return null; + } } // Updates the merkle trees for a transaction. The first enqueued job for a transaction @@ -414,91 +428,77 @@ export class ProvingOrchestrator { // Executes the base rollup circuit and stored the output as intermediate state for the parent merge/root circuit // Executes the next level of merge if all inputs are available - private async runBaseRollup(provingState: ProvingState | undefined, index: bigint, tx: TxProvingState) { + private enqueueBaseRollup(provingState: ProvingState | undefined, index: bigint, tx: TxProvingState) { + if (!provingState?.verifyState()) { + logger.debug('Not running base rollup, state invalid'); + return; + } if ( !tx.baseRollupInputs.kernelData.publicInputs.end.encryptedLogsHash .toBuffer() .equals(tx.processedTx.encryptedLogs.hash()) ) { - throw new Error( + provingState.reject( `Encrypted logs hash mismatch: ${ tx.baseRollupInputs.kernelData.publicInputs.end.encryptedLogsHash } === ${Fr.fromBuffer(tx.processedTx.encryptedLogs.hash())}`, ); + return; } if ( !tx.baseRollupInputs.kernelData.publicInputs.end.unencryptedLogsHash .toBuffer() .equals(tx.processedTx.unencryptedLogs.hash()) ) { - throw new Error( + provingState.reject( `Unencrypted logs hash mismatch: ${ tx.baseRollupInputs.kernelData.publicInputs.end.unencryptedLogsHash } === ${Fr.fromBuffer(tx.processedTx.unencryptedLogs.hash())}`, ); - } - if (!provingState?.verifyState()) { - logger.debug('Not running base rollup, state invalid'); return; } - const [duration, baseRollupOutputs] = await elapsed(async () => { - const [rollupOutput, proof] = await this.prover.getBaseRollupProof(tx.baseRollupInputs); - validatePartialState(rollupOutput.end, tx.treeSnapshots); - return { rollupOutput, proof }; - }); - logger.debug(`Simulated base rollup circuit`, { - eventName: 'circuit-simulation', - circuitName: 'base-rollup', - duration, - inputSize: tx.baseRollupInputs.toBuffer().length, - outputSize: baseRollupOutputs.rollupOutput.toBuffer().length, - } satisfies CircuitSimulationStats); - if (!provingState?.verifyState()) { - logger.debug(`Discarding job as state no longer valid`); - return; - } - const currentLevel = provingState.numMergeLevels + 1n; - logger.info(`Completed base rollup at index ${index}, current level ${currentLevel}`); - this.storeAndExecuteNextMergeLevel(provingState, currentLevel, index, [ - baseRollupOutputs.rollupOutput, - baseRollupOutputs.proof, - ]); + + this.enqueueJob( + provingState, + { + inputs: tx.baseRollupInputs, + type: ProvingRequestType.BASE_ROLLUP, + }, + (publicInputs, proof) => { + validatePartialState(publicInputs.end, tx.treeSnapshots); + const currentLevel = provingState.numMergeLevels + 1n; + this.storeAndExecuteNextMergeLevel(provingState, currentLevel, index, [publicInputs, proof]); + }, + ); } // Executes the merge rollup circuit and stored the output as intermediate state for the parent merge/root circuit // Enqueues the next level of merge if all inputs are available - private async runMergeRollup( - provingState: ProvingState | undefined, + private enqueueMergeRollup( + provingState: ProvingState, level: bigint, index: bigint, mergeInputData: MergeRollupInputData, ) { - if (!provingState?.verifyState()) { - logger.debug('Not running merge rollup, state invalid'); - return; - } - const circuitInputs = createMergeRollupInputs( + const inputs = createMergeRollupInputs( [mergeInputData.inputs[0]!, mergeInputData.proofs[0]!], [mergeInputData.inputs[1]!, mergeInputData.proofs[1]!], ); - const [duration, circuitOutputs] = await elapsed(() => this.prover.getMergeRollupProof(circuitInputs)); - logger.debug(`Simulated merge rollup circuit`, { - eventName: 'circuit-simulation', - circuitName: 'merge-rollup', - duration, - inputSize: circuitInputs.toBuffer().length, - outputSize: circuitOutputs[0].toBuffer().length, - } satisfies CircuitSimulationStats); - if (!provingState?.verifyState()) { - logger.debug(`Discarding job as state no longer valid`); - return; - } - logger.info(`Completed merge rollup at level ${level}, index ${index}`); - this.storeAndExecuteNextMergeLevel(provingState, level, index, circuitOutputs); + + this.enqueueJob( + provingState, + { + type: ProvingRequestType.MERGE_ROLLUP, + inputs, + }, + (publicInputs, proof) => { + this.storeAndExecuteNextMergeLevel(provingState, level, index, [publicInputs, proof]); + }, + ); } // Executes the root rollup circuit - private async runRootRollup(provingState: ProvingState | undefined) { + private async enqueueRootRollup(provingState: ProvingState | undefined) { if (!provingState?.verifyState()) { logger.debug('Not running root rollup, state no longer valid'); return; @@ -506,7 +506,7 @@ export class ProvingOrchestrator { const mergeInputData = provingState.getMergeInputs(0); const rootParityInput = provingState.finalRootParityInput!; - const rootInput = await getRootRollupInput( + const inputs = await getRootRollupInput( mergeInputData.inputs[0]!, mergeInputData.proofs[0]!, mergeInputData.inputs[1]!, @@ -518,90 +518,67 @@ export class ProvingOrchestrator { this.db, ); - // Simulate and get proof for the root circuit - const [rootOutput, rootProof] = await this.prover.getRootRollupProof(rootInput); - - logger.info(`Completed root rollup`); - - provingState.rootRollupPublicInputs = rootOutput; - provingState.finalProof = rootProof; - - const provingResult: ProvingResult = { - status: PROVING_STATUS.SUCCESS, - }; - provingState.resolve(provingResult); + this.enqueueJob( + provingState, + { + type: ProvingRequestType.ROOT_ROLLUP, + inputs, + }, + (publicInputs, proof) => { + provingState.rootRollupPublicInputs = publicInputs; + provingState.finalProof = proof; + + const provingResult: ProvingResult = { + status: PROVING_STATUS.SUCCESS, + }; + provingState.resolve(provingResult); + }, + ); } // Executes the base parity circuit and stores the intermediate state for the root parity circuit // Enqueues the root parity circuit if all inputs are available - private async runBaseParityCircuit(provingState: ProvingState | undefined, inputs: BaseParityInputs, index: number) { - if (!provingState?.verifyState()) { - logger.debug('Not running base parity, state no longer valid'); - return; - } - const [duration, circuitOutputs] = await elapsed(async () => { - const [parityPublicInputs, proof] = await this.prover.getBaseParityProof(inputs); - return new RootParityInput(proof, parityPublicInputs); - }); - logger.debug(`Simulated base parity circuit`, { - eventName: 'circuit-simulation', - circuitName: 'base-parity', - duration, - inputSize: inputs.toBuffer().length, - outputSize: circuitOutputs.toBuffer().length, - } satisfies CircuitSimulationStats); - - if (!provingState?.verifyState()) { - logger.debug(`Discarding job as state no longer valid`); - return; - } - provingState.setRootParityInputs(circuitOutputs, index); - - if (!provingState.areRootParityInputsReady()) { - // not ready to run the root parity circuit yet - return; - } - const rootParityInputs = new RootParityInputs( - provingState.rootParityInput as Tuple, - ); - this.enqueueJob(provingState, PROVING_JOB_TYPE.ROOT_PARITY, () => - this.runRootParityCircuit(provingState, rootParityInputs), + private enqueueBaseParityCircuit(provingState: ProvingState, inputs: BaseParityInputs, index: number) { + this.enqueueJob( + provingState, + { + inputs, + type: ProvingRequestType.BASE_PARITY, + }, + (publicInputs, proof) => { + const rootInput = new RootParityInput(proof, publicInputs); + provingState.setRootParityInputs(rootInput, index); + const rootParityInputs = new RootParityInputs( + provingState.rootParityInput as Tuple, + ); + this.enqueueRootParityCircuit(provingState, rootParityInputs); + }, ); } // Runs the root parity circuit ans stored the outputs // Enqueues the root rollup proof if all inputs are available - private async runRootParityCircuit(provingState: ProvingState | undefined, inputs: RootParityInputs) { - if (!provingState?.verifyState()) { - logger.debug(`Not running root parity circuit as state is no longer valid`); - return; - } - const [duration, circuitOutputs] = await elapsed(async () => { - const [parityPublicInputs, proof] = await this.prover.getRootParityProof(inputs); - return new RootParityInput(proof, parityPublicInputs); - }); - logger.debug(`Simulated root parity circuit`, { - eventName: 'circuit-simulation', - circuitName: 'root-parity', - duration, - inputSize: inputs.toBuffer().length, - outputSize: circuitOutputs.toBuffer().length, - } satisfies CircuitSimulationStats); - - if (!provingState?.verifyState()) { - logger.debug(`Discarding job as state no longer valid`); - return; - } - provingState!.finalRootParityInput = circuitOutputs; - this.checkAndExecuteRootRollup(provingState); + private enqueueRootParityCircuit(provingState: ProvingState | undefined, inputs: RootParityInputs) { + this.enqueueJob( + provingState, + { + type: ProvingRequestType.ROOT_PARITY, + inputs, + }, + async (publicInputs, proof) => { + const rootInput = new RootParityInput(proof, publicInputs); + provingState!.finalRootParityInput = rootInput; + await this.checkAndEnqueueRootRollup(provingState); + }, + ); } - private checkAndExecuteRootRollup(provingState: ProvingState | undefined) { + private async checkAndEnqueueRootRollup(provingState: ProvingState | undefined) { if (!provingState?.isReadyForRootRollup()) { logger.debug('Not ready for root rollup'); return; } - this.enqueueJob(provingState, PROVING_JOB_TYPE.ROOT_ROLLUP, () => this.runRootRollup(provingState)); + await this.enqueueRootRollup(provingState); } /** @@ -625,12 +602,11 @@ export class ProvingOrchestrator { } if (result.mergeLevel === 0n) { - this.checkAndExecuteRootRollup(provingState); + // TODO (alexg) remove this `void` + void this.checkAndEnqueueRootRollup(provingState); } else { // onto the next merge level - this.enqueueJob(provingState, PROVING_JOB_TYPE.MERGE_ROLLUP, () => - this.runMergeRollup(provingState, result.mergeLevel, result.indexWithinMergeLevel, result.mergeInputData), - ); + this.enqueueMergeRollup(provingState, result.mergeLevel, result.indexWithinMergeLevel, result.mergeInputData); } } @@ -641,7 +617,7 @@ export class ProvingOrchestrator { * @param txIndex - The index of the transaction being proven * @param functionIndex - The index of the function/kernel being proven */ - private async executeVM(provingState: ProvingState | undefined, txIndex: number, functionIndex: number) { + private enqueueVM(provingState: ProvingState | undefined, txIndex: number, functionIndex: number) { if (!provingState?.verifyState()) { logger.debug(`Not running VM circuit as state is no longer valid`); return; @@ -653,15 +629,24 @@ export class ProvingOrchestrator { // Prove the VM if this is a kernel that requires one if (!KernelTypesWithoutFunctions.has(publicFunction.publicKernelRequest.type)) { // Just sleep for a small amount of time - await sleep(Math.random() * 10 + 10); - logger.debug(`Proven VM for function index ${functionIndex} of tx index ${txIndex}`); - } - - if (!provingState?.verifyState()) { - logger.debug(`Not continuing after VM circuit as state is no longer valid`); - return; + this.enqueueJob( + provingState, + { + type: ProvingRequestType.PUBLIC_VM, + inputs: {}, + }, + (_1, _2) => { + logger.debug(`Proven VM for function index ${functionIndex} of tx index ${txIndex}`); + this.checkAndEnqueuePublicKernel(provingState, txIndex, functionIndex); + }, + ); + } else { + this.checkAndEnqueuePublicKernel(provingState, txIndex, functionIndex); } + } + private checkAndEnqueuePublicKernel(provingState: ProvingState, txIndex: number, functionIndex: number) { + const txProvingState = provingState.getTxProvingState(txIndex); const kernelRequest = txProvingState.getNextPublicKernelFromVMProof(functionIndex, makeEmptyProof()); if (kernelRequest.code === TX_PROVING_CODE.READY) { if (kernelRequest.function === undefined) { @@ -669,9 +654,7 @@ export class ProvingOrchestrator { throw new Error(`Error occurred, public function request undefined after VM proof completed`); } logger.debug(`Enqueuing kernel from VM for tx ${txIndex}, function ${functionIndex}`); - this.enqueueJob(provingState, PROVING_JOB_TYPE.PUBLIC_KERNEL, () => - this.executePublicKernel(provingState, txIndex, functionIndex), - ); + this.enqueuePublicKernel(provingState, txIndex, functionIndex); } } @@ -682,115 +665,37 @@ export class ProvingOrchestrator { * @param txIndex - The index of the transaction being proven * @param functionIndex - The index of the function/kernel being proven */ - private async executePublicKernel(provingState: ProvingState | undefined, txIndex: number, functionIndex: number) { + private enqueuePublicKernel(provingState: ProvingState | undefined, txIndex: number, functionIndex: number) { if (!provingState?.verifyState()) { logger.debug(`Not running public kernel circuit as state is no longer valid`); return; } const txProvingState = provingState.getTxProvingState(txIndex); - const kernelRequest = txProvingState.getPublicFunctionState(functionIndex).publicKernelRequest; - - // We may need to use the public inputs produced here instead of those coming from the sequencer - const [_, proof] = - kernelRequest.type == PublicKernelType.TAIL - ? await this.prover.getPublicTailProof(kernelRequest) - : await this.prover.getPublicKernelProof(kernelRequest); - - if (!provingState?.verifyState()) { - logger.debug(`Not continuing after public kernel circuit as state is no longer valid`); - return; - } - - logger.debug(`Proven ${PublicKernelType[kernelRequest.type]} at index ${functionIndex} for tx index ${txIndex}`); - - const nextKernelRequest = txProvingState.getNextPublicKernelFromKernelProof(functionIndex, proof); - // What's the status of the next kernel? - if (nextKernelRequest.code === TX_PROVING_CODE.NOT_READY) { - // Must be waiting on a VM proof - return; - } - if (nextKernelRequest.code === TX_PROVING_CODE.COMPLETED) { - // We must have completed all public function proving, we now move to the base rollup - logger.debug(`Public functions completed for tx ${txIndex} enqueueing base rollup`); - this.enqueueJob(provingState, PROVING_JOB_TYPE.BASE_ROLLUP, () => - this.runBaseRollup(provingState, BigInt(txIndex), txProvingState), - ); - return; - } - // There must be another kernel ready to be proven - if (nextKernelRequest.function === undefined) { - // Should not be possible - throw new Error(`Error occurred, public function request undefined after kernel proof completed`); - } - logger.debug(`Enqueuing kernel from kernel for tx ${txIndex}, function ${functionIndex + 1}`); - this.enqueueJob(provingState, PROVING_JOB_TYPE.PUBLIC_KERNEL, () => - this.executePublicKernel(provingState, txIndex, functionIndex + 1), - ); - } - - /** - * Process the job queue - * Works by managing an input queue of proof requests and an active pool of proving 'jobs' - */ - private async processJobQueue() { - // Used for determining the current state of a proving job - const promiseState = (p: Promise) => { - const t = {}; - return Promise.race([p, t]).then( - v => (v === t ? 'pending' : 'fulfilled'), - () => 'rejected', - ); - }; - - // Just a short break between managing the sets of requests and active jobs - const createSleepPromise = () => - sleep(SLEEP_TIME).then(_ => { - return PROMISE_RESULT.SLEEP; - }); - - let sleepPromise = createSleepPromise(); - let promises: Promise[] = []; - while (!this.stopped) { - // first look for more work - if (this.jobQueue.length() && promises.length < this.maxConcurrentJobs) { - // more work could be available - const job = await this.jobQueue.get(); - if (job !== null) { - // a proving job, add it to the pool of outstanding jobs - promises.push(job.operation()); - } - // continue adding more work - continue; + const provingRequest = txProvingState.getPublicFunctionState(functionIndex).provingRequest; + + this.enqueueJob(provingState, provingRequest, (_, proof) => { + logger.debug(`Proven ${PublicKernelType[provingRequest.type]} at index ${functionIndex} for tx index ${txIndex}`); + const nextKernelRequest = txProvingState.getNextPublicKernelFromKernelProof(functionIndex, proof); + // What's the status of the next kernel? + if (nextKernelRequest.code === TX_PROVING_CODE.NOT_READY) { + // Must be waiting on a VM proof + return; } - // no more work to add, here we wait for any outstanding jobs to finish and/or sleep a little - try { - const ops = Promise.race(promises).then(_ => { - return PROMISE_RESULT.OPERATIONS; - }); - const result = await Promise.race([sleepPromise, ops]); - if (result === PROMISE_RESULT.SLEEP) { - // this is the sleep promise - // we simply setup the promise again and go round the loop checking for more work - sleepPromise = createSleepPromise(); - continue; - } - } catch (err) { - // We shouldn't get here as all jobs should be wrapped in a 'safeJob' meaning they don't fail! - logger.error(`Unexpected error in proving orchestrator ${err}`); + if (nextKernelRequest.code === TX_PROVING_CODE.COMPLETED) { + // We must have completed all public function proving, we now move to the base rollup + logger.debug(`Public functions completed for tx ${txIndex} enqueueing base rollup`); + this.enqueueBaseRollup(provingState, BigInt(txIndex), txProvingState); + return; } - - // one or more of the jobs completed, remove them - const pendingPromises = []; - for (const jobPromise of promises) { - const state = await promiseState(jobPromise); - if (state === 'pending') { - pendingPromises.push(jobPromise); - } + // There must be another kernel ready to be proven + if (nextKernelRequest.function === undefined) { + // Should not be possible + throw new Error(`Error occurred, public function request undefined after kernel proof completed`); } - // eslint-disable-next-line @typescript-eslint/no-floating-promises - promises = pendingPromises; - } + + this.enqueuePublicKernel(provingState, txIndex, functionIndex + 1); + }); } } diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator_errors.test.ts b/yarn-project/prover-client/src/orchestrator/orchestrator_errors.test.ts index 42bb5a177d0..8f23bd02b3b 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator_errors.test.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator_errors.test.ts @@ -2,13 +2,9 @@ import { PROVING_STATUS } from '@aztec/circuit-types'; import { Fr } from '@aztec/circuits.js'; import { createDebugLogger } from '@aztec/foundation/log'; -import { type MemDown, default as memdown } from 'memdown'; - import { makeBloatedProcessedTx, makeEmptyProcessedTestTx } from '../mocks/fixtures.js'; import { TestContext } from '../mocks/test_context.js'; -export const createMemDown = () => (memdown as any)() as MemDown; - const logger = createDebugLogger('aztec:orchestrator-errors'); describe('prover/orchestrator/errors', () => { @@ -53,7 +49,7 @@ describe('prover/orchestrator/errors', () => { const finalisedBlock = await context.orchestrator.finaliseBlock(); expect(finalisedBlock.block.number).toEqual(context.blockNumber); - }, 30_000); + }, 40_000); it('throws if adding a transaction before start', async () => { await expect( diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator_failures.test.ts b/yarn-project/prover-client/src/orchestrator/orchestrator_failures.test.ts index 1b9b0e28614..d8b7f1e6c69 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator_failures.test.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator_failures.test.ts @@ -3,21 +3,21 @@ import { createDebugLogger } from '@aztec/foundation/log'; import { WASMSimulator } from '@aztec/simulator'; import { jest } from '@jest/globals'; -import { type MemDown, default as memdown } from 'memdown'; import { makeEmptyProcessedTestTx } from '../mocks/fixtures.js'; import { TestContext } from '../mocks/test_context.js'; +import { CircuitProverAgent } from '../prover-pool/circuit-prover-agent.js'; +import { ProverPool } from '../prover-pool/prover-pool.js'; import { type CircuitProver } from '../prover/index.js'; import { TestCircuitProver } from '../prover/test_circuit_prover.js'; import { ProvingOrchestrator } from './orchestrator.js'; -export const createMemDown = () => (memdown as any)() as MemDown; - const logger = createDebugLogger('aztec:orchestrator-failures'); describe('prover/orchestrator/failures', () => { let context: TestContext; let orchestrator: ProvingOrchestrator; + let proverPool: ProverPool; beforeEach(async () => { context = await TestContext.new(logger); @@ -32,11 +32,13 @@ describe('prover/orchestrator/failures', () => { beforeEach(async () => { mockProver = new TestCircuitProver(new WASMSimulator()); - orchestrator = await ProvingOrchestrator.new(context.actualDb, mockProver); + proverPool = new ProverPool(1, i => new CircuitProverAgent(mockProver, 10, `${i}`)); + orchestrator = new ProvingOrchestrator(context.actualDb, proverPool.queue); + await proverPool.start(); }); afterEach(async () => { - await orchestrator.stop(); + await proverPool.stop(); }); it.each([ diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator_lifecycle.test.ts b/yarn-project/prover-client/src/orchestrator/orchestrator_lifecycle.test.ts index bfffd42382f..898e3aab9bb 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator_lifecycle.test.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator_lifecycle.test.ts @@ -4,13 +4,9 @@ import { fr } from '@aztec/circuits.js/testing'; import { range } from '@aztec/foundation/array'; import { createDebugLogger } from '@aztec/foundation/log'; -import { type MemDown, default as memdown } from 'memdown'; - import { makeBloatedProcessedTx, makeEmptyProcessedTestTx, makeGlobals } from '../mocks/fixtures.js'; import { TestContext } from '../mocks/test_context.js'; -export const createMemDown = () => (memdown as any)() as MemDown; - const logger = createDebugLogger('aztec:orchestrator-lifecycle'); describe('prover/orchestrator/lifecycle', () => { @@ -79,7 +75,7 @@ describe('prover/orchestrator/lifecycle', () => { const finalisedBlock = await context.orchestrator.finaliseBlock(); expect(finalisedBlock.block.number).toEqual(101); - }, 20000); + }, 40000); it('automatically cancels an incomplete block when starting a new one', async () => { const txs1 = await Promise.all([ diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator_mixed_blocks.test.ts b/yarn-project/prover-client/src/orchestrator/orchestrator_mixed_blocks.test.ts index 7191c868466..53a6959b710 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator_mixed_blocks.test.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator_mixed_blocks.test.ts @@ -4,13 +4,9 @@ import { fr } from '@aztec/circuits.js/testing'; import { range } from '@aztec/foundation/array'; import { createDebugLogger } from '@aztec/foundation/log'; -import { type MemDown, default as memdown } from 'memdown'; - import { makeBloatedProcessedTx, makeEmptyProcessedTestTx } from '../mocks/fixtures.js'; import { TestContext } from '../mocks/test_context.js'; -export const createMemDown = () => (memdown as any)() as MemDown; - const logger = createDebugLogger('aztec:orchestrator-mixed-blocks'); describe('prover/orchestrator/mixed-blocks', () => { diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator_mixed_blocks_2.test.ts b/yarn-project/prover-client/src/orchestrator/orchestrator_mixed_blocks_2.test.ts index 63a32b713a7..1233bbe30f7 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator_mixed_blocks_2.test.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator_mixed_blocks_2.test.ts @@ -7,13 +7,9 @@ import { createDebugLogger } from '@aztec/foundation/log'; import { openTmpStore } from '@aztec/kv-store/utils'; import { type MerkleTreeOperations, MerkleTrees } from '@aztec/world-state'; -import { type MemDown, default as memdown } from 'memdown'; - import { makeBloatedProcessedTx, makeEmptyProcessedTestTx, updateExpectedTreesFromTxs } from '../mocks/fixtures.js'; import { TestContext } from '../mocks/test_context.js'; -export const createMemDown = () => (memdown as any)() as MemDown; - const logger = createDebugLogger('aztec:orchestrator-mixed-blocks-2'); describe('prover/orchestrator/mixed-blocks', () => { diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator_multi_public_functions.test.ts b/yarn-project/prover-client/src/orchestrator/orchestrator_multi_public_functions.test.ts index e1c18cf3dac..6e1054032b1 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator_multi_public_functions.test.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator_multi_public_functions.test.ts @@ -2,13 +2,9 @@ import { PROVING_STATUS, mockTx } from '@aztec/circuit-types'; import { times } from '@aztec/foundation/collection'; import { createDebugLogger } from '@aztec/foundation/log'; -import { type MemDown, default as memdown } from 'memdown'; - import { makeEmptyProcessedTestTx } from '../mocks/fixtures.js'; import { TestContext } from '../mocks/test_context.js'; -export const createMemDown = () => (memdown as any)() as MemDown; - const logger = createDebugLogger('aztec:orchestrator-multi-public-functions'); describe('prover/orchestrator/public-functions', () => { diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator_multiple_blocks.test.ts b/yarn-project/prover-client/src/orchestrator/orchestrator_multiple_blocks.test.ts index a84fa807929..1525aeff740 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator_multiple_blocks.test.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator_multiple_blocks.test.ts @@ -1,13 +1,9 @@ import { PROVING_STATUS } from '@aztec/circuit-types'; import { createDebugLogger } from '@aztec/foundation/log'; -import { type MemDown, default as memdown } from 'memdown'; - import { makeBloatedProcessedTx, makeEmptyProcessedTestTx, makeGlobals } from '../mocks/fixtures.js'; import { TestContext } from '../mocks/test_context.js'; -export const createMemDown = () => (memdown as any)() as MemDown; - const logger = createDebugLogger('aztec:orchestrator-multi-blocks'); describe('prover/orchestrator/multi-block', () => { diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator_public_functions.test.ts b/yarn-project/prover-client/src/orchestrator/orchestrator_public_functions.test.ts index 9409ba9d41e..2f7679b973b 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator_public_functions.test.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator_public_functions.test.ts @@ -1,13 +1,9 @@ import { PROVING_STATUS, mockTx } from '@aztec/circuit-types'; import { createDebugLogger } from '@aztec/foundation/log'; -import { type MemDown, default as memdown } from 'memdown'; - import { makeEmptyProcessedTestTx } from '../mocks/fixtures.js'; import { TestContext } from '../mocks/test_context.js'; -export const createMemDown = () => (memdown as any)() as MemDown; - const logger = createDebugLogger('aztec:orchestrator-public-functions'); describe('prover/orchestrator/public-functions', () => { diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator_single_blocks.test.ts b/yarn-project/prover-client/src/orchestrator/orchestrator_single_blocks.test.ts index 96f8f64b3df..959a6105c6a 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator_single_blocks.test.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator_single_blocks.test.ts @@ -7,13 +7,9 @@ import { sleep } from '@aztec/foundation/sleep'; import { openTmpStore } from '@aztec/kv-store/utils'; import { type MerkleTreeOperations, MerkleTrees } from '@aztec/world-state'; -import { type MemDown, default as memdown } from 'memdown'; - import { makeBloatedProcessedTx, makeEmptyProcessedTestTx, updateExpectedTreesFromTxs } from '../mocks/fixtures.js'; import { TestContext } from '../mocks/test_context.js'; -export const createMemDown = () => (memdown as any)() as MemDown; - const logger = createDebugLogger('aztec:orchestrator-single-blocks'); describe('prover/orchestrator/blocks', () => { diff --git a/yarn-project/prover-client/src/orchestrator/tx-proving-state.ts b/yarn-project/prover-client/src/orchestrator/tx-proving-state.ts index ab8802d2fcc..73339d00d6d 100644 --- a/yarn-project/prover-client/src/orchestrator/tx-proving-state.ts +++ b/yarn-project/prover-client/src/orchestrator/tx-proving-state.ts @@ -1,6 +1,8 @@ import { type MerkleTreeId, type ProcessedTx, type PublicKernelRequest, PublicKernelType } from '@aztec/circuit-types'; import { type AppendOnlyTreeSnapshot, type BaseRollupInputs, type Proof } from '@aztec/circuits.js'; +import { type ProvingRequest, ProvingRequestType } from '../prover-pool/proving-request.js'; + export enum TX_PROVING_CODE { NOT_READY, READY, @@ -12,6 +14,7 @@ export type PublicFunction = { previousProofType: PublicKernelType; previousKernelProof: Proof | undefined; publicKernelRequest: PublicKernelRequest; + provingRequest: ProvingRequest; }; // Type encapsulating the instruction to the orchestrator as to what @@ -37,11 +40,24 @@ export class TxProvingState { let previousKernelProof: Proof | undefined = processedTx.proof; let previousProofType = PublicKernelType.NON_PUBLIC; for (const kernelRequest of processedTx.publicKernelRequests) { + const provingRequest: ProvingRequest = + kernelRequest.type === PublicKernelType.TAIL + ? { + type: ProvingRequestType.PUBLIC_KERNEL_TAIL, + kernelType: kernelRequest.type, + inputs: kernelRequest.inputs, + } + : { + type: ProvingRequestType.PUBLIC_KERNEL_NON_TAIL, + kernelType: kernelRequest.type, + inputs: kernelRequest.inputs, + }; const publicFunction: PublicFunction = { vmProof: undefined, previousProofType, previousKernelProof, publicKernelRequest: kernelRequest, + provingRequest, }; this.publicFunctions.push(publicFunction); previousKernelProof = undefined; diff --git a/yarn-project/prover-client/src/prover-pool/circuit-prover-agent.test.ts b/yarn-project/prover-client/src/prover-pool/circuit-prover-agent.test.ts new file mode 100644 index 00000000000..a5e8b224cc9 --- /dev/null +++ b/yarn-project/prover-client/src/prover-pool/circuit-prover-agent.test.ts @@ -0,0 +1,85 @@ +import { makeBaseParityInputs, makeParityPublicInputs, makeProof } from '@aztec/circuits.js/testing'; + +import { type MockProxy, mock } from 'jest-mock-extended'; + +import { type CircuitProver } from '../prover/interface.js'; +import { CircuitProverAgent } from './circuit-prover-agent.js'; +import { MemoryProvingQueue } from './memory-proving-queue.js'; +import { type ProvingAgent } from './prover-agent.js'; +import { type ProvingQueue } from './proving-queue.js'; +import { ProvingRequestType } from './proving-request.js'; + +describe('LocalProvingAgent', () => { + let queue: ProvingQueue; + let agent: ProvingAgent; + let prover: MockProxy; + + beforeEach(() => { + prover = mock(); + queue = new MemoryProvingQueue(); + agent = new CircuitProverAgent(prover); + }); + + beforeEach(() => { + agent.start(queue); + }); + + afterEach(async () => { + await agent.stop(); + }); + + it('takes jobs from the queue', async () => { + const publicInputs = makeParityPublicInputs(); + const proof = makeProof(); + prover.getBaseParityProof.mockResolvedValue([publicInputs, proof]); + + const inputs = makeBaseParityInputs(); + const promise = queue.prove({ + type: ProvingRequestType.BASE_PARITY, + inputs, + }); + + await expect(promise).resolves.toEqual([publicInputs, proof]); + expect(prover.getBaseParityProof).toHaveBeenCalledWith(inputs); + }); + + it('reports errors', async () => { + const error = new Error('test error'); + prover.getBaseParityProof.mockRejectedValue(error); + + const inputs = makeBaseParityInputs(); + const promise = queue.prove({ + type: ProvingRequestType.BASE_PARITY, + inputs, + }); + + await expect(promise).rejects.toEqual(error); + expect(prover.getBaseParityProof).toHaveBeenCalledWith(inputs); + }); + + it('continues to process jobs', async () => { + const publicInputs = makeParityPublicInputs(); + const proof = makeProof(); + prover.getBaseParityProof.mockResolvedValue([publicInputs, proof]); + + const inputs = makeBaseParityInputs(); + const promise1 = queue.prove({ + type: ProvingRequestType.BASE_PARITY, + inputs, + }); + + await expect(promise1).resolves.toEqual([publicInputs, proof]); + + const inputs2 = makeBaseParityInputs(); + const promise2 = queue.prove({ + type: ProvingRequestType.BASE_PARITY, + inputs: inputs2, + }); + + await expect(promise2).resolves.toEqual([publicInputs, proof]); + + expect(prover.getBaseParityProof).toHaveBeenCalledTimes(2); + expect(prover.getBaseParityProof).toHaveBeenCalledWith(inputs); + expect(prover.getBaseParityProof).toHaveBeenCalledWith(inputs2); + }); +}); diff --git a/yarn-project/prover-client/src/prover-pool/circuit-prover-agent.ts b/yarn-project/prover-client/src/prover-pool/circuit-prover-agent.ts new file mode 100644 index 00000000000..76553512eb2 --- /dev/null +++ b/yarn-project/prover-client/src/prover-pool/circuit-prover-agent.ts @@ -0,0 +1,107 @@ +import { makeEmptyProof } from '@aztec/circuits.js'; +import { createDebugLogger } from '@aztec/foundation/log'; +import { RunningPromise } from '@aztec/foundation/running-promise'; +import { elapsed } from '@aztec/foundation/timer'; + +import { type CircuitProver } from '../prover/interface.js'; +import { type ProvingAgent } from './prover-agent.js'; +import { type ProvingQueueConsumer } from './proving-queue.js'; +import { type ProvingRequest, type ProvingRequestResult, ProvingRequestType } from './proving-request.js'; + +export class CircuitProverAgent implements ProvingAgent { + private runningPromise?: RunningPromise; + + constructor( + /** The prover implementation to defer jobs to */ + private prover: CircuitProver, + /** How long to wait between jobs */ + private intervalMs = 10, + /** A name for this agent (if there are multiple agents running) */ + name = '', + private log = createDebugLogger('aztec:prover-client:prover-pool:agent' + (name ? `:${name}` : '')), + ) {} + + start(queue: ProvingQueueConsumer): void { + if (this.runningPromise) { + throw new Error('Agent is already running'); + } + + this.runningPromise = new RunningPromise(async () => { + const job = await queue.getProvingJob(); + if (!job) { + return; + } + + try { + const [time, result] = await elapsed(() => this.work(job.request)); + await queue.resolveProvingJob(job.id, result); + this.log.info( + `Processed proving job id=${job.id} type=${ProvingRequestType[job.request.type]} duration=${time}ms`, + ); + } catch (err) { + this.log.error( + `Error processing proving job id=${job.id} type=${ProvingRequestType[job.request.type]}: ${err}`, + ); + await queue.rejectProvingJob(job.id, err as Error); + } + }, this.intervalMs); + + this.runningPromise.start(); + } + + async stop(): Promise { + if (!this.runningPromise) { + throw new Error('Agent is not running'); + } + + await this.runningPromise.stop(); + this.runningPromise = undefined; + } + + private work(request: ProvingRequest): Promise> { + const { type, inputs } = request; + switch (type) { + case ProvingRequestType.PUBLIC_VM: { + return Promise.resolve([{}, makeEmptyProof()] as const); + } + + case ProvingRequestType.PUBLIC_KERNEL_NON_TAIL: { + return this.prover.getPublicKernelProof({ + type: request.kernelType, + inputs, + }); + } + + case ProvingRequestType.PUBLIC_KERNEL_TAIL: { + return this.prover.getPublicTailProof({ + type: request.kernelType, + inputs, + }); + } + + case ProvingRequestType.BASE_ROLLUP: { + return this.prover.getBaseRollupProof(inputs); + } + + case ProvingRequestType.MERGE_ROLLUP: { + return this.prover.getMergeRollupProof(inputs); + } + + case ProvingRequestType.ROOT_ROLLUP: { + return this.prover.getRootRollupProof(inputs); + } + + case ProvingRequestType.BASE_PARITY: { + return this.prover.getBaseParityProof(inputs); + } + + case ProvingRequestType.ROOT_PARITY: { + return this.prover.getRootParityProof(inputs); + } + + default: { + return Promise.reject(new Error(`Invalid proof request type: ${type}`)); + } + } + } +} diff --git a/yarn-project/prover-client/src/prover-pool/memory-proving-queue.test.ts b/yarn-project/prover-client/src/prover-pool/memory-proving-queue.test.ts new file mode 100644 index 00000000000..cea156acfc6 --- /dev/null +++ b/yarn-project/prover-client/src/prover-pool/memory-proving-queue.test.ts @@ -0,0 +1,70 @@ +import { + makeBaseParityInputs, + makeBaseRollupInputs, + makeParityPublicInputs, + makeProof, +} from '@aztec/circuits.js/testing'; + +import { MemoryProvingQueue } from './memory-proving-queue.js'; +import { type ProvingQueue } from './proving-queue.js'; +import { ProvingRequestType } from './proving-request.js'; + +describe('MemoryProvingQueue', () => { + let queue: ProvingQueue; + + beforeEach(() => { + queue = new MemoryProvingQueue(); + }); + + it('returns jobs in order', async () => { + void queue.prove({ + type: ProvingRequestType.BASE_PARITY, + inputs: makeBaseParityInputs(), + }); + + void queue.prove({ + type: ProvingRequestType.BASE_ROLLUP, + inputs: makeBaseRollupInputs(), + }); + + const job1 = await queue.getProvingJob(); + expect(job1?.request.type).toEqual(ProvingRequestType.BASE_PARITY); + + const job2 = await queue.getProvingJob(); + expect(job2?.request.type).toEqual(ProvingRequestType.BASE_ROLLUP); + }); + + it('returns null when no jobs are available', async () => { + await expect(queue.getProvingJob({ timeoutSec: 0 })).resolves.toBeNull(); + }); + + it('notifies of completion', async () => { + const inputs = makeBaseParityInputs(); + const promise = queue.prove({ + inputs, + type: ProvingRequestType.BASE_PARITY, + }); + + const job = await queue.getProvingJob(); + expect(job?.request.inputs).toEqual(inputs); + + const publicInputs = makeParityPublicInputs(); + const proof = makeProof(); + await queue.resolveProvingJob(job!.id, [publicInputs, proof]); + await expect(promise).resolves.toEqual([publicInputs, proof]); + }); + + it('notifies of errors', async () => { + const inputs = makeBaseParityInputs(); + const promise = queue.prove({ + inputs, + type: ProvingRequestType.BASE_PARITY, + }); + const job = await queue.getProvingJob(); + expect(job?.request.inputs).toEqual(inputs); + + const error = new Error('test error'); + await queue.rejectProvingJob(job!.id, error); + await expect(promise).rejects.toEqual(error); + }); +}); diff --git a/yarn-project/prover-client/src/prover-pool/memory-proving-queue.ts b/yarn-project/prover-client/src/prover-pool/memory-proving-queue.ts new file mode 100644 index 00000000000..155b548ff2e --- /dev/null +++ b/yarn-project/prover-client/src/prover-pool/memory-proving-queue.ts @@ -0,0 +1,86 @@ +import { TimeoutError } from '@aztec/foundation/error'; +import { MemoryFifo } from '@aztec/foundation/fifo'; +import { createDebugLogger } from '@aztec/foundation/log'; +import { type PromiseWithResolvers, promiseWithResolvers } from '@aztec/foundation/promise'; + +import { type ProvingJob, type ProvingQueue } from './proving-queue.js'; +import { type ProvingRequest, type ProvingRequestResult, ProvingRequestType } from './proving-request.js'; + +type ProvingJobWithResolvers = { + id: string; + request: T; +} & PromiseWithResolvers>; + +export class MemoryProvingQueue implements ProvingQueue { + private jobId = 0; + private log = createDebugLogger('aztec:prover-client:prover-pool:queue'); + private queue = new MemoryFifo(); + private jobsInProgress = new Map(); + + async getProvingJob({ timeoutSec = 1 } = {}): Promise | null> { + try { + const job = await this.queue.get(timeoutSec); + if (!job) { + return null; + } + + this.jobsInProgress.set(job.id, job); + return { + id: job.id, + request: job.request, + }; + } catch (err) { + if (err instanceof TimeoutError) { + return null; + } + + throw err; + } + } + + resolveProvingJob(jobId: string, result: ProvingRequestResult): Promise { + const job = this.jobsInProgress.get(jobId); + if (!job) { + return Promise.reject(new Error('Job not found')); + } + + this.jobsInProgress.delete(jobId); + job.resolve(result); + return Promise.resolve(); + } + + rejectProvingJob(jobId: string, err: any): Promise { + const job = this.jobsInProgress.get(jobId); + if (!job) { + return Promise.reject(new Error('Job not found')); + } + + this.jobsInProgress.delete(jobId); + job.reject(err); + return Promise.resolve(); + } + + prove(request: T): Promise> { + const { promise, resolve, reject } = promiseWithResolvers>(); + const item: ProvingJobWithResolvers = { + id: String(this.jobId++), + request, + promise, + resolve, + reject, + }; + + this.log.info(`Adding ${ProvingRequestType[request.type]} proving job to queue`); + // TODO (alexg) remove the `any` + if (!this.queue.put(item as any)) { + throw new Error(); + } + + return promise; + } + + cancelAll(): void { + this.queue.cancel(); + this.queue = new MemoryFifo(); + } +} diff --git a/yarn-project/prover-client/src/prover-pool/prover-agent.ts b/yarn-project/prover-client/src/prover-pool/prover-agent.ts new file mode 100644 index 00000000000..6d408e3a074 --- /dev/null +++ b/yarn-project/prover-client/src/prover-pool/prover-agent.ts @@ -0,0 +1,15 @@ +import { type ProvingQueueConsumer } from './proving-queue.js'; + +/** An agent that reads proving jobs from the queue, creates the proof and submits back the result */ +export interface ProvingAgent { + /** + * Starts the agent to read proving jobs from the queue. + * @param queue - The queue to read proving jobs from. + */ + start(queue: ProvingQueueConsumer): void; + + /** + * Stops the agent. Does nothing if the agent is not running. + */ + stop(): Promise; +} diff --git a/yarn-project/prover-client/src/prover-pool/prover-pool.ts b/yarn-project/prover-client/src/prover-pool/prover-pool.ts new file mode 100644 index 00000000000..defeed61ce7 --- /dev/null +++ b/yarn-project/prover-client/src/prover-pool/prover-pool.ts @@ -0,0 +1,47 @@ +import { MemoryProvingQueue } from './memory-proving-queue.js'; +import { type ProvingAgent } from './prover-agent.js'; +import { type ProvingQueue } from './proving-queue.js'; + +/** + * Utility class that spawns N prover agents all connected to the same queue + */ +export class ProverPool { + private agents: ProvingAgent[] = []; + private running = false; + + constructor( + private size: number, + private agentFactory: (i: number) => ProvingAgent | Promise, + public readonly queue: ProvingQueue = new MemoryProvingQueue(), + ) {} + + async start(): Promise { + if (this.running) { + throw new Error('Prover pool is already running'); + } + + // lock the pool state here since creating agents is async + this.running = true; + + // handle start, stop, start cycles by only creating as many agents as were requested + for (let i = this.agents.length; i < this.size; i++) { + this.agents.push(await this.agentFactory(i)); + } + + for (const agent of this.agents) { + agent.start(this.queue); + } + } + + async stop(): Promise { + if (!this.running) { + throw new Error('Prover pool is not running'); + } + + for (const agent of this.agents) { + await agent.stop(); + } + + this.running = false; + } +} diff --git a/yarn-project/prover-client/src/prover-pool/proving-queue.ts b/yarn-project/prover-client/src/prover-pool/proving-queue.ts new file mode 100644 index 00000000000..3ab8b015345 --- /dev/null +++ b/yarn-project/prover-client/src/prover-pool/proving-queue.ts @@ -0,0 +1,23 @@ +import type { ProvingRequest, ProvingRequestResult, ProvingRequestType } from './proving-request.js'; + +export type GetJobOptions = { + timeoutSec?: number; +}; + +export type ProvingJob = { + id: string; + request: T; +}; + +export interface ProvingRequestProducer { + prove(request: T): Promise>; + cancelAll(): void; +} + +export interface ProvingQueueConsumer { + getProvingJob(options?: GetJobOptions): Promise | null>; + resolveProvingJob(jobId: string, result: ProvingRequestResult): Promise; + rejectProvingJob(jobId: string, reason: Error): Promise; +} + +export interface ProvingQueue extends ProvingQueueConsumer, ProvingRequestProducer {} diff --git a/yarn-project/prover-client/src/prover-pool/proving-request.ts b/yarn-project/prover-client/src/prover-pool/proving-request.ts new file mode 100644 index 00000000000..ef98e7e18cd --- /dev/null +++ b/yarn-project/prover-client/src/prover-pool/proving-request.ts @@ -0,0 +1,81 @@ +import { type PublicKernelNonTailRequest, type PublicKernelTailRequest } from '@aztec/circuit-types'; +import { + type BaseOrMergeRollupPublicInputs, + type BaseParityInputs, + type BaseRollupInputs, + type KernelCircuitPublicInputs, + type MergeRollupInputs, + type ParityPublicInputs, + type Proof, + type PublicKernelCircuitPublicInputs, + type RootParityInputs, + type RootRollupInputs, + type RootRollupPublicInputs, +} from '@aztec/circuits.js'; + +export enum ProvingRequestType { + PUBLIC_VM, + + PUBLIC_KERNEL_NON_TAIL, + PUBLIC_KERNEL_TAIL, + + BASE_ROLLUP, + MERGE_ROLLUP, + ROOT_ROLLUP, + + BASE_PARITY, + ROOT_PARITY, +} + +export type ProvingRequest = + | { + type: ProvingRequestType.PUBLIC_VM; + // prefer object over unknown so that we can run "in" checks, e.g. `'toBuffer' in request.inputs` + inputs: object; + } + | { + type: ProvingRequestType.PUBLIC_KERNEL_NON_TAIL; + kernelType: PublicKernelNonTailRequest['type']; + inputs: PublicKernelNonTailRequest['inputs']; + } + | { + type: ProvingRequestType.PUBLIC_KERNEL_TAIL; + kernelType: PublicKernelTailRequest['type']; + inputs: PublicKernelTailRequest['inputs']; + } + | { + type: ProvingRequestType.BASE_PARITY; + inputs: BaseParityInputs; + } + | { + type: ProvingRequestType.ROOT_PARITY; + inputs: RootParityInputs; + } + | { + type: ProvingRequestType.BASE_ROLLUP; + inputs: BaseRollupInputs; + } + | { + type: ProvingRequestType.MERGE_ROLLUP; + inputs: MergeRollupInputs; + } + | { + type: ProvingRequestType.ROOT_ROLLUP; + inputs: RootRollupInputs; + }; + +export type ProvingRequestPublicInputs = { + [ProvingRequestType.PUBLIC_VM]: object; + + [ProvingRequestType.PUBLIC_KERNEL_NON_TAIL]: PublicKernelCircuitPublicInputs; + [ProvingRequestType.PUBLIC_KERNEL_TAIL]: KernelCircuitPublicInputs; + + [ProvingRequestType.BASE_ROLLUP]: BaseOrMergeRollupPublicInputs; + [ProvingRequestType.MERGE_ROLLUP]: BaseOrMergeRollupPublicInputs; + [ProvingRequestType.ROOT_ROLLUP]: RootRollupPublicInputs; + + [ProvingRequestType.BASE_PARITY]: ParityPublicInputs; + [ProvingRequestType.ROOT_PARITY]: ParityPublicInputs; +}; + +export type ProvingRequestResult = [ProvingRequestPublicInputs[T], Proof]; diff --git a/yarn-project/prover-client/src/prover/bb_prover_base_rollup.test.ts b/yarn-project/prover-client/src/prover/bb_prover_base_rollup.test.ts index bd010508498..4b1e0337337 100644 --- a/yarn-project/prover-client/src/prover/bb_prover_base_rollup.test.ts +++ b/yarn-project/prover-client/src/prover/bb_prover_base_rollup.test.ts @@ -1,14 +1,10 @@ import { createDebugLogger } from '@aztec/foundation/log'; -import { type MemDown, default as memdown } from 'memdown'; - import { makeBloatedProcessedTx } from '../mocks/fixtures.js'; import { TestContext } from '../mocks/test_context.js'; import { buildBaseRollupInput } from '../orchestrator/block-building-helpers.js'; import { BBNativeRollupProver, type BBProverConfig } from './bb_prover.js'; -export const createMemDown = () => (memdown as any)() as MemDown; - const logger = createDebugLogger('aztec:bb-prover-base-rollup'); describe('prover/bb_prover/base-rollup', () => { @@ -19,7 +15,7 @@ describe('prover/bb_prover/base-rollup', () => { bbConfig.circuitFilter = ['BaseRollupArtifact']; return BBNativeRollupProver.new(bbConfig); }; - context = await TestContext.new(logger, buildProver); + context = await TestContext.new(logger, 1, buildProver); }, 60_000); afterAll(async () => { diff --git a/yarn-project/prover-client/src/prover/bb_prover_full_rollup.test.ts b/yarn-project/prover-client/src/prover/bb_prover_full_rollup.test.ts index 3e77bdb45f8..5d8fbc7b8dd 100644 --- a/yarn-project/prover-client/src/prover/bb_prover_full_rollup.test.ts +++ b/yarn-project/prover-client/src/prover/bb_prover_full_rollup.test.ts @@ -3,20 +3,16 @@ import { Fr, Header } from '@aztec/circuits.js'; import { times } from '@aztec/foundation/collection'; import { createDebugLogger } from '@aztec/foundation/log'; -import { type MemDown, default as memdown } from 'memdown'; - import { TestContext } from '../mocks/test_context.js'; import { BBNativeRollupProver } from './bb_prover.js'; -export const createMemDown = () => (memdown as any)() as MemDown; - const logger = createDebugLogger('aztec:bb-prover-full-rollup'); describe('prover/bb_prover/full-rollup', () => { let context: TestContext; beforeAll(async () => { - context = await TestContext.new(logger, BBNativeRollupProver.new); + context = await TestContext.new(logger, 1, BBNativeRollupProver.new); }, 60_000); afterAll(async () => { @@ -56,7 +52,5 @@ describe('prover/bb_prover/full-rollup', () => { const blockResult = await context.orchestrator.finaliseBlock(); await expect(context.prover.verifyProof('RootRollupArtifact', blockResult.proof)).resolves.not.toThrow(); - - await context.orchestrator.stop(); }, 600_000); }); diff --git a/yarn-project/prover-client/src/prover/bb_prover_parity.test.ts b/yarn-project/prover-client/src/prover/bb_prover_parity.test.ts index 58fafabdf3d..8f112fd9988 100644 --- a/yarn-project/prover-client/src/prover/bb_prover_parity.test.ts +++ b/yarn-project/prover-client/src/prover/bb_prover_parity.test.ts @@ -10,13 +10,9 @@ import { makeTuple } from '@aztec/foundation/array'; import { createDebugLogger } from '@aztec/foundation/log'; import { type Tuple } from '@aztec/foundation/serialize'; -import { type MemDown, default as memdown } from 'memdown'; - import { TestContext } from '../mocks/test_context.js'; import { BBNativeRollupProver, type BBProverConfig } from './bb_prover.js'; -export const createMemDown = () => (memdown as any)() as MemDown; - const logger = createDebugLogger('aztec:bb-prover-parity'); describe('prover/bb_prover/parity', () => { @@ -27,7 +23,7 @@ describe('prover/bb_prover/parity', () => { bbConfig.circuitFilter = ['BaseParityArtifact', 'RootParityArtifact']; return BBNativeRollupProver.new(bbConfig); }; - context = await TestContext.new(logger, buildProver); + context = await TestContext.new(logger, 1, buildProver); }, 60_000); afterAll(async () => { diff --git a/yarn-project/prover-client/src/prover/bb_prover_public_kernel.test.ts b/yarn-project/prover-client/src/prover/bb_prover_public_kernel.test.ts index d25675c41e9..17bb3e55a42 100644 --- a/yarn-project/prover-client/src/prover/bb_prover_public_kernel.test.ts +++ b/yarn-project/prover-client/src/prover/bb_prover_public_kernel.test.ts @@ -3,13 +3,9 @@ import { type Proof, makeEmptyProof } from '@aztec/circuits.js'; import { createDebugLogger } from '@aztec/foundation/log'; import { type ServerProtocolArtifact } from '@aztec/noir-protocol-circuits-types'; -import { type MemDown, default as memdown } from 'memdown'; - import { TestContext } from '../mocks/test_context.js'; import { BBNativeRollupProver, type BBProverConfig } from './bb_prover.js'; -export const createMemDown = () => (memdown as any)() as MemDown; - const logger = createDebugLogger('aztec:bb-prover-public-kernel'); describe('prover/bb_prover/public-kernel', () => { @@ -25,7 +21,7 @@ describe('prover/bb_prover/public-kernel', () => { ]; return BBNativeRollupProver.new(bbConfig); }; - context = await TestContext.new(logger, buildProver); + context = await TestContext.new(logger, 1, buildProver); }, 60_000); afterAll(async () => { diff --git a/yarn-project/prover-client/src/tx-prover/tx-prover.ts b/yarn-project/prover-client/src/tx-prover/tx-prover.ts index daa7259f65c..14f36024a39 100644 --- a/yarn-project/prover-client/src/tx-prover/tx-prover.ts +++ b/yarn-project/prover-client/src/tx-prover/tx-prover.ts @@ -7,6 +7,8 @@ import { type WorldStateSynchronizer } from '@aztec/world-state'; import { type ProverConfig } from '../config.js'; import { type VerificationKeys, getVerificationKeys } from '../mocks/verification_keys.js'; import { ProvingOrchestrator } from '../orchestrator/orchestrator.js'; +import { CircuitProverAgent } from '../prover-pool/circuit-prover-agent.js'; +import { ProverPool } from '../prover-pool/prover-pool.js'; import { TestCircuitProver } from '../prover/test_circuit_prover.js'; /** @@ -14,29 +16,35 @@ import { TestCircuitProver } from '../prover/test_circuit_prover.js'; */ export class TxProver implements ProverClient { private orchestrator: ProvingOrchestrator; + private proverPool: ProverPool; + constructor( private worldStateSynchronizer: WorldStateSynchronizer, simulationProvider: SimulationProvider, protected vks: VerificationKeys, + agentCount = 4, + agentPollIntervalMS = 10, ) { - this.orchestrator = new ProvingOrchestrator( - worldStateSynchronizer.getLatest(), - new TestCircuitProver(simulationProvider), + this.proverPool = new ProverPool( + agentCount, + i => new CircuitProverAgent(new TestCircuitProver(simulationProvider), agentPollIntervalMS, `${i}`), ); + + this.orchestrator = new ProvingOrchestrator(worldStateSynchronizer.getLatest(), this.proverPool.queue); } /** * Starts the prover instance */ - public start() { - return this.orchestrator.start(); + public async start() { + await this.proverPool.start(); } /** * Stops the prover instance */ public async stop() { - await this.orchestrator.stop(); + await this.proverPool.stop(); } /** From e26d342c5646425da31d95c50ce94025e5c6d053 Mon Sep 17 00:00:00 2001 From: Santiago Palladino Date: Fri, 19 Apr 2024 10:53:29 -0300 Subject: [PATCH 034/102] refactor: Reorganize gas fields in structs (#5828) Move gas stuff around! More info in [this internal doc](https://hackmd.io/v1EJ-qG3SzGpFg7WO9QlOw). Suggest reviewing per commit. - Removes all gas fields (`gasFee`, `gasSettings`, `transactionFee`) from `CallContext` - Removes unused flags `isFeePayment` and `isRebate` from `TxContext` - Removes `PrivateGlobalVariables` - Adds `gasSettings` to `TxContext`, removing them from `CombinedConstantData`, `TxRequest`, and `TxExecutionRequest` - Adds `gasLeft` and `transactionFee` to `PublicContextInputs` - Adds `startGasLeft`, `endGasLeft`, and `transactionFee` to `PublicCircuitPublicInputs`, removing `gasFee` - Adds `TxContext` to `PrivateContextInputs` and `PrivateCircuitPublicInputs`, removing `chainId` and `version` - Refactors `GasSettings` so it depends on `Gas` and `GasFees`, removing `DimensionGasFees` --- .../contracts/references/globals.md | 8 +- .../writing_contracts/functions/context.md | 6 +- .../circuits/private-function.md | 19 +- .../circuits/private-kernel-initial.mdx | 3 - .../circuits/private-kernel-inner.mdx | 3 - .../rollup-circuits/base-rollup.md | 26 +-- .../protocol-specs/rollup-circuits/index.md | 6 +- .../transactions/local-execution.md | 2 +- .../protocol-specs/transactions/tx-object.md | 1 - .../src/core/libraries/ConstantsGen.sol | 19 +- .../aztec-nr/aztec/src/context/globals.nr | 1 - .../globals/private_global_variables.nr | 26 --- .../context/inputs/private_context_inputs.nr | 11 +- .../context/inputs/public_context_inputs.nr | 5 +- .../aztec/src/context/private_context.nr | 11 +- .../aztec/src/context/public_context.nr | 4 +- .../crates/private-kernel-lib/src/common.nr | 10 +- .../src/private_kernel_init.nr | 19 +- .../crates/public-kernel-lib/src/common.nr | 17 +- .../src/public_kernel_app_logic.nr | 8 +- .../src/public_kernel_setup.nr | 20 +- .../private_accumulated_data.nr | 6 +- .../private_accumulated_data_builder.nr | 9 +- .../crates/types/src/abis/call_context.nr | 13 -- .../types/src/abis/combined_constant_data.nr | 4 - .../crates/types/src/abis/gas_fees.nr | 2 +- .../crates/types/src/abis/gas_settings.nr | 103 ++++------ .../types/src/abis/private_call_stack_item.nr | 2 +- .../src/abis/private_circuit_public_inputs.nr | 31 ++- .../types/src/abis/public_call_stack_item.nr | 4 +- .../src/abis/public_circuit_public_inputs.nr | 26 ++- .../crates/types/src/constants.nr | 19 +- .../crates/types/src/tests.nr | 1 - .../crates/types/src/tests/fixture_builder.nr | 13 +- .../src/tests/private_call_data_builder.nr | 20 +- .../private_circuit_public_inputs_builder.nr | 24 +-- .../src/tests/public_call_data_builder.nr | 3 - .../public_circuit_public_inputs_builder.nr | 12 +- .../crates/types/src/tests/testing_harness.nr | 5 - .../types/src/transaction/tx_context.nr | 51 ++--- .../types/src/transaction/tx_request.nr | 24 +-- .../contract/contract_function_interaction.ts | 4 +- .../src/entrypoint/default_entrypoint.ts | 4 +- .../default_multi_call_entrypoint.ts | 4 +- yarn-project/circuit-types/src/mocks.ts | 2 +- .../circuit-types/src/tx_execution_request.ts | 10 +- yarn-project/circuits.js/src/constants.gen.ts | 18 +- .../private_call_stack_item.test.ts.snap | 4 +- ...private_circuit_public_inputs.test.ts.snap | 4 +- .../public_call_stack_item.test.ts.snap | 8 +- .../public_circuit_public_inputs.test.ts.snap | 4 +- .../__snapshots__/tx_context.test.ts.snap | 2 +- .../__snapshots__/tx_request.test.ts.snap | 2 +- .../circuits.js/src/structs/call_context.ts | 32 +--- .../structs/context/private_context_inputs.ts | 22 +++ .../structs/context/public_context_inputs.ts | 40 ++++ yarn-project/circuits.js/src/structs/gas.ts | 11 ++ .../circuits.js/src/structs/gas_fees.ts | 35 +++- .../circuits.js/src/structs/gas_settings.ts | 178 ++++++------------ yarn-project/circuits.js/src/structs/index.ts | 2 + .../structs/kernel/combined_constant_data.ts | 14 +- .../kernel/private_accumulated_data.ts | 7 - .../structs/private_circuit_public_inputs.ts | 26 +-- .../structs/public_circuit_public_inputs.ts | 22 ++- .../src/structs/tx_context.test.ts | 4 +- .../circuits.js/src/structs/tx_context.ts | 65 +++---- .../src/structs/tx_request.test.ts | 11 +- .../circuits.js/src/structs/tx_request.ts | 16 +- .../circuits.js/src/tests/factories.ts | 15 +- .../src/benchmarks/bench_tx_size_fees.test.ts | 8 +- .../src/e2e_dapp_subscription.test.ts | 8 +- yarn-project/end-to-end/src/e2e_fees.test.ts | 8 +- .../src/flakey_e2e_account_init_fees.test.ts | 10 +- .../entrypoints/src/account_entrypoint.ts | 4 +- .../entrypoints/src/dapp_entrypoint.ts | 5 +- .../nested-call-private-kernel-init.hex | 2 +- .../nested-call-private-kernel-inner.hex | 2 +- .../nested-call-private-kernel-ordering.hex | 2 +- .../src/type_conversion.ts | 56 ++---- .../src/instance-deployer/index.ts | 2 +- .../src/pxe_service/test/pxe_test_suite.ts | 2 - .../src/client/client_execution_context.ts | 26 +-- .../src/client/private_execution.test.ts | 14 +- .../simulator/src/client/simulator.ts | 4 - yarn-project/simulator/src/mocks/fixtures.ts | 16 +- .../src/public/abstract_phase_manager.ts | 5 +- .../simulator/src/public/avm_executor.test.ts | 14 +- .../simulator/src/public/execution.ts | 2 +- yarn-project/simulator/src/public/executor.ts | 4 +- .../simulator/src/public/index.test.ts | 6 - .../src/public/public_execution_context.ts | 23 ++- .../src/public/transitional_adaptors.ts | 9 +- 92 files changed, 608 insertions(+), 787 deletions(-) delete mode 100644 noir-projects/aztec-nr/aztec/src/context/globals/private_global_variables.nr delete mode 100644 noir-projects/noir-protocol-circuits/crates/types/src/tests/testing_harness.nr create mode 100644 yarn-project/circuits.js/src/structs/context/private_context_inputs.ts create mode 100644 yarn-project/circuits.js/src/structs/context/public_context_inputs.ts diff --git a/docs/docs/developers/contracts/references/globals.md b/docs/docs/developers/contracts/references/globals.md index 987d194c15e..f1308c4ca96 100644 --- a/docs/docs/developers/contracts/references/globals.md +++ b/docs/docs/developers/contracts/references/globals.md @@ -11,9 +11,9 @@ For developers coming from solidity, this concept will be similar to how the glo ## Private Global Variables -#include_code private-global-variables /noir-projects/aztec-nr/aztec/src/context/globals/private_global_variables.nr rust +#include_code tx-context /noir-projects/noir-protocol-circuits/crates/types/src/transaction/tx_context.nr rust -The private global variables contain: +The private global variables are equal to the transaction context and contain: ### Chain Id @@ -31,6 +31,10 @@ The version number indicates which Aztec hardfork you are on. The Genesis block context.version(); ``` +### Gas Settings + +The gas limits set by the user for the transaction, the max fee per gas, and the inclusion fee. + ## Public Global Variables #include_code global-variables /noir-projects/noir-protocol-circuits/crates/types/src/abis/global_variables.nr rust diff --git a/docs/docs/developers/contracts/writing_contracts/functions/context.md b/docs/docs/developers/contracts/writing_contracts/functions/context.md index 1bf93ed093f..172d13890ea 100644 --- a/docs/docs/developers/contracts/writing_contracts/functions/context.md +++ b/docs/docs/developers/contracts/writing_contracts/functions/context.md @@ -76,11 +76,11 @@ In the public context this header is set by sequencer (sequencer executes public #include_code header /noir-projects/noir-protocol-circuits/crates/types/src/header.nr rust -### Private Global Variables +### Transaction Context -In the private execution context, we only have access to a subset of the total global variables, we are restricted to those which can be reliably proven by the kernel circuits. +The private context provides access to the transaction context as well, which are user-defined values for the transaction in general that stay constant throughout its execution. -#include_code private-global-variables /noir-projects/aztec-nr/aztec/src/context/globals/private_global_variables.nr rust +#include_code tx-context /noir-projects/noir-protocol-circuits/crates/types/src/transaction/tx_context.nr rust ### Args Hash diff --git a/docs/docs/protocol-specs/circuits/private-function.md b/docs/docs/protocol-specs/circuits/private-function.md index 6b603c08401..79051d9b81c 100644 --- a/docs/docs/protocol-specs/circuits/private-function.md +++ b/docs/docs/protocol-specs/circuits/private-function.md @@ -67,18 +67,13 @@ After generating a proof for a private function circuit, that proof (and associa ### `CallContext` -| Field | Type | Description | -| -------------------------- | ----------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `msg_sender` | `AztecAddress` | Address of the caller contract. | -| `storage_contract_address` | `AztecAddress` | Address of the contract against which all state changes will be stored. (It is not called `contract_address`, because in the context of delegate calls, that would be an ambiguous name.) | -| `portal_contract_address` | `AztecAddress` | Address of the portal contract to the storage contract. | -| `is_delegate_call` | `bool` | A flag indicating whether the call is a [delegate call](../calls/delegate-calls.md). | -| `is_static_call` | `bool` | A flag indicating whether the call is a [static call](../calls/static-calls.md). | -| `gas_settings` | [`GasSettings`](#gassettings) | User-defined limits and max fees per each gas dimension for the transaction. | -| `gas_left.da_gas` | `u32` | How much DA gas is available for this call. | -| `gas_left.l1_gas` | `u32` | How much L1 gas is available for this call. | -| `gas_left.l2_gas` | `u32` | How much L2 gas is available for this call. | -| `transaction_fee` | `field` | Accumulated transaction fee, only set during teardown phase. | +| Field | Type | Description | +| -------------------------- | -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `msg_sender` | `AztecAddress` | Address of the caller contract. | +| `storage_contract_address` | `AztecAddress` | Address of the contract against which all state changes will be stored. (It is not called `contract_address`, because in the context of delegate calls, that would be an ambiguous name.) | +| `portal_contract_address` | `AztecAddress` | Address of the portal contract to the storage contract. | +| `is_delegate_call` | `bool` | A flag indicating whether the call is a [delegate call](../calls/delegate-calls.md). | +| `is_static_call` | `bool` | A flag indicating whether the call is a [static call](../calls/static-calls.md). | ### `GasSettings` diff --git a/docs/docs/protocol-specs/circuits/private-kernel-initial.mdx b/docs/docs/protocol-specs/circuits/private-kernel-initial.mdx index f1815a556e5..c946a84656f 100644 --- a/docs/docs/protocol-specs/circuits/private-kernel-initial.mdx +++ b/docs/docs/protocol-specs/circuits/private-kernel-initial.mdx @@ -493,9 +493,6 @@ class CallContext { portal_contract_address: AztecAddress is_delegate_call: bool is_static_call: bool - gas_left: Gas - gas_settings: GasSettings - transaction_fee: field } CallContext ..> CallerContext : call_context diff --git a/docs/docs/protocol-specs/circuits/private-kernel-inner.mdx b/docs/docs/protocol-specs/circuits/private-kernel-inner.mdx index acc3c2495a0..7041d3a6999 100644 --- a/docs/docs/protocol-specs/circuits/private-kernel-inner.mdx +++ b/docs/docs/protocol-specs/circuits/private-kernel-inner.mdx @@ -291,9 +291,6 @@ class CallContext { portal_contract_address: AztecAddress is_delegate_call: bool is_static_call: bool - gas_left: Gas - gas_settings: GasSettings - transaction_fee: field } CallContext ..> CallerContext : call_context diff --git a/docs/docs/protocol-specs/rollup-circuits/base-rollup.md b/docs/docs/protocol-specs/rollup-circuits/base-rollup.md index dc1e75f93df..c4cd165b165 100644 --- a/docs/docs/protocol-specs/rollup-circuits/base-rollup.md +++ b/docs/docs/protocol-specs/rollup-circuits/base-rollup.md @@ -124,12 +124,6 @@ class PublicDataRead { value: Fr } -class NewContractData { - function_tree_root: Fr - address: Address - portal: EthAddress -} - class CombinedAccumulatedData { aggregation_object: AggregationObject read_requests: List~Fr~ @@ -139,7 +133,6 @@ class CombinedAccumulatedData { nullified_note_hashes: List~Fr~ l2_to_l1_messages: List~Fr~ - contracts: List~NewContractData~ public_update_requests: List~PublicDataUpdateRequest~ public_reads: List~PublicDataRead~ logs: Logs @@ -153,37 +146,24 @@ class CombinedAccumulatedData { gas_used.l1_gas: u32 gas_used.l2_gas: u32 } -CombinedAccumulatedData *-- "m" NewContractData: contracts CombinedAccumulatedData *-- "m" PublicDataUpdateRequest: public_update_requests CombinedAccumulatedData *-- "m" PublicDataRead: public_reads CombinedAccumulatedData *-- Logs : logs -class ContractDeploymentData { - deployer_public_key: Point - constructor_vk_hash: Fr - constructor_args_hash: Fr - function_tree_root: Fr - salt: Fr - portal_address: Fr -} - class TxContext { - fee_context: FeeContext - is_contract_deployment: bool chain_id: Fr version: Fr - contract_deployment_data: ContractDeploymentData + gas_settings: GasSettings } -TxContext *-- ContractDeploymentData: contract_deployment_data + +TxContext *-- GasSettings : gas_settings class CombinedConstantData { historical_header: Header tx_context: TxContext - gas_settings: GasSettings } CombinedConstantData *-- Header : historical_header CombinedConstantData *-- TxContext : tx_context -CombinedConstantData *-- GasSettings : gas_settings class GasSettings { da.gas_limit: u32 diff --git a/docs/docs/protocol-specs/rollup-circuits/index.md b/docs/docs/protocol-specs/rollup-circuits/index.md index 21284ea1974..0cdac7e1f49 100644 --- a/docs/docs/protocol-specs/rollup-circuits/index.md +++ b/docs/docs/protocol-specs/rollup-circuits/index.md @@ -275,19 +275,19 @@ CombinedAccumulatedData *-- "m" PublicDataRead: public_reads CombinedAccumulatedData *-- Logs : logs class TxContext { - fee_context: FeeContext chain_id: Fr version: Fr + gas_settings: GasSettings } +TxContext *-- GasSettings : gas_settings + class CombinedConstantData { historical_header: Header tx_context: TxContext - gas_settings: GasSettings } CombinedConstantData *-- Header : historical_header CombinedConstantData *-- TxContext : tx_context -CombinedConstantData *-- GasSettings : gas_settings class GasSettings { da.gas_limit: u32 diff --git a/docs/docs/protocol-specs/transactions/local-execution.md b/docs/docs/protocol-specs/transactions/local-execution.md index f9f7e5c57c7..70170bdb720 100644 --- a/docs/docs/protocol-specs/transactions/local-execution.md +++ b/docs/docs/protocol-specs/transactions/local-execution.md @@ -24,7 +24,7 @@ A transaction execution request has the following structure. Note that, since Az | `origin` | `AztecAddress` | Address of the contract where the transaction is initiated. | | `functionSelector` | u32 | Selector (identifier) of the function to be called as entrypoint in the origin contract. | | `argsHash` | `Field` | Hash of the arguments to be used for calling the entrypoint function. | -| `txContext` | `TxContext` | Includes chain id, and protocol version. | +| `txContext` | `TxContext` | Includes chain id, protocol version, and gas settings. | | `packedArguments` | `PackedValues[]` | Preimages for argument hashes. When executing a function call with the hash of the arguments, the PXE will look for the preimage of that hash in this list, and expand the arguments to execute the call. | | `authWitnesses` | `AuthWitness[]` | Authorization witnesses. When authorizing an action identified by a hash, the PXE will look for the authorization witness identified by that hash and provide that value to the account contract. | diff --git a/docs/docs/protocol-specs/transactions/tx-object.md b/docs/docs/protocol-specs/transactions/tx-object.md index 20609cead71..d60f2a0b184 100644 --- a/docs/docs/protocol-specs/transactions/tx-object.md +++ b/docs/docs/protocol-specs/transactions/tx-object.md @@ -51,7 +51,6 @@ Output of the last iteration of the private kernel circuit. Includes _accumulate | unencryptedLogsHash | Field[] | Accumulated unencrypted logs hash from all the previous kernel iterations. | | encryptedLogPreimagesLength | Field | Total accumulated length of the encrypted log preimages emitted in all the previous kernel iterations. | | unencryptedLogPreimagesLength | Field | Total accumulated length of the unencrypted log preimages emitted in all the previous kernel iterations. | -| newContracts | NewContractData[] | All the new contracts deployed in this transaction. | | maxBlockNum | Field | Maximum block number (inclusive) for inclusion of this transaction in a block. | **Block header** diff --git a/l1-contracts/src/core/libraries/ConstantsGen.sol b/l1-contracts/src/core/libraries/ConstantsGen.sol index 068ee6df4ef..27a50262e36 100644 --- a/l1-contracts/src/core/libraries/ConstantsGen.sol +++ b/l1-contracts/src/core/libraries/ConstantsGen.sol @@ -90,12 +90,16 @@ library Constants { 0x85864497636cf755ae7bde03f267ce01a520981c21c3682aaf82a631; uint256 internal constant DEPLOYER_CONTRACT_ADDRESS = 0x1f47133752dfcd9604f2d89c631797a84ed207c1c51d08533226dafcc8bd8548; + uint256 internal constant DEFAULT_GAS_LIMIT = 1_000_000_000; + uint256 internal constant DEFAULT_TEARDOWN_GAS_LIMIT = 100_000_000; + uint256 internal constant DEFAULT_MAX_FEE_PER_GAS = 10; + uint256 internal constant DEFAULT_INCLUSION_FEE = 0; uint256 internal constant AZTEC_ADDRESS_LENGTH = 1; - uint256 internal constant DIMENSION_GAS_SETTINGS_LENGTH = 3; uint256 internal constant GAS_FEES_LENGTH = 3; uint256 internal constant GAS_LENGTH = 3; - uint256 internal constant GAS_SETTINGS_LENGTH = 1 + 3 * DIMENSION_GAS_SETTINGS_LENGTH; - uint256 internal constant CALL_CONTEXT_LENGTH = 8 + GAS_SETTINGS_LENGTH + GAS_LENGTH; + uint256 internal constant GAS_SETTINGS_LENGTH = + GAS_LENGTH * 2 + GAS_FEES_LENGTH /* inclusion_fee */ + 1; + uint256 internal constant CALL_CONTEXT_LENGTH = 7; uint256 internal constant CONTENT_COMMITMENT_LENGTH = 4; uint256 internal constant CONTRACT_INSTANCE_LENGTH = 6; uint256 internal constant CONTRACT_STORAGE_READ_LENGTH = 2; @@ -116,9 +120,8 @@ library Constants { uint256 internal constant SIDE_EFFECT_LINKED_TO_NOTE_HASH_LENGTH = 3; uint256 internal constant STATE_REFERENCE_LENGTH = APPEND_ONLY_TREE_SNAPSHOT_LENGTH + PARTIAL_STATE_REFERENCE_LENGTH; - uint256 internal constant TX_CONTEXT_DATA_LENGTH = 4; - uint256 internal constant TX_REQUEST_LENGTH = - 2 + TX_CONTEXT_DATA_LENGTH + FUNCTION_DATA_LENGTH + GAS_SETTINGS_LENGTH; + uint256 internal constant TX_CONTEXT_LENGTH = 2 + GAS_SETTINGS_LENGTH; + uint256 internal constant TX_REQUEST_LENGTH = 2 + TX_CONTEXT_LENGTH + FUNCTION_DATA_LENGTH; uint256 internal constant HEADER_LENGTH = APPEND_ONLY_TREE_SNAPSHOT_LENGTH + CONTENT_COMMITMENT_LENGTH + STATE_REFERENCE_LENGTH + GLOBAL_VARIABLES_LENGTH; uint256 internal constant PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH = CALL_CONTEXT_LENGTH + 3 @@ -130,7 +133,7 @@ library Constants { + MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL + (L2_TO_L1_MESSAGE_LENGTH * MAX_NEW_L2_TO_L1_MSGS_PER_CALL) + 2 + (SIDE_EFFECT_LENGTH * MAX_ENCRYPTED_LOGS_PER_CALL) - + (SIDE_EFFECT_LENGTH * MAX_UNENCRYPTED_LOGS_PER_CALL) + 2 + HEADER_LENGTH + 2; + + (SIDE_EFFECT_LENGTH * MAX_UNENCRYPTED_LOGS_PER_CALL) + 2 + HEADER_LENGTH + TX_CONTEXT_LENGTH; uint256 internal constant PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH = CALL_CONTEXT_LENGTH + 2 + (READ_REQUEST_LENGTH * MAX_NULLIFIER_READ_REQUESTS_PER_CALL) + (READ_REQUEST_LENGTH * MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL) @@ -140,7 +143,7 @@ library Constants { + (SIDE_EFFECT_LINKED_TO_NOTE_HASH_LENGTH * MAX_NEW_NULLIFIERS_PER_CALL) + (L2_TO_L1_MESSAGE_LENGTH * MAX_NEW_L2_TO_L1_MSGS_PER_CALL) + 2 + (SIDE_EFFECT_LENGTH * MAX_UNENCRYPTED_LOGS_PER_CALL) + 1 + HEADER_LENGTH + AZTEC_ADDRESS_LENGTH /* revert_code */ - + 1 + GAS_LENGTH; + + 1 + 2 * GAS_LENGTH /* transaction_fee */ + 1; uint256 internal constant PRIVATE_CALL_STACK_ITEM_LENGTH = AZTEC_ADDRESS_LENGTH + FUNCTION_DATA_LENGTH + PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH; uint256 internal constant ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH = diff --git a/noir-projects/aztec-nr/aztec/src/context/globals.nr b/noir-projects/aztec-nr/aztec/src/context/globals.nr index 8b50aa87a59..81cc3621321 100644 --- a/noir-projects/aztec-nr/aztec/src/context/globals.nr +++ b/noir-projects/aztec-nr/aztec/src/context/globals.nr @@ -1,2 +1 @@ -mod private_global_variables; mod public_global_variables; diff --git a/noir-projects/aztec-nr/aztec/src/context/globals/private_global_variables.nr b/noir-projects/aztec-nr/aztec/src/context/globals/private_global_variables.nr deleted file mode 100644 index ef8c0ed5c3f..00000000000 --- a/noir-projects/aztec-nr/aztec/src/context/globals/private_global_variables.nr +++ /dev/null @@ -1,26 +0,0 @@ -use dep::protocol_types::traits::{Serialize, Empty}; - -global PRIVATE_GLOBAL_VARIABLES_LENGTH: u64 = 2; - -// docs:start:private-global-variables -struct PrivateGlobalVariables { - chain_id: Field, - version: Field, -} -// docs:end:private-global-variables - -// Note: public global vars are equal to the private ones -impl Serialize for PrivateGlobalVariables { - fn serialize(self) -> [Field; PRIVATE_GLOBAL_VARIABLES_LENGTH] { - [self.chain_id, self.version] - } -} - -impl Empty for PrivateGlobalVariables { - fn empty() -> Self { - PrivateGlobalVariables { - chain_id: 0, - version: 0, - } - } -} \ No newline at end of file diff --git a/noir-projects/aztec-nr/aztec/src/context/inputs/private_context_inputs.nr b/noir-projects/aztec-nr/aztec/src/context/inputs/private_context_inputs.nr index 4f75c45d360..a766cf9858a 100644 --- a/noir-projects/aztec-nr/aztec/src/context/inputs/private_context_inputs.nr +++ b/noir-projects/aztec-nr/aztec/src/context/inputs/private_context_inputs.nr @@ -1,13 +1,14 @@ -use dep::protocol_types::{abis::call_context::CallContext, header::Header, traits::Empty}; -use crate::context::globals::private_global_variables::PrivateGlobalVariables; - +use dep::protocol_types::{ + transaction::tx_context::TxContext, abis::{call_context::CallContext, gas_settings::GasSettings}, + header::Header, traits::Empty +}; // PrivateContextInputs are expected to be provided to each private function // docs:start:private-context-inputs struct PrivateContextInputs { call_context : CallContext, historical_header: Header, - private_global_variables: PrivateGlobalVariables, + tx_context: TxContext, start_side_effect_counter: u32, } // docs:end:private-context-inputs @@ -17,7 +18,7 @@ impl Empty for PrivateContextInputs { PrivateContextInputs { call_context : CallContext::empty(), historical_header: Header::empty(), - private_global_variables: PrivateGlobalVariables::empty(), + tx_context: TxContext::empty(), start_side_effect_counter: 0 as u32, } } diff --git a/noir-projects/aztec-nr/aztec/src/context/inputs/public_context_inputs.nr b/noir-projects/aztec-nr/aztec/src/context/inputs/public_context_inputs.nr index fb2f1d27f42..3461315502d 100644 --- a/noir-projects/aztec-nr/aztec/src/context/inputs/public_context_inputs.nr +++ b/noir-projects/aztec-nr/aztec/src/context/inputs/public_context_inputs.nr @@ -9,8 +9,9 @@ struct PublicContextInputs { historical_header: Header, public_global_variables: PublicGlobalVariables, - start_side_effect_counter: u32, + gas_left: Gas, + transaction_fee: Field, } // docs:end:public-context-inputs @@ -21,6 +22,8 @@ impl Empty for PublicContextInputs { historical_header: Header::empty(), public_global_variables: PublicGlobalVariables::empty(), start_side_effect_counter: 0 as u32, + gas_left: Gas::empty(), + transaction_fee: 0, } } } diff --git a/noir-projects/aztec-nr/aztec/src/context/private_context.nr b/noir-projects/aztec-nr/aztec/src/context/private_context.nr index 691e491b13b..a65da233b71 100644 --- a/noir-projects/aztec-nr/aztec/src/context/private_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/private_context.nr @@ -87,11 +87,11 @@ impl ContextInterface for PrivateContext { } fn chain_id(self) -> Field { - self.inputs.private_global_variables.chain_id + self.inputs.tx_context.chain_id } fn version(self) -> Field { - self.inputs.private_global_variables.version + self.inputs.tx_context.version } fn selector(self) -> FunctionSelector { @@ -190,8 +190,7 @@ impl PrivateContext { encrypted_log_preimages_length, unencrypted_log_preimages_length, historical_header: self.historical_header, - chain_id: self.inputs.private_global_variables.chain_id, - version: self.inputs.private_global_variables.version + tx_context: self.inputs.tx_context }; priv_circuit_pub_inputs @@ -500,7 +499,9 @@ impl PrivateContext { historical_header: Header::empty(), prover_address: AztecAddress::zero(), revert_code: 0, - gas_left: Gas::empty() + start_gas_left: Gas::empty(), + end_gas_left: Gas::empty(), + transaction_fee: 0 }, is_execution_request: true }; diff --git a/noir-projects/aztec-nr/aztec/src/context/public_context.nr b/noir-projects/aztec-nr/aztec/src/context/public_context.nr index ba70631a79f..e37c80eb4f6 100644 --- a/noir-projects/aztec-nr/aztec/src/context/public_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/public_context.nr @@ -169,7 +169,9 @@ impl PublicContext { historical_header: self.inputs.historical_header, prover_address: self.prover_address, revert_code: 0, - gas_left: self.inputs.call_context.gas_left + start_gas_left: self.inputs.gas_left, + end_gas_left: self.inputs.gas_left, // AVM should decrease this value + transaction_fee: self.inputs.transaction_fee }; pub_circuit_pub_inputs } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/common.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/common.nr index 7b188057a16..72c62b8f903 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/common.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/common.nr @@ -16,8 +16,8 @@ use dep::types::{ MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL }, hash::{ - compute_l2_to_l1_hash, pedersen_hash, private_functions_root_from_siblings, - silo_note_hash, silo_nullifier, stdlib_recursion_verification_key_compress_native_vk, + compute_l2_to_l1_hash, pedersen_hash, private_functions_root_from_siblings, silo_note_hash, + silo_nullifier, stdlib_recursion_verification_key_compress_native_vk }, merkle_tree::check_membership, utils::{arrays::{array_length, array_to_bounded_vec, validate_array}}, @@ -280,15 +280,15 @@ pub fn update_end_values( if !is_empty(msg) { let new_l2_to_l1_msgs = compute_l2_to_l1_hash( storage_contract_address, - private_call_public_inputs.version, - private_call_public_inputs.chain_id, + private_call_public_inputs.tx_context.version, + private_call_public_inputs.tx_context.chain_id, msg ); new_l2_to_l1_msgs_to_insert.push(new_l2_to_l1_msgs) } } public_inputs.end.new_l2_to_l1_msgs.extend_from_bounded_vec(new_l2_to_l1_msgs_to_insert); - + // logs hashes // See the following thread if not clear: // https://discourse.aztec.network/t/proposal-forcing-the-sequencer-to-actually-submit-data-to-l1/426 diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_init.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_init.nr index 3f9677da95b..64bc2e703dd 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_init.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_init.nr @@ -22,7 +22,6 @@ impl PrivateKernelInitCircuitPrivateInputs { public_inputs.constants = CombinedConstantData { historical_header: self.private_call.call_stack_item.public_inputs.historical_header, tx_context: self.tx_request.tx_context, - gas_settings: self.tx_request.gas_settings, }; public_inputs.min_revertible_side_effect_counter = self.private_call.call_stack_item.public_inputs.min_revertible_side_effect_counter; } @@ -163,9 +162,15 @@ mod tests { let unencrypted_logs_hashes = [26, 46]; let unencrypted_log_preimages_length = [50, 25]; builder.private_call.set_encrypted_logs(encrypted_logs_hashes[0], encrypted_log_preimages_length[0]); - builder.private_call.set_unencrypted_logs(unencrypted_logs_hashes[0], unencrypted_log_preimages_length[0]); + builder.private_call.set_unencrypted_logs( + unencrypted_logs_hashes[0], + unencrypted_log_preimages_length[0] + ); builder.private_call.set_encrypted_logs(encrypted_logs_hashes[1], encrypted_log_preimages_length[1]); - builder.private_call.set_unencrypted_logs(unencrypted_logs_hashes[1], unencrypted_log_preimages_length[1]); + builder.private_call.set_unencrypted_logs( + unencrypted_logs_hashes[1], + unencrypted_log_preimages_length[1] + ); let public_inputs = builder.execute(); @@ -174,8 +179,12 @@ mod tests { assert_eq(public_inputs.end.new_nullifiers[0].value, tx_hash); // Log preimages length should increase by `(un)encrypted_log_preimages_length` from private input - assert_eq(public_inputs.end.encrypted_log_preimages_length, encrypted_log_preimages_length.reduce(|a, b| a + b)); - assert_eq(public_inputs.end.unencrypted_log_preimages_length, unencrypted_log_preimages_length.reduce(|a, b| a + b)); + assert_eq( + public_inputs.end.encrypted_log_preimages_length, encrypted_log_preimages_length.reduce(|a, b| a + b) + ); + assert_eq( + public_inputs.end.unencrypted_log_preimages_length, unencrypted_log_preimages_length.reduce(|a, b| a + b) + ); assert_eq(public_inputs.end.encrypted_logs_hashes[0].value, encrypted_logs_hashes[0]); assert_eq(public_inputs.end.unencrypted_logs_hashes[0].value, unencrypted_logs_hashes[0]); assert_eq(public_inputs.end.encrypted_logs_hashes[1].value, encrypted_logs_hashes[1]); diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/common.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/common.nr index b9d428ecd6c..7cff5c51619 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/common.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/common.nr @@ -172,8 +172,8 @@ pub fn update_validation_requests(public_call: PublicCallData, circuit_outputs: } pub fn update_revertible_gas_used(public_call: PublicCallData, circuit_outputs: &mut PublicKernelCircuitPublicInputsBuilder) { - let tx_gas_limits = circuit_outputs.constants.gas_settings.get_gas_limits(); - let call_gas_left = public_call.call_stack_item.public_inputs.gas_left; + let tx_gas_limits = circuit_outputs.constants.tx_context.gas_settings.gas_limits; + let call_gas_left = public_call.call_stack_item.public_inputs.end_gas_left; let accum_end_non_revertible_gas_used = circuit_outputs.end_non_revertible.gas_used; // dep::types::debug_log::debug_log_format( @@ -191,14 +191,18 @@ pub fn update_revertible_gas_used(public_call: PublicCallData, circuit_outputs: // ] // ); + // println( + // f"Updating revertible gas: tx_gas_limits={tx_gas_limits} call_gas_left={call_gas_left} accum_end_non_revertible_gas_used={accum_end_non_revertible_gas_used}" + // ); + circuit_outputs.end.gas_used = tx_gas_limits .sub(call_gas_left) .sub(accum_end_non_revertible_gas_used); } pub fn update_non_revertible_gas_used(public_call: PublicCallData, circuit_outputs: &mut PublicKernelCircuitPublicInputsBuilder) { - let tx_gas_limits = circuit_outputs.constants.gas_settings.get_gas_limits(); - let call_gas_left = public_call.call_stack_item.public_inputs.gas_left; + let tx_gas_limits = circuit_outputs.constants.tx_context.gas_settings.gas_limits; + let call_gas_left = public_call.call_stack_item.public_inputs.end_gas_left; let accum_end_gas_used = circuit_outputs.end.gas_used; // dep::types::debug_log::debug_log_format( @@ -519,7 +523,10 @@ pub fn propagate_new_unencrypted_logs(public_call: PublicCallData, public_inputs public_inputs.end.unencrypted_log_preimages_length += public_call.call_stack_item.public_inputs.unencrypted_log_preimages_length; } -pub fn propagate_new_unencrypted_logs_non_revertible(public_call: PublicCallData, public_inputs: &mut PublicKernelCircuitPublicInputsBuilder) { +pub fn propagate_new_unencrypted_logs_non_revertible( + public_call: PublicCallData, + public_inputs: &mut PublicKernelCircuitPublicInputsBuilder +) { // new unencrypted logs let new_logs = public_call.call_stack_item.public_inputs.unencrypted_logs_hashes; // TODO(Miranda): silo logs here once we have finalised struct diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_app_logic.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_app_logic.nr index dda4e888bdc..fe42b435064 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_app_logic.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_app_logic.nr @@ -448,18 +448,16 @@ mod tests { let mut builder = PublicKernelAppLogicCircuitPrivateInputsBuilder::new(); // Transaction gas limit is 1k - builder.previous_kernel.gas_settings.da.gas_limit = 1000; - builder.previous_kernel.gas_settings.l1.gas_limit = 1000; - builder.previous_kernel.gas_settings.l2.gas_limit = 1000; + builder.previous_kernel.tx_context.gas_settings.gas_limits = Gas::new(1000, 1000, 1000); // Revertible has already used 300 builder.previous_kernel.gas_used = Gas::new(300, 300, 300); // This call starts with 700 gas left - builder.public_call.public_inputs.call_context.gas_left = Gas::new(700, 700, 700); + builder.public_call.public_inputs.start_gas_left = Gas::new(700, 700, 700); // And uses 200, ending with 500 left - builder.public_call.public_inputs.gas_left = Gas::new(500, 500, 500); + builder.public_call.public_inputs.end_gas_left = Gas::new(500, 500, 500); // So the updated gas used by revertible must go up by 200, and non-revertible must stay the same let output = builder.execute(); diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_setup.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_setup.nr index 1703f951a53..9b0f1764a6a 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_setup.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_setup.nr @@ -437,7 +437,7 @@ mod tests { // Logs for the previous call stack. let prev_encrypted_logs_hash = 80; let prev_encrypted_log_preimages_length = 13; - let prev_unencrypted_logs_hash = 956; + let prev_unencrypted_logs_hash = 956; let prev_unencrypted_log_preimages_length = 24; builder.previous_kernel.set_encrypted_logs(prev_encrypted_logs_hash, prev_encrypted_log_preimages_length); builder.previous_kernel.set_unencrypted_logs( @@ -446,14 +446,18 @@ mod tests { ); let public_inputs = builder.execute(); - - assert_eq(public_inputs.end_non_revertible.encrypted_log_preimages_length, prev_encrypted_log_preimages_length); + + assert_eq( + public_inputs.end_non_revertible.encrypted_log_preimages_length, prev_encrypted_log_preimages_length + ); assert_eq( public_inputs.end_non_revertible.unencrypted_log_preimages_length, unencrypted_log_preimages_length + prev_unencrypted_log_preimages_length ); assert_eq(public_inputs.end_non_revertible.encrypted_logs_hashes[0].value, prev_encrypted_logs_hash); - assert_eq(public_inputs.end_non_revertible.unencrypted_logs_hashes[0].value, prev_unencrypted_logs_hash); + assert_eq( + public_inputs.end_non_revertible.unencrypted_logs_hashes[0].value, prev_unencrypted_logs_hash + ); assert_eq(public_inputs.end_non_revertible.unencrypted_logs_hashes[1].value, unencrypted_logs_hash); } @@ -496,9 +500,7 @@ mod tests { let mut builder = PublicKernelSetupCircuitPrivateInputsBuilder::new(); // Transaction gas limit is 1k - builder.previous_kernel.gas_settings.da.gas_limit = 1000; - builder.previous_kernel.gas_settings.l1.gas_limit = 1000; - builder.previous_kernel.gas_settings.l2.gas_limit = 1000; + builder.previous_kernel.tx_context.gas_settings.gas_limits = Gas::new(1000, 1000, 1000); // Revertible has already used 100 builder.previous_revertible.gas_used = Gas::new(100, 100, 100); @@ -507,10 +509,10 @@ mod tests { builder.previous_kernel.gas_used = Gas::new(200, 200, 200); // So this call starts with 700 gas left - builder.public_call.public_inputs.call_context.gas_left = Gas::new(700, 700, 700); + builder.public_call.public_inputs.start_gas_left = Gas::new(700, 700, 700); // And uses 300, ending with 400 left - builder.public_call.public_inputs.gas_left = Gas::new(400, 400, 400); + builder.public_call.public_inputs.end_gas_left = Gas::new(400, 400, 400); // So the updated gas used by non-revertible must go up by 300, and revertible must stay the same let output = builder.execute(); diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data.nr index 2fc4064125a..cfde3348d1b 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data.nr @@ -1,8 +1,8 @@ use crate::{abis::{call_request::CallRequest, gas::Gas, side_effect::{SideEffect, SideEffectLinkedToNoteHash}}}; use crate::constants::{ MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, - MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, MAX_NEW_L2_TO_L1_MSGS_PER_TX, - MAX_ENCRYPTED_LOGS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX + MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, MAX_NEW_L2_TO_L1_MSGS_PER_TX, MAX_ENCRYPTED_LOGS_PER_TX, + MAX_UNENCRYPTED_LOGS_PER_TX }; struct PrivateAccumulatedData { @@ -20,6 +20,4 @@ struct PrivateAccumulatedData { private_call_stack: [CallRequest; MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX], public_call_stack: [CallRequest; MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX], - - gas_used: Gas, } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data_builder.nr index 464fdda2079..bc735cc1558 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data_builder.nr @@ -34,7 +34,7 @@ struct PrivateAccumulatedDataBuilder { private_call_stack: BoundedVec, public_call_stack: BoundedVec, - gas_used: Gas + gas_used: Gas, } impl PrivateAccumulatedDataBuilder { @@ -48,8 +48,7 @@ impl PrivateAccumulatedDataBuilder { encrypted_log_preimages_length: self.encrypted_log_preimages_length, unencrypted_log_preimages_length: self.unencrypted_log_preimages_length, private_call_stack: self.private_call_stack.storage, - public_call_stack: self.public_call_stack.storage, - gas_used: self.gas_used + public_call_stack: self.public_call_stack.storage } } @@ -62,8 +61,8 @@ impl PrivateAccumulatedDataBuilder { new_note_hashes: self.new_note_hashes.storage.map(|n: SideEffect| n.value), new_nullifiers: self.new_nullifiers.storage.map(|n: SideEffectLinkedToNoteHash| n.value), new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage, - encrypted_logs_hash: encrypted_logs_hash, - unencrypted_logs_hash: unencrypted_logs_hash, + encrypted_logs_hash, + unencrypted_logs_hash, encrypted_log_preimages_length: self.encrypted_log_preimages_length, unencrypted_log_preimages_length: self.unencrypted_log_preimages_length, public_data_update_requests: [PublicDataUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/call_context.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/call_context.nr index 870e4b80df5..006b805fbc3 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/call_context.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/call_context.nr @@ -11,15 +11,11 @@ struct CallContext { storage_contract_address : AztecAddress, portal_contract_address : EthAddress, function_selector : FunctionSelector, - gas_left: Gas, is_delegate_call : bool, is_static_call : bool, side_effect_counter : u32, - - gas_settings: GasSettings, - transaction_fee: Field, } // docs:end:call-context @@ -53,12 +49,9 @@ impl Serialize for CallContext { serialized.push(self.storage_contract_address.to_field()); serialized.push(self.portal_contract_address.to_field()); serialized.push(self.function_selector.to_field()); - serialized.extend_from_array(self.gas_left.serialize()); serialized.push(self.is_delegate_call as Field); serialized.push(self.is_static_call as Field); serialized.push(self.side_effect_counter as Field); - serialized.extend_from_array(self.gas_settings.serialize()); - serialized.push(self.transaction_fee); serialized.storage } @@ -72,12 +65,9 @@ impl Deserialize for CallContext { storage_contract_address: AztecAddress::from_field(reader.read()), portal_contract_address: EthAddress::from_field(reader.read()), function_selector: FunctionSelector::from_field(reader.read()), - gas_left: reader.read_struct(Gas::deserialize), is_delegate_call: reader.read() as bool, is_static_call: reader.read() as bool, side_effect_counter: reader.read() as u32, - gas_settings: reader.read_struct(GasSettings::deserialize), - transaction_fee: reader.read(), } } } @@ -89,12 +79,9 @@ impl Empty for CallContext { storage_contract_address: AztecAddress::empty(), portal_contract_address: EthAddress::empty(), function_selector: FunctionSelector::empty(), - gas_left: Gas::empty(), is_delegate_call: false, is_static_call: false, side_effect_counter: 0, - gas_settings: GasSettings::empty(), - transaction_fee: 0, } } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/combined_constant_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/combined_constant_data.nr index 3b5ec8fc0ed..09655af7058 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/combined_constant_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/combined_constant_data.nr @@ -1,7 +1,6 @@ use crate::transaction::tx_context::TxContext; use crate::header::Header; use crate::traits::Empty; -use crate::abis::gas_settings::GasSettings; struct CombinedConstantData { historical_header: Header, @@ -10,8 +9,6 @@ struct CombinedConstantData { // a situation we could be using header from a block before the upgrade took place but be using the updated // protocol to execute and prove the transaction. tx_context: TxContext, - - gas_settings: GasSettings, } impl Empty for CombinedConstantData { @@ -19,7 +16,6 @@ impl Empty for CombinedConstantData { CombinedConstantData { historical_header: Header::empty(), tx_context: TxContext::empty(), - gas_settings: GasSettings::empty(), } } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas_fees.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas_fees.nr index 3495fadc65e..5e9fa42c556 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas_fees.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas_fees.nr @@ -11,7 +11,7 @@ struct GasFees { } impl GasFees { - fn new(fee_per_da_gas: Field, fee_per_l1_gas: Field, fee_per_l2_gas: Field) -> Self { + pub fn new(fee_per_da_gas: Field, fee_per_l1_gas: Field, fee_per_l2_gas: Field) -> Self { Self { fee_per_da_gas, fee_per_l1_gas, fee_per_l2_gas } } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas_settings.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas_settings.nr index f50b22528d9..ba4657985b7 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas_settings.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas_settings.nr @@ -1,44 +1,59 @@ use crate::{ abis::function_selector::FunctionSelector, address::{EthAddress, AztecAddress}, abis::gas::Gas, - constants::{GAS_SETTINGS_LENGTH, DIMENSION_GAS_SETTINGS_LENGTH}, hash::pedersen_hash, - traits::{Deserialize, Hash, Serialize, Empty}, abis::side_effect::Ordered, utils::reader::Reader + abis::gas_fees::GasFees, + constants::{ + GAS_SETTINGS_LENGTH, DEFAULT_GAS_LIMIT, DEFAULT_TEARDOWN_GAS_LIMIT, DEFAULT_MAX_FEE_PER_GAS, + DEFAULT_INCLUSION_FEE +}, + hash::pedersen_hash, traits::{Deserialize, Hash, Serialize, Empty}, abis::side_effect::Ordered, + utils::reader::Reader }; struct GasSettings { - da: DimensionGasSettings, - l1: DimensionGasSettings, - l2: DimensionGasSettings, + gas_limits: Gas, + teardown_gas_limits: Gas, + max_fees_per_gas: GasFees, inclusion_fee: Field, } impl GasSettings { - fn new( - da: DimensionGasSettings, - l1: DimensionGasSettings, - l2: DimensionGasSettings, + pub fn new( + gas_limits: Gas, + teardown_gas_limits: Gas, + max_fees_per_gas: GasFees, inclusion_fee: Field ) -> Self { - Self { da, l1, l2, inclusion_fee } + Self { gas_limits, teardown_gas_limits, max_fees_per_gas, inclusion_fee } } - fn get_gas_limits(self) -> Gas { - Gas { da_gas: self.da.gas_limit, l1_gas: self.l1.gas_limit, l2_gas: self.l2.gas_limit } + pub fn default() -> Self { + GasSettings::new( + Gas::new(DEFAULT_GAS_LIMIT, DEFAULT_GAS_LIMIT, DEFAULT_GAS_LIMIT), + Gas::new( + DEFAULT_TEARDOWN_GAS_LIMIT, + DEFAULT_TEARDOWN_GAS_LIMIT, + DEFAULT_TEARDOWN_GAS_LIMIT + ), + GasFees::new( + DEFAULT_MAX_FEE_PER_GAS, + DEFAULT_MAX_FEE_PER_GAS, + DEFAULT_MAX_FEE_PER_GAS + ), + DEFAULT_INCLUSION_FEE + ) } } impl Eq for GasSettings { fn eq(self, other: Self) -> bool { - (self.da == other.da) & (self.l1 == other.l1) & (self.l2 == other.l2) & (self.inclusion_fee == other.inclusion_fee) + (self.gas_limits == other.gas_limits) & (self.teardown_gas_limits == other.teardown_gas_limits) & (self.max_fees_per_gas == other.max_fees_per_gas) & (self.inclusion_fee == other.inclusion_fee) } } impl Empty for GasSettings { fn empty() -> Self { GasSettings::new( - DimensionGasSettings::empty(), - DimensionGasSettings::empty(), - DimensionGasSettings::empty(), - 0, + Gas::empty(), Gas::empty(), GasFees::empty(), 0 ) } } @@ -47,9 +62,9 @@ impl Serialize for GasSettings { fn serialize(self) -> [Field; GAS_SETTINGS_LENGTH] { let mut serialized: BoundedVec = BoundedVec::new(); - serialized.extend_from_array(self.da.serialize()); - serialized.extend_from_array(self.l1.serialize()); - serialized.extend_from_array(self.l2.serialize()); + serialized.extend_from_array(self.gas_limits.serialize()); + serialized.extend_from_array(self.teardown_gas_limits.serialize()); + serialized.extend_from_array(self.max_fees_per_gas.serialize()); serialized.push(self.inclusion_fee); serialized.storage @@ -59,52 +74,6 @@ impl Serialize for GasSettings { impl Deserialize for GasSettings { fn deserialize(serialized: [Field; GAS_SETTINGS_LENGTH]) -> GasSettings { let mut reader = Reader::new(serialized); - GasSettings { - da: reader.read_struct(DimensionGasSettings::deserialize), - l1: reader.read_struct(DimensionGasSettings::deserialize), - l2: reader.read_struct(DimensionGasSettings::deserialize), - inclusion_fee: reader.read(), - } - } -} - -struct DimensionGasSettings { - gas_limit: u32, - teardown_gas_limit: u32, - max_fee_per_gas: Field, -} - -impl DimensionGasSettings { - pub fn new(gas_limit: u32, teardown_gas_limit: u32, max_fee_per_gas: Field) -> Self { - Self { gas_limit, teardown_gas_limit, max_fee_per_gas } - } -} - -impl Eq for DimensionGasSettings { - fn eq(self, other: Self) -> bool { - (self.gas_limit == other.gas_limit) & (self.teardown_gas_limit == other.teardown_gas_limit) & (self.max_fee_per_gas == other.max_fee_per_gas) - } - -} - -impl Serialize for DimensionGasSettings { - fn serialize(self) -> [Field; DIMENSION_GAS_SETTINGS_LENGTH] { - [ - self.gas_limit as Field, - self.teardown_gas_limit as Field, - self.max_fee_per_gas, - ] - } -} - -impl Deserialize for DimensionGasSettings { - fn deserialize(serialized: [Field; DIMENSION_GAS_SETTINGS_LENGTH]) -> DimensionGasSettings { - DimensionGasSettings::new(serialized[0] as u32, serialized[1] as u32, serialized[2]) - } -} - -impl Empty for DimensionGasSettings { - fn empty() -> Self { - DimensionGasSettings::new(0,0,0) + GasSettings::new(reader.read_struct(Gas::deserialize), reader.read_struct(Gas::deserialize), reader.read_struct(GasFees::deserialize), reader.read()) } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr index 87a2ffcb2c6..11035fb5580 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr @@ -85,6 +85,6 @@ fn empty_hash() { let hash = item.hash(); // Value from private_call_stack_item.test.ts "computes empty item hash" test - let test_data_empty_hash = 0x2826eee20026ba6fb21916387c4dfa7843cbce1fdcff508132812be5e544f286; + let test_data_empty_hash = 0x25d9c6ba3de2cf8baec904e5c1ba76e130c5181bc2d6c4f1ceea4663287ba9ba; assert_eq(hash, test_data_empty_hash); } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr index 50a0b517681..e3331c59c96 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr @@ -1,6 +1,6 @@ use crate::{ abis::{ - call_context::CallContext, max_block_number::MaxBlockNumber, + call_context::CallContext, max_block_number::MaxBlockNumber, gas_settings::GasSettings, nullifier_key_validation_request::NullifierKeyValidationRequest, read_request::ReadRequest, side_effect::{SideEffect, SideEffectLinkedToNoteHash} }, @@ -9,11 +9,12 @@ use crate::{ MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL, MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL, MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, - PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH, - GENERATOR_INDEX__PRIVATE_CIRCUIT_PUBLIC_INPUTS, MAX_ENCRYPTED_LOGS_PER_CALL, MAX_UNENCRYPTED_LOGS_PER_CALL + PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH, GENERATOR_INDEX__PRIVATE_CIRCUIT_PUBLIC_INPUTS, + MAX_ENCRYPTED_LOGS_PER_CALL, MAX_UNENCRYPTED_LOGS_PER_CALL }, header::Header, hash::pedersen_hash, messaging::l2_to_l1_message::L2ToL1Message, - traits::{Deserialize, Hash, Serialize, Empty}, utils::reader::Reader + traits::{Deserialize, Hash, Serialize, Empty}, utils::reader::Reader, + transaction::tx_context::TxContext }; struct PrivateCircuitPublicInputs { @@ -49,11 +50,10 @@ struct PrivateCircuitPublicInputs { // Header of a block whose state is used during private execution (not the block the transaction is included in). historical_header: Header, - // Note: The following 2 values are not redundant to the values in self.historical_header.global_variables because + // Note: The chain_id and version here are not redundant to the values in self.historical_header.global_variables because // they can be different in case of a protocol upgrade. In such a situation we could be using header from a block // before the upgrade took place but be using the updated protocol to execute and prove the transaction. - chain_id: Field, - version: Field, + tx_context: TxContext, } impl Eq for PrivateCircuitPublicInputs { @@ -77,8 +77,7 @@ impl Eq for PrivateCircuitPublicInputs { (self.encrypted_log_preimages_length == other.encrypted_log_preimages_length) & (self.unencrypted_log_preimages_length == other.unencrypted_log_preimages_length) & self.historical_header.eq(other.historical_header) & - self.chain_id.eq(other.chain_id) & - self.version.eq(other.version) + self.tx_context.eq(other.tx_context) } } @@ -124,8 +123,7 @@ impl Serialize for PrivateCircuitPublicInp fields.push(self.encrypted_log_preimages_length); fields.push(self.unencrypted_log_preimages_length); fields.extend_from_array(self.historical_header.serialize()); - fields.push(self.chain_id); - fields.push(self.version); + fields.extend_from_array(self.tx_context.serialize()); assert_eq(fields.len(), PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH); @@ -158,8 +156,7 @@ impl Deserialize for PrivateCircuitPublicI encrypted_log_preimages_length: reader.read(), unencrypted_log_preimages_length: reader.read(), historical_header: reader.read_struct(Header::deserialize), - chain_id: reader.read(), - version: reader.read(), + tx_context: reader.read_struct(TxContext::deserialize), }; reader.finish(); @@ -173,7 +170,6 @@ impl Hash for PrivateCircuitPublicInputs { } } - impl Empty for PrivateCircuitPublicInputs { fn empty() -> Self { PrivateCircuitPublicInputs { @@ -197,8 +193,7 @@ impl Empty for PrivateCircuitPublicInputs { encrypted_log_preimages_length: 0, unencrypted_log_preimages_length: 0, historical_header: Header::empty(), - chain_id: 0, - version: 0, + tx_context: TxContext::empty(), } } } @@ -215,7 +210,7 @@ fn serialization_of_empty() { fn empty_hash() { let inputs = PrivateCircuitPublicInputs::empty(); let hash = inputs.hash(); - // Value from private_circuit_public_inputs.test.ts "computes empty inputs hash" test - let test_data_empty_hash = 0x265dcde577695a65f00acc24d861e65e9486526ec2b9f9bab9493476f73e4bc9; + // Value from private_circuit_public_inputs.test.ts "computes empty item hash" test + let test_data_empty_hash = 0x0a61fd8a00a3d160e723b316437484bf643f8ed7952031e493717e1f0f1f9345; assert_eq(hash, test_data_empty_hash); } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_stack_item.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_stack_item.nr index ea5f4637f06..2ef46661fb1 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_stack_item.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_stack_item.nr @@ -69,7 +69,7 @@ mod tests { let call_stack_item = PublicCallStackItem { contract_address, public_inputs, is_execution_request: true, function_data }; // Value from public_call_stack_item.test.ts "Computes a callstack item request hash" test - let test_data_call_stack_item_request_hash = 0x23066ad690c088120f8397cfeb2ef5608d4517342c7ff9fcb713009933ef1c61; + let test_data_call_stack_item_request_hash = 0x18e440e4e58ed510c02062986f71ef37ed610fc300b8baab334fd543758b9f11; assert_eq(call_stack_item.hash(), test_data_call_stack_item_request_hash); } @@ -87,7 +87,7 @@ mod tests { let call_stack_item = PublicCallStackItem { contract_address, public_inputs, is_execution_request: false, function_data }; // Value from public_call_stack_item.test.ts "Computes a callstack item hash" test - let test_data_call_stack_item_hash = 0x1ef9292cf3383605672c06dd50a12c251aa1f037cd826c0fc70d8ee5324e88c4; + let test_data_call_stack_item_hash = 0x2bf24099a6954a9bb9be6689fd765366fbb94fb25328d7e3942698ae891bbfad; assert_eq(call_stack_item.hash(), test_data_call_stack_item_hash); } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_circuit_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_circuit_public_inputs.nr index f4b2c4d3a2e..af908e1f3c5 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_circuit_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_circuit_public_inputs.nr @@ -8,9 +8,8 @@ use crate::{ MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL, MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_DATA_READS_PER_CALL, - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, - GENERATOR_INDEX__PUBLIC_CIRCUIT_PUBLIC_INPUTS, PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH, - MAX_UNENCRYPTED_LOGS_PER_CALL + MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, GENERATOR_INDEX__PUBLIC_CIRCUIT_PUBLIC_INPUTS, + PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH, MAX_UNENCRYPTED_LOGS_PER_CALL }, contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest}, hash::pedersen_hash, header::Header, messaging::l2_to_l1_message::L2ToL1Message, @@ -51,8 +50,9 @@ struct PublicCircuitPublicInputs { revert_code: u8, - // gas left after execution is completed - gas_left: Gas, + start_gas_left: Gas, + end_gas_left: Gas, + transaction_fee: Field, } impl Eq for PublicCircuitPublicInputs { @@ -101,7 +101,9 @@ impl Serialize for PublicCircuitPublicInput fields.extend_from_array(self.historical_header.serialize()); fields.push(self.prover_address.to_field()); fields.push(self.revert_code as Field); - fields.extend_from_array(self.gas_left.serialize()); + fields.extend_from_array(self.start_gas_left.serialize()); + fields.extend_from_array(self.end_gas_left.serialize()); + fields.push(self.transaction_fee); fields.storage } } @@ -129,7 +131,9 @@ impl Deserialize for PublicCircuitPublicInp historical_header: reader.read_struct(Header::deserialize), prover_address: reader.read_struct(AztecAddress::deserialize), revert_code: reader.read() as u8, - gas_left: reader.read_struct(Gas::deserialize), + start_gas_left: reader.read_struct(Gas::deserialize), + end_gas_left: reader.read_struct(Gas::deserialize), + transaction_fee: reader.read(), }; reader.finish(); @@ -164,7 +168,9 @@ impl Empty for PublicCircuitPublicInputs { historical_header: Header::empty(), prover_address: AztecAddress::zero(), revert_code: 0 as u8, - gas_left: Gas::empty(), + start_gas_left: Gas::empty(), + end_gas_left: Gas::empty(), + transaction_fee: 0, } } } @@ -182,7 +188,7 @@ fn empty_hash() { let inputs = PublicCircuitPublicInputs::empty(); let hash = inputs.hash(); - // Value from public_circuit_public_inputs.test.ts "computes empty inputs hash" test - let test_data_empty_hash = 0x048912d56248af479f8d7ecedbba7092d27741b10075a989e040f8e3242a7a3f; + // Value from public_circuit_public_inputs.test.ts "computes empty item hash" test + let test_data_empty_hash = 0x19eaa0a5aea3d131456d0daffc2d79fd27db9c201e91475ab620801b78504d79; assert_eq(hash, test_data_empty_hash); } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr index a089d51d2d3..7004102819e 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr @@ -128,13 +128,18 @@ global REGISTERER_UNCONSTRAINED_FUNCTION_BROADCASTED_MAGIC_VALUE = 0xe7af8166354 global DEPLOYER_CONTRACT_INSTANCE_DEPLOYED_MAGIC_VALUE = 0x85864497636cf755ae7bde03f267ce01a520981c21c3682aaf82a631; global DEPLOYER_CONTRACT_ADDRESS = 0x1f47133752dfcd9604f2d89c631797a84ed207c1c51d08533226dafcc8bd8548; +// GAS DEFAULTS +global DEFAULT_GAS_LIMIT: u32 = 1_000_000_000; +global DEFAULT_TEARDOWN_GAS_LIMIT: u32 = 100_000_000; +global DEFAULT_MAX_FEE_PER_GAS: Field = 10; +global DEFAULT_INCLUSION_FEE: Field = 0; + // LENGTH OF STRUCTS SERIALIZED TO FIELDS global AZTEC_ADDRESS_LENGTH = 1; -global DIMENSION_GAS_SETTINGS_LENGTH: u64 = 3; global GAS_FEES_LENGTH: u64 = 3; global GAS_LENGTH: u64 = 3; -global GAS_SETTINGS_LENGTH: u64 = 1 + 3 * DIMENSION_GAS_SETTINGS_LENGTH; -global CALL_CONTEXT_LENGTH: u64 = 8 + GAS_SETTINGS_LENGTH + GAS_LENGTH; +global GAS_SETTINGS_LENGTH: u64 = GAS_LENGTH * 2 + GAS_FEES_LENGTH + /* inclusion_fee */ 1; +global CALL_CONTEXT_LENGTH: u64 = 7; global CONTENT_COMMITMENT_LENGTH: u64 = 4; global CONTRACT_INSTANCE_LENGTH: u64 = 6; global CONTRACT_STORAGE_READ_LENGTH: u64 = 2; @@ -154,11 +159,11 @@ global READ_REQUEST_LENGTH = 2; global SIDE_EFFECT_LENGTH = 2; global SIDE_EFFECT_LINKED_TO_NOTE_HASH_LENGTH = 3; global STATE_REFERENCE_LENGTH: u64 = APPEND_ONLY_TREE_SNAPSHOT_LENGTH + PARTIAL_STATE_REFERENCE_LENGTH; -global TX_CONTEXT_DATA_LENGTH: u64 = 4; -global TX_REQUEST_LENGTH: u64 = 2 + TX_CONTEXT_DATA_LENGTH + FUNCTION_DATA_LENGTH + GAS_SETTINGS_LENGTH; +global TX_CONTEXT_LENGTH: u64 = 2 + GAS_SETTINGS_LENGTH; +global TX_REQUEST_LENGTH: u64 = 2 + TX_CONTEXT_LENGTH + FUNCTION_DATA_LENGTH; global HEADER_LENGTH: u64 = APPEND_ONLY_TREE_SNAPSHOT_LENGTH + CONTENT_COMMITMENT_LENGTH + STATE_REFERENCE_LENGTH + GLOBAL_VARIABLES_LENGTH; -global PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH: u64 = CALL_CONTEXT_LENGTH + 3 + MAX_BLOCK_NUMBER_LENGTH + (SIDE_EFFECT_LENGTH * MAX_NOTE_HASH_READ_REQUESTS_PER_CALL) + (READ_REQUEST_LENGTH * MAX_NULLIFIER_READ_REQUESTS_PER_CALL) + (NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH * MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL) + (SIDE_EFFECT_LENGTH * MAX_NEW_NOTE_HASHES_PER_CALL) + (SIDE_EFFECT_LINKED_TO_NOTE_HASH_LENGTH * MAX_NEW_NULLIFIERS_PER_CALL) + MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL + (L2_TO_L1_MESSAGE_LENGTH * MAX_NEW_L2_TO_L1_MSGS_PER_CALL) + 2 + (SIDE_EFFECT_LENGTH * MAX_ENCRYPTED_LOGS_PER_CALL) + (SIDE_EFFECT_LENGTH * MAX_UNENCRYPTED_LOGS_PER_CALL) + 2 + HEADER_LENGTH + 2; -global PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH: u64 = CALL_CONTEXT_LENGTH + 2 + (READ_REQUEST_LENGTH * MAX_NULLIFIER_READ_REQUESTS_PER_CALL) + (READ_REQUEST_LENGTH * MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL) + (CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH * MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL) + (CONTRACT_STORAGE_READ_LENGTH * MAX_PUBLIC_DATA_READS_PER_CALL) + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL + (SIDE_EFFECT_LENGTH * MAX_NEW_NOTE_HASHES_PER_CALL) + (SIDE_EFFECT_LINKED_TO_NOTE_HASH_LENGTH * MAX_NEW_NULLIFIERS_PER_CALL) + (L2_TO_L1_MESSAGE_LENGTH * MAX_NEW_L2_TO_L1_MSGS_PER_CALL) + 2 + (SIDE_EFFECT_LENGTH * MAX_UNENCRYPTED_LOGS_PER_CALL) + 1 + HEADER_LENGTH + AZTEC_ADDRESS_LENGTH + /* revert_code */ 1 + GAS_LENGTH; +global PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH: u64 = CALL_CONTEXT_LENGTH + 3 + MAX_BLOCK_NUMBER_LENGTH + (SIDE_EFFECT_LENGTH * MAX_NOTE_HASH_READ_REQUESTS_PER_CALL) + (READ_REQUEST_LENGTH * MAX_NULLIFIER_READ_REQUESTS_PER_CALL) + (NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH * MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL) + (SIDE_EFFECT_LENGTH * MAX_NEW_NOTE_HASHES_PER_CALL) + (SIDE_EFFECT_LINKED_TO_NOTE_HASH_LENGTH * MAX_NEW_NULLIFIERS_PER_CALL) + MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL + (L2_TO_L1_MESSAGE_LENGTH * MAX_NEW_L2_TO_L1_MSGS_PER_CALL) + 2 + (SIDE_EFFECT_LENGTH * MAX_ENCRYPTED_LOGS_PER_CALL) + (SIDE_EFFECT_LENGTH * MAX_UNENCRYPTED_LOGS_PER_CALL) + 2 + HEADER_LENGTH + TX_CONTEXT_LENGTH; +global PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH: u64 = CALL_CONTEXT_LENGTH + 2 + (READ_REQUEST_LENGTH * MAX_NULLIFIER_READ_REQUESTS_PER_CALL) + (READ_REQUEST_LENGTH * MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL) + (CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH * MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL) + (CONTRACT_STORAGE_READ_LENGTH * MAX_PUBLIC_DATA_READS_PER_CALL) + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL + (SIDE_EFFECT_LENGTH * MAX_NEW_NOTE_HASHES_PER_CALL) + (SIDE_EFFECT_LINKED_TO_NOTE_HASH_LENGTH * MAX_NEW_NULLIFIERS_PER_CALL) + (L2_TO_L1_MESSAGE_LENGTH * MAX_NEW_L2_TO_L1_MSGS_PER_CALL) + 2 + (SIDE_EFFECT_LENGTH * MAX_UNENCRYPTED_LOGS_PER_CALL) + 1 + HEADER_LENGTH + AZTEC_ADDRESS_LENGTH + /* revert_code */ 1 + 2 * GAS_LENGTH + /* transaction_fee */ 1; global PRIVATE_CALL_STACK_ITEM_LENGTH: u64 = AZTEC_ADDRESS_LENGTH + FUNCTION_DATA_LENGTH + PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH; global ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH: u64 = 2 + FUNCTION_DATA_LENGTH + CALL_CONTEXT_LENGTH; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests.nr index 0defe42f5bd..4b5d7263f39 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests.nr @@ -1,4 +1,3 @@ -mod testing_harness; mod fixture_builder; mod fixtures; mod merkle_tree_utils; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr index d0e54861371..8a402fae806 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr @@ -35,7 +35,6 @@ struct FixtureBuilder { // Constant data. historical_header: Header, tx_context: TxContext, - gas_settings: GasSettings, // Accumulated data. new_note_hashes: BoundedVec, @@ -77,7 +76,7 @@ struct FixtureBuilder { impl FixtureBuilder { pub fn new() -> Self { - let tx_context = TxContext { is_fee_payment_tx: false, is_rebate_payment_tx: false, chain_id: 1, version: 0 }; + let tx_context = TxContext { chain_id: 1, version: 0, gas_settings: GasSettings::empty() }; FixtureBuilder { contract_address: fixtures::contracts::parent_contract.address, @@ -110,17 +109,12 @@ impl FixtureBuilder { min_revertible_side_effect_counter: 0, counter: 0, start_state: PartialStateReference::empty(), - gas_used: Gas::empty(), - gas_settings: GasSettings::empty() + gas_used: Gas::empty() } } pub fn to_constant_data(self) -> CombinedConstantData { - CombinedConstantData { - historical_header: self.historical_header, - tx_context: self.tx_context, - gas_settings: self.gas_settings - } + CombinedConstantData { historical_header: self.historical_header, tx_context: self.tx_context } } pub fn to_private_accumulated_data(self) -> PrivateAccumulatedData { @@ -456,7 +450,6 @@ impl Empty for FixtureBuilder { min_revertible_side_effect_counter: 0, counter: 0, start_state: PartialStateReference::empty(), - gas_settings: GasSettings::empty(), gas_used: Gas::empty(), } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/private_call_data_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/private_call_data_builder.nr index bceb7f0fbba..47338325790 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/private_call_data_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/private_call_data_builder.nr @@ -5,15 +5,12 @@ use crate::{ max_block_number::MaxBlockNumber, membership_witness::{FunctionLeafMembershipWitness, NoteHashReadRequestMembershipWitness}, private_circuit_public_inputs::{PrivateCircuitPublicInputs}, - private_kernel::private_call_data::PrivateCallData, side_effect::SideEffect, + private_kernel::private_call_data::PrivateCallData, side_effect::SideEffect }, address::{AztecAddress, EthAddress, SaltedInitializationHash, PublicKeysHash}, mocked::{Proof, VerificationKey}, - tests::{ - fixtures, private_circuit_public_inputs_builder::PrivateCircuitPublicInputsBuilder, - testing_harness::build_tx_context -}, - transaction::{tx_request::TxRequest} + tests::{fixtures, private_circuit_public_inputs_builder::PrivateCircuitPublicInputsBuilder}, + transaction::{tx_request::TxRequest, tx_context::TxContext} }; use crate::constants::{ MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, @@ -67,7 +64,7 @@ impl PrivateCallDataBuilder { note_hash_read_request_membership_witnesses: BoundedVec::new(), portal_contract_address: public_inputs.call_context.portal_contract_address, acir_hash: contract_function.acir_hash, - gas_settings: public_inputs.call_context.gas_settings + gas_settings: public_inputs.gas_settings } } @@ -85,16 +82,19 @@ impl PrivateCallDataBuilder { } pub fn build_tx_request(self) -> TxRequest { - let tx_context = build_tx_context(); + let tx_context = self.build_tx_context(); TxRequest { origin: self.contract_address, args_hash: self.public_inputs.args_hash, tx_context, - function_data: self.function_data, - gas_settings: self.gas_settings + function_data: self.function_data } } + pub fn build_tx_context(self) -> TxContext { + TxContext { chain_id: 1, version: 0, gas_settings: self.gas_settings } + } + pub fn append_private_call_requests(&mut self, num_requests: u64, is_delegate_call: bool) { let (hashes, call_requests) = self.generate_call_requests(self.private_call_stack, num_requests, is_delegate_call); self.public_inputs.private_call_stack_hashes.extend_from_bounded_vec(hashes); diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/private_circuit_public_inputs_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/private_circuit_public_inputs_builder.nr index e72d8ee686e..61c14a8a5fb 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/private_circuit_public_inputs_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/private_circuit_public_inputs_builder.nr @@ -1,21 +1,21 @@ use crate::{ abis::{ - call_context::CallContext, gas_settings::{GasSettings, DimensionGasSettings}, gas::Gas, - max_block_number::MaxBlockNumber, nullifier_key_validation_request::NullifierKeyValidationRequest, + call_context::CallContext, gas_settings::GasSettings, gas::Gas, max_block_number::MaxBlockNumber, + nullifier_key_validation_request::NullifierKeyValidationRequest, private_circuit_public_inputs::PrivateCircuitPublicInputs, read_request::ReadRequest, side_effect::{SideEffect, SideEffectLinkedToNoteHash} }, address::{AztecAddress, compute_initialization_hash}, header::Header, - messaging::l2_to_l1_message::L2ToL1Message, tests::fixtures + messaging::l2_to_l1_message::L2ToL1Message, tests::fixtures, transaction::tx_context::TxContext }; use crate::{ constants::{ MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL, MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL, MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, - MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, - MAX_ENCRYPTED_LOGS_PER_CALL, MAX_UNENCRYPTED_LOGS_PER_CALL - }, + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_ENCRYPTED_LOGS_PER_CALL, + MAX_UNENCRYPTED_LOGS_PER_CALL +}, traits::Empty }; @@ -50,6 +50,8 @@ struct PrivateCircuitPublicInputsBuilder { chain_id: Field, version: Field, + + gas_settings: GasSettings, } impl PrivateCircuitPublicInputsBuilder { @@ -73,16 +75,14 @@ impl PrivateCircuitPublicInputsBuilder { function_selector: function_data.selector, is_delegate_call: false, is_static_call: false, - side_effect_counter: 0, - gas_left: Gas::empty(), - gas_settings: GasSettings::empty(), - transaction_fee: 0 + side_effect_counter: 0 }; public_inputs.call_context = call_context; public_inputs.args_hash = args_hash; public_inputs.historical_header = fixtures::HEADER; public_inputs.chain_id = 0; public_inputs.version = 1; + public_inputs.gas_settings = GasSettings::default(); public_inputs } @@ -109,8 +109,7 @@ impl PrivateCircuitPublicInputsBuilder { encrypted_log_preimages_length: self.encrypted_log_preimages_length, unencrypted_log_preimages_length: self.unencrypted_log_preimages_length, historical_header: self.historical_header, - chain_id: self.chain_id, - version: self.version + tx_context: TxContext::new(self.chain_id, self.version, self.gas_settings) } } } @@ -138,6 +137,7 @@ impl Empty for PrivateCircuitPublicInputsBuilder { historical_header: Header::empty(), chain_id: 0, version: 0, + gas_settings: GasSettings::empty() } } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/public_call_data_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/public_call_data_builder.nr index 262a2dd4c54..6c875c049e3 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/public_call_data_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/public_call_data_builder.nr @@ -44,9 +44,6 @@ impl PublicCallDataBuilder { is_delegate_call: false, is_static_call: false, side_effect_counter: 0, // needed? - gas_settings: GasSettings::empty(), - transaction_fee: 0, - gas_left: Gas::empty(), }; PublicCallDataBuilder { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/public_circuit_public_inputs_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/public_circuit_public_inputs_builder.nr index 6556b96d8ac..f6d712bb814 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/public_circuit_public_inputs_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/public_circuit_public_inputs_builder.nr @@ -36,7 +36,9 @@ struct PublicCircuitPublicInputsBuilder { historical_header: Header, prover_address: AztecAddress, revert_code: u8, - gas_left: Gas, + start_gas_left: Gas, + end_gas_left: Gas, + transaction_fee: Field, } impl PublicCircuitPublicInputsBuilder { @@ -67,7 +69,9 @@ impl PublicCircuitPublicInputsBuilder { historical_header: self.historical_header, prover_address: self.prover_address, revert_code: self.revert_code, - gas_left: self.gas_left + start_gas_left: self.start_gas_left, + end_gas_left: self.end_gas_left, + transaction_fee: self.transaction_fee } } } @@ -93,7 +97,9 @@ impl Empty for PublicCircuitPublicInputsBuilder { historical_header: Header::empty(), prover_address: AztecAddress::zero(), revert_code: 0 as u8, - gas_left: Gas::empty(), + start_gas_left: Gas::empty(), + end_gas_left: Gas::empty(), + transaction_fee: 0 } } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/testing_harness.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/testing_harness.nr deleted file mode 100644 index 9f03462c7d9..00000000000 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/testing_harness.nr +++ /dev/null @@ -1,5 +0,0 @@ -use crate::{tests::fixtures, transaction::tx_context::TxContext, address::compute_initialization_hash}; - -pub fn build_tx_context() -> TxContext { - TxContext { is_fee_payment_tx: false, is_rebate_payment_tx: false, chain_id: 1, version: 0 } -} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/transaction/tx_context.nr b/noir-projects/noir-protocol-circuits/crates/types/src/transaction/tx_context.nr index 69cc22add13..d90eb2a6ee7 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/transaction/tx_context.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/transaction/tx_context.nr @@ -1,61 +1,64 @@ use crate::{ - constants::{GENERATOR_INDEX__TX_CONTEXT, TX_CONTEXT_DATA_LENGTH}, hash::pedersen_hash, - traits::{Deserialize, Hash, Serialize, Empty}, utils::reader::Reader + constants::{GENERATOR_INDEX__TX_CONTEXT, TX_CONTEXT_LENGTH}, hash::pedersen_hash, + traits::{Deserialize, Hash, Serialize, Empty}, utils::reader::Reader, + abis::gas_settings::GasSettings }; +// docs:start:tx-context struct TxContext { - is_fee_payment_tx : bool, - is_rebate_payment_tx : bool, - chain_id : Field, version : Field, + gas_settings: GasSettings, +} +// docs:end:tx-context + +impl TxContext { + pub fn new(chain_id: Field, version: Field, gas_settings: GasSettings) -> Self { + TxContext { chain_id, version, gas_settings } + } } impl Eq for TxContext { fn eq(self, other: Self) -> bool { - (self.is_fee_payment_tx == other.is_fee_payment_tx) & - (self.is_rebate_payment_tx == other.is_rebate_payment_tx) & (self.chain_id == other.chain_id) & - (self.version == other.version) + (self.version == other.version) & + (self.gas_settings.eq(other.gas_settings)) } } impl Empty for TxContext { fn empty() -> Self { TxContext { - is_fee_payment_tx : false, - is_rebate_payment_tx : false, - chain_id : 0, - version : 0, + chain_id: 0, + version: 0, + gas_settings: GasSettings::empty(), } } } -impl Serialize for TxContext { - fn serialize(self) -> [Field; TX_CONTEXT_DATA_LENGTH] { - let mut fields: BoundedVec = BoundedVec::new(); +impl Serialize for TxContext { + fn serialize(self) -> [Field; TX_CONTEXT_LENGTH] { + let mut fields: BoundedVec = BoundedVec::new(); - fields.push(self.is_fee_payment_tx as Field); - fields.push(self.is_rebate_payment_tx as Field); fields.push(self.chain_id); fields.push(self.version); + fields.extend_from_array(self.gas_settings.serialize()); - assert_eq(fields.len(), TX_CONTEXT_DATA_LENGTH); + assert_eq(fields.len(), TX_CONTEXT_LENGTH); fields.storage } } -impl Deserialize for TxContext { - fn deserialize(serialized: [Field; TX_CONTEXT_DATA_LENGTH]) -> Self { +impl Deserialize for TxContext { + fn deserialize(serialized: [Field; TX_CONTEXT_LENGTH]) -> Self { // TODO(#4390): This should accept a reader ^ to avoid copying data. let mut reader = Reader::new(serialized); let context = Self { - is_fee_payment_tx: reader.read() as bool, - is_rebate_payment_tx: reader.read() as bool, chain_id: reader.read(), version: reader.read(), + gas_settings: reader.read_struct(GasSettings::deserialize), }; reader.finish(); @@ -82,7 +85,7 @@ fn empty_hash() { let context = TxContext::empty(); let hash = context.hash(); - // Value from tx_context.test.ts "computes empty context hash" test - let test_data_empty_hash = 0x200569267c0f73ac89aaa414239398db9445dd4ad3a8cf37015cd55b8d4c5e8d; + // Value from tx_context.test.ts "computes empty item hash" test + let test_data_empty_hash = 0x1acd086cc3b911cd49713c263bf4af6032a567fa1e79fe7ef77c063565d3ead3; assert_eq(hash, test_data_empty_hash); } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/transaction/tx_request.nr b/noir-projects/noir-protocol-circuits/crates/types/src/transaction/tx_request.nr index 59b1299d7e0..2ca9a759d13 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/transaction/tx_request.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/transaction/tx_request.nr @@ -10,7 +10,6 @@ struct TxRequest { args_hash: Field, tx_context: TxContext, function_data: FunctionData, - gas_settings: GasSettings, } impl Empty for TxRequest { @@ -20,7 +19,6 @@ impl Empty for TxRequest { args_hash: 0, tx_context: TxContext::empty(), function_data: FunctionData::empty(), - gas_settings: GasSettings::empty(), } } } @@ -30,8 +28,7 @@ impl Eq for TxRequest { (self.origin == other.origin) & (self.args_hash == other.args_hash) & (self.tx_context == other.tx_context) & - (self.function_data == other.function_data) & - (self.gas_settings == other.gas_settings) + (self.function_data == other.function_data) } } @@ -50,7 +47,6 @@ impl Serialize for TxRequest { fields.extend_from_array(self.function_data.serialize()); fields.push(self.args_hash); fields.extend_from_array(self.tx_context.serialize()); - fields.extend_from_array(self.gas_settings.serialize()); assert_eq(fields.len(), TX_REQUEST_LENGTH); @@ -67,7 +63,6 @@ impl Deserialize for TxRequest { args_hash: reader.read(), tx_context: reader.read_struct(TxContext::deserialize), function_data: reader.read_struct(FunctionData::deserialize), - gas_settings: reader.read_struct(GasSettings::deserialize), }; reader.finish(); @@ -78,8 +73,8 @@ impl Deserialize for TxRequest { mod tests { use crate::{ abis::{ - function_selector::FunctionSelector, function_data::FunctionData, - gas_settings::{GasSettings, DimensionGasSettings} + function_selector::FunctionSelector, function_data::FunctionData, gas_settings::GasSettings, + gas::Gas, gas_fees::GasFees }, address::{AztecAddress, EthAddress}, contract_class_id::ContractClassId, grumpkin_point::GrumpkinPoint, transaction::{tx_request::TxRequest, tx_context::TxContext} @@ -95,20 +90,15 @@ mod tests { #[test] fn compute_hash() { + let gas_settings = GasSettings::new(Gas::new(2, 2, 2), Gas::new(1, 1, 1), GasFees::new(3, 3, 3), 10); let tx_request = TxRequest { origin: AztecAddress::from_field(1), args_hash: 3, - tx_context: TxContext { is_fee_payment_tx: false, is_rebate_payment_tx: false, chain_id: 0, version: 0 }, - function_data: FunctionData { selector: FunctionSelector::from_u32(2), is_private: true }, - gas_settings: GasSettings { - da: DimensionGasSettings { gas_limit: 2, teardown_gas_limit: 1, max_fee_per_gas: 3 }, - l1: DimensionGasSettings { gas_limit: 2, teardown_gas_limit: 1, max_fee_per_gas: 3 }, - l2: DimensionGasSettings { gas_limit: 2, teardown_gas_limit: 1, max_fee_per_gas: 3 }, - inclusion_fee: 10 - } + tx_context: TxContext { chain_id: 0, version: 0, gas_settings }, + function_data: FunctionData { selector: FunctionSelector::from_u32(2), is_private: true } }; // Value from tx_request.test.ts "compute hash" test - let test_data_tx_request_hash = 0x03b678e327818eb368f9eac21839ee67a98968318f0dcd76c89d3fcf66af7257; + let test_data_tx_request_hash = 0x00b8affaf5ca65d647756e359ce0b2c5fa5c2c03f219189e28db323f22975706; assert(tx_request.hash() == test_data_tx_request_hash); } } diff --git a/yarn-project/aztec.js/src/contract/contract_function_interaction.ts b/yarn-project/aztec.js/src/contract/contract_function_interaction.ts index f0c2a9e3578..06a8e67abc9 100644 --- a/yarn-project/aztec.js/src/contract/contract_function_interaction.ts +++ b/yarn-project/aztec.js/src/contract/contract_function_interaction.ts @@ -88,15 +88,15 @@ export class ContractFunctionInteraction extends BaseContractInteraction { if (this.functionDao.functionType == FunctionType.SECRET) { const nodeInfo = await this.wallet.getNodeInfo(); const packedArgs = PackedValues.fromValues(encodeArguments(this.functionDao, this.args)); + const gasSettings = options.gasSettings ?? GasSettings.simulation(); const txRequest = TxExecutionRequest.from({ argsHash: packedArgs.hash, origin: this.contractAddress, functionData: FunctionData.fromAbi(this.functionDao), - txContext: TxContext.empty(nodeInfo.chainId, nodeInfo.protocolVersion), + txContext: new TxContext(nodeInfo.chainId, nodeInfo.protocolVersion, gasSettings), packedArguments: [packedArgs], authWitnesses: [], - gasSettings: options.gasSettings ?? GasSettings.simulation(), }); const simulatedTx = await this.pxe.simulateTx(txRequest, true, options.from ?? this.wallet.getAddress()); const flattened = simulatedTx.privateReturnValues; diff --git a/yarn-project/aztec.js/src/entrypoint/default_entrypoint.ts b/yarn-project/aztec.js/src/entrypoint/default_entrypoint.ts index 1596a1c6c02..9728d610c59 100644 --- a/yarn-project/aztec.js/src/entrypoint/default_entrypoint.ts +++ b/yarn-project/aztec.js/src/entrypoint/default_entrypoint.ts @@ -18,7 +18,8 @@ export class DefaultEntrypoint implements EntrypointInterface { const call = calls[0]; const entrypointPackedValues = PackedValues.fromValues(call.args); - const txContext = TxContext.empty(this.chainId, this.protocolVersion); + const gasSettings = exec.fee?.gasSettings ?? GasSettings.default(); + const txContext = new TxContext(this.chainId, this.protocolVersion, gasSettings); return Promise.resolve( new TxExecutionRequest( call.to, @@ -27,7 +28,6 @@ export class DefaultEntrypoint implements EntrypointInterface { txContext, [...packedArguments, entrypointPackedValues], authWitnesses, - exec.fee?.gasSettings ?? GasSettings.default(), ), ); } diff --git a/yarn-project/aztec.js/src/entrypoint/default_multi_call_entrypoint.ts b/yarn-project/aztec.js/src/entrypoint/default_multi_call_entrypoint.ts index 968960c4671..389f2d43237 100644 --- a/yarn-project/aztec.js/src/entrypoint/default_multi_call_entrypoint.ts +++ b/yarn-project/aztec.js/src/entrypoint/default_multi_call_entrypoint.ts @@ -19,15 +19,15 @@ export class DefaultMultiCallEntrypoint implements EntrypointInterface { const payload = EntrypointPayload.fromAppExecution(calls); const abi = this.getEntrypointAbi(); const entrypointPackedArgs = PackedValues.fromValues(encodeArguments(abi, [payload])); + const gasSettings = executions.fee?.gasSettings ?? GasSettings.default(); const txRequest = TxExecutionRequest.from({ argsHash: entrypointPackedArgs.hash, origin: this.address, functionData: FunctionData.fromAbi(abi), - txContext: TxContext.empty(this.chainId, this.version), + txContext: new TxContext(this.chainId, this.version, gasSettings), packedArguments: [...payload.packedArguments, ...packedArguments, entrypointPackedArgs], authWitnesses, - gasSettings: executions.fee?.gasSettings ?? GasSettings.default(), }); return Promise.resolve(txRequest); diff --git a/yarn-project/circuit-types/src/mocks.ts b/yarn-project/circuit-types/src/mocks.ts index 3c613163756..7f0442ffd3e 100644 --- a/yarn-project/circuit-types/src/mocks.ts +++ b/yarn-project/circuit-types/src/mocks.ts @@ -62,7 +62,7 @@ export const mockTx = ( const firstNullifier = new SideEffectLinkedToNoteHash(new Fr(seed + 1), new Fr(seed + 2), Fr.ZERO); const encryptedLogs = hasLogs ? EncryptedTxL2Logs.random(2, 3) : EncryptedTxL2Logs.empty(); // 2 priv function invocations creating 3 encrypted logs each const unencryptedLogs = hasLogs ? UnencryptedTxL2Logs.random(2, 1) : UnencryptedTxL2Logs.empty(); // 2 priv function invocations creating 1 unencrypted log each - data.constants.gasSettings = GasSettings.default(); + data.constants.txContext.gasSettings = GasSettings.default(); if (isForPublic) { data.forRollup = undefined; diff --git a/yarn-project/circuit-types/src/tx_execution_request.ts b/yarn-project/circuit-types/src/tx_execution_request.ts index 9169dfe0cee..eba0eda27d8 100644 --- a/yarn-project/circuit-types/src/tx_execution_request.ts +++ b/yarn-project/circuit-types/src/tx_execution_request.ts @@ -1,4 +1,4 @@ -import { AztecAddress, Fr, FunctionData, GasSettings, TxContext, TxRequest, Vector } from '@aztec/circuits.js'; +import { AztecAddress, Fr, FunctionData, TxContext, TxRequest, Vector } from '@aztec/circuits.js'; import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; import { type FieldsOf } from '@aztec/foundation/types'; @@ -38,13 +38,10 @@ export class TxExecutionRequest { * These witnesses are not expected to be stored in the local witnesses database of the PXE. */ public authWitnesses: AuthWitness[], - - /** Gas choices for this transaction. */ - public gasSettings: GasSettings, ) {} toTxRequest(): TxRequest { - return new TxRequest(this.origin, this.functionData, this.argsHash, this.txContext, this.gasSettings); + return new TxRequest(this.origin, this.functionData, this.argsHash, this.txContext); } static getFields(fields: FieldsOf) { @@ -55,7 +52,6 @@ export class TxExecutionRequest { fields.txContext, fields.packedArguments, fields.authWitnesses, - fields.gasSettings, ] as const; } @@ -75,7 +71,6 @@ export class TxExecutionRequest { this.txContext, new Vector(this.packedArguments), new Vector(this.authWitnesses), - this.gasSettings, ); } @@ -101,7 +96,6 @@ export class TxExecutionRequest { reader.readObject(TxContext), reader.readVector(PackedValues), reader.readVector(AuthWitness), - reader.readObject(GasSettings), ); } diff --git a/yarn-project/circuits.js/src/constants.gen.ts b/yarn-project/circuits.js/src/constants.gen.ts index 754d6b5b5dc..c3b1341b83b 100644 --- a/yarn-project/circuits.js/src/constants.gen.ts +++ b/yarn-project/circuits.js/src/constants.gen.ts @@ -75,12 +75,15 @@ export const REGISTERER_UNCONSTRAINED_FUNCTION_BROADCASTED_MAGIC_VALUE = export const DEPLOYER_CONTRACT_INSTANCE_DEPLOYED_MAGIC_VALUE = 0x85864497636cf755ae7bde03f267ce01a520981c21c3682aaf82a631n; export const DEPLOYER_CONTRACT_ADDRESS = 0x1f47133752dfcd9604f2d89c631797a84ed207c1c51d08533226dafcc8bd8548n; +export const DEFAULT_GAS_LIMIT = 1_000_000_000; +export const DEFAULT_TEARDOWN_GAS_LIMIT = 100_000_000; +export const DEFAULT_MAX_FEE_PER_GAS = 10; +export const DEFAULT_INCLUSION_FEE = 0; export const AZTEC_ADDRESS_LENGTH = 1; -export const DIMENSION_GAS_SETTINGS_LENGTH = 3; export const GAS_FEES_LENGTH = 3; export const GAS_LENGTH = 3; -export const GAS_SETTINGS_LENGTH = 1 + 3 * DIMENSION_GAS_SETTINGS_LENGTH; -export const CALL_CONTEXT_LENGTH = 8 + GAS_SETTINGS_LENGTH + GAS_LENGTH; +export const GAS_SETTINGS_LENGTH = GAS_LENGTH * 2 + GAS_FEES_LENGTH + /* inclusion_fee */ 1; +export const CALL_CONTEXT_LENGTH = 7; export const CONTENT_COMMITMENT_LENGTH = 4; export const CONTRACT_INSTANCE_LENGTH = 6; export const CONTRACT_STORAGE_READ_LENGTH = 2; @@ -100,8 +103,8 @@ export const READ_REQUEST_LENGTH = 2; export const SIDE_EFFECT_LENGTH = 2; export const SIDE_EFFECT_LINKED_TO_NOTE_HASH_LENGTH = 3; export const STATE_REFERENCE_LENGTH = APPEND_ONLY_TREE_SNAPSHOT_LENGTH + PARTIAL_STATE_REFERENCE_LENGTH; -export const TX_CONTEXT_DATA_LENGTH = 4; -export const TX_REQUEST_LENGTH = 2 + TX_CONTEXT_DATA_LENGTH + FUNCTION_DATA_LENGTH + GAS_SETTINGS_LENGTH; +export const TX_CONTEXT_LENGTH = 2 + GAS_SETTINGS_LENGTH; +export const TX_REQUEST_LENGTH = 2 + TX_CONTEXT_LENGTH + FUNCTION_DATA_LENGTH; export const HEADER_LENGTH = APPEND_ONLY_TREE_SNAPSHOT_LENGTH + CONTENT_COMMITMENT_LENGTH + STATE_REFERENCE_LENGTH + GLOBAL_VARIABLES_LENGTH; export const PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH = @@ -121,7 +124,7 @@ export const PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH = SIDE_EFFECT_LENGTH * MAX_UNENCRYPTED_LOGS_PER_CALL + 2 + HEADER_LENGTH + - 2; + TX_CONTEXT_LENGTH; export const PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH = CALL_CONTEXT_LENGTH + 2 + @@ -139,7 +142,8 @@ export const PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH = HEADER_LENGTH + AZTEC_ADDRESS_LENGTH + /* revert_code */ 1 + - GAS_LENGTH; + 2 * GAS_LENGTH + + /* transaction_fee */ 1; export const PRIVATE_CALL_STACK_ITEM_LENGTH = AZTEC_ADDRESS_LENGTH + FUNCTION_DATA_LENGTH + PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH; export const ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH = 2 + FUNCTION_DATA_LENGTH + CALL_CONTEXT_LENGTH; diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/private_call_stack_item.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/private_call_stack_item.test.ts.snap index a66f2803864..7e5834b450f 100644 --- a/yarn-project/circuits.js/src/structs/__snapshots__/private_call_stack_item.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/__snapshots__/private_call_stack_item.test.ts.snap @@ -1,5 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`PrivateCallStackItem computes empty item hash 1`] = `Fr<0x2826eee20026ba6fb21916387c4dfa7843cbce1fdcff508132812be5e544f286>`; +exports[`PrivateCallStackItem computes empty item hash 1`] = `Fr<0x25d9c6ba3de2cf8baec904e5c1ba76e130c5181bc2d6c4f1ceea4663287ba9ba>`; -exports[`PrivateCallStackItem computes hash 1`] = `Fr<0x28222ff70df9ed6dbdc2d36cfb59599a9281dbe05d8ba6b50f168ad844db6fd9>`; +exports[`PrivateCallStackItem computes hash 1`] = `Fr<0x1b183e4ba97199f9b205f7748e363d628a8624156f95ebf306c5da1925a79ddc>`; diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/private_circuit_public_inputs.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/private_circuit_public_inputs.test.ts.snap index b3a2831c1dd..65fa6ed6f6c 100644 --- a/yarn-project/circuits.js/src/structs/__snapshots__/private_circuit_public_inputs.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/__snapshots__/private_circuit_public_inputs.test.ts.snap @@ -1,5 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`PrivateCircuitPublicInputs computes empty inputs hash 1`] = `Fr<0x265dcde577695a65f00acc24d861e65e9486526ec2b9f9bab9493476f73e4bc9>`; +exports[`PrivateCircuitPublicInputs computes empty inputs hash 1`] = `Fr<0x0a61fd8a00a3d160e723b316437484bf643f8ed7952031e493717e1f0f1f9345>`; -exports[`PrivateCircuitPublicInputs hash matches snapshot 1`] = `Fr<0x1c33182dc9780bb0b5b05314ba465dddf21ef16465e977f8093895541efe11f2>`; +exports[`PrivateCircuitPublicInputs hash matches snapshot 1`] = `Fr<0x16cda30b8402ab87d4892f801a91868ec9571748441c6e4abc796d17418bd1cc>`; diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/public_call_stack_item.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/public_call_stack_item.test.ts.snap index a6d3353003d..117139972e0 100644 --- a/yarn-project/circuits.js/src/structs/__snapshots__/public_call_stack_item.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/__snapshots__/public_call_stack_item.test.ts.snap @@ -1,9 +1,9 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`PublicCallStackItem Computes a callstack item hash 1`] = `"0x1ef9292cf3383605672c06dd50a12c251aa1f037cd826c0fc70d8ee5324e88c4"`; +exports[`PublicCallStackItem Computes a callstack item hash 1`] = `"0x2bf24099a6954a9bb9be6689fd765366fbb94fb25328d7e3942698ae891bbfad"`; -exports[`PublicCallStackItem Computes a callstack item request hash 1`] = `"0x23066ad690c088120f8397cfeb2ef5608d4517342c7ff9fcb713009933ef1c61"`; +exports[`PublicCallStackItem Computes a callstack item request hash 1`] = `"0x18e440e4e58ed510c02062986f71ef37ed610fc300b8baab334fd543758b9f11"`; -exports[`PublicCallStackItem computes empty item hash 1`] = `Fr<0x0eef6f20d1f73de870f781dad46a843966eb560e2b684752c82cd2bd45f97a34>`; +exports[`PublicCallStackItem computes empty item hash 1`] = `Fr<0x14d45139af9cc8f9a5a8537de0615a093ec755974d3460ce921eb78f9a533863>`; -exports[`PublicCallStackItem computes hash 1`] = `Fr<0x1571225ac99b706576b42ca98a76865ac6057c17bec38f22f6a78793d4b201b6>`; +exports[`PublicCallStackItem computes hash 1`] = `Fr<0x15fd7b945b88bba32060703eee30a4db98c35b291c5c0c211c03cd4a77436953>`; diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/public_circuit_public_inputs.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/public_circuit_public_inputs.test.ts.snap index b3fd8d646cd..ed74b387c27 100644 --- a/yarn-project/circuits.js/src/structs/__snapshots__/public_circuit_public_inputs.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/__snapshots__/public_circuit_public_inputs.test.ts.snap @@ -1,5 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`PublicCircuitPublicInputs computes empty inputs hash 1`] = `Fr<0x048912d56248af479f8d7ecedbba7092d27741b10075a989e040f8e3242a7a3f>`; +exports[`PublicCircuitPublicInputs computes empty inputs hash 1`] = `Fr<0x19eaa0a5aea3d131456d0daffc2d79fd27db9c201e91475ab620801b78504d79>`; -exports[`PublicCircuitPublicInputs hash matches snapshot 1`] = `Fr<0x15e41ce024b6e97478b456f670cfdd712aefe2504fd5145116e9ab7a26672d02>`; +exports[`PublicCircuitPublicInputs hash matches snapshot 1`] = `Fr<0x090fe4de8ca3cb2395490ef4e8e3ca0fc722168719726cdf7ee6999de3295767>`; diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/tx_context.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/tx_context.test.ts.snap index a27ef5d7eb7..439ecb7f0c3 100644 --- a/yarn-project/circuits.js/src/structs/__snapshots__/tx_context.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/__snapshots__/tx_context.test.ts.snap @@ -1,3 +1,3 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`TxContext computes empty context hash 1`] = `Fr<0x200569267c0f73ac89aaa414239398db9445dd4ad3a8cf37015cd55b8d4c5e8d>`; +exports[`TxContext computes empty context hash 1`] = `Fr<0x1acd086cc3b911cd49713c263bf4af6032a567fa1e79fe7ef77c063565d3ead3>`; diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/tx_request.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/tx_request.test.ts.snap index 7bf6df6c4a4..94bae498a3c 100644 --- a/yarn-project/circuits.js/src/structs/__snapshots__/tx_request.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/__snapshots__/tx_request.test.ts.snap @@ -1,3 +1,3 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`TxRequest compute hash 1`] = `"0x03b678e327818eb368f9eac21839ee67a98968318f0dcd76c89d3fcf66af7257"`; +exports[`TxRequest compute hash 1`] = `"0x00b8affaf5ca65d647756e359ce0b2c5fa5c2c03f219189e28db323f22975706"`; diff --git a/yarn-project/circuits.js/src/structs/call_context.ts b/yarn-project/circuits.js/src/structs/call_context.ts index b542a46b1e0..68aaaa99c1a 100644 --- a/yarn-project/circuits.js/src/structs/call_context.ts +++ b/yarn-project/circuits.js/src/structs/call_context.ts @@ -6,8 +6,6 @@ import { BufferReader, FieldReader, serializeToBuffer, serializeToFields } from import { type FieldsOf } from '@aztec/foundation/types'; import { CALL_CONTEXT_LENGTH } from '../constants.gen.js'; -import { Gas } from './gas.js'; -import { GasSettings } from './gas_settings.js'; /** * Call context. @@ -32,8 +30,6 @@ export class CallContext { * Function selector of the function being called. */ public functionSelector: FunctionSelector, - /** How much gas is available for execution of this function. */ - public gasLeft: Gas, /** * Determines whether the call is a delegate call (see Ethereum's delegate call opcode for more information). */ @@ -46,12 +42,6 @@ export class CallContext { * The start side effect counter for this call context. */ public sideEffectCounter: number, - - /** Gas settings for this tx. */ - public gasSettings: GasSettings, - - /** Accumulated transaction fee, only set during teardown phase. */ - public transactionFee: Fr, ) {} /** @@ -64,12 +54,9 @@ export class CallContext { AztecAddress.ZERO, EthAddress.ZERO, FunctionSelector.empty(), - Gas.empty(), false, false, 0, - GasSettings.empty(), - Fr.ZERO, ); } @@ -79,10 +66,7 @@ export class CallContext { this.storageContractAddress.isZero() && this.portalContractAddress.isZero() && this.functionSelector.isEmpty() && - this.gasLeft.isEmpty() && - Fr.ZERO && - this.gasSettings.isEmpty() && - this.transactionFee.isZero() + Fr.ZERO ); } @@ -96,12 +80,9 @@ export class CallContext { fields.storageContractAddress, fields.portalContractAddress, fields.functionSelector, - fields.gasLeft, fields.isDelegateCall, fields.isStaticCall, fields.sideEffectCounter, - fields.gasSettings, - fields.transactionFee, ] as const; } @@ -135,12 +116,9 @@ export class CallContext { reader.readObject(AztecAddress), reader.readObject(EthAddress), reader.readObject(FunctionSelector), - reader.readObject(Gas), reader.readBoolean(), reader.readBoolean(), reader.readNumber(), - reader.readObject(GasSettings), - reader.readObject(Fr), ); } @@ -151,12 +129,9 @@ export class CallContext { reader.readObject(AztecAddress), reader.readObject(EthAddress), reader.readObject(FunctionSelector), - reader.readObject(Gas), reader.readBoolean(), reader.readBoolean(), reader.readU32(), - reader.readObject(GasSettings), - reader.readField(), ); } @@ -166,12 +141,9 @@ export class CallContext { callContext.storageContractAddress.equals(this.storageContractAddress) && callContext.portalContractAddress.equals(this.portalContractAddress) && callContext.functionSelector.equals(this.functionSelector) && - callContext.gasLeft.equals(this.gasLeft) && callContext.isDelegateCall === this.isDelegateCall && callContext.isStaticCall === this.isStaticCall && - callContext.sideEffectCounter === this.sideEffectCounter && - this.gasSettings.equals(callContext.gasSettings) && - callContext.transactionFee.equals(this.transactionFee) + callContext.sideEffectCounter === this.sideEffectCounter ); } } diff --git a/yarn-project/circuits.js/src/structs/context/private_context_inputs.ts b/yarn-project/circuits.js/src/structs/context/private_context_inputs.ts new file mode 100644 index 00000000000..f930eabf3ba --- /dev/null +++ b/yarn-project/circuits.js/src/structs/context/private_context_inputs.ts @@ -0,0 +1,22 @@ +import { serializeToFields } from '@aztec/foundation/serialize'; + +import { CallContext } from '../call_context.js'; +import { Header } from '../header.js'; +import { TxContext } from '../tx_context.js'; + +export class PrivateContextInputs { + constructor( + public callContext: CallContext, + public historicalHeader: Header, + public txContext: TxContext, + public startSideEffectCounter: number, + ) {} + + public static empty(): PrivateContextInputs { + return new PrivateContextInputs(CallContext.empty(), Header.empty(), TxContext.empty(), 0); + } + + public toFields() { + return serializeToFields([this.callContext, this.historicalHeader, this.txContext, this.startSideEffectCounter]); + } +} diff --git a/yarn-project/circuits.js/src/structs/context/public_context_inputs.ts b/yarn-project/circuits.js/src/structs/context/public_context_inputs.ts new file mode 100644 index 00000000000..567c3d09027 --- /dev/null +++ b/yarn-project/circuits.js/src/structs/context/public_context_inputs.ts @@ -0,0 +1,40 @@ +import { Fr } from '@aztec/foundation/fields'; +import { serializeToFields } from '@aztec/foundation/serialize'; + +import { CallContext } from '../call_context.js'; +import { Gas } from '../gas.js'; +import { GlobalVariables } from '../global_variables.js'; +import { Header } from '../header.js'; + +export class PublicContextInputs { + constructor( + public callContext: CallContext, + public historicalHeader: Header, + public publicGlobalVariables: GlobalVariables, + public startSideEffectCounter: number, + public gasLeft: Gas, + public transactionFee: Fr, + ) {} + + public static empty(): PublicContextInputs { + return new PublicContextInputs( + CallContext.empty(), + Header.empty(), + GlobalVariables.empty(), + 0, + Gas.empty(), + Fr.ZERO, + ); + } + + public toFields() { + return serializeToFields([ + this.callContext, + this.historicalHeader, + this.publicGlobalVariables, + this.startSideEffectCounter, + this.gasLeft, + this.transactionFee, + ]); + } +} diff --git a/yarn-project/circuits.js/src/structs/gas.ts b/yarn-project/circuits.js/src/structs/gas.ts index 5924282216a..8380f362e25 100644 --- a/yarn-project/circuits.js/src/structs/gas.ts +++ b/yarn-project/circuits.js/src/structs/gas.ts @@ -6,10 +6,21 @@ import { inspect } from 'util'; import { type UInt32 } from './shared.js'; +export const GasDimensions = ['da', 'l1', 'l2'] as const; +export type GasDimensions = (typeof GasDimensions)[number]; + /** Gas amounts in each dimension. */ export class Gas { constructor(public readonly daGas: UInt32, public readonly l1Gas: UInt32, public readonly l2Gas: UInt32) {} + clone(): Gas { + return new Gas(this.daGas, this.l1Gas, this.l2Gas); + } + + get(dimension: GasDimensions) { + return this[`${dimension}Gas`]; + } + equals(other: Gas) { return this.daGas === other.daGas && this.l1Gas === other.l1Gas && this.l2Gas === other.l2Gas; } diff --git a/yarn-project/circuits.js/src/structs/gas_fees.ts b/yarn-project/circuits.js/src/structs/gas_fees.ts index ee5489d47b2..4e2cde284c1 100644 --- a/yarn-project/circuits.js/src/structs/gas_fees.ts +++ b/yarn-project/circuits.js/src/structs/gas_fees.ts @@ -4,9 +4,42 @@ import { type FieldsOf } from '@aztec/foundation/types'; import { inspect } from 'util'; +import { type GasDimensions } from './gas.js'; + /** Gas prices for each dimension. */ export class GasFees { - constructor(public readonly feePerDaGas: Fr, public readonly feePerL1Gas: Fr, public readonly feePerL2Gas: Fr) {} + public readonly feePerDaGas: Fr; + public readonly feePerL1Gas: Fr; + public readonly feePerL2Gas: Fr; + + constructor(feePerDaGas: Fr | number | bigint, feePerL1Gas: Fr | number | bigint, feePerL2Gas: Fr | number | bigint) { + this.feePerDaGas = new Fr(feePerDaGas); + this.feePerL1Gas = new Fr(feePerL1Gas); + this.feePerL2Gas = new Fr(feePerL2Gas); + } + + clone(): GasFees { + return new GasFees(this.feePerDaGas, this.feePerL1Gas, this.feePerL2Gas); + } + + equals(other: GasFees) { + return ( + this.feePerDaGas.equals(other.feePerDaGas) && + this.feePerL1Gas.equals(other.feePerL1Gas) && + this.feePerL2Gas.equals(other.feePerL2Gas) + ); + } + + get(dimension: GasDimensions) { + switch (dimension) { + case 'da': + return this.feePerDaGas; + case 'l1': + return this.feePerL1Gas; + case 'l2': + return this.feePerL2Gas; + } + } static from(fields: FieldsOf) { return new GasFees(fields.feePerDaGas, fields.feePerL1Gas, fields.feePerL2Gas); diff --git a/yarn-project/circuits.js/src/structs/gas_settings.ts b/yarn-project/circuits.js/src/structs/gas_settings.ts index 80a57f0c19b..4f6a3eb52da 100644 --- a/yarn-project/circuits.js/src/structs/gas_settings.ts +++ b/yarn-project/circuits.js/src/structs/gas_settings.ts @@ -2,79 +2,94 @@ import { Fr } from '@aztec/foundation/fields'; import { BufferReader, FieldReader, serializeToBuffer, serializeToFields } from '@aztec/foundation/serialize'; import { type FieldsOf } from '@aztec/foundation/types'; -import { GAS_SETTINGS_LENGTH } from '../constants.gen.js'; -import { Gas } from './gas.js'; -import { type UInt32 } from './shared.js'; +import { + DEFAULT_GAS_LIMIT, + DEFAULT_INCLUSION_FEE, + DEFAULT_MAX_FEE_PER_GAS, + DEFAULT_TEARDOWN_GAS_LIMIT, + GAS_SETTINGS_LENGTH, +} from '../constants.gen.js'; +import { Gas, GasDimensions } from './gas.js'; +import { GasFees } from './gas_fees.js'; /** Gas usage and fees limits set by the transaction sender for different dimensions and phases. */ export class GasSettings { constructor( - public readonly da: DimensionGasSettings, - public readonly l1: DimensionGasSettings, - public readonly l2: DimensionGasSettings, + public readonly gasLimits: Gas, + public readonly teardownGasLimits: Gas, + public readonly maxFeesPerGas: GasFees, public readonly inclusionFee: Fr, ) {} - static new(args: { - da: FieldsOf; - l1: FieldsOf; - l2: FieldsOf; + static from(args: { + gasLimits: FieldsOf; + teardownGasLimits: FieldsOf; + maxFeesPerGas: FieldsOf; inclusionFee: Fr; }) { return new GasSettings( - DimensionGasSettings.from(args.da), - DimensionGasSettings.from(args.l1), - DimensionGasSettings.from(args.l2), + Gas.from(args.gasLimits), + Gas.from(args.teardownGasLimits), + GasFees.from(args.maxFeesPerGas), args.inclusionFee, ); } + clone() { + return new GasSettings( + this.gasLimits.clone(), + this.teardownGasLimits.clone(), + this.maxFeesPerGas.clone(), + this.inclusionFee, + ); + } + /** Returns the maximum fee to be paid according to gas limits and max fees set. */ getFeeLimit() { - return [this.da, this.l1, this.l2] - .reduce((acc, dimension) => acc.add(dimension.getFeeLimit()), Fr.ZERO) - .add(this.inclusionFee); + return GasDimensions.reduce( + (acc, dimension) => + this.maxFeesPerGas + .get(dimension) + .mul(new Fr(this.gasLimits.get(dimension))) + .add(acc), + Fr.ZERO, + ).add(this.inclusionFee); } /** Zero-value gas settings. */ static empty() { - return new GasSettings( - DimensionGasSettings.empty(), - DimensionGasSettings.empty(), - DimensionGasSettings.empty(), - Fr.ZERO, - ); + return new GasSettings(Gas.empty(), Gas.empty(), GasFees.empty(), Fr.ZERO); } /** Default gas settings to use when user has not provided them. */ static default() { return new GasSettings( - DimensionGasSettings.default(), - DimensionGasSettings.default(), - DimensionGasSettings.default(), - Fr.ONE, + new Gas(DEFAULT_GAS_LIMIT, DEFAULT_GAS_LIMIT, DEFAULT_GAS_LIMIT), + new Gas(DEFAULT_TEARDOWN_GAS_LIMIT, DEFAULT_TEARDOWN_GAS_LIMIT, DEFAULT_TEARDOWN_GAS_LIMIT), + new GasFees(new Fr(DEFAULT_MAX_FEE_PER_GAS), new Fr(DEFAULT_MAX_FEE_PER_GAS), new Fr(DEFAULT_MAX_FEE_PER_GAS)), + new Fr(DEFAULT_INCLUSION_FEE), ); } /** Gas settings to use for simulating a contract call. */ static simulation() { - return new GasSettings( - DimensionGasSettings.simulation(), - DimensionGasSettings.simulation(), - DimensionGasSettings.simulation(), - Fr.ONE, - ); + return GasSettings.default(); } isEmpty() { - return this.da.isEmpty() && this.l1.isEmpty() && this.l2.isEmpty() && this.inclusionFee.isZero(); + return ( + this.gasLimits.isEmpty() && + this.teardownGasLimits.isEmpty() && + this.maxFeesPerGas.isEmpty() && + this.inclusionFee.isZero() + ); } equals(other: GasSettings) { return ( - this.da.equals(other.da) && - this.l1.equals(other.l1) && - this.l2.equals(other.l2) && + this.gasLimits.equals(other.gasLimits) && + this.teardownGasLimits.equals(other.teardownGasLimits) && + this.maxFeesPerGas.equals(other.maxFeesPerGas) && this.inclusionFee.equals(other.inclusionFee) ); } @@ -82,9 +97,9 @@ export class GasSettings { static fromBuffer(buffer: Buffer | BufferReader): GasSettings { const reader = BufferReader.asReader(buffer); return new GasSettings( - reader.readObject(DimensionGasSettings), - reader.readObject(DimensionGasSettings), - reader.readObject(DimensionGasSettings), + reader.readObject(Gas), + reader.readObject(Gas), + reader.readObject(GasFees), reader.readObject(Fr), ); } @@ -96,9 +111,9 @@ export class GasSettings { static fromFields(fields: Fr[] | FieldReader): GasSettings { const reader = FieldReader.asReader(fields); return new GasSettings( - reader.readObject(DimensionGasSettings), - reader.readObject(DimensionGasSettings), - reader.readObject(DimensionGasSettings), + reader.readObject(Gas), + reader.readObject(Gas), + reader.readObject(GasFees), reader.readField(), ); } @@ -114,92 +129,21 @@ export class GasSettings { } static getFields(fields: FieldsOf) { - return [fields.da, fields.l1, fields.l2, fields.inclusionFee] as const; + return [fields.gasLimits, fields.teardownGasLimits, fields.maxFeesPerGas, fields.inclusionFee] as const; } /** Returns total gas limits. */ getLimits(): Gas { - return new Gas(this.da.gasLimit, this.l1.gasLimit, this.l2.gasLimit); + return this.gasLimits; } /** Returns how much gas is available for execution of setup and app phases (ie total limit minus teardown). */ getInitialAvailable(): Gas { - return new Gas( - this.da.gasLimit - this.da.teardownGasLimit, - this.l1.gasLimit - this.l1.teardownGasLimit, - this.l2.gasLimit - this.l2.teardownGasLimit, - ); + return this.gasLimits.sub(this.teardownGasLimits); } /** Returns how much gas is available for execution of teardown phase. */ getTeardownLimits(): Gas { - return new Gas(this.da.teardownGasLimit, this.l1.teardownGasLimit, this.l2.teardownGasLimit); - } -} - -/** Gas usage and fees limits set by the transaction sender for different phases on a specific dimension. */ -export class DimensionGasSettings { - constructor( - public readonly gasLimit: UInt32, - public readonly teardownGasLimit: UInt32, - public readonly maxFeePerGas: Fr, - ) { - if (teardownGasLimit > gasLimit) { - throw new Error(`Teardown gas limit ${teardownGasLimit} is greater than gas limit ${gasLimit}`); - } - } - - static default() { - return new DimensionGasSettings(1e9, 1e8, Fr.ONE); - } - - static simulation() { - return new DimensionGasSettings(1e9, 1e8, Fr.ONE); - } - - getFeeLimit() { - return this.maxFeePerGas.mul(new Fr(this.gasLimit + this.teardownGasLimit)); - } - - static empty() { - return new DimensionGasSettings(0, 0, Fr.ZERO); - } - - isEmpty() { - return this.gasLimit === 0 && this.maxFeePerGas.isZero() && this.teardownGasLimit === 0; - } - - equals(other: DimensionGasSettings) { - return ( - this.gasLimit === other.gasLimit && - this.maxFeePerGas.equals(other.maxFeePerGas) && - this.teardownGasLimit === other.teardownGasLimit - ); - } - - static fromBuffer(buffer: Buffer | BufferReader): DimensionGasSettings { - const reader = BufferReader.asReader(buffer); - return new DimensionGasSettings(reader.readNumber(), reader.readNumber(), reader.readObject(Fr)); - } - - toBuffer() { - return serializeToBuffer(...DimensionGasSettings.getFields(this)); - } - - static fromFields(fields: Fr[] | FieldReader): DimensionGasSettings { - const reader = FieldReader.asReader(fields); - return new DimensionGasSettings(reader.readU32(), reader.readU32(), reader.readField()); - } - - toFields(): Fr[] { - return serializeToFields(...DimensionGasSettings.getFields(this)); - } - - static getFields(fields: FieldsOf) { - return [fields.gasLimit, fields.teardownGasLimit, fields.maxFeePerGas] as const; - } - - static from(fields: FieldsOf) { - return new DimensionGasSettings(fields.gasLimit, fields.teardownGasLimit, fields.maxFeePerGas); + return this.teardownGasLimits; } } diff --git a/yarn-project/circuits.js/src/structs/index.ts b/yarn-project/circuits.js/src/structs/index.ts index 400c60e8ac9..0daa44c581a 100644 --- a/yarn-project/circuits.js/src/structs/index.ts +++ b/yarn-project/circuits.js/src/structs/index.ts @@ -4,6 +4,8 @@ export * from './call_context.js'; export * from './call_request.js'; export * from './complete_address.js'; export * from './content_commitment.js'; +export * from './context/private_context_inputs.js'; +export * from './context/public_context_inputs.js'; export * from './contract_storage_read.js'; export * from './contract_storage_update_request.js'; export * from './function_data.js'; diff --git a/yarn-project/circuits.js/src/structs/kernel/combined_constant_data.ts b/yarn-project/circuits.js/src/structs/kernel/combined_constant_data.ts index 6534f7c90a0..189d6a27764 100644 --- a/yarn-project/circuits.js/src/structs/kernel/combined_constant_data.ts +++ b/yarn-project/circuits.js/src/structs/kernel/combined_constant_data.ts @@ -1,6 +1,5 @@ import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; -import { GasSettings } from '../gas_settings.js'; import { Header } from '../header.js'; import { TxContext } from '../tx_context.js'; @@ -22,13 +21,10 @@ export class CombinedConstantData { * protocol to execute and prove the transaction. */ public txContext: TxContext, - - /** Gas limits and max prices for this transaction as set by the sender. */ - public gasSettings: GasSettings, ) {} toBuffer() { - return serializeToBuffer(this.historicalHeader, this.txContext, this.gasSettings); + return serializeToBuffer(this.historicalHeader, this.txContext); } /** @@ -38,14 +34,10 @@ export class CombinedConstantData { */ static fromBuffer(buffer: Buffer | BufferReader): CombinedConstantData { const reader = BufferReader.asReader(buffer); - return new CombinedConstantData( - reader.readObject(Header), - reader.readObject(TxContext), - reader.readObject(GasSettings), - ); + return new CombinedConstantData(reader.readObject(Header), reader.readObject(TxContext)); } static empty() { - return new CombinedConstantData(Header.empty(), TxContext.empty(), GasSettings.empty()); + return new CombinedConstantData(Header.empty(), TxContext.empty()); } } diff --git a/yarn-project/circuits.js/src/structs/kernel/private_accumulated_data.ts b/yarn-project/circuits.js/src/structs/kernel/private_accumulated_data.ts index d52cc104bc7..e626d056ca2 100644 --- a/yarn-project/circuits.js/src/structs/kernel/private_accumulated_data.ts +++ b/yarn-project/circuits.js/src/structs/kernel/private_accumulated_data.ts @@ -13,7 +13,6 @@ import { MAX_UNENCRYPTED_LOGS_PER_TX, } from '../../constants.gen.js'; import { CallRequest } from '../call_request.js'; -import { Gas } from '../gas.js'; import { SideEffect, SideEffectLinkedToNoteHash } from '../side_effects.js'; /** @@ -61,9 +60,6 @@ export class PrivateAccumulatedData { * Current public call stack. */ public publicCallStack: Tuple, - - /** Gas used so far by this transaction. */ - public gasUsed: Gas, ) {} toBuffer() { @@ -77,7 +73,6 @@ export class PrivateAccumulatedData { this.unencryptedLogPreimagesLength, this.privateCallStack, this.publicCallStack, - this.gasUsed, ); } @@ -102,7 +97,6 @@ export class PrivateAccumulatedData { Fr.fromBuffer(reader), reader.readArray(MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, CallRequest), reader.readArray(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, CallRequest), - reader.readObject(Gas), ); } @@ -126,7 +120,6 @@ export class PrivateAccumulatedData { Fr.zero(), makeTuple(MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, CallRequest.empty), makeTuple(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, CallRequest.empty), - Gas.empty(), ); } } diff --git a/yarn-project/circuits.js/src/structs/private_circuit_public_inputs.ts b/yarn-project/circuits.js/src/structs/private_circuit_public_inputs.ts index 981f7263059..b776f73962a 100644 --- a/yarn-project/circuits.js/src/structs/private_circuit_public_inputs.ts +++ b/yarn-project/circuits.js/src/structs/private_circuit_public_inputs.ts @@ -32,6 +32,7 @@ import { L2ToL1Message } from './l2_to_l1_message.js'; import { MaxBlockNumber } from './max_block_number.js'; import { NullifierKeyValidationRequest } from './nullifier_key_validation_request.js'; import { ReadRequest } from './read_request.js'; +import { TxContext } from './tx_context.js'; /** * Public inputs to a private circuit. @@ -127,17 +128,13 @@ export class PrivateCircuitPublicInputs { */ public historicalHeader: Header, /** - * Chain Id of the instance. + * Transaction context. * - * Note: The following 2 values are not redundant to the values in self.historical_header.global_variables because + * Note: The chainId and version in the txContext are not redundant to the values in self.historical_header.global_variables because * they can be different in case of a protocol upgrade. In such a situation we could be using header from a block * before the upgrade took place but be using the updated protocol to execute and prove the transaction. */ - public chainId: Fr, - /** - * Version of the instance. - */ - public version: Fr, + public txContext: TxContext, ) {} /** @@ -177,8 +174,7 @@ export class PrivateCircuitPublicInputs { reader.readObject(Fr), reader.readObject(Fr), reader.readObject(Header), - reader.readObject(Fr), - reader.readObject(Fr), + reader.readObject(TxContext), ); } @@ -205,8 +201,7 @@ export class PrivateCircuitPublicInputs { reader.readField(), reader.readField(), reader.readObject(Header), - reader.readField(), - reader.readField(), + reader.readObject(TxContext), ); } @@ -236,8 +231,7 @@ export class PrivateCircuitPublicInputs { Fr.ZERO, Fr.ZERO, Header.empty(), - Fr.ZERO, - Fr.ZERO, + TxContext.empty(), ); } @@ -265,8 +259,7 @@ export class PrivateCircuitPublicInputs { this.encryptedLogPreimagesLength.isZero() && this.unencryptedLogPreimagesLength.isZero() && this.historicalHeader.isEmpty() && - this.chainId.isZero() && - this.version.isZero() + this.txContext.isEmpty() ); } @@ -297,8 +290,7 @@ export class PrivateCircuitPublicInputs { fields.encryptedLogPreimagesLength, fields.unencryptedLogPreimagesLength, fields.historicalHeader, - fields.chainId, - fields.version, + fields.txContext, ] as const; } diff --git a/yarn-project/circuits.js/src/structs/public_circuit_public_inputs.ts b/yarn-project/circuits.js/src/structs/public_circuit_public_inputs.ts index df93a84cd24..220101ff45a 100644 --- a/yarn-project/circuits.js/src/structs/public_circuit_public_inputs.ts +++ b/yarn-project/circuits.js/src/structs/public_circuit_public_inputs.ts @@ -122,8 +122,14 @@ export class PublicCircuitPublicInputs { */ public revertCode: RevertCode, + /** How much gas was available for execution. */ + public startGasLeft: Gas, + /** How much gas was left after execution. */ - public gasLeft: Gas, + public endGasLeft: Gas, + + /** Transaction fee in the fee-payment asset. Zero in all phases except teardown. */ + public transactionFee: Fr, ) {} /** @@ -160,6 +166,8 @@ export class PublicCircuitPublicInputs { AztecAddress.ZERO, RevertCode.OK, Gas.empty(), + Gas.empty(), + Fr.ZERO, ); } @@ -187,7 +195,9 @@ export class PublicCircuitPublicInputs { this.historicalHeader.isEmpty() && this.proverAddress.isZero() && this.revertCode.isOK() && - this.gasLeft.isEmpty() + this.startGasLeft.isEmpty() && + this.endGasLeft.isEmpty() && + this.transactionFee.isZero() ); } @@ -216,7 +226,9 @@ export class PublicCircuitPublicInputs { fields.historicalHeader, fields.proverAddress, fields.revertCode, - fields.gasLeft, + fields.startGasLeft, + fields.endGasLeft, + fields.transactionFee, ] as const; } @@ -265,6 +277,8 @@ export class PublicCircuitPublicInputs { reader.readObject(AztecAddress), reader.readObject(RevertCode), reader.readObject(Gas), + reader.readObject(Gas), + reader.readObject(Fr), ); } @@ -291,6 +305,8 @@ export class PublicCircuitPublicInputs { AztecAddress.fromFields(reader), RevertCode.fromFields(reader), Gas.fromFields(reader), + Gas.fromFields(reader), + reader.readField(), ); } diff --git a/yarn-project/circuits.js/src/structs/tx_context.test.ts b/yarn-project/circuits.js/src/structs/tx_context.test.ts index d6c09627e59..4acd8c5b4c0 100644 --- a/yarn-project/circuits.js/src/structs/tx_context.test.ts +++ b/yarn-project/circuits.js/src/structs/tx_context.test.ts @@ -1,7 +1,7 @@ import { randomInt } from '@aztec/foundation/crypto'; import { setupCustomSnapshotSerializers, updateInlineTestData } from '@aztec/foundation/testing'; -import { TX_CONTEXT_DATA_LENGTH } from '../constants.gen.js'; +import { TX_CONTEXT_LENGTH } from '../constants.gen.js'; import { makeTxContext } from '../tests/factories.js'; import { TxContext } from './tx_context.js'; @@ -22,7 +22,7 @@ describe('TxContext', () => { it('number of fields matches constant', () => { const fields = context.toFields(); - expect(fields.length).toBe(TX_CONTEXT_DATA_LENGTH); + expect(fields.length).toBe(TX_CONTEXT_LENGTH); }); it('computes empty context hash', () => { diff --git a/yarn-project/circuits.js/src/structs/tx_context.ts b/yarn-project/circuits.js/src/structs/tx_context.ts index 73d484e54af..22697d79a5d 100644 --- a/yarn-project/circuits.js/src/structs/tx_context.ts +++ b/yarn-project/circuits.js/src/structs/tx_context.ts @@ -1,39 +1,33 @@ import { pedersenHash } from '@aztec/foundation/crypto'; import { Fr } from '@aztec/foundation/fields'; -import { BufferReader, serializeToBuffer, serializeToFields } from '@aztec/foundation/serialize'; +import { BufferReader, FieldReader, serializeToBuffer, serializeToFields } from '@aztec/foundation/serialize'; import { type FieldsOf } from '@aztec/foundation/types'; -import { GeneratorIndex, TX_CONTEXT_DATA_LENGTH } from '../constants.gen.js'; +import { GeneratorIndex, TX_CONTEXT_LENGTH } from '../constants.gen.js'; +import { GasSettings } from './gas_settings.js'; /** * Transaction context. */ export class TxContext { + public chainId: Fr; + public version: Fr; + constructor( - /** - * Whether this is a fee paying tx. If not other tx in a bundle will pay the fee. - * TODO(#3417): Remove fee and rebate payment fields. - */ - public isFeePaymentTx: boolean, - /** - * Indicates whether this a gas rebate payment tx. - * - * NOTE: The following is a WIP and it is likely to change in the future. - * Explanation: Each tx is actually 3 txs in one: a fee-paying tx, the actual tx you want to execute, and a rebate - * tx. The fee-paying tx pays some `max_fee = gas_price * gas_limit`. Then the actual tx will cost an amount of gas - * to execute (actual_fee = gas_price * gas_used). Then the rebate tx returns `max_fee - actual_fee` back to - * the user. - */ - public isRebatePaymentTx: boolean, - /** - * Chain ID of the transaction. Here for replay protection. - */ - public chainId: Fr, - /** - * Version of the transaction. Here for replay protection. - */ - public version: Fr, - ) {} + /** Chain ID of the transaction. Here for replay protection. */ + chainId: Fr | number | bigint, + /** Version of the transaction. Here for replay protection. */ + version: Fr | number | bigint, + /** Gas limits for this transaction. */ + public gasSettings: GasSettings, + ) { + this.chainId = new Fr(chainId); + this.version = new Fr(version); + } + + clone() { + return new TxContext(this.chainId, this.version, this.gasSettings.clone()); + } /** * Serialize as a buffer. @@ -43,12 +37,15 @@ export class TxContext { return serializeToBuffer(...TxContext.getFields(this)); } + static fromFields(fields: Fr[] | FieldReader): TxContext { + const reader = FieldReader.asReader(fields); + return new TxContext(reader.readField(), reader.readField(), reader.readObject(GasSettings)); + } + toFields(): Fr[] { const fields = serializeToFields(...TxContext.getFields(this)); - if (fields.length !== TX_CONTEXT_DATA_LENGTH) { - throw new Error( - `Invalid number of fields for TxContext. Expected ${TX_CONTEXT_DATA_LENGTH}, got ${fields.length}`, - ); + if (fields.length !== TX_CONTEXT_LENGTH) { + throw new Error(`Invalid number of fields for TxContext. Expected ${TX_CONTEXT_LENGTH}, got ${fields.length}`); } return fields; } @@ -60,15 +57,15 @@ export class TxContext { */ static fromBuffer(buffer: Buffer | BufferReader): TxContext { const reader = BufferReader.asReader(buffer); - return new TxContext(reader.readBoolean(), reader.readBoolean(), Fr.fromBuffer(reader), Fr.fromBuffer(reader)); + return new TxContext(Fr.fromBuffer(reader), Fr.fromBuffer(reader), reader.readObject(GasSettings)); } static empty(chainId: Fr | number = 0, version: Fr | number = 0) { - return new TxContext(false, false, new Fr(chainId), new Fr(version)); + return new TxContext(new Fr(chainId), new Fr(version), GasSettings.empty()); } isEmpty(): boolean { - return !this.isFeePaymentTx && !this.isRebatePaymentTx && this.chainId.isZero() && this.version.isZero(); + return this.chainId.isZero() && this.version.isZero() && this.gasSettings.isEmpty(); } /** @@ -86,7 +83,7 @@ export class TxContext { * @returns The array. */ static getFields(fields: FieldsOf) { - return [fields.isFeePaymentTx, fields.isRebatePaymentTx, fields.chainId, fields.version] as const; + return [fields.chainId, fields.version, fields.gasSettings] as const; } hash(): Fr { diff --git a/yarn-project/circuits.js/src/structs/tx_request.test.ts b/yarn-project/circuits.js/src/structs/tx_request.test.ts index ee364557c5f..c7c0882827a 100644 --- a/yarn-project/circuits.js/src/structs/tx_request.test.ts +++ b/yarn-project/circuits.js/src/structs/tx_request.test.ts @@ -7,6 +7,8 @@ import { setupCustomSnapshotSerializers, updateInlineTestData } from '@aztec/fou import { TX_REQUEST_LENGTH } from '../constants.gen.js'; import { makeTxRequest } from '../tests/factories.js'; import { FunctionData } from './function_data.js'; +import { Gas } from './gas.js'; +import { GasFees } from './gas_fees.js'; import { GasSettings } from './gas_settings.js'; import { TxContext } from './tx_context.js'; import { TxRequest } from './tx_request.js'; @@ -32,17 +34,12 @@ describe('TxRequest', () => { }); it('compute hash', () => { + const gasSettings = new GasSettings(new Gas(2, 2, 2), new Gas(1, 1, 1), new GasFees(3, 3, 3), new Fr(10)); const txRequest = TxRequest.from({ origin: AztecAddress.fromBigInt(1n), functionData: new FunctionData(FunctionSelector.fromField(new Fr(2n)), true), argsHash: new Fr(3), - txContext: new TxContext(false, false, Fr.ZERO, Fr.ZERO), - gasSettings: GasSettings.new({ - da: { gasLimit: 2, teardownGasLimit: 1, maxFeePerGas: new Fr(3) }, - l1: { gasLimit: 2, teardownGasLimit: 1, maxFeePerGas: new Fr(3) }, - l2: { gasLimit: 2, teardownGasLimit: 1, maxFeePerGas: new Fr(3) }, - inclusionFee: new Fr(10), - }), + txContext: new TxContext(Fr.ZERO, Fr.ZERO, gasSettings), }); const hash = txRequest.hash().toString(); diff --git a/yarn-project/circuits.js/src/structs/tx_request.ts b/yarn-project/circuits.js/src/structs/tx_request.ts index 8b2337e665d..53e30e9e843 100644 --- a/yarn-project/circuits.js/src/structs/tx_request.ts +++ b/yarn-project/circuits.js/src/structs/tx_request.ts @@ -6,7 +6,6 @@ import { type FieldsOf } from '@aztec/foundation/types'; import { GeneratorIndex, TX_REQUEST_LENGTH } from '../constants.gen.js'; import { FunctionData } from './function_data.js'; -import { GasSettings } from './gas_settings.js'; import { TxContext } from './tx_context.js'; /** @@ -22,12 +21,10 @@ export class TxRequest { public argsHash: Fr, /** Transaction context. */ public txContext: TxContext, - /** Gas limits and max fees per dimension. */ - public gasSettings: GasSettings, ) {} static getFields(fields: FieldsOf) { - return [fields.origin, fields.functionData, fields.argsHash, fields.txContext, fields.gasSettings] as const; + return [fields.origin, fields.functionData, fields.argsHash, fields.txContext] as const; } static from(fields: FieldsOf): TxRequest { @@ -62,7 +59,6 @@ export class TxRequest { reader.readObject(FunctionData), Fr.fromBuffer(reader), reader.readObject(TxContext), - reader.readObject(GasSettings), ); } @@ -71,16 +67,10 @@ export class TxRequest { } static empty() { - return new TxRequest(AztecAddress.ZERO, FunctionData.empty(), Fr.zero(), TxContext.empty(), GasSettings.empty()); + return new TxRequest(AztecAddress.ZERO, FunctionData.empty(), Fr.zero(), TxContext.empty()); } isEmpty() { - return ( - this.origin.isZero() && - this.functionData.isEmpty() && - this.argsHash.isZero() && - this.txContext.isEmpty() && - this.gasSettings.isEmpty() - ); + return this.origin.isZero() && this.functionData.isEmpty() && this.argsHash.isZero() && this.txContext.isEmpty(); } } diff --git a/yarn-project/circuits.js/src/tests/factories.ts b/yarn-project/circuits.js/src/tests/factories.ts index 389329b678f..ead75b997c1 100644 --- a/yarn-project/circuits.js/src/tests/factories.ts +++ b/yarn-project/circuits.js/src/tests/factories.ts @@ -171,7 +171,7 @@ export function makeNewSideEffectLinkedToNoteHash(seed: number): SideEffectLinke */ export function makeTxContext(seed: number): TxContext { // @todo @LHerskind should probably take value for chainId as it will be verified later. - return new TxContext(false, false, new Fr(seed), Fr.ZERO); + return new TxContext(new Fr(seed), Fr.ZERO, makeGasSettings()); } /** @@ -180,7 +180,7 @@ export function makeTxContext(seed: number): TxContext { * @returns A constant data object. */ export function makeConstantData(seed = 1): CombinedConstantData { - return new CombinedConstantData(makeHeader(seed, undefined), makeTxContext(seed + 4), makeGasSettings()); + return new CombinedConstantData(makeHeader(seed, undefined), makeTxContext(seed + 4)); } /** @@ -377,7 +377,6 @@ export function makePrivateAccumulatedData(seed = 1, full = false) { fr(seed + 0xa00), // unencrypted_log_preimages_length tupleGenerator(MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, makeCallRequest, seed + 0x400, CallRequest.empty), tupleGenerator(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, makeCallRequest, seed + 0x500, CallRequest.empty), - makeGas(seed + 0x600), ); } @@ -402,18 +401,14 @@ export function makeAggregationObject(seed = 1): AggregationObject { * @returns A call context. */ export function makeCallContext(seed = 0, overrides: Partial> = {}): CallContext { - const gasSettings = makeGasSettings(); return CallContext.from({ msgSender: makeAztecAddress(seed), storageContractAddress: makeAztecAddress(seed + 1), portalContractAddress: makeEthAddress(seed + 2), functionSelector: makeSelector(seed + 3), - gasLeft: gasSettings.getLimits(), isStaticCall: false, isDelegateCall: false, sideEffectCounter: 0, - gasSettings, - transactionFee: fr(seed + 6), ...overrides, }); } @@ -461,6 +456,8 @@ export function makePublicCircuitPublicInputs( makeAztecAddress(seed + 0xb01), RevertCode.OK, makeGas(seed + 0xc00), + makeGas(seed + 0xc00), + fr(0), ); } @@ -841,7 +838,6 @@ export function makeTxRequest(seed = 1): TxRequest { functionData: new FunctionData(makeSelector(seed + 0x100), true), argsHash: fr(seed + 0x200), txContext: makeTxContext(seed + 0x400), - gasSettings: makeGasSettings(), }); } @@ -916,8 +912,7 @@ export function makePrivateCircuitPublicInputs(seed = 0): PrivateCircuitPublicIn encryptedLogPreimagesLength: fr(seed + 0xb00), unencryptedLogPreimagesLength: fr(seed + 0xc00), historicalHeader: makeHeader(seed + 0xd00, undefined), - chainId: fr(seed + 0x1400), - version: fr(seed + 0x1500), + txContext: makeTxContext(seed + 0x1400), }); } diff --git a/yarn-project/end-to-end/src/benchmarks/bench_tx_size_fees.test.ts b/yarn-project/end-to-end/src/benchmarks/bench_tx_size_fees.test.ts index 1deb698f41e..af887a7be5a 100644 --- a/yarn-project/end-to-end/src/benchmarks/bench_tx_size_fees.test.ts +++ b/yarn-project/end-to-end/src/benchmarks/bench_tx_size_fees.test.ts @@ -68,10 +68,10 @@ describe('benchmarks/tx_size_fees', () => { () => Promise.resolve(new PrivateFeePaymentMethod(token.address, fpc.address, aliceWallet)), ])('sends a tx with a fee', async createPaymentMethod => { const paymentMethod = await createPaymentMethod(); - const gasSettings = GasSettings.new({ - da: { gasLimit: 5, teardownGasLimit: 3, maxFeePerGas: Fr.ONE }, - l1: { gasLimit: 5, teardownGasLimit: 3, maxFeePerGas: Fr.ONE }, - l2: { gasLimit: 5, teardownGasLimit: 3, maxFeePerGas: Fr.ONE }, + const gasSettings = GasSettings.from({ + gasLimits: { daGas: 5, l1Gas: 5, l2Gas: 5 }, + teardownGasLimits: { daGas: 3, l1Gas: 3, l2Gas: 3 }, + maxFeesPerGas: { feePerDaGas: Fr.ONE, feePerL1Gas: Fr.ONE, feePerL2Gas: Fr.ONE }, inclusionFee: new Fr(6), }); const tx = await token.methods diff --git a/yarn-project/end-to-end/src/e2e_dapp_subscription.test.ts b/yarn-project/end-to-end/src/e2e_dapp_subscription.test.ts index 251e27734bc..c1ee4fcc0d7 100644 --- a/yarn-project/end-to-end/src/e2e_dapp_subscription.test.ts +++ b/yarn-project/end-to-end/src/e2e_dapp_subscription.test.ts @@ -56,10 +56,10 @@ describe('e2e_dapp_subscription', () => { const REFUND = 29n; // intentionally overpay the gas fee. This is the expected refund. const MAX_FEE = FEE_AMOUNT + REFUND; - const GAS_SETTINGS = GasSettings.new({ - da: { gasLimit: 5, teardownGasLimit: 3, maxFeePerGas: Fr.ONE }, - l1: { gasLimit: 5, teardownGasLimit: 3, maxFeePerGas: Fr.ONE }, - l2: { gasLimit: 5, teardownGasLimit: 3, maxFeePerGas: Fr.ONE }, + const GAS_SETTINGS = GasSettings.from({ + gasLimits: { daGas: 5, l1Gas: 5, l2Gas: 5 }, + teardownGasLimits: { daGas: 3, l1Gas: 3, l2Gas: 3 }, + maxFeesPerGas: { feePerDaGas: Fr.ONE, feePerL1Gas: Fr.ONE, feePerL2Gas: Fr.ONE }, inclusionFee: new Fr(6), }); diff --git a/yarn-project/end-to-end/src/e2e_fees.test.ts b/yarn-project/end-to-end/src/e2e_fees.test.ts index d6301790f78..e3ff4f75cd5 100644 --- a/yarn-project/end-to-end/src/e2e_fees.test.ts +++ b/yarn-project/end-to-end/src/e2e_fees.test.ts @@ -54,10 +54,10 @@ describe('e2e_fees', () => { let bananaPublicBalances: BalancesFn; let bananaPrivateBalances: BalancesFn; - const gasSettings = GasSettings.new({ - da: { gasLimit: 5, teardownGasLimit: 3, maxFeePerGas: Fr.ONE }, - l1: { gasLimit: 5, teardownGasLimit: 3, maxFeePerGas: Fr.ONE }, - l2: { gasLimit: 5, teardownGasLimit: 3, maxFeePerGas: Fr.ONE }, + const gasSettings = GasSettings.from({ + gasLimits: { daGas: 5, l1Gas: 5, l2Gas: 5 }, + teardownGasLimits: { daGas: 3, l1Gas: 3, l2Gas: 3 }, + maxFeesPerGas: { feePerDaGas: Fr.ONE, feePerL1Gas: Fr.ONE, feePerL2Gas: Fr.ONE }, inclusionFee: new Fr(6), }); diff --git a/yarn-project/end-to-end/src/flakey_e2e_account_init_fees.test.ts b/yarn-project/end-to-end/src/flakey_e2e_account_init_fees.test.ts index 0abceba6d0c..9b902e001a4 100644 --- a/yarn-project/end-to-end/src/flakey_e2e_account_init_fees.test.ts +++ b/yarn-project/end-to-end/src/flakey_e2e_account_init_fees.test.ts @@ -15,7 +15,7 @@ import { computeMessageSecretHash, deriveKeys, } from '@aztec/aztec.js'; -import { type AztecAddress, CompleteAddress, DimensionGasSettings, Fq, GasSettings } from '@aztec/circuits.js'; +import { type AztecAddress, CompleteAddress, Fq, GasSettings } from '@aztec/circuits.js'; import { TokenContract as BananaCoin, FPCContract, @@ -125,8 +125,12 @@ describe('e2e_fees_account_init', () => { afterAll(() => ctx.teardown()); beforeEach(() => { - const individualGasSettings = new DimensionGasSettings(2, 1, Fr.ONE); - gasSettings = new GasSettings(individualGasSettings, individualGasSettings, individualGasSettings, new Fr(5)); + gasSettings = GasSettings.from({ + gasLimits: { daGas: 2, l1Gas: 2, l2Gas: 2 }, + teardownGasLimits: { daGas: 1, l1Gas: 1, l2Gas: 1 }, + maxFeesPerGas: { feePerDaGas: Fr.ONE, feePerL1Gas: Fr.ONE, feePerL2Gas: Fr.ONE }, + inclusionFee: new Fr(5), + }); maxFee = 3n * 3n + 5n; actualFee = 1n; bobsSecretKey = Fr.random(); diff --git a/yarn-project/entrypoints/src/account_entrypoint.ts b/yarn-project/entrypoints/src/account_entrypoint.ts index fccd4800177..2b9a867578a 100644 --- a/yarn-project/entrypoints/src/account_entrypoint.ts +++ b/yarn-project/entrypoints/src/account_entrypoint.ts @@ -25,6 +25,7 @@ export class DefaultAccountEntrypoint implements EntrypointInterface { const abi = this.getEntrypointAbi(); const entrypointPackedArgs = PackedValues.fromValues(encodeArguments(abi, [appPayload, feePayload])); + const gasSettings = exec.fee?.gasSettings ?? GasSettings.default(); const appAuthWitness = await this.auth.createAuthWit(appPayload.hash()); const feeAuthWitness = await this.auth.createAuthWit(feePayload.hash()); @@ -33,10 +34,9 @@ export class DefaultAccountEntrypoint implements EntrypointInterface { argsHash: entrypointPackedArgs.hash, origin: this.address, functionData: FunctionData.fromAbi(abi), - txContext: TxContext.empty(this.chainId, this.version), + txContext: new TxContext(this.chainId, this.version, gasSettings), packedArguments: [...appPayload.packedArguments, ...feePayload.packedArguments, entrypointPackedArgs], authWitnesses: [appAuthWitness, feeAuthWitness], - gasSettings: exec.fee?.gasSettings ?? GasSettings.default(), }); return txRequest; diff --git a/yarn-project/entrypoints/src/dapp_entrypoint.ts b/yarn-project/entrypoints/src/dapp_entrypoint.ts index 55381e04cc0..22e16aeff71 100644 --- a/yarn-project/entrypoints/src/dapp_entrypoint.ts +++ b/yarn-project/entrypoints/src/dapp_entrypoint.ts @@ -30,7 +30,7 @@ export class DefaultDappEntrypoint implements EntrypointInterface { const abi = this.getEntrypointAbi(); const entrypointPackedArgs = PackedValues.fromValues(encodeArguments(abi, [payload, this.userAddress])); - + const gasSettings = exec.fee?.gasSettings ?? GasSettings.default(); const functionData = FunctionData.fromAbi(abi); const innerHash = computeInnerAuthWitHash([Fr.ZERO, functionData.selector.toField(), entrypointPackedArgs.hash]); @@ -47,10 +47,9 @@ export class DefaultDappEntrypoint implements EntrypointInterface { argsHash: entrypointPackedArgs.hash, origin: this.dappEntrypointAddress, functionData, - txContext: TxContext.empty(this.chainId, this.version), + txContext: new TxContext(this.chainId, this.version, gasSettings), packedArguments: [...payload.packedArguments, entrypointPackedArgs], authWitnesses: [authWitness], - gasSettings: exec.fee?.gasSettings ?? GasSettings.default(), }); return txRequest; diff --git a/yarn-project/noir-protocol-circuits-types/src/fixtures/nested-call-private-kernel-init.hex b/yarn-project/noir-protocol-circuits-types/src/fixtures/nested-call-private-kernel-init.hex index 77e9dca1224..4823cda732e 100644 --- a/yarn-project/noir-protocol-circuits-types/src/fixtures/nested-call-private-kernel-init.hex +++ b/yarn-project/noir-protocol-circuits-types/src/fixtures/nested-call-private-kernel-init.hex @@ -1 +1 @@ -0d27622958018fb0d6eddd432d5ab189772cb5a403cb80cfc1f9a9dc37cff37937889ba10107cc8d92c6d80f5119f3fa271649fbf9e8a9d3d92ee4790145cdf8bb984c86e600000000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000013b9aca0005f5e10000000000000000000000000000000000000000000000000000000000000000013b9aca0005f5e10000000000000000000000000000000000000000000000000000000000000000013b9aca0005f5e100000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010d27622958018fb0d6eddd432d5ab189772cb5a403cb80cfc1f9a9dc37cff37937889ba10100000000000000000000000000000000000000000000000000000000000000000d27622958018fb0d6eddd432d5ab189772cb5a403cb80cfc1f9a9dc37cff379000000000000000000000000000000000000000037889ba135a4e90035a4e90035a4e9000000000000013b9aca0005f5e10000000000000000000000000000000000000000000000000000000000000000013b9aca0005f5e10000000000000000000000000000000000000000000000000000000000000000013b9aca0005f5e10000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000007cc8d92c6d80f5119f3fa271649fbf9e8a9d3d92ee4790145cdf8bb984c86e60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008cc9e9f9c7e273402be86892aac8530b0b573a44d53b847042d2bf25393327b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000000016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000000000bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278000000800572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007a69000000000000000000000000000000000000000000000000000000000000000108cc9e9f9c7e273402be86892aac8530b0b573a44d53b847042d2bf25393327b0d27622958018fb0d6eddd432d5ab189772cb5a403cb80cfc1f9a9dc37cff37900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000800000000740000000f00000003515f3109623eb3c25aa5b16a1a79fd558bac7a7ce62c4560a8c537c77ce80dd339128d1d37b6582ee9e6df9567efb64313471dfa18f520f9ce53161b50dbf7731bc5f900000003515f322bc4cce83a486a92c92fd59bd84e0f92595baa639fc2ed86b00ffa0dfded2a092a669a3bdb7a273a015eda494457cc7ed5236f26cee330c290d45a33b9daa94800000003515f332729426c008c085a81bd34d8ef12dd31e80130339ef99d50013a89e4558eee6d0fa4ffe2ee7b7b62eb92608b2251ac31396a718f9b34978888789042b790a30100000003515f342be6b6824a913eb7a57b03cb1ee7bfb4de02f2f65fe8a4e97baa7766ddb353a82a8a25c49dc63778cd9fe96173f12a2bc77f3682f4c4448f98f1df82c75234a100000003515f351f85760d6ab567465aadc2f180af9eae3800e6958fec96aef53fd8a7b195d7c000c6267a0dd5cfc22b3fe804f53e266069c0e36f51885baec1e7e67650c62e170000000c515f41524954484d455449430d9d0f8ece2aa12012fa21e6e5c859e97bd5704e5c122064a66051294bc5e04213f61f54a0ebdf6fee4d4a6ecf693478191de0c2899bcd8e86a636c8d3eff43400000003515f43224a99d02c86336737c8dd5b746c40d2be6aead8393889a76a18d664029096e90f7fe81adcc92a74350eada9622ac453f49ebac24a066a1f83b394df54dfa0130000000c515f46495845445f42415345060e8a013ed289c2f9fd7473b04f6594b138ddb4b4cf6b901622a14088f04b8d2c83ff74fce56e3d5573b99c7b26d85d5046ce0c6559506acb7a675e7713eb3a00000007515f4c4f4749430721a91cb8da4b917e054f72147e1760cfe0ef3d45090ac0f4961d84ec1996961a25e787b26bd8b50b1a99450f77a424a83513c2b33af268cd253b0587ff50c700000003515f4d05dbd8623b8652511e1eb38d38887a69eceb082f807514f09e127237c5213b401b9325b48c6c225968002318095f89d0ef9cf629b2b7f0172e03bc39aacf6ed800000007515f52414e474504b57a3805e41df328f5ca9aefa40fad5917391543b7b65c6476e60b8f72e9ad07c92f3b3e11c8feae96dedc4b14a6226ef3201244f37cfc1ee5b96781f48d2b000000075349474d415f3125001d1954a18571eaa007144c5a567bb0d2be4def08a8be918b8c05e3b27d312c59ed41e09e144eab5de77ca89a2fd783be702a47c951d3112e3de02ce6e47c000000075349474d415f3223994e6a23618e60fa01c449a7ab88378709197e186d48d604bfb6931ffb15ad11c5ec7a0700570f80088fd5198ab5d5c227f2ad2a455a6edeec024156bb7beb000000075349474d415f3300cda5845f23468a13275d18bddae27c6bb189cf9aa95b6a03a0cb6688c7e8d829639b45cf8607c525cc400b55ebf90205f2f378626dc3406cc59b2d1b474fba000000075349474d415f342d299e7928496ea2d37f10b43afd6a80c90a33b483090d18069ffa275eedb2fc2f82121e8de43dc036d99b478b6227ceef34248939987a19011f065d8b5cef5c0000000010000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f1d2910fa7478af96ba0f336875a93c7f5f1e2eba63d9925014ad4ef5779f64ad1dae27cc7fe2af345f160253be3875d449a7e9ba6bd68747d87d4e7054b81115000000000000000000000000000000000000000000000000000000000000000019ffad41d477b4d4077d3edfe7eaf592f3b332d915dc68b41f2f1f370ebed632000000000000000000000000000000000000000000000000000000000000000027b1d0839a5b23baf12a8d195b18ac288fcf401afb2f70b8a4b529ede5fa9fed21dbfd1d029bf447152fcf89e355c334610d1632436ba170f738107266a715500bcd1f91cf7bdd471d0a30c58c4706f3fdab3807a954b8f5b5e3bfec87d001bb06e62084ee7b602fe9abc15632dda3269f56fb0c6e12519a2eb2ec897091919d03c9e2e67178ac638746f068907e6677b4cc7a9592ef234ab6ab518f17efffa000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 \ No newline at end of file +1208bb4077b4aab092065c8eb86b8d139689f93880a264325e000409ba39e47637889ba1010b86a1d0bdd5439df0c6963fb74bec68e8ed783ae6ba42134fbec27fdff1dbbf0000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000013b9aca003b9aca003b9aca0005f5e10005f5e10005f5e100000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001208bb4077b4aab092065c8eb86b8d139689f93880a264325e000409ba39e47637889ba10100000000000000000000000000000000000000000000000000000000000000001208bb4077b4aab092065c8eb86b8d139689f93880a264325e000409ba39e476000000000000000000000000000000000000000037889ba10000000000010b86a1d0bdd5439df0c6963fb74bec68e8ed783ae6ba42134fbec27fdff1dbbf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024d7113705d561cecb85ccf9461289286badb01289521111fe65c762b463e465000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000000016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000000000bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278000000800572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000013b9aca003b9aca003b9aca0005f5e10005f5e10005f5e100000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000024d7113705d561cecb85ccf9461289286badb01289521111fe65c762b463e4651208bb4077b4aab092065c8eb86b8d139689f93880a264325e000409ba39e47600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000800000000740000000f00000003515f3109623eb3c25aa5b16a1a79fd558bac7a7ce62c4560a8c537c77ce80dd339128d1d37b6582ee9e6df9567efb64313471dfa18f520f9ce53161b50dbf7731bc5f900000003515f322bc4cce83a486a92c92fd59bd84e0f92595baa639fc2ed86b00ffa0dfded2a092a669a3bdb7a273a015eda494457cc7ed5236f26cee330c290d45a33b9daa94800000003515f332729426c008c085a81bd34d8ef12dd31e80130339ef99d50013a89e4558eee6d0fa4ffe2ee7b7b62eb92608b2251ac31396a718f9b34978888789042b790a30100000003515f342be6b6824a913eb7a57b03cb1ee7bfb4de02f2f65fe8a4e97baa7766ddb353a82a8a25c49dc63778cd9fe96173f12a2bc77f3682f4c4448f98f1df82c75234a100000003515f351f85760d6ab567465aadc2f180af9eae3800e6958fec96aef53fd8a7b195d7c000c6267a0dd5cfc22b3fe804f53e266069c0e36f51885baec1e7e67650c62e170000000c515f41524954484d455449430d9d0f8ece2aa12012fa21e6e5c859e97bd5704e5c122064a66051294bc5e04213f61f54a0ebdf6fee4d4a6ecf693478191de0c2899bcd8e86a636c8d3eff43400000003515f43224a99d02c86336737c8dd5b746c40d2be6aead8393889a76a18d664029096e90f7fe81adcc92a74350eada9622ac453f49ebac24a066a1f83b394df54dfa0130000000c515f46495845445f42415345060e8a013ed289c2f9fd7473b04f6594b138ddb4b4cf6b901622a14088f04b8d2c83ff74fce56e3d5573b99c7b26d85d5046ce0c6559506acb7a675e7713eb3a00000007515f4c4f4749430721a91cb8da4b917e054f72147e1760cfe0ef3d45090ac0f4961d84ec1996961a25e787b26bd8b50b1a99450f77a424a83513c2b33af268cd253b0587ff50c700000003515f4d05dbd8623b8652511e1eb38d38887a69eceb082f807514f09e127237c5213b401b9325b48c6c225968002318095f89d0ef9cf629b2b7f0172e03bc39aacf6ed800000007515f52414e474504b57a3805e41df328f5ca9aefa40fad5917391543b7b65c6476e60b8f72e9ad07c92f3b3e11c8feae96dedc4b14a6226ef3201244f37cfc1ee5b96781f48d2b000000075349474d415f3125001d1954a18571eaa007144c5a567bb0d2be4def08a8be918b8c05e3b27d312c59ed41e09e144eab5de77ca89a2fd783be702a47c951d3112e3de02ce6e47c000000075349474d415f3223994e6a23618e60fa01c449a7ab88378709197e186d48d604bfb6931ffb15ad11c5ec7a0700570f80088fd5198ab5d5c227f2ad2a455a6edeec024156bb7beb000000075349474d415f3300cda5845f23468a13275d18bddae27c6bb189cf9aa95b6a03a0cb6688c7e8d829639b45cf8607c525cc400b55ebf90205f2f378626dc3406cc59b2d1b474fba000000075349474d415f342d299e7928496ea2d37f10b43afd6a80c90a33b483090d18069ffa275eedb2fc2f82121e8de43dc036d99b478b6227ceef34248939987a19011f065d8b5cef5c0000000010000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f1b2aa77d3f3c5d63609195083f85a6d13fbc2720ec0979f88710dd3238ade1e01dae27cc7fe2af345f160253be3875d449a7e9ba6bd68747d87d4e7054b8111527b1d0839a5b23baf12a8d195b18ac288fcf401afb2f70b8a4b529ede5fa9fed19ffad41d477b4d4077d3edfe7eaf592f3b332d915dc68b41f2f1f370ebed632000000000000000000000000000000000000000000000000000000000000000027b1d0839a5b23baf12a8d195b18ac288fcf401afb2f70b8a4b529ede5fa9fed21dbfd1d029bf447152fcf89e355c334610d1632436ba170f738107266a715500bcd1f91cf7bdd471d0a30c58c4706f3fdab3807a954b8f5b5e3bfec87d001bb06e62084ee7b602fe9abc15632dda3269f56fb0c6e12519a2eb2ec897091919d03c9e2e67178ac638746f068907e6677b4cc7a9592ef234ab6ab518f17efffa000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 diff --git a/yarn-project/noir-protocol-circuits-types/src/fixtures/nested-call-private-kernel-inner.hex b/yarn-project/noir-protocol-circuits-types/src/fixtures/nested-call-private-kernel-inner.hex index 15c347b813e..e4f3852113d 100644 --- a/yarn-project/noir-protocol-circuits-types/src/fixtures/nested-call-private-kernel-inner.hex +++ b/yarn-project/noir-protocol-circuits-types/src/fixtures/nested-call-private-kernel-inner.hex @@ -1 +1 @@ -0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000001000000bd300000bd400000bd500000bd600000bd700000bd800000bd900000bda00000bdb00000bdc00000bdd00000bde00000bdf00000be000000be100000be200000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013daceb117f1e04877221d14fc7403b63cf3850b153e8b6d155f83480c84674d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000008157bd672caa283c59831ddc26b03a29b01584331348e47656a8fbdeee87cd0962fdd03d17aec998c95b7d7bb2bf86e09a8ab19dbd72ff3cf36b0c03d03d17caa000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009b1e8feb235295c8b2c5cde8be3e0567ca1ec56b136b45b22f2ae64ab10343200000003000000000000000000000000000000000000000000000000000000000000000100cc62a4e0963228e1dc61a8d492a3ce5efe102a59f183d57d3c4c02365cc10d00089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c31864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f8000000030224d964eca00bbde1241ab70a698c277212bd33ac6318a14b746deff8a24587300000180023288a057e2a3458890dba31a91b8ef338433fb54a32e0952b4ab78073ebcb1000002000572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000001000000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000662114850000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000013b9aca0005f5e10000000000000000000000000000000000000000000000000000000000000000013b9aca0005f5e10000000000000000000000000000000000000000000000000000000000000000013b9aca0005f5e100000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000002a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000800000000740000000f00000003515f3109623eb3c25aa5b16a1a79fd558bac7a7ce62c4560a8c537c77ce80dd339128d1d37b6582ee9e6df9567efb64313471dfa18f520f9ce53161b50dbf7731bc5f900000003515f322bc4cce83a486a92c92fd59bd84e0f92595baa639fc2ed86b00ffa0dfded2a092a669a3bdb7a273a015eda494457cc7ed5236f26cee330c290d45a33b9daa94800000003515f332729426c008c085a81bd34d8ef12dd31e80130339ef99d50013a89e4558eee6d0fa4ffe2ee7b7b62eb92608b2251ac31396a718f9b34978888789042b790a30100000003515f342be6b6824a913eb7a57b03cb1ee7bfb4de02f2f65fe8a4e97baa7766ddb353a82a8a25c49dc63778cd9fe96173f12a2bc77f3682f4c4448f98f1df82c75234a100000003515f351f85760d6ab567465aadc2f180af9eae3800e6958fec96aef53fd8a7b195d7c000c6267a0dd5cfc22b3fe804f53e266069c0e36f51885baec1e7e67650c62e170000000c515f41524954484d455449430d9d0f8ece2aa12012fa21e6e5c859e97bd5704e5c122064a66051294bc5e04213f61f54a0ebdf6fee4d4a6ecf693478191de0c2899bcd8e86a636c8d3eff43400000003515f43224a99d02c86336737c8dd5b746c40d2be6aead8393889a76a18d664029096e90f7fe81adcc92a74350eada9622ac453f49ebac24a066a1f83b394df54dfa0130000000c515f46495845445f42415345060e8a013ed289c2f9fd7473b04f6594b138ddb4b4cf6b901622a14088f04b8d2c83ff74fce56e3d5573b99c7b26d85d5046ce0c6559506acb7a675e7713eb3a00000007515f4c4f4749430721a91cb8da4b917e054f72147e1760cfe0ef3d45090ac0f4961d84ec1996961a25e787b26bd8b50b1a99450f77a424a83513c2b33af268cd253b0587ff50c700000003515f4d05dbd8623b8652511e1eb38d38887a69eceb082f807514f09e127237c5213b401b9325b48c6c225968002318095f89d0ef9cf629b2b7f0172e03bc39aacf6ed800000007515f52414e474504b57a3805e41df328f5ca9aefa40fad5917391543b7b65c6476e60b8f72e9ad07c92f3b3e11c8feae96dedc4b14a6226ef3201244f37cfc1ee5b96781f48d2b000000075349474d415f3125001d1954a18571eaa007144c5a567bb0d2be4def08a8be918b8c05e3b27d312c59ed41e09e144eab5de77ca89a2fd783be702a47c951d3112e3de02ce6e47c000000075349474d415f3223994e6a23618e60fa01c449a7ab88378709197e186d48d604bfb6931ffb15ad11c5ec7a0700570f80088fd5198ab5d5c227f2ad2a455a6edeec024156bb7beb000000075349474d415f3300cda5845f23468a13275d18bddae27c6bb189cf9aa95b6a03a0cb6688c7e8d829639b45cf8607c525cc400b55ebf90205f2f378626dc3406cc59b2d1b474fba000000075349474d415f342d299e7928496ea2d37f10b43afd6a80c90a33b483090d18069ffa275eedb2fc2f82121e8de43dc036d99b478b6227ceef34248939987a19011f065d8b5cef5c0000000010000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f000000001e6b568badd4d62a636485e905dac7ebd6a3c6741ccdd70533395de789c7c88f2459707154b6cab4215fb7972c3e724ac296d7af4e7f94fbe442e7ead473da2e2a478a56fb98bf3ddf5ae94552a21ca9ae89e8ea803152f2954c71ee1f1febcd1edec315c79a4e7ab031346e957408fd653f7f4e491c955f8403ec871ace71ec0906bca1012fdd03d17aec998c95b7d7bb2bf86e09a8ab19dbd72ff3cf36b0c03d03d17caa1edec315c79a4e7ab031346e957408fd653f7f4e491c955f8403ec871ace71ec00000000000000000000000000000000000000000906bca135a4e90035a4e90035a4e9000000000000033b9aca0005f5e10000000000000000000000000000000000000000000000000000000000000000013b9aca0005f5e10000000000000000000000000000000000000000000000000000000000000000013b9aca0005f5e1000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000002898402da2fa95f47c47763fe5b171ff3155bd31e5af88d9823bccb26b6701542451ab56341b4067780469e41818b47f8fd45f4bd186f22ba4b4a1bb5d45a42d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000409b1e8feb235295c8b2c5cde8be3e0567ca1ec56b136b45b22f2ae64ab10343200000003000000000000000000000000000000000000000000000000000000000000000100cc62a4e0963228e1dc61a8d492a3ce5efe102a59f183d57d3c4c02365cc10d00089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c31864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f8000000030224d964eca00bbde1241ab70a698c277212bd33ac6318a14b746deff8a24587300000180023288a057e2a3458890dba31a91b8ef338433fb54a32e0952b4ab78073ebcb1000002000572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000001000000000000000000000000000000000000000000000000000000000000007a69000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000066211485000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000800000000740000000f00000003515f3109623eb3c25aa5b16a1a79fd558bac7a7ce62c4560a8c537c77ce80dd339128d1d37b6582ee9e6df9567efb64313471dfa18f520f9ce53161b50dbf7731bc5f900000003515f322bc4cce83a486a92c92fd59bd84e0f92595baa639fc2ed86b00ffa0dfded2a092a669a3bdb7a273a015eda494457cc7ed5236f26cee330c290d45a33b9daa94800000003515f332729426c008c085a81bd34d8ef12dd31e80130339ef99d50013a89e4558eee6d0fa4ffe2ee7b7b62eb92608b2251ac31396a718f9b34978888789042b790a30100000003515f342be6b6824a913eb7a57b03cb1ee7bfb4de02f2f65fe8a4e97baa7766ddb353a82a8a25c49dc63778cd9fe96173f12a2bc77f3682f4c4448f98f1df82c75234a100000003515f351f85760d6ab567465aadc2f180af9eae3800e6958fec96aef53fd8a7b195d7c000c6267a0dd5cfc22b3fe804f53e266069c0e36f51885baec1e7e67650c62e170000000c515f41524954484d455449430d9d0f8ece2aa12012fa21e6e5c859e97bd5704e5c122064a66051294bc5e04213f61f54a0ebdf6fee4d4a6ecf693478191de0c2899bcd8e86a636c8d3eff43400000003515f43224a99d02c86336737c8dd5b746c40d2be6aead8393889a76a18d664029096e90f7fe81adcc92a74350eada9622ac453f49ebac24a066a1f83b394df54dfa0130000000c515f46495845445f42415345060e8a013ed289c2f9fd7473b04f6594b138ddb4b4cf6b901622a14088f04b8d2c83ff74fce56e3d5573b99c7b26d85d5046ce0c6559506acb7a675e7713eb3a00000007515f4c4f4749430721a91cb8da4b917e054f72147e1760cfe0ef3d45090ac0f4961d84ec1996961a25e787b26bd8b50b1a99450f77a424a83513c2b33af268cd253b0587ff50c700000003515f4d05dbd8623b8652511e1eb38d38887a69eceb082f807514f09e127237c5213b401b9325b48c6c225968002318095f89d0ef9cf629b2b7f0172e03bc39aacf6ed800000007515f52414e474504b57a3805e41df328f5ca9aefa40fad5917391543b7b65c6476e60b8f72e9ad07c92f3b3e11c8feae96dedc4b14a6226ef3201244f37cfc1ee5b96781f48d2b000000075349474d415f3125001d1954a18571eaa007144c5a567bb0d2be4def08a8be918b8c05e3b27d312c59ed41e09e144eab5de77ca89a2fd783be702a47c951d3112e3de02ce6e47c000000075349474d415f3223994e6a23618e60fa01c449a7ab88378709197e186d48d604bfb6931ffb15ad11c5ec7a0700570f80088fd5198ab5d5c227f2ad2a455a6edeec024156bb7beb000000075349474d415f3300cda5845f23468a13275d18bddae27c6bb189cf9aa95b6a03a0cb6688c7e8d829639b45cf8607c525cc400b55ebf90205f2f378626dc3406cc59b2d1b474fba000000075349474d415f342d299e7928496ea2d37f10b43afd6a80c90a33b483090d18069ffa275eedb2fc2f82121e8de43dc036d99b478b6227ceef34248939987a19011f065d8b5cef5c0000000010000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f1cdaa2eb61b6efb48b22c9ef5bf3ee4b109df74054dfb6d5ab845c70a8397008265f771f4a6725790024cd25130aba2b529badd70c776209735034054e5d03b00000000000000000000000000000000000000000000000000000000000000000212ece512924f2d5704d8e364125acf1ac78d11e30ba58192837e098670e695d00000000000000000000000000000000000000000000000000000000000000002452a14c748981acff167dba9088770b6c2c2dc34677295a1974f2c247236ba11e904e4d0a67667f8faaa89198f5e89684e213bc99a83c3b20888d5854d3dd320bcd1f91cf7bdd471d0a30c58c4706f3fdab3807a954b8f5b5e3bfec87d001bb06e62084ee7b602fe9abc15632dda3269f56fb0c6e12519a2eb2ec897091919d03c9e2e67178ac638746f068907e6677b4cc7a9592ef234ab6ab518f17efffa000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 \ No newline at end of file +0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000001000000bd300000bd400000bd500000bd600000bd700000bd800000bd900000bda00000bdb00000bdc00000bdd00000bde00000bdf00000be000000be100000be2000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000015c446324f722bbc6584be77af92029c4a5638bcd9026b6bc507826a7e5c396000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000082c92e4a3a7b0eea72481f167f53201e45c8f0a269031748f35d7e6110d414e872dbb7298b3e49c346d4114d8d87f8347bdeae324221f4b8fcfca0b31631ffa2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002accd12fa83016ee308faa9afa34802e7d671a1cdcaca7500da76c0bbad572750000000300000000000000000000000000000000000000000000000000000000000000010036b711b054177001e7f65a938888b99148cd176cd91e6fba16ab5fe5c6aabb00089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c31864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f80000000302edb97f3c068922c2665f7af463e66bdf88b043f3c63a9e82bd3efec6104ae4f000001802f89cb7525bc847226eeb4fafdbdce54af6df1080ccb517b31596e29217b3314000002000572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000001000000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000662052bf000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000013b9aca003b9aca003b9aca0005f5e10005f5e10005f5e100000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000800000000740000000f00000003515f3109623eb3c25aa5b16a1a79fd558bac7a7ce62c4560a8c537c77ce80dd339128d1d37b6582ee9e6df9567efb64313471dfa18f520f9ce53161b50dbf7731bc5f900000003515f322bc4cce83a486a92c92fd59bd84e0f92595baa639fc2ed86b00ffa0dfded2a092a669a3bdb7a273a015eda494457cc7ed5236f26cee330c290d45a33b9daa94800000003515f332729426c008c085a81bd34d8ef12dd31e80130339ef99d50013a89e4558eee6d0fa4ffe2ee7b7b62eb92608b2251ac31396a718f9b34978888789042b790a30100000003515f342be6b6824a913eb7a57b03cb1ee7bfb4de02f2f65fe8a4e97baa7766ddb353a82a8a25c49dc63778cd9fe96173f12a2bc77f3682f4c4448f98f1df82c75234a100000003515f351f85760d6ab567465aadc2f180af9eae3800e6958fec96aef53fd8a7b195d7c000c6267a0dd5cfc22b3fe804f53e266069c0e36f51885baec1e7e67650c62e170000000c515f41524954484d455449430d9d0f8ece2aa12012fa21e6e5c859e97bd5704e5c122064a66051294bc5e04213f61f54a0ebdf6fee4d4a6ecf693478191de0c2899bcd8e86a636c8d3eff43400000003515f43224a99d02c86336737c8dd5b746c40d2be6aead8393889a76a18d664029096e90f7fe81adcc92a74350eada9622ac453f49ebac24a066a1f83b394df54dfa0130000000c515f46495845445f42415345060e8a013ed289c2f9fd7473b04f6594b138ddb4b4cf6b901622a14088f04b8d2c83ff74fce56e3d5573b99c7b26d85d5046ce0c6559506acb7a675e7713eb3a00000007515f4c4f4749430721a91cb8da4b917e054f72147e1760cfe0ef3d45090ac0f4961d84ec1996961a25e787b26bd8b50b1a99450f77a424a83513c2b33af268cd253b0587ff50c700000003515f4d05dbd8623b8652511e1eb38d38887a69eceb082f807514f09e127237c5213b401b9325b48c6c225968002318095f89d0ef9cf629b2b7f0172e03bc39aacf6ed800000007515f52414e474504b57a3805e41df328f5ca9aefa40fad5917391543b7b65c6476e60b8f72e9ad07c92f3b3e11c8feae96dedc4b14a6226ef3201244f37cfc1ee5b96781f48d2b000000075349474d415f3125001d1954a18571eaa007144c5a567bb0d2be4def08a8be918b8c05e3b27d312c59ed41e09e144eab5de77ca89a2fd783be702a47c951d3112e3de02ce6e47c000000075349474d415f3223994e6a23618e60fa01c449a7ab88378709197e186d48d604bfb6931ffb15ad11c5ec7a0700570f80088fd5198ab5d5c227f2ad2a455a6edeec024156bb7beb000000075349474d415f3300cda5845f23468a13275d18bddae27c6bb189cf9aa95b6a03a0cb6688c7e8d829639b45cf8607c525cc400b55ebf90205f2f378626dc3406cc59b2d1b474fba000000075349474d415f342d299e7928496ea2d37f10b43afd6a80c90a33b483090d18069ffa275eedb2fc2f82121e8de43dc036d99b478b6227ceef34248939987a19011f065d8b5cef5c0000000010000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f00000000011cb320164fe32db123539102d89f8c20c9f8e78beb24f6e6b564a3805439a80b4b27bbea6b1ff784b985e72ce90f5f3239909bb6b8964c35f569f6ef7b634811dd79e7bcc26d3ce8a77bdcb86a7bf9d8806437f08e66486b7bbb6bcccbe47611d5a9127ff97dc532b6e99387388252313599069bd0e5c76f2b9cedb9f24e550906bca1012dbb7298b3e49c346d4114d8d87f8347bdeae324221f4b8fcfca0b31631ffa2011d5a9127ff97dc532b6e99387388252313599069bd0e5c76f2b9cedb9f24e5500000000000000000000000000000000000000000906bca10000000000032898402da2fa95f47c47763fe5b171ff3155bd31e5af88d9823bccb26b6701542451ab56341b4067780469e41818b47f8fd45f4bd186f22ba4b4a1bb5d45a42d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000042accd12fa83016ee308faa9afa34802e7d671a1cdcaca7500da76c0bbad572750000000300000000000000000000000000000000000000000000000000000000000000010036b711b054177001e7f65a938888b99148cd176cd91e6fba16ab5fe5c6aabb00089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c31864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f80000000302edb97f3c068922c2665f7af463e66bdf88b043f3c63a9e82bd3efec6104ae4f000001802f89cb7525bc847226eeb4fafdbdce54af6df1080ccb517b31596e29217b3314000002000572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000001000000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000662052bf000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000013b9aca003b9aca003b9aca0005f5e10005f5e10005f5e100000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000800000000740000000f00000003515f3109623eb3c25aa5b16a1a79fd558bac7a7ce62c4560a8c537c77ce80dd339128d1d37b6582ee9e6df9567efb64313471dfa18f520f9ce53161b50dbf7731bc5f900000003515f322bc4cce83a486a92c92fd59bd84e0f92595baa639fc2ed86b00ffa0dfded2a092a669a3bdb7a273a015eda494457cc7ed5236f26cee330c290d45a33b9daa94800000003515f332729426c008c085a81bd34d8ef12dd31e80130339ef99d50013a89e4558eee6d0fa4ffe2ee7b7b62eb92608b2251ac31396a718f9b34978888789042b790a30100000003515f342be6b6824a913eb7a57b03cb1ee7bfb4de02f2f65fe8a4e97baa7766ddb353a82a8a25c49dc63778cd9fe96173f12a2bc77f3682f4c4448f98f1df82c75234a100000003515f351f85760d6ab567465aadc2f180af9eae3800e6958fec96aef53fd8a7b195d7c000c6267a0dd5cfc22b3fe804f53e266069c0e36f51885baec1e7e67650c62e170000000c515f41524954484d455449430d9d0f8ece2aa12012fa21e6e5c859e97bd5704e5c122064a66051294bc5e04213f61f54a0ebdf6fee4d4a6ecf693478191de0c2899bcd8e86a636c8d3eff43400000003515f43224a99d02c86336737c8dd5b746c40d2be6aead8393889a76a18d664029096e90f7fe81adcc92a74350eada9622ac453f49ebac24a066a1f83b394df54dfa0130000000c515f46495845445f42415345060e8a013ed289c2f9fd7473b04f6594b138ddb4b4cf6b901622a14088f04b8d2c83ff74fce56e3d5573b99c7b26d85d5046ce0c6559506acb7a675e7713eb3a00000007515f4c4f4749430721a91cb8da4b917e054f72147e1760cfe0ef3d45090ac0f4961d84ec1996961a25e787b26bd8b50b1a99450f77a424a83513c2b33af268cd253b0587ff50c700000003515f4d05dbd8623b8652511e1eb38d38887a69eceb082f807514f09e127237c5213b401b9325b48c6c225968002318095f89d0ef9cf629b2b7f0172e03bc39aacf6ed800000007515f52414e474504b57a3805e41df328f5ca9aefa40fad5917391543b7b65c6476e60b8f72e9ad07c92f3b3e11c8feae96dedc4b14a6226ef3201244f37cfc1ee5b96781f48d2b000000075349474d415f3125001d1954a18571eaa007144c5a567bb0d2be4def08a8be918b8c05e3b27d312c59ed41e09e144eab5de77ca89a2fd783be702a47c951d3112e3de02ce6e47c000000075349474d415f3223994e6a23618e60fa01c449a7ab88378709197e186d48d604bfb6931ffb15ad11c5ec7a0700570f80088fd5198ab5d5c227f2ad2a455a6edeec024156bb7beb000000075349474d415f3300cda5845f23468a13275d18bddae27c6bb189cf9aa95b6a03a0cb6688c7e8d829639b45cf8607c525cc400b55ebf90205f2f378626dc3406cc59b2d1b474fba000000075349474d415f342d299e7928496ea2d37f10b43afd6a80c90a33b483090d18069ffa275eedb2fc2f82121e8de43dc036d99b478b6227ceef34248939987a19011f065d8b5cef5c0000000010000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f2325f6e082ffa398877cb453883d5246d3cc9760420ac2d878b64a8277ef70c608d3564858ceb303e224cebd7e81a2b80832ecc3b9d8693dcf74f327fdac566127b1d0839a5b23baf12a8d195b18ac288fcf401afb2f70b8a4b529ede5fa9fed09aafc479d665f3656928406f719298279519dcb2a3f03ee9a3530aac5f8b95300000000000000000000000000000000000000000000000000000000000000002452a14c748981acff167dba9088770b6c2c2dc34677295a1974f2c247236ba11e904e4d0a67667f8faaa89198f5e89684e213bc99a83c3b20888d5854d3dd320bcd1f91cf7bdd471d0a30c58c4706f3fdab3807a954b8f5b5e3bfec87d001bb06e62084ee7b602fe9abc15632dda3269f56fb0c6e12519a2eb2ec897091919d03c9e2e67178ac638746f068907e6677b4cc7a9592ef234ab6ab518f17efffa000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 diff --git a/yarn-project/noir-protocol-circuits-types/src/fixtures/nested-call-private-kernel-ordering.hex b/yarn-project/noir-protocol-circuits-types/src/fixtures/nested-call-private-kernel-ordering.hex index c1231be5208..ceff8945d53 100644 --- a/yarn-project/noir-protocol-circuits-types/src/fixtures/nested-call-private-kernel-ordering.hex +++ b/yarn-project/noir-protocol-circuits-types/src/fixtures/nested-call-private-kernel-ordering.hex @@ -1 +1 @@ -0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000001000000bd300000bd400000bd500000bd600000bd700000bd800000bd900000bda00000bdb00000bdc00000bdd00000bde00000bdf00000be000000be100000be200000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ccd0272c6e45c4b05c1a84a83653d65c96e887eb2ebc63452743d3c7e1808660000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000158f5201c0037cd8557264add6c5043e596acc241ab0265661024a83ff299338000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001df4db6b8a78745d88326f389fa82444a7f96b95d7cc911f4c95ac9d28a8c42f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012e1e9a2149619391c5951865799264d481dd20fa0441ba2e432f0c49bcb65d02000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d8b9d32dadd05ec8b3e708f735d6beb18a96f084d747a0060dcc71b81f07c90000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013c000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000000016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000000000bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278000000800572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b0000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000013b9aca0005f5e10000000000000000000000000000000000000000000000000000000000000000013b9aca0005f5e10000000000000000000000000000000000000000000000000000000000000000013b9aca0005f5e100000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000002a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000800000000740000000f00000003515f3109623eb3c25aa5b16a1a79fd558bac7a7ce62c4560a8c537c77ce80dd339128d1d37b6582ee9e6df9567efb64313471dfa18f520f9ce53161b50dbf7731bc5f900000003515f322bc4cce83a486a92c92fd59bd84e0f92595baa639fc2ed86b00ffa0dfded2a092a669a3bdb7a273a015eda494457cc7ed5236f26cee330c290d45a33b9daa94800000003515f332729426c008c085a81bd34d8ef12dd31e80130339ef99d50013a89e4558eee6d0fa4ffe2ee7b7b62eb92608b2251ac31396a718f9b34978888789042b790a30100000003515f342be6b6824a913eb7a57b03cb1ee7bfb4de02f2f65fe8a4e97baa7766ddb353a82a8a25c49dc63778cd9fe96173f12a2bc77f3682f4c4448f98f1df82c75234a100000003515f351f85760d6ab567465aadc2f180af9eae3800e6958fec96aef53fd8a7b195d7c000c6267a0dd5cfc22b3fe804f53e266069c0e36f51885baec1e7e67650c62e170000000c515f41524954484d455449430d9d0f8ece2aa12012fa21e6e5c859e97bd5704e5c122064a66051294bc5e04213f61f54a0ebdf6fee4d4a6ecf693478191de0c2899bcd8e86a636c8d3eff43400000003515f43224a99d02c86336737c8dd5b746c40d2be6aead8393889a76a18d664029096e90f7fe81adcc92a74350eada9622ac453f49ebac24a066a1f83b394df54dfa0130000000c515f46495845445f42415345060e8a013ed289c2f9fd7473b04f6594b138ddb4b4cf6b901622a14088f04b8d2c83ff74fce56e3d5573b99c7b26d85d5046ce0c6559506acb7a675e7713eb3a00000007515f4c4f4749430721a91cb8da4b917e054f72147e1760cfe0ef3d45090ac0f4961d84ec1996961a25e787b26bd8b50b1a99450f77a424a83513c2b33af268cd253b0587ff50c700000003515f4d05dbd8623b8652511e1eb38d38887a69eceb082f807514f09e127237c5213b401b9325b48c6c225968002318095f89d0ef9cf629b2b7f0172e03bc39aacf6ed800000007515f52414e474504b57a3805e41df328f5ca9aefa40fad5917391543b7b65c6476e60b8f72e9ad07c92f3b3e11c8feae96dedc4b14a6226ef3201244f37cfc1ee5b96781f48d2b000000075349474d415f3125001d1954a18571eaa007144c5a567bb0d2be4def08a8be918b8c05e3b27d312c59ed41e09e144eab5de77ca89a2fd783be702a47c951d3112e3de02ce6e47c000000075349474d415f3223994e6a23618e60fa01c449a7ab88378709197e186d48d604bfb6931ffb15ad11c5ec7a0700570f80088fd5198ab5d5c227f2ad2a455a6edeec024156bb7beb000000075349474d415f3300cda5845f23468a13275d18bddae27c6bb189cf9aa95b6a03a0cb6688c7e8d829639b45cf8607c525cc400b55ebf90205f2f378626dc3406cc59b2d1b474fba000000075349474d415f342d299e7928496ea2d37f10b43afd6a80c90a33b483090d18069ffa275eedb2fc2f82121e8de43dc036d99b478b6227ceef34248939987a19011f065d8b5cef5c0000000010000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f000000002f0906b34e42aa88c9ac829fda9637a69992c1151d0ad73d3f38ad4e243d2afa0492d22613f2fee8cf576e977f7889a85d51ea07d50324a2ac6041bd7ee93c980a80ec0bbad4f3728d52a045a5dc34074944fb4306b4e2995d69cbc0c9954e370ccd0272c6e45c4b05c1a84a83653d65c96e887eb2ebc63452743d3c7e1808660000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f000000100000001100000012000000130000001400000015000000160000001700000018000000190000001a0000001b0000001c0000001d0000001e0000001f000000200000002100000022000000230000002400000025000000260000002700000028000000290000002a0000002b0000002c0000002d0000002e0000002f000000300000003100000032000000330000003400000035000000360000003700000038000000390000003a0000003b0000003c0000003d0000003e0000003f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000158f5201c0037cd8557264add6c5043e596acc241ab0265661024a83ff299338000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001df4db6b8a78745d88326f389fa82444a7f96b95d7cc911f4c95ac9d28a8c42f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012e1e9a2149619391c5951865799264d481dd20fa0441ba2e432f0c49bcb65d0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f000000100000001100000012000000130000001400000015000000160000001700000018000000190000001a0000001b0000001c0000001d0000001e0000001f000000200000002100000022000000230000002400000025000000260000002700000028000000290000002a0000002b0000002c0000002d0000002e0000002f000000300000003100000032000000330000003400000035000000360000003700000038000000390000003a0000003b0000003c0000003d0000003e0000003f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000008000000000000000800000000000000080000000000000008000000000000000800000000000000080000000000000008000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d8b9d32dadd05ec8b3e708f735d6beb18a96f084d747a0060dcc71b81f07c90000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000020000000300000004000000050000000600000007000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000200000003000000040000000500000006000000070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 \ No newline at end of file +0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000001000000bd300000bd400000bd500000bd600000bd700000bd800000bd900000bda00000bdb00000bdc00000bdd00000bde00000bdf00000be000000be100000be2000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003b86e17221b711698d6de43ec54eeda9af13bda30c33e3db70587d8ea551394000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007edb80abefedb368296b473533fdb0416d00182de5344e31d0e04814968c9b100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000213c2a87dc40aa23174f55b771deb93b71bf166eac35cd93eb59d5981bef0f370000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000128473c66178a71b790fd4402380f78251bed3d1ff81bf8b7efd327f62213e8f80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a4018558b08cedfd32828817f8c5baa517132c660cfb4cce7d830c0a2bdbd0000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013c000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000000016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000000000bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278000000800572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000013b9aca003b9aca003b9aca0005f5e10005f5e10005f5e100000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000800000000740000000f00000003515f3109623eb3c25aa5b16a1a79fd558bac7a7ce62c4560a8c537c77ce80dd339128d1d37b6582ee9e6df9567efb64313471dfa18f520f9ce53161b50dbf7731bc5f900000003515f322bc4cce83a486a92c92fd59bd84e0f92595baa639fc2ed86b00ffa0dfded2a092a669a3bdb7a273a015eda494457cc7ed5236f26cee330c290d45a33b9daa94800000003515f332729426c008c085a81bd34d8ef12dd31e80130339ef99d50013a89e4558eee6d0fa4ffe2ee7b7b62eb92608b2251ac31396a718f9b34978888789042b790a30100000003515f342be6b6824a913eb7a57b03cb1ee7bfb4de02f2f65fe8a4e97baa7766ddb353a82a8a25c49dc63778cd9fe96173f12a2bc77f3682f4c4448f98f1df82c75234a100000003515f351f85760d6ab567465aadc2f180af9eae3800e6958fec96aef53fd8a7b195d7c000c6267a0dd5cfc22b3fe804f53e266069c0e36f51885baec1e7e67650c62e170000000c515f41524954484d455449430d9d0f8ece2aa12012fa21e6e5c859e97bd5704e5c122064a66051294bc5e04213f61f54a0ebdf6fee4d4a6ecf693478191de0c2899bcd8e86a636c8d3eff43400000003515f43224a99d02c86336737c8dd5b746c40d2be6aead8393889a76a18d664029096e90f7fe81adcc92a74350eada9622ac453f49ebac24a066a1f83b394df54dfa0130000000c515f46495845445f42415345060e8a013ed289c2f9fd7473b04f6594b138ddb4b4cf6b901622a14088f04b8d2c83ff74fce56e3d5573b99c7b26d85d5046ce0c6559506acb7a675e7713eb3a00000007515f4c4f4749430721a91cb8da4b917e054f72147e1760cfe0ef3d45090ac0f4961d84ec1996961a25e787b26bd8b50b1a99450f77a424a83513c2b33af268cd253b0587ff50c700000003515f4d05dbd8623b8652511e1eb38d38887a69eceb082f807514f09e127237c5213b401b9325b48c6c225968002318095f89d0ef9cf629b2b7f0172e03bc39aacf6ed800000007515f52414e474504b57a3805e41df328f5ca9aefa40fad5917391543b7b65c6476e60b8f72e9ad07c92f3b3e11c8feae96dedc4b14a6226ef3201244f37cfc1ee5b96781f48d2b000000075349474d415f3125001d1954a18571eaa007144c5a567bb0d2be4def08a8be918b8c05e3b27d312c59ed41e09e144eab5de77ca89a2fd783be702a47c951d3112e3de02ce6e47c000000075349474d415f3223994e6a23618e60fa01c449a7ab88378709197e186d48d604bfb6931ffb15ad11c5ec7a0700570f80088fd5198ab5d5c227f2ad2a455a6edeec024156bb7beb000000075349474d415f3300cda5845f23468a13275d18bddae27c6bb189cf9aa95b6a03a0cb6688c7e8d829639b45cf8607c525cc400b55ebf90205f2f378626dc3406cc59b2d1b474fba000000075349474d415f342d299e7928496ea2d37f10b43afd6a80c90a33b483090d18069ffa275eedb2fc2f82121e8de43dc036d99b478b6227ceef34248939987a19011f065d8b5cef5c0000000010000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f0000000011bb983dfa4801cee58f690ce093fba18470c2259d0e843417a5653a086f6cf123f2eda1cd168f6327dcbcf5ff46942df0553219fa62a0bf3b242e8af2967d2226efd4d7263eb62754b969586b1a5e33cd6974f86cd40df4a8cf6dfbb7d87bcf03b86e17221b711698d6de43ec54eeda9af13bda30c33e3db70587d8ea5513940000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f000000100000001100000012000000130000001400000015000000160000001700000018000000190000001a0000001b0000001c0000001d0000001e0000001f000000200000002100000022000000230000002400000025000000260000002700000028000000290000002a0000002b0000002c0000002d0000002e0000002f000000300000003100000032000000330000003400000035000000360000003700000038000000390000003a0000003b0000003c0000003d0000003e0000003f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007edb80abefedb368296b473533fdb0416d00182de5344e31d0e04814968c9b100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000213c2a87dc40aa23174f55b771deb93b71bf166eac35cd93eb59d5981bef0f370000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000128473c66178a71b790fd4402380f78251bed3d1ff81bf8b7efd327f62213e8f800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f000000100000001100000012000000130000001400000015000000160000001700000018000000190000001a0000001b0000001c0000001d0000001e0000001f000000200000002100000022000000230000002400000025000000260000002700000028000000290000002a0000002b0000002c0000002d0000002e0000002f000000300000003100000032000000330000003400000035000000360000003700000038000000390000003a0000003b0000003c0000003d0000003e0000003f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000080000000000000008000000000000000800000000000000080000000000000008000000000000000800000000000000080000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a4018558b08cedfd32828817f8c5baa517132c660cfb4cce7d830c0a2bdbd0000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000020000000300000004000000050000000600000007000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000200000003000000040000000500000006000000070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 diff --git a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts index 15877cde1c9..51265ed43e6 100644 --- a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts +++ b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts @@ -15,7 +15,6 @@ import { ContentCommitment, type ContractStorageRead, type ContractStorageUpdateRequest, - DimensionGasSettings, EthAddress, type FUNCTION_TREE_HEIGHT, Fr, @@ -117,12 +116,10 @@ import { type CallRequest as CallRequestNoir, type CallerContext as CallerContextNoir, type CombinedConstantData as CombinedConstantDataNoir, - type DimensionGasSettings as DimensionGasSettingsNoir, type FunctionData as FunctionDataNoir, type FunctionLeafMembershipWitness as FunctionLeafMembershipWitnessNoir, type FunctionSelector as FunctionSelectorNoir, type GasFees as GasFeesNoir, - type Gas as GasNoir, type GasSettings as GasSettingsNoir, type L2ToL1Message as L2ToL1MessageNoir, type MaxBlockNumber as MaxBlockNumberNoir, @@ -153,6 +150,7 @@ import { type PrivateKernelInnerCircuitPrivateInputs as PrivateKernelInnerCircui import { type PrivateKernelTailToPublicCircuitPrivateInputs as PrivateKernelTailToPublicCircuitPrivateInputsNoir } from './types/private_kernel_tail_to_public_types.js'; import { type CombinedAccumulatedData as CombinedAccumulatedDataNoir, + type Gas as GasNoir, type GrumpkinPrivateKey as GrumpkinPrivateKeyNoir, type NullifierReadRequestHints as NullifierReadRequestHintsNoir, type NullifierSettledReadHint as NullifierSettledReadHintNoir, @@ -345,10 +343,9 @@ export function mapEthAddressFromNoir(address: NoirEthAddress): EthAddress { */ export function mapTxContextToNoir(txContext: TxContext): TxContextNoir { return { - is_fee_payment_tx: txContext.isFeePaymentTx, - is_rebate_payment_tx: txContext.isRebatePaymentTx, chain_id: mapFieldToNoir(txContext.chainId), version: mapFieldToNoir(txContext.version), + gas_settings: mapGasSettingsToNoir(txContext.gasSettings), }; } @@ -359,10 +356,9 @@ export function mapTxContextToNoir(txContext: TxContext): TxContextNoir { */ export function mapTxContextFromNoir(txContext: TxContextNoir): TxContext { return new TxContext( - txContext.is_fee_payment_tx, - txContext.is_rebate_payment_tx, mapFieldFromNoir(txContext.chain_id), mapFieldFromNoir(txContext.version), + mapGasSettingsFromNoir(txContext.gas_settings), ); } @@ -418,7 +414,6 @@ export function mapTxRequestToNoir(txRequest: TxRequest): TxRequestNoir { args_hash: mapFieldToNoir(txRequest.argsHash), tx_context: mapTxContextToNoir(txRequest.txContext), function_data: mapFunctionDataToNoir(txRequest.functionData), - gas_settings: mapGasSettingsToNoir(txRequest.gasSettings), }; } @@ -433,12 +428,9 @@ export function mapCallContextFromNoir(callContext: CallContextNoir): CallContex mapAztecAddressFromNoir(callContext.storage_contract_address), mapEthAddressFromNoir(callContext.portal_contract_address), mapFunctionSelectorFromNoir(callContext.function_selector), - mapGasFromNoir(callContext.gas_left), callContext.is_delegate_call, callContext.is_static_call, mapNumberFromNoir(callContext.side_effect_counter), - mapGasSettingsFromNoir(callContext.gas_settings), - mapFieldFromNoir(callContext.transaction_fee), ); } @@ -453,49 +445,30 @@ export function mapCallContextToNoir(callContext: CallContext): CallContextNoir storage_contract_address: mapAztecAddressToNoir(callContext.storageContractAddress), portal_contract_address: mapEthAddressToNoir(callContext.portalContractAddress), function_selector: mapFunctionSelectorToNoir(callContext.functionSelector), - gas_left: mapGasToNoir(callContext.gasLeft), is_delegate_call: callContext.isDelegateCall, is_static_call: callContext.isStaticCall, side_effect_counter: mapNumberToNoir(callContext.sideEffectCounter), - gas_settings: mapGasSettingsToNoir(callContext.gasSettings), - transaction_fee: mapFieldToNoir(callContext.transactionFee), }; } export function mapGasSettingsFromNoir(gasSettings: GasSettingsNoir): GasSettings { return new GasSettings( - mapDimensionGasSettingsFromNoir(gasSettings.da), - mapDimensionGasSettingsFromNoir(gasSettings.l1), - mapDimensionGasSettingsFromNoir(gasSettings.l2), + mapGasFromNoir(gasSettings.gas_limits), + mapGasFromNoir(gasSettings.teardown_gas_limits), + mapGasFeesFromNoir(gasSettings.max_fees_per_gas), mapFieldFromNoir(gasSettings.inclusion_fee), ); } export function mapGasSettingsToNoir(gasSettings: GasSettings): GasSettingsNoir { return { - da: mapDimensionGasSettingsToNoir(gasSettings.da), - l1: mapDimensionGasSettingsToNoir(gasSettings.l1), - l2: mapDimensionGasSettingsToNoir(gasSettings.l2), + gas_limits: mapGasToNoir(gasSettings.gasLimits), + teardown_gas_limits: mapGasToNoir(gasSettings.teardownGasLimits), + max_fees_per_gas: mapGasFeesToNoir(gasSettings.maxFeesPerGas), inclusion_fee: mapFieldToNoir(gasSettings.inclusionFee), }; } -export function mapDimensionGasSettingsFromNoir(dimensionGasSettings: DimensionGasSettingsNoir): DimensionGasSettings { - return new DimensionGasSettings( - mapNumberFromNoir(dimensionGasSettings.gas_limit), - mapNumberFromNoir(dimensionGasSettings.teardown_gas_limit), - mapFieldFromNoir(dimensionGasSettings.max_fee_per_gas), - ); -} - -export function mapDimensionGasSettingsToNoir(dimensionGasSettings: DimensionGasSettings): DimensionGasSettingsNoir { - return { - gas_limit: mapNumberToNoir(dimensionGasSettings.gasLimit), - teardown_gas_limit: mapNumberToNoir(dimensionGasSettings.teardownGasLimit), - max_fee_per_gas: mapFieldToNoir(dimensionGasSettings.maxFeePerGas), - }; -} - /** * Maps a caller context to a noir caller context. * @param callContext - The caller context. @@ -749,8 +722,7 @@ export function mapPrivateCircuitPublicInputsToNoir( encrypted_log_preimages_length: mapFieldToNoir(privateCircuitPublicInputs.encryptedLogPreimagesLength), unencrypted_log_preimages_length: mapFieldToNoir(privateCircuitPublicInputs.unencryptedLogPreimagesLength), historical_header: mapHeaderToNoir(privateCircuitPublicInputs.historicalHeader), - chain_id: mapFieldToNoir(privateCircuitPublicInputs.chainId), - version: mapFieldToNoir(privateCircuitPublicInputs.version), + tx_context: mapTxContextToNoir(privateCircuitPublicInputs.txContext), min_revertible_side_effect_counter: mapFieldToNoir(privateCircuitPublicInputs.minRevertibleSideEffectCounter), }; } @@ -1062,7 +1034,6 @@ export function mapPrivateAccumulatedDataFromNoir( MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, mapCallRequestFromNoir, ), - mapGasFromNoir(privateAccumulatedData.gas_used), ); } @@ -1077,7 +1048,6 @@ export function mapPrivateAccumulatedDataToNoir(data: PrivateAccumulatedData): P unencrypted_log_preimages_length: mapFieldToNoir(data.unencryptedLogPreimagesLength), private_call_stack: mapTuple(data.privateCallStack, mapCallRequestToNoir), public_call_stack: mapTuple(data.publicCallStack, mapCallRequestToNoir), - gas_used: mapGasToNoir(data.gasUsed), }; } @@ -1222,7 +1192,6 @@ export function mapCombinedConstantDataFromNoir(combinedConstantData: CombinedCo return new CombinedConstantData( mapHeaderFromNoir(combinedConstantData.historical_header), mapTxContextFromNoir(combinedConstantData.tx_context), - mapGasSettingsFromNoir(combinedConstantData.gas_settings), ); } @@ -1235,7 +1204,6 @@ export function mapCombinedConstantDataToNoir(combinedConstantData: CombinedCons return { historical_header: mapHeaderToNoir(combinedConstantData.historicalHeader), tx_context: mapTxContextToNoir(combinedConstantData.txContext), - gas_settings: mapGasSettingsToNoir(combinedConstantData.gasSettings), }; } @@ -1585,7 +1553,9 @@ export function mapPublicCircuitPublicInputsToNoir( historical_header: mapHeaderToNoir(publicInputs.historicalHeader), prover_address: mapAztecAddressToNoir(publicInputs.proverAddress), revert_code: mapRevertCodeToNoir(publicInputs.revertCode), - gas_left: mapGasToNoir(publicInputs.gasLeft), + start_gas_left: mapGasToNoir(publicInputs.startGasLeft), + end_gas_left: mapGasToNoir(publicInputs.endGasLeft), + transaction_fee: mapFieldToNoir(publicInputs.transactionFee), }; } /** diff --git a/yarn-project/protocol-contracts/src/instance-deployer/index.ts b/yarn-project/protocol-contracts/src/instance-deployer/index.ts index 9b9935da037..640b1314d02 100644 --- a/yarn-project/protocol-contracts/src/instance-deployer/index.ts +++ b/yarn-project/protocol-contracts/src/instance-deployer/index.ts @@ -8,7 +8,7 @@ export function getCanonicalInstanceDeployer(): ProtocolContract { const contract = getCanonicalProtocolContract(ContractInstanceDeployerArtifact, 1); if (!contract.address.equals(InstanceDeployerAddress)) { throw new Error( - `Incorrect address for contract deployer (got ${contract.address.toString()} but expected (${InstanceDeployerAddress.toString()}). Check DEPLOYER_CONTRACT_ADDRESS is set to the correct value in the constants files and run the protocol-contracts package tests.`, + `Incorrect address for contract deployer (got ${contract.address.toString()} but expected ${InstanceDeployerAddress.toString()}). Check DEPLOYER_CONTRACT_ADDRESS is set to the correct value in the constants files and run the protocol-contracts package tests.`, ); } return contract; diff --git a/yarn-project/pxe/src/pxe_service/test/pxe_test_suite.ts b/yarn-project/pxe/src/pxe_service/test/pxe_test_suite.ts index af5d40a371c..9b17eefc01c 100644 --- a/yarn-project/pxe/src/pxe_service/test/pxe_test_suite.ts +++ b/yarn-project/pxe/src/pxe_service/test/pxe_test_suite.ts @@ -10,7 +10,6 @@ import { CompleteAddress, Fr, FunctionData, - GasSettings, INITIAL_L2_BLOCK_NUM, Point, TxContext, @@ -131,7 +130,6 @@ export const pxeTestSuite = (testName: string, pxeSetup: () => Promise) => txContext: TxContext.empty(), packedArguments: [], authWitnesses: [], - gasSettings: GasSettings.default(), }); await expect(async () => await pxe.proveTx(txExecutionRequest, false)).rejects.toThrow( diff --git a/yarn-project/simulator/src/client/client_execution_context.ts b/yarn-project/simulator/src/client/client_execution_context.ts index 5d7d33375b4..1363fe615e7 100644 --- a/yarn-project/simulator/src/client/client_execution_context.ts +++ b/yarn-project/simulator/src/client/client_execution_context.ts @@ -16,9 +16,10 @@ import { FunctionSelector, type Header, NoteHashReadRequestMembershipWitness, + PrivateContextInputs, PublicCallRequest, type SideEffect, - TxContext, + type TxContext, } from '@aztec/circuits.js'; import { type Grumpkin } from '@aztec/circuits.js/barretenberg'; import { computePublicDataTreeLeafSlot, computeUniqueCommitment, siloNoteHash } from '@aztec/circuits.js/hash'; @@ -99,18 +100,14 @@ export class ClientExecutionContext extends ViewDataOracle { throw new Error('Invalid arguments size'); } - const fields = [ - ...this.callContext.toFields(), - ...this.historicalHeader.toFields(), - - this.txContext.chainId, - this.txContext.version, - - new Fr(this.sideEffectCounter), - - ...args, - ]; + const privateContextInputs = new PrivateContextInputs( + this.callContext, + this.historicalHeader, + this.txContext, + this.sideEffectCounter, + ); + const fields = [...privateContextInputs.toFields(), ...args]; return toACVMWitness(0, fields); } @@ -383,7 +380,7 @@ export class ClientExecutionContext extends ViewDataOracle { const targetArtifact = await this.db.getFunctionArtifact(targetContractAddress, functionSelector); const targetFunctionData = FunctionData.fromAbi(targetArtifact); - const derivedTxContext = new TxContext(false, false, this.txContext.chainId, this.txContext.version); + const derivedTxContext = this.txContext.clone(); const derivedCallContext = await this.deriveCallContext( targetContractAddress, @@ -497,12 +494,9 @@ export class ClientExecutionContext extends ViewDataOracle { isDelegateCall ? this.contractAddress : targetContractAddress, portalContractAddress, FunctionSelector.fromNameAndParameters(targetArtifact.name, targetArtifact.parameters), - this.callContext.gasLeft, // TODO(palla/gas): We should deduct DA and L1 gas used for the derived context isDelegateCall, isStaticCall, startSideEffectCounter, - this.callContext.gasSettings, - this.callContext.transactionFee, ); } diff --git a/yarn-project/simulator/src/client/private_execution.test.ts b/yarn-project/simulator/src/client/private_execution.test.ts index a605f2d9876..5cbf65ec767 100644 --- a/yarn-project/simulator/src/client/private_execution.test.ts +++ b/yarn-project/simulator/src/client/private_execution.test.ts @@ -90,10 +90,9 @@ describe('Private Execution test suite', () => { let trees: { [name: keyof typeof treeHeights]: AppendOnlyTree } = {}; const txContextFields: FieldsOf = { - isFeePaymentTx: false, - isRebatePaymentTx: false, chainId: new Fr(10), version: new Fr(20), + gasSettings: GasSettings.default(), }; const runSimulator = ({ @@ -120,7 +119,6 @@ describe('Private Execution test suite', () => { txContext: TxContext.from({ ...txContextFields, ...txContext }), packedArguments: [packedArguments], authWitnesses: [], - gasSettings: GasSettings.default(), }); return acirSimulator.run(txRequest, artifact, contractAddress, portalContractAddress, msgSender); @@ -799,10 +797,6 @@ describe('Private Execution test suite', () => { // Alter function data to match the manipulated oracle const functionData = FunctionData.fromAbi(childContractArtifact); - const transactionFee = new Fr(0); - const gasSettings = GasSettings.default(); - const gasLeft = gasSettings.getInitialAvailable(); - const publicCallRequest = PublicCallRequest.from({ contractAddress: childAddress, functionData: functionData, @@ -812,24 +806,18 @@ describe('Private Execution test suite', () => { storageContractAddress: childAddress, portalContractAddress: childPortalContractAddress, functionSelector: childSelector, - gasLeft, isDelegateCall: false, isStaticCall: false, sideEffectCounter: 1, - transactionFee, - gasSettings, }), parentCallContext: CallContext.from({ msgSender: parentAddress, storageContractAddress: parentAddress, portalContractAddress: EthAddress.ZERO, functionSelector: FunctionSelector.fromNameAndParameters(parentArtifact.name, parentArtifact.parameters), - gasLeft, isDelegateCall: false, isStaticCall: false, sideEffectCounter: 1, - transactionFee, - gasSettings, }), }); diff --git a/yarn-project/simulator/src/client/simulator.ts b/yarn-project/simulator/src/client/simulator.ts index 25bd77e8688..a191f1ff721 100644 --- a/yarn-project/simulator/src/client/simulator.ts +++ b/yarn-project/simulator/src/client/simulator.ts @@ -89,18 +89,14 @@ export class AcirSimulator { // reserve the first side effect for the tx hash (inserted by the private kernel) const startSideEffectCounter = 1; - const transactionFee = Fr.ZERO; const callContext = new CallContext( msgSender, contractAddress, portalContractAddress, FunctionSelector.fromNameAndParameters(entryPointArtifact.name, entryPointArtifact.parameters), - request.gasSettings.getInitialAvailable(), false, false, startSideEffectCounter, - request.gasSettings, - transactionFee, ); const context = new ClientExecutionContext( contractAddress, diff --git a/yarn-project/simulator/src/mocks/fixtures.ts b/yarn-project/simulator/src/mocks/fixtures.ts index 96d2c9cc39e..a68a2181eb8 100644 --- a/yarn-project/simulator/src/mocks/fixtures.ts +++ b/yarn-project/simulator/src/mocks/fixtures.ts @@ -9,7 +9,6 @@ import { Fr, FunctionData, Gas, - GasSettings, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, type PrivateKernelTailCircuitPublicInputs, type PublicCallRequest, @@ -67,18 +66,7 @@ export class PublicExecutionResultBuilder { revertReason?: SimulationError; }) { const builder = new PublicExecutionResultBuilder({ - callContext: new CallContext( - from, - tx.to, - EthAddress.ZERO, - tx.functionData.selector, - Gas.test(), - false, - false, - 0, - GasSettings.default(), - Fr.ZERO, - ), + callContext: new CallContext(from, tx.to, EthAddress.ZERO, tx.functionData.selector, false, false, 0), contractAddress: tx.to, functionData: tx.functionData, args: tx.args, @@ -133,7 +121,7 @@ export class PublicExecutionResultBuilder { endSideEffectCounter: Fr.ZERO, reverted: this._reverted, revertReason: this._revertReason, - gasLeft: this._execution.callContext.gasLeft.mul(0.9), + gasLeft: Gas.test(), // TODO(palla/gas): Set a proper value }; } } diff --git a/yarn-project/simulator/src/public/abstract_phase_manager.ts b/yarn-project/simulator/src/public/abstract_phase_manager.ts index 2f62dd004d4..fbd4d95435c 100644 --- a/yarn-project/simulator/src/public/abstract_phase_manager.ts +++ b/yarn-project/simulator/src/public/abstract_phase_manager.ts @@ -401,7 +401,10 @@ export abstract class AbstractPhaseManager { historicalHeader: this.historicalHeader, // TODO(@just-mitch): need better mapping from simulator to revert code. revertCode: result.reverted ? RevertCode.REVERTED : RevertCode.OK, - gasLeft: Gas.from(result.gasLeft), + // TODO(palla/gas): Set proper values + startGasLeft: Gas.test(), + endGasLeft: Gas.test(), + transactionFee: Fr.ZERO, }); } diff --git a/yarn-project/simulator/src/public/avm_executor.test.ts b/yarn-project/simulator/src/public/avm_executor.test.ts index 43c1dc7663c..036e8d4a00d 100644 --- a/yarn-project/simulator/src/public/avm_executor.test.ts +++ b/yarn-project/simulator/src/public/avm_executor.test.ts @@ -1,13 +1,4 @@ -import { - AztecAddress, - CallContext, - EthAddress, - FunctionData, - FunctionSelector, - Gas, - GasSettings, - type Header, -} from '@aztec/circuits.js'; +import { AztecAddress, CallContext, EthAddress, FunctionData, FunctionSelector, type Header } from '@aztec/circuits.js'; import { makeHeader } from '@aztec/circuits.js/testing'; import { randomInt } from '@aztec/foundation/crypto'; import { Fr } from '@aztec/foundation/fields'; @@ -31,12 +22,9 @@ describe('AVM WitGen and Proof Generation', () => { storageContractAddress: AztecAddress.random(), portalContractAddress: EthAddress.random(), functionSelector: FunctionSelector.empty(), - gasLeft: Gas.test(), isDelegateCall: false, isStaticCall: false, sideEffectCounter: 0, - gasSettings: GasSettings.empty(), - transactionFee: Fr.ZERO, }); const contractAddress = AztecAddress.random(); diff --git a/yarn-project/simulator/src/public/execution.ts b/yarn-project/simulator/src/public/execution.ts index 8b16f6c8e49..871002e9635 100644 --- a/yarn-project/simulator/src/public/execution.ts +++ b/yarn-project/simulator/src/public/execution.ts @@ -62,7 +62,7 @@ export interface PublicExecutionResult { */ revertReason: SimulationError | undefined; /** How much gas was left after this public execution. */ - gasLeft: Gas; + gasLeft: Gas; // TODO(palla/gas): Check this field } /** diff --git a/yarn-project/simulator/src/public/executor.ts b/yarn-project/simulator/src/public/executor.ts index 412ea1b973b..57710e7c5a8 100644 --- a/yarn-project/simulator/src/public/executor.ts +++ b/yarn-project/simulator/src/public/executor.ts @@ -66,7 +66,7 @@ async function executePublicFunctionAvm(executionContext: PublicExecutionContext executionContext.globalVariables, ); - const machineState = new AvmMachineState(executionContext.execution.callContext.gasLeft); + const machineState = new AvmMachineState(Gas.test()); // TODO(palla/gas): Set proper values const context = new AvmContext(worldStateJournal, executionEnv, machineState); const simulator = new AvmSimulator(context); @@ -196,7 +196,7 @@ async function executePublicFunctionAcvm( const nestedExecutions = context.getNestedExecutions(); const unencryptedLogs = context.getUnencryptedLogs(); - const gasLeft = context.execution.callContext.gasLeft; // No gas metering for ACVM + const gasLeft = Gas.test(); // TODO(palla/gas): Set proper value return { execution, diff --git a/yarn-project/simulator/src/public/index.test.ts b/yarn-project/simulator/src/public/index.test.ts index 6f74908fadd..5a295aef6cb 100644 --- a/yarn-project/simulator/src/public/index.test.ts +++ b/yarn-project/simulator/src/public/index.test.ts @@ -3,9 +3,7 @@ import { AppendOnlyTreeSnapshot, CallContext, FunctionData, - Gas, GasFees, - GasSettings, GlobalVariables, type Header, L1_TO_L2_MSG_TREE_HEIGHT, @@ -48,7 +46,6 @@ describe('ACIR public execution simulator', () => { let executor: PublicExecutor; let header: Header; - const gasLeft = new Gas(1e9, 1e9, 1e9); const globalVariables = GlobalVariables.empty(); beforeEach(() => { @@ -93,14 +90,11 @@ describe('ACIR public execution simulator', () => { CallContext.from({ storageContractAddress, msgSender: AztecAddress.random(), - gasLeft, portalContractAddress: EthAddress.random(), functionSelector: FunctionSelector.empty(), isDelegateCall: false, isStaticCall: false, sideEffectCounter: 0, - gasSettings: GasSettings.empty(), - transactionFee: Fr.ZERO, ...overrides, }); diff --git a/yarn-project/simulator/src/public/public_execution_context.ts b/yarn-project/simulator/src/public/public_execution_context.ts index adf3e893484..96a5627ca21 100644 --- a/yarn-project/simulator/src/public/public_execution_context.ts +++ b/yarn-project/simulator/src/public/public_execution_context.ts @@ -3,8 +3,10 @@ import { CallContext, FunctionData, type FunctionSelector, + Gas, type GlobalVariables, type Header, + PublicContextInputs, } from '@aztec/circuits.js'; import { type AztecAddress } from '@aztec/foundation/aztec-address'; import { EthAddress } from '@aztec/foundation/eth-address'; @@ -56,14 +58,15 @@ export class PublicExecutionContext extends TypedOracle { */ public getInitialWitness(witnessStartIndex = 0) { const { callContext, args } = this.execution; - const fields = [ - ...callContext.toFields(), - ...this.header.toFields(), - ...this.globalVariables.toFields(), - new Fr(this.sideEffectCounter.current()), - ...args, - ]; - + const publicContextInputs = new PublicContextInputs( + callContext, + this.header, + this.globalVariables, + this.sideEffectCounter.current(), + Gas.test(), // TODO(palla/gas): Set proper values + new Fr(0), + ); + const fields = [...publicContextInputs.toFields(), ...args]; return toACVMWitness(witnessStartIndex, fields); } @@ -196,18 +199,14 @@ export class PublicExecutionContext extends TypedOracle { const portalAddress = (await this.contractsDb.getPortalContractAddress(targetContractAddress)) ?? EthAddress.ZERO; const functionData = new FunctionData(functionSelector, /*isPrivate=*/ false); - const { transactionFee, gasSettings, gasLeft } = this.execution.callContext; const callContext = CallContext.from({ msgSender: isDelegateCall ? this.execution.callContext.msgSender : this.execution.contractAddress, storageContractAddress: isDelegateCall ? this.execution.contractAddress : targetContractAddress, portalContractAddress: portalAddress, functionSelector, - gasLeft, // Propagate the same gas left as when we started since ACVM public functions don't have any metering isDelegateCall, isStaticCall, sideEffectCounter, - gasSettings, - transactionFee, }); const nestedExecution: PublicExecution = { diff --git a/yarn-project/simulator/src/public/transitional_adaptors.ts b/yarn-project/simulator/src/public/transitional_adaptors.ts index 81cd68ebab0..204db746fd8 100644 --- a/yarn-project/simulator/src/public/transitional_adaptors.ts +++ b/yarn-project/simulator/src/public/transitional_adaptors.ts @@ -5,7 +5,7 @@ import { ContractStorageRead, ContractStorageUpdateRequest, FunctionData, - Gas, + GasSettings, type GlobalVariables, type Header, L2ToL1Message, @@ -52,8 +52,8 @@ export function createAvmExecutionEnvironment( current.callContext.isStaticCall, current.callContext.isDelegateCall, current.args, - current.callContext.gasSettings, - current.callContext.transactionFee, + GasSettings.default(), // TODO(palla/gas): Set proper values + Fr.ZERO, // TODO(palla/gas): Set proper values current.functionData.selector, ); } @@ -65,12 +65,9 @@ export function createPublicExecutionContext(avmContext: AvmContext, calldata: F storageContractAddress: avmContext.environment.storageAddress, portalContractAddress: avmContext.environment.portal, functionSelector: avmContext.environment.temporaryFunctionSelector, - gasLeft: Gas.from(avmContext.machineState.gasLeft), isDelegateCall: avmContext.environment.isDelegateCall, isStaticCall: avmContext.environment.isStaticCall, sideEffectCounter: sideEffectCounter, - gasSettings: avmContext.environment.gasSettings, - transactionFee: avmContext.environment.transactionFee, }); const functionData = new FunctionData(avmContext.environment.temporaryFunctionSelector, /*isPrivate=*/ false); const execution: PublicExecution = { From 6a5ad7ccfe7fc17237a5a6237493c1fbb6af6d53 Mon Sep 17 00:00:00 2001 From: Facundo Date: Fri, 19 Apr 2024 14:58:59 +0100 Subject: [PATCH 035/102] refactor(aztec-nr)!: unencrypted logs go behind context (#5871) Moving unencrypted logs behind context. --- .../writing_contracts/events/emit_event.md | 8 +--- docs/docs/misc/migration_notes.md | 14 ++++++ .../aztec-nr/aztec/src/context/avm_context.nr | 6 +-- .../aztec-nr/aztec/src/context/interface.nr | 3 -- .../aztec/src/context/private_context.nr | 29 ++++++++++-- .../aztec/src/context/public_context.nr | 14 +++--- noir-projects/aztec-nr/aztec/src/log.nr | 19 -------- .../aztec-nr/aztec/src/oracle/logs.nr | 16 ------- noir-projects/aztec-nr/aztec/src/prelude.nr | 3 +- .../contracts/auth_contract/src/main.nr | 5 +-- .../benchmarking_contract/src/main.nr | 7 +-- .../contracts/child_contract/src/main.nr | 15 +++---- .../src/main.nr | 10 ++--- .../src/main.nr | 4 +- .../crowdfunding_contract/src/main.nr | 3 +- .../delegated_on_contract/src/main.nr | 4 +- .../contracts/delegator_contract/src/main.nr | 5 +-- .../contracts/test_contract/src/main.nr | 44 +++++++++---------- 18 files changed, 90 insertions(+), 119 deletions(-) diff --git a/docs/docs/developers/contracts/writing_contracts/events/emit_event.md b/docs/docs/developers/contracts/writing_contracts/events/emit_event.md index 0c4204b3d67..86794f3afed 100644 --- a/docs/docs/developers/contracts/writing_contracts/events/emit_event.md +++ b/docs/docs/developers/contracts/writing_contracts/events/emit_event.md @@ -96,15 +96,9 @@ They can be emitted by both public and private functions. - Unencrypted events are currently **NOT** linked to the contract emitting them, so it is practically a [`debug_log`](../oracles/main.md#a-few-useful-inbuilt-oracles). ::: -### Import library - -To emit unencrypted logs first import the `emit_unencrypted_log` utility function inside your contract: - -#include_code unencrypted_import /noir-projects/noir-contracts/contracts/test_contract/src/main.nr rust - ### Call emit_unencrypted_log -After importing, you can call the function: +To emit unencrypted logs you don't need to import any library. You call the context method `emit_unencrypted_log`: #include_code emit_unencrypted /noir-projects/noir-contracts/contracts/test_contract/src/main.nr rust diff --git a/docs/docs/misc/migration_notes.md b/docs/docs/misc/migration_notes.md index fe424ddb820..f906c8ad3be 100644 --- a/docs/docs/misc/migration_notes.md +++ b/docs/docs/misc/migration_notes.md @@ -117,6 +117,20 @@ Note that gas limits are not yet enforced. For now, it is suggested you use `dep Note that this is not required when enqueuing a public function from a private one, since top-level enqueued public functions will always consume all gas available for the transaction, as it is not possible to handle any out-of-gas errors. +### [Aztec.nr] Emmiting unencrypted logs + +The `emit_unencrypted_logs` function is now a context method. + +```diff +- use dep::aztec::log::emit_unencrypted_log; +- use dep::aztec::log::emit_unencrypted_log_from_private; + +- emit_unencrypted_log(context, log1); +- emit_unencrypted_log_from_private(context, log2); ++ context.emit_unencrypted_log(log1); ++ context.emit_unencrypted_log(log2); +``` + ## 0.33 ### [Aztec.nr] Storage struct annotation diff --git a/noir-projects/aztec-nr/aztec/src/context/avm_context.nr b/noir-projects/aztec-nr/aztec/src/context/avm_context.nr index c4a6350af39..0a457fee204 100644 --- a/noir-projects/aztec-nr/aztec/src/context/avm_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/avm_context.nr @@ -121,14 +121,10 @@ impl PublicContextInterface for AvmContext { } fn emit_unencrypted_log(&mut self, log: T) { - let event_selector = 0; + let event_selector = 5; // Matches current PublicContext. self.emit_unencrypted_log(event_selector, log); } - fn push_unencrypted_log(&mut self, log_hash: Field) { - assert(false, "'push_unencrypted_log' not required for avm - use emit_unencrypted_log!"); - } - fn consume_l1_to_l2_message(&mut self, content: Field, secret: Field, sender: EthAddress, leaf_index: Field) { let secret_hash = compute_secret_hash(secret); let message_hash = compute_message_hash( diff --git a/noir-projects/aztec-nr/aztec/src/context/interface.nr b/noir-projects/aztec-nr/aztec/src/context/interface.nr index a076158d71d..83494f8153e 100644 --- a/noir-projects/aztec-nr/aztec/src/context/interface.nr +++ b/noir-projects/aztec-nr/aztec/src/context/interface.nr @@ -35,9 +35,6 @@ trait PublicContextInterface { fn message_portal(&mut self, recipient: EthAddress, content: Field); fn consume_l1_to_l2_message(&mut self, content: Field, secret: Field, sender: EthAddress, leaf_index: Field); fn emit_unencrypted_log(&mut self, log: T); - // TODO(1165) Merge push_unencrypted_log into emit_unencrypted_log, since oracle call - // in PublicContext will no longer be needed for extracting log hash - fn push_unencrypted_log(&mut self, log_hash: Field); fn call_public_function( self: &mut Self, contract_address: AztecAddress, diff --git a/noir-projects/aztec-nr/aztec/src/context/private_context.nr b/noir-projects/aztec-nr/aztec/src/context/private_context.nr index a65da233b71..a5c7f782e38 100644 --- a/noir-projects/aztec-nr/aztec/src/context/private_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/private_context.nr @@ -3,8 +3,8 @@ use crate::{ messaging::process_l1_to_l2_message, hash::{hash_args_array, ArgsHasher}, oracle::{ arguments, returns, call_private_function::call_private_function_internal, - enqueue_public_function_call::enqueue_public_function_call_internal, - header::get_header_at, nullifier_key::{get_nullifier_keys, NullifierKeys} + enqueue_public_function_call::enqueue_public_function_call_internal, header::get_header_at, + nullifier_key::{get_nullifier_keys, NullifierKeys} } }; use dep::protocol_types::{ @@ -271,7 +271,14 @@ impl PrivateContext { // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1165) } - pub fn push_unencrypted_log(&mut self, log_hash: Field) { + // TODO: We might want to remove this since emitting unencrypted logs from private functions is violating privacy. + // --> might be a better approach to force devs to make a public function call that emits the log if needed then + // it would be less easy to accidentally leak information. + // If we decide to keep this function around would make sense to wait for traits and then merge it with emit_unencrypted_log. + pub fn emit_unencrypted_log(&mut self, log: T) { + let event_selector = 5; // TODO: compute actual event selector. + let log_hash = emit_unencrypted_log_private_internal(self.this_address(), event_selector, log); + let side_effect = SideEffect { value: log_hash, counter: self.side_effect_counter }; self.unencrypted_logs_hashes.push(side_effect); self.side_effect_counter = self.side_effect_counter + 1; @@ -591,3 +598,19 @@ impl PackedReturns { Deserialize::deserialize(unpacked) } } + +#[oracle(emitUnencryptedLog)] +fn emit_unencrypted_log_oracle_private( + _contract_address: AztecAddress, + _event_selector: Field, + _message: T +) -> Field {} + +unconstrained pub fn emit_unencrypted_log_private_internal( + contract_address: AztecAddress, + event_selector: Field, + message: T +) -> Field { + // https://github.com/AztecProtocol/aztec-packages/issues/885 + emit_unencrypted_log_oracle_private(contract_address, event_selector, message) +} diff --git a/noir-projects/aztec-nr/aztec/src/context/public_context.nr b/noir-projects/aztec-nr/aztec/src/context/public_context.nr index e37c80eb4f6..eab245d65ab 100644 --- a/noir-projects/aztec-nr/aztec/src/context/public_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/public_context.nr @@ -283,14 +283,11 @@ impl PublicContextInterface for PublicContext { } fn emit_unencrypted_log(&mut self, log: T) { - let _void1 = self; - let _void2 = log; + let event_selector = 5; + let log_hash = emit_unencrypted_log_oracle(self.this_address(), event_selector, log); // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1165) // Once we hash inside circuits, this replaces push_unencrypted_log // For now we need an oracle to get the hash - } - - fn push_unencrypted_log(&mut self, log_hash: Field) { let side_effect = SideEffect { value: log_hash, counter: self.side_effect_counter }; self.unencrypted_logs_hashes.push(side_effect); self.side_effect_counter = self.side_effect_counter + 1; @@ -359,6 +356,13 @@ impl Empty for PublicContext { #[oracle(checkNullifierExists)] fn nullifier_exists_oracle(nullifier: Field) -> Field {} +#[oracle(emitUnencryptedLog)] +fn emit_unencrypted_log_oracle( + _contract_address: AztecAddress, + _event_selector: Field, + _message: T +) -> Field {} + struct FunctionReturns { values: [Field; N] } diff --git a/noir-projects/aztec-nr/aztec/src/log.nr b/noir-projects/aztec-nr/aztec/src/log.nr index 0334f1407a7..c3e3f361f59 100644 --- a/noir-projects/aztec-nr/aztec/src/log.nr +++ b/noir-projects/aztec-nr/aztec/src/log.nr @@ -19,22 +19,3 @@ pub fn emit_encrypted_log( ); context.push_encrypted_log(log_hash); } - -pub fn emit_unencrypted_log(context: &mut PublicContext, log: T) { - let contract_address = context.this_address(); - let event_selector = 5; // TODO: compute actual event selector. - let log_hash = oracle::logs::emit_unencrypted_log(contract_address, event_selector, log); - context.push_unencrypted_log(log_hash); -} - -// TODO: We might want to remove this since emitting unencrypted logs from private functions is violating privacy. -// --> might be a better approach to force devs to make a public function call that emits the log if needed then -// it would be less easy to accidentally leak information. -// If we decide to keep this function around would make sense to wait for traits and then merge it with emit_unencrypted_log. -pub fn emit_unencrypted_log_from_private(context: &mut PrivateContext, log: T) { - let contract_address = context.this_address(); - let event_selector = 5; // TODO: compute actual event selector. - let log_hash = oracle::logs::emit_unencrypted_log(contract_address, event_selector, log); - context.push_unencrypted_log(log_hash); - // context.accumulate_unencrypted_logs(log); -} diff --git a/noir-projects/aztec-nr/aztec/src/oracle/logs.nr b/noir-projects/aztec-nr/aztec/src/oracle/logs.nr index 6a95e6897e8..849a5726c9f 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/logs.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/logs.nr @@ -25,19 +25,3 @@ unconstrained pub fn emit_encrypted_log( preimage ) } - -#[oracle(emitUnencryptedLog)] -fn emit_unencrypted_log_oracle( - _contract_address: AztecAddress, - _event_selector: Field, - _message: T -) -> Field {} - -unconstrained pub fn emit_unencrypted_log( - contract_address: AztecAddress, - event_selector: Field, - message: T -) -> Field { - // https://github.com/AztecProtocol/aztec-packages/issues/885 - emit_unencrypted_log_oracle(contract_address, event_selector, message) -} diff --git a/noir-projects/aztec-nr/aztec/src/prelude.nr b/noir-projects/aztec-nr/aztec/src/prelude.nr index 70adb81dd1f..08177f65e7d 100644 --- a/noir-projects/aztec-nr/aztec/src/prelude.nr +++ b/noir-projects/aztec-nr/aztec/src/prelude.nr @@ -9,8 +9,7 @@ use crate::{ public_immutable::PublicImmutable, public_mutable::PublicMutable, private_set::PrivateSet, shared_immutable::SharedImmutable, storage::Storable }, - log::{emit_unencrypted_log, emit_encrypted_log}, - context::{PrivateContext, PackedReturns, FunctionReturns}, + log::emit_encrypted_log, context::{PrivateContext, PackedReturns, FunctionReturns}, note::{ note_header::NoteHeader, note_interface::NoteInterface, note_getter_options::NoteGetterOptions, note_viewer_options::NoteViewerOptions, diff --git a/noir-projects/noir-contracts/contracts/auth_contract/src/main.nr b/noir-projects/noir-contracts/contracts/auth_contract/src/main.nr index 36df4cbeb45..765107b0ea9 100644 --- a/noir-projects/noir-contracts/contracts/auth_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/auth_contract/src/main.nr @@ -2,10 +2,7 @@ // publicly store the address of an authorized account that can call private functions. contract Auth { use dep::aztec::protocol_types::address::AztecAddress; - use dep::aztec::{ - log::{emit_unencrypted_log, emit_unencrypted_log_from_private}, - state_vars::{PublicImmutable, SharedMutable} - }; + use dep::aztec::state_vars::{PublicImmutable, SharedMutable}; // Authorizing a new address has a certain block delay before it goes into effect. global CHANGE_AUTHORIZED_DELAY_BLOCKS = 5; diff --git a/noir-projects/noir-contracts/contracts/benchmarking_contract/src/main.nr b/noir-projects/noir-contracts/contracts/benchmarking_contract/src/main.nr index 38511fc3a9f..a8b9f34d36b 100644 --- a/noir-projects/noir-contracts/contracts/benchmarking_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/benchmarking_contract/src/main.nr @@ -4,10 +4,7 @@ // subject being tested as unmodified as possible so we can detect metric changes that contract Benchmarking { - use dep::aztec::prelude::{ - AztecAddress, FunctionSelector, NoteHeader, NoteGetterOptions, emit_unencrypted_log, Map, - PublicMutable, PrivateSet - }; + use dep::aztec::prelude::{AztecAddress, FunctionSelector, NoteHeader, NoteGetterOptions, Map, PublicMutable, PrivateSet}; use dep::value_note::{utils::{increment, decrement}, value_note::ValueNote}; use dep::aztec::{context::{Context, gas::GasOpts}}; @@ -50,6 +47,6 @@ contract Benchmarking { // Emits a public log. #[aztec(public)] fn broadcast(owner: AztecAddress) { - emit_unencrypted_log(&mut context, storage.balances.at(owner).read()); + context.emit_unencrypted_log(storage.balances.at(owner).read()); } } diff --git a/noir-projects/noir-contracts/contracts/child_contract/src/main.nr b/noir-projects/noir-contracts/contracts/child_contract/src/main.nr index 15117e2dbfa..ff8e270a2a0 100644 --- a/noir-projects/noir-contracts/contracts/child_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/child_contract/src/main.nr @@ -1,9 +1,6 @@ // A contract used along with `Parent` contract to test nested calls. contract Child { - use dep::aztec::prelude::{ - AztecAddress, FunctionSelector, PublicMutable, PrivateSet, PrivateContext, emit_unencrypted_log, - Deserialize - }; + use dep::aztec::prelude::{AztecAddress, FunctionSelector, PublicMutable, PrivateSet, PrivateContext, Deserialize}; use dep::aztec::{ context::{PublicContext, Context, gas::GasOpts}, @@ -47,7 +44,7 @@ contract Child { #[aztec(public)] fn pub_set_value(new_value: Field) -> Field { storage.current_value.write(new_value); - emit_unencrypted_log(&mut context, new_value); + context.emit_unencrypted_log(new_value); new_value } @@ -76,7 +73,7 @@ contract Child { fn pub_inc_value(new_value: Field) -> Field { let old_value = storage.current_value.read(); storage.current_value.write(old_value + new_value); - emit_unencrypted_log(&mut context, new_value); + context.emit_unencrypted_log(new_value); new_value } @@ -87,7 +84,7 @@ contract Child { fn pub_inc_value_internal(new_value: Field) -> Field { let old_value = storage.current_value.read(); storage.current_value.write(old_value + new_value); - emit_unencrypted_log(&mut context, new_value); + context.emit_unencrypted_log(new_value); new_value } @@ -96,13 +93,13 @@ contract Child { fn set_value_twice_with_nested_first() { let _result = Child::at(context.this_address()).pub_set_value(10).call(&mut context); storage.current_value.write(20); - emit_unencrypted_log(&mut context, 20); + context.emit_unencrypted_log(20); } #[aztec(public)] fn set_value_twice_with_nested_last() { storage.current_value.write(20); - emit_unencrypted_log(&mut context, 20); + context.emit_unencrypted_log(20); let _result = Child::at(context.this_address()).pub_set_value(10).call(&mut context); } } diff --git a/noir-projects/noir-contracts/contracts/contract_class_registerer_contract/src/main.nr b/noir-projects/noir-contracts/contracts/contract_class_registerer_contract/src/main.nr index a329f6da2f6..9857b3e6f3e 100644 --- a/noir-projects/noir-contracts/contracts/contract_class_registerer_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/contract_class_registerer_contract/src/main.nr @@ -2,7 +2,7 @@ mod events; mod capsule; contract ContractClassRegisterer { - use dep::aztec::prelude::{AztecAddress, EthAddress, FunctionSelector, emit_unencrypted_log}; + use dep::aztec::prelude::{AztecAddress, EthAddress, FunctionSelector}; use dep::aztec::protocol_types::{ contract_class_id::ContractClassId, constants::{ @@ -12,8 +12,6 @@ contract ContractClassRegisterer { traits::Serialize }; - use dep::aztec::log::emit_unencrypted_log_from_private; - use crate::events::{ class_registered::ContractClassRegistered, private_function_broadcasted::{ClassPrivateFunctionBroadcasted, PrivateFunction}, @@ -50,7 +48,7 @@ contract ContractClassRegisterer { public_bytecode_commitment ] ); - emit_unencrypted_log_from_private(&mut context, event.serialize()); + context.emit_unencrypted_log(event.serialize()); } #[aztec(private)] @@ -85,7 +83,7 @@ contract ContractClassRegisterer { function_data.metadata_hash ] ); - emit_unencrypted_log_from_private(&mut context, event.serialize()); + context.emit_unencrypted_log(event.serialize()); } #[aztec(private)] @@ -115,6 +113,6 @@ contract ContractClassRegisterer { function_data.metadata_hash ] ); - emit_unencrypted_log_from_private(&mut context, event.serialize()); + context.emit_unencrypted_log(event.serialize()); } } diff --git a/noir-projects/noir-contracts/contracts/contract_instance_deployer_contract/src/main.nr b/noir-projects/noir-contracts/contracts/contract_instance_deployer_contract/src/main.nr index 3363324acff..be9f464ea3a 100644 --- a/noir-projects/noir-contracts/contracts/contract_instance_deployer_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/contract_instance_deployer_contract/src/main.nr @@ -7,8 +7,6 @@ contract ContractInstanceDeployer { traits::Serialize }; - use dep::aztec::log::{emit_unencrypted_log, emit_unencrypted_log_from_private}; - use crate::events::{instance_deployed::ContractInstanceDeployed}; #[aztec(private)] @@ -54,6 +52,6 @@ contract ContractInstanceDeployer { }; let event_payload = event.serialize(); dep::aztec::oracle::debug_log::debug_log_array_with_prefix("ContractInstanceDeployed", event_payload); - emit_unencrypted_log_from_private(&mut context, event_payload); + context.emit_unencrypted_log(event_payload); } } diff --git a/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr b/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr index 76d6335e6ff..71102fda1a9 100644 --- a/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr @@ -1,7 +1,6 @@ contract Crowdfunding { use dep::aztec::{ - log::emit_unencrypted_log_from_private, protocol_types::{abis::function_selector::FunctionSelector, address::AztecAddress, traits::Serialize}, state_vars::{PrivateSet, PublicImmutable, SharedImmutable} }; @@ -78,6 +77,6 @@ contract Crowdfunding { // 3) Emit an unencrypted event so that anyone can audit how much the operator has withdrawn let event = WithdrawalProcessed { amount, who: operator_address }; - emit_unencrypted_log_from_private(&mut context, event.serialize()); + context.emit_unencrypted_log(event.serialize()); } } diff --git a/noir-projects/noir-contracts/contracts/delegated_on_contract/src/main.nr b/noir-projects/noir-contracts/contracts/delegated_on_contract/src/main.nr index 2dfa3fb6cd4..e6f093e569d 100644 --- a/noir-projects/noir-contracts/contracts/delegated_on_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/delegated_on_contract/src/main.nr @@ -1,8 +1,8 @@ // A contract used along with `Parent` contract to test nested calls. contract DelegatedOn { use dep::aztec::prelude::{ - AztecAddress, FunctionSelector, NoteHeader, NoteGetterOptions, NoteViewerOptions, - emit_unencrypted_log, PublicMutable, PrivateSet, PrivateContext + AztecAddress, FunctionSelector, NoteHeader, NoteGetterOptions, NoteViewerOptions, PublicMutable, + PrivateSet, PrivateContext }; use dep::value_note::value_note::ValueNote; diff --git a/noir-projects/noir-contracts/contracts/delegator_contract/src/main.nr b/noir-projects/noir-contracts/contracts/delegator_contract/src/main.nr index 939c2f1907f..b7f7592350a 100644 --- a/noir-projects/noir-contracts/contracts/delegator_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/delegator_contract/src/main.nr @@ -1,9 +1,6 @@ // A contract used along with `Parent` contract to test nested calls. contract Delegator { - use dep::aztec::prelude::{ - AztecAddress, FunctionSelector, NoteHeader, NoteViewerOptions, emit_unencrypted_log, - PublicMutable, PrivateSet, Deserialize - }; + use dep::aztec::prelude::{AztecAddress, FunctionSelector, NoteHeader, NoteViewerOptions, PublicMutable, PrivateSet, Deserialize}; use dep::value_note::value_note::ValueNote; use dep::delegated_on::DelegatedOn; diff --git a/noir-projects/noir-contracts/contracts/test_contract/src/main.nr b/noir-projects/noir-contracts/contracts/test_contract/src/main.nr index 3e6b04baf2d..43a0d80c528 100644 --- a/noir-projects/noir-contracts/contracts/test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/test_contract/src/main.nr @@ -7,17 +7,13 @@ contract Test { use dep::aztec::protocol_types::{ abis::private_circuit_public_inputs::PrivateCircuitPublicInputs, - constants::{MAX_NOTE_HASH_READ_REQUESTS_PER_CALL}, traits::Serialize + constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, traits::Serialize }; use dep::aztec::note::constants::MAX_NOTES_PER_PAGE; use dep::aztec::state_vars::shared_mutable::SharedMutablePrivateGetter; - // docs:start:unencrypted_import - use dep::aztec::prelude::emit_unencrypted_log; - // docs:end:unencrypted_import - use dep::aztec::{ context::{Context, inputs::private_context_inputs::PrivateContextInputs}, hash::{pedersen_hash, compute_secret_hash, ArgsHasher}, @@ -26,11 +22,7 @@ contract Test { note_getter_options::NoteStatus }, deploy::deploy_contract as aztec_deploy_contract, - oracle::{ - get_public_key::get_public_key as get_public_key_oracle, - unsafe_rand::unsafe_rand - }, - log::emit_unencrypted_log_from_private + oracle::{get_public_key::get_public_key as get_public_key_oracle, unsafe_rand::unsafe_rand} }; use dep::token_portal_content_hash_lib::{get_mint_private_content_hash, get_mint_public_content_hash}; use dep::field_note::field_note::FieldNote; @@ -240,13 +232,13 @@ contract Test { #[aztec(private)] fn emit_msg_sender() { - // Note: don't use emit_unencrypted_log_from_private in production code - emit_unencrypted_log_from_private(&mut context, context.msg_sender()); + // Note: don't use emit_unencrypted_log from private in production code + context.emit_unencrypted_log(context.msg_sender()); } #[aztec(private)] fn emit_array_as_unencrypted_log(fields: [Field; 5]) { - emit_unencrypted_log_from_private(&mut context, fields); + context.emit_unencrypted_log(fields); } // docs:start:is-time-equal @@ -260,7 +252,7 @@ contract Test { #[aztec(public)] fn emit_unencrypted(value: Field) -> Field { // docs:start:emit_unencrypted - emit_unencrypted_log(&mut context, value); + context.emit_unencrypted_log(value); // docs:end:emit_unencrypted 0 } @@ -389,36 +381,40 @@ contract Test { fn test_shared_mutable_private_getter_for_registry_contract( contract_address_to_read: AztecAddress, storage_slot_of_shared_mutable: Field, - address_to_get_in_registry: AztecAddress, + address_to_get_in_registry: AztecAddress ) { // We have to derive this slot to get the location of the shared mutable inside the Map - let derived_slot = dep::aztec::hash::pedersen_hash([storage_slot_of_shared_mutable, address_to_get_in_registry.to_field()], 0); + let derived_slot = dep::aztec::hash::pedersen_hash( + [storage_slot_of_shared_mutable, address_to_get_in_registry.to_field()], + 0 + ); // It's a bit wonky because we need to know the delay for get_current_value_in_private to work correctly let registry_private_getter: SharedMutablePrivateGetter = SharedMutablePrivateGetter::new(context, contract_address_to_read, derived_slot); let nullifier_public_key = registry_private_getter.get_current_value_in_private(); - emit_unencrypted_log_from_private(&mut context, nullifier_public_key); + context.emit_unencrypted_log(nullifier_public_key); } #[aztec(private)] fn test_shared_mutable_private_getter( contract_address_to_read: AztecAddress, - storage_slot_of_shared_mutable: Field, + storage_slot_of_shared_mutable: Field ) { // It's a bit wonky because we need to know the delay for get_current_value_in_private to work correctly - let test: SharedMutablePrivateGetter = SharedMutablePrivateGetter::new(context, contract_address_to_read, storage_slot_of_shared_mutable); + let test: SharedMutablePrivateGetter = SharedMutablePrivateGetter::new( + context, + contract_address_to_read, + storage_slot_of_shared_mutable + ); let authorized = test.get_current_value_in_private(); - emit_unencrypted_log_from_private(&mut context, authorized); + context.emit_unencrypted_log(authorized); } #[aztec(public)] fn delay() { // We use this as a util function to "mine a block" - dep::aztec::log::emit_unencrypted_log( - &mut context, - "dummy" - ); + context.emit_unencrypted_log("dummy"); } // Purely exists for testing From b348ec149b7df0d4620a79d501834a6590078160 Mon Sep 17 00:00:00 2001 From: josh crites Date: Fri, 19 Apr 2024 10:29:00 -0400 Subject: [PATCH 036/102] chore(docs): Remove 'yellow paper' reference from protocol specs (#5872) --- docs/docs/protocol-specs/intro.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/docs/protocol-specs/intro.md b/docs/docs/protocol-specs/intro.md index 8a7c2fc331b..275b370ed15 100644 --- a/docs/docs/protocol-specs/intro.md +++ b/docs/docs/protocol-specs/intro.md @@ -1,8 +1,8 @@ # Editorial guidelines -This "yellow paper" is a first attempt to describe the Aztec protocol in its entirety. +This protocol specification is a first attempt to describe the Aztec protocol in its entirety. -It'll be more 'beige' than a yellow paper, initially. For example, we haven't settled on exact hashes, or encryption schemes, or gas metering schedules yet, so it won't contain such exact details as the Ethereum yellow paper. +It is still a work in progress. For example, we haven't settled on exact hashes, or encryption schemes, or gas metering schedules yet, so it won't contain such exact details as the Ethereum yellow paper. ## Target audience From ad55af0d44b3c818d5e42fe75bb72fa95e88c309 Mon Sep 17 00:00:00 2001 From: Santiago Palladino Date: Fri, 19 Apr 2024 11:36:10 -0300 Subject: [PATCH 037/102] chore: Temporarily skip failing gas tests (#5874) These were broken due to a bad merge coming from https://github.com/AztecProtocol/aztec-packages/pull/5828. Will fix and reenable asap. --- .circleci/config.yml | 4 ++-- ...ubscription.test.ts => skip_e2e_dapp_subscription.test.ts} | 0 .../src/{e2e_fees.test.ts => skip_e2e_fees.test.ts} | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename yarn-project/end-to-end/src/{e2e_dapp_subscription.test.ts => skip_e2e_dapp_subscription.test.ts} (100%) rename yarn-project/end-to-end/src/{e2e_fees.test.ts => skip_e2e_fees.test.ts} (100%) diff --git a/.circleci/config.yml b/.circleci/config.yml index 6b4c8af64ae..3b8f67c0c97 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -900,12 +900,12 @@ workflows: # Benchmark jobs. - bench-publish-rollup: *e2e_test - bench-process-history: *e2e_test - - bench-tx-size: *e2e_test + # - bench-tx-size: *e2e_test - bench-summary: requires: - bench-publish-rollup - bench-process-history - - bench-tx-size + # - bench-tx-size <<: *defaults # Production releases. diff --git a/yarn-project/end-to-end/src/e2e_dapp_subscription.test.ts b/yarn-project/end-to-end/src/skip_e2e_dapp_subscription.test.ts similarity index 100% rename from yarn-project/end-to-end/src/e2e_dapp_subscription.test.ts rename to yarn-project/end-to-end/src/skip_e2e_dapp_subscription.test.ts diff --git a/yarn-project/end-to-end/src/e2e_fees.test.ts b/yarn-project/end-to-end/src/skip_e2e_fees.test.ts similarity index 100% rename from yarn-project/end-to-end/src/e2e_fees.test.ts rename to yarn-project/end-to-end/src/skip_e2e_fees.test.ts From c999dae76580ea63486aaa17edb774736dc32b89 Mon Sep 17 00:00:00 2001 From: ludamad Date: Fri, 19 Apr 2024 11:10:36 -0400 Subject: [PATCH 038/102] fix: merge-check (#5873) This was passing on skip. We may have to improve this logic in the future. Note: This wasn't done in github checks page because it can't list matrix builds. --- .github/workflows/ci.yml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1b5547c9488..b3902c551f2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -147,8 +147,17 @@ jobs: merge-check: runs-on: ${{ github.actor }}-x86 needs: [e2e, bb-native-tests, bb-bench] + if: always() # Ensures this job runs regardless of the success or failure of dependencies. steps: - - run: echo Pull request merging now allowed. + - run: | + echo "E2E Test Status: ${{ needs.e2e.result }}" + echo "Native Tests Status: ${{ needs.bb-native-tests.result }}" + echo "Bench Tests Status: ${{ needs.bb-bench.result }}" + if [[ "${{ needs.e2e.result }}" != 'success' || "${{ needs.bb-native-tests.result }}" != 'success' || "${{ needs.bb-bench.result }}" != 'success' ]]; then + echo "Pull request merging not allowed due to failures." + exit 1 + fi + echo "Pull request merging now allowed." notify: needs: [e2e, bb-native-tests, bb-bench] From 0c9d0b4e611472e0e8718449f6d8f2451e0391a0 Mon Sep 17 00:00:00 2001 From: Facundo Date: Fri, 19 Apr 2024 16:54:19 +0100 Subject: [PATCH 039/102] chore(avm-simulator): remove AvmContext::raw_* external calls (#5869) I introduced raw and "old interface" methods in the AvmContext when I was less familiar with Aztec-nr. I now think we only should have the one supporting the old interface behaviour. Once we successfully transition, we can change those as much as we want. --- .../aztec-nr/aztec/src/context/avm_context.nr | 30 -------- .../src/main.nr | 75 +------------------ .../end-to-end/src/e2e_avm_simulator.test.ts | 4 + .../simulator/src/avm/avm_simulator.test.ts | 51 +------------ 4 files changed, 10 insertions(+), 150 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/context/avm_context.nr b/noir-projects/aztec-nr/aztec/src/context/avm_context.nr index 0a457fee204..1df9863af65 100644 --- a/noir-projects/aztec-nr/aztec/src/context/avm_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/avm_context.nr @@ -50,36 +50,6 @@ impl AvmContext { pub fn l1_to_l2_msg_exists(self, msg_hash: Field, msg_leaf_index: Field) -> bool { l1_to_l2_msg_exists(msg_hash, msg_leaf_index) == 1 } - - fn call_public_function_raw( - self: &mut Self, - gas: GasOpts, - contract_address: AztecAddress, - temporary_function_selector: Field, - args: [Field] - ) -> ([Field; RET_COUNT], u8) { - call( - gas_for_call(gas), - contract_address, - args, - temporary_function_selector - ) - } - - fn static_call_public_function_raw( - self: &mut Self, - gas: GasOpts, - contract_address: AztecAddress, - temporary_function_selector: Field, - args: [Field] - ) -> ([Field; RET_COUNT], u8) { - call_static( - gas_for_call(gas), - contract_address, - args, - temporary_function_selector - ) - } } impl PublicContextInterface for AvmContext { diff --git a/noir-projects/noir-contracts/contracts/avm_nested_calls_test_contract/src/main.nr b/noir-projects/noir-contracts/contracts/avm_nested_calls_test_contract/src/main.nr index e5d34183f42..1526d48e5b6 100644 --- a/noir-projects/noir-contracts/contracts/avm_nested_calls_test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/avm_nested_calls_test_contract/src/main.nr @@ -32,54 +32,16 @@ contract AvmNestedCallsTest { context.push_new_nullifier(nullifier, 0); } - // Directly call the external call opcode to initiate a nested call to the add function + // External call opcode to initiate a nested call to the add function with user-specified gas #[aztec(public-vm)] - fn raw_nested_call_to_add(arg_a: Field, arg_b: Field) -> pub Field { - let selector = FunctionSelector::from_signature("add_args_return(Field,Field)").to_field(); - - // Nested call - let results = context.call_public_function_raw( - GasOpts::default(), - context.this_address(), - selector, - [arg_a, arg_b].as_slice() - ); - let data_to_return: [Field; 1] = results.0; - // this explicit size is necessary to ensure that ret_size is compile-time - // (ensure the data_to_return is in a HeapArray not a HeapVector) - let success: u8 = results.1; - - assert(success == 1, "Call failed"); - - let add_result = data_to_return[0]; - add_result - } - - // Directly call the external call opcode to initiate a nested call to the add function with user-specified gas - #[aztec(public-vm)] - fn raw_nested_call_to_add_with_gas( + fn nested_call_to_add_with_gas( arg_a: Field, arg_b: Field, l1_gas: Field, l2_gas: Field, da_gas: Field ) -> pub Field { - let selector = FunctionSelector::from_signature("add_args_return(Field,Field)").to_field(); - - // Nested call - let results = context.call_public_function_raw( - GasOpts::new(l1_gas, l2_gas, da_gas), - context.this_address(), - selector, - [arg_a, arg_b].as_slice() - ); - let data_to_return: [Field; 1] = results.0; - // this explicit size is necessary to ensure that ret_size is compile-time - // (ensure the data_to_return is in a HeapArray not a HeapVector) - let _success: u8 = results.1; - - let add_result = data_to_return[0]; - add_result + AvmNestedCallsTest::at(context.this_address()).add_args_return(arg_a, arg_b).call(&mut context, GasOpts::new(l1_gas, l2_gas, da_gas)) } // Use the `call_public_function` wrapper to initiate a nested call to the add function @@ -88,37 +50,6 @@ contract AvmNestedCallsTest { AvmNestedCallsTest::at(context.this_address()).add_args_return(arg_a, arg_b).call(&mut context, GasOpts::default()) } - // Directly call_static the external call opcode to initiate a nested call to the add function - #[aztec(public-vm)] - fn raw_nested_static_call_to_add(arg_a: Field, arg_b: Field) -> pub (Field, u8) { - let selector = FunctionSelector::from_signature("add_args_return(Field,Field)").to_field(); - - let (result_data, success): ([Field; 1], u8) = context.static_call_public_function_raw( - GasOpts::default(), - context.this_address(), - selector, - [arg_a, arg_b].as_slice() - ); - - (result_data[0], success) - } - - // Directly call_static `set_storage_single`. Should fail since it's accessing storage. - #[aztec(public-vm)] - fn raw_nested_static_call_to_set_storage() -> pub u8 { - let selector = FunctionSelector::from_signature("set_storage_single(Field)").to_field(); - let calldata: [Field; 1] = [20]; - - let (_data_to_return, success): ([Field; 0], u8) = context.static_call_public_function_raw( - GasOpts::default(), - context.this_address(), - selector, - calldata.as_slice() - ); - - success - } - // Indirectly call_static the external call opcode to initiate a nested call to the add function #[aztec(public-vm)] fn nested_static_call_to_add(arg_a: Field, arg_b: Field) -> pub Field { diff --git a/yarn-project/end-to-end/src/e2e_avm_simulator.test.ts b/yarn-project/end-to-end/src/e2e_avm_simulator.test.ts index 1a941a6f685..ac36f13ceaf 100644 --- a/yarn-project/end-to-end/src/e2e_avm_simulator.test.ts +++ b/yarn-project/end-to-end/src/e2e_avm_simulator.test.ts @@ -105,6 +105,7 @@ describe('e2e_avm_simulator', () => { .send() .wait(); }); + describe('Authwit', () => { it('Works if authwit provided', async () => { const recipient = AztecAddress.random(); @@ -167,6 +168,7 @@ describe('e2e_avm_simulator', () => { avmContract.methods.create_same_nullifier_in_nested_call(avmContract.address, nullifier).send().wait(), ).rejects.toThrow(); }); + it('Should be able to emit different unsiloed nullifiers from the same contract', async () => { const nullifier = new Fr(1); const tx = await avmContract.methods @@ -175,6 +177,7 @@ describe('e2e_avm_simulator', () => { .wait(); expect(tx.status).toEqual(TxStatus.MINED); }); + // TODO(4293): this should work! Fails in public kernel because both nullifiers are incorrectly being siloed by same address it.skip('Should be able to emit the same unsiloed nullifier from two different contracts', async () => { const nullifier = new Fr(1); @@ -184,6 +187,7 @@ describe('e2e_avm_simulator', () => { .wait(); expect(tx.status).toEqual(TxStatus.MINED); }); + it('Should be able to emit different unsiloed nullifiers from two different contracts', async () => { const nullifier = new Fr(1); const tx = await avmContract.methods diff --git a/yarn-project/simulator/src/avm/avm_simulator.test.ts b/yarn-project/simulator/src/avm/avm_simulator.test.ts index 411d6c8fa84..783089c16dd 100644 --- a/yarn-project/simulator/src/avm/avm_simulator.test.ts +++ b/yarn-project/simulator/src/avm/avm_simulator.test.ts @@ -787,27 +787,11 @@ describe('AVM simulator: transpiled Noir contracts', () => { }); describe('Nested external calls', () => { - it(`Nested call succeeds`, async () => { - const calldata: Fr[] = [new Fr(1), new Fr(2)]; - const callBytecode = getAvmNestedCallsTestContractBytecode('raw_nested_call_to_add'); - const addBytecode = getAvmNestedCallsTestContractBytecode('add_args_return'); - const context = initContext({ env: initExecutionEnvironment({ calldata }) }); - jest - .spyOn(context.persistableState.hostStorage.contractsDb, 'getBytecode') - .mockReturnValue(Promise.resolve(addBytecode)); - - const results = await new AvmSimulator(context).executeBytecode(callBytecode); - - expect(results.revertReason).toBeUndefined(); - expect(results.reverted).toBe(false); - expect(results.output).toEqual([new Fr(3)]); - }); - // TODO(https://github.com/AztecProtocol/aztec-packages/issues/5625): gas not plumbed through correctly in nested calls. // it(`Nested call with not enough gas`, async () => { // const gas = [/*l1=*/ 10000, /*l2=*/ 20, /*da=*/ 10000].map(g => new Fr(g)); // const calldata: Fr[] = [new Fr(1), new Fr(2), ...gas]; - // const callBytecode = getAvmNestedCallsTestContractBytecode('raw_nested_call_to_add_with_gas'); + // const callBytecode = getAvmNestedCallsTestContractBytecode('nested_call_to_add_with_gas'); // const addBytecode = getAvmNestedCallsTestContractBytecode('add_args_return'); // const context = initContext({ env: initExecutionEnvironment({ calldata }) }); // jest @@ -822,7 +806,7 @@ describe('AVM simulator: transpiled Noir contracts', () => { // expect(results.output).toEqual([new Fr(0)]); // }); - it(`Nested call through the old interface`, async () => { + it(`Nested call`, async () => { const calldata: Fr[] = [new Fr(1), new Fr(2)]; const callBytecode = getAvmNestedCallsTestContractBytecode('nested_call_to_add'); const addBytecode = getAvmNestedCallsTestContractBytecode('add_args_return'); @@ -838,35 +822,6 @@ describe('AVM simulator: transpiled Noir contracts', () => { }); it(`Nested static call`, async () => { - const calldata: Fr[] = [new Fr(1), new Fr(2)]; - const callBytecode = getAvmNestedCallsTestContractBytecode('raw_nested_static_call_to_add'); - const addBytecode = getAvmNestedCallsTestContractBytecode('add_args_return'); - const context = initContext({ env: initExecutionEnvironment({ calldata }) }); - jest - .spyOn(context.persistableState.hostStorage.contractsDb, 'getBytecode') - .mockReturnValue(Promise.resolve(addBytecode)); - - const results = await new AvmSimulator(context).executeBytecode(callBytecode); - - expect(results.reverted).toBe(false); - expect(results.output).toEqual([/*result=*/ new Fr(3), /*success=*/ new Fr(1)]); - }); - - it(`Nested static call which modifies storage`, async () => { - const callBytecode = getAvmNestedCallsTestContractBytecode('raw_nested_static_call_to_set_storage'); - const nestedBytecode = getAvmNestedCallsTestContractBytecode('set_storage_single'); - const context = initContext(); - jest - .spyOn(context.persistableState.hostStorage.contractsDb, 'getBytecode') - .mockReturnValue(Promise.resolve(nestedBytecode)); - - const results = await new AvmSimulator(context).executeBytecode(callBytecode); - - expect(results.reverted).toBe(false); // The outer call should not revert. - expect(results.output).toEqual([new Fr(0)]); // The inner call should have reverted. - }); - - it(`Nested static call (old interface)`, async () => { const calldata: Fr[] = [new Fr(1), new Fr(2)]; const callBytecode = getAvmNestedCallsTestContractBytecode('nested_static_call_to_add'); const addBytecode = getAvmNestedCallsTestContractBytecode('add_args_return'); @@ -881,7 +836,7 @@ describe('AVM simulator: transpiled Noir contracts', () => { expect(results.output).toEqual([/*result=*/ new Fr(3)]); }); - it(`Nested static call which modifies storage (old interface)`, async () => { + it(`Nested static call which modifies storage`, async () => { const callBytecode = getAvmNestedCallsTestContractBytecode('nested_static_call_to_set_storage'); const nestedBytecode = getAvmNestedCallsTestContractBytecode('set_storage_single'); const context = initContext(); From 165e62f38239f25cc6595bb43f435e9f4673fd83 Mon Sep 17 00:00:00 2001 From: Santiago Palladino Date: Fri, 19 Apr 2024 14:45:03 -0300 Subject: [PATCH 040/102] fix: Fix and reenable fees e2e tests (#5877) Fixes fees, dapp subscription, and bench tx e2e tests, and reverts #5874 to reenable them on CI. --- .circleci/config.yml | 4 +-- .../src/benchmarks/bench_tx_size_fees.test.ts | 17 +++++-------- ....test.ts => e2e_dapp_subscription.test.ts} | 20 ++++++--------- ...skip_e2e_fees.test.ts => e2e_fees.test.ts} | 25 ++++++++----------- 4 files changed, 25 insertions(+), 41 deletions(-) rename yarn-project/end-to-end/src/{skip_e2e_dapp_subscription.test.ts => e2e_dapp_subscription.test.ts} (94%) rename yarn-project/end-to-end/src/{skip_e2e_fees.test.ts => e2e_fees.test.ts} (97%) diff --git a/.circleci/config.yml b/.circleci/config.yml index 3b8f67c0c97..6b4c8af64ae 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -900,12 +900,12 @@ workflows: # Benchmark jobs. - bench-publish-rollup: *e2e_test - bench-process-history: *e2e_test - # - bench-tx-size: *e2e_test + - bench-tx-size: *e2e_test - bench-summary: requires: - bench-publish-rollup - bench-process-history - # - bench-tx-size + - bench-tx-size <<: *defaults # Production releases. diff --git a/yarn-project/end-to-end/src/benchmarks/bench_tx_size_fees.test.ts b/yarn-project/end-to-end/src/benchmarks/bench_tx_size_fees.test.ts index af887a7be5a..0ab7176c82c 100644 --- a/yarn-project/end-to-end/src/benchmarks/bench_tx_size_fees.test.ts +++ b/yarn-project/end-to-end/src/benchmarks/bench_tx_size_fees.test.ts @@ -8,7 +8,7 @@ import { PublicFeePaymentMethod, TxStatus, } from '@aztec/aztec.js'; -import { Fr, GasSettings } from '@aztec/circuits.js'; +import { GasSettings } from '@aztec/circuits.js'; import { FPCContract, GasTokenContract, TokenContract } from '@aztec/noir-contracts.js'; import { getCanonicalGasTokenAddress } from '@aztec/protocol-contracts/gas-token'; @@ -54,11 +54,11 @@ describe('benchmarks/tx_size_fees', () => { // mint tokens beforeAll(async () => { await Promise.all([ - gas.methods.mint_public(aliceWallet.getAddress(), 1000n).send().wait(), - gas.methods.mint_public(fpc.address, 1000n).send().wait(), + gas.methods.mint_public(aliceWallet.getAddress(), 100e9).send().wait(), + gas.methods.mint_public(fpc.address, 100e9).send().wait(), ]); - await token.methods.privately_mint_private_note(1000n).send().wait(); - await token.methods.mint_public(aliceWallet.getAddress(), 1000n).send().wait(); + await token.methods.privately_mint_private_note(100e9).send().wait(); + await token.methods.mint_public(aliceWallet.getAddress(), 100e9).send().wait(); }); it.each<() => Promise>([ @@ -68,12 +68,7 @@ describe('benchmarks/tx_size_fees', () => { () => Promise.resolve(new PrivateFeePaymentMethod(token.address, fpc.address, aliceWallet)), ])('sends a tx with a fee', async createPaymentMethod => { const paymentMethod = await createPaymentMethod(); - const gasSettings = GasSettings.from({ - gasLimits: { daGas: 5, l1Gas: 5, l2Gas: 5 }, - teardownGasLimits: { daGas: 3, l1Gas: 3, l2Gas: 3 }, - maxFeesPerGas: { feePerDaGas: Fr.ONE, feePerL1Gas: Fr.ONE, feePerL2Gas: Fr.ONE }, - inclusionFee: new Fr(6), - }); + const gasSettings = GasSettings.default(); const tx = await token.methods .transfer(aliceWallet.getAddress(), bobAddress, 1n, 0) .send({ fee: paymentMethod ? { gasSettings, paymentMethod } : undefined }) diff --git a/yarn-project/end-to-end/src/skip_e2e_dapp_subscription.test.ts b/yarn-project/end-to-end/src/e2e_dapp_subscription.test.ts similarity index 94% rename from yarn-project/end-to-end/src/skip_e2e_dapp_subscription.test.ts rename to yarn-project/end-to-end/src/e2e_dapp_subscription.test.ts index c1ee4fcc0d7..cf465a0ea7f 100644 --- a/yarn-project/end-to-end/src/skip_e2e_dapp_subscription.test.ts +++ b/yarn-project/end-to-end/src/e2e_dapp_subscription.test.ts @@ -47,21 +47,15 @@ describe('e2e_dapp_subscription', () => { let bananasPublicBalances: BalancesFn; let bananasPrivateBalances: BalancesFn; - const SUBSCRIPTION_AMOUNT = 100n; - const INITIAL_GAS_BALANCE = 1000n; - const PUBLICLY_MINTED_BANANAS = 500n; - const PRIVATELY_MINTED_BANANAS = 600n; + const SUBSCRIPTION_AMOUNT = BigInt(100e9); + const INITIAL_GAS_BALANCE = BigInt(1000e9); + const PUBLICLY_MINTED_BANANAS = BigInt(500e9); + const PRIVATELY_MINTED_BANANAS = BigInt(600e9); const FEE_AMOUNT = 1n; - const REFUND = 29n; // intentionally overpay the gas fee. This is the expected refund. - const MAX_FEE = FEE_AMOUNT + REFUND; - - const GAS_SETTINGS = GasSettings.from({ - gasLimits: { daGas: 5, l1Gas: 5, l2Gas: 5 }, - teardownGasLimits: { daGas: 3, l1Gas: 3, l2Gas: 3 }, - maxFeesPerGas: { feePerDaGas: Fr.ONE, feePerL1Gas: Fr.ONE, feePerL2Gas: Fr.ONE }, - inclusionFee: new Fr(6), - }); + const MAX_FEE = BigInt(30e9); + + const GAS_SETTINGS = GasSettings.default(); beforeAll(async () => { process.env.PXE_URL = ''; diff --git a/yarn-project/end-to-end/src/skip_e2e_fees.test.ts b/yarn-project/end-to-end/src/e2e_fees.test.ts similarity index 97% rename from yarn-project/end-to-end/src/skip_e2e_fees.test.ts rename to yarn-project/end-to-end/src/e2e_fees.test.ts index e3ff4f75cd5..e22cd633fd4 100644 --- a/yarn-project/end-to-end/src/skip_e2e_fees.test.ts +++ b/yarn-project/end-to-end/src/e2e_fees.test.ts @@ -54,12 +54,7 @@ describe('e2e_fees', () => { let bananaPublicBalances: BalancesFn; let bananaPrivateBalances: BalancesFn; - const gasSettings = GasSettings.from({ - gasLimits: { daGas: 5, l1Gas: 5, l2Gas: 5 }, - teardownGasLimits: { daGas: 3, l1Gas: 3, l2Gas: 3 }, - maxFeesPerGas: { feePerDaGas: Fr.ONE, feePerL1Gas: Fr.ONE, feePerL2Gas: Fr.ONE }, - inclusionFee: new Fr(6), - }); + const gasSettings = GasSettings.default(); beforeAll(async () => { const ctx = await setup(3, {}, {}, true); @@ -113,8 +108,8 @@ describe('e2e_fees', () => { }); it('reverts transactions but still pays fees using PublicFeePaymentMethod', async () => { - const OutrageousPublicAmountAliceDoesNotHave = 10000n; - const PublicMintedAlicePublicBananas = 1000n; + const OutrageousPublicAmountAliceDoesNotHave = BigInt(1e15); + const PublicMintedAlicePublicBananas = BigInt(1e12); const FeeAmount = 1n; const [initialAlicePrivateBananas, initialFPCPrivateBananas] = await bananaPrivateBalances( @@ -218,13 +213,13 @@ describe('e2e_fees', () => { beforeAll(async () => { // Fund Alice private and publicly - await mintPrivate(1000n, aliceAddress); - await bananaCoin.methods.mint_public(aliceAddress, 1000n).send().wait(); + await mintPrivate(BigInt(1e12), aliceAddress); + await bananaCoin.methods.mint_public(aliceAddress, 1e12).send().wait(); }); beforeEach(async () => { FeeAmount = 1n; - MaxFee = 30n; + MaxFee = BigInt(30e9); RefundAmount = MaxFee - FeeAmount; RefundSecret = Fr.random(); @@ -241,7 +236,7 @@ describe('e2e_fees', () => { ]); }); - it("pays fees for tx that don't run public app logic", async () => { + it('pays fees for tx that dont run public app logic', async () => { /** * PRIVATE SETUP * check authwit @@ -514,7 +509,7 @@ describe('e2e_fees', () => { ).resolves.toBeUndefined(); }); - it("rejects txs that don't have enough balance to cover gas costs", async () => { + it('rejects txs that dont have enough balance to cover gas costs', async () => { // deploy a copy of bananaFPC but don't fund it! const bankruptFPC = await FPCContract.deploy(aliceWallet, bananaCoin.address, gasTokenContract.address) .send() @@ -544,7 +539,7 @@ describe('e2e_fees', () => { }); it('fails transaction that error in setup', async () => { - const OutrageousPublicAmountAliceDoesNotHave = 10000n; + const OutrageousPublicAmountAliceDoesNotHave = BigInt(100e12); // simulation throws an error when setup fails await expect( @@ -579,7 +574,7 @@ describe('e2e_fees', () => { * We trigger an error in teardown by having the FPC authorize a transfer of its entire balance to Alice * as part of app logic. This will cause the FPC to not have enough funds to pay the refund back to Alice. */ - const PublicMintedAlicePublicBananas = 1000n; + const PublicMintedAlicePublicBananas = 100_000_000_000n; const [initialAlicePrivateBananas, initialFPCPrivateBananas] = await bananaPrivateBalances( aliceAddress, From 3683f0bb034ea59258c587d70d0517ee2ed00b91 Mon Sep 17 00:00:00 2001 From: ludamad Date: Sat, 20 Apr 2024 04:27:39 -0400 Subject: [PATCH 041/102] fix(ci): merge check fails ungracefully on spot issues (#5887) Merge-check shouldn't also rely on the spot, just makes issues worse --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b3902c551f2..0b5f2c532c0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -145,7 +145,7 @@ jobs: run: earthly-ci --no-output +bench-ultra-honk --bench_mode=cache merge-check: - runs-on: ${{ github.actor }}-x86 + runs-on: ubuntu-latest needs: [e2e, bb-native-tests, bb-bench] if: always() # Ensures this job runs regardless of the success or failure of dependencies. steps: @@ -160,8 +160,8 @@ jobs: echo "Pull request merging now allowed." notify: - needs: [e2e, bb-native-tests, bb-bench] runs-on: ubuntu-latest + needs: [e2e, bb-native-tests, bb-bench] if: ${{ github.ref == 'refs/heads/master' && failure() }} steps: - name: Send notification to aztec3-ci channel if workflow failed on master From 564b893486375e88945bdeb63364bca374f376fb Mon Sep 17 00:00:00 2001 From: ludamad Date: Sat, 20 Apr 2024 04:28:53 -0400 Subject: [PATCH 042/102] chore(ci): address start-runner edge-cases (#5888) https://github.com/AztecProtocol/ec2-action-builder/commit/a576467b9f0f86edaebf171399b6b0684d1aff1f - Tries to address runner finding unusable spot, we now stop it and restart. Not fully sure why this would be the case, but it came up and allows for recovery. Also poll less in case it was a rate limit issue. - Add a minute polling logic around both creating spot and then creating on-demand. This might add a minute to most builds - so will be monitoring - but should be no different than our old spot start times with circleci --- .github/workflows/setup-runner.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/setup-runner.yml b/.github/workflows/setup-runner.yml index 4aa9f22ac8d..0fe34e0cb73 100644 --- a/.github/workflows/setup-runner.yml +++ b/.github/workflows/setup-runner.yml @@ -58,7 +58,7 @@ jobs: group: start-builder-${{ inputs.runner_label }} steps: - name: Start EC2 runner - uses: AztecProtocol/ec2-action-builder@v0.14e + uses: AztecProtocol/ec2-action-builder@v0.15 with: github_token: ${{ secrets.GH_SELF_HOSTED_RUNNER_TOKEN }} aws_access_key_id: ${{ secrets.AWS_ACCESS_KEY_ID }} From eb1cfefc4ff11802a97127f10ab30fb5487335fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Pedro=20Sousa?= Date: Sun, 21 Apr 2024 01:17:05 +0100 Subject: [PATCH 043/102] chore: adding devcontainer with create aztec app (#5849) Fixing a bug, weird stuff --- .devcontainer/scripts/onCreateCommand.sh | 1 - .devcontainer/scripts/postAttachCommand.sh | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/scripts/onCreateCommand.sh b/.devcontainer/scripts/onCreateCommand.sh index 0208ef55640..74e240cdb3c 100755 --- a/.devcontainer/scripts/onCreateCommand.sh +++ b/.devcontainer/scripts/onCreateCommand.sh @@ -3,7 +3,6 @@ TYPE=$1 NAME=$2 -apt install gh curl -s install.aztec.network | NON_INTERACTIVE=1 BIN_PATH=/usr/local/bin bash -s docker compose -f $HOME/.aztec/docker-compose.yml pull diff --git a/.devcontainer/scripts/postAttachCommand.sh b/.devcontainer/scripts/postAttachCommand.sh index e2ccda17ac5..4b092522be6 100755 --- a/.devcontainer/scripts/postAttachCommand.sh +++ b/.devcontainer/scripts/postAttachCommand.sh @@ -2,6 +2,7 @@ TYPE=$1 NAME=$2 +apt install gh gh codespace ports visibility 8080:public -c $CODESPACE_NAME (nohup /usr/local/bin/aztec sandbox &) From e1eb98e85e6ef6ca87f502036426457c8c2a7efc Mon Sep 17 00:00:00 2001 From: James Zaki Date: Sun, 21 Apr 2024 12:46:35 +0100 Subject: [PATCH 044/102] docs: Update info around VERSION (#5891) --- docs/docs/developers/versions-updating.md | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/docs/docs/developers/versions-updating.md b/docs/docs/developers/versions-updating.md index 6b570b12beb..ac062cd3c61 100644 --- a/docs/docs/developers/versions-updating.md +++ b/docs/docs/developers/versions-updating.md @@ -61,12 +61,18 @@ The second point requires a restart of the extension, which you can trigger with ## Updating ### TL;DR -1. Updating the sandbox and CLI: +1. Updating Aztec sandbox to the latest version (includes `aztec-nargo`, `aztec-cli`, etc): ```shell aztec-up ``` +To set `VERSION` for a particular git tag, eg for [aztec-package-v**0.35.0**](https://github.com/AztecProtocol/aztec-packages/tree/aztec-packages-v0.35.0) + +```shell +VERSION=0.35.0 aztec-up +``` + 2. Updating aztec-nr and individual @aztec dependencies: Inside your project run: @@ -125,14 +131,18 @@ If the dependencies fail to resolve ensure that the tag matches a tag in the [az ## Updating `aztec-nargo` -`aztec-nargo` is updated by running: +As mentioned in the tl;dr, `aztec-nargo` is updated as part of updating the whole sandbox via: ```bash aztec-up ``` -If exceptionally needing to test different versions, a `VERSION` tag can be specified. Eg to use `master`: +The version of aztec-nargo that comes with a particular version of the Aztec sandbox can be seen in the monorepo. Eg tag: aztec-packages-v0.35.0 contains aztec-nargo [v0.27.0](https://github.com/AztecProtocol/aztec-packages/blob/aztec-packages-v0.35.0/noir/noir-repo/Cargo.toml#L44). + +Set VERSION to specify the desired Aztec sandbox version, eg monorepo tag suffix [0.35.0](https://github.com/AztecProtocol/aztec-packages/tree/aztec-packages-v0.35.0) (to have `aztec-nargo` v0.27.0). ```bash -VERSION=master aztec-up +VERSION= aztec-up ``` + +Note: Being under highly active development it is NOT recommended to specify, `master`, due to the increased effort to align tooling, dependencies, and example code syntax. From c48c91349dd592520ee33d4c45bc2d3913883541 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Bene=C5=A1?= Date: Mon, 22 Apr 2024 10:10:05 +0200 Subject: [PATCH 045/102] chore: nuking CLI (#5865) Fixes #5894 --- .circleci/config.yml | 15 - aztec-up/bin/aztec-install | 3 - boxes/Dockerfile | 2 +- boxes/Earthfile | 2 +- boxes/boxes/react/package.json | 2 +- boxes/boxes/vanilla/package.json | 2 +- boxes/contract-only/package.json | 2 +- build_manifest.yml | 10 - .../aztecjs/guides/call_view_function.md | 4 +- .../aztecjs/guides/create_account.md | 2 - .../aztecjs/guides/deploy_contract.md | 2 - .../aztecjs/guides/send_transaction.md | 2 - .../how_to_compile_contract.md | 2 +- .../sandbox/references/cli-commands.md | 129 ----- .../writing_private_voting_contract.md | 2 +- docs/sidebars.js | 1 - release-please-config.json | 6 +- yarn-project/Dockerfile | 2 +- yarn-project/Earthfile | 7 +- yarn-project/cli/.eslintrc.cjs | 1 - yarn-project/cli/CHANGELOG.md | 221 -------- yarn-project/cli/Dockerfile | 10 - yarn-project/cli/README.md | 450 ---------------- yarn-project/cli/aztec-cli-dest | 3 - yarn-project/cli/package.json | 86 --- yarn-project/cli/src/bin/index.ts | 24 - yarn-project/cli/src/client.test.ts | 31 -- yarn-project/cli/src/client.ts | 68 --- yarn-project/cli/src/cmds/add_contract.ts | 46 -- yarn-project/cli/src/cmds/add_note.ts | 22 - yarn-project/cli/src/cmds/block_number.ts | 9 - yarn-project/cli/src/cmds/call.ts | 32 -- yarn-project/cli/src/cmds/check_deploy.ts | 19 - yarn-project/cli/src/cmds/compute_selector.ts | 7 - yarn-project/cli/src/cmds/create_account.ts | 38 -- yarn-project/cli/src/cmds/deploy.ts | 81 --- .../cli/src/cmds/deploy_l1_contracts.ts | 24 - .../cli/src/cmds/example_contracts.ts | 9 - .../cli/src/cmds/generate_p2p_private_key.ts | 10 - .../cli/src/cmds/generate_private_key.ts | 20 - yarn-project/cli/src/cmds/get_account.ts | 15 - yarn-project/cli/src/cmds/get_accounts.ts | 36 -- .../cli/src/cmds/get_contract_data.ts | 32 -- yarn-project/cli/src/cmds/get_logs.ts | 69 --- yarn-project/cli/src/cmds/get_node_info.ts | 13 - yarn-project/cli/src/cmds/get_recipient.ts | 15 - yarn-project/cli/src/cmds/get_recipients.ts | 16 - yarn-project/cli/src/cmds/get_tx_receipt.ts | 15 - yarn-project/cli/src/cmds/inspect_contract.ts | 43 -- .../cli/src/cmds/parse_parameter_struct.ts | 27 - yarn-project/cli/src/cmds/register_account.ts | 21 - .../cli/src/cmds/register_recipient.ts | 18 - yarn-project/cli/src/cmds/send.ts | 40 -- yarn-project/cli/src/encoding.ts | 117 ---- yarn-project/cli/src/github.ts | 3 - yarn-project/cli/src/index.ts | 502 ------------------ yarn-project/cli/src/parse_args.ts | 248 --------- yarn-project/cli/src/test/mocks.ts | 73 --- yarn-project/cli/src/test/utils.test.ts | 157 ------ yarn-project/cli/src/update/common.ts | 16 - yarn-project/cli/src/update/noir.ts | 57 -- yarn-project/cli/src/update/npm.ts | 154 ------ yarn-project/cli/src/update/update.ts | 79 --- yarn-project/cli/src/utils.ts | 235 -------- yarn-project/cli/tsconfig.json | 42 -- yarn-project/end-to-end/Earthfile | 4 - yarn-project/end-to-end/package.json | 1 - .../src/composed/cli_docs_sandbox.test.ts | 389 -------------- yarn-project/end-to-end/src/e2e_cli.test.ts | 35 -- .../src/guides/up_quick_start.test.ts | 3 +- yarn-project/end-to-end/src/shared/cli.ts | 242 --------- yarn-project/end-to-end/src/shared/index.ts | 1 - yarn-project/end-to-end/tsconfig.json | 3 - yarn-project/noir-compiler/aztec-compile-dest | 3 + yarn-project/tsconfig.json | 1 - yarn-project/yarn.lock | 204 +------ 76 files changed, 21 insertions(+), 4316 deletions(-) delete mode 100644 docs/docs/developers/sandbox/references/cli-commands.md delete mode 100644 yarn-project/cli/.eslintrc.cjs delete mode 100644 yarn-project/cli/CHANGELOG.md delete mode 100644 yarn-project/cli/Dockerfile delete mode 100644 yarn-project/cli/README.md delete mode 100755 yarn-project/cli/aztec-cli-dest delete mode 100644 yarn-project/cli/package.json delete mode 100644 yarn-project/cli/src/bin/index.ts delete mode 100644 yarn-project/cli/src/client.test.ts delete mode 100644 yarn-project/cli/src/client.ts delete mode 100644 yarn-project/cli/src/cmds/add_contract.ts delete mode 100644 yarn-project/cli/src/cmds/add_note.ts delete mode 100644 yarn-project/cli/src/cmds/block_number.ts delete mode 100644 yarn-project/cli/src/cmds/call.ts delete mode 100644 yarn-project/cli/src/cmds/check_deploy.ts delete mode 100644 yarn-project/cli/src/cmds/compute_selector.ts delete mode 100644 yarn-project/cli/src/cmds/create_account.ts delete mode 100644 yarn-project/cli/src/cmds/deploy.ts delete mode 100644 yarn-project/cli/src/cmds/deploy_l1_contracts.ts delete mode 100644 yarn-project/cli/src/cmds/example_contracts.ts delete mode 100644 yarn-project/cli/src/cmds/generate_p2p_private_key.ts delete mode 100644 yarn-project/cli/src/cmds/generate_private_key.ts delete mode 100644 yarn-project/cli/src/cmds/get_account.ts delete mode 100644 yarn-project/cli/src/cmds/get_accounts.ts delete mode 100644 yarn-project/cli/src/cmds/get_contract_data.ts delete mode 100644 yarn-project/cli/src/cmds/get_logs.ts delete mode 100644 yarn-project/cli/src/cmds/get_node_info.ts delete mode 100644 yarn-project/cli/src/cmds/get_recipient.ts delete mode 100644 yarn-project/cli/src/cmds/get_recipients.ts delete mode 100644 yarn-project/cli/src/cmds/get_tx_receipt.ts delete mode 100644 yarn-project/cli/src/cmds/inspect_contract.ts delete mode 100644 yarn-project/cli/src/cmds/parse_parameter_struct.ts delete mode 100644 yarn-project/cli/src/cmds/register_account.ts delete mode 100644 yarn-project/cli/src/cmds/register_recipient.ts delete mode 100644 yarn-project/cli/src/cmds/send.ts delete mode 100644 yarn-project/cli/src/encoding.ts delete mode 100644 yarn-project/cli/src/github.ts delete mode 100644 yarn-project/cli/src/index.ts delete mode 100644 yarn-project/cli/src/parse_args.ts delete mode 100644 yarn-project/cli/src/test/mocks.ts delete mode 100644 yarn-project/cli/src/test/utils.test.ts delete mode 100644 yarn-project/cli/src/update/common.ts delete mode 100644 yarn-project/cli/src/update/noir.ts delete mode 100644 yarn-project/cli/src/update/npm.ts delete mode 100644 yarn-project/cli/src/update/update.ts delete mode 100644 yarn-project/cli/src/utils.ts delete mode 100644 yarn-project/cli/tsconfig.json delete mode 100644 yarn-project/end-to-end/src/composed/cli_docs_sandbox.test.ts delete mode 100644 yarn-project/end-to-end/src/e2e_cli.test.ts delete mode 100644 yarn-project/end-to-end/src/shared/cli.ts create mode 100755 yarn-project/noir-compiler/aztec-compile-dest diff --git a/.circleci/config.yml b/.circleci/config.yml index 6b4c8af64ae..49f9588d930 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -443,18 +443,6 @@ jobs: command: build aztec aztec_manifest_key: aztec - cli: - machine: - image: default - resource_class: large - steps: - - *checkout - - *setup_env - - run: - name: "Build and test" - command: build cli - aztec_manifest_key: cli - mainnet-fork: machine: image: default @@ -621,7 +609,6 @@ jobs: should_release || exit 0 deploy_dockerhub noir deploy_dockerhub aztec - deploy_dockerhub cli deploy_dockerhub aztec-faucet deploy_dockerhub mainnet-fork - run: @@ -851,7 +838,6 @@ workflows: # Artifacts - aztec-package: *defaults_yarn_project - - cli: *defaults_yarn_project # Boxes. - boxes: @@ -872,7 +858,6 @@ workflows: requires: - end-to-end - aztec-package - - cli <<: *defaults # Everything that must complete before deployment. diff --git a/aztec-up/bin/aztec-install b/aztec-up/bin/aztec-install index 769ed5fcb8c..1862bf2d400 100755 --- a/aztec-up/bin/aztec-install +++ b/aztec-up/bin/aztec-install @@ -41,7 +41,6 @@ function title() { fi echo -e "This will install the following scripts and update your PATH if necessary:" echo -e " ${bold}${g}aztec${r} - launches various infrastructure subsystems (node, sequencer, prover, pxe, etc)." - echo -e " ${bold}${g}aztec-cli${r} - a command line tool for interfacing and experimenting with infrastructure." echo -e " ${bold}${g}aztec-nargo${r} - aztec's build of nargo, the noir compiler toolchain." echo -e " ${bold}${g}aztec-sandbox${r} - a wrapper around docker-compose that launches services needed for sandbox testing." echo -e " ${bold}${g}aztec-up${r} - a tool to upgrade the aztec toolchain to the latest, or specific versions." @@ -106,7 +105,6 @@ export DOCKER_CLI_HINTS=false if [ -z "${SKIP_PULL:-}" ]; then info "Pulling aztec version $VERSION..." pull_container aztec - pull_container cli pull_container noir fi @@ -123,7 +121,6 @@ info "Installing scripts in $BIN_PATH..." rm -f $BIN_PATH/aztec* install_bin .aztec-run install_bin aztec -install_bin aztec-cli install_bin aztec-sandbox install_bin aztec-up install_bin aztec-nargo diff --git a/boxes/Dockerfile b/boxes/Dockerfile index d1bb35ae159..5809c3a2b5b 100644 --- a/boxes/Dockerfile +++ b/boxes/Dockerfile @@ -13,7 +13,7 @@ COPY --from=noir-projects /usr/src/noir-projects/noir-protocol-circuits/crates/t WORKDIR /usr/src/boxes COPY . . ENV AZTEC_NARGO=/usr/src/noir/noir-repo/target/release/nargo -ENV AZTEC_CLI=/usr/src/yarn-project/cli/aztec-cli-dest +ENV AZTEC_COMPILE=/usr/src/yarn-project/noir-compiler/aztec-compile-dest RUN yarn RUN npx -y playwright@1.42 install --with-deps ENTRYPOINT ["/bin/sh", "-c"] diff --git a/boxes/Earthfile b/boxes/Earthfile index 35ebe466c69..77999a36a41 100644 --- a/boxes/Earthfile +++ b/boxes/Earthfile @@ -12,7 +12,7 @@ build: WORKDIR /usr/src/boxes COPY . . ENV AZTEC_NARGO=/usr/src/noir/noir-repo/target/release/nargo - ENV AZTEC_CLI=/usr/src/yarn-project/cli/aztec-cli-dest + ENV AZTEC_COMPILE=/usr/src/yarn-project/noir-compiler/aztec-compile-dest RUN yarn && yarn build RUN npx -y playwright@1.42 install --with-deps ENTRYPOINT ["/bin/sh", "-c"] diff --git a/boxes/boxes/react/package.json b/boxes/boxes/react/package.json index 0cd42e16ae5..31619d2ea24 100644 --- a/boxes/boxes/react/package.json +++ b/boxes/boxes/react/package.json @@ -7,7 +7,7 @@ "main": "./dist/index.js", "scripts": { "compile": "cd src/contracts && ${AZTEC_NARGO:-aztec-nargo} compile", - "codegen": "${AZTEC_CLI:-aztec-cli} codegen src/contracts/target -o artifacts", + "codegen": "${AZTEC_COMPILE:-aztec-compile} codegen src/contracts/target -o artifacts", "clean": "rm -rf ./dist .tsbuildinfo ./artifacts ./src/contracts/target", "prep": "yarn clean && yarn compile && yarn codegen", "dev": "yarn prep && webpack serve --mode development", diff --git a/boxes/boxes/vanilla/package.json b/boxes/boxes/vanilla/package.json index 4e9c549afc6..92b3ebc7cd2 100644 --- a/boxes/boxes/vanilla/package.json +++ b/boxes/boxes/vanilla/package.json @@ -6,7 +6,7 @@ "type": "module", "scripts": { "compile": "cd src/contracts && ${AZTEC_NARGO:-aztec-nargo} compile", - "codegen": "${AZTEC_CLI:-aztec-cli} codegen src/contracts/target -o artifacts", + "codegen": "${AZTEC_COMPILE:-aztec-compile} codegen src/contracts/target -o artifacts", "clean": "rm -rf ./dest .tsbuildinfo ./artifacts ./src/contracts/target", "prep": "yarn clean && yarn compile && yarn codegen && tsc -b", "dev": "yarn prep && webpack serve --mode development", diff --git a/boxes/contract-only/package.json b/boxes/contract-only/package.json index 93e8c27ca85..13edb7678fd 100644 --- a/boxes/contract-only/package.json +++ b/boxes/contract-only/package.json @@ -6,7 +6,7 @@ "type": "module", "scripts": { "compile": "cd src && ${AZTEC_NARGO:-aztec-nargo} compile", - "codegen": "${AZTEC_CLI:-aztec-cli} codegen target -o artifacts", + "codegen": "${AZTEC_COMPILE:-aztec-compile} codegen target -o artifacts", "clean": "rm -rf ./dest .tsbuildinfo ./artifacts ./target", "prep": "yarn clean && yarn compile && yarn codegen && tsc -b", "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules $(yarn bin jest) --runInBand", diff --git a/build_manifest.yml b/build_manifest.yml index eb20879ecae..7fa488e722f 100644 --- a/build_manifest.yml +++ b/build_manifest.yml @@ -153,7 +153,6 @@ yarn-project-test: rebuildPatterns: - ^yarn-project/.*\.(ts|tsx|js|cjs|mjs|json|html|md|sh|nr|toml|snap)$ - ^yarn-project/Dockerfile$ - - ^yarn-project/cli/aztec-cli dependencies: - bb.js - noir-packages @@ -185,7 +184,6 @@ yarn-project: rebuildPatterns: - ^yarn-project/.*\.(ts|tsx|js|cjs|mjs|json|html|md|sh|nr|toml|snap)$ - ^yarn-project/Dockerfile$ - - ^yarn-project/cli/aztec-cli dependencies: - bb.js - noir-packages @@ -211,14 +209,6 @@ aztec-faucet: - bb.js - noir-packages -# A runnable container, sets entrypoint to be the aztec-cli entrypoint. -cli: - buildDir: yarn-project - projectDir: yarn-project/cli - dependencies: - - yarn-project - multiarch: buildx - # Builds all the boxes. They are then independently tested in the container. boxes: buildDir: boxes diff --git a/docs/docs/developers/aztecjs/guides/call_view_function.md b/docs/docs/developers/aztecjs/guides/call_view_function.md index 4ff12b8e5fd..4eacff80d1b 100644 --- a/docs/docs/developers/aztecjs/guides/call_view_function.md +++ b/docs/docs/developers/aztecjs/guides/call_view_function.md @@ -4,8 +4,6 @@ title: How to Simulate a Function Call This guide explains how to `simulate` a function call using [Aztec.js](../main.md). -To do this from the CLI, go [here](../../sandbox/references/cli-commands.md#calling-an-unconstrained-view-function). - ## Prerequisites You should have a wallet to act as the caller, and a contract that has been deployed. @@ -14,7 +12,7 @@ You can learn how to create wallets from [this guide](./create_account.md). You can learn how to deploy a contract [here](./deploy_contract.md). -## Relevent imports +## Relevant imports You will need to import this from Aztec.js: diff --git a/docs/docs/developers/aztecjs/guides/create_account.md b/docs/docs/developers/aztecjs/guides/create_account.md index 9aacc62a851..de27eea400c 100644 --- a/docs/docs/developers/aztecjs/guides/create_account.md +++ b/docs/docs/developers/aztecjs/guides/create_account.md @@ -4,8 +4,6 @@ title: How to Create a New Account This guide explains how to create a new account using [Aztec.js](../main.md). -To do this from the CLI, go [here](../../sandbox/references/cli-commands.md#creating-accounts). - ## Relevant imports You will need to import these libraries: diff --git a/docs/docs/developers/aztecjs/guides/deploy_contract.md b/docs/docs/developers/aztecjs/guides/deploy_contract.md index 8f16fbe3364..72aab6ab758 100644 --- a/docs/docs/developers/aztecjs/guides/deploy_contract.md +++ b/docs/docs/developers/aztecjs/guides/deploy_contract.md @@ -4,8 +4,6 @@ title: How to Deploy a Contract This guide explains how to deploy a smart contract using [Aztec.js](../main.md). -To do this from the CLI, go [here](../../sandbox/references/cli-commands.md#deploying-a-token-contract). - ## Prerequisites You should have a wallet to act as the deployer, and a contract artifact ready to be deployed. diff --git a/docs/docs/developers/aztecjs/guides/send_transaction.md b/docs/docs/developers/aztecjs/guides/send_transaction.md index cd05c514942..b1daee16121 100644 --- a/docs/docs/developers/aztecjs/guides/send_transaction.md +++ b/docs/docs/developers/aztecjs/guides/send_transaction.md @@ -4,8 +4,6 @@ title: How to Send a Transaction This guide explains how to send a transaction using [Aztec.js](../main.md). -To do this from the CLI, go [here](../../sandbox/references/cli-commands.md#sending-a-transaction). - ## Prerequisites You should have a wallet to act as the transaction sender, and a contract that has been deployed. diff --git a/docs/docs/developers/contracts/compiling_contracts/how_to_compile_contract.md b/docs/docs/developers/contracts/compiling_contracts/how_to_compile_contract.md index 25f87f2d2e4..3f53b1b55d7 100644 --- a/docs/docs/developers/contracts/compiling_contracts/how_to_compile_contract.md +++ b/docs/docs/developers/contracts/compiling_contracts/how_to_compile_contract.md @@ -254,7 +254,7 @@ At the moment, the compiler generates these interfaces from already compiled ABI ## Next steps -Once you have compiled your contracts, you can use the generated artifacts via the `Contract` class in the `aztec.js` package to deploy and interact with them, or rely on the type-safe typescript classes directly. Alternatively, use the CLI [to deploy](../../sandbox/references/cli-commands.md#deploying-a-token-contract) and [interact](../../sandbox/references/cli-commands.md#calling-an-unconstrained-view-function) with them. +Once you have compiled your contracts, you can use the generated artifacts via the `Contract` class in the `aztec.js` package to deploy and interact with them, or rely on the type-safe typescript classes directly. import Disclaimer from "../../../misc/common/\_disclaimer.mdx"; diff --git a/docs/docs/developers/sandbox/references/cli-commands.md b/docs/docs/developers/sandbox/references/cli-commands.md deleted file mode 100644 index b9a5b5fc896..00000000000 --- a/docs/docs/developers/sandbox/references/cli-commands.md +++ /dev/null @@ -1,129 +0,0 @@ ---- -title: CLI Commands ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -Here you will find an incomplete reference to the commands available in the Aztec CLI. - -:::info - -For a full up-to-date list, run `aztec-cli -h`. - -::: - -## Installation - -### Docker - -The CLI will be installed automatically via Docker by running the command to install and start the sandbox, [instructions here](./sandbox-reference.md#with-docker). - -## Update - -The CLI comes with an update command. - -```bash -aztec-cli update . --contract src/contract1 --contract src/contract2 -``` - -This command does a few things to manage updates: - -- It looks for a `package.json` and updates all `@aztec/` dependencies to the versions the sandbox expects. -- It looks for `Nargo.toml` at the `--contract` paths specified and updates all `aztec.nr` dependencies to the versions the sandbox expects. -- It outputs the changes. - -You can specify a version to update to with the `--aztec-version` flag, but it defaults to `latest` so this is typically not necessary. - -:::info - -The update command won't update the CLI itself. To update these follow the [updating instructions which point to our curl command](./sandbox-reference.md#with-docker). - -::: - -## Compile - -You can find more information about compiling contracts [on this page](../../contracts/compiling_contracts/how_to_compile_contract.md). - -## Creating Accounts - -The first thing we want to do is create a couple of accounts. We will use the `create-account` command which will generate a new private key for us, register the account on the sandbox, and deploy a simple account contract which [uses a single key for privacy and authentication](../../../learn/concepts/accounts/keys.md): - -#include_code create-account yarn-project/end-to-end/src/composed/cli_docs_sandbox.test.ts bash - -Once the account is set up, the CLI returns the resulting address, its privacy key, and partial address. You can read more about these [here](../../../learn/concepts/accounts/keys.md#addresses-partial-addresses-and-public-keys). - -Save the Address and Private key as environment variables. We will be using them later. - -```bash -export ADDRESS=
-export PRIVATE_KEY= -``` - -Alternatively, we can also manually generate a private key and use it for creating the account, either via a `-k` option or by setting the `PRIVATE_KEY` environment variable. - -#include_code create-account-from-private-key yarn-project/end-to-end/src/composed/cli_docs_sandbox.test.ts bash - -For all commands that require a user's private key, the CLI will look for the `PRIVATE_KEY` environment variable in absence of an optional argument. - -Let's double check that the accounts have been registered with the sandbox using the `get-accounts` command: - -#include_code get-accounts yarn-project/end-to-end/src/composed/cli_docs_sandbox.test.ts bash - -You will see that a number of accounts exist that we did not create. The Sandbox initializes itself with 3 default accounts. Save one of the printed accounts (not the one that you generated above) in an environment variable. We will use it later. - -```bash -export ADDRESS2= -``` - -## Deploying a Token Contract - -We will now deploy a token contract using the `deploy` command, and set an address of the admin via a constructor argument. You can find the contract we are deploying [here](https://github.com/AztecProtocol/aztec-packages/blob/master/noir-projects/noir-contracts/contracts/token_contract/src/main.nr) (or write it for yourself in [this tutorial!](../../tutorials/writing_token_contract.md)) -Make sure to replace this address with one of the two you created earlier. - -#include_code deploy yarn-project/end-to-end/src/composed/cli_docs_sandbox.test.ts bash - -Save the contract address as an environment variable. We will use it later. - -```bash -export CONTRACT_ADDRESS= -``` - -- `--args` - Arguments to the constructor of the contract. In this case we have set an address as admin. - -The CLI tells us that the contract was successfully deployed. We can use the `check-deploy` command to verify that a contract has been successfully deployed to that address: - -#include_code check-deploy yarn-project/end-to-end/src/composed/cli_docs_sandbox.test.ts bash - -## Sending a Transaction - -We can now send a transaction to the network. We will mint funds in the public domain. -To form and submit the transaction we will use the `send` command of `aztec-cli`. -The `send` command expect the function name as the first unnamed argument and the following named arguments: - -- `--args` - The list of arguments to the function call. -- `--contract-artifact` - The artifact of the contract to call. -- `--contract-address` - The deployed address of the contract to call. -- `--private-key` - The private key of the sender. - -#include_code send yarn-project/end-to-end/src/composed/cli_docs_sandbox.test.ts bash - -We called the [`mint_public`](https://github.com/AztecProtocol/aztec-packages/blob/87fa621347e55f82e36c70515c1824161eee5282/noir-projects/noir-contracts/contracts/token_contract/src/main.nr#L157C10-L157C10) function and provided it with the 2 arguments it expects: the recipient's address and the amount to be minted. Make sure to replace all addresses in this command with yours. - -The command output tells us the details of the transaction such as its hash and status. We can use this hash to query the receipt of the transaction at a later time: - -#include_code get-tx-receipt yarn-project/end-to-end/src/composed/cli_docs_sandbox.test.ts bash - -## Calling an Unconstrained (View) Function - -Now that the `mint_public` tx has been settled we can call the `balance_of_public` unconstrained function: - -#include_code call yarn-project/end-to-end/src/composed/cli_docs_sandbox.test.ts bash - -The `call` command calls a read-only method on a contract, one that will not generate a transaction to be sent to the network. The arguments here are: - -- `--args` - The address for which we want to retrieve the balance. -- `--contract-artifact` - The artifact of the contract we are calling. -- `--contract-address` - The address of the deployed contract - -As you can see from the result, this address has a public balance of 543, as expected. diff --git a/docs/docs/developers/tutorials/writing_private_voting_contract.md b/docs/docs/developers/tutorials/writing_private_voting_contract.md index 1178600c72a..df8a8f03a05 100644 --- a/docs/docs/developers/tutorials/writing_private_voting_contract.md +++ b/docs/docs/developers/tutorials/writing_private_voting_contract.md @@ -191,7 +191,7 @@ aztec-cli call get_vote --contract-artifact ./target/private_voting-Voting.json This should return `1n`. -You can follow this pattern to test `end_vote()` and access control of other functions. Find more information about calling functions from the CLI [here](../sandbox/references/cli-commands.md). +You can follow this pattern to test `end_vote()` and access control of other functions. ## Next steps diff --git a/docs/sidebars.js b/docs/sidebars.js index 5a5e9b00006..f4725933719 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -308,7 +308,6 @@ const sidebars = { label: "References", type: "category", items: [ - "developers/sandbox/references/cli-commands", "developers/sandbox/references/sandbox-reference", "developers/sandbox/references/cheat_codes", { diff --git a/release-please-config.json b/release-please-config.json index 7cf01cd694f..6c5411dc506 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -21,10 +21,6 @@ "component": "aztec-packages", "package-name": "aztec-packages" }, - "yarn-project/cli": { - "release-type": "node", - "component": "aztec-cli" - }, "yarn-project/aztec": { "release-type": "node", "component": "aztec-package" @@ -48,7 +44,7 @@ { "type": "linked-versions", "groupName": "aztec-packages", - "components": ["barretenberg", "barretenberg.js", "aztec-packages", "aztec-package", "aztec-cli"] + "components": ["barretenberg", "barretenberg.js", "aztec-packages", "aztec-package"] }, "sentence-case" ] diff --git a/yarn-project/Dockerfile b/yarn-project/Dockerfile index 7223c9b057a..2038b05b45e 100644 --- a/yarn-project/Dockerfile +++ b/yarn-project/Dockerfile @@ -32,7 +32,7 @@ RUN ln -s /usr/src/yarn-project/node_modules /usr/src/node_modules ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true RUN ./bootstrap.sh -RUN yarn workspaces focus @aztec/cli @aztec/aztec --production && yarn cache clean +RUN yarn workspaces focus @aztec/aztec --production && yarn cache clean # TODO: Use release-please to update package.json directly, and remove this! # It's here to ensure the image rebuilds if the commit tag changes (as the content hash won't). diff --git a/yarn-project/Earthfile b/yarn-project/Earthfile index 6825755a732..0118394dc78 100644 --- a/yarn-project/Earthfile +++ b/yarn-project/Earthfile @@ -49,7 +49,7 @@ build: aztec-prod: FROM +build - RUN yarn workspaces focus @aztec/cli @aztec/aztec --production && yarn cache clean + RUN yarn workspaces focus @aztec/aztec --production && yarn cache clean SAVE ARTIFACT /usr/src /usr/src aztec-prod-slim: @@ -61,11 +61,6 @@ aztec: ENTRYPOINT ["node", "--no-warnings", "/usr/src/yarn-project/aztec/dest/bin/index.js"] EXPOSE 8080 -cli: - FROM +aztec-prod-slim - ENTRYPOINT ["node", "--no-warnings", "/usr/src/yarn-project/cli/dest/bin/index.js"] - EXPOSE 8080 - end-to-end-prod: FROM +build RUN yarn workspaces focus @aztec/end-to-end --production && yarn cache clean diff --git a/yarn-project/cli/.eslintrc.cjs b/yarn-project/cli/.eslintrc.cjs deleted file mode 100644 index e659927475c..00000000000 --- a/yarn-project/cli/.eslintrc.cjs +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('@aztec/foundation/eslint'); diff --git a/yarn-project/cli/CHANGELOG.md b/yarn-project/cli/CHANGELOG.md deleted file mode 100644 index bdb8e7a5808..00000000000 --- a/yarn-project/cli/CHANGELOG.md +++ /dev/null @@ -1,221 +0,0 @@ -# Changelog - -## [0.35.1](https://github.com/AztecProtocol/aztec-packages/compare/aztec-cli-v0.35.0...aztec-cli-v0.35.1) (2024-04-16) - - -### Miscellaneous - -* **aztec-cli:** Synchronize aztec-packages versions - -## [0.35.0](https://github.com/AztecProtocol/aztec-packages/compare/aztec-cli-v0.34.0...aztec-cli-v0.35.0) (2024-04-16) - - -### ⚠ BREAKING CHANGES - -* pay fee for account init ([#5601](https://github.com/AztecProtocol/aztec-packages/issues/5601)) - -### Features - -* Pay fee for account init ([#5601](https://github.com/AztecProtocol/aztec-packages/issues/5601)) ([aca804f](https://github.com/AztecProtocol/aztec-packages/commit/aca804f96ca9e74b6b553449333e195c0639b151)) - -## [0.34.0](https://github.com/AztecProtocol/aztec-packages/compare/aztec-cli-v0.33.0...aztec-cli-v0.34.0) (2024-04-10) - - -### Miscellaneous - -* Reduce log verbosity in local e2e tests ([#5622](https://github.com/AztecProtocol/aztec-packages/issues/5622)) ([c496a10](https://github.com/AztecProtocol/aztec-packages/commit/c496a105eac3b78e53b7d42d4a64e88e3a4759a5)) - -## [0.33.0](https://github.com/AztecProtocol/aztec-packages/compare/aztec-cli-v0.32.1...aztec-cli-v0.33.0) (2024-04-09) - - -### ⚠ BREAKING CHANGES - -* contract_abi-exports ([#5386](https://github.com/AztecProtocol/aztec-packages/issues/5386)) - -### Features - -* **avm:** Integrate AVM with initializers ([#5469](https://github.com/AztecProtocol/aztec-packages/issues/5469)) ([59799f2](https://github.com/AztecProtocol/aztec-packages/commit/59799f273addec01eb0cdea365fe72bcbc8d9493)) -* Contract_abi-exports ([#5386](https://github.com/AztecProtocol/aztec-packages/issues/5386)) ([745d522](https://github.com/AztecProtocol/aztec-packages/commit/745d5229db86b2188f52ab7ccc8f568aef8f5797)) -* Jest fast transpile. no more ts-jest. ([#5530](https://github.com/AztecProtocol/aztec-packages/issues/5530)) ([1912802](https://github.com/AztecProtocol/aztec-packages/commit/19128024292a91d0f947f397ab1b0dc2cd7ef7aa)) - - -### Bug Fixes - -* Update CLI & terraforms with new contract addresses ([#5553](https://github.com/AztecProtocol/aztec-packages/issues/5553)) ([eb73d20](https://github.com/AztecProtocol/aztec-packages/commit/eb73d20e825f3e18acfb68a2b0b7d3501f39e52d)) - -## [0.32.1](https://github.com/AztecProtocol/aztec-packages/compare/aztec-cli-v0.32.0...aztec-cli-v0.32.1) (2024-04-02) - - -### Miscellaneous - -* Explicit type imports ([#5519](https://github.com/AztecProtocol/aztec-packages/issues/5519)) ([2a217de](https://github.com/AztecProtocol/aztec-packages/commit/2a217de4da2031a9f3913a657a4b39201f4483bf)) - -## [0.32.0](https://github.com/AztecProtocol/aztec-packages/compare/aztec-cli-v0.31.0...aztec-cli-v0.32.0) (2024-03-27) - - -### Miscellaneous - -* **aztec-cli:** Synchronize aztec-packages versions - -## [0.31.0](https://github.com/AztecProtocol/aztec-packages/compare/aztec-cli-v0.30.1...aztec-cli-v0.31.0) (2024-03-26) - - -### Features - -* Capture broadcasted functions in node ([#5353](https://github.com/AztecProtocol/aztec-packages/issues/5353)) ([bc05db2](https://github.com/AztecProtocol/aztec-packages/commit/bc05db26c864c9a9dae43f149814e082cdcfd7df)) - - -### Bug Fixes - -* **cli:** Support initializers not named constructor in cli ([#5397](https://github.com/AztecProtocol/aztec-packages/issues/5397)) ([85f14c5](https://github.com/AztecProtocol/aztec-packages/commit/85f14c5dc84c46910b8de498472959fa561d593c)) - -## [0.30.1](https://github.com/AztecProtocol/aztec-packages/compare/aztec-cli-v0.30.0...aztec-cli-v0.30.1) (2024-03-20) - - -### Miscellaneous - -* **aztec-cli:** Synchronize aztec-packages versions - -## [0.30.0](https://github.com/AztecProtocol/aztec-packages/compare/aztec-cli-v0.29.0...aztec-cli-v0.30.0) (2024-03-19) - - -### Features - -* Allow registering contract classes in PXE ([#5291](https://github.com/AztecProtocol/aztec-packages/issues/5291)) ([b811207](https://github.com/AztecProtocol/aztec-packages/commit/b811207bad691f519b31a6391967b9215a9e17d3)), closes [#4055](https://github.com/AztecProtocol/aztec-packages/issues/4055) - - -### Miscellaneous - -* Add gas portal to l1 contract addresses ([#5265](https://github.com/AztecProtocol/aztec-packages/issues/5265)) ([640c89a](https://github.com/AztecProtocol/aztec-packages/commit/640c89a04d7b780795d40e239be3b3db73a16923)), closes [#5022](https://github.com/AztecProtocol/aztec-packages/issues/5022) - -## [0.29.0](https://github.com/AztecProtocol/aztec-packages/compare/aztec-cli-v0.28.1...aztec-cli-v0.29.0) (2024-03-18) - - -### Features - -* Use deployer in address computation ([#5201](https://github.com/AztecProtocol/aztec-packages/issues/5201)) ([258ff4a](https://github.com/AztecProtocol/aztec-packages/commit/258ff4a00208be8695e2e59aecc14d6a92eaac1c)) - - -### Miscellaneous - -* Delete ContractData ([#5258](https://github.com/AztecProtocol/aztec-packages/issues/5258)) ([e516f9b](https://github.com/AztecProtocol/aztec-packages/commit/e516f9b94d1fbdc126a9d0d7d79c571d61914980)) -* Delete ExtendedContractData struct ([#5248](https://github.com/AztecProtocol/aztec-packages/issues/5248)) ([8ae0c13](https://github.com/AztecProtocol/aztec-packages/commit/8ae0c13ceaf8a1f3db09d0e61f0a3781c8926ca6)) -* Removing redundant receipts check ([#5271](https://github.com/AztecProtocol/aztec-packages/issues/5271)) ([5ab07fb](https://github.com/AztecProtocol/aztec-packages/commit/5ab07fb8b395b6edbda6167845c7ea864e9395a3)) - -## [0.28.1](https://github.com/AztecProtocol/aztec-packages/compare/aztec-cli-v0.28.0...aztec-cli-v0.28.1) (2024-03-14) - - -### Miscellaneous - -* **aztec-cli:** Synchronize aztec-packages versions - -## [0.28.0](https://github.com/AztecProtocol/aztec-packages/compare/aztec-cli-v0.27.2...aztec-cli-v0.28.0) (2024-03-14) - - -### ⚠ BREAKING CHANGES - -* Support contracts with no constructor ([#5175](https://github.com/AztecProtocol/aztec-packages/issues/5175)) - -### Features - -* Support contracts with no constructor ([#5175](https://github.com/AztecProtocol/aztec-packages/issues/5175)) ([df7fa32](https://github.com/AztecProtocol/aztec-packages/commit/df7fa32f34e790231e091c38a4a6e84be5407763)) - -## [0.27.2](https://github.com/AztecProtocol/aztec-packages/compare/aztec-cli-v0.27.1...aztec-cli-v0.27.2) (2024-03-13) - - -### Miscellaneous - -* **aztec-cli:** Synchronize aztec-packages versions - -## [0.27.1](https://github.com/AztecProtocol/aztec-packages/compare/aztec-cli-v0.27.0...aztec-cli-v0.27.1) (2024-03-12) - - -### Miscellaneous - -* **aztec-cli:** Synchronize aztec-packages versions - -## [0.27.0](https://github.com/AztecProtocol/aztec-packages/compare/aztec-cli-v0.26.6...aztec-cli-v0.27.0) (2024-03-12) - - -### Miscellaneous - -* Remove old contract deployment flow ([#4970](https://github.com/AztecProtocol/aztec-packages/issues/4970)) ([6d15947](https://github.com/AztecProtocol/aztec-packages/commit/6d1594736e96cd744ea691a239fcd3a46bdade60)) - -## [0.26.6](https://github.com/AztecProtocol/aztec-packages/compare/aztec-cli-v0.26.5...aztec-cli-v0.26.6) (2024-03-08) - - -### Features - -* Show bytecode size per function in CLI inspect-contract ([#5059](https://github.com/AztecProtocol/aztec-packages/issues/5059)) ([cb9fdc6](https://github.com/AztecProtocol/aztec-packages/commit/cb9fdc6b5069ee2ab8fb1f68f369e360039fa18b)) - -## [0.26.5](https://github.com/AztecProtocol/aztec-packages/compare/aztec-cli-v0.26.4...aztec-cli-v0.26.5) (2024-03-07) - - -### Miscellaneous - -* **aztec-cli:** Synchronize aztec-packages versions - -## [0.26.4](https://github.com/AztecProtocol/aztec-packages/compare/aztec-cli-v0.26.3...aztec-cli-v0.26.4) (2024-03-06) - - -### Miscellaneous - -* **aztec-cli:** Synchronize aztec-packages versions - -## [0.26.3](https://github.com/AztecProtocol/aztec-packages/compare/aztec-cli-v0.26.2...aztec-cli-v0.26.3) (2024-03-06) - - -### Miscellaneous - -* **aztec-cli:** Synchronize aztec-packages versions - -## [0.26.2](https://github.com/AztecProtocol/aztec-packages/compare/aztec-cli-v0.26.1...aztec-cli-v0.26.2) (2024-03-06) - - -### Miscellaneous - -* **aztec-cli:** Synchronize aztec-packages versions - -## [0.26.1](https://github.com/AztecProtocol/aztec-packages/compare/aztec-cli-v0.26.0...aztec-cli-v0.26.1) (2024-03-06) - - -### Miscellaneous - -* **aztec-cli:** Synchronize aztec-packages versions - -## [0.26.0](https://github.com/AztecProtocol/aztec-packages/compare/aztec-cli-v0.25.0...aztec-cli-v0.26.0) (2024-03-05) - - -### ⚠ BREAKING CHANGES - -* Use new deployment flow in ContractDeployer ([#4497](https://github.com/AztecProtocol/aztec-packages/issues/4497)) -* move noir out of yarn-project ([#4479](https://github.com/AztecProtocol/aztec-packages/issues/4479)) -* note type ids ([#4500](https://github.com/AztecProtocol/aztec-packages/issues/4500)) -* Include contract class id in deployment info ([#4223](https://github.com/AztecProtocol/aztec-packages/issues/4223)) -* aztec binary ([#3927](https://github.com/AztecProtocol/aztec-packages/issues/3927)) - -### Features - -* **avm-transpiler:** Brillig to AVM transpiler ([#4227](https://github.com/AztecProtocol/aztec-packages/issues/4227)) ([c366c6e](https://github.com/AztecProtocol/aztec-packages/commit/c366c6e6d5c9f28a5dc92a303dcab4a23fb2d84e)) -* Aztec binary ([#3927](https://github.com/AztecProtocol/aztec-packages/issues/3927)) ([12356d9](https://github.com/AztecProtocol/aztec-packages/commit/12356d9e34994a239d5612798c1bc82fa3d26562)) -* Aztec.js API for registering a contract class ([#4469](https://github.com/AztecProtocol/aztec-packages/issues/4469)) ([d566c74](https://github.com/AztecProtocol/aztec-packages/commit/d566c74786a1ea960e9beee4599c1fdedc7ae6eb)) -* Include contract class id in deployment info ([#4223](https://github.com/AztecProtocol/aztec-packages/issues/4223)) ([0ed4126](https://github.com/AztecProtocol/aztec-packages/commit/0ed41261ae43e21f695c35ad753e07adfaaa55f9)), closes [#4054](https://github.com/AztecProtocol/aztec-packages/issues/4054) -* Moving the unbox option to npx command ([#4718](https://github.com/AztecProtocol/aztec-packages/issues/4718)) ([4c3bb92](https://github.com/AztecProtocol/aztec-packages/commit/4c3bb9294fc10ff4663275c952e277eaa7ecd647)) -* Note type ids ([#4500](https://github.com/AztecProtocol/aztec-packages/issues/4500)) ([e1da2fd](https://github.com/AztecProtocol/aztec-packages/commit/e1da2fd509c75d7886b95655d233165e087cf2ed)) -* Parallel native/wasm bb builds. Better messaging around using ci cache. ([#4766](https://github.com/AztecProtocol/aztec-packages/issues/4766)) ([a924e55](https://github.com/AztecProtocol/aztec-packages/commit/a924e55393daa89fbba3a87cf019977286104b59)) -* Use new deployment flow in ContractDeployer ([#4497](https://github.com/AztecProtocol/aztec-packages/issues/4497)) ([0702dc6](https://github.com/AztecProtocol/aztec-packages/commit/0702dc6988149258124184b85d38db930effe0e7)) - - -### Bug Fixes - -* Add new oracle contract to devnet in CI ([#4687](https://github.com/AztecProtocol/aztec-packages/issues/4687)) ([920fa10](https://github.com/AztecProtocol/aztec-packages/commit/920fa10d4d5fb476cd6d868439310452f6e8dcc5)) -* Load contract artifact from json ([#4352](https://github.com/AztecProtocol/aztec-packages/issues/4352)) ([47a0a79](https://github.com/AztecProtocol/aztec-packages/commit/47a0a79f6beaa241eafc94fcae84103488a9dcef)) - - -### Miscellaneous - -* **docs:** Fix a few links to docs ([#4260](https://github.com/AztecProtocol/aztec-packages/issues/4260)) ([1c8ea49](https://github.com/AztecProtocol/aztec-packages/commit/1c8ea497fb1d64da64cb240917a60d57bd1efef8)) -* Move noir out of yarn-project ([#4479](https://github.com/AztecProtocol/aztec-packages/issues/4479)) ([1fe674b](https://github.com/AztecProtocol/aztec-packages/commit/1fe674b046c694e1cbbbb2edaf5a855828bb5340)), closes [#4107](https://github.com/AztecProtocol/aztec-packages/issues/4107) -* Remove stubbed docs ([#4196](https://github.com/AztecProtocol/aztec-packages/issues/4196)) ([25a4bc4](https://github.com/AztecProtocol/aztec-packages/commit/25a4bc490a53304110e7e1f79e99f4c8b7639164)) -* Squash yp ypb + other build improvements. ([#4901](https://github.com/AztecProtocol/aztec-packages/issues/4901)) ([be5855c](https://github.com/AztecProtocol/aztec-packages/commit/be5855cdbd1993155bd228afbeafee2c447b46a5)) -* Updating viem ([#4783](https://github.com/AztecProtocol/aztec-packages/issues/4783)) ([23bc26a](https://github.com/AztecProtocol/aztec-packages/commit/23bc26a4859d9777c3e6dd49e351a4e6b13a989a)) diff --git a/yarn-project/cli/Dockerfile b/yarn-project/cli/Dockerfile deleted file mode 100644 index c69606b278c..00000000000 --- a/yarn-project/cli/Dockerfile +++ /dev/null @@ -1,10 +0,0 @@ -FROM aztecprotocol/yarn-project AS yarn-project -ENTRYPOINT ["node", "--no-warnings", "/usr/src/yarn-project/cli/dest/bin/index.js"] - -# The version has been updated in yarn-project. -# Adding COMMIT_TAG here to rebuild versioned image. -ARG COMMIT_TAG="" - -RUN mkdir /cache && chmod 777 /cache -ENV XDG_CACHE_HOME /cache -VOLUME "/cache" diff --git a/yarn-project/cli/README.md b/yarn-project/cli/README.md deleted file mode 100644 index 56bf674e842..00000000000 --- a/yarn-project/cli/README.md +++ /dev/null @@ -1,450 +0,0 @@ -# Aztec CLI Documentation - -The Aztec CLI `aztec-cli` is a command-line interface (CLI) tool for interacting with Aztec. It provides various commands for deploying contracts, creating accounts, interacting with contracts, and retrieving blockchain data. - -## Installation - -1. In your terminal, download the sandbox by running - -``` -bash -i <(curl -s install.aztec.network) -``` - -2. Verify the installation: After the installation is complete, run the following command to verify that `aztec-cli` is installed correctly: - - ```shell - aztec-cli --version - ``` - - This command will display the version number of `aztec-cli` if the installation was successful. - -## Usage - -To use `aztec-cli`, open a terminal or command prompt and run the `aztec-cli` command followed by the desired command and its options. - -Here's the basic syntax for running a command: - -```shell -aztec-cli [options] -``` - -Replace `` with the actual command you want to execute and `[options]` with any optional flags or parameters required by the command. - -### Environment Variables - -Some options can be set globally as environment variables to avoid having to re-enter them every time you call `aztec-cli.` -These options are: - -- `PRIVATE_KEY` -> `-k, --private-key` for all commands that require a private key. -- `PUBLIC_KEY` -> `-k, --public-key` for all commands that require a public key. -- `PXE_URL` -> `-u, --rpc-url` for commands that require a PXE -- `API_KEY` -> `a, --api-key` for `deploy-l1-contracts`. -- `ETHEREUM_RPC_HOST` -> `-u, --rpc-url` for `deploy-l1-contracts`. - -So if for example you are running your Private eXecution Environment (PXE) remotely you can do: - -```shell -export PXE_URL=http://external.site/rpc:8080 -aztec-cli deploy my_contract.json -``` - -And this will send the request to `http://external.site/rpc:8080`. - -**NOTE**: Entering an option value will override the environment variable. - -## Available Commands - -`aztec-cli` provides the following commands for interacting with Aztec: - -### deploy-l1-contracts - -Deploys all necessary Ethereum contracts for Aztec. - -Syntax: - -```shell -aztec-cli deploy-l1-contracts [rpcUrl] [options] -``` - -- `rpcUrl` (optional): URL of the Ethereum host. Chain identifiers `localhost` and `testnet` can be used. Default: `http://localhost:8545`. - -Options: - -- `-a, --api-key `: API key for the Ethereum host. -- `-p, --private-key `: The private key to use for deployment. -- `-m, --mnemonic `: The mnemonic to use in deployment. Default: `test test test test test test test test test test test junk`. - -This command deploys all the necessary Ethereum contracts required for Aztec. It creates the rollup contract, registry contract, inbox contract, outbox contract, and contract deployment emitter. The command displays the addresses of the deployed contracts. - -Example usage: - -```shell -aztec-cli deploy-l1-contracts -``` - -### create-private-key - -Generates a 32-byte private key. - -Syntax: - -```shell -aztec-cli create-private-key [options] -``` - -Options: - -- `-m, --mnemonic`: A mnemonic string that can be used for the private key generation. - -This command generates a random 32-byte private key or derives one from the provided mnemonic string. It displays the generated private key. - -Example usage: - -```shell -aztec-cli create-private-key -``` - -### create-account - -Creates an Aztec account that can be used for transactions. - -Syntax: - -```shell -aztec-cli create-account [options] -``` - -Options: - -- `-k, --private-key`: Private key to use for the account generation. Uses a random key by default. -- `-u, --rpc-url `: URL of PXE Service. Default: `http://localhost:8080`. - -This command creates an Aztec account that can be used for transactions. It generates a new account with a private key or uses the provided private key. The command displays the account's address and public key. - -Example usage: - -```shell -aztec-cli create-account -``` - -### deploy - -Deploys a compiled Aztec.nr contract to Aztec. - -Syntax: - -```shell -aztec-cli deploy [options] -``` - -Options: - -- `-c, --contract-artifact `: Path to the compiled Aztec.nr contract's artifact file in JSON format. You can also use one of Aztec's example contracts found in [@aztec/noir-contracts](https://www.npmjs.com/package/@aztec/noir-contracts), e.g. PrivateTokenContractArtifact. You can get a full ist of the available contracts with `aztec-cli example-contracts` -- `-a, --args ` (optional): Contract constructor arguments Default: []. -- `-u, --rpc-url `: URL of PXE Service. Default: `http://localhost:8080`. -- `-k, --public-key `: Public key of the deployer. If not provided, it will check the RPC for existing ones. - -This command deploys a compiled Aztec.nr contract to Aztec. It requires the path to the contract's artifact file in JSON format. Optionally, you can specify the public key of the deployer and provide constructor arguments for the contract. The command displays the address of the deployed contract. - -Example usage: - -```shell -aztec-cli deploy -c path/to/contract.artifact.json -a ...args -``` - -With an Aztec example contract: - -```shell -aztec-cli deploy -c PrivateTokenContractArtifact -a 333 0x134567890abcdef -``` - -### check-deploy - -Checks if a contract is deployed to the specified Aztec address. - -Syntax: - -```shell -aztec-cli check-deploy [options] -``` - -Options: - -- `-ca, --contract-address
`: An Aztec address to check if the contract has been deployed to. -- `-u, --rpc-url `: URL of PXE Service. Default: `http://localhost:8080`. - -This command checks if a contract is deployed to the specified Aztec address. It verifies if the contract is present at the given address and displays the result. - -Example usage: - -```shell -aztec-cli check-deploy -ca 0x123456789abcdef123456789abcdef12345678 -``` - -### get-tx-receipt - -Gets the receipt for the specified transaction hash. - -Syntax: - -```shell -aztec-cli get-tx-receipt [options] -``` - -- `txHash`: A transaction hash to get the receipt for. - -Options: - -- `-u, --rpc-url `: URL of PXE Service. Default: `http://localhost:8080`. - -This command retrieves and displays the receipt for the specified transaction hash. It shows details such as the transaction status, block number, and block hash. - -Example usage: - -```shell -aztec-cli get-tx-receipt 0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef12345678 -``` - -### get-contract-data - -Gets information about the Aztec contract deployed at the specified address. - -Syntax: - -```shell -aztec-cli get-contract-data [options] -``` - -- `contractAddress`: Aztec address of the contract. - -Options: - -- `-u, --rpc-url `: URL of PXE Service. Default: `http://localhost:8080`. -- `-b, --include-bytecode`: Include the contract's public function bytecode, if any. - -This command retrieves and displays information about the Aztec contract deployed at the specified address. It shows the contract address, portal contract address, and optionally, the bytecode of the contract's public functions. - -Example usage: - -```shell -aztec-cli get-contract-data 0x123456789abcdef123456789abcdef12345678 -``` - -### register-recipient - -Register a recipient account on the PXE (called recipient because we can only send notes to this account and not receive them via this PXE). -To read about how keys are generated and used, head to our docs [here](https://github.com/AztecProtocol/aztec-packages/blob/master/docs/docs/aztec/developer/wallet-providers/keys.md#addresses-partial-addresses-and-public-keys). - -Syntax: - -```shell -aztec-cli register-recipient [options] -``` - -Options: - -- `-a, --address `: The account's Aztec address. -- `-p, --public-key `: 'The account public key.' -- `-pa, --partial-address `: URL of PXE Service. Default: `http://localhost:8080`. - -Example usage: - -```shell -aztec-cli register-recipient -p 0x20d9d93c4a9eb2b4bdb70ead07d28d1edb74bfd78443a8c36b098b024cd26f0e0647f5dbe3619453f42eb788c2beed0294c84676425047aadac23294605c4af9 -a 0x111fdc0f6bf831ca59f05863199762d643b782699d7ce6feaae40a923baf60af -pa 0x72bf7c9537875b0af267b4a8c497927e251f5988af6e30527feb16299042ed -``` - -### get-accounts - -Gets all the Aztec accounts stored in a PXE. - -Syntax: - -```shell -aztec-cli get-accounts [options] -``` - -Options: - -- `-u, --rpc-url `: URL of PXE Service. Default: `http://localhost:8080`. - -This command retrieves and displays all the Aztec accounts available in the system. - -Example usage: - -```shell -aztec-cli get-accounts -``` - -### get-account - -Gets an account given its Aztec address. - -Syntax: - -```shell -aztec-cli get-account
[options] -``` - -- `address`: The Aztec address to get the public key for. - -Options: - -- `-u, --rpc-url `: URL of PXE Service. Default: `http://localhost:8080`. - -This command retrieves and displays the public key of an account given its Aztec address. - -Example usage: - -```shell -aztec-cli get-account 0x123456789abcdef123456789abcdef12345678 -``` - -### send - -Sends a transaction invoking a function on an Aztec contract. - -Syntax: - -```shell -aztec-cli send --args [functionArgs...] --contract-artifact --contract-address --private-key -``` - -- `functionName`: Name of the function to call. - -Options: - -- `'-a, --args [functionArgs...]` (optional): Function arguments. Default: []. -- `-c, --contract-artifact `: The compiled contract's artifact in JSON format. You can also use one of Aztec's example contracts found in (@aztec/noir-contracts)[https://www.npmjs.com/package/@aztec/noir-contracts], e.g. PrivateTokenContractArtifact. -- `-ca, --contract-address
`: Address of the contract. -- `-k, --private-key `: The sender's private key. -- `-u, --rpc-url `: URL of PXE Service. Default: `http://localhost:8080`. - -This command calls a function on an Aztec contract. It requires the contract's artifact, address, function name, and optionally, function arguments. The command executes the function call and displays the transaction details. - -Example usage: - -```shell -aztec-cli send transfer -ca 0x123456789abcdef123456789abcdef12345678 -a 100 -c path/to/artifact.json -``` - -### call - -Calls a view (read-only) function on a deployed contract. -Unlike transactions, view calls do not modify the state of the contract. - -Syntax: - -```shell -aztec-cli call -a [functionArgs...] -c -ca -f -``` - -- `functionName`: Name of the function to view. - -Options: - -- `'-a, --args [functionArgs...]` (optional): Function arguments. Default: []. -- `-c, --contract-artifact `: The compiled contract's artifact in JSON format. You can also use one of Aztec's example contracts found in (@aztec/noir-contracts)[https://www.npmjs.com/package/@aztec/noir-contracts], e.g. PrivateTokenContractArtifact. -- `-ca, --contract-address
`: Address of the contract. -- `-f, --from `: Address of the caller. If empty, first account in the Private eXecution Environment (PXE) will be used. -- `-u, --rpc-url `: URL of PXE Service. Default: `http://localhost:8080`. - -This command simulates the execution of a view function on a deployed contract without modifying the state. It requires the contract's artifact, address, function name, and optionally, function arguments. The command displays the result of the view function. - -Example usage: - -```shell -aztec-cli call balanceOf -c path/to/contract.artifact.json -ca 0x123456789abcdef123456789abcdef12345678 -a balanceOf 0xabcdef1234567890abcdef1234567890abcdef12 -``` - -### parse-parameter-struct - -Helper for parsing an encoded string into a contract's parameter struct. - -Syntax: - -```shell -aztec-cli parse-parameter-struct -``` - -- `encodedString`: The encoded hex string. -- `contractArtifact`: The compiled contract's artifact in JSON format. -- `parameterName`: The name of the struct parameter to decode into. - -This command is a helper for parsing an encoded hex string into a contract's parameter struct. It requires the encoded string, the contract's artifact, and the name of the struct parameter. The command decodes the string and displays the struct data. - -Example usage: - -```shell -aztec-cli parse-parameter-struct 0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890 path/to/contract.artifact.json paramName -``` - -### get-logs - -Applies filter and returns the resulting unencrypted logs. -The filter is applied by doing an intersection of all its params. - -Syntax: - -```shell -aztec-cli get-logs --fromBlock -``` - -Options: - -- `-u, --rpc-url `: URL of PXE Service. Default: `http://localhost:8080`. - -This command retrieves and displays all the unencrypted logs from L2 blocks in the specified range or from a specific transaction. -Example usage: - -```shell -aztec-cli get-logs --txHash 21fef567e01f8508e30843ebcef9c5f6ff27b29d66783cfcdbd070c3a9174234 -aztec-cli get-logs --fromBlock 4 --toBlock 5 --contractAddress 0x1db5f68861c5960c37205d3d5b23466240359c115c49e45982865ea7ace69a02 -aztec-cli get-logs --fromBlock 4 --toBlock 5 --contractAddress 0x1db5f68861c5960c37205d3d5b23466240359c115c49e45982865ea7ace69a02 --selector 00000005 -``` - -Run `aztec-cli get-logs --help` for more information on the filtering options. - -### block-number - -Gets the current Aztec L2 block number. - -Syntax: - -```shell -aztec-cli block-number -``` - -Options: - -- `-u, --rpc-url `: URL of PXE Service. Default: `http://localhost:8080`. - -This command retrieves and displays the current Aztec L2 block number. - -### example-contracts - -Lists the contracts available in [@aztec/noir-contracts](https://github.com/AztecProtocol/aztec-packages/tree/master/noir-contracts) - -Syntax: - -```shell -aztec-cli example-contracts -``` - -### get-node-info - -Gets information of an Aztec node at the specified URL. - -Syntax: - -```shell -aztec-cli get-node-info -``` - -Options: - -- `-u, --rpc-url `: URL of PXE Service. Default: `http://localhost:8080`. - -## Conclusion - -That covers the available commands and their usage in the `aztec-cli`. You can now use these commands to interact with Aztec and perform various actions such as deploying contracts, creating accounts, executing functions, and retrieving blockchain data. diff --git a/yarn-project/cli/aztec-cli-dest b/yarn-project/cli/aztec-cli-dest deleted file mode 100755 index d2fc2aa3694..00000000000 --- a/yarn-project/cli/aztec-cli-dest +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh -SCRIPT_PATH=$(dirname $(realpath $0)) -node --no-warnings $SCRIPT_PATH/dest/bin/index.js $@ diff --git a/yarn-project/cli/package.json b/yarn-project/cli/package.json deleted file mode 100644 index e1a887fb1cb..00000000000 --- a/yarn-project/cli/package.json +++ /dev/null @@ -1,86 +0,0 @@ -{ - "name": "@aztec/cli", - "version": "0.35.1", - "type": "module", - "main": "./dest/index.js", - "bin": { - "aztec-cli": "./dest/bin/index.js" - }, - "typedocOptions": { - "entryPoints": [ - "./src/index.ts" - ], - "name": "Aztec CLI", - "tsconfig": "./tsconfig.json" - }, - "scripts": { - "build": "yarn clean && tsc -b", - "build:dev": "tsc -b --watch", - "clean": "rm -rf ./dest .tsbuildinfo", - "formatting": "run -T prettier --check ./src && run -T eslint ./src", - "formatting:fix": "run -T eslint --fix ./src && run -T prettier -w ./src", - "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --passWithNoTests", - "start": "node --no-warnings ./dest/bin/index.js" - }, - "inherits": [ - "../package.common.json" - ], - "jest": { - "moduleNameMapper": { - "^(\\.{1,2}/.*)\\.[cm]?js$": "$1" - }, - "testRegex": "./src/.*\\.test\\.(js|mjs|ts)$", - "rootDir": "./src", - "transform": { - "^.+\\.tsx?$": [ - "@swc/jest" - ] - }, - "extensionsToTreatAsEsm": [ - ".ts" - ] - }, - "dependencies": { - "@aztec/accounts": "workspace:^", - "@aztec/aztec.js": "workspace:^", - "@aztec/circuit-types": "workspace:^", - "@aztec/circuits.js": "workspace:^", - "@aztec/ethereum": "workspace:^", - "@aztec/foundation": "workspace:^", - "@aztec/l1-artifacts": "workspace:^", - "@aztec/noir-compiler": "workspace:^", - "@aztec/noir-contracts.js": "workspace:^", - "@aztec/types": "workspace:^", - "@iarna/toml": "^2.2.5", - "@libp2p/peer-id-factory": "^3.0.4", - "commander": "^9.0.0", - "jszip": "^3.10.1", - "lodash.startcase": "^4.4.0", - "node-fetch": "^3.3.2", - "semver": "^7.5.4", - "source-map-support": "^0.5.21", - "tslib": "^2.4.0", - "viem": "^2.7.15" - }, - "devDependencies": { - "@jest/globals": "^29.5.0", - "@types/jest": "^29.5.0", - "@types/lodash.startcase": "^4.4.7", - "@types/node": "^18.7.23", - "@types/semver": "^7.5.2", - "@types/source-map-support": "^0.5.10", - "jest": "^29.5.0", - "jest-mock-extended": "^3.0.5", - "ts-node": "^10.9.1", - "typescript": "^5.0.4" - }, - "files": [ - "dest", - "src", - "!*.test.*" - ], - "types": "./dest/index.d.ts", - "engines": { - "node": ">=18" - } -} diff --git a/yarn-project/cli/src/bin/index.ts b/yarn-project/cli/src/bin/index.ts deleted file mode 100644 index 0d79e796d50..00000000000 --- a/yarn-project/cli/src/bin/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env -S node --no-warnings -import { createConsoleLogger, createDebugLogger } from '@aztec/foundation/log'; - -import 'source-map-support/register.js'; - -import { getProgram } from '../index.js'; - -const debugLogger = createDebugLogger('aztec:cli-client'); -const log = createConsoleLogger(); - -/** CLI main entrypoint */ -async function main() { - process.once('SIGINT', () => process.exit(0)); - process.once('SIGTERM', () => process.exit(0)); - - const program = getProgram(log, debugLogger); - await program.parseAsync(process.argv); -} - -main().catch(err => { - log(`Error in command execution`); - log(err); - process.exit(1); -}); diff --git a/yarn-project/cli/src/client.test.ts b/yarn-project/cli/src/client.test.ts deleted file mode 100644 index ad21f399256..00000000000 --- a/yarn-project/cli/src/client.test.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { type NodeInfo } from '@aztec/aztec.js'; -import { type PXE } from '@aztec/circuit-types'; - -import { type MockProxy, mock } from 'jest-mock-extended'; - -import { checkServerVersion } from './client.js'; - -describe('client', () => { - describe('checkServerVersion', () => { - let pxe: MockProxy; - - beforeEach(() => { - pxe = mock(); - }); - - it('checks versions match', async () => { - pxe.getNodeInfo.mockResolvedValue({ nodeVersion: '0.1.0-alpha47' } as NodeInfo); - await checkServerVersion(pxe, '0.1.0-alpha47'); - }); - - it('reports mismatch on older pxe version', async () => { - pxe.getNodeInfo.mockResolvedValue({ nodeVersion: '0.1.0-alpha47' } as NodeInfo); - await expect(checkServerVersion(pxe, '0.1.0-alpha48')).rejects.toThrow(/is older than the expected by this CLI/); - }); - - it('reports mismatch on newer pxe version', async () => { - pxe.getNodeInfo.mockResolvedValue({ nodeVersion: '0.1.0-alpha48' } as NodeInfo); - await expect(checkServerVersion(pxe, '0.1.0-alpha47')).rejects.toThrow(/is newer than the expected by this CLI/); - }); - }); -}); diff --git a/yarn-project/cli/src/client.ts b/yarn-project/cli/src/client.ts deleted file mode 100644 index 8b3d55c37d9..00000000000 --- a/yarn-project/cli/src/client.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { type PXE, createPXEClient } from '@aztec/aztec.js'; -import { type DebugLogger } from '@aztec/foundation/log'; -import { fileURLToPath } from '@aztec/foundation/url'; - -import { readFileSync } from 'fs'; -import { dirname, resolve } from 'path'; -import { gtr, ltr, satisfies, valid } from 'semver'; - -/** - * Creates a PXE client with a given set of retries on non-server errors. - * Checks that PXE matches the expected version, and warns if not. - * @param rpcUrl - URL of the RPC server wrapping the PXE. - * @param logger - Debug logger to warn version incompatibilities. - * @returns A PXE client. - */ -export async function createCompatibleClient(rpcUrl: string, logger: DebugLogger) { - const pxe = createPXEClient(rpcUrl); - const packageJsonPath = resolve(dirname(fileURLToPath(import.meta.url)), '../package.json'); - const packageJsonContents = JSON.parse(readFileSync(packageJsonPath).toString()); - const expectedVersionRange = packageJsonContents.version; - - try { - await checkServerVersion(pxe, expectedVersionRange); - } catch (err) { - if (err instanceof VersionMismatchError) { - logger.warn(err.message); - } else { - throw err; - } - } - - return pxe; -} - -/** Mismatch between server and client versions. */ -class VersionMismatchError extends Error {} - -/** - * Checks that Private eXecution Environment (PXE) version matches the expected one by this CLI. Throws if not. - * @param pxe - PXE client. - * @param expectedVersionRange - Expected version by CLI. - */ -export async function checkServerVersion(pxe: PXE, expectedVersionRange: string) { - const serverName = 'Aztec Node'; - const { nodeVersion } = await pxe.getNodeInfo(); - if (!nodeVersion) { - throw new VersionMismatchError(`Couldn't determine ${serverName} version. You may run into issues.`); - } - if (!nodeVersion || !valid(nodeVersion)) { - throw new VersionMismatchError( - `Missing or invalid version identifier for ${serverName} (${nodeVersion ?? 'empty'}).`, - ); - } else if (!satisfies(nodeVersion, expectedVersionRange)) { - if (gtr(nodeVersion, expectedVersionRange)) { - throw new VersionMismatchError( - `${serverName} is running version ${nodeVersion} which is newer than the expected by this CLI (${expectedVersionRange}). Consider upgrading your CLI to a newer version.`, - ); - } else if (ltr(nodeVersion, expectedVersionRange)) { - throw new VersionMismatchError( - `${serverName} is running version ${nodeVersion} which is older than the expected by this CLI (${expectedVersionRange}). Consider upgrading your ${serverName} to a newer version.`, - ); - } else { - throw new VersionMismatchError( - `${serverName} is running version ${nodeVersion} which does not match the expected by this CLI (${expectedVersionRange}).`, - ); - } - } -} diff --git a/yarn-project/cli/src/cmds/add_contract.ts b/yarn-project/cli/src/cmds/add_contract.ts deleted file mode 100644 index 2c29aedf3f8..00000000000 --- a/yarn-project/cli/src/cmds/add_contract.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { - AztecAddress, - type ContractInstanceWithAddress, - EthAddress, - Fr, - getContractClassFromArtifact, -} from '@aztec/aztec.js'; -import { computeContractAddressFromInstance } from '@aztec/circuits.js/contract'; -import { type DebugLogger, type LogFn } from '@aztec/foundation/log'; - -import { createCompatibleClient } from '../client.js'; -import { getContractArtifact } from '../utils.js'; - -export async function addContract( - rpcUrl: string, - contractArtifactPath: string, - address: AztecAddress, - initializationHash: Fr, - salt: Fr, - publicKeysHash: Fr | undefined, - portalContract: EthAddress | undefined, - deployer: AztecAddress | undefined, - debugLogger: DebugLogger, - log: LogFn, -) { - const artifact = await getContractArtifact(contractArtifactPath); - const instance: ContractInstanceWithAddress = { - version: 1, - salt, - initializationHash, - contractClassId: getContractClassFromArtifact(artifact).id, - portalContractAddress: portalContract ?? EthAddress.ZERO, - publicKeysHash: publicKeysHash ?? Fr.ZERO, // TODO(https://github.com/AztecProtocol/aztec-packages/issues/5862) - address, - deployer: deployer ?? AztecAddress.ZERO, - }; - const computed = computeContractAddressFromInstance(instance); - if (!computed.equals(address)) { - throw new Error(`Contract address ${address.toString()} does not match computed address ${computed.toString()}`); - } - - const client = await createCompatibleClient(rpcUrl, debugLogger); - - await client.registerContract({ artifact, instance }); - log(`\nContract added to PXE at ${address.toString()} with class ${instance.contractClassId.toString()}\n`); -} diff --git a/yarn-project/cli/src/cmds/add_note.ts b/yarn-project/cli/src/cmds/add_note.ts deleted file mode 100644 index f6359bd5c1c..00000000000 --- a/yarn-project/cli/src/cmds/add_note.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { type AztecAddress, type Fr } from '@aztec/aztec.js'; -import { ExtendedNote, Note, type TxHash } from '@aztec/circuit-types'; -import { type DebugLogger } from '@aztec/foundation/log'; - -import { createCompatibleClient } from '../client.js'; -import { parseFields } from '../parse_args.js'; - -export async function addNote( - address: AztecAddress, - contractAddress: AztecAddress, - storageSlot: Fr, - noteTypeId: Fr, - txHash: TxHash, - noteFields: string[], - rpcUrl: string, - debugLogger: DebugLogger, -) { - const note = new Note(parseFields(noteFields)); - const extendedNote = new ExtendedNote(note, address, contractAddress, storageSlot, noteTypeId, txHash); - const client = await createCompatibleClient(rpcUrl, debugLogger); - await client.addNote(extendedNote); -} diff --git a/yarn-project/cli/src/cmds/block_number.ts b/yarn-project/cli/src/cmds/block_number.ts deleted file mode 100644 index 5b6ca472d6b..00000000000 --- a/yarn-project/cli/src/cmds/block_number.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { type DebugLogger, type LogFn } from '@aztec/foundation/log'; - -import { createCompatibleClient } from '../client.js'; - -export async function blockNumber(rpcUrl: string, debugLogger: DebugLogger, log: LogFn) { - const client = await createCompatibleClient(rpcUrl, debugLogger); - const num = await client.getBlockNumber(); - log(`${num}\n`); -} diff --git a/yarn-project/cli/src/cmds/call.ts b/yarn-project/cli/src/cmds/call.ts deleted file mode 100644 index 3efffe1668c..00000000000 --- a/yarn-project/cli/src/cmds/call.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { type AztecAddress } from '@aztec/aztec.js'; -import { type DebugLogger, type LogFn } from '@aztec/foundation/log'; - -import { format } from 'util'; - -import { createCompatibleClient } from '../client.js'; -import { getFunctionArtifact, getTxSender, prepTx } from '../utils.js'; - -export async function call( - functionName: string, - functionArgsIn: any[], - contractArtifactPath: string, - contractAddress: AztecAddress, - fromAddress: string | undefined, - rpcUrl: string, - debugLogger: DebugLogger, - log: LogFn, -) { - const { functionArgs, contractArtifact } = await prepTx(contractArtifactPath, functionName, functionArgsIn); - - const fnArtifact = getFunctionArtifact(contractArtifact, functionName); - if (fnArtifact.parameters.length !== functionArgs.length) { - throw Error( - `Invalid number of args passed. Expected ${fnArtifact.parameters.length}; Received: ${functionArgs.length}`, - ); - } - - const client = await createCompatibleClient(rpcUrl, debugLogger); - const from = await getTxSender(client, fromAddress); - const result = await client.viewTx(functionName, functionArgs, contractAddress, from); - log(format('\nView result: ', result, '\n')); -} diff --git a/yarn-project/cli/src/cmds/check_deploy.ts b/yarn-project/cli/src/cmds/check_deploy.ts deleted file mode 100644 index 4a00c72a518..00000000000 --- a/yarn-project/cli/src/cmds/check_deploy.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { type AztecAddress } from '@aztec/aztec.js'; -import { type DebugLogger, type LogFn } from '@aztec/foundation/log'; - -import { createCompatibleClient } from '../client.js'; - -export async function checkDeploy(rpcUrl: string, contractAddress: AztecAddress, debugLogger: DebugLogger, log: LogFn) { - const client = await createCompatibleClient(rpcUrl, debugLogger); - const isPrivatelyDeployed = await client.getContractInstance(contractAddress); - const isPubliclyDeployed = await client.isContractPubliclyDeployed(contractAddress); - if (isPubliclyDeployed && isPrivatelyDeployed) { - log(`\nContract is publicly deployed at ${contractAddress.toString()}\n`); - } else if (isPrivatelyDeployed) { - log(`\nContract is registered in the local pxe at ${contractAddress.toString()} but not publicly deployed\n`); - } else if (isPubliclyDeployed) { - log(`\nContract is publicly deployed at ${contractAddress.toString()} but not registered in the local pxe\n`); - } else { - log(`\nNo contract found at ${contractAddress.toString()}\n`); - } -} diff --git a/yarn-project/cli/src/cmds/compute_selector.ts b/yarn-project/cli/src/cmds/compute_selector.ts deleted file mode 100644 index 9d299a64eff..00000000000 --- a/yarn-project/cli/src/cmds/compute_selector.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { FunctionSelector } from '@aztec/foundation/abi'; -import { type LogFn } from '@aztec/foundation/log'; - -export function computeSelector(functionSignature: string, log: LogFn) { - const selector = FunctionSelector.fromSignature(functionSignature); - log(`${selector}`); -} diff --git a/yarn-project/cli/src/cmds/create_account.ts b/yarn-project/cli/src/cmds/create_account.ts deleted file mode 100644 index f0dc92fdf37..00000000000 --- a/yarn-project/cli/src/cmds/create_account.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { getSchnorrAccount } from '@aztec/accounts/schnorr'; -import { deriveKeys } from '@aztec/circuits.js'; -import { Fr } from '@aztec/foundation/fields'; -import { type DebugLogger, type LogFn } from '@aztec/foundation/log'; - -import { createCompatibleClient } from '../client.js'; - -export async function createAccount( - rpcUrl: string, - secretKey: Fr, - wait: boolean, - debugLogger: DebugLogger, - log: LogFn, -) { - const client = await createCompatibleClient(rpcUrl, debugLogger); - const actualSecretKey = secretKey ?? Fr.random(); - - const signingKey = deriveKeys(actualSecretKey).masterIncomingViewingSecretKey; - const account = getSchnorrAccount(client, actualSecretKey, signingKey, Fr.ZERO); - const { address, publicKey, partialAddress } = account.getCompleteAddress(); - const tx = account.deploy(); - const txHash = await tx.getTxHash(); - debugLogger.verbose(`Account contract tx sent with hash ${txHash}`); - if (wait) { - log(`\nWaiting for account contract deployment...`); - await tx.wait(); - } else { - log(`\nAccount deployment transaction hash: ${txHash}\n`); - } - - log(`\nNew account:\n`); - log(`Address: ${address.toString()}`); - log(`Public key: ${publicKey.toString()}`); - if (!secretKey) { - log(`Secret key: ${actualSecretKey.toString()}`); - } - log(`Partial address: ${partialAddress.toString()}`); -} diff --git a/yarn-project/cli/src/cmds/deploy.ts b/yarn-project/cli/src/cmds/deploy.ts deleted file mode 100644 index 91b64afaf34..00000000000 --- a/yarn-project/cli/src/cmds/deploy.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { getSchnorrAccount } from '@aztec/accounts/schnorr'; -import { ContractDeployer, type EthAddress, Fr } from '@aztec/aztec.js'; -import { deriveKeys } from '@aztec/circuits.js'; -import { getInitializer } from '@aztec/foundation/abi'; -import { type DebugLogger, type LogFn } from '@aztec/foundation/log'; - -import { createCompatibleClient } from '../client.js'; -import { encodeArgs } from '../encoding.js'; -import { GITHUB_TAG_PREFIX } from '../github.js'; -import { getContractArtifact } from '../utils.js'; - -export async function deploy( - artifactPath: string, - json: boolean, - rpcUrl: string, - rawArgs: any[], - portalAddress: EthAddress, - salt: Fr, - secretKey: Fr, - initializer: string | undefined, - wait: boolean, - debugLogger: DebugLogger, - log: LogFn, - logJson: (output: any) => void, -) { - const contractArtifact = await getContractArtifact(artifactPath); - const constructorArtifact = getInitializer(contractArtifact, initializer); - - const client = await createCompatibleClient(rpcUrl, debugLogger); - const nodeInfo = await client.getNodeInfo(); - const expectedAztecNrVersion = `${GITHUB_TAG_PREFIX}-v${nodeInfo.nodeVersion}`; - if (contractArtifact.aztecNrVersion && contractArtifact.aztecNrVersion !== expectedAztecNrVersion) { - log( - `\nWarning: Contract was compiled with a different version of Aztec.nr: ${contractArtifact.aztecNrVersion}. Consider updating Aztec.nr to ${expectedAztecNrVersion}\n`, - ); - } - - const keys = deriveKeys(secretKey); - const wallet = await getSchnorrAccount(client, secretKey, keys.masterIncomingViewingSecretKey, Fr.ZERO).getWallet(); - const deployer = new ContractDeployer(contractArtifact, wallet, keys.publicKeysHash, initializer); - - let args = []; - if (rawArgs.length > 0) { - if (!constructorArtifact) { - throw new Error(`Cannot process constructor arguments as no constructor was found`); - } - debugLogger.verbose(`Input arguments: ${rawArgs.map((x: any) => `"${x}"`).join(', ')}`); - args = encodeArgs(rawArgs, constructorArtifact!.parameters); - debugLogger.verbose(`Encoded arguments: ${args.join(', ')}`); - } - - const deploy = deployer.deploy(...args); - - await deploy.create({ contractAddressSalt: salt, portalContract: portalAddress }); - const tx = deploy.send({ contractAddressSalt: salt, portalContract: portalAddress }); - const txHash = await tx.getTxHash(); - debugLogger.verbose(`Deploy tx sent with hash ${txHash}`); - if (wait) { - const deployed = await tx.wait(); - const { address, partialAddress } = deployed.contract; - if (json) { - logJson({ address: address.toString(), partialAddress: partialAddress.toString() }); - } else { - log(`\nContract deployed at ${address.toString()}\n`); - log(`Contract partial address ${partialAddress.toString()}\n`); - } - } else { - const { address, partialAddress } = deploy; - if (json) { - logJson({ - address: address?.toString() ?? 'N/A', - partialAddress: partialAddress?.toString() ?? 'N/A', - txHash: txHash.toString(), - }); - } else { - log(`\nContract Address: ${address?.toString() ?? 'N/A'}`); - log(`Contract Partial Address: ${partialAddress?.toString() ?? 'N/A'}`); - log(`Deployment transaction hash: ${txHash}\n`); - } - } -} diff --git a/yarn-project/cli/src/cmds/deploy_l1_contracts.ts b/yarn-project/cli/src/cmds/deploy_l1_contracts.ts deleted file mode 100644 index 49c6f5decb6..00000000000 --- a/yarn-project/cli/src/cmds/deploy_l1_contracts.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { type DebugLogger, type LogFn } from '@aztec/foundation/log'; - -import { deployAztecContracts } from '../utils.js'; - -export async function deployL1Contracts( - rpcUrl: string, - apiKey: string, - privateKey: string, - mnemonic: string, - log: LogFn, - debugLogger: DebugLogger, -) { - const { l1ContractAddresses } = await deployAztecContracts(rpcUrl, apiKey, privateKey, mnemonic, debugLogger); - - log('\n'); - log(`Rollup Address: ${l1ContractAddresses.rollupAddress.toString()}`); - log(`Registry Address: ${l1ContractAddresses.registryAddress.toString()}`); - log(`L1 -> L2 Inbox Address: ${l1ContractAddresses.inboxAddress.toString()}`); - log(`L2 -> L1 Outbox address: ${l1ContractAddresses.outboxAddress.toString()}`); - log(`Availability Oracle Address: ${l1ContractAddresses.availabilityOracleAddress.toString()}`); - log(`Gas Token Address: ${l1ContractAddresses.gasTokenAddress.toString()}`); - log(`Gas Portal Address: ${l1ContractAddresses.gasPortalAddress.toString()}`); - log('\n'); -} diff --git a/yarn-project/cli/src/cmds/example_contracts.ts b/yarn-project/cli/src/cmds/example_contracts.ts deleted file mode 100644 index f79be05b25a..00000000000 --- a/yarn-project/cli/src/cmds/example_contracts.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { type LogFn } from '@aztec/foundation/log'; - -import { getExampleContractArtifacts } from '../utils.js'; - -export async function exampleContracts(log: LogFn) { - const abisList = await getExampleContractArtifacts(); - const names = Object.keys(abisList).filter(name => !name.startsWith('Avm')); - names.forEach(name => log(name)); -} diff --git a/yarn-project/cli/src/cmds/generate_p2p_private_key.ts b/yarn-project/cli/src/cmds/generate_p2p_private_key.ts deleted file mode 100644 index f62617ae6ea..00000000000 --- a/yarn-project/cli/src/cmds/generate_p2p_private_key.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { type LogFn } from '@aztec/foundation/log'; - -import { createSecp256k1PeerId } from '@libp2p/peer-id-factory'; - -export async function generateP2PPrivateKey(log: LogFn) { - const peerId = await createSecp256k1PeerId(); - const exportedPeerId = Buffer.from(peerId.privateKey!).toString('hex'); - log(`Private key: ${exportedPeerId}`); - log(`Peer Id: ${peerId}`); -} diff --git a/yarn-project/cli/src/cmds/generate_private_key.ts b/yarn-project/cli/src/cmds/generate_private_key.ts deleted file mode 100644 index f7504de90de..00000000000 --- a/yarn-project/cli/src/cmds/generate_private_key.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { GrumpkinScalar, generatePublicKey } from '@aztec/aztec.js'; -import { type LogFn } from '@aztec/foundation/log'; - -import { mnemonicToAccount } from 'viem/accounts'; - -export function generatePrivateKey(mnemonic: string | undefined, log: LogFn) { - let privKey; - let publicKey; - if (mnemonic) { - const acc = mnemonicToAccount(mnemonic); - // TODO(#2052): This reduction is not secure enough. TACKLE THIS ISSUE BEFORE MAINNET. - const key = GrumpkinScalar.fromBufferReduce(Buffer.from(acc.getHdKey().privateKey!)); - publicKey = generatePublicKey(key); - } else { - const key = GrumpkinScalar.random(); - privKey = key.toString(); - publicKey = generatePublicKey(key); - } - log(`\nPrivate Key: ${privKey}\nPublic Key: ${publicKey.toString()}\n`); -} diff --git a/yarn-project/cli/src/cmds/get_account.ts b/yarn-project/cli/src/cmds/get_account.ts deleted file mode 100644 index c672c85fb85..00000000000 --- a/yarn-project/cli/src/cmds/get_account.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { type AztecAddress } from '@aztec/aztec.js'; -import { type DebugLogger, type LogFn } from '@aztec/foundation/log'; - -import { createCompatibleClient } from '../client.js'; - -export async function getAccount(aztecAddress: AztecAddress, rpcUrl: string, debugLogger: DebugLogger, log: LogFn) { - const client = await createCompatibleClient(rpcUrl, debugLogger); - const account = await client.getRegisteredAccount(aztecAddress); - - if (!account) { - log(`Unknown account ${aztecAddress.toString()}`); - } else { - log(account.toReadableString()); - } -} diff --git a/yarn-project/cli/src/cmds/get_accounts.ts b/yarn-project/cli/src/cmds/get_accounts.ts deleted file mode 100644 index 9d84cc581ed..00000000000 --- a/yarn-project/cli/src/cmds/get_accounts.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { type DebugLogger, type LogFn } from '@aztec/foundation/log'; - -import { createCompatibleClient } from '../client.js'; - -export async function getAccounts( - rpcUrl: string, - json: boolean, - debugLogger: DebugLogger, - log: LogFn, - logJson: (output: any) => void, -) { - const client = await createCompatibleClient(rpcUrl, debugLogger); - const accounts = await client.getRegisteredAccounts(); - if (!accounts.length) { - if (json) { - logJson([]); - } else { - log('No accounts found.'); - } - return; - } - if (json) { - logJson( - accounts.map(a => ({ - address: a.address.toString(), - publicKey: a.publicKey.toString(), - partialAddress: a.partialAddress.toString(), - })), - ); - } else { - log(`Accounts found: \n`); - for (const account of accounts) { - log(account.toReadableString()); - } - } -} diff --git a/yarn-project/cli/src/cmds/get_contract_data.ts b/yarn-project/cli/src/cmds/get_contract_data.ts deleted file mode 100644 index 592358a9fd3..00000000000 --- a/yarn-project/cli/src/cmds/get_contract_data.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { type AztecAddress } from '@aztec/aztec.js'; -import { type DebugLogger, type LogFn } from '@aztec/foundation/log'; - -import { createCompatibleClient } from '../client.js'; - -export async function getContractData( - rpcUrl: string, - contractAddress: AztecAddress, - includeBytecode: boolean, - debugLogger: DebugLogger, - log: LogFn, -) { - const client = await createCompatibleClient(rpcUrl, debugLogger); - const instance = await client.getContractInstance(contractAddress); - const contractClass = includeBytecode && instance && (await client.getContractClass(instance?.contractClassId)); - - if (!instance) { - log(`No contract found at ${contractAddress}`); - return; - } - - log(`\nContract Data:`); - Object.entries(instance).forEach(([key, value]) => { - const capitalized = key.charAt(0).toUpperCase() + key.slice(1); - log(`${capitalized}: ${value.toString()}`); - }); - - if (contractClass) { - log(`Bytecode: ${contractClass.packedBytecode.toString('base64')}`); - } - log('\n'); -} diff --git a/yarn-project/cli/src/cmds/get_logs.ts b/yarn-project/cli/src/cmds/get_logs.ts deleted file mode 100644 index 29afb7bbc6f..00000000000 --- a/yarn-project/cli/src/cmds/get_logs.ts +++ /dev/null @@ -1,69 +0,0 @@ -import { type AztecAddress, type LogFilter, type LogId, type TxHash } from '@aztec/aztec.js'; -import { type EventSelector } from '@aztec/foundation/abi'; -import { type DebugLogger, type LogFn } from '@aztec/foundation/log'; -import { sleep } from '@aztec/foundation/sleep'; - -import { createCompatibleClient } from '../client.js'; - -export async function getLogs( - txHash: TxHash, - fromBlock: number, - toBlock: number, - afterLog: LogId, - contractAddress: AztecAddress, - selector: EventSelector, - rpcUrl: string, - follow: boolean, - debugLogger: DebugLogger, - log: LogFn, -) { - const pxe = await createCompatibleClient(rpcUrl, debugLogger); - - if (follow) { - if (txHash) { - throw Error('Cannot use --follow with --tx-hash'); - } - if (toBlock) { - throw Error('Cannot use --follow with --to-block'); - } - } - - const filter: LogFilter = { txHash, fromBlock, toBlock, afterLog, contractAddress, selector }; - - const fetchLogs = async () => { - const response = await pxe.getUnencryptedLogs(filter); - const logs = response.logs; - - if (!logs.length) { - const filterOptions = Object.entries(filter) - .filter(([, value]) => value !== undefined) - .map(([key, value]) => `${key}: ${value}`) - .join(', '); - if (!follow) { - log(`No logs found for filter: {${filterOptions}}`); - } - } else { - if (!follow && !filter.afterLog) { - log('Logs found: \n'); - } - logs.forEach(unencryptedLog => log(unencryptedLog.toHumanReadable())); - // Set the continuation parameter for the following requests - filter.afterLog = logs[logs.length - 1].id; - } - return response.maxLogsHit; - }; - - if (follow) { - log('Fetching logs...'); - while (true) { - const maxLogsHit = await fetchLogs(); - if (!maxLogsHit) { - await sleep(1000); - } - } - } else { - while (await fetchLogs()) { - // Keep fetching logs until we reach the end. - } - } -} diff --git a/yarn-project/cli/src/cmds/get_node_info.ts b/yarn-project/cli/src/cmds/get_node_info.ts deleted file mode 100644 index b66df822532..00000000000 --- a/yarn-project/cli/src/cmds/get_node_info.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { type DebugLogger, type LogFn } from '@aztec/foundation/log'; - -import { createCompatibleClient } from '../client.js'; - -export async function getNodeInfo(rpcUrl: string, debugLogger: DebugLogger, log: LogFn) { - const client = await createCompatibleClient(rpcUrl, debugLogger); - const info = await client.getNodeInfo(); - log(`\nNode Info:\n`); - log(`Node Version: ${info.nodeVersion}\n`); - log(`Chain Id: ${info.chainId}\n`); - log(`Protocol Version: ${info.protocolVersion}\n`); - log(`Rollup Address: ${info.l1ContractAddresses.rollupAddress.toString()}`); -} diff --git a/yarn-project/cli/src/cmds/get_recipient.ts b/yarn-project/cli/src/cmds/get_recipient.ts deleted file mode 100644 index 4ae6baac896..00000000000 --- a/yarn-project/cli/src/cmds/get_recipient.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { type AztecAddress } from '@aztec/aztec.js'; -import { type DebugLogger, type LogFn } from '@aztec/foundation/log'; - -import { createCompatibleClient } from '../client.js'; - -export async function getRecipient(aztecAddress: AztecAddress, rpcUrl: string, debugLogger: DebugLogger, log: LogFn) { - const client = await createCompatibleClient(rpcUrl, debugLogger); - const recipient = await client.getRecipient(aztecAddress); - - if (!recipient) { - log(`Unknown recipient ${aztecAddress.toString()}`); - } else { - log(recipient.toReadableString()); - } -} diff --git a/yarn-project/cli/src/cmds/get_recipients.ts b/yarn-project/cli/src/cmds/get_recipients.ts deleted file mode 100644 index bc091bc5dd6..00000000000 --- a/yarn-project/cli/src/cmds/get_recipients.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { type DebugLogger, type LogFn } from '@aztec/foundation/log'; - -import { createCompatibleClient } from '../client.js'; - -export async function getRecipients(rpcUrl: string, debugLogger: DebugLogger, log: LogFn) { - const client = await createCompatibleClient(rpcUrl, debugLogger); - const recipients = await client.getRecipients(); - if (!recipients.length) { - log('No recipients found.'); - } else { - log(`Recipients found: \n`); - for (const recipient of recipients) { - log(recipient.toReadableString()); - } - } -} diff --git a/yarn-project/cli/src/cmds/get_tx_receipt.ts b/yarn-project/cli/src/cmds/get_tx_receipt.ts deleted file mode 100644 index 6119f035aac..00000000000 --- a/yarn-project/cli/src/cmds/get_tx_receipt.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { type TxHash } from '@aztec/aztec.js'; -import { JsonStringify } from '@aztec/foundation/json-rpc'; -import { type DebugLogger, type LogFn } from '@aztec/foundation/log'; - -import { createCompatibleClient } from '../client.js'; - -export async function getTxReceipt(rpcUrl: string, txHash: TxHash, debugLogger: DebugLogger, log: LogFn) { - const client = await createCompatibleClient(rpcUrl, debugLogger); - const receipt = await client.getTxReceipt(txHash); - if (!receipt) { - log(`No receipt found for transaction hash ${txHash.toString()}`); - } else { - log(`\nTransaction receipt: \n${JsonStringify(receipt, true)}\n`); - } -} diff --git a/yarn-project/cli/src/cmds/inspect_contract.ts b/yarn-project/cli/src/cmds/inspect_contract.ts deleted file mode 100644 index 0156c1e8c77..00000000000 --- a/yarn-project/cli/src/cmds/inspect_contract.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { getContractClassFromArtifact } from '@aztec/circuits.js'; -import { - type FunctionArtifact, - FunctionSelector, - decodeFunctionSignature, - decodeFunctionSignatureWithParameterNames, -} from '@aztec/foundation/abi'; -import { sha256 } from '@aztec/foundation/crypto'; -import { type LogFn } from '@aztec/foundation/log'; - -import { getContractArtifact } from '../utils.js'; - -export async function inspectContract(contractArtifactFile: string, log: LogFn) { - const contractArtifact = await getContractArtifact(contractArtifactFile); - const contractFns = contractArtifact.functions.filter(f => f.name !== 'compute_note_hash_and_nullifier'); - if (contractFns.length === 0) { - log(`No functions found for contract ${contractArtifact.name}`); - } - const contractClass = getContractClassFromArtifact(contractArtifact); - const bytecodeLengthInFields = 1 + Math.ceil(contractClass.packedBytecode.length / 31); - - log(`Contract class details:`); - log(`\tidentifier: ${contractClass.id.toString()}`); - log(`\tartifact hash: ${contractClass.artifactHash.toString()}`); - log(`\tprivate function tree root: ${contractClass.privateFunctionsRoot.toString()}`); - log(`\tpublic bytecode commitment: ${contractClass.publicBytecodeCommitment.toString()}`); - log(`\tpublic bytecode length: ${contractClass.packedBytecode.length} bytes (${bytecodeLengthInFields} fields)`); - log(`\nExternal functions:`); - contractFns.filter(f => !f.isInternal).forEach(f => logFunction(f, log)); - log(`\nInternal functions:`); - contractFns.filter(f => f.isInternal).forEach(f => logFunction(f, log)); -} - -function logFunction(fn: FunctionArtifact, log: LogFn) { - const signatureWithParameterNames = decodeFunctionSignatureWithParameterNames(fn.name, fn.parameters); - const signature = decodeFunctionSignature(fn.name, fn.parameters); - const selector = FunctionSelector.fromSignature(signature); - const bytecodeSize = fn.bytecode.length; - const bytecodeHash = sha256(fn.bytecode).toString('hex'); - log( - `${fn.functionType} ${signatureWithParameterNames} \n\tfunction signature: ${signature}\n\tselector: ${selector}\n\tbytecode: ${bytecodeSize} bytes (sha256 ${bytecodeHash})`, - ); -} diff --git a/yarn-project/cli/src/cmds/parse_parameter_struct.ts b/yarn-project/cli/src/cmds/parse_parameter_struct.ts deleted file mode 100644 index e319b8fe8e0..00000000000 --- a/yarn-project/cli/src/cmds/parse_parameter_struct.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { type StructType } from '@aztec/foundation/abi'; -import { JsonStringify } from '@aztec/foundation/json-rpc'; -import { type LogFn } from '@aztec/foundation/log'; - -import { parseStructString } from '../encoding.js'; -import { getContractArtifact } from '../utils.js'; - -export async function parseParameterStruct( - encodedString: string, - contractArtifactPath: string, - parameterName: string, - log: LogFn, -) { - const contractArtifact = await getContractArtifact(contractArtifactPath); - const parameterAbitype = contractArtifact.functions - .map(({ parameters }) => parameters) - .flat() - .find(({ name, type }) => name === parameterName && type.kind === 'struct'); - - if (!parameterAbitype) { - log(`No struct parameter found with name ${parameterName}`); - return; - } - - const data = parseStructString(encodedString, parameterAbitype.type as StructType); - log(`\nStruct Data: \n${JsonStringify(data, true)}\n`); -} diff --git a/yarn-project/cli/src/cmds/register_account.ts b/yarn-project/cli/src/cmds/register_account.ts deleted file mode 100644 index 868bd04721d..00000000000 --- a/yarn-project/cli/src/cmds/register_account.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { type Fr } from '@aztec/foundation/fields'; -import { type DebugLogger, type LogFn } from '@aztec/foundation/log'; - -import { createCompatibleClient } from '../client.js'; - -export async function registerAccount( - rpcUrl: string, - secretKey: Fr, - partialAddress: Fr, - debugLogger: DebugLogger, - log: LogFn, -) { - const client = await createCompatibleClient(rpcUrl, debugLogger); - - const { address, publicKey } = await client.registerAccount(secretKey, partialAddress); - - log(`\nRegistered account:\n`); - log(`Address: ${address.toString()}`); - log(`Public key: ${publicKey.toString()}`); - log(`Partial address: ${partialAddress.toString()}`); -} diff --git a/yarn-project/cli/src/cmds/register_recipient.ts b/yarn-project/cli/src/cmds/register_recipient.ts deleted file mode 100644 index 7e9cf877f04..00000000000 --- a/yarn-project/cli/src/cmds/register_recipient.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { type AztecAddress, type Fr, type Point } from '@aztec/aztec.js'; -import { CompleteAddress } from '@aztec/circuit-types'; -import { type DebugLogger, type LogFn } from '@aztec/foundation/log'; - -import { createCompatibleClient } from '../client.js'; - -export async function registerRecipient( - aztecAddress: AztecAddress, - publicKey: Point, - partialAddress: Fr, - rpcUrl: string, - debugLogger: DebugLogger, - log: LogFn, -) { - const client = await createCompatibleClient(rpcUrl, debugLogger); - await client.registerRecipient(CompleteAddress.create(aztecAddress, publicKey, partialAddress)); - log(`\nRegistered details for account with address: ${aztecAddress}\n`); -} diff --git a/yarn-project/cli/src/cmds/send.ts b/yarn-project/cli/src/cmds/send.ts deleted file mode 100644 index be3c4eea600..00000000000 --- a/yarn-project/cli/src/cmds/send.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { getSchnorrAccount } from '@aztec/accounts/schnorr'; -import { type AztecAddress, Contract, Fr } from '@aztec/aztec.js'; -import { deriveKeys } from '@aztec/circuits.js'; -import { type DebugLogger, type LogFn } from '@aztec/foundation/log'; - -import { createCompatibleClient } from '../client.js'; -import { prepTx } from '../utils.js'; - -export async function send( - functionName: string, - functionArgsIn: any[], - contractArtifactPath: string, - contractAddress: AztecAddress, - secretKey: Fr, - rpcUrl: string, - wait: boolean, - debugLogger: DebugLogger, - log: LogFn, -) { - const { functionArgs, contractArtifact } = await prepTx(contractArtifactPath, functionName, functionArgsIn); - - const client = await createCompatibleClient(rpcUrl, debugLogger); - const signingKey = deriveKeys(secretKey).masterIncomingViewingSecretKey; - const wallet = await getSchnorrAccount(client, secretKey, signingKey, Fr.ZERO).getWallet(); - const contract = await Contract.at(contractAddress, contractArtifact, wallet); - const tx = contract.methods[functionName](...functionArgs).send(); - log(`\nTransaction hash: ${(await tx.getTxHash()).toString()}`); - if (wait) { - await tx.wait(); - - log('Transaction has been mined'); - - const receipt = await tx.getReceipt(); - log(`Status: ${receipt.status}\n`); - log(`Block number: ${receipt.blockNumber}`); - log(`Block hash: ${receipt.blockHash?.toString('hex')}`); - } else { - log('Transaction pending. Check status with get-tx-receipt'); - } -} diff --git a/yarn-project/cli/src/encoding.ts b/yarn-project/cli/src/encoding.ts deleted file mode 100644 index e10f843814d..00000000000 --- a/yarn-project/cli/src/encoding.ts +++ /dev/null @@ -1,117 +0,0 @@ -import { type ABIParameter, type AbiType, type StructType } from '@aztec/foundation/abi'; -import { Fr } from '@aztec/foundation/fields'; - -/** - * Parses a hex string into an ABI struct type. - * @param str - The encoded hex string. - * @param abiType - The ABI Struct type. - * @returns An object in the ABI struct type's format. - */ -export function parseStructString(str: string, abiType: StructType) { - // Assign string bytes to struct fields. - const buf = Buffer.from(str.replace(/^0x/i, ''), 'hex'); - const struct: any = {}; - let byteIndex = 0; - let argIndex = 0; - while (byteIndex < buf.length) { - const { name } = abiType.fields[argIndex]; - struct[name] = Fr.fromBuffer(buf.subarray(byteIndex, byteIndex + 32)); - byteIndex += 32; - argIndex += 1; - } - - return struct; -} - -/** - * Helper function to encode CLI string args to an appropriate JS type. - * @param arg - The CLI argument. - * @param abiType - The type as described by the contract's ABI. - * @returns The encoded argument. - */ -function encodeArg(arg: string, abiType: AbiType, name: string): any { - const { kind } = abiType; - if (kind === 'field' || kind === 'integer') { - let res: bigint; - try { - res = BigInt(arg); - } catch (err) { - throw new Error( - `Invalid value passed for ${name}. Could not parse ${arg} as a${kind === 'integer' ? 'n' : ''} ${kind}.`, - ); - } - return res; - } else if (kind === 'boolean') { - if (arg === 'true') { - return true; - } - if (arg === 'false') { - return false; - } else { - throw Error(`Invalid boolean value passed for ${name}: ${arg}.`); - } - } else if (kind === 'string') { - return arg; - } else if (kind === 'array') { - let arr; - const res = []; - try { - arr = JSON.parse(arg); - } catch { - throw new Error(`Unable to parse arg ${arg} as array for ${name} parameter`); - } - if (!Array.isArray(arr)) { - throw Error(`Invalid argument ${arg} passed for array parameter ${name}.`); - } - if (arr.length !== abiType.length) { - throw Error(`Invalid array length passed for ${name}. Expected ${abiType.length}, received ${arr.length}.`); - } - for (let i = 0; i < abiType.length; i += 1) { - res.push(encodeArg(arr[i], abiType.type, name)); - } - return res; - } else if (kind === 'struct') { - // check if input is encoded long string - if (arg.startsWith('0x')) { - return parseStructString(arg, abiType); - } - let obj; - try { - obj = JSON.parse(arg); - } catch { - throw new Error(`Unable to parse arg ${arg} as struct`); - } - if (Array.isArray(obj)) { - throw Error(`Array passed for arg ${name}. Expected a struct.`); - } - const res: any = {}; - for (const field of abiType.fields) { - // Remove field name from list as it's present - const arg = obj[field.name]; - if (!arg) { - throw Error(`Expected field ${field.name} not found in struct ${name}.`); - } - res[field.name] = encodeArg(obj[field.name], field.type, field.name); - } - return res; - } -} - -/** - * Tries to encode function args to their equivalent TS type. - * @param args - An array of function's / constructor's args. - * @returns The encoded array. - */ -export function encodeArgs(args: any[], params: ABIParameter[]) { - if (args.length !== params.length) { - throw new Error( - `Invalid args provided.\nExpected args: [${params - .map(param => param.name + ': ' + param.type.kind) - .join(', ')}]\nReceived args: ${args.join(', ')}`, - ); - } - return args.map((arg: any, index) => { - const { type, name } = params[index]; - return encodeArg(arg, type, name); - }); -} diff --git a/yarn-project/cli/src/github.ts b/yarn-project/cli/src/github.ts deleted file mode 100644 index 0486c382369..00000000000 --- a/yarn-project/cli/src/github.ts +++ /dev/null @@ -1,3 +0,0 @@ -export const GITHUB_OWNER = 'AztecProtocol'; -export const GITHUB_REPO = 'aztec-packages'; -export const GITHUB_TAG_PREFIX = 'aztec-packages'; diff --git a/yarn-project/cli/src/index.ts b/yarn-project/cli/src/index.ts deleted file mode 100644 index fc9daa45fbf..00000000000 --- a/yarn-project/cli/src/index.ts +++ /dev/null @@ -1,502 +0,0 @@ -import { Fr } from '@aztec/circuits.js'; -import { type DebugLogger, type LogFn } from '@aztec/foundation/log'; -import { fileURLToPath } from '@aztec/foundation/url'; -import { addCodegenCommanderAction } from '@aztec/noir-compiler/cli'; - -import { Command, Option } from 'commander'; -import { lookup } from 'dns/promises'; -import { readFileSync } from 'fs'; -import { dirname, resolve } from 'path'; - -import { - parseAztecAddress, - parseEthereumAddress, - parseField, - parseFieldFromHexString, - parseOptionalAztecAddress, - parseOptionalInteger, - parseOptionalLogId, - parseOptionalSelector, - parseOptionalTxHash, - parsePartialAddress, - parsePrivateKey, - parsePublicKey, - parseTxHash, -} from './parse_args.js'; - -/** - * If we can successfully resolve 'host.docker.internal', then we are running in a container, and we should treat - * localhost as being host.docker.internal. - */ -const getLocalhost = () => - lookup('host.docker.internal') - .then(() => 'host.docker.internal') - .catch(() => 'localhost'); - -const LOCALHOST = await getLocalhost(); -const { ETHEREUM_HOST = `http://${LOCALHOST}:8545`, PRIVATE_KEY, API_KEY, CLI_VERSION } = process.env; - -/** - * Returns commander program that defines the CLI. - * @param log - Console logger. - * @param debugLogger - Debug logger. - * @returns The CLI. - */ -export function getProgram(log: LogFn, debugLogger: DebugLogger): Command { - const program = new Command(); - - const packageJsonPath = resolve(dirname(fileURLToPath(import.meta.url)), '../package.json'); - const cliVersion: string = CLI_VERSION || JSON.parse(readFileSync(packageJsonPath).toString()).version; - const logJson = (obj: object) => log(JSON.stringify(obj, null, 2)); - - program.name('aztec-cli').description('CLI for interacting with Aztec.').version(cliVersion); - - const pxeOption = new Option('-u, --rpc-url ', 'URL of the PXE') - .env('PXE_URL') - .default(`http://${LOCALHOST}:8080`) - .makeOptionMandatory(true); - - const createPrivateKeyOption = (description: string, mandatory: boolean) => - new Option('-k, --private-key ', description) - .env('PRIVATE_KEY') - .argParser(parsePrivateKey) - .makeOptionMandatory(mandatory); - - program - .command('deploy-l1-contracts') - .description('Deploys all necessary Ethereum contracts for Aztec.') - .requiredOption( - '-u, --rpc-url ', - 'Url of the ethereum host. Chain identifiers localhost and testnet can be used', - ETHEREUM_HOST, - ) - .option('-a, --api-key ', 'Api key for the ethereum host', API_KEY) - .requiredOption('-p, --private-key ', 'The private key to use for deployment', PRIVATE_KEY) - .option( - '-m, --mnemonic ', - 'The mnemonic to use in deployment', - 'test test test test test test test test test test test junk', - ) - .action(async options => { - const { deployL1Contracts } = await import('./cmds/deploy_l1_contracts.js'); - await deployL1Contracts( - options.rpcUrl, - options.apiKey ?? '', - options.privateKey, - options.mnemonic, - log, - debugLogger, - ); - }); - - program - .command('generate-private-key') - .summary('Generates an encryption private key.') - .description( - 'Generates a private key which fits into the scalar field used by Grumpkin curve, can be used as an encryption private key.', - ) - .option( - '-m, --mnemonic', - 'An optional mnemonic string used for the private key generation. If not provided, random private key will be generated.', - ) - .action(async options => { - const { generatePrivateKey } = await import('./cmds/generate_private_key.js'); - generatePrivateKey(options.mnemonic, log); - }); - - program - .command('generate-p2p-private-key') - .summary('Generates a LibP2P peer private key.') - .description('Generates a private key that can be used for running a node on a LibP2P network.') - .action(async () => { - const { generateP2PPrivateKey } = await import('./cmds/generate_p2p_private_key.js'); - await generateP2PPrivateKey(log); - }); - - program - .command('create-account') - .description( - 'Creates an aztec account that can be used for sending transactions. Registers the account on the PXE and deploys an account contract. Uses a Schnorr single-key account which uses the same key for encryption and authentication (not secure for production usage).', - ) - .summary('Creates an aztec account that can be used for sending transactions.') - .addOption( - createPrivateKeyOption('Private key for note encryption and transaction signing. Uses random by default.', false), - ) - .addOption(pxeOption) - // `options.wait` is default true. Passing `--no-wait` will set it to false. - // https://github.com/tj/commander.js#other-option-types-negatable-boolean-and-booleanvalue - .option('--no-wait', 'Skip waiting for the contract to be deployed. Print the hash of deployment transaction') - .action(async ({ rpcUrl, privateKey, wait }) => { - const { createAccount } = await import('./cmds/create_account.js'); - await createAccount(rpcUrl, privateKey, wait, debugLogger, log); - }); - - program - .command('register-account') - .description( - 'Registers an aztec account that can be used for sending transactions. Registers the account on the PXE. Uses a Schnorr single-key account which uses the same key for encryption and authentication (not secure for production usage).', - ) - .summary('Registers an aztec account that can be used for sending transactions.') - .addOption(createPrivateKeyOption('Private key for note encryption and transaction signing.', true)) - .requiredOption( - '-pa, --partial-address ', - 'The partially computed address of the account contract.', - parsePartialAddress, - ) - .addOption(pxeOption) - .action(async ({ rpcUrl, privateKey, partialAddress }) => { - const { registerAccount } = await import('./cmds/register_account.js'); - await registerAccount(rpcUrl, privateKey, partialAddress, debugLogger, log); - }); - - program - .command('deploy') - .description('Deploys a compiled Aztec.nr contract to Aztec.') - .argument( - '', - "A compiled Aztec.nr contract's artifact in JSON format or name of a contract artifact exported by @aztec/noir-contracts.js", - ) - .option('--initializer ', 'The contract initializer function to call') - .option('-a, --args ', 'Contract constructor arguments', []) - .addOption(pxeOption) - .option( - '-p, --portal-address ', - 'Optional L1 portal address to link the contract to.', - parseEthereumAddress, - ) - .option( - '-s, --salt ', - 'Optional deployment salt as a hex string for generating the deployment address.', - parseFieldFromHexString, - ) - .addOption(createPrivateKeyOption("The sender's private key.", true)) - .option('--json', 'Emit output as json') - // `options.wait` is default true. Passing `--no-wait` will set it to false. - // https://github.com/tj/commander.js#other-option-types-negatable-boolean-and-booleanvalue - .option('--no-wait', 'Skip waiting for the contract to be deployed. Print the hash of deployment transaction') - .action( - async (artifactPath, { json, rpcUrl, args: rawArgs, portalAddress, salt, wait, privateKey, initializer }) => { - // TODO(#5726): everywhere here in CLI we consume private key instead of secret key --> we should accept - // secret key everywhere and derive the rest. Also unlike before the keys change the public key is now always - // derived and set for the contract. We should allow setting zero public key again. Remove the hack on the next - // line. - const secretKey = Fr.fromBufferReduce(privateKey.toBuffer()); - const { deploy } = await import('./cmds/deploy.js'); - await deploy( - artifactPath, - json, - rpcUrl, - rawArgs, - portalAddress, - salt, - secretKey, - initializer, - wait, - debugLogger, - log, - logJson, - ); - }, - ); - - program - .command('check-deploy') - .description('Checks if a contract is deployed to the specified Aztec address.') - .requiredOption( - '-ca, --contract-address
', - 'An Aztec address to check if contract has been deployed to.', - parseAztecAddress, - ) - .addOption(pxeOption) - .action(async options => { - const { checkDeploy } = await import('./cmds/check_deploy.js'); - await checkDeploy(options.rpcUrl, options.contractAddress, debugLogger, log); - }); - - program - .command('add-contract') - .description( - 'Adds an existing contract to the PXE. This is useful if you have deployed a contract outside of the PXE and want to use it with the PXE.', - ) - .requiredOption( - '-c, --contract-artifact ', - "A compiled Aztec.nr contract's ABI in JSON format or name of a contract ABI exported by @aztec/noir-contracts.js", - ) - .requiredOption('-ca, --contract-address
', 'Aztec address of the contract.', parseAztecAddress) - .requiredOption('--init-hash ', 'Initialization hash', parseFieldFromHexString) - .option('--salt ', 'Optional deployment salt', parseFieldFromHexString) - .option('-p, --public-key ', 'Optional public key for this contract', parsePublicKey) - .option('--portal-address
', 'Optional address to a portal contract on L1', parseEthereumAddress) - .option('--deployer-address
', 'Optional address of the contract deployer', parseAztecAddress) - .addOption(pxeOption) - .action(async options => { - const { addContract } = await import('./cmds/add_contract.js'); - await addContract( - options.rpcUrl, - options.contractArtifact, - options.contractAddress, - options.initHash, - options.salt ?? Fr.ZERO, - options.publicKey, - options.portalContract, - options.deployerAddress, - debugLogger, - log, - ); - }); - - program - .command('get-tx-receipt') - .description('Gets the receipt for the specified transaction hash.') - .argument('', 'A transaction hash to get the receipt for.', parseTxHash) - .addOption(pxeOption) - .action(async (txHash, options) => { - const { getTxReceipt } = await import('./cmds/get_tx_receipt.js'); - await getTxReceipt(options.rpcUrl, txHash, debugLogger, log); - }); - - program - .command('get-contract-data') - .description('Gets information about the Aztec contract deployed at the specified address.') - .argument('', 'Aztec address of the contract.', parseAztecAddress) - .addOption(pxeOption) - .option('-b, --include-bytecode ', "Include the contract's public function bytecode, if any.", false) - .action(async (contractAddress, options) => { - const { getContractData } = await import('./cmds/get_contract_data.js'); - await getContractData(options.rpcUrl, contractAddress, options.includeBytecode, debugLogger, log); - }); - - program - .command('get-logs') - .description('Gets all the unencrypted logs from an intersection of all the filter params.') - .option('-tx, --tx-hash ', 'A transaction hash to get the receipt for.', parseOptionalTxHash) - .option( - '-fb, --from-block ', - 'Initial block number for getting logs (defaults to 1).', - parseOptionalInteger, - ) - .option('-tb, --to-block ', 'Up to which block to fetch logs (defaults to latest).', parseOptionalInteger) - .option('-al --after-log ', 'ID of a log after which to fetch the logs.', parseOptionalLogId) - .option('-ca, --contract-address
', 'Contract address to filter logs by.', parseOptionalAztecAddress) - .option('-s, --selector ', 'Event selector to filter logs by.', parseOptionalSelector) - .addOption(pxeOption) - .option('--follow', 'If set, will keep polling for new logs until interrupted.') - .action(async ({ txHash, fromBlock, toBlock, afterLog, contractAddress, selector, rpcUrl, follow }) => { - const { getLogs } = await import('./cmds/get_logs.js'); - await getLogs(txHash, fromBlock, toBlock, afterLog, contractAddress, selector, rpcUrl, follow, debugLogger, log); - }); - - program - .command('register-recipient') - .description('Register a recipient in the PXE.') - .requiredOption('-a, --address ', "The account's Aztec address.", parseAztecAddress) - .requiredOption('-p, --public-key ', 'The account public key.', parsePublicKey) - .requiredOption( - '-pa, --partial-address ', - 'The partially computed address of the account contract.', - parsePartialAddress, - ) - .addOption(pxeOption) - .action(async ({ address, publicKey, partialAddress, rpcUrl }) => { - const { registerRecipient } = await import('./cmds/register_recipient.js'); - await registerRecipient(address, publicKey, partialAddress, rpcUrl, debugLogger, log); - }); - - program - .command('get-accounts') - .description('Gets all the Aztec accounts stored in the PXE.') - .addOption(pxeOption) - .option('--json', 'Emit output as json') - .action(async (options: any) => { - const { getAccounts } = await import('./cmds/get_accounts.js'); - await getAccounts(options.rpcUrl, options.json, debugLogger, log, logJson); - }); - - program - .command('get-account') - .description('Gets an account given its Aztec address.') - .argument('
', 'The Aztec address to get account for', parseAztecAddress) - .addOption(pxeOption) - .action(async (address, options) => { - const { getAccount } = await import('./cmds/get_account.js'); - await getAccount(address, options.rpcUrl, debugLogger, log); - }); - - program - .command('get-recipients') - .description('Gets all the recipients stored in the PXE.') - .addOption(pxeOption) - .action(async (options: any) => { - const { getRecipients } = await import('./cmds/get_recipients.js'); - await getRecipients(options.rpcUrl, debugLogger, log); - }); - - program - .command('get-recipient') - .description('Gets a recipient given its Aztec address.') - .argument('
', 'The Aztec address to get recipient for', parseAztecAddress) - .addOption(pxeOption) - .action(async (address, options) => { - const { getRecipient } = await import('./cmds/get_recipient.js'); - await getRecipient(address, options.rpcUrl, debugLogger, log); - }); - - program - .command('send') - .description('Calls a function on an Aztec contract.') - .argument('', 'Name of function to execute') - .option('-a, --args [functionArgs...]', 'Function arguments', []) - .requiredOption( - '-c, --contract-artifact ', - "A compiled Aztec.nr contract's ABI in JSON format or name of a contract ABI exported by @aztec/noir-contracts.js", - ) - .requiredOption('-ca, --contract-address
', 'Aztec address of the contract.', parseAztecAddress) - .addOption(createPrivateKeyOption("The sender's private key.", true)) - .addOption(pxeOption) - .option('--no-wait', 'Print transaction hash without waiting for it to be mined') - .action(async (functionName, options) => { - const { send } = await import('./cmds/send.js'); - await send( - functionName, - options.args, - options.contractArtifact, - options.contractAddress, - options.privateKey, - options.rpcUrl, - !options.noWait, - debugLogger, - log, - ); - }); - - program - .command('call') - .description( - 'Simulates the execution of a view (read-only) function on a deployed contract, without modifying state.', - ) - .argument('', 'Name of function to call') - .option('-a, --args [functionArgs...]', 'Function arguments', []) - .requiredOption( - '-c, --contract-artifact ', - "A compiled Aztec.nr contract's ABI in JSON format or name of a contract ABI exported by @aztec/noir-contracts.js", - ) - .requiredOption('-ca, --contract-address
', 'Aztec address of the contract.', parseAztecAddress) - .option('-f, --from ', 'Aztec address of the caller. If empty, will use the first account from RPC.') - .addOption(pxeOption) - .action(async (functionName, options) => { - const { call } = await import('./cmds/call.js'); - await call( - functionName, - options.args, - options.contractArtifact, - options.contractAddress, - options.from, - options.rpcUrl, - debugLogger, - log, - ); - }); - - program - .command('add-note') - .description('Adds a note to the database in the PXE.') - .argument('
', 'The Aztec address of the note owner.', parseAztecAddress) - .argument('', 'Aztec address of the contract.', parseAztecAddress) - .argument('', 'The storage slot of the note.', parseField) - .argument('', 'The type ID of the note.', parseField) - .argument('', 'The tx hash of the tx containing the note.', parseTxHash) - .requiredOption('-n, --note [note...]', 'The members of a Note serialized as hex strings.', []) - .addOption(pxeOption) - .action(async (address, contractAddress, storageSlot, noteTypeId, txHash, options) => { - const { addNote } = await import('./cmds/add_note.js'); - await addNote( - address, - contractAddress, - storageSlot, - noteTypeId, - txHash, - options.note, - options.rpcUrl, - debugLogger, - ); - }); - - // Helper for users to decode hex strings into structs if needed. - program - .command('parse-parameter-struct') - .description("Helper for parsing an encoded string into a contract's parameter struct.") - .argument('', 'The encoded hex string') - .requiredOption( - '-c, --contract-artifact ', - "A compiled Aztec.nr contract's ABI in JSON format or name of a contract ABI exported by @aztec/noir-contracts.js", - ) - .requiredOption('-p, --parameter ', 'The name of the struct parameter to decode into') - .action(async (encodedString, options) => { - const { parseParameterStruct } = await import('./cmds/parse_parameter_struct.js'); - await parseParameterStruct(encodedString, options.contractArtifact, options.parameter, log); - }); - - program - .command('block-number') - .description('Gets the current Aztec L2 block number.') - .addOption(pxeOption) - .action(async (options: any) => { - const { blockNumber } = await import('./cmds/block_number.js'); - await blockNumber(options.rpcUrl, debugLogger, log); - }); - - program - .command('example-contracts') - .description('Lists the example contracts available to deploy from @aztec/noir-contracts.js') - .action(async () => { - const { exampleContracts } = await import('./cmds/example_contracts.js'); - await exampleContracts(log); - }); - - program - .command('get-node-info') - .description('Gets the information of an aztec node at a URL.') - .addOption(pxeOption) - .action(async options => { - const { getNodeInfo } = await import('./cmds/get_node_info.js'); - await getNodeInfo(options.rpcUrl, debugLogger, log); - }); - - program - .command('inspect-contract') - .description('Shows list of external callable functions for a contract') - .argument( - '', - `A compiled Noir contract's artifact in JSON format or name of a contract artifact exported by @aztec/noir-contracts.js`, - ) - .action(async (contractArtifactFile: string) => { - const { inspectContract } = await import('./cmds/inspect_contract.js'); - await inspectContract(contractArtifactFile, log); - }); - - program - .command('compute-selector') - .description('Given a function signature, it computes a selector') - .argument('', 'Function signature to compute selector for e.g. foo(Field)') - .action(async (functionSignature: string) => { - const { computeSelector } = await import('./cmds/compute_selector.js'); - computeSelector(functionSignature, log); - }); - - program - .command('update') - .description('Updates Nodejs and Noir dependencies') - .argument('[projectPath]', 'Path to the project directory', process.cwd()) - .option('--contract [paths...]', 'Paths to contracts to update dependencies', []) - .option('--aztec-version ', 'The version to update Aztec packages to. Defaults to latest', 'latest') - .addOption(pxeOption) - .action(async (projectPath: string, options) => { - const { update } = await import('./update/update.js'); - const { contract, aztecVersion, rpcUrl } = options; - await update(projectPath, contract, rpcUrl, aztecVersion, log); - }); - - addCodegenCommanderAction(program, log); - - return program; -} diff --git a/yarn-project/cli/src/parse_args.ts b/yarn-project/cli/src/parse_args.ts deleted file mode 100644 index d71129d48dd..00000000000 --- a/yarn-project/cli/src/parse_args.ts +++ /dev/null @@ -1,248 +0,0 @@ -import { FunctionSelector } from '@aztec/aztec.js/abi'; -import { AztecAddress } from '@aztec/aztec.js/aztec_address'; -import { EthAddress } from '@aztec/aztec.js/eth_address'; -import { Fr, GrumpkinScalar, Point } from '@aztec/aztec.js/fields'; -import { LogId } from '@aztec/aztec.js/log_id'; -import { TxHash } from '@aztec/aztec.js/tx_hash'; - -import { InvalidArgumentError } from 'commander'; - -/** - * Removes the leading 0x from a hex string. If no leading 0x is found the string is returned unchanged. - * @param hex - A hex string - * @returns A new string with leading 0x removed - */ -const stripLeadingHex = (hex: string) => { - if (hex.length > 2 && hex.startsWith('0x')) { - return hex.substring(2); - } - return hex; -}; - -/** - * Parses a hex encoded string to an Fr integer - * @param str - Hex encoded string - * @returns A integer - */ -export function parseFieldFromHexString(str: string): Fr { - const hex = stripLeadingHex(str); - - // ensure it's a hex string - if (!hex.match(/^[0-9a-f]+$/i)) { - throw new InvalidArgumentError('Invalid hex string'); - } - - // pad it so that we may read it as a buffer. - // Buffer needs _exactly_ two hex characters per byte - const padded = hex.length % 2 === 1 ? '0' + hex : hex; - - // finally, turn it into an integer - return Fr.fromBuffer(Buffer.from(padded, 'hex')); -} - -/** - * Parses an AztecAddress from a string. - * @param address - A serialized Aztec address - * @returns An Aztec address - * @throws InvalidArgumentError if the input string is not valid. - */ -export function parseAztecAddress(address: string): AztecAddress { - try { - return AztecAddress.fromString(address); - } catch { - throw new InvalidArgumentError(`Invalid address: ${address}`); - } -} - -/** - * Parses an Ethereum address from a string. - * @param address - A serialized Ethereum address - * @returns An Ethereum address - * @throws InvalidArgumentError if the input string is not valid. - */ -export function parseEthereumAddress(address: string): EthAddress { - try { - return EthAddress.fromString(address); - } catch { - throw new InvalidArgumentError(`Invalid address: ${address}`); - } -} - -/** - * Parses an AztecAddress from a string. - * @param address - A serialized Aztec address - * @returns An Aztec address - * @throws InvalidArgumentError if the input string is not valid. - */ -export function parseOptionalAztecAddress(address: string): AztecAddress | undefined { - if (!address) { - return undefined; - } - return parseAztecAddress(address); -} - -/** - * Parses an optional log ID string into a LogId object. - * - * @param logId - The log ID string to parse. - * @returns The parsed LogId object, or undefined if the log ID is missing or empty. - */ -export function parseOptionalLogId(logId: string): LogId | undefined { - if (!logId) { - return undefined; - } - return LogId.fromString(logId); -} - -/** - * Parses a selector from a string. - * @param selector - A serialized selector. - * @returns A selector. - * @throws InvalidArgumentError if the input string is not valid. - */ -export function parseOptionalSelector(selector: string): FunctionSelector | undefined { - if (!selector) { - return undefined; - } - try { - return FunctionSelector.fromString(selector); - } catch { - throw new InvalidArgumentError(`Invalid selector: ${selector}`); - } -} - -/** - * Parses a string into an integer or returns undefined if the input is falsy. - * - * @param value - The string to parse into an integer. - * @returns The parsed integer, or undefined if the input string is falsy. - * @throws If the input is not a valid integer. - */ -export function parseOptionalInteger(value: string): number | undefined { - if (!value) { - return undefined; - } - const parsed = Number(value); - if (!Number.isInteger(parsed)) { - throw new InvalidArgumentError('Invalid integer.'); - } - return parsed; -} - -/** - * Parses a TxHash from a string. - * @param txHash - A transaction hash - * @returns A TxHash instance - * @throws InvalidArgumentError if the input string is not valid. - */ -export function parseTxHash(txHash: string): TxHash { - try { - return TxHash.fromString(txHash); - } catch { - throw new InvalidArgumentError(`Invalid transaction hash: ${txHash}`); - } -} - -/** - * Parses an optional TxHash from a string. - * Calls parseTxHash internally. - * @param txHash - A transaction hash - * @returns A TxHash instance, or undefined if the input string is falsy. - * @throws InvalidArgumentError if the input string is not valid. - */ -export function parseOptionalTxHash(txHash: string): TxHash | undefined { - if (!txHash) { - return undefined; - } - return parseTxHash(txHash); -} - -/** - * Parses a public key from a string. - * @param publicKey - A public key - * @returns A Point instance - * @throws InvalidArgumentError if the input string is not valid. - */ -export function parsePublicKey(publicKey: string): Point { - try { - return Point.fromString(publicKey); - } catch (err) { - throw new InvalidArgumentError(`Invalid public key: ${publicKey}`); - } -} - -/** - * Parses a partial address from a string. - * @param address - A partial address - * @returns A Fr instance - * @throws InvalidArgumentError if the input string is not valid. - */ -export function parsePartialAddress(address: string): Fr { - try { - return Fr.fromString(address); - } catch (err) { - throw new InvalidArgumentError(`Invalid partial address: ${address}`); - } -} - -/** - * Parses a private key from a string. - * @param privateKey - A string - * @returns A private key - * @throws InvalidArgumentError if the input string is not valid. - */ -export function parsePrivateKey(privateKey: string): GrumpkinScalar { - try { - const value = GrumpkinScalar.fromString(privateKey); - // most likely a badly formatted key was passed - if (value.isZero()) { - throw new Error('Private key must not be zero'); - } - - return value; - } catch (err) { - throw new InvalidArgumentError(`Invalid private key: ${privateKey}`); - } -} - -/** - * Parses a field from a string. - * @param field - A string representing the field. - * @returns A field. - * @throws InvalidArgumentError if the input string is not valid. - */ -export function parseField(field: string): Fr { - try { - const isHex = field.startsWith('0x') || field.match(new RegExp(`^[0-9a-f]{${Fr.SIZE_IN_BYTES * 2}}$`, 'i')); - if (isHex) { - return Fr.fromString(field); - } - - if (['true', 'false'].includes(field)) { - return new Fr(field === 'true'); - } - - const isNumber = +field || field === '0'; - if (isNumber) { - return new Fr(BigInt(field)); - } - - const isBigInt = field.endsWith('n'); - if (isBigInt) { - return new Fr(BigInt(field.replace(/n$/, ''))); - } - - return new Fr(BigInt(field)); - } catch (err) { - throw new InvalidArgumentError(`Invalid field: ${field}`); - } -} - -/** - * Parses an array of strings to Frs. - * @param fields - An array of strings representing the fields. - * @returns An array of Frs. - */ -export function parseFields(fields: string[]): Fr[] { - return fields.map(parseField); -} diff --git a/yarn-project/cli/src/test/mocks.ts b/yarn-project/cli/src/test/mocks.ts deleted file mode 100644 index 1c56cf0dba2..00000000000 --- a/yarn-project/cli/src/test/mocks.ts +++ /dev/null @@ -1,73 +0,0 @@ -import { ABIParameterVisibility, type ContractArtifact, FunctionType } from '@aztec/foundation/abi'; - -export const mockContractArtifact: ContractArtifact = { - name: 'MockContract', - functions: [ - { - name: 'constructor', - isInitializer: true, - functionType: FunctionType.SECRET, - isInternal: false, - parameters: [ - { - name: 'constructorParam1', - type: { - kind: 'field', - }, - visibility: ABIParameterVisibility.SECRET, - }, - ], - returnTypes: [], - bytecode: Buffer.alloc(8, 0xfa), - debugSymbols: '', - }, - { - name: 'mockFunction', - isInitializer: false, - functionType: FunctionType.SECRET, - isInternal: false, - parameters: [ - { - name: 'fieldParam', - type: { kind: 'field' }, - visibility: ABIParameterVisibility.SECRET, - }, - { - name: 'boolParam', - type: { kind: 'boolean' }, - visibility: ABIParameterVisibility.SECRET, - }, - { - name: 'integerParam', - type: { kind: 'integer', sign: 'signed', width: 32 }, - visibility: ABIParameterVisibility.SECRET, - }, - { - name: 'arrayParam', - type: { kind: 'array', length: 3, type: { kind: 'field' } }, - visibility: ABIParameterVisibility.SECRET, - }, - { - name: 'structParam', - type: { - kind: 'struct', - path: 'mystruct', - fields: [ - { name: 'subField1', type: { kind: 'field' } }, - { name: 'subField2', type: { kind: 'boolean' } }, - ], - }, - visibility: ABIParameterVisibility.SECRET, - }, - ], - returnTypes: [{ kind: 'boolean' }], - bytecode: Buffer.alloc(8, 0xfa), - debugSymbols: '', - }, - ], - outputs: { - structs: {}, - globals: {}, - }, - fileMap: {}, -}; diff --git a/yarn-project/cli/src/test/utils.test.ts b/yarn-project/cli/src/test/utils.test.ts deleted file mode 100644 index 56f3e109d91..00000000000 --- a/yarn-project/cli/src/test/utils.test.ts +++ /dev/null @@ -1,157 +0,0 @@ -import { AztecAddress, Fr } from '@aztec/aztec.js'; -import { CompleteAddress, type PXE } from '@aztec/circuit-types'; - -import { InvalidArgumentError } from 'commander'; -import { type MockProxy, mock } from 'jest-mock-extended'; - -import { encodeArgs } from '../encoding.js'; -import { parseFieldFromHexString } from '../parse_args.js'; -import { getTxSender, stripLeadingHex } from '../utils.js'; -import { mockContractArtifact } from './mocks.js'; - -describe('CLI Utils', () => { - let client: MockProxy; - - // test values - const addr1 = AztecAddress.random(); - const addr2 = AztecAddress.random(); - const addr3 = AztecAddress.random(); - const fieldArray = [addr1.toString(), addr2.toString(), addr3.toString()]; - const num = 33; - const field = Fr.random(); - const struct = { - subField1: field.toString(), - subField2: 'true', - }; - - beforeEach(() => { - client = mock(); - }); - - it('Gets a txSender correctly or throw error', async () => { - // returns a parsed Aztec Address - const aztecAddress = AztecAddress.random(); - const result = await getTxSender(client, aztecAddress.toString()); - expect(client.getRegisteredAccounts).toHaveBeenCalledTimes(0); - expect(result).toEqual(aztecAddress); - - // returns an address found in the aztec client - const completeAddress = CompleteAddress.random(); - client.getRegisteredAccounts.mockResolvedValueOnce([completeAddress]); - const resultWithoutString = await getTxSender(client); - expect(client.getRegisteredAccounts).toHaveBeenCalled(); - expect(resultWithoutString).toEqual(completeAddress.address); - - // throws when invalid parameter passed - const errorAddr = 'foo'; - await expect(getTxSender(client, errorAddr)).rejects.toThrow(`Invalid option 'from' passed: ${errorAddr}`); - - // Throws error when no string is passed & no accounts found in RPC - client.getRegisteredAccounts.mockResolvedValueOnce([]); - await expect(getTxSender(client)).rejects.toThrow('No accounts found in PXE instance.'); - }); - - it('Encodes args correctly', () => { - const args = [addr1.toString(), 'false', num.toString(), `${JSON.stringify(fieldArray)}`, JSON.stringify(struct)]; - const result = encodeArgs(args, mockContractArtifact.functions[1].parameters); - const exp = [ - addr1.toBigInt(), - false, - 33n, - [addr1.toBigInt(), addr2.toBigInt(), addr3.toBigInt()], - { - subField1: field.toBigInt(), - subField2: true, - }, - ]; - expect(result).toEqual(exp); - }); - - it('Errors on invalid inputs', () => { - // invalid number of args - const args1 = [field.toString(), 'false']; - expect(() => encodeArgs(args1, mockContractArtifact.functions[1].parameters)).toThrow('Invalid args provided'); - - // invalid array length - const invalidArray = fieldArray.concat([Fr.random().toString()]); - const args2 = [ - addr1.toString(), - 'false', - num.toString(), - `${JSON.stringify(invalidArray)}`, - JSON.stringify(struct), - ]; - expect(() => encodeArgs(args2, mockContractArtifact.functions[1].parameters)).toThrow( - 'Invalid array length passed for arrayParam. Expected 3, received 4.', - ); - - // invalid struct - const invalidStruct = { - subField1: Fr.random().toString(), - }; - const args3 = [ - addr1.toString(), - 'false', - num.toString(), - `${JSON.stringify(fieldArray)}`, - JSON.stringify(invalidStruct), - ]; - expect(() => encodeArgs(args3, mockContractArtifact.functions[1].parameters)).toThrow( - 'Expected field subField2 not found in struct structParam.', - ); - - // invalid bool - const args4 = [ - addr1.toString(), - 'foo', - num.toString(), - `${JSON.stringify(fieldArray)}`, - JSON.stringify(invalidStruct), - ]; - expect(() => encodeArgs(args4, mockContractArtifact.functions[1].parameters)).toThrow( - 'Invalid boolean value passed for boolParam: foo.', - ); - - // invalid field - const args5 = ['foo', 'false', num.toString(), `${JSON.stringify(fieldArray)}`, JSON.stringify(invalidStruct)]; - expect(() => encodeArgs(args5, mockContractArtifact.functions[1].parameters)).toThrow( - 'Invalid value passed for fieldParam. Could not parse foo as a field.', - ); - - // invalid int - const args6 = [addr1.toString(), 'false', 'foo', `${JSON.stringify(fieldArray)}`, JSON.stringify(invalidStruct)]; - expect(() => encodeArgs(args6, mockContractArtifact.functions[1].parameters)).toThrow( - 'Invalid value passed for integerParam. Could not parse foo as an integer.', - ); - }); - - describe('stripLeadingHex', () => { - it.each([ - ['0x1', '1'], - ['1', '1'], - ['0x00', '00'], - ['00', '00'], - ])('removes optional leading hex', (hex, expected) => { - expect(stripLeadingHex(hex)).toEqual(expected); - }); - }); - - describe('parseSaltFromHexString', () => { - it.each([ - ['0', Fr.ZERO], - ['0x0', Fr.ZERO], - ['00', Fr.ZERO], - ['1', new Fr(1)], - ['0x1', new Fr(1)], - ['0x01', new Fr(1)], - ['0xa', new Fr(0xa)], - ['fff', new Fr(0xfff)], - ])('correctly generates salt from a hex string', (hex, expected) => { - expect(parseFieldFromHexString(hex)).toEqual(expected); - }); - - it.each(['foo', '', ' ', ' 0x1', '01foo', 'foo1', '0xfoo'])('throws an error for invalid hex strings', str => { - expect(() => parseFieldFromHexString(str)).toThrow(InvalidArgumentError); - }); - }); -}); diff --git a/yarn-project/cli/src/update/common.ts b/yarn-project/cli/src/update/common.ts deleted file mode 100644 index 6041c1266e4..00000000000 --- a/yarn-project/cli/src/update/common.ts +++ /dev/null @@ -1,16 +0,0 @@ -/** - * Tracks changes to dependencies - */ -export type DependencyChanges = { - /** Which file was changed */ - file: string; - /** changes done to the file */ - dependencies: Array<{ - /** Name of the dependency being changed */ - name: string; - /** Previous version of the dependency */ - from: string; - /** New version of the dependency (after the update) */ - to: string; - }>; -}; diff --git a/yarn-project/cli/src/update/noir.ts b/yarn-project/cli/src/update/noir.ts deleted file mode 100644 index b18c38284b6..00000000000 --- a/yarn-project/cli/src/update/noir.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { type LogFn } from '@aztec/foundation/log'; -import { parseNoirPackageConfig } from '@aztec/foundation/noir'; - -import TOML from '@iarna/toml'; -import { readFile } from 'fs/promises'; -import { join, relative, resolve } from 'path'; - -import { atomicUpdateFile, prettyPrintNargoToml } from '../utils.js'; -import { type DependencyChanges } from './common.js'; - -/** - * Updates Aztec.nr dependencies - * @param contractPath - Path to the contract to be updated - * @param tag - The tag to update to - * @param log - Logging function - */ -export async function updateAztecNr(contractPath: string, tag: string, log: LogFn): Promise { - const configFilepath = resolve(join(contractPath, 'Nargo.toml')); - const packageConfig = parseNoirPackageConfig(TOML.parse(await readFile(configFilepath, 'utf-8'))); - const changes: DependencyChanges = { - dependencies: [], - file: configFilepath, - }; - - log(`Updating Aztec.nr libraries to ${tag} in ${relative(process.cwd(), changes.file)}`); - for (const dep of Object.values(packageConfig.dependencies)) { - if (!('git' in dep)) { - continue; - } - - // remove trailing slash - const gitUrl = dep.git.toLowerCase().replace(/\/$/, ''); - if (gitUrl !== 'https://github.com/aztecprotocol/aztec-packages') { - continue; - } - - if (dep.tag !== tag) { - // show the Aztec.nr package name rather than the lib name - const dirParts = dep.directory?.split('/') ?? []; - changes.dependencies.push({ - name: dirParts.slice(-2).join('/'), - from: dep.tag, - to: tag, - }); - - dep.tag = tag; - dep.directory = dep.directory?.replace('yarn-project/', 'noir-projects/'); - } - } - - if (changes.dependencies.length > 0) { - const contents = prettyPrintNargoToml(packageConfig); - await atomicUpdateFile(configFilepath, contents); - } - - return changes; -} diff --git a/yarn-project/cli/src/update/npm.ts b/yarn-project/cli/src/update/npm.ts deleted file mode 100644 index c18716ca474..00000000000 --- a/yarn-project/cli/src/update/npm.ts +++ /dev/null @@ -1,154 +0,0 @@ -import { type LogFn } from '@aztec/foundation/log'; - -import { spawnSync } from 'child_process'; -import { existsSync } from 'fs'; -import { readFile } from 'fs/promises'; -import { join, relative, resolve } from 'path'; -import { type SemVer, parse } from 'semver'; - -import { atomicUpdateFile } from '../utils.js'; -import { type DependencyChanges } from './common.js'; - -const deprecatedNpmPackages = new Set(['@aztec/cli', '@aztec/aztec-sandbox']); -const npmDeprecationMessage = ` -The following packages have been deprecated and will no longer be updated on the npm registry: -${Array.from(deprecatedNpmPackages) - .map(pkg => ` - ${pkg}`) - .join('\n')} -Remove them from package.json -`; - -/** - * Looks up a package.json file and returns its contents - * @param projectPath - Path to Nodejs project - * @returns The parsed package.json - */ -export async function readPackageJson(projectPath: string): Promise<{ - /** dependencies */ - dependencies?: Record; - /** devDependencies */ - devDependencies?: Record; -}> { - const configFilepath = resolve(join(projectPath, 'package.json')); - const pkg = JSON.parse(await readFile(configFilepath, 'utf-8')); - - return pkg; -} - -/** - * Queries the npm registry for the latest version of a package - * @param packageName - The package to query - * @param distTag - The distribution tag - * @returns The latest version of the package on that distribution tag - */ -export async function getNewestVersion(packageName: string, distTag = 'latest'): Promise { - const url = new URL(packageName, 'https://registry.npmjs.org/'); - const response = await fetch(url); - if (!response.ok) { - throw new Error(`Failed to fetch ${url}`); - } - - const body = await response.json(); - const latestVersion = parse(body['dist-tags'][distTag]); - if (!latestVersion) { - throw new Error(`Failed to get latest version from registry`); - } - - return latestVersion; -} - -/** - * Updates a project's \@aztec/* dependencies to the specific version - * @param projectPath - Path to Nodejs project - * @param aztecVersion - The version to update to - * @returns True if the project was updated - */ -export async function updateAztecDeps( - projectPath: string, - aztecVersion: SemVer, - log: LogFn, -): Promise { - const pkg = await readPackageJson(projectPath); - const changes: DependencyChanges = { - file: resolve(join(projectPath, 'package.json')), - dependencies: [], - }; - - log(`Updating @aztec packages to ${aztecVersion} in ${relative(process.cwd(), changes.file)}`); - const version = aztecVersion.version; - - let detectedDeprecatedPackages = false; - - for (const depType of ['dependencies', 'devDependencies'] as const) { - const dependencies = pkg[depType]; - if (!dependencies) { - continue; - } - - for (const name of Object.keys(dependencies)) { - if (!name.startsWith('@aztec/')) { - continue; - } - - // different release schedule - if (name === '@aztec/aztec-ui') { - continue; - } - - if (deprecatedNpmPackages.has(name)) { - detectedDeprecatedPackages = true; - continue; - } - - if (dependencies[name] !== version) { - changes.dependencies.push({ - name, - from: dependencies[name], - to: version, - }); - - dependencies[name] = version; - } - } - } - - if (detectedDeprecatedPackages) { - log(npmDeprecationMessage); - } - - if (changes.dependencies.length > 0) { - const contents = JSON.stringify(pkg, null, 2) + '\n'; - await atomicUpdateFile(resolve(join(projectPath, 'package.json')), contents); - } - - return changes; -} - -/** - * Updates a project's yarn.lock or package-lock.json - * @param projectPath - Path to Nodejs project - */ -export function updateLockfile(projectPath: string, log: LogFn): void { - const isNpm = existsSync(resolve(join(projectPath, 'package-lock.json'))); - const isYarn = existsSync(resolve(join(projectPath, 'yarn.lock'))); - const isPnpm = existsSync(resolve(join(projectPath, 'pnpm-lock.yaml'))); - - if (isPnpm) { - spawnSync('pnpm', ['install'], { - cwd: projectPath, - stdio: 'inherit', - }); - } else if (isYarn) { - spawnSync('yarn', ['install'], { - cwd: projectPath, - stdio: 'inherit', - }); - } else if (isNpm) { - spawnSync('npm', ['install'], { - cwd: projectPath, - stdio: 'inherit', - }); - } else { - log(`No lockfile found in ${projectPath}. Skipping lockfile update...`); - } -} diff --git a/yarn-project/cli/src/update/update.ts b/yarn-project/cli/src/update/update.ts deleted file mode 100644 index e2bc90f7947..00000000000 --- a/yarn-project/cli/src/update/update.ts +++ /dev/null @@ -1,79 +0,0 @@ -/* eslint-disable jsdoc/require-jsdoc */ -import { type LogFn } from '@aztec/foundation/log'; - -import { relative, resolve } from 'path'; -import { parse } from 'semver'; - -import { GITHUB_TAG_PREFIX } from '../github.js'; -import { type DependencyChanges } from './common.js'; -import { updateAztecNr } from './noir.js'; -import { getNewestVersion, updateAztecDeps, updateLockfile } from './npm.js'; - -const AZTECJS_PACKAGE = '@aztec/aztec.js'; -const UPDATE_DOCS_URL = 'https://docs.aztec.network/developers/updating'; - -export async function update( - projectPath: string, - contracts: string[], - pxeUrl: string, - aztecVersion: string, - log: LogFn, -): Promise { - const targetAztecVersion = - aztecVersion === 'latest' ? await getNewestVersion(AZTECJS_PACKAGE, 'latest') : parse(aztecVersion); - - if (!targetAztecVersion) { - throw new Error(`Invalid aztec version ${aztecVersion}`); - } - - const projectDependencyChanges: DependencyChanges[] = []; - try { - const npmChanges = await updateAztecDeps(resolve(process.cwd(), projectPath), targetAztecVersion, log); - if (npmChanges.dependencies.length > 0) { - updateLockfile(projectPath, log); - } - - projectDependencyChanges.push(npmChanges); - } catch (err) { - if (err instanceof Error && 'code' in err && err.code === 'ENOENT') { - log(`No package.json found in ${projectPath}. Skipping npm update...`); - } else { - throw err; - } - } - - for (const contract of contracts) { - try { - projectDependencyChanges.push( - await updateAztecNr( - resolve(process.cwd(), projectPath, contract), - `${GITHUB_TAG_PREFIX}-v${targetAztecVersion.version}`, - log, - ), - ); - } catch (err) { - if (err instanceof Error && 'code' in err && err.code === 'ENOENT') { - log(`No Nargo.toml found in ${relative(process.cwd(), contract)}. Skipping...`); - } else { - throw err; - } - } - } - - log(`To update Docker containers follow instructions at ${UPDATE_DOCS_URL}`); - - projectDependencyChanges.forEach(changes => { - printChanges(changes, log); - }); -} - -function printChanges(changes: DependencyChanges, log: LogFn): void { - log(`\nIn ${relative(process.cwd(), changes.file)}:`); - if (changes.dependencies.length === 0) { - log(' No changes'); - } else { - changes.dependencies.forEach(({ name, from, to }) => { - log(` Updated ${name} from ${from} to ${to}`); - }); - } -} diff --git a/yarn-project/cli/src/utils.ts b/yarn-project/cli/src/utils.ts deleted file mode 100644 index e9e17997f2d..00000000000 --- a/yarn-project/cli/src/utils.ts +++ /dev/null @@ -1,235 +0,0 @@ -import { type ContractArtifact, type FunctionArtifact, loadContractArtifact } from '@aztec/aztec.js/abi'; -import { AztecAddress } from '@aztec/aztec.js/aztec_address'; -import { type L1ContractArtifactsForDeployment } from '@aztec/aztec.js/ethereum'; -import { type PXE } from '@aztec/aztec.js/interfaces/pxe'; -import { type DebugLogger } from '@aztec/foundation/log'; -import { type NoirPackageConfig } from '@aztec/foundation/noir'; - -import TOML from '@iarna/toml'; -import { CommanderError, InvalidArgumentError } from 'commander'; -import { readFile, rename, writeFile } from 'fs/promises'; - -import { encodeArgs } from './encoding.js'; - -/** - * Helper type to dynamically import contracts. - */ -interface ArtifactsType { - [key: string]: ContractArtifact; -} - -/** - * Helper to get an ABI function or throw error if it doesn't exist. - * @param artifact - Contract's build artifact in JSON format. - * @param fnName - Function name to be found. - * @returns The function's ABI. - */ -export function getFunctionArtifact(artifact: ContractArtifact, fnName: string): FunctionArtifact { - const fn = artifact.functions.find(({ name }) => name === fnName); - if (!fn) { - throw Error(`Function ${fnName} not found in contract ABI.`); - } - return fn; -} - -/** - * Function to execute the 'deployRollupContracts' command. - * @param rpcUrl - The RPC URL of the ethereum node. - * @param apiKey - The api key of the ethereum node endpoint. - * @param privateKey - The private key to be used in contract deployment. - * @param mnemonic - The mnemonic to be used in contract deployment. - */ -export async function deployAztecContracts( - rpcUrl: string, - apiKey: string, - privateKey: string, - mnemonic: string, - debugLogger: DebugLogger, -) { - const { - AvailabilityOracleAbi, - AvailabilityOracleBytecode, - GasPortalAbi, - GasPortalBytecode, - InboxAbi, - InboxBytecode, - OutboxAbi, - OutboxBytecode, - PortalERC20Abi, - PortalERC20Bytecode, - RegistryAbi, - RegistryBytecode, - RollupAbi, - RollupBytecode, - } = await import('@aztec/l1-artifacts'); - const { createEthereumChain, deployL1Contracts } = await import('@aztec/ethereum'); - const { mnemonicToAccount, privateKeyToAccount } = await import('viem/accounts'); - - const account = !privateKey - ? mnemonicToAccount(mnemonic!) - : privateKeyToAccount(`${privateKey.startsWith('0x') ? '' : '0x'}${privateKey}` as `0x${string}`); - const chain = createEthereumChain(rpcUrl, apiKey); - const l1Artifacts: L1ContractArtifactsForDeployment = { - registry: { - contractAbi: RegistryAbi, - contractBytecode: RegistryBytecode, - }, - inbox: { - contractAbi: InboxAbi, - contractBytecode: InboxBytecode, - }, - outbox: { - contractAbi: OutboxAbi, - contractBytecode: OutboxBytecode, - }, - availabilityOracle: { - contractAbi: AvailabilityOracleAbi, - contractBytecode: AvailabilityOracleBytecode, - }, - rollup: { - contractAbi: RollupAbi, - contractBytecode: RollupBytecode, - }, - gasToken: { - contractAbi: PortalERC20Abi, - contractBytecode: PortalERC20Bytecode, - }, - gasPortal: { - contractAbi: GasPortalAbi, - contractBytecode: GasPortalBytecode, - }, - }; - return await deployL1Contracts(chain.rpcUrl, account, chain.chainInfo, debugLogger, l1Artifacts); -} - -/** - * Gets all contracts available in \@aztec/noir-contracts.js. - * @returns The contract ABIs. - */ -export async function getExampleContractArtifacts(): Promise { - const imports: any = await import('@aztec/noir-contracts.js'); - return Object.fromEntries(Object.entries(imports).filter(([key]) => key.endsWith('Artifact'))) as any; -} - -/** - * Reads a file and converts it to an Aztec Contract ABI. - * @param fileDir - The directory of the compiled contract ABI. - * @returns The parsed contract artifact. - */ -export async function getContractArtifact(fileDir: string) { - // first check if it's a noir-contracts example - const artifacts = await getExampleContractArtifacts(); - if (artifacts[fileDir]) { - return artifacts[fileDir] as ContractArtifact; - } - - let contents: string; - try { - contents = await readFile(fileDir, 'utf8'); - } catch { - throw new Error(`Contract ${fileDir} not found`); - } - - try { - return loadContractArtifact(JSON.parse(contents)); - } catch (err) { - throw new Error(`Invalid contract ABI file ${fileDir}: ${err}`); - } -} - -/** - * Utility to select a TX sender either from user input - * or from the first account that is found in a PXE instance. - * @param pxe - The PXE instance that will be checked for an account. - * @param _from - The user input. - * @returns An Aztec address. Will throw if one can't be found in either options. - */ -export async function getTxSender(pxe: PXE, _from?: string) { - let from: AztecAddress; - if (_from) { - try { - from = AztecAddress.fromString(_from); - } catch { - throw new InvalidArgumentError(`Invalid option 'from' passed: ${_from}`); - } - } else { - const accounts = await pxe.getRegisteredAccounts(); - if (!accounts.length) { - throw new Error('No accounts found in PXE instance.'); - } - from = accounts[0].address; - } - return from; -} - -/** - * Performs necessary checks, conversions & operations to call a contract fn from the CLI. - * @param contractFile - Directory of the compiled contract ABI. - * @param functionName - Name of the function to be called. - * @param _functionArgs - Arguments to call the function with. - * @returns Formatted contract address, function arguments and caller's aztec address. - */ -export async function prepTx(contractFile: string, functionName: string, _functionArgs: string[]) { - const contractArtifact = await getContractArtifact(contractFile); - const functionArtifact = getFunctionArtifact(contractArtifact, functionName); - const functionArgs = encodeArgs(_functionArgs, functionArtifact.parameters); - - return { functionArgs, contractArtifact }; -} - -/** - * Removes the leading 0x from a hex string. If no leading 0x is found the string is returned unchanged. - * @param hex - A hex string - * @returns A new string with leading 0x removed - */ -export const stripLeadingHex = (hex: string) => { - if (hex.length > 2 && hex.startsWith('0x')) { - return hex.substring(2); - } - return hex; -}; - -/** - * Updates a file in place atomically. - * @param filePath - Path to file - * @param contents - New contents to write - */ -export async function atomicUpdateFile(filePath: string, contents: string) { - const tmpFilepath = filePath + '.tmp'; - try { - await writeFile(tmpFilepath, contents, { - // let's crash if the tmp file already exists - flag: 'wx', - }); - await rename(tmpFilepath, filePath); - } catch (e) { - if (e instanceof Error && 'code' in e && e.code === 'EEXIST') { - const commanderError = new CommanderError( - 1, - e.code, - `Temporary file already exists: ${tmpFilepath}. Delete this file and try again.`, - ); - commanderError.nestedError = e.message; - throw commanderError; - } else { - throw e; - } - } -} - -/** - * Pretty prints Nargo.toml contents to a string - * @param config - Nargo.toml contents - * @returns The Nargo.toml contents as a string - */ -export function prettyPrintNargoToml(config: NoirPackageConfig): string { - const withoutDependencies = Object.fromEntries(Object.entries(config).filter(([key]) => key !== 'dependencies')); - - const partialToml = TOML.stringify(withoutDependencies); - const dependenciesToml = Object.entries(config.dependencies).map(([name, dep]) => { - const depToml = TOML.stringify.value(dep); - return `${name} = ${depToml}`; - }); - - return partialToml + '\n[dependencies]\n' + dependenciesToml.join('\n') + '\n'; -} diff --git a/yarn-project/cli/tsconfig.json b/yarn-project/cli/tsconfig.json deleted file mode 100644 index 29032103ade..00000000000 --- a/yarn-project/cli/tsconfig.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "extends": "..", - "compilerOptions": { - "outDir": "dest", - "rootDir": "src", - "tsBuildInfoFile": ".tsbuildinfo" - }, - "references": [ - { - "path": "../accounts" - }, - { - "path": "../aztec.js" - }, - { - "path": "../circuit-types" - }, - { - "path": "../circuits.js" - }, - { - "path": "../ethereum" - }, - { - "path": "../foundation" - }, - { - "path": "../l1-artifacts" - }, - { - "path": "../noir-compiler" - }, - { - "path": "../noir-contracts.js" - }, - { - "path": "../types" - } - ], - "include": ["src"], - "exclude": ["contracts"] -} diff --git a/yarn-project/end-to-end/Earthfile b/yarn-project/end-to-end/Earthfile index f75127fe1f2..b546dbf84a3 100644 --- a/yarn-project/end-to-end/Earthfile +++ b/yarn-project/end-to-end/Earthfile @@ -106,10 +106,6 @@ pxe: ARG e2e_mode=local DO +E2E_TEST --test=pxe.test.ts --e2e_mode=$e2e_mode -cli-docs-sandbox: - ARG e2e_mode=local - DO +E2E_TEST --test=cli_docs_sandbox.test.ts --e2e_mode=$e2e_mode - e2e-docs-examples: ARG e2e_mode=local DO +E2E_TEST --test=docs_examples.test.ts --e2e_mode=$e2e_mode diff --git a/yarn-project/end-to-end/package.json b/yarn-project/end-to-end/package.json index 9fe157450d0..3ff8401dd77 100644 --- a/yarn-project/end-to-end/package.json +++ b/yarn-project/end-to-end/package.json @@ -26,7 +26,6 @@ "@aztec/aztec.js": "workspace:^", "@aztec/circuit-types": "workspace:^", "@aztec/circuits.js": "workspace:^", - "@aztec/cli": "workspace:^", "@aztec/entrypoints": "workspace:^", "@aztec/ethereum": "workspace:^", "@aztec/foundation": "workspace:^", diff --git a/yarn-project/end-to-end/src/composed/cli_docs_sandbox.test.ts b/yarn-project/end-to-end/src/composed/cli_docs_sandbox.test.ts deleted file mode 100644 index 09f026b561f..00000000000 --- a/yarn-project/end-to-end/src/composed/cli_docs_sandbox.test.ts +++ /dev/null @@ -1,389 +0,0 @@ -import { AztecAddress, TxHash, createDebugLogger, sleep } from '@aztec/aztec.js'; -import { getProgram } from '@aztec/cli'; - -import stringArgv from 'string-argv'; - -const debug = createDebugLogger('aztec:e2e_cli'); - -const { PXE_URL = 'http://localhost:8080' } = process.env; - -describe('CLI docs sandbox', () => { - let cli: ReturnType; - let log: (msg: string) => void; - - // All logs emitted by the cli will be collected here, and reset between tests - const logs: string[] = []; - - beforeAll(async () => { - log = (msg: string) => { - logs.push(msg); - debug.verbose(msg); - }; - - await waitForSandboxWithCli(); - }, 60_000); - - const waitForSandboxWithCli = async () => { - const docs = ` -// docs:start:node-info -% aztec-cli get-node-info -Node Info: - -Node Version: #include_aztec_short_version -Chain Id: 31337 -Protocol Version: 1 -Rollup Address: 0x0dcd1bf9a1b36ce34237eeafef220932846bcd82 -// docs:end:node-info -`; - - const command = docs.split('\n')[2].split('aztec-cli ')[1]; - while (true) { - resetCli(); - try { - await run(command); - break; - } catch (err) { - await sleep(1000); - } - } - }; - - // in order to run the same command twice, we need to create a new CLI instance - const resetCli = () => { - cli = getProgram(log, debug); - }; - - beforeEach(() => { - logs.splice(0); - resetCli(); - }); - - // Run a command on the CLI - const run = (cmd: string, addRpcUrl = true) => { - const args = stringArgv(cmd, 'node', 'dest/bin/index.js'); - if (addRpcUrl) { - args.push('--rpc-url', PXE_URL); - } - return cli.parseAsync(args); - }; - - // Returns first match across all logs collected so far - const findInLogs = (regex: RegExp) => { - for (const log of logs) { - const match = regex.exec(log); - if (match) { - return match; - } - } - }; - - const findMultipleInLogs = (regex: RegExp) => { - const matches = []; - for (const log of logs) { - const match = regex.exec(log); - if (match) { - matches.push(match); - } - } - return matches; - }; - - const clearLogs = () => { - logs.splice(0); - }; - - it('prints example contracts', async () => { - const docs = ` -// docs:start:example-contracts -% aztec-cli example-contracts -AppSubscriptionContractArtifact -AuthContractArtifact -BenchmarkingContractArtifact -CardGameContractArtifact -ChildContractArtifact -ClaimContractArtifact -ContractClassRegistererContractArtifact -ContractInstanceDeployerContractArtifact -CounterContractArtifact -CrowdfundingContractArtifact -DelegatedOnContractArtifact -DelegatorContractArtifact -DocsExampleContractArtifact -EasyPrivateTokenContractArtifact -EasyPrivateVotingContractArtifact -EcdsaAccountContractArtifact -EscrowContractArtifact -FPCContractArtifact -GasTokenContractArtifact -ImportTestContractArtifact -InclusionProofsContractArtifact -KeyRegistryContractArtifact -LendingContractArtifact -MultiCallEntrypointContractArtifact -ParentContractArtifact -PendingNoteHashesContractArtifact -PriceFeedContractArtifact -ReaderContractArtifact -SchnorrAccountContractArtifact -SchnorrHardcodedAccountContractArtifact -SchnorrSingleKeyAccountContractArtifact -SlowTreeContractArtifact -StatefulTestContractArtifact -TestContractArtifact -TokenBlacklistContractArtifact -TokenBridgeContractArtifact -TokenContractArtifact -UniswapContractArtifact -// docs:end:example-contracts -`; - - const command = docs.split('\n')[2].split('aztec-cli ')[1]; - const expectedConsoleOutput = docs.split('\n').slice(3, -2); - - await run(command, false); - expect(logs).toEqual(expectedConsoleOutput); - }); - - it('gets a block number', async () => { - const docs = ` -// docs:start:block-number -% aztec-cli block-number -1 -// docs:end:block-number -`; - - const command = docs.split('\n')[2].split('aztec-cli ')[1]; - - await run(command); - // expect logs to contain a number and nothing else - expect(logs.length).toEqual(1); - expect(logs[0]).toMatch(/\d+/); - }); - - it('creates an account from private key', async () => { - const docs = ` -// docs:start:create-account-from-private-key -% aztec-cli generate-private-key - -Private Key: 0x12684562c8676e66be100878434b01286a757dea468233f818b906f66fb34984 -Public Key: 0x1003732857c052c1d6af4dd74b5631863a056c90a586c4e3ea6d94782ee712d317cdb713ed1ba02d3df0ac2b581d269490f9e24916c1b677c7259444aa0ad66b - - -% aztec-cli create-account --private-key 0x12684562c8676e66be100878434b01286a757dea468233f818b906f66fb34984 - -Created new account: - -Address: 0x26e831b1b146d1faf0c1d27fc72f2243887e9963cc87a6b3af64fe6481920a80 -Public key: 0x1003732857c052c1d6af4dd74b5631863a056c90a586c4e3ea6d94782ee712d317cdb713ed1ba02d3df0ac2b581d269490f9e24916c1b677c7259444aa0ad66b -Partial address: 0x01e5e7b2abbfb98a93b7549ae80faa6886f8ea8e8f412416fb330b565fd2b4ed -// docs:end:create-account-from-private-key -`; - - const generateCommand = docs.split('\n')[2].split('aztec-cli ')[1]; - await run(generateCommand, false); - - const foundPrivateKey = findInLogs(/Private\sKey:\s+(?0x[a-fA-F0-9]+)/)?.groups?.privateKey; - expect(foundPrivateKey).toBeDefined(); - const foundPublicKeyGenerate = findInLogs(/Public\sKey:\s+(?0x[a-fA-F0-9]+)/)?.groups?.publicKey; - expect(foundPublicKeyGenerate).toBeDefined(); - - clearLogs(); - - const createCommand = docs.split('\n')[8].split('aztec-cli ')[1]; - - await run(createCommand); - const foundAddress = findInLogs(/Address:\s+(?
0x[a-fA-F0-9]+)/)?.groups?.address; - expect(foundAddress).toBeDefined(); - const foundPublicKey = findInLogs(/Public\skey:\s+(?0x[a-fA-F0-9]+)/)?.groups?.publicKey; - expect(foundPublicKey).toBeDefined(); - const foundPartialAddress = findInLogs(/Partial\saddress:\s+(?0x[a-fA-F0-9]+)/)?.groups - ?.partialAddress; - expect(foundPartialAddress).toBeDefined(); - }); - - it.skip('creates an account, gets account, deploys, checks deployed, view method, sending a tx... [SEQUENTIAL]', async () => { - // Test create-account - let docs = ` -// docs:start:create-account -% aztec-cli create-account -Created new account: - -Address: 0x20d3321707d53cebb168568e25c5c62a853ae1f0766d965e00d6f6c4eb05d599 -Public key: 0x02d18745eadddd496be95274367ee2cbf0bf667b81373fb6bed715c18814a09022907c273ec1c469fcc678738bd8efc3e9053fe1acbb11fa32da0d6881a1370e -Private key: 0x2aba9e7de7075deee3e3f4ad1e47749f985f0f72543ed91063cc97a40d851f1e -Partial address: 0x72bf7c9537875b0af267b4a8c497927e251f5988af6e30527feb16299042ed -// docs:end:create-account -`; - - let command = docs.split('\n')[2].split('aztec-cli ')[1]; - - await run(command); - const foundAddress = findInLogs(/Address:\s+(?
0x[a-fA-F0-9]+)/)?.groups?.address; - expect(foundAddress).toBeDefined(); - const foundPublicKey = findInLogs(/Public\skey:\s+(?0x[a-fA-F0-9]+)/)?.groups?.publicKey; - expect(foundPublicKey).toBeDefined(); - const foundPrivateKey = findInLogs(/Private\skey:\s+(?0x[a-fA-F0-9]+)/)?.groups?.privateKey; - expect(foundPrivateKey).toBeDefined(); - const foundPartialAddress = findInLogs(/Partial\saddress:\s+(?0x[a-fA-F0-9]+)/)?.groups - ?.partialAddress; - expect(foundPartialAddress).toBeDefined(); - const newAddress = AztecAddress.fromString(foundAddress!); - - clearLogs(); - - // Test get-account - docs = ` -// docs:start:get-accounts -% aztec-cli get-accounts -Accounts found: - - Address: 0x0c8a6673d7676cc80aaebe7fa7504cf51daa90ba906861bfad70a58a98bf5a7d - Public Key: 0x27c20118733174347b8082f578a7d8fb84b3ad38be293715eee8119ee5cd8a6d0d6b7d8124b37359663e75bcd2756f544a93b821a06f8e33fba68cc8029794d9 - Partial Address: 0x1c6484e22441e5ca43bba53495d0cdc911da299150fde1191bcb330b64716ff9 - - Address: 0x226f8087792beff8d5009eb94e65d2a4a505b70baf4a9f28d33c8d620b0ba972 - Public Key: 0x08145e8e8d46f51cda8d4c9cad81920236366abeafb8d387002bad879a3e87a81570b04ac829e4c007141d856d5a36d3b9c464e0f3c1c99cdbadaa6bb93f3257 - Partial Address: 0x1833e53112953e6830a230cfc2895caed604f6395bbfafa730da26c5bf53c0a9 - - Address: 0x0e1f60e8566e2c6d32378bdcadb7c63696e853281be798c107266b8c3a88ea9b - Public Key: 0x13e6151ea8e7386a5e7c4c5221047bf73d0b1b7a2ad14d22b7f73e57c1fa00c614bc6da69da1b581b09ee6cdc195e5d58ae4dce01b63bbb744e58f03855a94dd - Partial Address: 0x30034aaf5d78821effa4827a132357110a49a4f37b6e384d884e233595bcf342 - - Address: 0x01b18c2044bbedd4a2e5f67cf6858370ccfb2b869b2000abe2f4ca12d9cc166e - Public Key: 0x240845f1179e3fbaa6ce587d44722b3452bbdaa11deb29553196b23534985d432b746bcf2f0e7046eb13f0ca0c4fedd027dc80b64384f50d6a14ad248faa941a - Partial Address: 0x03834845fc488d1454f195abe7d52b3393f6902eee080c90cd694c63572f7160 -// docs:end:get-accounts -`; - - command = docs.split('\n')[2].split('aztec-cli ')[1]; - await run(command); - - const fetchedAddresses = findMultipleInLogs(/Address:\s+(?
0x[a-fA-F0-9]+)/); - const foundFetchedAddress = fetchedAddresses.find(match => match.groups?.address === newAddress.toString()); - expect(foundFetchedAddress).toBeDefined(); - - clearLogs(); - - // Test deploy - docs = ` -// docs:start:deploy -% aztec-cli deploy TokenContractArtifact --private-key $PRIVATE_KEY --args $ADDRESS TokenName TKN 18 - -Contract deployed at 0x1ae8eea0dc265fb7f160dae62cc8912686d8a9ed78e821fbdd8bcedc54c06d0f -// docs:end:deploy - `; - - command = docs - .split('\n')[2] - .split('aztec-cli ')[1] - .replace('$ADDRESS', newAddress.toString()) - .replace('$PRIVATE_KEY', foundPrivateKey!); - await run(command); - - let foundContractAddress = findInLogs(/Contract\sdeployed\sat\s(?
0x[a-fA-F0-9]+)/)?.groups?.address; - expect(foundContractAddress).toBeDefined(); - const contractAddress = AztecAddress.fromString(foundContractAddress!); - - clearLogs(); - - // Test check-deploy - docs = ` -// docs:start:check-deploy -% aztec-cli check-deploy --contract-address $CONTRACT_ADDRESS - -Contract is publicly deployed at 0x1ae8eea0dc265fb7f160dae62cc8912686d8a9ed78e821fbdd8bcedc54c06d0f -// docs:end:check-deploy -`; - command = docs.split('\n')[2].split('aztec-cli ')[1].replace('$CONTRACT_ADDRESS', contractAddress.toString()); - await run(command); - - foundContractAddress = findInLogs(/Contract.+\sat\s(?
0x[a-fA-F0-9]+)/)?.groups?.address; - expect(foundContractAddress).toEqual(contractAddress.toString()); - - clearLogs(); - - // Test send - docs = ` -// docs:start:send -% aztec-cli send mint_public \ - --args $ADDRESS 543 \ - --contract-artifact TokenContractArtifact \ - --contract-address $CONTRACT_ADDRESS \ - --private-key $PRIVATE_KEY - -Transaction has been mined -Transaction hash: 15c5a8e58d5f895c7e3017a706efbad693635e01f67345fa60a64a340d83c78c -Status: mined -Block number: 5 -Block hash: 163697608599543b2bee9652f543938683e4cdd0f94ac506e5764d8b908d43d4 -// docs:end:send -`; - - command = docs - .split('\n')[2] - .split('aztec-cli ')[1] - .replace('$ADDRESS', newAddress.toString()) - .replace('$CONTRACT_ADDRESS', contractAddress.toString()) - .replace('$PRIVATE_KEY', foundPrivateKey!); - await run(command); - - let foundTxHash = findInLogs(/Transaction\shash:\s+(?\S+)/)?.groups?.txHash; - expect(foundTxHash).toBeDefined(); - - clearLogs(); - - // Save the tx hash for later use - const transferTxHash = TxHash.fromString(foundTxHash!); - - // Test get-tx-receipt - docs = ` -// docs:start:get-tx-receipt -% aztec-cli get-tx-receipt 15c5a8e58d5f895c7e3017a706efbad693635e01f67345fa60a64a340d83c78c - -Transaction receipt: -{ - "txHash": "15c5a8e58d5f895c7e3017a706efbad693635e01f67345fa60a64a340d83c78c", - "status": "mined", - "error": "", - "blockHash": "163697608599543b2bee9652f543938683e4cdd0f94ac506e5764d8b908d43d4", - "blockNumber": 5, - "origin": "0x2337f1d5cfa6c03796db5539b0b2d5a57e9aed42665df2e0907f66820cb6eebe" -} -// docs:end:get-tx-receipt -`; - - command = docs - .split('\n')[2] - .split('aztec-cli ')[1] - .replace('15c5a8e58d5f895c7e3017a706efbad693635e01f67345fa60a64a340d83c78c', transferTxHash.toString()); - await run(command); - - foundTxHash = findInLogs(/"txHash":\s+"(?\S+)"/)?.groups?.txHash; - expect(foundTxHash).toEqual(transferTxHash.toString()); - const status = findInLogs(/"status":\s+"(?\S+)"/)?.groups?.status; - expect(status).toEqual('mined'); - const error = findInLogs(/"error":\s+"(?\S*)"/)?.groups?.error; - expect(error).toEqual(''); - - clearLogs(); - - // Test call - docs = ` -// docs:start:call -% aztec-cli call balance_of_public -a $ADDRESS -c TokenContractArtifact -ca $CONTRACT_ADDRESS - -View result: 543n -// docs:end:call -`; - command = docs - .split('\n')[2] - .split('aztec-cli ')[1] - .replace('$ADDRESS', newAddress.toString()) - .replace('$CONTRACT_ADDRESS', contractAddress.toString()); - - await run(command); - - const foundBalance = findInLogs(/View\sresult:\s+(?\S+)/)?.groups?.data; - expect(foundBalance!).toEqual(`${BigInt(543).toString()}n`); - }, 60_000); -}); diff --git a/yarn-project/end-to-end/src/e2e_cli.test.ts b/yarn-project/end-to-end/src/e2e_cli.test.ts deleted file mode 100644 index 7acb8ed6327..00000000000 --- a/yarn-project/end-to-end/src/e2e_cli.test.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { type PXE, createDebugLogger } from '@aztec/aztec.js'; -import { startHttpRpcServer } from '@aztec/foundation/json-rpc/server'; -import { createPXERpcServer } from '@aztec/pxe'; - -import { setup as e2eSetup } from './fixtures/utils.js'; -import { cliTestSuite } from './shared/cli.js'; - -const HTTP_PORT = 9009; -const log = createDebugLogger('aztec:e2e_cli'); - -const { PXE_URL = '' } = process.env; -let RPC_URL = PXE_URL; - -let http: ReturnType; -let pxe: PXE; -let teardown: () => Promise; - -const testSetup = async () => { - const context = await e2eSetup(2); - log.info(`Environment set up`); - ({ pxe, teardown } = context); - if (!RPC_URL) { - http = startHttpRpcServer('pxe', pxe, createPXERpcServer, HTTP_PORT); - log.info(`HTTP RPC server started on port ${HTTP_PORT}`); - RPC_URL = `http://localhost:${HTTP_PORT}`; - } - return { pxe, rpcURL: RPC_URL }; -}; - -const testCleanup = async () => { - http?.close(); - await teardown(); -}; - -cliTestSuite('E2E CLI Test', testSetup, testCleanup, createDebugLogger('aztec:e2e_cli')); diff --git a/yarn-project/end-to-end/src/guides/up_quick_start.test.ts b/yarn-project/end-to-end/src/guides/up_quick_start.test.ts index dfacf8687cf..1dd55e6ea35 100644 --- a/yarn-project/end-to-end/src/guides/up_quick_start.test.ts +++ b/yarn-project/end-to-end/src/guides/up_quick_start.test.ts @@ -6,7 +6,8 @@ const { PXE_URL = '' } = process.env; // Entrypoint for running the up-quick-start script on the CI describe('guides/up_quick_start', () => { - it('works', async () => { + // TODO: update to not use CLI + it.skip('works', async () => { await waitForPXE(createPXEClient(PXE_URL)); execSync( `DEBUG="aztec:*" PXE_URL=\${PXE_URL:-http://localhost:8080} PATH=$PATH:../node_modules/.bin ./src/guides/up_quick_start.sh`, diff --git a/yarn-project/end-to-end/src/shared/cli.ts b/yarn-project/end-to-end/src/shared/cli.ts deleted file mode 100644 index b6738c2371a..00000000000 --- a/yarn-project/end-to-end/src/shared/cli.ts +++ /dev/null @@ -1,242 +0,0 @@ -import { - AztecAddress, - type CompleteAddress, - type DebugLogger, - Fr, - type PXE, - computeMessageSecretHash, -} from '@aztec/aztec.js'; -import { getProgram } from '@aztec/cli'; - -import stringArgv from 'string-argv'; - -const INITIAL_BALANCE = 33000; -const TRANSFER_BALANCE = 3000; - -export const cliTestSuite = ( - name: string, - setup: () => Promise<{ pxe: PXE; rpcURL: string }>, - cleanup: () => Promise, - debug: DebugLogger, -) => - describe(name, () => { - let cli: ReturnType; - let pxe: PXE; - let existingAccounts: CompleteAddress[]; - let contractAddress: AztecAddress; - let log: (msg: string) => void; - let rpcURL = ''; - - // All logs emitted by the cli will be collected here, and reset between tests - const logs: string[] = []; - - beforeAll(async () => { - ({ pxe, rpcURL } = await setup()); - log = (msg: string) => { - logs.push(msg); - debug.verbose(msg); - }; - }, 30_000); - - afterAll(async () => { - await cleanup(); - }); - - // in order to run the same command twice, we need to create a new CLI instance - const resetCli = () => { - cli = getProgram(log, debug); - }; - - beforeEach(() => { - logs.splice(0); - resetCli(); - }); - - // Run a command on the CLI - const run = (cmd: string, addRpcUrl = true) => { - const args = stringArgv(cmd, 'node', 'dest/bin/index.js'); - if (addRpcUrl) { - args.push('--rpc-url', rpcURL); - } - debug.info(`Running command ${args.join(' ')}`); - const res = cli.parseAsync(args); - resetCli(); - return res; - }; - - // Returns first match across all logs collected so far - const findInLogs = (regex: RegExp) => { - for (const log of logs) { - const match = regex.exec(log); - if (match) { - return match; - } - } - }; - - const findMultipleInLogs = (regex: RegExp) => { - const matches = []; - for (const log of logs) { - const match = regex.exec(log); - if (match) { - matches.push(match); - } - } - return matches; - }; - - const clearLogs = () => { - logs.splice(0); - }; - - it('creates & retrieves an account', async () => { - existingAccounts = await pxe.getRegisteredAccounts(); - debug.info('Create an account'); - await run(`create-account`); - const foundAddress = findInLogs(/Address:\s+(?
0x[a-fA-F0-9]+)/)?.groups?.address; - expect(foundAddress).toBeDefined(); - const newAddress = AztecAddress.fromString(foundAddress!); - - const accountsAfter = await pxe.getRegisteredAccounts(); - const expectedAccounts = [...existingAccounts.map(a => a.address), newAddress]; - expect(accountsAfter.map(a => a.address)).toEqual(expectedAccounts); - const newCompleteAddress = accountsAfter[accountsAfter.length - 1]; - - // Test get-accounts - debug.info('Check that account was added to the list of accounts in RPC'); - await run('get-accounts'); - const fetchedAddresses = findMultipleInLogs(/Address:\s+(?
0x[a-fA-F0-9]+)/); - const foundFetchedAddress = fetchedAddresses.find(match => match.groups?.address === newAddress.toString()); - expect(foundFetchedAddress).toBeDefined(); - - // Test get-account - debug.info('Check we can retrieve the specific account'); - clearLogs(); - await run(`get-account ${newAddress.toString()}`); - const fetchedAddress = findInLogs(/Public Key:\s+(?
0x[a-fA-F0-9]+)/)?.groups?.address; - expect(fetchedAddress).toEqual(newCompleteAddress.publicKey.toString()); - }); - - // Regression test for deploy cmd with a constructor not named "constructor" - it('deploys a contract using a public initializer', async () => { - debug.info('Create an account using a private key'); - await run('generate-private-key', false); - const privKey = findInLogs(/Private\sKey:\s+0x(?[a-fA-F0-9]+)/)?.groups?.privKey; - expect(privKey).toHaveLength(64); - await run(`create-account --private-key ${privKey}`); - const foundAddress = findInLogs(/Address:\s+(?
0x[a-fA-F0-9]+)/)?.groups?.address; - expect(foundAddress).toBeDefined(); - const ownerAddress = AztecAddress.fromString(foundAddress!); - const salt = 42; - - debug.info('Deploy StatefulTestContract with public_constructor using created account.'); - await run( - `deploy StatefulTestContractArtifact --private-key ${privKey} --salt ${salt} --initializer public_constructor --args ${ownerAddress} 100`, - ); - const loggedAddress = findInLogs(/Contract\sdeployed\sat\s+(?
0x[a-fA-F0-9]+)/)?.groups?.address; - expect(loggedAddress).toBeDefined(); - contractAddress = AztecAddress.fromString(loggedAddress!); - - const deployedContract = await pxe.getContractInstance(contractAddress); - expect(deployedContract?.address).toEqual(contractAddress); - - clearLogs(); - await run( - `call get_public_value --args ${ownerAddress} --contract-artifact StatefulTestContractArtifact --contract-address ${contractAddress.toString()}`, - ); - - const balance = findInLogs(/View\sresult:\s+(?\S+)/)?.groups?.data; - expect(balance!).toEqual(`${BigInt(100).toString()}n`); - }, 60_000); - - it.each([ - ['an example Token contract', 'TokenContractArtifact', '0'], - ['a Nargo artifact', '../noir-contracts.js/artifacts/token_contract-Token.json', '1'], - ])( - 'deploys %s & sends transactions', - async (_, artifact, salt) => { - // generate a private key - debug.info('Create an account using a private key'); - await run('generate-private-key', false); - const privKey = findInLogs(/Private\sKey:\s+0x(?[a-fA-F0-9]+)/)?.groups?.privKey; - expect(privKey).toHaveLength(64); - await run(`create-account --private-key ${privKey}`); - const foundAddress = findInLogs(/Address:\s+(?
0x[a-fA-F0-9]+)/)?.groups?.address; - expect(foundAddress).toBeDefined(); - const ownerAddress = AztecAddress.fromString(foundAddress!); - - debug.info('Deploy Token Contract using created account.'); - await run( - `deploy ${artifact} --private-key ${privKey} --salt ${salt} --args ${ownerAddress} 'TokenName' 'TKN' 18`, - ); - const loggedAddress = findInLogs(/Contract\sdeployed\sat\s+(?
0x[a-fA-F0-9]+)/)?.groups?.address; - expect(loggedAddress).toBeDefined(); - contractAddress = AztecAddress.fromString(loggedAddress!); - - const deployedContract = await pxe.getContractInstance(contractAddress); - expect(deployedContract?.address).toEqual(contractAddress); - - debug.info('Check contract can be found in returned address'); - await run(`check-deploy -ca ${loggedAddress}`); - const checkResult = findInLogs(/Contract.+\sat\s+(?
0x[a-fA-F0-9]+)/)?.groups?.address; - expect(checkResult).toEqual(deployedContract?.address.toString()); - - const secret = Fr.random(); - const secretHash = computeMessageSecretHash(secret); - - debug.info('Mint initial tokens.'); - await run( - `send mint_private --args ${INITIAL_BALANCE} ${secretHash} --contract-artifact TokenContractArtifact --contract-address ${contractAddress.toString()} --private-key ${privKey}`, - ); - - debug.info('Add note to the PXE.'); - const txHashes = findMultipleInLogs(/Transaction Hash: ([0-9a-f]{64})/i); - const mintPrivateTxHash = txHashes[txHashes.length - 1][1]; - await run( - `add-note ${ownerAddress} ${contractAddress} 5 84114971101151129711410111011678111116101 ${mintPrivateTxHash} --note ${INITIAL_BALANCE} ${secretHash}`, - ); - - debug.info('Redeem tokens.'); - await run( - `send redeem_shield --args ${ownerAddress} ${INITIAL_BALANCE} ${secret} --contract-artifact TokenContractArtifact --contract-address ${contractAddress.toString()} --private-key ${privKey}`, - ); - - clearLogs(); - await run(`get-contract-data ${loggedAddress}`); - const contractDataAddress = findInLogs(/^\s?Address:\s+(?
0x[a-fA-F0-9]+)/)?.groups?.address; - expect(contractDataAddress).toEqual(deployedContract?.address.toString()); - - debug.info("Check owner's balance"); - await run( - `call balance_of_private --args ${ownerAddress} --contract-artifact TokenContractArtifact --contract-address ${contractAddress.toString()}`, - ); - const balance = findInLogs(/View\sresult:\s+(?\S+)/)?.groups?.data; - expect(balance!).toEqual(`${BigInt(INITIAL_BALANCE).toString()}n`); - - debug.info('Transfer some tokens'); - const existingAccounts = await pxe.getRegisteredAccounts(); - // ensure we pick a different acc - const receiver = existingAccounts.find(acc => acc.address.toString() !== ownerAddress.toString()); - - await run( - `send transfer --args ${ownerAddress.toString()} ${receiver?.address.toString()} ${TRANSFER_BALANCE} 0 --contract-address ${contractAddress.toString()} --contract-artifact TokenContractArtifact --private-key ${privKey}`, - ); - const txHash = findInLogs(/Transaction\shash:\s+(?\S+)/)?.groups?.txHash; - - debug.info('Check the transfer receipt'); - await run(`get-tx-receipt ${txHash}`); - const txResult = findInLogs(/Transaction receipt:\s*(?[\s\S]*?\})/)?.groups?.txHash; - const parsedResult = JSON.parse(txResult!); - expect(parsedResult.txHash).toEqual(txHash); - expect(parsedResult.status).toEqual('mined'); - debug.info("Check Receiver's balance"); - clearLogs(); - await run( - `call balance_of_private --args ${receiver?.address.toString()} --contract-artifact TokenContractArtifact --contract-address ${contractAddress.toString()}`, - ); - const receiverBalance = findInLogs(/View\sresult:\s+(?\S+)/)?.groups?.data; - expect(receiverBalance).toEqual(`${BigInt(TRANSFER_BALANCE).toString()}n`); - }, - 100_000, - ); - }); diff --git a/yarn-project/end-to-end/src/shared/index.ts b/yarn-project/end-to-end/src/shared/index.ts index 4c6d1eef910..dcb31a19745 100644 --- a/yarn-project/end-to-end/src/shared/index.ts +++ b/yarn-project/end-to-end/src/shared/index.ts @@ -1,3 +1,2 @@ -export { cliTestSuite } from './cli.js'; export { browserTestSuite } from './browser.js'; export { uniswapL1L2TestSuite, UniswapSetupContext } from './uniswap_l1_l2.js'; diff --git a/yarn-project/end-to-end/tsconfig.json b/yarn-project/end-to-end/tsconfig.json index 159d8f7cea1..b0e697f1148 100644 --- a/yarn-project/end-to-end/tsconfig.json +++ b/yarn-project/end-to-end/tsconfig.json @@ -24,9 +24,6 @@ { "path": "../circuits.js" }, - { - "path": "../cli" - }, { "path": "../entrypoints" }, diff --git a/yarn-project/noir-compiler/aztec-compile-dest b/yarn-project/noir-compiler/aztec-compile-dest new file mode 100755 index 00000000000..c5b74ae02df --- /dev/null +++ b/yarn-project/noir-compiler/aztec-compile-dest @@ -0,0 +1,3 @@ +#!/bin/sh +SCRIPT_PATH=$(dirname $(realpath $0)) +node --no-warnings $SCRIPT_PATH/dest/cli.js $@ diff --git a/yarn-project/tsconfig.json b/yarn-project/tsconfig.json index eafb807f772..3fde67b857e 100644 --- a/yarn-project/tsconfig.json +++ b/yarn-project/tsconfig.json @@ -29,7 +29,6 @@ { "path": "aztec/tsconfig.json" }, { "path": "circuits.js/tsconfig.json" }, { "path": "circuit-types/tsconfig.json" }, - { "path": "cli/tsconfig.json" }, { "path": "end-to-end/tsconfig.json" }, { "path": "foundation/tsconfig.json" }, { "path": "key-store/tsconfig.json" }, diff --git a/yarn-project/yarn.lock b/yarn-project/yarn.lock index 1121959ee0b..105ac89cb19 100644 --- a/yarn-project/yarn.lock +++ b/yarn-project/yarn.lock @@ -314,45 +314,6 @@ __metadata: languageName: unknown linkType: soft -"@aztec/cli@workspace:^, @aztec/cli@workspace:cli": - version: 0.0.0-use.local - resolution: "@aztec/cli@workspace:cli" - dependencies: - "@aztec/accounts": "workspace:^" - "@aztec/aztec.js": "workspace:^" - "@aztec/circuit-types": "workspace:^" - "@aztec/circuits.js": "workspace:^" - "@aztec/ethereum": "workspace:^" - "@aztec/foundation": "workspace:^" - "@aztec/l1-artifacts": "workspace:^" - "@aztec/noir-compiler": "workspace:^" - "@aztec/noir-contracts.js": "workspace:^" - "@aztec/types": "workspace:^" - "@iarna/toml": ^2.2.5 - "@jest/globals": ^29.5.0 - "@libp2p/peer-id-factory": ^3.0.4 - "@types/jest": ^29.5.0 - "@types/lodash.startcase": ^4.4.7 - "@types/node": ^18.7.23 - "@types/semver": ^7.5.2 - "@types/source-map-support": ^0.5.10 - commander: ^9.0.0 - jest: ^29.5.0 - jest-mock-extended: ^3.0.5 - jszip: ^3.10.1 - lodash.startcase: ^4.4.0 - node-fetch: ^3.3.2 - semver: ^7.5.4 - source-map-support: ^0.5.21 - ts-node: ^10.9.1 - tslib: ^2.4.0 - typescript: ^5.0.4 - viem: ^2.7.15 - bin: - aztec-cli: ./dest/bin/index.js - languageName: unknown - linkType: soft - "@aztec/docs@workspace:docs": version: 0.0.0-use.local resolution: "@aztec/docs@workspace:docs" @@ -371,7 +332,6 @@ __metadata: "@aztec/aztec.js": "workspace:^" "@aztec/circuit-types": "workspace:^" "@aztec/circuits.js": "workspace:^" - "@aztec/cli": "workspace:^" "@aztec/entrypoints": "workspace:^" "@aztec/ethereum": "workspace:^" "@aztec/foundation": "workspace:^" @@ -2467,7 +2427,7 @@ __metadata: languageName: node linkType: hard -"@libp2p/peer-id-factory@npm:^3.0.3, @libp2p/peer-id-factory@npm:^3.0.4, @libp2p/peer-id-factory@npm:^3.0.8": +"@libp2p/peer-id-factory@npm:^3.0.3, @libp2p/peer-id-factory@npm:^3.0.8": version: 3.0.11 resolution: "@libp2p/peer-id-factory@npm:3.0.11" dependencies: @@ -3617,15 +3577,6 @@ __metadata: languageName: node linkType: hard -"@types/lodash.startcase@npm:^4.4.7": - version: 4.4.9 - resolution: "@types/lodash.startcase@npm:4.4.9" - dependencies: - "@types/lodash": "*" - checksum: 448203f0b6d31c1af9fe8292d5417af670bee560bb0af0cac3a6047b90c2d60ba03197367c2defae21e3982c665763197343863ce7d97131efa8e13e6431fe9f - languageName: node - linkType: hard - "@types/lodash.times@npm:^4.3.7": version: 4.3.9 resolution: "@types/lodash.times@npm:4.3.9" @@ -3748,7 +3699,7 @@ __metadata: languageName: node linkType: hard -"@types/semver@npm:^7.5.0, @types/semver@npm:^7.5.2, @types/semver@npm:^7.5.4": +"@types/semver@npm:^7.5.0, @types/semver@npm:^7.5.4": version: 7.5.6 resolution: "@types/semver@npm:7.5.6" checksum: 563a0120ec0efcc326567db2ed920d5d98346f3638b6324ea6b50222b96f02a8add3c51a916b6897b51523aad8ac227d21d3dcf8913559f1bfc6c15b14d23037 @@ -5570,7 +5521,7 @@ __metadata: languageName: node linkType: hard -"core-util-is@npm:^1.0.2, core-util-is@npm:~1.0.0": +"core-util-is@npm:^1.0.2": version: 1.0.3 resolution: "core-util-is@npm:1.0.3" checksum: 9de8597363a8e9b9952491ebe18167e3b36e7707569eed0ebf14f8bba773611376466ae34575bca8cfe3c767890c859c74056084738f09d4e4a6f902b2ad7d99 @@ -5694,13 +5645,6 @@ __metadata: languageName: node linkType: hard -"data-uri-to-buffer@npm:^4.0.0": - version: 4.0.1 - resolution: "data-uri-to-buffer@npm:4.0.1" - checksum: 0d0790b67ffec5302f204c2ccca4494f70b4e2d940fea3d36b09f0bb2b8539c2e86690429eb1f1dc4bcc9e4df0644193073e63d9ee48ac9fce79ec1506e4aa4c - languageName: node - linkType: hard - "data-uri-to-buffer@npm:^6.0.0": version: 6.0.1 resolution: "data-uri-to-buffer@npm:6.0.1" @@ -7072,16 +7016,6 @@ __metadata: languageName: node linkType: hard -"fetch-blob@npm:^3.1.2, fetch-blob@npm:^3.1.4": - version: 3.2.0 - resolution: "fetch-blob@npm:3.2.0" - dependencies: - node-domexception: ^1.0.0 - web-streams-polyfill: ^3.0.3 - checksum: f19bc28a2a0b9626e69fd7cf3a05798706db7f6c7548da657cbf5026a570945f5eeaedff52007ea35c8bcd3d237c58a20bf1543bc568ab2422411d762dd3d5bf - languageName: node - linkType: hard - "file-entry-cache@npm:^6.0.1": version: 6.0.1 resolution: "file-entry-cache@npm:6.0.1" @@ -7233,15 +7167,6 @@ __metadata: languageName: node linkType: hard -"formdata-polyfill@npm:^4.0.10": - version: 4.0.10 - resolution: "formdata-polyfill@npm:4.0.10" - dependencies: - fetch-blob: ^3.1.2 - checksum: 82a34df292afadd82b43d4a740ce387bc08541e0a534358425193017bf9fb3567875dc5f69564984b1da979979b70703aa73dee715a17b6c229752ae736dd9db - languageName: node - linkType: hard - "formidable@npm:^2.1.2": version: 2.1.2 resolution: "formidable@npm:2.1.2" @@ -7931,13 +7856,6 @@ __metadata: languageName: node linkType: hard -"immediate@npm:~3.0.5": - version: 3.0.6 - resolution: "immediate@npm:3.0.6" - checksum: f9b3486477555997657f70318cc8d3416159f208bec4cca3ff3442fd266bc23f50f0c9bd8547e1371a6b5e82b821ec9a7044a4f7b944798b25aa3cc6d5e63e62 - languageName: node - linkType: hard - "import-fresh@npm:^3.2.1, import-fresh@npm:^3.3.0": version: 3.3.0 resolution: "import-fresh@npm:3.3.0" @@ -7998,7 +7916,7 @@ __metadata: languageName: node linkType: hard -"inherits@npm:2, inherits@npm:2.0.4, inherits@npm:^2.0.1, inherits@npm:^2.0.3, inherits@npm:^2.0.4, inherits@npm:~2.0.3, inherits@npm:~2.0.4": +"inherits@npm:2, inherits@npm:2.0.4, inherits@npm:^2.0.1, inherits@npm:^2.0.3, inherits@npm:^2.0.4, inherits@npm:~2.0.4": version: 2.0.4 resolution: "inherits@npm:2.0.4" checksum: 4a48a733847879d6cf6691860a6b1e3f0f4754176e4d71494c41f3475553768b10f84b5ce1d40fbd0e34e6bfbb864ee35858ad4dd2cf31e02fc4a154b724d7f1 @@ -8413,13 +8331,6 @@ __metadata: languageName: node linkType: hard -"isarray@npm:~1.0.0": - version: 1.0.0 - resolution: "isarray@npm:1.0.0" - checksum: f032df8e02dce8ec565cf2eb605ea939bdccea528dbcf565cdf92bfa2da9110461159d86a537388ef1acef8815a330642d7885b29010e8f7eac967c9993b65ab - languageName: node - linkType: hard - "isexe@npm:^2.0.0": version: 2.0.0 resolution: "isexe@npm:2.0.0" @@ -9369,18 +9280,6 @@ __metadata: languageName: node linkType: hard -"jszip@npm:^3.10.1": - version: 3.10.1 - resolution: "jszip@npm:3.10.1" - dependencies: - lie: ~3.3.0 - pako: ~1.0.2 - readable-stream: ~2.3.6 - setimmediate: ^1.0.5 - checksum: abc77bfbe33e691d4d1ac9c74c8851b5761fba6a6986630864f98d876f3fcc2d36817dfc183779f32c00157b5d53a016796677298272a714ae096dfe6b1c8b60 - languageName: node - linkType: hard - "keygrip@npm:~1.1.0": version: 1.1.0 resolution: "keygrip@npm:1.1.0" @@ -9668,15 +9567,6 @@ __metadata: languageName: node linkType: hard -"lie@npm:~3.3.0": - version: 3.3.0 - resolution: "lie@npm:3.3.0" - dependencies: - immediate: ~3.0.5 - checksum: 33102302cf19766f97919a6a98d481e01393288b17a6aa1f030a3542031df42736edde8dab29ffdbf90bebeffc48c761eb1d064dc77592ca3ba3556f9fe6d2a8 - languageName: node - linkType: hard - "lines-and-columns@npm:^1.1.6": version: 1.2.4 resolution: "lines-and-columns@npm:1.2.4" @@ -9840,13 +9730,6 @@ __metadata: languageName: node linkType: hard -"lodash.startcase@npm:^4.4.0": - version: 4.4.0 - resolution: "lodash.startcase@npm:4.4.0" - checksum: c03a4a784aca653845fe09d0ef67c902b6e49288dc45f542a4ab345a9c406a6dc194c774423fa313ee7b06283950301c1221dd2a1d8ecb2dac8dfbb9ed5606b5 - languageName: node - linkType: hard - "lodash.times@npm:^4.3.2": version: 4.3.2 resolution: "lodash.times@npm:4.3.2" @@ -10554,13 +10437,6 @@ __metadata: languageName: node linkType: hard -"node-domexception@npm:^1.0.0": - version: 1.0.0 - resolution: "node-domexception@npm:1.0.0" - checksum: ee1d37dd2a4eb26a8a92cd6b64dfc29caec72bff5e1ed9aba80c294f57a31ba4895a60fd48347cf17dd6e766da0ae87d75657dfd1f384ebfa60462c2283f5c7f - languageName: node - linkType: hard - "node-fetch@npm:^2.6.12": version: 2.7.0 resolution: "node-fetch@npm:2.7.0" @@ -10575,17 +10451,6 @@ __metadata: languageName: node linkType: hard -"node-fetch@npm:^3.3.2": - version: 3.3.2 - resolution: "node-fetch@npm:3.3.2" - dependencies: - data-uri-to-buffer: ^4.0.0 - fetch-blob: ^3.1.4 - formdata-polyfill: ^4.0.10 - checksum: 06a04095a2ddf05b0830a0d5302699704d59bda3102894ea64c7b9d4c865ecdff2d90fd042df7f5bc40337266961cb6183dcc808ea4f3000d024f422b462da92 - languageName: node - linkType: hard - "node-forge@npm:^1.1.0": version: 1.3.1 resolution: "node-forge@npm:1.3.1" @@ -11039,13 +10904,6 @@ __metadata: languageName: node linkType: hard -"pako@npm:~1.0.2": - version: 1.0.11 - resolution: "pako@npm:1.0.11" - checksum: 1be2bfa1f807608c7538afa15d6f25baa523c30ec870a3228a89579e474a4d992f4293859524e46d5d87fd30fa17c5edf34dbef0671251d9749820b488660b16 - languageName: node - linkType: hard - "parent-module@npm:^1.0.0": version: 1.0.1 resolution: "parent-module@npm:1.0.1" @@ -11361,13 +11219,6 @@ __metadata: languageName: node linkType: hard -"process-nextick-args@npm:~2.0.0": - version: 2.0.1 - resolution: "process-nextick-args@npm:2.0.1" - checksum: 1d38588e520dab7cea67cbbe2efdd86a10cc7a074c09657635e34f035277b59fbb57d09d8638346bf7090f8e8ebc070c96fa5fd183b777fff4f5edff5e9466cf - languageName: node - linkType: hard - "process@npm:^0.11.10": version: 0.11.10 resolution: "process@npm:0.11.10" @@ -11655,21 +11506,6 @@ __metadata: languageName: node linkType: hard -"readable-stream@npm:~2.3.6": - version: 2.3.8 - resolution: "readable-stream@npm:2.3.8" - dependencies: - core-util-is: ~1.0.0 - inherits: ~2.0.3 - isarray: ~1.0.0 - process-nextick-args: ~2.0.0 - safe-buffer: ~5.1.1 - string_decoder: ~1.1.1 - util-deprecate: ~1.0.1 - checksum: 65645467038704f0c8aaf026a72fbb588a9e2ef7a75cd57a01702ee9db1c4a1e4b03aaad36861a6a0926546a74d174149c8c207527963e0c2d3eee2f37678a42 - languageName: node - linkType: hard - "receptacle@npm:^1.3.2": version: 1.3.2 resolution: "receptacle@npm:1.3.2" @@ -11971,13 +11807,6 @@ __metadata: languageName: node linkType: hard -"safe-buffer@npm:~5.1.0, safe-buffer@npm:~5.1.1": - version: 5.1.2 - resolution: "safe-buffer@npm:5.1.2" - checksum: f2f1f7943ca44a594893a852894055cf619c1fbcb611237fc39e461ae751187e7baf4dc391a72125e0ac4fb2d8c5c0b3c71529622e6a58f46b960211e704903c - languageName: node - linkType: hard - "safe-regex-test@npm:^1.0.0": version: 1.0.2 resolution: "safe-regex-test@npm:1.0.2" @@ -12123,13 +11952,6 @@ __metadata: languageName: node linkType: hard -"setimmediate@npm:^1.0.5": - version: 1.0.5 - resolution: "setimmediate@npm:1.0.5" - checksum: c9a6f2c5b51a2dabdc0247db9c46460152ffc62ee139f3157440bd48e7c59425093f42719ac1d7931f054f153e2d26cf37dfeb8da17a794a58198a2705e527fd - languageName: node - linkType: hard - "setprototypeof@npm:1.1.0": version: 1.1.0 resolution: "setprototypeof@npm:1.1.0" @@ -12581,15 +12403,6 @@ __metadata: languageName: node linkType: hard -"string_decoder@npm:~1.1.1": - version: 1.1.1 - resolution: "string_decoder@npm:1.1.1" - dependencies: - safe-buffer: ~5.1.0 - checksum: 9ab7e56f9d60a28f2be697419917c50cac19f3e8e6c28ef26ed5f4852289fe0de5d6997d29becf59028556f2c62983790c1d9ba1e2a3cc401768ca12d5183a5b - languageName: node - linkType: hard - "stringify-object@npm:^3.2.1": version: 3.3.0 resolution: "stringify-object@npm:3.3.0" @@ -13441,7 +13254,7 @@ __metadata: languageName: node linkType: hard -"util-deprecate@npm:^1.0.1, util-deprecate@npm:~1.0.1": +"util-deprecate@npm:^1.0.1": version: 1.0.2 resolution: "util-deprecate@npm:1.0.2" checksum: 474acf1146cb2701fe3b074892217553dfcf9a031280919ba1b8d651a068c9b15d863b7303cb15bd00a862b498e6cf4ad7b4a08fb134edd5a6f7641681cb54a2 @@ -13620,13 +13433,6 @@ __metadata: languageName: node linkType: hard -"web-streams-polyfill@npm:^3.0.3": - version: 3.3.2 - resolution: "web-streams-polyfill@npm:3.3.2" - checksum: 0292f4113c1bda40d8e8ecebee39eb14cc2e2e560a65a6867980e394537a2645130e2c73f5ef6e641fd3697d2f71720ccf659aebaf69a9d5a773f653a0fdf39d - languageName: node - linkType: hard - "webidl-conversions@npm:^3.0.0": version: 3.0.1 resolution: "webidl-conversions@npm:3.0.1" From 566f25c25744501ce1ae31243820ef549d9b1f30 Mon Sep 17 00:00:00 2001 From: Gregorio Juliana Date: Mon, 22 Apr 2024 11:23:44 +0200 Subject: [PATCH 046/102] chore: Improve `compute_note_hash_and_nullifier` autogeneration and `NoteProcessor` warnings (#5838) Closes https://github.com/AztecProtocol/aztec-packages/issues/5669, https://github.com/AztecProtocol/aztec-packages/issues/5670, https://github.com/AztecProtocol/aztec-packages/issues/4649 Correctly determines the signature of the autogenerated `compute_note_hash_and_nullifier` by looking up the serialized content size of notes used in the contract. Furthermore, that langth is compared against MAX_NOTE_FIELDS_LEN and a compile time error is emited if the user attempts to use a note that is bigger than currently supported. Finally changed the `NoteProcessor` warns to be errors (even thought this particular one shouldn't get that far anymore!) --- .../src/core/libraries/ConstantsGen.sol | 2 +- .../crates/types/src/constants.nr | 2 +- noir/noir-repo/aztec_macros/src/lib.rs | 13 +-- .../compute_note_hash_and_nullifier.rs | 94 ++++++++++++++++--- .../aztec_macros/src/transforms/functions.rs | 19 ++-- .../aztec_macros/src/transforms/storage.rs | 60 ++++-------- .../aztec_macros/src/utils/hir_utils.rs | 84 ++++++++++++++++- yarn-project/circuits.js/src/constants.gen.ts | 2 +- .../pxe/src/note_processor/note_processor.ts | 2 +- 9 files changed, 202 insertions(+), 76 deletions(-) diff --git a/l1-contracts/src/core/libraries/ConstantsGen.sol b/l1-contracts/src/core/libraries/ConstantsGen.sol index 27a50262e36..18770c1be97 100644 --- a/l1-contracts/src/core/libraries/ConstantsGen.sol +++ b/l1-contracts/src/core/libraries/ConstantsGen.sol @@ -89,7 +89,7 @@ library Constants { uint256 internal constant DEPLOYER_CONTRACT_INSTANCE_DEPLOYED_MAGIC_VALUE = 0x85864497636cf755ae7bde03f267ce01a520981c21c3682aaf82a631; uint256 internal constant DEPLOYER_CONTRACT_ADDRESS = - 0x1f47133752dfcd9604f2d89c631797a84ed207c1c51d08533226dafcc8bd8548; + 0x0cde95a10e1160d0ff69ac8212cb5902fa5add38d8596595631fcf3a667798e0; uint256 internal constant DEFAULT_GAS_LIMIT = 1_000_000_000; uint256 internal constant DEFAULT_TEARDOWN_GAS_LIMIT = 100_000_000; uint256 internal constant DEFAULT_MAX_FEE_PER_GAS = 10; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr index 7004102819e..7faf3c22c0e 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr @@ -126,7 +126,7 @@ global REGISTERER_UNCONSTRAINED_FUNCTION_BROADCASTED_MAGIC_VALUE = 0xe7af8166354 // CONTRACT INSTANCE CONSTANTS // sha224sum 'struct ContractInstanceDeployed' global DEPLOYER_CONTRACT_INSTANCE_DEPLOYED_MAGIC_VALUE = 0x85864497636cf755ae7bde03f267ce01a520981c21c3682aaf82a631; -global DEPLOYER_CONTRACT_ADDRESS = 0x1f47133752dfcd9604f2d89c631797a84ed207c1c51d08533226dafcc8bd8548; +global DEPLOYER_CONTRACT_ADDRESS = 0x0cde95a10e1160d0ff69ac8212cb5902fa5add38d8596595631fcf3a667798e0; // GAS DEFAULTS global DEFAULT_GAS_LIMIT: u32 = 1_000_000_000; diff --git a/noir/noir-repo/aztec_macros/src/lib.rs b/noir/noir-repo/aztec_macros/src/lib.rs index dff3193a327..17ae999fb8f 100644 --- a/noir/noir-repo/aztec_macros/src/lib.rs +++ b/noir/noir-repo/aztec_macros/src/lib.rs @@ -93,17 +93,18 @@ fn transform_module( // Check for a user defined storage struct let maybe_storage_struct_name = check_for_storage_definition(module)?; + let storage_defined = maybe_storage_struct_name.is_some(); - if let Some(storage_struct_name) = maybe_storage_struct_name { - if !check_for_storage_implementation(module, &storage_struct_name) { - generate_storage_implementation(module, &storage_struct_name)?; + if let Some(ref storage_struct_name) = maybe_storage_struct_name { + if !check_for_storage_implementation(module, storage_struct_name) { + generate_storage_implementation(module, storage_struct_name)?; } // Make sure we're only generating the storage layout for the root crate // In case we got a contract importing other contracts for their interface, we // don't want to generate the storage layout for them if crate_id == context.root_crate_id() { - generate_storage_layout(module, storage_struct_name)?; + generate_storage_layout(module, storage_struct_name.clone())?; } } @@ -164,14 +165,14 @@ fn transform_module( transform_function( fn_type, func, - storage_defined, + maybe_storage_struct_name.clone(), is_initializer, insert_init_check, is_internal, )?; has_transformed_module = true; } else if storage_defined && func.def.is_unconstrained { - transform_unconstrained(func); + transform_unconstrained(func, maybe_storage_struct_name.clone().unwrap()); has_transformed_module = true; } } diff --git a/noir/noir-repo/aztec_macros/src/transforms/compute_note_hash_and_nullifier.rs b/noir/noir-repo/aztec_macros/src/transforms/compute_note_hash_and_nullifier.rs index 4ff97a5dcae..c8e7e807d87 100644 --- a/noir/noir-repo/aztec_macros/src/transforms/compute_note_hash_and_nullifier.rs +++ b/noir/noir-repo/aztec_macros/src/transforms/compute_note_hash_and_nullifier.rs @@ -7,7 +7,10 @@ use noirc_frontend::{ use crate::utils::{ errors::AztecMacroError, - hir_utils::{collect_crate_functions, fetch_notes, get_contract_module_data, inject_fn}, + hir_utils::{ + collect_crate_functions, collect_traits, fetch_notes, get_contract_module_data, + get_global_numberic_const, get_serialized_length, inject_fn, + }, }; // Check if "compute_note_hash_and_nullifier(AztecAddress,Field,Field,Field,[Field; N]) -> [Field; 4]" is defined @@ -59,13 +62,68 @@ pub fn inject_compute_note_hash_and_nullifier( return Ok(()); } + let traits: Vec<_> = collect_traits(context); + + // Get MAX_NOTE_FIELDS_LENGTH global to check if the notes in our contract are too long. + let max_note_length_const = get_global_numberic_const(context, "MAX_NOTE_FIELDS_LENGTH") + .map_err(|err| { + ( + AztecMacroError::CouldNotImplementComputeNoteHashAndNullifier { + secondary_message: Some(err.primary_message), + }, + file_id, + ) + })?; + // In order to implement compute_note_hash_and_nullifier, we need to know all of the different note types the - // contract might use. These are the types that are marked as #[aztec(note)]. + // contract might use and their serialized lengths. These are the types that are marked as #[aztec(note)]. + let mut notes_and_lengths = vec![]; + + for (path, typ) in fetch_notes(context) { + let serialized_len: u128 = get_serialized_length( + &traits, + "NoteInterface", + &Type::Struct(typ.clone(), vec![]), + &context.def_interner, + ) + .map_err(|_err| { + ( + AztecMacroError::CouldNotImplementComputeNoteHashAndNullifier { + secondary_message: Some(format!( + "Failed to get serialized length for note type {}", + path + )), + }, + file_id, + ) + })? + .into(); + + if serialized_len > max_note_length_const { + return Err(( + AztecMacroError::CouldNotImplementComputeNoteHashAndNullifier { + secondary_message: Some(format!( + "Note type {} as {} fields, which is more than the maximum allowed length of {}.", + path, + serialized_len, + max_note_length_const + )), + }, + file_id, + )); + } + + notes_and_lengths.push((path.to_string(), serialized_len)); + } + + let max_note_length: u128 = + *notes_and_lengths.iter().map(|(_, serialized_len)| serialized_len).max().unwrap_or(&0); + let note_types = - fetch_notes(context).iter().map(|(path, _)| path.to_string()).collect::>(); + notes_and_lengths.iter().map(|(note_type, _)| note_type.clone()).collect::>(); // We can now generate a version of compute_note_hash_and_nullifier tailored for the contract in this crate. - let func = generate_compute_note_hash_and_nullifier(¬e_types); + let func = generate_compute_note_hash_and_nullifier(¬e_types, max_note_length); // And inject the newly created function into the contract. @@ -85,8 +143,12 @@ pub fn inject_compute_note_hash_and_nullifier( Ok(()) } -fn generate_compute_note_hash_and_nullifier(note_types: &[String]) -> NoirFunction { - let function_source = generate_compute_note_hash_and_nullifier_source(note_types); +fn generate_compute_note_hash_and_nullifier( + note_types: &[String], + max_note_length: u128, +) -> NoirFunction { + let function_source = + generate_compute_note_hash_and_nullifier_source(note_types, max_note_length); let (function_ast, errors) = parse_program(&function_source); if !errors.is_empty() { @@ -98,25 +160,30 @@ fn generate_compute_note_hash_and_nullifier(note_types: &[String]) -> NoirFuncti function_ast.functions.remove(0) } -fn generate_compute_note_hash_and_nullifier_source(note_types: &[String]) -> String { +fn generate_compute_note_hash_and_nullifier_source( + note_types: &[String], + max_note_length: u128, +) -> String { // TODO(#4649): The serialized_note parameter is a fixed-size array, but we don't know what length it should have. // For now we hardcode it to 20, which is the same as MAX_NOTE_FIELDS_LENGTH. if note_types.is_empty() { // Even if the contract does not include any notes, other parts of the stack expect for this function to exist, // so we include a dummy version. - " + format!( + " unconstrained fn compute_note_hash_and_nullifier( contract_address: dep::aztec::protocol_types::address::AztecAddress, nonce: Field, storage_slot: Field, note_type_id: Field, - serialized_note: [Field; 20] - ) -> pub [Field; 4] { + serialized_note: [Field; {}] + ) -> pub [Field; 4] {{ assert(false, \"This contract does not use private notes\"); [0, 0, 0, 0] - }" - .to_string() + }}", + max_note_length + ) } else { // For contracts that include notes we do a simple if-else chain comparing note_type_id with the different // get_note_type_id of each of the note types. @@ -141,12 +208,13 @@ fn generate_compute_note_hash_and_nullifier_source(note_types: &[String]) -> Str nonce: Field, storage_slot: Field, note_type_id: Field, - serialized_note: [Field; 20] + serialized_note: [Field; {}] ) -> pub [Field; 4] {{ let note_header = dep::aztec::prelude::NoteHeader::new(contract_address, nonce, storage_slot); {} }}", + max_note_length, full_if_statement ) } diff --git a/noir/noir-repo/aztec_macros/src/transforms/functions.rs b/noir/noir-repo/aztec_macros/src/transforms/functions.rs index 534d24289b7..8e90d40aaec 100644 --- a/noir/noir-repo/aztec_macros/src/transforms/functions.rs +++ b/noir/noir-repo/aztec_macros/src/transforms/functions.rs @@ -26,7 +26,7 @@ use crate::{ pub fn transform_function( ty: &str, func: &mut NoirFunction, - storage_defined: bool, + storage_struct_name: Option, is_initializer: bool, insert_init_check: bool, is_internal: bool, @@ -54,8 +54,8 @@ pub fn transform_function( } // Add access to the storage struct - if storage_defined { - let storage_def = abstract_storage(&ty.to_lowercase(), false); + if let Some(storage_struct_name) = storage_struct_name { + let storage_def = abstract_storage(storage_struct_name, &ty.to_lowercase(), false); func.def.body.statements.insert(0, storage_def); } @@ -206,8 +206,11 @@ pub fn export_fn_abi( /// ``` /// /// This will allow developers to access their contract' storage struct in unconstrained functions -pub fn transform_unconstrained(func: &mut NoirFunction) { - func.def.body.statements.insert(0, abstract_storage("Unconstrained", true)); +pub fn transform_unconstrained(func: &mut NoirFunction, storage_struct_name: String) { + func.def + .body + .statements + .insert(0, abstract_storage(storage_struct_name, "Unconstrained", true)); } /// Helper function that returns what the private context would look like in the ast @@ -572,7 +575,7 @@ fn abstract_return_values(func: &NoirFunction) -> Result>, /// unconstrained fn lol() { /// let storage = Storage::init(Context::none()); /// } -fn abstract_storage(typ: &str, unconstrained: bool) -> Statement { +fn abstract_storage(storage_struct_name: String, typ: &str, unconstrained: bool) -> Statement { let init_context_call = if unconstrained { call( variable_path(chained_dep!("aztec", "context", "Context", "none")), // Path @@ -588,8 +591,8 @@ fn abstract_storage(typ: &str, unconstrained: bool) -> Statement { assignment( "storage", // Assigned to call( - variable_path(chained_path!("Storage", "init")), // Path - vec![init_context_call], // args + variable_path(chained_path!(storage_struct_name.as_str(), "init")), // Path + vec![init_context_call], // args ), ) } diff --git a/noir/noir-repo/aztec_macros/src/transforms/storage.rs b/noir/noir-repo/aztec_macros/src/transforms/storage.rs index 9135be32443..66057108517 100644 --- a/noir/noir-repo/aztec_macros/src/transforms/storage.rs +++ b/noir/noir-repo/aztec_macros/src/transforms/storage.rs @@ -1,12 +1,10 @@ -use std::borrow::Borrow; - use noirc_errors::Span; use noirc_frontend::{ graph::CrateId, macros_api::{ FieldElement, FileId, HirContext, HirExpression, HirLiteral, HirStatement, NodeInterner, }, - node_interner::{TraitId, TraitImplKind}, + node_interner::TraitId, parse_program, parser::SortedModule, token::SecondaryAttribute, @@ -23,7 +21,9 @@ use crate::{ make_type, pattern, return_type, variable, variable_path, }, errors::AztecMacroError, - hir_utils::{collect_crate_structs, collect_traits, get_contract_module_data}, + hir_utils::{ + collect_crate_structs, collect_traits, get_contract_module_data, get_serialized_length, + }, }, }; @@ -196,7 +196,7 @@ pub fn generate_storage_implementation( } /// Obtains the serialized length of a type that implements the Serialize trait. -fn get_serialized_length( +pub fn get_storage_serialized_length( traits: &[TraitId], typ: &Type, interner: &NodeInterner, @@ -214,48 +214,22 @@ fn get_serialized_length( secondary_message: Some("State storage variable must be generic".to_string()), })?; - let is_note = traits.iter().any(|&trait_id| { - let r#trait = interner.get_trait(trait_id); - r#trait.name.0.contents == "NoteInterface" - && !interner.lookup_all_trait_implementations(stored_in_state, trait_id).is_empty() - }); + let is_note = match stored_in_state { + Type::Struct(typ, _) => interner + .struct_attributes(&typ.borrow().id) + .iter() + .any(|attr| is_custom_attribute(attr, "aztec(note)")), + _ => false, + }; // Maps and (private) Notes always occupy a single slot. Someone could store a Note in PublicMutable for whatever reason though. if struct_name == "Map" || (is_note && struct_name != "PublicMutable") { return Ok(1); } - let serialized_trait_impl_kind = traits - .iter() - .find_map(|&trait_id| { - let r#trait = interner.get_trait(trait_id); - if r#trait.borrow().name.0.contents == "Serialize" - && r#trait.borrow().generics.len() == 1 - { - interner - .lookup_all_trait_implementations(stored_in_state, trait_id) - .into_iter() - .next() - } else { - None - } - }) - .ok_or(AztecMacroError::CouldNotAssignStorageSlots { - secondary_message: Some("Stored data must implement Serialize trait".to_string()), - })?; - - let serialized_trait_impl_id = match serialized_trait_impl_kind { - TraitImplKind::Normal(trait_impl_id) => Ok(trait_impl_id), - _ => Err(AztecMacroError::CouldNotAssignStorageSlots { secondary_message: None }), - }?; - - let serialized_trait_impl_shared = interner.get_trait_implementation(*serialized_trait_impl_id); - let serialized_trait_impl = serialized_trait_impl_shared.borrow(); - - match serialized_trait_impl.trait_generics.first().unwrap() { - Type::Constant(value) => Ok(*value), - _ => Err(AztecMacroError::CouldNotAssignStorageSlots { secondary_message: None }), - } + get_serialized_length(traits, "Serialize", stored_in_state, interner).map_err(|err| { + AztecMacroError::CouldNotAssignStorageSlots { secondary_message: Some(err.primary_message) } + }) } /// Assigns storage slots to the storage struct fields based on the serialized length of the types. This automatic assignment @@ -436,7 +410,7 @@ pub fn assign_storage_slots( }; let type_serialized_len = - get_serialized_length(&traits, field_type, &context.def_interner) + get_storage_serialized_length(&traits, field_type, &context.def_interner) .map_err(|err| (err, file_id))?; context.def_interner.update_expression(new_call_expression.arguments[1], |expr| { @@ -504,7 +478,7 @@ pub fn generate_storage_layout( let (struct_ast, errors) = parse_program(&storage_fields_source); if !errors.is_empty() { dbg!(errors); - return Err(AztecMacroError::CouldNotImplementNoteInterface { + return Err(AztecMacroError::CouldNotExportStorageLayout { secondary_message: Some("Failed to parse Noir macro code (struct StorageLayout). This is either a bug in the compiler or the Noir macro code".to_string()), span: None }); diff --git a/noir/noir-repo/aztec_macros/src/utils/hir_utils.rs b/noir/noir-repo/aztec_macros/src/utils/hir_utils.rs index ae895d2075c..3b2f14fd87e 100644 --- a/noir/noir-repo/aztec_macros/src/utils/hir_utils.rs +++ b/noir/noir-repo/aztec_macros/src/utils/hir_utils.rs @@ -7,8 +7,11 @@ use noirc_frontend::{ resolution::{path_resolver::StandardPathResolver, resolver::Resolver}, type_check::type_check_func, }, - macros_api::{FileId, HirContext, MacroError, ModuleDefId, StructId}, - node_interner::{FuncId, TraitId}, + macros_api::{ + FileId, HirContext, HirExpression, HirLiteral, MacroError, ModuleDefId, NodeInterner, + StructId, + }, + node_interner::{FuncId, TraitId, TraitImplKind}, ItemVisibility, LetStatement, NoirFunction, Shared, Signedness, StructType, Type, }; @@ -309,3 +312,80 @@ fn find_non_contract_dependencies_bfs( }) }) } + +pub fn get_serialized_length( + traits: &[TraitId], + trait_name: &str, + typ: &Type, + interner: &NodeInterner, +) -> Result { + let serialized_trait_impl_kind = traits + .iter() + .find_map(|&trait_id| { + let r#trait = interner.get_trait(trait_id); + if r#trait.name.0.contents == trait_name && r#trait.generics.len() == 1 { + interner.lookup_all_trait_implementations(typ, trait_id).into_iter().next() + } else { + None + } + }) + .ok_or(MacroError { + primary_message: format!("Type {} must implement {} trait", typ, trait_name), + secondary_message: None, + span: None, + })?; + + let serialized_trait_impl_id = match serialized_trait_impl_kind { + TraitImplKind::Normal(trait_impl_id) => Ok(trait_impl_id), + _ => Err(MacroError { + primary_message: format!("{} trait impl for {} must not be assumed", trait_name, typ), + secondary_message: None, + span: None, + }), + }?; + + let serialized_trait_impl_shared = interner.get_trait_implementation(*serialized_trait_impl_id); + let serialized_trait_impl = serialized_trait_impl_shared.borrow(); + + match serialized_trait_impl.trait_generics.first().unwrap() { + Type::Constant(value) => Ok(*value), + _ => Err(MacroError { + primary_message: format!("{} length for {} must be a constant", trait_name, typ), + secondary_message: None, + span: None, + }), + } +} + +pub fn get_global_numberic_const( + context: &HirContext, + const_name: &str, +) -> Result { + context + .def_interner + .get_all_globals() + .iter() + .find_map(|global_info| { + if global_info.ident.0.contents == const_name { + let stmt = context.def_interner.get_global_let_statement(global_info.id); + if let Some(let_stmt) = stmt { + let expression = context.def_interner.expression(&let_stmt.expression); + match expression { + HirExpression::Literal(HirLiteral::Integer(value, _)) => { + Some(value.to_u128()) + } + _ => None, + } + } else { + None + } + } else { + None + } + }) + .ok_or(MacroError { + primary_message: format!("Could not find {} global constant", const_name), + secondary_message: None, + span: None, + }) +} diff --git a/yarn-project/circuits.js/src/constants.gen.ts b/yarn-project/circuits.js/src/constants.gen.ts index c3b1341b83b..4a8b78294c1 100644 --- a/yarn-project/circuits.js/src/constants.gen.ts +++ b/yarn-project/circuits.js/src/constants.gen.ts @@ -74,7 +74,7 @@ export const REGISTERER_UNCONSTRAINED_FUNCTION_BROADCASTED_MAGIC_VALUE = 0xe7af816635466f128568edb04c9fa024f6c87fb9010fdbffa68b3d99n; export const DEPLOYER_CONTRACT_INSTANCE_DEPLOYED_MAGIC_VALUE = 0x85864497636cf755ae7bde03f267ce01a520981c21c3682aaf82a631n; -export const DEPLOYER_CONTRACT_ADDRESS = 0x1f47133752dfcd9604f2d89c631797a84ed207c1c51d08533226dafcc8bd8548n; +export const DEPLOYER_CONTRACT_ADDRESS = 0x0cde95a10e1160d0ff69ac8212cb5902fa5add38d8596595631fcf3a667798e0n; export const DEFAULT_GAS_LIMIT = 1_000_000_000; export const DEFAULT_TEARDOWN_GAS_LIMIT = 100_000_000; export const DEFAULT_MAX_FEE_PER_GAS = 10; diff --git a/yarn-project/pxe/src/note_processor/note_processor.ts b/yarn-project/pxe/src/note_processor/note_processor.ts index 4a1c66481eb..0950a427598 100644 --- a/yarn-project/pxe/src/note_processor/note_processor.ts +++ b/yarn-project/pxe/src/note_processor/note_processor.ts @@ -166,7 +166,7 @@ export class NoteProcessor { deferredNoteDaos.push(deferredNoteDao); } else { this.stats.failed++; - this.log.warn(`Could not process note because of "${e}". Discarding note...`); + this.log.error(`Could not process note because of "${e}". Discarding note...`); } } } From ce8416174f360a4a00cc70c20c8f2d99354aec2e Mon Sep 17 00:00:00 2001 From: Lasse Herskind <16536249+LHerskind@users.noreply.github.com> Date: Mon, 22 Apr 2024 11:47:10 +0100 Subject: [PATCH 047/102] refactor: purge unconstrained functions where possible (#5819) Fixes #5451 --- noir-projects/noir-contracts/Nargo.toml | 1 - .../contracts/avm_test_contract/src/main.nr | 12 --- .../contracts/gas_token_contract/src/main.nr | 4 +- .../contracts/lending_contract/src/asset.nr | 16 ++-- .../contracts/lending_contract/src/main.nr | 17 ++--- .../lending_contract/src/position.nr | 30 ++++++++ .../price_feed_contract/src/asset.nr | 2 +- .../contracts/price_feed_contract/src/main.nr | 4 - .../contracts/reader_contract/Nargo.toml | 9 --- .../contracts/reader_contract/src/main.nr | 69 ----------------- .../stateful_test_contract/src/main.nr | 3 +- .../token_blacklist_contract/src/main.nr | 24 +++--- .../token_bridge_contract/src/main.nr | 25 +------ .../contracts/token_contract/src/main.nr | 64 +++++++--------- .../end-to-end/src/e2e_avm_simulator.test.ts | 4 +- .../src/e2e_blacklist_token_contract.test.ts | 1 - .../reading_constants.test.ts | 75 ++++--------------- .../src/shared/cross_chain_test_harness.ts | 2 +- 18 files changed, 112 insertions(+), 250 deletions(-) create mode 100644 noir-projects/noir-contracts/contracts/lending_contract/src/position.nr delete mode 100644 noir-projects/noir-contracts/contracts/reader_contract/Nargo.toml delete mode 100644 noir-projects/noir-contracts/contracts/reader_contract/src/main.nr diff --git a/noir-projects/noir-contracts/Nargo.toml b/noir-projects/noir-contracts/Nargo.toml index b3d1c57c752..e27753c3f88 100644 --- a/noir-projects/noir-contracts/Nargo.toml +++ b/noir-projects/noir-contracts/Nargo.toml @@ -40,6 +40,5 @@ members = [ "contracts/token_blacklist_contract", "contracts/token_bridge_contract", "contracts/uniswap_contract", - "contracts/reader_contract", "contracts/multi_call_entrypoint_contract", ] diff --git a/noir-projects/noir-contracts/contracts/avm_test_contract/src/main.nr b/noir-projects/noir-contracts/contracts/avm_test_contract/src/main.nr index 7eb12dd0e7c..98b92a0065e 100644 --- a/noir-projects/noir-contracts/contracts/avm_test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/avm_test_contract/src/main.nr @@ -41,18 +41,6 @@ contract AvmTest { /************************************************************************ * Storage ************************************************************************/ - unconstrained fn view_storage_single() -> pub Field { - storage.single.read() - } - - unconstrained fn view_storage_list() -> pub [Field; 2] { - storage.list.read().serialize() - } - - unconstrained fn view_storage_map(address: AztecAddress) -> pub u32 { - storage.map.at(address).read() - } - #[aztec(public-vm)] fn set_storage_single(a: Field) { storage.single.write(a); diff --git a/noir-projects/noir-contracts/contracts/gas_token_contract/src/main.nr b/noir-projects/noir-contracts/contracts/gas_token_contract/src/main.nr index ec1adf32116..e1b8c0fd39d 100644 --- a/noir-projects/noir-contracts/contracts/gas_token_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/gas_token_contract/src/main.nr @@ -55,8 +55,8 @@ contract GasToken { rebate.to_field() } - // utility function for testing - unconstrained fn balance_of_public(owner: AztecAddress) -> pub Field { + #[aztec(public)] + fn balance_of_public(owner: AztecAddress) -> pub Field { storage.balances.at(owner).read().to_field() } } diff --git a/noir-projects/noir-contracts/contracts/lending_contract/src/asset.nr b/noir-projects/noir-contracts/contracts/lending_contract/src/asset.nr index 7415ec54d92..3e53fbb28e1 100644 --- a/noir-projects/noir-contracts/contracts/lending_contract/src/asset.nr +++ b/noir-projects/noir-contracts/contracts/lending_contract/src/asset.nr @@ -13,14 +13,16 @@ struct Asset { oracle: AztecAddress, } -global SERIALIZED_LEN: Field = 4; +global SERIALIZED_LEN: Field = 6; impl Serialize for Asset { fn serialize(Asset: Asset) -> [Field; SERIALIZED_LEN] { [ - Asset.interest_accumulator.to_integer(), + Asset.interest_accumulator.lo as Field, + Asset.interest_accumulator.hi as Field, Asset.last_updated_ts as Field, - Asset.loan_to_value.to_integer(), + Asset.loan_to_value.lo as Field, + Asset.loan_to_value.hi as Field, Asset.oracle.to_field() ] } @@ -30,10 +32,10 @@ impl Deserialize for Asset { // Right now we are wasting so many writes. If changing last_updated_ts // we will end up rewriting all of them, wasting writes. fn deserialize(fields: [Field; SERIALIZED_LEN]) -> Asset { - let interest_accumulator = U128::from_integer(fields[0]); - let last_updated_ts = fields[1] as u64; - let loan_to_value = U128::from_integer(fields[2]); - let oracle = AztecAddress::from_field(fields[3]); + let interest_accumulator = U128 {lo: fields[0], hi: fields[1]}; + let last_updated_ts = fields[2] as u64; + let loan_to_value = U128 {lo: fields[3], hi: fields[4]}; + let oracle = AztecAddress::from_field(fields[5]); Asset { interest_accumulator, diff --git a/noir-projects/noir-contracts/contracts/lending_contract/src/main.nr b/noir-projects/noir-contracts/contracts/lending_contract/src/main.nr index c2c05f58a09..328ec71ce97 100644 --- a/noir-projects/noir-contracts/contracts/lending_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/lending_contract/src/main.nr @@ -1,4 +1,5 @@ mod asset; +mod position; mod interest_math; mod helpers; @@ -14,6 +15,7 @@ contract Lending { use dep::aztec::context::{PublicContext, Context, gas::GasOpts}; use crate::asset::Asset; + use crate::position::Position; use crate::interest_math::compute_multiplier; use crate::helpers::{covered_by_collateral, DebtReturn, debt_updates, debt_value, compute_identifier}; use dep::token::Token; @@ -29,12 +31,6 @@ contract Lending { static_debt: Map>, // abusing keys very heavily } - struct Position { - collateral: Field, - static_debt: Field, - debt: Field, - } - // Constructs the contract. #[aztec(private)] #[aztec(initializer)] @@ -265,11 +261,13 @@ contract Lending { storage.static_debt.at(owner).write(debt_returns.static_debt.to_integer()); } - unconstrained fn get_asset(asset_id: Field) -> pub Asset { + #[aztec(public)] + fn get_asset(asset_id: Field) -> pub Asset { storage.assets.at(asset_id).read() } - unconstrained fn get_position(owner: AztecAddress) -> pub Position { + #[aztec(public)] + fn get_position(owner: AztecAddress) -> pub Position { let collateral = storage.collateral.at(owner).read(); let static_debt = storage.static_debt.at(owner).read(); let asset: Asset = storage.assets.at(0).read(); @@ -280,7 +278,8 @@ contract Lending { Position { collateral, static_debt, debt } } - unconstrained fn get_assets() -> pub [AztecAddress; 2] { + #[aztec(public)] + fn get_assets() -> pub [AztecAddress; 2] { [storage.collateral_asset.read(), storage.stable_coin.read()] } } diff --git a/noir-projects/noir-contracts/contracts/lending_contract/src/position.nr b/noir-projects/noir-contracts/contracts/lending_contract/src/position.nr new file mode 100644 index 00000000000..080f977e9c0 --- /dev/null +++ b/noir-projects/noir-contracts/contracts/lending_contract/src/position.nr @@ -0,0 +1,30 @@ +use dep::aztec::prelude::AztecAddress; +use dep::aztec::protocol_types::traits::{Deserialize, Serialize}; + +struct Position { + collateral: Field, + static_debt: Field, + debt: Field, +} + +global POSITION_SERIALIZED_LEN: Field = 3; + +impl Serialize for Position { + fn serialize(position: Position) -> [Field; POSITION_SERIALIZED_LEN] { + [ + position.collateral.to_field(), + position.static_debt.to_field(), + position.debt.to_field(), + ] + } +} + +impl Deserialize for Position { + fn deserialize(fields: [Field; POSITION_SERIALIZED_LEN]) -> Position { + Position { + collateral: fields[0], + static_debt: fields[1], + debt: fields[2], + } + } +} diff --git a/noir-projects/noir-contracts/contracts/price_feed_contract/src/asset.nr b/noir-projects/noir-contracts/contracts/price_feed_contract/src/asset.nr index 0f34a0429b1..3e148e12aa3 100644 --- a/noir-projects/noir-contracts/contracts/price_feed_contract/src/asset.nr +++ b/noir-projects/noir-contracts/contracts/price_feed_contract/src/asset.nr @@ -8,7 +8,7 @@ global ASSET_SERIALIZED_LEN: Field = 1; impl Serialize for Asset { fn serialize(asset: Asset) -> [Field; ASSET_SERIALIZED_LEN] { - [asset.price.to_integer()] + [asset.price.to_field()] } } diff --git a/noir-projects/noir-contracts/contracts/price_feed_contract/src/main.nr b/noir-projects/noir-contracts/contracts/price_feed_contract/src/main.nr index c4afaacf753..c563792bf0c 100644 --- a/noir-projects/noir-contracts/contracts/price_feed_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/price_feed_contract/src/main.nr @@ -21,8 +21,4 @@ contract PriceFeed { fn get_price(asset_id: Field) -> Asset { storage.assets.at(asset_id).read() } - - unconstrained fn fetch_price(asset_id: Field) -> pub Asset { - storage.assets.at(asset_id).read() - } } diff --git a/noir-projects/noir-contracts/contracts/reader_contract/Nargo.toml b/noir-projects/noir-contracts/contracts/reader_contract/Nargo.toml deleted file mode 100644 index 8ae3ed01400..00000000000 --- a/noir-projects/noir-contracts/contracts/reader_contract/Nargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[package] -name = "reader_contract" -authors = [""] -compiler_version = ">=0.25.0" -type = "contract" - -[dependencies] -aztec = { path = "../../../aztec-nr/aztec" } -compressed_string = { path = "../../../aztec-nr/compressed-string" } diff --git a/noir-projects/noir-contracts/contracts/reader_contract/src/main.nr b/noir-projects/noir-contracts/contracts/reader_contract/src/main.nr deleted file mode 100644 index 0cfbb45b596..00000000000 --- a/noir-projects/noir-contracts/contracts/reader_contract/src/main.nr +++ /dev/null @@ -1,69 +0,0 @@ -contract Reader { - use dep::aztec::prelude::{AztecAddress, FunctionSelector, Deserialize}; - - use dep::compressed_string::FieldCompressedString; - - #[aztec(private)] - fn constructor() {} - - #[aztec(public)] - fn check_name_public(who: AztecAddress, what: str<31>) { - let selector = FunctionSelector::from_signature("public_get_name()"); - let name: FieldCompressedString = context.call_public_function_no_args(who, selector).deserialize_into(); - let _what = FieldCompressedString::from_string(what); - assert(name.is_eq(_what)); - } - - #[aztec(private)] - fn check_name_private(who: AztecAddress, what: str<31>) { - let selector = FunctionSelector::from_signature("private_get_name()"); - let name: FieldCompressedString = context.call_private_function_no_args(who, selector).unpack_into(); - let _what = FieldCompressedString::from_string(what); - assert(name.is_eq(_what)); - } - - unconstrained fn get_name(who: AztecAddress) -> pub str<6> { - // We cannot yet call an unconstrained function from another - "Reader" - } - - #[aztec(public)] - fn check_symbol_public(who: AztecAddress, what: str<31>) { - let selector = FunctionSelector::from_signature("public_get_symbol()"); - let symbol: FieldCompressedString = context.call_public_function_no_args(who, selector).deserialize_into(); - let _what = FieldCompressedString::from_string(what); - assert(symbol.is_eq(_what)); - } - - #[aztec(private)] - fn check_symbol_private(who: AztecAddress, what: str<31>) { - let selector = FunctionSelector::from_signature("private_get_symbol()"); - let symbol: FieldCompressedString = context.call_private_function_no_args(who, selector).unpack_into(); - let _what = FieldCompressedString::from_string(what); - assert(symbol.is_eq(_what)); - } - - unconstrained fn get_symbol(who: AztecAddress) -> pub str<3> { - // We cannot yet call an unconstrained function from another - "RDR" - } - - #[aztec(public)] - fn check_decimals_public(who: AztecAddress, what: u8) { - let selector = FunctionSelector::from_signature("public_get_decimals()"); - let ret: u8 = context.call_public_function_no_args(who, selector).deserialize_into(); - assert(ret == what); - } - - #[aztec(private)] - fn check_decimals_private(who: AztecAddress, what: u8) { - let selector = FunctionSelector::from_signature("private_get_decimals()"); - let result: u8 = context.call_private_function_no_args(who, selector).unpack_into(); - assert(result == what); - } - - unconstrained fn get_decimals(who: AztecAddress) -> pub u8 { - // We cannot yet call an unconstrained function from another - 18 - } -} diff --git a/noir-projects/noir-contracts/contracts/stateful_test_contract/src/main.nr b/noir-projects/noir-contracts/contracts/stateful_test_contract/src/main.nr index db8efde4a25..a96fbfca3a1 100644 --- a/noir-projects/noir-contracts/contracts/stateful_test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/stateful_test_contract/src/main.nr @@ -94,7 +94,8 @@ contract StatefulTest { balance_utils::get_balance(owner_balance) } - unconstrained fn get_public_value(owner: AztecAddress) -> pub Field { + #[aztec(public)] + fn get_public_value(owner: AztecAddress) -> pub Field { storage.public_values.at(owner).read() } } diff --git a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr index ddb115c721e..21f62b8853f 100644 --- a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr @@ -38,6 +38,16 @@ contract TokenBlacklist { slow_update: SharedImmutable, } + #[aztec(public)] + fn total_supply() -> pub Field { + storage.total_supply.read().to_field() + } + + #[aztec(public)] + fn balance_of_public(owner: AztecAddress) -> pub Field { + storage.public_balances.at(owner).read().to_field() + } + // docs:start:constructor #[aztec(public)] #[aztec(initializer)] @@ -227,8 +237,7 @@ contract TokenBlacklist { storage.balances.sub(from, U128::from_integer(amount)); - let selector = FunctionSelector::from_signature("_increase_public_balance((Field),Field)"); - context.call_public_function(context.this_address(), selector, [to.to_field(), amount]); + TokenBlacklist::at(context.this_address())._increase_public_balance(to, amount).enqueue(&mut context); } // docs:start:transfer_private @@ -266,8 +275,7 @@ contract TokenBlacklist { storage.balances.sub(from, U128::from_integer(amount)); - let selector = FunctionSelector::from_signature("_reduce_total_supply(Field)"); - context.call_public_function(context.this_address(), selector, [amount]); + TokenBlacklist::at(context.this_address())._reduce_total_supply(amount).enqueue(&mut context); } /// Internal /// @@ -289,15 +297,7 @@ contract TokenBlacklist { /// Unconstrained /// - unconstrained fn total_supply() -> pub Field { - storage.total_supply.read().to_field() - } - unconstrained fn balance_of_private(owner: AztecAddress) -> pub Field { storage.balances.balance_of(owner).to_field() } - - unconstrained fn balance_of_public(owner: AztecAddress) -> pub Field { - storage.public_balances.at(owner).read().to_field() - } } diff --git a/noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr b/noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr index 28226b5b10b..b32d8c41d78 100644 --- a/noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr @@ -26,8 +26,7 @@ contract TokenBridge { #[aztec(private)] #[aztec(initializer)] fn constructor(token: AztecAddress) { - let selector = FunctionSelector::from_signature("_initialize((Field))"); - context.call_public_function(context.this_address(), selector, [token.to_field()]); + TokenBridge::at(context.this_address())._initialize(token).enqueue(&mut context); } // docs:end:token_bridge_storage_and_constructor @@ -99,11 +98,7 @@ contract TokenBridge { // `mint_private` on token is public. So we call an internal public function // which then calls the public method on the token contract. // Since the secret_hash is passed, no secret is leaked. - context.call_public_function( - context.this_address(), - FunctionSelector::from_signature("_call_mint_on_token(Field,Field)"), - [amount, secret_hash_for_redeeming_minted_notes] - ); + TokenBridge::at(context.this_address())._call_mint_on_token(amount, secret_hash_for_redeeming_minted_notes).enqueue(&mut context); } // docs:end:claim_private @@ -124,11 +119,7 @@ contract TokenBridge { // docs:start:call_assert_token_is_same // Assert that user provided token address is same as seen in storage. - context.call_public_function( - context.this_address(), - FunctionSelector::from_signature("_assert_token_is_same((Field))"), - [token.to_field()] - ); + TokenBridge::at(context.this_address())._assert_token_is_same(token).enqueue(&mut context); // docs:end:call_assert_token_is_same // Burn tokens @@ -136,19 +127,11 @@ contract TokenBridge { } /// docs:end:exit_to_l1_private - // View function that is callable by other contracts. - // Unconstrained can't be called by others since it isn't safe. + // docs:start:read_token #[aztec(public)] fn get_token() -> AztecAddress { storage.token.read() } - - // /// Unconstrained /// - - // docs:start:read_token - unconstrained fn token() -> pub AztecAddress { - storage.token.read() - } // docs:end:read_token #[aztec(public)] diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/main.nr b/noir-projects/noir-contracts/contracts/token_contract/src/main.nr index cc892421ece..a8a5cb8edbd 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/main.nr @@ -84,10 +84,6 @@ contract Token { storage.name.read_private() } - unconstrained fn un_get_name() -> pub [u8; 31] { - storage.name.read_public().to_bytes() - } - #[aztec(public)] fn public_get_symbol() -> pub FieldCompressedString { storage.symbol.read_public() @@ -98,10 +94,6 @@ contract Token { storage.symbol.read_private() } - unconstrained fn un_get_symbol() -> pub [u8; 31] { - storage.symbol.read_public().to_bytes() - } - #[aztec(public)] fn public_get_decimals() -> pub u8 { // docs:start:read_decimals_public @@ -116,9 +108,33 @@ contract Token { // docs:end:read_decimals_private } - unconstrained fn un_get_decimals() -> pub u8 { - storage.decimals.read_public() + // docs:start:admin + #[aztec(public)] + fn admin() -> pub Field { + storage.admin.read().to_field() + } + // docs:end:admin + + // docs:start:is_minter + #[aztec(public)] + fn is_minter(minter: AztecAddress) -> pub bool { + storage.minters.at(minter).read() } + // docs:end:is_minter + + // docs:start:total_supply + #[aztec(public)] + fn total_supply() -> pub Field { + storage.total_supply.read().to_field() + } + // docs:end:total_supply + + // docs:start:balance_of_public + #[aztec(public)] + fn balance_of_public(owner: AztecAddress) -> pub Field { + storage.public_balances.at(owner).read().to_field() + } + // docs:end:balance_of_public // docs:start:set_minter #[aztec(public)] @@ -190,7 +206,7 @@ contract Token { let from_balance = storage.public_balances.at(from).read().sub(amount); let pending_shields = storage.pending_shields; - let mut note = TransparentNote::new(amount.to_integer(), secret_hash); + let mut note = TransparentNote::new(amount.to_field(), secret_hash); storage.public_balances.at(from).write(from_balance); pending_shields.insert_from_public(&mut note); @@ -330,34 +346,10 @@ contract Token { /// Unconstrained /// - // docs:start:admin - unconstrained fn admin() -> pub Field { - storage.admin.read().to_field() - } - // docs:end:admin - - // docs:start:is_minter - unconstrained fn is_minter(minter: AztecAddress) -> pub bool { - storage.minters.at(minter).read() - } - // docs:end:is_minter - - // docs:start:total_supply - unconstrained fn total_supply() -> pub Field { - storage.total_supply.read().to_integer() - } - // docs:end:total_supply - // docs:start:balance_of_private unconstrained fn balance_of_private(owner: AztecAddress) -> pub Field { - storage.balances.balance_of(owner).to_integer() + storage.balances.balance_of(owner).to_field() } // docs:end:balance_of_private - - // docs:start:balance_of_public - unconstrained fn balance_of_public(owner: AztecAddress) -> pub Field { - storage.public_balances.at(owner).read().to_integer() - } - // docs:end:balance_of_public } // docs:end:token_all diff --git a/yarn-project/end-to-end/src/e2e_avm_simulator.test.ts b/yarn-project/end-to-end/src/e2e_avm_simulator.test.ts index ac36f13ceaf..c94e1ca00ff 100644 --- a/yarn-project/end-to-end/src/e2e_avm_simulator.test.ts +++ b/yarn-project/end-to-end/src/e2e_avm_simulator.test.ts @@ -35,14 +35,14 @@ describe('e2e_avm_simulator', () => { describe('Storage', () => { it('Modifies storage (Field)', async () => { await avmContract.methods.set_storage_single(20n).send().wait(); - expect(await avmContract.methods.view_storage_single().simulate()).toEqual(20n); + expect(await avmContract.methods.read_storage_single().simulate()).toEqual(20n); }); it('Modifies storage (Map)', async () => { const address = AztecAddress.fromBigInt(9090n); await avmContract.methods.set_storage_map(address, 100).send().wait(); await avmContract.methods.add_storage_map(address, 100).send().wait(); - expect(await avmContract.methods.view_storage_map(address).simulate()).toEqual(200n); + expect(await avmContract.methods.read_storage_map(address).simulate()).toEqual(200n); }); }); diff --git a/yarn-project/end-to-end/src/e2e_blacklist_token_contract.test.ts b/yarn-project/end-to-end/src/e2e_blacklist_token_contract.test.ts index 59224084453..1500098a5bc 100644 --- a/yarn-project/end-to-end/src/e2e_blacklist_token_contract.test.ts +++ b/yarn-project/end-to-end/src/e2e_blacklist_token_contract.test.ts @@ -994,7 +994,6 @@ describe('e2e_blacklist_token_contract', () => { .methods.unshield(wallets[0].getAddress(), wallets[1].getAddress(), amount, nonce) .send(); await expect(txReplay.wait()).rejects.toThrow('Transaction '); - // @todo @LHerskind This error is weird? }); describe('failure cases', () => { diff --git a/yarn-project/end-to-end/src/e2e_token_contract/reading_constants.test.ts b/yarn-project/end-to-end/src/e2e_token_contract/reading_constants.test.ts index b7a5089217f..af856853415 100644 --- a/yarn-project/end-to-end/src/e2e_token_contract/reading_constants.test.ts +++ b/yarn-project/end-to-end/src/e2e_token_contract/reading_constants.test.ts @@ -1,12 +1,14 @@ -import { ReaderContract } from '@aztec/noir-contracts.js'; +import { Fr } from '@aztec/circuits.js'; import { TokenContractTest } from './token_contract_test.js'; -const toString = (val: bigint[]) => { +const toString = ({ value }: { value: bigint }) => { + const vals: number[] = Array.from(new Fr(value).toBuffer()); + let str = ''; - for (let i = 0; i < val.length; i++) { - if (val[i] != 0n) { - str += String.fromCharCode(Number(val[i])); + for (let i = 0; i < vals.length; i++) { + if (vals[i] != 0) { + str += String.fromCharCode(Number(vals[i])); } } return str; @@ -16,26 +18,9 @@ describe('e2e_token_contract reading constants', () => { const t = new TokenContractTest('reading_constants'); const { TOKEN_DECIMALS, TOKEN_NAME, TOKEN_SYMBOL } = TokenContractTest; // Do not destructure anything mutable. - const { logger } = t; - let reader: ReaderContract; beforeAll(async () => { await t.applyBaseSnapshots(); - - await t.snapshot( - 'reading_constants', - async () => { - logger.verbose('Deploying ReaderContract...'); - const reader = await ReaderContract.deploy(t.wallets[0]).send().deployed(); - logger.verbose(`Deployed ReaderContract to ${reader.address}.`); - return { readerAddress: reader.address }; - }, - async ({ readerAddress }) => { - reader = await ReaderContract.at(readerAddress, t.wallets[0]); - logger.verbose(`Reader contract restored to ${readerAddress}.`); - }, - ); - await t.setup(); }); @@ -50,66 +35,32 @@ describe('e2e_token_contract reading constants', () => { }); it('check name private', async () => { - const name = toString(await t.asset.methods.un_get_name().simulate()); + const name = toString(await t.asset.methods.private_get_name().simulate()); expect(name).toBe(TOKEN_NAME); - - await reader.methods.check_name_private(t.asset.address, TOKEN_NAME).send().wait(); - await expect(reader.methods.check_name_private(t.asset.address, 'WRONG_NAME').simulate()).rejects.toThrow( - 'name.is_eq(_what)', - ); }); it('check name public', async () => { - const name = toString(await t.asset.methods.un_get_name().simulate()); + const name = toString(await t.asset.methods.public_get_name().simulate()); expect(name).toBe(TOKEN_NAME); - - await reader.methods.check_name_public(t.asset.address, TOKEN_NAME).send().wait(); - await expect(reader.methods.check_name_public(t.asset.address, 'WRONG_NAME').simulate()).rejects.toThrow( - 'name.is_eq(_what)', - ); }); it('check symbol private', async () => { - const sym = toString(await t.asset.methods.un_get_symbol().simulate()); + const sym = toString(await t.asset.methods.private_get_symbol().simulate()); expect(sym).toBe(TOKEN_SYMBOL); - - await reader.methods.check_symbol_private(t.asset.address, TOKEN_SYMBOL).send().wait(); - - await expect(reader.methods.check_symbol_private(t.asset.address, 'WRONG_SYMBOL').simulate()).rejects.toThrow( - "Cannot satisfy constraint 'symbol.is_eq(_what)'", - ); }); it('check symbol public', async () => { - const sym = toString(await t.asset.methods.un_get_symbol().simulate()); + const sym = toString(await t.asset.methods.public_get_symbol().simulate()); expect(sym).toBe(TOKEN_SYMBOL); - - await reader.methods.check_symbol_public(t.asset.address, TOKEN_SYMBOL).send().wait(); - - await expect(reader.methods.check_symbol_public(t.asset.address, 'WRONG_SYMBOL').simulate()).rejects.toThrow( - "Failed to solve brillig function 'symbol.is_eq(_what)'", - ); }); it('check decimals private', async () => { - const dec = await t.asset.methods.un_get_decimals().simulate(); + const dec = await t.asset.methods.private_get_decimals().simulate(); expect(dec).toBe(TOKEN_DECIMALS); - - await reader.methods.check_decimals_private(t.asset.address, TOKEN_DECIMALS).send().wait(); - - await expect(reader.methods.check_decimals_private(t.asset.address, 99).simulate()).rejects.toThrow( - "Cannot satisfy constraint 'result == what'", - ); }); it('check decimals public', async () => { - const dec = await t.asset.methods.un_get_decimals().simulate(); + const dec = await t.asset.methods.public_get_decimals().simulate(); expect(dec).toBe(TOKEN_DECIMALS); - - await reader.methods.check_decimals_public(t.asset.address, TOKEN_DECIMALS).send().wait(); - - await expect(reader.methods.check_decimals_public(t.asset.address, 99).simulate()).rejects.toThrow( - "Failed to solve brillig function 'ret == what'", - ); }); }); diff --git a/yarn-project/end-to-end/src/shared/cross_chain_test_harness.ts b/yarn-project/end-to-end/src/shared/cross_chain_test_harness.ts index 63975935c91..ef1d31bd8d3 100644 --- a/yarn-project/end-to-end/src/shared/cross_chain_test_harness.ts +++ b/yarn-project/end-to-end/src/shared/cross_chain_test_harness.ts @@ -109,7 +109,7 @@ export async function deployAndInitializeTokenAndBridgeContracts( throw new Error(`Token admin is not ${owner}`); } - if (!(await bridge.methods.token().simulate()).equals(token.address)) { + if (!(await bridge.methods.get_token().simulate()).equals(token.address)) { throw new Error(`Bridge token is not ${token.address}`); } From cec819178635b41c3b310431afa435bea207d925 Mon Sep 17 00:00:00 2001 From: Santiago Palladino Date: Mon, 22 Apr 2024 08:33:36 -0300 Subject: [PATCH 048/102] chore: Fix and reenable e2e account init fees test (#5878) Similar fix to #5877. --- ....test.ts => e2e_account_init_fees.test.ts} | 15 +++---- .../src/shared/gas_portal_test_harness.ts | 44 +++++-------------- 2 files changed, 17 insertions(+), 42 deletions(-) rename yarn-project/end-to-end/src/{flakey_e2e_account_init_fees.test.ts => e2e_account_init_fees.test.ts} (96%) diff --git a/yarn-project/end-to-end/src/flakey_e2e_account_init_fees.test.ts b/yarn-project/end-to-end/src/e2e_account_init_fees.test.ts similarity index 96% rename from yarn-project/end-to-end/src/flakey_e2e_account_init_fees.test.ts rename to yarn-project/end-to-end/src/e2e_account_init_fees.test.ts index 9b902e001a4..d8acec1c0d5 100644 --- a/yarn-project/end-to-end/src/flakey_e2e_account_init_fees.test.ts +++ b/yarn-project/end-to-end/src/e2e_account_init_fees.test.ts @@ -38,7 +38,7 @@ import { GasPortalTestingHarnessFactory, type IGasBridgingTestHarness } from './ const TOKEN_NAME = 'BananaCoin'; const TOKEN_SYMBOL = 'BC'; const TOKEN_DECIMALS = 18n; -const BRIDGED_FPC_GAS = 444n; +const BRIDGED_FPC_GAS = BigInt(10e12); jest.setTimeout(1000_000); @@ -125,13 +125,8 @@ describe('e2e_fees_account_init', () => { afterAll(() => ctx.teardown()); beforeEach(() => { - gasSettings = GasSettings.from({ - gasLimits: { daGas: 2, l1Gas: 2, l2Gas: 2 }, - teardownGasLimits: { daGas: 1, l1Gas: 1, l2Gas: 1 }, - maxFeesPerGas: { feePerDaGas: Fr.ONE, feePerL1Gas: Fr.ONE, feePerL2Gas: Fr.ONE }, - inclusionFee: new Fr(5), - }); - maxFee = 3n * 3n + 5n; + gasSettings = GasSettings.default(); + maxFee = gasSettings.getFeeLimit().toBigInt(); actualFee = 1n; bobsSecretKey = Fr.random(); bobsPrivateSigningKey = Fq.random(); @@ -168,7 +163,7 @@ describe('e2e_fees_account_init', () => { describe('privately through an FPC', () => { let mintedPrivateBananas: bigint; beforeEach(async () => { - mintedPrivateBananas = 42n; + mintedPrivateBananas = BigInt(1e12); // TODO the following sequence of events ends in a timeout // 1. pxe.registerRecipient (aka just add the public key so pxe can encrypt notes) @@ -243,7 +238,7 @@ describe('e2e_fees_account_init', () => { let mintedPublicBananas: bigint; beforeEach(async () => { - mintedPublicBananas = 37n; + mintedPublicBananas = BigInt(1e12); await bananaCoin.methods.mint_public(bobsAddress, mintedPublicBananas).send().wait(); }); diff --git a/yarn-project/end-to-end/src/shared/gas_portal_test_harness.ts b/yarn-project/end-to-end/src/shared/gas_portal_test_harness.ts index 7a0c7625302..fbc95e97416 100644 --- a/yarn-project/end-to-end/src/shared/gas_portal_test_harness.ts +++ b/yarn-project/end-to-end/src/shared/gas_portal_test_harness.ts @@ -138,15 +138,15 @@ class GasBridgingTestHarness implements IGasBridgingTestHarness { /** Portal address. */ public tokenPortalAddress: EthAddress, /** Token portal instance. */ - public tokenPortal: any, + public tokenPortal: GetContractReturnType>, /** Underlying token for portal tests. */ - public underlyingERC20: any, + public underlyingERC20: GetContractReturnType>, /** Message Bridge Outbox. */ public outbox: GetContractReturnType>, /** Viem Public client instance. */ public publicClient: PublicClient, /** Viem Wallet Client instance. */ - public walletClient: any, + public walletClient: WalletClient, ) {} generateClaimSecret(): [Fr, Fr] { @@ -159,7 +159,9 @@ class GasBridgingTestHarness implements IGasBridgingTestHarness { async mintTokensOnL1(amount: bigint) { this.logger.info('Minting tokens on L1'); - await this.underlyingERC20.write.mint([this.ethAccount.toString(), amount], {} as any); + await this.publicClient.waitForTransactionReceipt({ + hash: await this.underlyingERC20.write.mint([this.ethAccount.toString(), amount]), + }); expect(await this.underlyingERC20.read.balanceOf([this.ethAccount.toString()])).toBe(amount); } @@ -168,7 +170,9 @@ class GasBridgingTestHarness implements IGasBridgingTestHarness { } async sendTokensToPortalPublic(bridgeAmount: bigint, l2Address: AztecAddress, secretHash: Fr) { - await this.underlyingERC20.write.approve([this.tokenPortalAddress.toString(), bridgeAmount], {} as any); + await this.publicClient.waitForTransactionReceipt({ + hash: await this.underlyingERC20.write.approve([this.tokenPortalAddress.toString(), bridgeAmount]), + }); // Deposit tokens to the TokenPortal this.logger.info('Sending messages to L1 portal to be consumed publicly'); @@ -176,33 +180,9 @@ class GasBridgingTestHarness implements IGasBridgingTestHarness { const { result: messageHash } = await this.tokenPortal.simulate.depositToAztecPublic(args, { account: this.ethAccount.toString(), } as any); - await this.tokenPortal.write.depositToAztecPublic(args, {} as any); - - return Fr.fromString(messageHash); - } - - async sendTokensToPortalPrivate( - secretHashForRedeemingMintedNotes: Fr, - bridgeAmount: bigint, - secretHashForL2MessageConsumption: Fr, - ) { - await this.underlyingERC20.write.approve([this.tokenPortalAddress.toString(), bridgeAmount], {} as any); - - // Deposit tokens to the TokenPortal - const deadline = 2 ** 32 - 1; // max uint32 - - this.logger.info('Sending messages to L1 portal to be consumed privately'); - const args = [ - secretHashForRedeemingMintedNotes.toString(), - bridgeAmount, - this.ethAccount.toString(), - deadline, - secretHashForL2MessageConsumption.toString(), - ] as const; - const { result: messageHash } = await this.tokenPortal.simulate.depositToAztecPrivate(args, { - account: this.ethAccount.toString(), - } as any); - await this.tokenPortal.write.depositToAztecPrivate(args, {} as any); + await this.publicClient.waitForTransactionReceipt({ + hash: await this.tokenPortal.write.depositToAztecPublic(args), + }); return Fr.fromString(messageHash); } From 1c24c8e53f190c7b1ac3b4d8896abb4ab6b5712b Mon Sep 17 00:00:00 2001 From: Santiago Palladino Date: Mon, 22 Apr 2024 09:03:18 -0300 Subject: [PATCH 049/102] chore: Patch jest to not use JSON serialization in message passing (#5883) We often get "Do not know how to serialize a BigInt" as an output from our failing tests (see [here](https://github.com/AztecProtocol/aztec-packages/actions/runs/8756999966/job/24035011971#step:5:465) for an example). This is caused by jest using node `child_process` to spawn multiple runners, and using json serialization for message passing, so when a child wants to report a failure in a test, if that failure involved a bigint, it triggers this error. One solution is to migrate to jest's experimental worker threads, but I'm not sure how memory is handled if we move from subprocesses to threads. This solution is dirtier but allows us to keep using child processes: it patches jest so it uses node's [advanced serialization](https://nodejs.org/api/child_process.html#advanced-serialization) which "is generally more powerful and supports more built-in JavaScript object types, such as BigInt, Map and Set, ArrayBuffer and TypedArray, Buffer, Error, RegExp etc". I tested it on the same PR as I linked above and indeed we can now see [failed bigint expectations](https://github.com/AztecProtocol/aztec-packages/actions/runs/8757912954/job/24037750048#step:5:739) as error messages. --- .../jest-runner-npm-29.7.0-3bc9f82b58.patch | 13 ++++++++ yarn-project/package.json | 3 +- yarn-project/yarn.lock | 31 ++++++++++++++++++- 3 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 yarn-project/.yarn/patches/jest-runner-npm-29.7.0-3bc9f82b58.patch diff --git a/yarn-project/.yarn/patches/jest-runner-npm-29.7.0-3bc9f82b58.patch b/yarn-project/.yarn/patches/jest-runner-npm-29.7.0-3bc9f82b58.patch new file mode 100644 index 00000000000..36a2a45009b --- /dev/null +++ b/yarn-project/.yarn/patches/jest-runner-npm-29.7.0-3bc9f82b58.patch @@ -0,0 +1,13 @@ +diff --git a/build/index.js b/build/index.js +index 65c0ed180a1f44a5095f80d572aacb68be1db3da..3bb4938110a50a2eca1b2f01466b7be16c9c8145 100644 +--- a/build/index.js ++++ b/build/index.js +@@ -124,7 +124,7 @@ class TestRunner extends _types.EmittingTestRunner { + enableWorkerThreads: this._globalConfig.workerThreads, + exposedMethods: ['worker'], + forkOptions: { +- serialization: 'json', ++ serialization: 'advanced', + stdio: 'pipe' + }, + // The workerIdleMemoryLimit should've been converted to a number during diff --git a/yarn-project/package.json b/yarn-project/package.json index 70f765df28f..78df3f10602 100644 --- a/yarn-project/package.json +++ b/yarn-project/package.json @@ -70,6 +70,7 @@ "@aztec/bb.js": "portal:../barretenberg/ts", "@noir-lang/acvm_js": "portal:../noir/packages/acvm_js", "@noir-lang/types": "portal:../noir/packages/types", - "@noir-lang/noirc_abi": "portal:../noir/packages/noirc_abi" + "@noir-lang/noirc_abi": "portal:../noir/packages/noirc_abi", + "jest-runner@^29.7.0": "patch:jest-runner@npm%3A29.7.0#./.yarn/patches/jest-runner-npm-29.7.0-3bc9f82b58.patch" } } diff --git a/yarn-project/yarn.lock b/yarn-project/yarn.lock index 105ac89cb19..65368a59d0d 100644 --- a/yarn-project/yarn.lock +++ b/yarn-project/yarn.lock @@ -8951,7 +8951,7 @@ __metadata: languageName: node linkType: hard -"jest-runner@npm:^29.7.0": +"jest-runner@npm:29.7.0": version: 29.7.0 resolution: "jest-runner@npm:29.7.0" dependencies: @@ -8980,6 +8980,35 @@ __metadata: languageName: node linkType: hard +"jest-runner@patch:jest-runner@npm%3A29.7.0#./.yarn/patches/jest-runner-npm-29.7.0-3bc9f82b58.patch::locator=%40aztec%2Faztec3-packages%40workspace%3A.": + version: 29.7.0 + resolution: "jest-runner@patch:jest-runner@npm%3A29.7.0#./.yarn/patches/jest-runner-npm-29.7.0-3bc9f82b58.patch::version=29.7.0&hash=a79dea&locator=%40aztec%2Faztec3-packages%40workspace%3A." + dependencies: + "@jest/console": ^29.7.0 + "@jest/environment": ^29.7.0 + "@jest/test-result": ^29.7.0 + "@jest/transform": ^29.7.0 + "@jest/types": ^29.6.3 + "@types/node": "*" + chalk: ^4.0.0 + emittery: ^0.13.1 + graceful-fs: ^4.2.9 + jest-docblock: ^29.7.0 + jest-environment-node: ^29.7.0 + jest-haste-map: ^29.7.0 + jest-leak-detector: ^29.7.0 + jest-message-util: ^29.7.0 + jest-resolve: ^29.7.0 + jest-runtime: ^29.7.0 + jest-util: ^29.7.0 + jest-watcher: ^29.7.0 + jest-worker: ^29.7.0 + p-limit: ^3.1.0 + source-map-support: 0.5.13 + checksum: 8345cba67695e45a6cc1fddca470ba61d981c6fa3565b53728ba36678acf6ce7657868e7483ab34b75e433efd42f57fd2894031069c06ac48b7b22ac9950ff1d + languageName: node + linkType: hard + "jest-runtime@npm:^29.7.0": version: 29.7.0 resolution: "jest-runtime@npm:29.7.0" From b5a8e02edf44bacc3415e478b75b182c5b352ca2 Mon Sep 17 00:00:00 2001 From: ludamad Date: Mon, 22 Apr 2024 07:44:17 -0500 Subject: [PATCH 050/102] chore(ci): better docker prune (#5889) Docker prune without -a could still allow continuous accumulation of space. Now only if you happen to keep hitting the same spot this will happen, but as long as the same spot is up I don't want to prune (yet) as to not prune while other jobs are saving images Bundled: - minor workflow streamlining/flexibility for impersonating - ci.py support for impersonating This was relevant to debugging our friend AztecBot's disk --- .github/ci-setup-action/action.yml | 3 -- .github/workflows/ci-arm.yml | 1 - .github/workflows/ci.yml | 52 +++++++----------- .github/workflows/setup-runner.yml | 4 +- .github/workflows/start-spot.yml | 24 ++++++--- ci.py | 86 ++++++++++++++++++------------ 6 files changed, 90 insertions(+), 80 deletions(-) diff --git a/.github/ci-setup-action/action.yml b/.github/ci-setup-action/action.yml index e96dfd29a7c..4b1d7da6dbb 100644 --- a/.github/ci-setup-action/action.yml +++ b/.github/ci-setup-action/action.yml @@ -9,9 +9,6 @@ inputs: concurrency_key: required: false description: 'Concurrency key for locking jobs' - concurrency_token: - required: false - description: 'TODO unused' runs: # define an action, runs in OS of caller using: composite diff --git a/.github/workflows/ci-arm.yml b/.github/workflows/ci-arm.yml index 84e4cc7dda1..aa1d3f26ea7 100644 --- a/.github/workflows/ci-arm.yml +++ b/.github/workflows/ci-arm.yml @@ -36,7 +36,6 @@ jobs: - uses: ./.github/ci-setup-action with: dockerhub_password: "${{ secrets.DOCKERHUB_PASSWORD }}" - concurrency_token: "${{ secrets.AZTEC_GITHUB_TOKEN }}" # must be globally unique for build x runner concurrency_key: build-master-arm # prepare images locally, tagged by commit hash diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0b5f2c532c0..bad2c7a5a53 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,13 +5,12 @@ on: pull_request: {} workflow_dispatch: inputs: + username: + description: 'Defaults to GitHub Actor' + required: false runner_action: description: "The action to take with the self-hosted runner (start, stop, restart)." required: false - just_start_spot: - description: "Should we just run spots?" - type: boolean - required: false concurrency: # force parallelism in master group: ci-${{ github.ref_name == 'master' && github.run_id || github.ref_name }} @@ -20,10 +19,10 @@ jobs: setup: uses: ./.github/workflows/setup-runner.yml with: - runner_label: ${{ github.actor }}-x86 + runner_label: ${{ inputs.username || github.actor }}-x86 ebs_cache_size_gb: 256 runner_concurrency: 20 - subaction: ${{ github.event.inputs.runner_action || 'start' }} + subaction: ${{ inputs.runner_action || 'start' }} ec2_instance_type: m6a.32xlarge ec2_ami_id: ami-04d8422a9ba4de80f ec2_instance_ttl: 40 # refreshed by jobs @@ -31,8 +30,7 @@ jobs: build: needs: setup - runs-on: ${{ github.actor }}-x86 - if: ${{ github.event.inputs.just_start_spot != 'true' }} + runs-on: ${{ inputs.username || github.actor }}-x86 outputs: e2e_list: ${{ steps.e2e_list.outputs.list }} steps: @@ -40,7 +38,7 @@ jobs: - uses: ./.github/ci-setup-action with: dockerhub_password: "${{ secrets.DOCKERHUB_PASSWORD }}" - concurrency_key: build-${{ github.actor }}-x86 + concurrency_key: build-${{ inputs.username || github.actor }}-x86 # prepare images locally, tagged by commit hash - name: "Build E2E Image" timeout-minutes: 40 @@ -54,7 +52,7 @@ jobs: # all the end-to-end integration tests for aztec e2e: needs: build - runs-on: ${{ github.actor }}-x86 + runs-on: ${{ inputs.username || github.actor }}-x86 strategy: fail-fast: false matrix: @@ -65,7 +63,7 @@ jobs: with: dockerhub_password: "${{ secrets.DOCKERHUB_PASSWORD }}" # must be globally unique for build x runner - concurrency_key: e2e-${{ github.actor }}-x86-${{ matrix.test }} + concurrency_key: e2e-${{ inputs.username || github.actor }}-x86-${{ matrix.test }} - name: Test working-directory: ./yarn-project/end-to-end/ timeout-minutes: 25 @@ -78,7 +76,7 @@ jobs: # only ran on x86 for resource reasons (memory intensive) bb-native-tests: needs: setup - runs-on: ${{ github.actor }}-x86 + runs-on: ${{ inputs.username || github.actor }}-x86 strategy: fail-fast: false steps: @@ -88,7 +86,7 @@ jobs: with: dockerhub_password: "${{ secrets.DOCKERHUB_PASSWORD }}" # must be globally unique for build x runner - concurrency_key: bb-native-tests-${{ github.actor }}-x86 + concurrency_key: bb-native-tests-${{ inputs.username || github.actor }}-x86 - name: "Native Prover Tests" working-directory: ./barretenberg/cpp/ timeout-minutes: 25 @@ -98,15 +96,14 @@ jobs: # push benchmarking binaries to dockerhub registry bb-bench-binaries: needs: setup - runs-on: ${{ github.actor }}-x86 + runs-on: ${{ inputs.username || github.actor }}-x86 steps: - {uses: actions/checkout@v4, with: { ref: "${{ github.event.pull_request.head.sha }}"}} - uses: ./.github/ci-setup-action with: dockerhub_password: "${{ secrets.DOCKERHUB_PASSWORD }}" - concurrency_key: bb-bench-binaries-${{ github.actor }}-x86 + concurrency_key: bb-bench-binaries-${{ inputs.username || github.actor }}-x86 - name: Build and Push Binaries - if: ${{ github.event.inputs.just_start_spot != 'true' }} timeout-minutes: 15 working-directory: ./barretenberg/cpp/ run: earthly-ci --push +bench-binaries @@ -115,24 +112,24 @@ jobs: uses: ./.github/workflows/setup-runner.yml needs: bb-bench-binaries with: - runner_label: ${{ github.actor }}-bench-x86 + runner_label: ${{ inputs.username || github.actor }}-bench-x86 ebs_cache_size_gb: 64 runner_concurrency: 1 - subaction: ${{ github.event.inputs.runner_action || 'start' }} + subaction: ${{ inputs.runner_action || 'start' }} ec2_instance_type: m6a.4xlarge ec2_ami_id: ami-04d8422a9ba4de80f ec2_instance_ttl: 15 # refreshed by jobs secrets: inherit bb-bench: - runs-on: ${{ github.actor }}-bench-x86 + runs-on: ${{ inputs.username || github.actor }}-bench-x86 needs: setup-bench steps: - {uses: actions/checkout@v4, with: { ref: "${{ github.event.pull_request.head.sha }}"}} - uses: ./.github/ci-setup-action with: dockerhub_password: "${{ secrets.DOCKERHUB_PASSWORD }}" - concurrency_key: bb-bench-${{ github.actor }}-bench-x86 + concurrency_key: bb-bench-${{ inputs.username || github.actor }}-bench-x86 # Use bench_mode=cache to read the pushed build above - name: Client IVC Bench working-directory: ./barretenberg/cpp/ @@ -145,23 +142,14 @@ jobs: run: earthly-ci --no-output +bench-ultra-honk --bench_mode=cache merge-check: - runs-on: ubuntu-latest + runs-on: ${{ inputs.username || github.actor }}-x86 needs: [e2e, bb-native-tests, bb-bench] - if: always() # Ensures this job runs regardless of the success or failure of dependencies. steps: - - run: | - echo "E2E Test Status: ${{ needs.e2e.result }}" - echo "Native Tests Status: ${{ needs.bb-native-tests.result }}" - echo "Bench Tests Status: ${{ needs.bb-bench.result }}" - if [[ "${{ needs.e2e.result }}" != 'success' || "${{ needs.bb-native-tests.result }}" != 'success' || "${{ needs.bb-bench.result }}" != 'success' ]]; then - echo "Pull request merging not allowed due to failures." - exit 1 - fi - echo "Pull request merging now allowed." + - run: echo Pull request merging now allowed. notify: - runs-on: ubuntu-latest needs: [e2e, bb-native-tests, bb-bench] + runs-on: ubuntu-latest if: ${{ github.ref == 'refs/heads/master' && failure() }} steps: - name: Send notification to aztec3-ci channel if workflow failed on master diff --git a/.github/workflows/setup-runner.yml b/.github/workflows/setup-runner.yml index 0fe34e0cb73..fdde1373f94 100644 --- a/.github/workflows/setup-runner.yml +++ b/.github/workflows/setup-runner.yml @@ -58,7 +58,7 @@ jobs: group: start-builder-${{ inputs.runner_label }} steps: - name: Start EC2 runner - uses: AztecProtocol/ec2-action-builder@v0.15 + uses: AztecProtocol/ec2-action-builder@v0.14e with: github_token: ${{ secrets.GH_SELF_HOSTED_RUNNER_TOKEN }} aws_access_key_id: ${{ secrets.AWS_ACCESS_KEY_ID }} @@ -117,7 +117,7 @@ jobs: - name: Run Docker Prune # helps to not overuse space - run: docker system prune -f || true + run: docker system prune -f -a || true - name: Run Earthly Bootstrap run: earthly bootstrap diff --git a/.github/workflows/start-spot.yml b/.github/workflows/start-spot.yml index f3d84c1f557..539567f08cb 100644 --- a/.github/workflows/start-spot.yml +++ b/.github/workflows/start-spot.yml @@ -1,27 +1,35 @@ # Useful if the spot runners are in a bad state -name: Start Personal Spot +name: Start/Stop Personal Spot on: - workflow_dispatch: {} + workflow_dispatch: + inputs: + username: + description: 'Defaults to GitHub Actor' + required: false + action: + description: 'Can also be stop or restart, defaults to start' + required: false + default: 'start' jobs: - stop-build-x86: + start-build: uses: ./.github/workflows/setup-runner.yml with: - runner_label: ${{ github.actor }}-x86 + runner_label: ${{ inputs.username || github.actor }}-x86 ebs_cache_size_gb: 256 runner_concurrency: 20 - subaction: start + subaction: ${{ inputs.action }} ec2_instance_type: m6a.32xlarge ec2_ami_id: ami-04d8422a9ba4de80f ec2_instance_ttl: 40 # refreshed by jobs secrets: inherit - stop-bench: + start-bench: uses: ./.github/workflows/setup-runner.yml with: - runner_label: ${{ github.actor }}-bench-x86 + runner_label: ${{ inputs.username || github.actor }}-bench-x86 ebs_cache_size_gb: 64 runner_concurrency: 1 - subaction: start + subaction: ${{ inputs.action }} ec2_instance_type: m6a.4xlarge ec2_ami_id: ami-04d8422a9ba4de80f ec2_instance_ttl: 15 # refreshed by jobs diff --git a/ci.py b/ci.py index f5127ec0759..21caf8c9480 100755 --- a/ci.py +++ b/ci.py @@ -1,27 +1,32 @@ #!/usr/bin/env python3 # ubuntu: apt install python3-blessed from blessed import Terminal -import os, json, subprocess, sys +import os, json, subprocess, sys, time term = Terminal() if 'GITHUB_ACTOR' not in os.environ: print("Make sure you have GITHUB_ACTOR in your environment variables e.g. .zshrc") sys.exit(1) GITHUB_ACTOR = os.environ['GITHUB_ACTOR'] +BRANCH = subprocess.run("git rev-parse --abbrev-ref HEAD", shell=True, text=True, capture_output=True).stdout.strip() def main(): selection = -1 - with term.fullscreen(), term.cbreak(): - print(term.home + term.clear) - while selection not in ('1', '2', '3', '4', 'q'): - print(term.move_y(1) + "Please select an option:") - print("1. SSH into build machine") - print("2. SSH into bench machine") - print("3. Start/Stop spot machines") - print("4. Manage Running Jobs") - print("q. Quit") - with term.location(0, term.height - 1): - selection = term.inkey() + if len(sys.argv) >= 2: + selection = sys.argv[1] + else: + with term.fullscreen(), term.cbreak(): + print(term.home + term.clear) + while selection not in ('1', '2', '3', '4', '5', 'q'): + print(term.move_y(1) + "Please select an option:") + print("1. SSH into build machine") + print("2. SSH into bench machine") + print("3. Start/Stop spot machines") + print("4. Manage Running Jobs") + print("5. Run ci.yml manually") + print("q. Quit") + with term.location(0, term.height - 1): + selection = term.inkey() if selection == '1': ssh_into_machine('x86') @@ -31,42 +36,55 @@ def main(): manage_spot_instances() elif selection == '4': manage_ci_workflows() + elif selection == '5': + call_ci_workflow() def ssh_into_machine(suffix): - GITHUB_ACTOR = os.getenv('GITHUB_ACTOR', 'default_actor') ssh_key_path = os.path.expanduser('~/.ssh/build_instance_key') if not os.path.exists(ssh_key_path): print("SSH key does not exist.") return - # Command to get the instance information - cmd = f'aws ec2 describe-instances --filters "Name=instance-state-name,Values=running" "Name=tag:Name,Values=aztec-packages-{GITHUB_ACTOR}-{suffix}" --output json --region us-east-2' - result = subprocess.run(cmd, shell=True, capture_output=True, text=True) - if result.returncode != 0: - print("Failed to get AWS instances:", result.stderr) - return - # Parse the output to find the public IP address - try: - instances_data = json.loads(result.stdout) - instance = instances_data['Reservations'][0]['Instances'][0] - instance_ip = instance['PublicIpAddress'] - except (KeyError, IndexError, json.JSONDecodeError) as e: - print("Error parsing AWS CLI output:", e) - return + for i in range(10): + # Command to get the instance information + cmd = f'aws ec2 describe-instances --filters "Name=instance-state-name,Values=running" "Name=tag:Name,Values=aztec-packages-{GITHUB_ACTOR}-{suffix}" --output json --region us-east-2' + result = subprocess.run(cmd, shell=True, capture_output=True, text=True) + if result.returncode != 0: + print("Failed to get AWS instances:", result.stderr) + return + try: + instances_data = json.loads(result.stdout) + instance = instances_data['Reservations'][0]['Instances'][0] + instance_ip = instance['PublicIpAddress'] + break + except (KeyError, IndexError, json.JSONDecodeError) as e: + print("Error parsing AWS CLI output, trying again:", e) + if i == 0: + print("Couldn't find spot, starting spot, and looping until we can find it") + call_spot_workflow('start') + elif i == 9: + print("Couldn't find spot even after creating it!") + sys.exit(1) + time.sleep(10) # SSH command using the public IP ssh_cmd = f"ssh -o StrictHostKeychecking=no -i {ssh_key_path} ubuntu@{instance_ip}" - print(f"Connecting to {instance_ip}. Consider delaying the impeding shutdown.") + print(f"Connecting to {instance_ip}. Consider delaying the impending shutdown and running a process called Runner.Worker to fool the reaper (automation TODO).") ssh_process = subprocess.Popen(ssh_cmd, shell=True) ssh_process.wait() # Wait for the SSH session to complete +def call_spot_workflow(action): + subprocess.run(f'gh workflow run start-spot.yml --ref {BRANCH} --field username="{GITHUB_ACTOR}" --field action="{action}"', shell=True) + +def call_ci_workflow(): + print( + "NOTE: This is mostly useful if impersonating a GITHUB_ACTOR. Usually you rather do Manage Running Jobs and retry." + ) + subprocess.run(f'gh workflow run ci.yml --ref {BRANCH} --field username="{GITHUB_ACTOR}"', shell=True) + def manage_spot_instances(): - action = input("Enter 'start' to run or 'stop' to stop spot instances: ") - if action == 'start': - subprocess.run('gh workflow run start-spot.yml', shell=True) - elif action == 'stop': - subprocess.run('gh workflow run stop-spot.yml', shell=True) + call_spot_workflow(input("Enter one of 'start', 'stop', 'restart':")) def manage_ci_workflows(): # Retrieve the most recent workflow run @@ -86,7 +104,7 @@ def manage_ci_workflows(): subprocess.run(f"gh run cancel {run_id}", shell=True) if action.lower() == 'rerun': # needed so the spot runners still work - subprocess.run('gh workflow run start-spot.yml', shell=True) + call_spot_workflow('start') subprocess.run(f"gh run rerun {run_id} --failed", shell=True) elif action.lower() == 'rerun-all': subprocess.run(f"gh run rerun {run_id}", shell=True) From 2e557130ace2f6db555fa27eab80ccfc18f0d88e Mon Sep 17 00:00:00 2001 From: ludamad Date: Mon, 22 Apr 2024 08:10:04 -0500 Subject: [PATCH 051/102] chore(ci): don't use redirected earthly (#5909) The cure is worse than the disease right now. While there is a 1 in 200 chance of this internal buildkit error (which Earthly folks tell me they are actively looking into), right now it makes logs hard to read --- .github/workflows/ci.yml | 12 ++++++------ scripts/earthly-ci | 36 ------------------------------------ 2 files changed, 6 insertions(+), 42 deletions(-) delete mode 100755 scripts/earthly-ci diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bad2c7a5a53..6fee521f74c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -42,7 +42,7 @@ jobs: # prepare images locally, tagged by commit hash - name: "Build E2E Image" timeout-minutes: 40 - run: earthly-ci ./yarn-project+export-end-to-end + run: earthly ./yarn-project+export-end-to-end # We base our e2e list used in e2e-x86 off the targets in ./yarn-project/end-to-end # (Note ARM uses just 2 tests as a smoketest) - name: Create list of end-to-end jobs @@ -67,7 +67,7 @@ jobs: - name: Test working-directory: ./yarn-project/end-to-end/ timeout-minutes: 25 - run: earthly-ci -P --no-output +${{ matrix.test }} --e2e_mode=cache + run: earthly -P --no-output +${{ matrix.test }} --e2e_mode=cache # TODO # - name: Upload logs # run: BRANCH=${{ github.ref_name }} PULL_REQUEST=${{ github.event.number }} scripts/ci/upload_logs_to_s3 ./yarn-project/end-to-end/log @@ -91,7 +91,7 @@ jobs: working-directory: ./barretenberg/cpp/ timeout-minutes: 25 # limit our parallelism to half our cores - run: earthly-ci --no-output +test --hardware_concurrency=64 + run: earthly --no-output +test --hardware_concurrency=64 # push benchmarking binaries to dockerhub registry bb-bench-binaries: @@ -106,7 +106,7 @@ jobs: - name: Build and Push Binaries timeout-minutes: 15 working-directory: ./barretenberg/cpp/ - run: earthly-ci --push +bench-binaries + run: earthly --push +bench-binaries setup-bench: uses: ./.github/workflows/setup-runner.yml @@ -134,12 +134,12 @@ jobs: - name: Client IVC Bench working-directory: ./barretenberg/cpp/ timeout-minutes: 15 - run: earthly-ci --no-output +bench-client-ivc --bench_mode=cache + run: earthly --no-output +bench-client-ivc --bench_mode=cache - name: Ultrahonk Bench working-directory: ./barretenberg/cpp/ timeout-minutes: 15 - run: earthly-ci --no-output +bench-ultra-honk --bench_mode=cache + run: earthly --no-output +bench-ultra-honk --bench_mode=cache merge-check: runs-on: ${{ inputs.username || github.actor }}-x86 diff --git a/scripts/earthly-ci b/scripts/earthly-ci deleted file mode 100755 index 43eeb9b17aa..00000000000 --- a/scripts/earthly-ci +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env bash -# A wrapper for Earthly that is meant to caught signs of known intermittent failures and continue. -# The silver lining is if Earthly does crash, the cache can pick up the build. -set -eu -o pipefail - -# Flag to determine if -i is present -INTERACTIVE=false -# Check for -i flag in the arguments -for arg in "$@"; do - if [ "$arg" == "-i" ] || [ "$arg" == "--interactive" ]; then - INTERACTIVE=true - break - fi -done - -OUTPUT_FILE=$(mktemp) -# capture output to handle earthly edge cases -if $INTERACTIVE ; then - # don't play nice with tee if interactive - earthly $@ -elif ! earthly $@ 2>&1 | tee $OUTPUT_FILE >&2 ; then - # we try earthly once, capturing output - # if we get one of our (unfortunate) known failures, handle retries - # TODO potentially handle other intermittent errors here - if grep 'failed to get edge: inconsistent graph state' $OUTPUT_FILE >/dev/null ; then - # TODO when earthly is overloaded we sometimes get - # 'failed to solve: failed to get edge: inconsistent graph state' - echo "Got 'inconsistent graph state'. Restarting earthly. See https://github.com/earthly/earthly/issues/2454'" - earthly $@ - # TODO handle - # could not configure satellite: failed getting org: unable to authenticate: failed to execute login request: Post - else - # otherwise, propagate error - exit 1 - fi -fi From c36246bb692bf9a3d8e338bbc26a3ce801f0e389 Mon Sep 17 00:00:00 2001 From: Lasse Herskind <16536249+LHerskind@users.noreply.github.com> Date: Mon, 22 Apr 2024 15:09:13 +0100 Subject: [PATCH 052/102] fix(Revert): "refactor: purge unconstrained functions where possible" (#5911) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reverts AztecProtocol/aztec-packages#5819. The use of constrained functions made the writing of tests etc nicer, but the testing time absolutely exploded as an effect 💀 Co-authored-by: ludamad --- noir-projects/noir-contracts/Nargo.toml | 1 + .../contracts/avm_test_contract/src/main.nr | 12 +++ .../contracts/gas_token_contract/src/main.nr | 4 +- .../contracts/lending_contract/src/asset.nr | 16 ++-- .../contracts/lending_contract/src/main.nr | 17 +++-- .../lending_contract/src/position.nr | 30 -------- .../price_feed_contract/src/asset.nr | 2 +- .../contracts/price_feed_contract/src/main.nr | 4 + .../contracts/reader_contract/Nargo.toml | 9 +++ .../contracts/reader_contract/src/main.nr | 69 +++++++++++++++++ .../stateful_test_contract/src/main.nr | 3 +- .../token_blacklist_contract/src/main.nr | 24 +++--- .../token_bridge_contract/src/main.nr | 25 ++++++- .../contracts/token_contract/src/main.nr | 64 +++++++++------- .../end-to-end/src/e2e_avm_simulator.test.ts | 4 +- .../src/e2e_blacklist_token_contract.test.ts | 1 + .../reading_constants.test.ts | 75 +++++++++++++++---- .../src/shared/cross_chain_test_harness.ts | 2 +- 18 files changed, 250 insertions(+), 112 deletions(-) delete mode 100644 noir-projects/noir-contracts/contracts/lending_contract/src/position.nr create mode 100644 noir-projects/noir-contracts/contracts/reader_contract/Nargo.toml create mode 100644 noir-projects/noir-contracts/contracts/reader_contract/src/main.nr diff --git a/noir-projects/noir-contracts/Nargo.toml b/noir-projects/noir-contracts/Nargo.toml index e27753c3f88..b3d1c57c752 100644 --- a/noir-projects/noir-contracts/Nargo.toml +++ b/noir-projects/noir-contracts/Nargo.toml @@ -40,5 +40,6 @@ members = [ "contracts/token_blacklist_contract", "contracts/token_bridge_contract", "contracts/uniswap_contract", + "contracts/reader_contract", "contracts/multi_call_entrypoint_contract", ] diff --git a/noir-projects/noir-contracts/contracts/avm_test_contract/src/main.nr b/noir-projects/noir-contracts/contracts/avm_test_contract/src/main.nr index 98b92a0065e..7eb12dd0e7c 100644 --- a/noir-projects/noir-contracts/contracts/avm_test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/avm_test_contract/src/main.nr @@ -41,6 +41,18 @@ contract AvmTest { /************************************************************************ * Storage ************************************************************************/ + unconstrained fn view_storage_single() -> pub Field { + storage.single.read() + } + + unconstrained fn view_storage_list() -> pub [Field; 2] { + storage.list.read().serialize() + } + + unconstrained fn view_storage_map(address: AztecAddress) -> pub u32 { + storage.map.at(address).read() + } + #[aztec(public-vm)] fn set_storage_single(a: Field) { storage.single.write(a); diff --git a/noir-projects/noir-contracts/contracts/gas_token_contract/src/main.nr b/noir-projects/noir-contracts/contracts/gas_token_contract/src/main.nr index e1b8c0fd39d..ec1adf32116 100644 --- a/noir-projects/noir-contracts/contracts/gas_token_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/gas_token_contract/src/main.nr @@ -55,8 +55,8 @@ contract GasToken { rebate.to_field() } - #[aztec(public)] - fn balance_of_public(owner: AztecAddress) -> pub Field { + // utility function for testing + unconstrained fn balance_of_public(owner: AztecAddress) -> pub Field { storage.balances.at(owner).read().to_field() } } diff --git a/noir-projects/noir-contracts/contracts/lending_contract/src/asset.nr b/noir-projects/noir-contracts/contracts/lending_contract/src/asset.nr index 3e53fbb28e1..7415ec54d92 100644 --- a/noir-projects/noir-contracts/contracts/lending_contract/src/asset.nr +++ b/noir-projects/noir-contracts/contracts/lending_contract/src/asset.nr @@ -13,16 +13,14 @@ struct Asset { oracle: AztecAddress, } -global SERIALIZED_LEN: Field = 6; +global SERIALIZED_LEN: Field = 4; impl Serialize for Asset { fn serialize(Asset: Asset) -> [Field; SERIALIZED_LEN] { [ - Asset.interest_accumulator.lo as Field, - Asset.interest_accumulator.hi as Field, + Asset.interest_accumulator.to_integer(), Asset.last_updated_ts as Field, - Asset.loan_to_value.lo as Field, - Asset.loan_to_value.hi as Field, + Asset.loan_to_value.to_integer(), Asset.oracle.to_field() ] } @@ -32,10 +30,10 @@ impl Deserialize for Asset { // Right now we are wasting so many writes. If changing last_updated_ts // we will end up rewriting all of them, wasting writes. fn deserialize(fields: [Field; SERIALIZED_LEN]) -> Asset { - let interest_accumulator = U128 {lo: fields[0], hi: fields[1]}; - let last_updated_ts = fields[2] as u64; - let loan_to_value = U128 {lo: fields[3], hi: fields[4]}; - let oracle = AztecAddress::from_field(fields[5]); + let interest_accumulator = U128::from_integer(fields[0]); + let last_updated_ts = fields[1] as u64; + let loan_to_value = U128::from_integer(fields[2]); + let oracle = AztecAddress::from_field(fields[3]); Asset { interest_accumulator, diff --git a/noir-projects/noir-contracts/contracts/lending_contract/src/main.nr b/noir-projects/noir-contracts/contracts/lending_contract/src/main.nr index 328ec71ce97..c2c05f58a09 100644 --- a/noir-projects/noir-contracts/contracts/lending_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/lending_contract/src/main.nr @@ -1,5 +1,4 @@ mod asset; -mod position; mod interest_math; mod helpers; @@ -15,7 +14,6 @@ contract Lending { use dep::aztec::context::{PublicContext, Context, gas::GasOpts}; use crate::asset::Asset; - use crate::position::Position; use crate::interest_math::compute_multiplier; use crate::helpers::{covered_by_collateral, DebtReturn, debt_updates, debt_value, compute_identifier}; use dep::token::Token; @@ -31,6 +29,12 @@ contract Lending { static_debt: Map>, // abusing keys very heavily } + struct Position { + collateral: Field, + static_debt: Field, + debt: Field, + } + // Constructs the contract. #[aztec(private)] #[aztec(initializer)] @@ -261,13 +265,11 @@ contract Lending { storage.static_debt.at(owner).write(debt_returns.static_debt.to_integer()); } - #[aztec(public)] - fn get_asset(asset_id: Field) -> pub Asset { + unconstrained fn get_asset(asset_id: Field) -> pub Asset { storage.assets.at(asset_id).read() } - #[aztec(public)] - fn get_position(owner: AztecAddress) -> pub Position { + unconstrained fn get_position(owner: AztecAddress) -> pub Position { let collateral = storage.collateral.at(owner).read(); let static_debt = storage.static_debt.at(owner).read(); let asset: Asset = storage.assets.at(0).read(); @@ -278,8 +280,7 @@ contract Lending { Position { collateral, static_debt, debt } } - #[aztec(public)] - fn get_assets() -> pub [AztecAddress; 2] { + unconstrained fn get_assets() -> pub [AztecAddress; 2] { [storage.collateral_asset.read(), storage.stable_coin.read()] } } diff --git a/noir-projects/noir-contracts/contracts/lending_contract/src/position.nr b/noir-projects/noir-contracts/contracts/lending_contract/src/position.nr deleted file mode 100644 index 080f977e9c0..00000000000 --- a/noir-projects/noir-contracts/contracts/lending_contract/src/position.nr +++ /dev/null @@ -1,30 +0,0 @@ -use dep::aztec::prelude::AztecAddress; -use dep::aztec::protocol_types::traits::{Deserialize, Serialize}; - -struct Position { - collateral: Field, - static_debt: Field, - debt: Field, -} - -global POSITION_SERIALIZED_LEN: Field = 3; - -impl Serialize for Position { - fn serialize(position: Position) -> [Field; POSITION_SERIALIZED_LEN] { - [ - position.collateral.to_field(), - position.static_debt.to_field(), - position.debt.to_field(), - ] - } -} - -impl Deserialize for Position { - fn deserialize(fields: [Field; POSITION_SERIALIZED_LEN]) -> Position { - Position { - collateral: fields[0], - static_debt: fields[1], - debt: fields[2], - } - } -} diff --git a/noir-projects/noir-contracts/contracts/price_feed_contract/src/asset.nr b/noir-projects/noir-contracts/contracts/price_feed_contract/src/asset.nr index 3e148e12aa3..0f34a0429b1 100644 --- a/noir-projects/noir-contracts/contracts/price_feed_contract/src/asset.nr +++ b/noir-projects/noir-contracts/contracts/price_feed_contract/src/asset.nr @@ -8,7 +8,7 @@ global ASSET_SERIALIZED_LEN: Field = 1; impl Serialize for Asset { fn serialize(asset: Asset) -> [Field; ASSET_SERIALIZED_LEN] { - [asset.price.to_field()] + [asset.price.to_integer()] } } diff --git a/noir-projects/noir-contracts/contracts/price_feed_contract/src/main.nr b/noir-projects/noir-contracts/contracts/price_feed_contract/src/main.nr index c563792bf0c..c4afaacf753 100644 --- a/noir-projects/noir-contracts/contracts/price_feed_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/price_feed_contract/src/main.nr @@ -21,4 +21,8 @@ contract PriceFeed { fn get_price(asset_id: Field) -> Asset { storage.assets.at(asset_id).read() } + + unconstrained fn fetch_price(asset_id: Field) -> pub Asset { + storage.assets.at(asset_id).read() + } } diff --git a/noir-projects/noir-contracts/contracts/reader_contract/Nargo.toml b/noir-projects/noir-contracts/contracts/reader_contract/Nargo.toml new file mode 100644 index 00000000000..8ae3ed01400 --- /dev/null +++ b/noir-projects/noir-contracts/contracts/reader_contract/Nargo.toml @@ -0,0 +1,9 @@ +[package] +name = "reader_contract" +authors = [""] +compiler_version = ">=0.25.0" +type = "contract" + +[dependencies] +aztec = { path = "../../../aztec-nr/aztec" } +compressed_string = { path = "../../../aztec-nr/compressed-string" } diff --git a/noir-projects/noir-contracts/contracts/reader_contract/src/main.nr b/noir-projects/noir-contracts/contracts/reader_contract/src/main.nr new file mode 100644 index 00000000000..0cfbb45b596 --- /dev/null +++ b/noir-projects/noir-contracts/contracts/reader_contract/src/main.nr @@ -0,0 +1,69 @@ +contract Reader { + use dep::aztec::prelude::{AztecAddress, FunctionSelector, Deserialize}; + + use dep::compressed_string::FieldCompressedString; + + #[aztec(private)] + fn constructor() {} + + #[aztec(public)] + fn check_name_public(who: AztecAddress, what: str<31>) { + let selector = FunctionSelector::from_signature("public_get_name()"); + let name: FieldCompressedString = context.call_public_function_no_args(who, selector).deserialize_into(); + let _what = FieldCompressedString::from_string(what); + assert(name.is_eq(_what)); + } + + #[aztec(private)] + fn check_name_private(who: AztecAddress, what: str<31>) { + let selector = FunctionSelector::from_signature("private_get_name()"); + let name: FieldCompressedString = context.call_private_function_no_args(who, selector).unpack_into(); + let _what = FieldCompressedString::from_string(what); + assert(name.is_eq(_what)); + } + + unconstrained fn get_name(who: AztecAddress) -> pub str<6> { + // We cannot yet call an unconstrained function from another + "Reader" + } + + #[aztec(public)] + fn check_symbol_public(who: AztecAddress, what: str<31>) { + let selector = FunctionSelector::from_signature("public_get_symbol()"); + let symbol: FieldCompressedString = context.call_public_function_no_args(who, selector).deserialize_into(); + let _what = FieldCompressedString::from_string(what); + assert(symbol.is_eq(_what)); + } + + #[aztec(private)] + fn check_symbol_private(who: AztecAddress, what: str<31>) { + let selector = FunctionSelector::from_signature("private_get_symbol()"); + let symbol: FieldCompressedString = context.call_private_function_no_args(who, selector).unpack_into(); + let _what = FieldCompressedString::from_string(what); + assert(symbol.is_eq(_what)); + } + + unconstrained fn get_symbol(who: AztecAddress) -> pub str<3> { + // We cannot yet call an unconstrained function from another + "RDR" + } + + #[aztec(public)] + fn check_decimals_public(who: AztecAddress, what: u8) { + let selector = FunctionSelector::from_signature("public_get_decimals()"); + let ret: u8 = context.call_public_function_no_args(who, selector).deserialize_into(); + assert(ret == what); + } + + #[aztec(private)] + fn check_decimals_private(who: AztecAddress, what: u8) { + let selector = FunctionSelector::from_signature("private_get_decimals()"); + let result: u8 = context.call_private_function_no_args(who, selector).unpack_into(); + assert(result == what); + } + + unconstrained fn get_decimals(who: AztecAddress) -> pub u8 { + // We cannot yet call an unconstrained function from another + 18 + } +} diff --git a/noir-projects/noir-contracts/contracts/stateful_test_contract/src/main.nr b/noir-projects/noir-contracts/contracts/stateful_test_contract/src/main.nr index a96fbfca3a1..db8efde4a25 100644 --- a/noir-projects/noir-contracts/contracts/stateful_test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/stateful_test_contract/src/main.nr @@ -94,8 +94,7 @@ contract StatefulTest { balance_utils::get_balance(owner_balance) } - #[aztec(public)] - fn get_public_value(owner: AztecAddress) -> pub Field { + unconstrained fn get_public_value(owner: AztecAddress) -> pub Field { storage.public_values.at(owner).read() } } diff --git a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr index 21f62b8853f..ddb115c721e 100644 --- a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr @@ -38,16 +38,6 @@ contract TokenBlacklist { slow_update: SharedImmutable, } - #[aztec(public)] - fn total_supply() -> pub Field { - storage.total_supply.read().to_field() - } - - #[aztec(public)] - fn balance_of_public(owner: AztecAddress) -> pub Field { - storage.public_balances.at(owner).read().to_field() - } - // docs:start:constructor #[aztec(public)] #[aztec(initializer)] @@ -237,7 +227,8 @@ contract TokenBlacklist { storage.balances.sub(from, U128::from_integer(amount)); - TokenBlacklist::at(context.this_address())._increase_public_balance(to, amount).enqueue(&mut context); + let selector = FunctionSelector::from_signature("_increase_public_balance((Field),Field)"); + context.call_public_function(context.this_address(), selector, [to.to_field(), amount]); } // docs:start:transfer_private @@ -275,7 +266,8 @@ contract TokenBlacklist { storage.balances.sub(from, U128::from_integer(amount)); - TokenBlacklist::at(context.this_address())._reduce_total_supply(amount).enqueue(&mut context); + let selector = FunctionSelector::from_signature("_reduce_total_supply(Field)"); + context.call_public_function(context.this_address(), selector, [amount]); } /// Internal /// @@ -297,7 +289,15 @@ contract TokenBlacklist { /// Unconstrained /// + unconstrained fn total_supply() -> pub Field { + storage.total_supply.read().to_field() + } + unconstrained fn balance_of_private(owner: AztecAddress) -> pub Field { storage.balances.balance_of(owner).to_field() } + + unconstrained fn balance_of_public(owner: AztecAddress) -> pub Field { + storage.public_balances.at(owner).read().to_field() + } } diff --git a/noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr b/noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr index b32d8c41d78..28226b5b10b 100644 --- a/noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr @@ -26,7 +26,8 @@ contract TokenBridge { #[aztec(private)] #[aztec(initializer)] fn constructor(token: AztecAddress) { - TokenBridge::at(context.this_address())._initialize(token).enqueue(&mut context); + let selector = FunctionSelector::from_signature("_initialize((Field))"); + context.call_public_function(context.this_address(), selector, [token.to_field()]); } // docs:end:token_bridge_storage_and_constructor @@ -98,7 +99,11 @@ contract TokenBridge { // `mint_private` on token is public. So we call an internal public function // which then calls the public method on the token contract. // Since the secret_hash is passed, no secret is leaked. - TokenBridge::at(context.this_address())._call_mint_on_token(amount, secret_hash_for_redeeming_minted_notes).enqueue(&mut context); + context.call_public_function( + context.this_address(), + FunctionSelector::from_signature("_call_mint_on_token(Field,Field)"), + [amount, secret_hash_for_redeeming_minted_notes] + ); } // docs:end:claim_private @@ -119,7 +124,11 @@ contract TokenBridge { // docs:start:call_assert_token_is_same // Assert that user provided token address is same as seen in storage. - TokenBridge::at(context.this_address())._assert_token_is_same(token).enqueue(&mut context); + context.call_public_function( + context.this_address(), + FunctionSelector::from_signature("_assert_token_is_same((Field))"), + [token.to_field()] + ); // docs:end:call_assert_token_is_same // Burn tokens @@ -127,11 +136,19 @@ contract TokenBridge { } /// docs:end:exit_to_l1_private - // docs:start:read_token + // View function that is callable by other contracts. + // Unconstrained can't be called by others since it isn't safe. #[aztec(public)] fn get_token() -> AztecAddress { storage.token.read() } + + // /// Unconstrained /// + + // docs:start:read_token + unconstrained fn token() -> pub AztecAddress { + storage.token.read() + } // docs:end:read_token #[aztec(public)] diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/main.nr b/noir-projects/noir-contracts/contracts/token_contract/src/main.nr index a8a5cb8edbd..cc892421ece 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/main.nr @@ -84,6 +84,10 @@ contract Token { storage.name.read_private() } + unconstrained fn un_get_name() -> pub [u8; 31] { + storage.name.read_public().to_bytes() + } + #[aztec(public)] fn public_get_symbol() -> pub FieldCompressedString { storage.symbol.read_public() @@ -94,6 +98,10 @@ contract Token { storage.symbol.read_private() } + unconstrained fn un_get_symbol() -> pub [u8; 31] { + storage.symbol.read_public().to_bytes() + } + #[aztec(public)] fn public_get_decimals() -> pub u8 { // docs:start:read_decimals_public @@ -108,33 +116,9 @@ contract Token { // docs:end:read_decimals_private } - // docs:start:admin - #[aztec(public)] - fn admin() -> pub Field { - storage.admin.read().to_field() - } - // docs:end:admin - - // docs:start:is_minter - #[aztec(public)] - fn is_minter(minter: AztecAddress) -> pub bool { - storage.minters.at(minter).read() - } - // docs:end:is_minter - - // docs:start:total_supply - #[aztec(public)] - fn total_supply() -> pub Field { - storage.total_supply.read().to_field() - } - // docs:end:total_supply - - // docs:start:balance_of_public - #[aztec(public)] - fn balance_of_public(owner: AztecAddress) -> pub Field { - storage.public_balances.at(owner).read().to_field() + unconstrained fn un_get_decimals() -> pub u8 { + storage.decimals.read_public() } - // docs:end:balance_of_public // docs:start:set_minter #[aztec(public)] @@ -206,7 +190,7 @@ contract Token { let from_balance = storage.public_balances.at(from).read().sub(amount); let pending_shields = storage.pending_shields; - let mut note = TransparentNote::new(amount.to_field(), secret_hash); + let mut note = TransparentNote::new(amount.to_integer(), secret_hash); storage.public_balances.at(from).write(from_balance); pending_shields.insert_from_public(&mut note); @@ -346,10 +330,34 @@ contract Token { /// Unconstrained /// + // docs:start:admin + unconstrained fn admin() -> pub Field { + storage.admin.read().to_field() + } + // docs:end:admin + + // docs:start:is_minter + unconstrained fn is_minter(minter: AztecAddress) -> pub bool { + storage.minters.at(minter).read() + } + // docs:end:is_minter + + // docs:start:total_supply + unconstrained fn total_supply() -> pub Field { + storage.total_supply.read().to_integer() + } + // docs:end:total_supply + // docs:start:balance_of_private unconstrained fn balance_of_private(owner: AztecAddress) -> pub Field { - storage.balances.balance_of(owner).to_field() + storage.balances.balance_of(owner).to_integer() } // docs:end:balance_of_private + + // docs:start:balance_of_public + unconstrained fn balance_of_public(owner: AztecAddress) -> pub Field { + storage.public_balances.at(owner).read().to_integer() + } + // docs:end:balance_of_public } // docs:end:token_all diff --git a/yarn-project/end-to-end/src/e2e_avm_simulator.test.ts b/yarn-project/end-to-end/src/e2e_avm_simulator.test.ts index c94e1ca00ff..ac36f13ceaf 100644 --- a/yarn-project/end-to-end/src/e2e_avm_simulator.test.ts +++ b/yarn-project/end-to-end/src/e2e_avm_simulator.test.ts @@ -35,14 +35,14 @@ describe('e2e_avm_simulator', () => { describe('Storage', () => { it('Modifies storage (Field)', async () => { await avmContract.methods.set_storage_single(20n).send().wait(); - expect(await avmContract.methods.read_storage_single().simulate()).toEqual(20n); + expect(await avmContract.methods.view_storage_single().simulate()).toEqual(20n); }); it('Modifies storage (Map)', async () => { const address = AztecAddress.fromBigInt(9090n); await avmContract.methods.set_storage_map(address, 100).send().wait(); await avmContract.methods.add_storage_map(address, 100).send().wait(); - expect(await avmContract.methods.read_storage_map(address).simulate()).toEqual(200n); + expect(await avmContract.methods.view_storage_map(address).simulate()).toEqual(200n); }); }); diff --git a/yarn-project/end-to-end/src/e2e_blacklist_token_contract.test.ts b/yarn-project/end-to-end/src/e2e_blacklist_token_contract.test.ts index 1500098a5bc..59224084453 100644 --- a/yarn-project/end-to-end/src/e2e_blacklist_token_contract.test.ts +++ b/yarn-project/end-to-end/src/e2e_blacklist_token_contract.test.ts @@ -994,6 +994,7 @@ describe('e2e_blacklist_token_contract', () => { .methods.unshield(wallets[0].getAddress(), wallets[1].getAddress(), amount, nonce) .send(); await expect(txReplay.wait()).rejects.toThrow('Transaction '); + // @todo @LHerskind This error is weird? }); describe('failure cases', () => { diff --git a/yarn-project/end-to-end/src/e2e_token_contract/reading_constants.test.ts b/yarn-project/end-to-end/src/e2e_token_contract/reading_constants.test.ts index af856853415..b7a5089217f 100644 --- a/yarn-project/end-to-end/src/e2e_token_contract/reading_constants.test.ts +++ b/yarn-project/end-to-end/src/e2e_token_contract/reading_constants.test.ts @@ -1,14 +1,12 @@ -import { Fr } from '@aztec/circuits.js'; +import { ReaderContract } from '@aztec/noir-contracts.js'; import { TokenContractTest } from './token_contract_test.js'; -const toString = ({ value }: { value: bigint }) => { - const vals: number[] = Array.from(new Fr(value).toBuffer()); - +const toString = (val: bigint[]) => { let str = ''; - for (let i = 0; i < vals.length; i++) { - if (vals[i] != 0) { - str += String.fromCharCode(Number(vals[i])); + for (let i = 0; i < val.length; i++) { + if (val[i] != 0n) { + str += String.fromCharCode(Number(val[i])); } } return str; @@ -18,9 +16,26 @@ describe('e2e_token_contract reading constants', () => { const t = new TokenContractTest('reading_constants'); const { TOKEN_DECIMALS, TOKEN_NAME, TOKEN_SYMBOL } = TokenContractTest; // Do not destructure anything mutable. + const { logger } = t; + let reader: ReaderContract; beforeAll(async () => { await t.applyBaseSnapshots(); + + await t.snapshot( + 'reading_constants', + async () => { + logger.verbose('Deploying ReaderContract...'); + const reader = await ReaderContract.deploy(t.wallets[0]).send().deployed(); + logger.verbose(`Deployed ReaderContract to ${reader.address}.`); + return { readerAddress: reader.address }; + }, + async ({ readerAddress }) => { + reader = await ReaderContract.at(readerAddress, t.wallets[0]); + logger.verbose(`Reader contract restored to ${readerAddress}.`); + }, + ); + await t.setup(); }); @@ -35,32 +50,66 @@ describe('e2e_token_contract reading constants', () => { }); it('check name private', async () => { - const name = toString(await t.asset.methods.private_get_name().simulate()); + const name = toString(await t.asset.methods.un_get_name().simulate()); expect(name).toBe(TOKEN_NAME); + + await reader.methods.check_name_private(t.asset.address, TOKEN_NAME).send().wait(); + await expect(reader.methods.check_name_private(t.asset.address, 'WRONG_NAME').simulate()).rejects.toThrow( + 'name.is_eq(_what)', + ); }); it('check name public', async () => { - const name = toString(await t.asset.methods.public_get_name().simulate()); + const name = toString(await t.asset.methods.un_get_name().simulate()); expect(name).toBe(TOKEN_NAME); + + await reader.methods.check_name_public(t.asset.address, TOKEN_NAME).send().wait(); + await expect(reader.methods.check_name_public(t.asset.address, 'WRONG_NAME').simulate()).rejects.toThrow( + 'name.is_eq(_what)', + ); }); it('check symbol private', async () => { - const sym = toString(await t.asset.methods.private_get_symbol().simulate()); + const sym = toString(await t.asset.methods.un_get_symbol().simulate()); expect(sym).toBe(TOKEN_SYMBOL); + + await reader.methods.check_symbol_private(t.asset.address, TOKEN_SYMBOL).send().wait(); + + await expect(reader.methods.check_symbol_private(t.asset.address, 'WRONG_SYMBOL').simulate()).rejects.toThrow( + "Cannot satisfy constraint 'symbol.is_eq(_what)'", + ); }); it('check symbol public', async () => { - const sym = toString(await t.asset.methods.public_get_symbol().simulate()); + const sym = toString(await t.asset.methods.un_get_symbol().simulate()); expect(sym).toBe(TOKEN_SYMBOL); + + await reader.methods.check_symbol_public(t.asset.address, TOKEN_SYMBOL).send().wait(); + + await expect(reader.methods.check_symbol_public(t.asset.address, 'WRONG_SYMBOL').simulate()).rejects.toThrow( + "Failed to solve brillig function 'symbol.is_eq(_what)'", + ); }); it('check decimals private', async () => { - const dec = await t.asset.methods.private_get_decimals().simulate(); + const dec = await t.asset.methods.un_get_decimals().simulate(); expect(dec).toBe(TOKEN_DECIMALS); + + await reader.methods.check_decimals_private(t.asset.address, TOKEN_DECIMALS).send().wait(); + + await expect(reader.methods.check_decimals_private(t.asset.address, 99).simulate()).rejects.toThrow( + "Cannot satisfy constraint 'result == what'", + ); }); it('check decimals public', async () => { - const dec = await t.asset.methods.public_get_decimals().simulate(); + const dec = await t.asset.methods.un_get_decimals().simulate(); expect(dec).toBe(TOKEN_DECIMALS); + + await reader.methods.check_decimals_public(t.asset.address, TOKEN_DECIMALS).send().wait(); + + await expect(reader.methods.check_decimals_public(t.asset.address, 99).simulate()).rejects.toThrow( + "Failed to solve brillig function 'ret == what'", + ); }); }); diff --git a/yarn-project/end-to-end/src/shared/cross_chain_test_harness.ts b/yarn-project/end-to-end/src/shared/cross_chain_test_harness.ts index ef1d31bd8d3..63975935c91 100644 --- a/yarn-project/end-to-end/src/shared/cross_chain_test_harness.ts +++ b/yarn-project/end-to-end/src/shared/cross_chain_test_harness.ts @@ -109,7 +109,7 @@ export async function deployAndInitializeTokenAndBridgeContracts( throw new Error(`Token admin is not ${owner}`); } - if (!(await bridge.methods.get_token().simulate()).equals(token.address)) { + if (!(await bridge.methods.token().simulate()).equals(token.address)) { throw new Error(`Bridge token is not ${token.address}`); } From 901ae87795ba39420258e5d70b92221f11f7d20e Mon Sep 17 00:00:00 2001 From: Santiago Palladino Date: Mon, 22 Apr 2024 11:16:59 -0300 Subject: [PATCH 053/102] chore: Flag two failing e2e tests as flakey until we fix them --- .../src/{e2e_2_pxes.test.ts => flakey_e2e_2_pxes.test.ts} | 0 ...unt_init_fees.test.ts => flakey_e2e_account_init_fees.test.ts} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename yarn-project/end-to-end/src/{e2e_2_pxes.test.ts => flakey_e2e_2_pxes.test.ts} (100%) rename yarn-project/end-to-end/src/{e2e_account_init_fees.test.ts => flakey_e2e_account_init_fees.test.ts} (100%) diff --git a/yarn-project/end-to-end/src/e2e_2_pxes.test.ts b/yarn-project/end-to-end/src/flakey_e2e_2_pxes.test.ts similarity index 100% rename from yarn-project/end-to-end/src/e2e_2_pxes.test.ts rename to yarn-project/end-to-end/src/flakey_e2e_2_pxes.test.ts diff --git a/yarn-project/end-to-end/src/e2e_account_init_fees.test.ts b/yarn-project/end-to-end/src/flakey_e2e_account_init_fees.test.ts similarity index 100% rename from yarn-project/end-to-end/src/e2e_account_init_fees.test.ts rename to yarn-project/end-to-end/src/flakey_e2e_account_init_fees.test.ts From 2b51fee7dee663ee4a8cc54b5a5412d862d04862 Mon Sep 17 00:00:00 2001 From: ludamad Date: Mon, 22 Apr 2024 09:38:28 -0500 Subject: [PATCH 054/102] chore(ci): don't interleave docker prunes (#5914) --- .github/workflows/setup-runner.yml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/.github/workflows/setup-runner.yml b/.github/workflows/setup-runner.yml index fdde1373f94..2863a7a63f2 100644 --- a/.github/workflows/setup-runner.yml +++ b/.github/workflows/setup-runner.yml @@ -58,7 +58,7 @@ jobs: group: start-builder-${{ inputs.runner_label }} steps: - name: Start EC2 runner - uses: AztecProtocol/ec2-action-builder@v0.14e + uses: AztecProtocol/ec2-action-builder@v0.15 with: github_token: ${{ secrets.GH_SELF_HOSTED_RUNNER_TOKEN }} aws_access_key_id: ${{ secrets.AWS_ACCESS_KEY_ID }} @@ -104,6 +104,8 @@ jobs: if ! [ -f /etc/docker/daemon.json ] ; then echo '{"default-address-pools":[{"base":"172.17.0.0/12","size":20}, {"base":"10.99.0.0/12","size":20}, {"base":"192.168.0.0/16","size":24}]}' > /etc/docker/daemon.json sudo service docker restart + # helps to not overuse space + docker system prune -f || true echo "Configured docker daemon for making many networks." # Run maybe_exit_spot.sh every minute cp scripts/ci/spot_runner_graceful_exit.sh /run/spot_runner_graceful_exit.sh @@ -115,9 +117,5 @@ jobs: echo "Docker daemon already configured." fi - - name: Run Docker Prune - # helps to not overuse space - run: docker system prune -f -a || true - - name: Run Earthly Bootstrap run: earthly bootstrap From 03a87b8d97b72f8144ef83b679eed564048d4683 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Bene=C5=A1?= Date: Mon, 22 Apr 2024 16:39:26 +0200 Subject: [PATCH 055/102] refactor: introducing re-export for poseidon2 (#5898) Fixes #5863 --- noir-projects/aztec-nr/aztec/src/hash.nr | 4 +--- .../contracts/key_registry_contract/src/main.nr | 8 +++----- .../src/private_validation_request_processor.nr | 11 ++++++----- .../crates/types/src/address/aztec_address.nr | 5 ++--- .../noir-protocol-circuits/crates/types/src/hash.nr | 4 ++++ 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/hash.nr b/noir-projects/aztec-nr/aztec/src/hash.nr index f6980f78c2c..8406cf8c298 100644 --- a/noir-projects/aztec-nr/aztec/src/hash.nr +++ b/noir-projects/aztec-nr/aztec/src/hash.nr @@ -4,11 +4,9 @@ use dep::protocol_types::{ GENERATOR_INDEX__L1_TO_L2_MESSAGE_SECRET, GENERATOR_INDEX__NULLIFIER, ARGS_HASH_CHUNK_COUNT, GENERATOR_INDEX__FUNCTION_ARGS, ARGS_HASH_CHUNK_LENGTH }, - traits::Hash, hash::{pedersen_hash, silo_nullifier} + traits::Hash, hash::{pedersen_hash, poseidon2_hash, silo_nullifier, sha256_to_field} }; -use dep::protocol_types::hash::sha256_to_field; - pub fn compute_secret_hash(secret: Field) -> Field { // TODO(#1205) This is probably not the right index to use pedersen_hash([secret], GENERATOR_INDEX__L1_TO_L2_MESSAGE_SECRET) diff --git a/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr b/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr index 8f2810f3dbf..d4ed6addd03 100644 --- a/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr @@ -1,5 +1,4 @@ contract KeyRegistry { - use dep::std::hash::poseidon2::Poseidon2::hash as poseidon2_hash; use dep::authwit::auth::assert_current_call_valid_authwit_public; use dep::aztec::{ @@ -21,6 +20,7 @@ contract KeyRegistry { GENERATOR_INDEX__CONTRACT_ADDRESS_V1, GENERATOR_INDEX__PUBLIC_KEYS_HASH }, + hash::poseidon2_hash, traits::{ Serialize, Deserialize, @@ -86,8 +86,7 @@ contract KeyRegistry { outgoing_public_key, tagging_public_key, GENERATOR_INDEX__PUBLIC_KEYS_HASH, - ], - 5 + ] ); let computed_address = AztecAddress::from_field( @@ -95,8 +94,7 @@ contract KeyRegistry { partial_address.to_field(), public_keys_hash.to_field(), GENERATOR_INDEX__CONTRACT_ADDRESS_V1 as Field, - ], - 3 + ] ) ); diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/private_validation_request_processor.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/private_validation_request_processor.nr index 0f82c12f557..7fc2e3929d7 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/private_validation_request_processor.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/private_validation_request_processor.nr @@ -1,4 +1,3 @@ -use dep::std::hash::poseidon2::Poseidon2::hash as poseidon2_hash; use crate::{nullifier_read_request_reset::NullifierReadRequestHints, reset::read_request::reset_read_requests}; use dep::types::{ abis::{side_effect::{SideEffect, SideEffectLinkedToNoteHash}, validation_requests::ValidationRequests}, @@ -7,7 +6,7 @@ use dep::types::{ MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, GENERATOR_INDEX__NSK_M }, grumpkin_private_key::GrumpkinPrivateKey, keys::compute_siloed_nullifier_secret_key, - traits::is_empty + hash::poseidon2_hash, traits::is_empty }; struct PrivateValidationRequestProcessor { @@ -70,10 +69,12 @@ impl PrivateValidationRequestProcessor { ); // Then we check that siloing the master secret key with the contract address gives the app nullifier secret key - let app_nullifier_secret_key_preimage = [ + + let app_nullifier_secret_key = poseidon2_hash( + [ master_nullifier_secret_key.high, master_nullifier_secret_key.low, request.contract_address.to_field(), GENERATOR_INDEX__NSK_M - ]; - let app_nullifier_secret_key = poseidon2_hash(app_nullifier_secret_key_preimage, app_nullifier_secret_key_preimage.len()); + ] + ); assert( app_nullifier_secret_key.eq(request.app_nullifier_secret_key), "Failed to derive matching app nullifier secret key from the secret key." ); diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr b/noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr index c96342721a6..fcbae4871d9 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr @@ -1,10 +1,9 @@ use crate::{ crate::address::{eth_address::EthAddress, partial_address::PartialAddress, public_keys_hash::PublicKeysHash}, constants::{AZTEC_ADDRESS_LENGTH, GENERATOR_INDEX__CONTRACT_ADDRESS_V1}, - contract_class_id::ContractClassId, hash::pedersen_hash, grumpkin_point::GrumpkinPoint, + contract_class_id::ContractClassId, hash::poseidon2_hash, grumpkin_point::GrumpkinPoint, traits::{Empty, FromField, ToField, Serialize, Deserialize}, utils }; -use dep::std::hash::poseidon2::Poseidon2::hash as poseidon2_hash; // Aztec address struct AztecAddress { @@ -57,7 +56,7 @@ impl AztecAddress { pub fn compute(pub_keys_hash: PublicKeysHash, partial_address: PartialAddress) -> AztecAddress { AztecAddress::from_field( poseidon2_hash( - [pub_keys_hash.to_field(), partial_address.to_field(), GENERATOR_INDEX__CONTRACT_ADDRESS_V1], 3 + [pub_keys_hash.to_field(), partial_address.to_field(), GENERATOR_INDEX__CONTRACT_ADDRESS_V1] ) ) } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr b/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr index f43ee8f9b5c..ef7bc7f62bd 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr @@ -171,6 +171,10 @@ pub fn pedersen_hash(inputs: [Field; N], hash_index: u32) -> Field { dep::std::hash::pedersen_hash_with_separator(inputs, hash_index) } +pub fn poseidon2_hash(inputs: [Field; N]) -> Field { + dep::std::hash::poseidon2::Poseidon2::hash(inputs, N) +} + #[test] fn smoke_sha256_to_field() { let full_buffer = [ From febf00fb841407d54f42634560146568c383f80a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Bene=C5=A1?= Date: Mon, 22 Apr 2024 17:01:35 +0200 Subject: [PATCH 056/102] refactor: `TransparentNote` cleanup (#5904) --- .../src/types/transparent_note.nr | 36 ++++++++----------- .../src/types/transparent_note.nr | 36 ++++++++----------- 2 files changed, 30 insertions(+), 42 deletions(-) diff --git a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/transparent_note.nr b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/transparent_note.nr index 80748a32375..3e722a207f8 100644 --- a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/transparent_note.nr +++ b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/transparent_note.nr @@ -7,14 +7,14 @@ use dep::aztec::{ global TRANSPARENT_NOTE_LEN: Field = 2; -// Transparent note represents a note that is created in the clear (public execution), -// but can only be spent by those that know the preimage of the "secret_hash" +// Transparent note represents a note that is created in the clear (public execution), but can only be spent by those +// that know the preimage of the "secret_hash" (the secret). This is typically used when shielding a token balance. +// Owner of the tokens provides a "secret_hash" as an argument to the public "shield" function and then the tokens +// can be redeemed in private by presenting the preimage of the "secret_hash" (the secret). #[aztec(note)] struct TransparentNote { amount: Field, secret_hash: Field, - // the secret is just here for ease of use and won't be (de)serialized - secret: Field, } struct TransparentNoteProperties { @@ -34,19 +34,27 @@ impl NoteInterface for TransparentNote { TransparentNote { amount: serialized_note[0], secret_hash: serialized_note[1], - secret: 0, header: NoteHeader::empty(), } } + // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1386): Ensure nullifier collisions are prevented fn compute_nullifier(self, _context: &mut PrivateContext) -> Field { self.compute_nullifier_without_context() } + // Computing a nullifier in a transparent note is not guarded by making secret a part of the nullifier preimage (as + // is common in other cases) and instead is guarded by the functionality of "redeem_shield" function. There we do + // the following: + // 1) We pass the secret as an argument to the function and use it to compute a secret hash, + // 2) we fetch a note via the "get_notes" oracle which accepts the secret hash as an argument, + // 3) the "get_notes" oracle constrains that the secret hash in the returned note matches the one computed in + // circuit. + // This achieves that the note can only be spent by the party that knows the secret. fn compute_nullifier_without_context(self) -> Field { let siloed_note_hash = compute_note_hash_for_consumption(self); // TODO(#1205) Should use a non-zero generator index. - pedersen_hash([self.secret, siloed_note_hash],0) + pedersen_hash([siloed_note_hash], 0) } fn broadcast(self, context: &mut PrivateContext, slot: Field) { @@ -55,26 +63,12 @@ impl NoteInterface for TransparentNote { } impl TransparentNote { - // CONSTRUCTORS - pub fn new(amount: Field, secret_hash: Field) -> Self { - TransparentNote { amount, secret_hash, secret: 0, header: NoteHeader::empty() } - } - - // new oracle call primitive - // get me the secret corresponding to this hash - pub fn new_from_secret(amount: Field, secret: Field) -> Self { - TransparentNote { amount, secret_hash: compute_secret_hash(secret), secret, header: NoteHeader::empty() } + TransparentNote { amount, secret_hash, header: NoteHeader::empty() } } // CUSTOM FUNCTIONS FOR THIS NOTE TYPE - - pub fn knows_secret(self, secret: Field) { - let hash = compute_secret_hash(secret); - assert(self.secret_hash == hash); - } - // Custom serialization forces us to manually create the metadata struct and its getter pub fn properties() -> TransparentNoteProperties { TransparentNoteProperties { diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/types/transparent_note.nr b/noir-projects/noir-contracts/contracts/token_contract/src/types/transparent_note.nr index dfc106d2c13..3e722a207f8 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/types/transparent_note.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/types/transparent_note.nr @@ -7,14 +7,14 @@ use dep::aztec::{ global TRANSPARENT_NOTE_LEN: Field = 2; -// Transparent note represents a note that is created in the clear (public execution), -// but can only be spent by those that know the preimage of the "secret_hash" +// Transparent note represents a note that is created in the clear (public execution), but can only be spent by those +// that know the preimage of the "secret_hash" (the secret). This is typically used when shielding a token balance. +// Owner of the tokens provides a "secret_hash" as an argument to the public "shield" function and then the tokens +// can be redeemed in private by presenting the preimage of the "secret_hash" (the secret). #[aztec(note)] struct TransparentNote { amount: Field, secret_hash: Field, - // the secret is just here for ease of use and won't be (de)serialized - secret: Field } struct TransparentNoteProperties { @@ -34,19 +34,27 @@ impl NoteInterface for TransparentNote { TransparentNote { amount: serialized_note[0], secret_hash: serialized_note[1], - secret: 0, header: NoteHeader::empty(), } } + // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1386): Ensure nullifier collisions are prevented fn compute_nullifier(self, _context: &mut PrivateContext) -> Field { self.compute_nullifier_without_context() } + // Computing a nullifier in a transparent note is not guarded by making secret a part of the nullifier preimage (as + // is common in other cases) and instead is guarded by the functionality of "redeem_shield" function. There we do + // the following: + // 1) We pass the secret as an argument to the function and use it to compute a secret hash, + // 2) we fetch a note via the "get_notes" oracle which accepts the secret hash as an argument, + // 3) the "get_notes" oracle constrains that the secret hash in the returned note matches the one computed in + // circuit. + // This achieves that the note can only be spent by the party that knows the secret. fn compute_nullifier_without_context(self) -> Field { let siloed_note_hash = compute_note_hash_for_consumption(self); // TODO(#1205) Should use a non-zero generator index. - pedersen_hash([self.secret, siloed_note_hash],0) + pedersen_hash([siloed_note_hash], 0) } fn broadcast(self, context: &mut PrivateContext, slot: Field) { @@ -55,26 +63,12 @@ impl NoteInterface for TransparentNote { } impl TransparentNote { - // CONSTRUCTORS - pub fn new(amount: Field, secret_hash: Field) -> Self { - TransparentNote { amount, secret_hash, secret: 0, header: NoteHeader::empty() } - } - - // new oracle call primitive - // get me the secret corresponding to this hash - pub fn new_from_secret(amount: Field, secret: Field) -> Self { - TransparentNote { amount, secret_hash: compute_secret_hash(secret), secret, header: NoteHeader::empty() } + TransparentNote { amount, secret_hash, header: NoteHeader::empty() } } // CUSTOM FUNCTIONS FOR THIS NOTE TYPE - - pub fn knows_secret(self, secret: Field) { - let hash = compute_secret_hash(secret); - assert(self.secret_hash == hash); - } - // Custom serialization forces us to manually create the metadata struct and its getter pub fn properties() -> TransparentNoteProperties { TransparentNoteProperties { From 74a9d5d6736a4376e40e501765974b9686ca738e Mon Sep 17 00:00:00 2001 From: maramihali Date: Mon, 22 Apr 2024 16:17:21 +0100 Subject: [PATCH 057/102] chore: simplify computation of pow for each sumcheck round (#5903) We used to construct a separate data structure to store the "constant contribution" of the pow polynomials : at round l this will be the product of the partial evaluation result `c_l` (i.e. `pow(u_0,...,u_{l-1})`where `u_0,...,u_{l-1}`) are the verifier challenges and the elements of `pow(\vec{beta})` not containing `\beta_0,...,\beta_l`. This can be simplified, additionally avoiding unnecessary field multiplications. This does not affect benchmarks: ### BEFORE ``` -------------------------------------------------------------------------------- Benchmark Time CPU -------------------------------------------------------------------------------- ClientIVCBench/Full/6 21590 ms 16489 ms ``` ### AFTER ``` -------------------------------------------------------------------------------- Benchmark Time CPU -------------------------------------------------------------------------------- ClientIVCBench/Full/6 21571 ms 16454 ms ``` --- .../barretenberg/sumcheck/sumcheck_round.hpp | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp index 8360fe20f74..b3129797af4 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp @@ -108,15 +108,6 @@ template class SumcheckProverRound { { BB_OP_COUNT_TIME(); - // Compute the constant contribution of pow polynomials for each edge. This is the product of the partial - // evaluation result c_l (i.e. pow(u_0,...,u_{l-1})) where u_0,...,u_{l-1} are the verifier challenges from - // previous rounds) and the elements of pow(\vec{β}) not containing β_0,..., β_l. - std::vector pow_challenges(round_size >> 1); - pow_challenges[0] = pow_polynomial.partial_evaluation_result; - for (size_t i = 1; i < (round_size >> 1); ++i) { - pow_challenges[i] = pow_challenges[0] * pow_polynomial[i * pow_polynomial.periodicity]; - } - // Determine number of threads for multithreading. // Note: Multithreading is "on" for every round but we reduce the number of threads from the max available based // on a specified minimum number of iterations per thread. This eventually leads to the use of a single thread. @@ -144,11 +135,12 @@ template class SumcheckProverRound { extend_edges(extended_edges[thread_idx], polynomials, edge_idx); // Compute the i-th edge's univariate contribution, - // scale it by pow_challenge constant contribution and add it to the accumulators for SË¡(Xₗ) + // scale it by the corresponding pow contribution and add it to the accumulators for SË¡(Xₗ). The pow + // contribution represents the elements of pow(\vec{β}) not containing β_0,..., β_l accumulate_relation_univariates(thread_univariate_accumulators[thread_idx], extended_edges[thread_idx], relation_parameters, - pow_challenges[edge_idx >> 1]); + pow_polynomial[(edge_idx >> 1) * pow_polynomial.periodicity]); } }); @@ -208,11 +200,15 @@ template class SumcheckProverRound { bb::subrelation_is_linearly_independent(); // Except from the log derivative subrelation, each other subrelation in part is required to be 0 hence we // multiply by the power polynomial. As the sumcheck prover is required to send a univariate to the - // verifier, we additionally need a univariate contribution from the pow polynomial. + // verifier, we additionally need a univariate contribution from the pow polynomial which is the + // extended_random_polynomial. if (!is_subrelation_linearly_independent) { result += extended; } else { - result += extended * extended_random_polynomial; + // Multiply by the pow polynomial univariate contribution and the partial + // evaluation result c_l (i.e. pow(u_0,...,u_{l-1})) where u_0,...,u_{l-1} are the verifier challenges + // from previous rounds) + result += extended * extended_random_polynomial * pow_polynomial.partial_evaluation_result; } }; Utils::apply_to_tuple_of_tuples(tuple, extend_and_sum); From b194f83188f0e874a1f4c67a512370d3efcf883b Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Mon, 22 Apr 2024 16:22:09 +0100 Subject: [PATCH 058/102] chore: fix typo in error message (#5139) We're trying to run the functioned as unconstrained rather than constrained here. --- yarn-project/simulator/src/client/simulator.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/simulator/src/client/simulator.ts b/yarn-project/simulator/src/client/simulator.ts index a191f1ff721..38831db4601 100644 --- a/yarn-project/simulator/src/client/simulator.ts +++ b/yarn-project/simulator/src/client/simulator.ts @@ -139,7 +139,7 @@ export class AcirSimulator { contractAddress: AztecAddress, ) { if (entryPointArtifact.functionType !== FunctionType.UNCONSTRAINED) { - throw new Error(`Cannot run ${entryPointArtifact.functionType} function as constrained`); + throw new Error(`Cannot run ${entryPointArtifact.functionType} function as unconstrained`); } const context = new ViewDataOracle(contractAddress, [], this.db, this.node); From d9c1ee938ea8ff94639f29e457bd5e04ab2b9e8a Mon Sep 17 00:00:00 2001 From: spypsy Date: Mon, 22 Apr 2024 16:45:23 +0100 Subject: [PATCH 059/102] chore(ci): remove devnet deployments (for now) (#5912) --- .circleci/config.yml | 73 -------------------------------------------- build_manifest.yml | 12 -------- 2 files changed, 85 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 49f9588d930..317c9158f6c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -443,30 +443,6 @@ jobs: command: build aztec aztec_manifest_key: aztec - mainnet-fork: - machine: - image: default - resource_class: large - steps: - - *checkout - - *setup_env - - run: - name: "Build" - command: build mainnet-fork | add_timestamps - aztec_manifest_key: mainnet-fork - - aztec-faucet: - machine: - image: default - resource_class: large - steps: - - *checkout - - *setup_env - - run: - name: "Build and test" - command: build aztec-faucet | add_timestamps - aztec_manifest_key: aztec-faucet - boxes: docker: - image: aztecprotocol/alpine-build-image @@ -609,14 +585,6 @@ jobs: should_release || exit 0 deploy_dockerhub noir deploy_dockerhub aztec - deploy_dockerhub aztec-faucet - deploy_dockerhub mainnet-fork - - run: - name: "Deploy mainnet fork" - command: | - should_deploy || exit 0 - deploy_terraform_services iac/mainnet-fork mainnet-fork mainnet-fork aws_efs_file_system.aztec_mainnet_fork_data_store - ./iac/mainnet-fork/scripts/wait_for_fork - run: name: "Release canary to NPM: bb.js" command: | @@ -647,43 +615,6 @@ jobs: command: | should_release || exit 0 deploy_npm l1-contracts latest - - run: - name: "Deploy L1 contracts to mainnet fork" - working_directory: l1-contracts - command: | - should_deploy || exit 0 - ./scripts/ci_deploy_contracts.sh - - run: - name: "Deploy P2P bootstrap servers to AWS" - command: | - should_deploy 0 || exit 0 - # Export variables for Terraform. - export TF_VAR_BOOTNODE_1_PRIVATE_KEY=$BOOTNODE_1_PRIVATE_KEY - export TF_VAR_BOOTNODE_2_PRIVATE_KEY=$BOOTNODE_2_PRIVATE_KEY - deploy_terraform_services yarn-project/p2p-bootstrap aztec - - run: - name: "Deploy Aztec Nodes to AWS" - command: | - should_deploy 0 || exit 0 - export TF_VAR_BOOTNODE_1_PEER_ID=$BOOTNODE_1_PEER_ID - export TF_VAR_BOOTNODE_2_PEER_ID=$BOOTNODE_2_PEER_ID - export TF_VAR_SEQ_1_PUBLISHER_PRIVATE_KEY=$SEQ_1_PUBLISHER_PRIVATE_KEY - export TF_VAR_SEQ_2_PUBLISHER_PRIVATE_KEY=$SEQ_2_PUBLISHER_PRIVATE_KEY - export TF_VAR_NODE_1_PRIVATE_KEY=$NODE_1_PRIVATE_KEY - export TF_VAR_NODE_2_PRIVATE_KEY=$NODE_2_PRIVATE_KEY - # Check if l1-contracts have changed - if [ "$CONTRACTS_DEPLOYED" -eq 1 ]; then - echo "Contracts have changed, taint nodes to force redeploy.." - deploy_terraform_services yarn-project/aztec-node aztec aztec-node "aws_ecs_task_definition.aztec-node[0],aws_ecs_task_definition.aztec-node[1]" 1 - else - deploy_terraform_services yarn-project/aztec-node aztec - fi - - run: - name: "Deploy Aztec Faucet to AWS" - command: | - should_deploy 0 || exit 0 - export TF_VAR_FAUCET_PRIVATE_KEY=$FAUCET_PRIVATE_KEY - deploy_terraform_services yarn-project/aztec-faucet aztec # Repeatable config for defining the workflow below. defaults: &defaults @@ -807,8 +738,6 @@ workflows: - l1-contracts: *defaults - - mainnet-fork: *defaults - - noir-projects: requires: - avm-transpiler @@ -824,7 +753,6 @@ workflows: - noir-projects <<: *defaults - end-to-end: *defaults_yarn_project - - aztec-faucet: *defaults_yarn_project_pre_join - build-docs: *defaults_yarn_project_pre_join - prover-client-test: *defaults_yarn_project - yarn-project-test: *defaults_yarn_project @@ -873,7 +801,6 @@ workflows: - barretenberg-acir-tests-bb-sol - barretenberg-docs - build-docs - - mainnet-fork - boxes-vanilla - boxes-react - noir-packages-tests diff --git a/build_manifest.yml b/build_manifest.yml index 7fa488e722f..6c79c6810d4 100644 --- a/build_manifest.yml +++ b/build_manifest.yml @@ -201,14 +201,6 @@ aztec: - yarn-project multiarch: buildx -# Aztec faucet server. Has these dependencies because it's part of workspace. Consider moving out? -aztec-faucet: - buildDir: yarn-project - projectDir: yarn-project/aztec-faucet - dependencies: - - bb.js - - noir-packages - # Builds all the boxes. They are then independently tested in the container. boxes: buildDir: boxes @@ -234,10 +226,6 @@ end-to-end: runDependencies: - aztec -mainnet-fork: - buildDir: iac/mainnet-fork - projectDir: iac/mainnet-fork - docs: buildDir: . dockerfile: docs/Dockerfile From 07fc1434ac780f8a35533775e26ef2bd9e190816 Mon Sep 17 00:00:00 2001 From: josh crites Date: Mon, 22 Apr 2024 12:24:55 -0400 Subject: [PATCH 060/102] fix(docs): Fix formatting in protocol specs (#5882) - Fixes and improperly formatted admonition - Adds text to mermaid diagrams so that they render properly --- .../gas-and-fees/fee-payments-and-metering.md | 54 +++++++++---------- .../l1-smart-contracts/index.md | 5 +- 2 files changed, 29 insertions(+), 30 deletions(-) diff --git a/docs/docs/protocol-specs/gas-and-fees/fee-payments-and-metering.md b/docs/docs/protocol-specs/gas-and-fees/fee-payments-and-metering.md index b8a7c1db90e..1e3f882b4b5 100644 --- a/docs/docs/protocol-specs/gas-and-fees/fee-payments-and-metering.md +++ b/docs/docs/protocol-specs/gas-and-fees/fee-payments-and-metering.md @@ -57,7 +57,7 @@ All of these phases occur **within the same transaction**, ultimately resulting ![Transaction Components](/img/protocol-specs/gas-and-fees/Transaction.png) -The fee preparation and fee distribution phases respectively are responsible for ensuring that sufficient quantity of the fee payment asset is made available for the transaction and that it is correctly distributed to the sequencer with any refund being returned to the transaction sender. The sequencer will have have agency over which contract methods they are willing to accept for execution in these phases and will have visibility over the arguments passed to them. This is important as these functions must be successfully executed in order for the sequencer to be paid. It is assumed that the network will settle on a number of universally recognised fee payment contracts implementing fee preparation and distribution. +The fee preparation and fee distribution phases respectively are responsible for ensuring that sufficient quantity of the fee payment asset is made available for the transaction and that it is correctly distributed to the sequencer with any refund being returned to the transaction sender. The sequencer will have have agency over which contract methods they are willing to accept for execution in these phases and will have visibility over the arguments passed to them. This is important as these functions must be successfully executed in order for the sequencer to be paid. It is assumed that the network will settle on a number of universally recognized fee payment contracts implementing fee preparation and distribution. ## Gas Metering @@ -80,15 +80,15 @@ A comprehensive table of gas consuming operations can be found in the [fee sched ## Paying Transaction Fees -Transactions will need to be provided with sufficient fees to cover their gas consumption. The [private kernel circuits](../circuits/high-level-topology.md) understand a transaction's private execution as having 2 phases. The first phase is for the payment of fees. It is during this phase that the private execution must generate side-effects and enqueued function calls for the fee preparation and fee distribution phases of the transaction. These side-effects are deemed non-revertible. Typically, only contracts designed to be written as transaction entrypoints will need to be concerned with these phases and once the fee payment execution is complete, the transaction is moved to the second phase where all execution is considered the appication logic. The [private kernel circuits](../circuits/high-level-topology.md) maintain a 'high water mark' of side effects below which those side effects are deemed non-revertible. +Transactions will need to be provided with sufficient fees to cover their gas consumption. The [private kernel circuits](../circuits/high-level-topology.md) understand a transaction's private execution as having 2 phases. The first phase is for the payment of fees. It is during this phase that the private execution must generate side-effects and enqueued function calls for the fee preparation and fee distribution phases of the transaction. These side-effects are deemed non-revertible. Typically, only contracts designed to be written as transaction entrypoints will need to be concerned with these phases and once the fee payment execution is complete, the transaction is moved to the second phase where all execution is considered the application logic. The [private kernel circuits](../circuits/high-level-topology.md) maintain a 'high water mark' of side effects below which those side effects are deemed non-revertible. Transaction senders will need to compute a sufficient fee for the transaction considering both the transaction specific and amortized gas consumption. Transaction specific L1, L2, and DA gas can be calculated via simulation whereas amortized gas will need to be calculated by using a transaction sender specified minimum amortization. This minimum amortization is simply the minimum sized rollup that the transaction sender is willing to be included in. From this value, the amortized L1, L2 and DA gas values can be determined. Finally, a fixed amount of gas for the execution of fee distribution will need to be specified. An example of L2 gas amortization could be the transaction sender specifying a minimum amortization of 1024 transactions. The transaction sender would then compute the amount of amortized gas required for a rollup of that size: ``` -TotalGasToBeAmortised = (1024 - 2) * GMerge + GRoot -L2AmortizedGasLimit = TotalGasToBeAmortised / 1024 +TotalGasToBeAmortized = (1024 - 2) * GMerge + GRoot +L2AmortizedGasLimit = TotalGasToBeAmortized / 1024 Where GMerge = The gas cost of proving the merge rollup circuit. @@ -197,18 +197,16 @@ sequenceDiagram Alice->>AccountContract: run entrypoint AccountContract->>FPA: enqueue FPA.pay_fee(max_fee) msg_sender == Alice as fee distribution function AccountContract->>App: app logic - App->>AccountContract: + App->>AccountContract: response AccountContract->>Alice: finished private execution Alice->>Sequencer: tx object - Sequencer->>Sequencer: Recognise whitelisted function FPA.pay_fee(max_fee) and msg.sender == Alice + Sequencer->>Sequencer: Recognize whitelisted function FPA.pay_fee(max_fee) and msg.sender == Alice Sequencer->>FPA: verify that Alice has >= funds required from tx object FPA->>Sequencer: Alice has >= funds required from tx object - Sequencer->>App: app logic - App->>Sequencer: - + App->>Sequencer: response Sequencer->>FPA: FPA.pay_fee(max_fee) FPA->>FPA: calculate fee based on inputs to VM circuit FPA->>Alice: Alice's balance is reduced by fee amount @@ -241,19 +239,19 @@ sequenceDiagram FPC->>AST: AST.transfer(FPC, max_fee + commission, nonce) AST->>AccountContract: check auth witness FPC->>FPC: enqueue FPA.private_fee_payment(max_fee) msg_sender == FPC as fee distribution function - FPC->>AccountContract: + FPC->>AccountContract: response AccountContract->>App: app logic - App->>AccountContract: + App->>AccountContract: response AccountContract->>Alice: finished private execution Alice->>Sequencer: tx object - Sequencer->>Sequencer: Recognise whitelisted function FPA.private_fee_payment(max_fee) and msg.sender == FPC + Sequencer->>Sequencer: Recognize whitelisted function FPA.private_fee_payment(max_fee) and msg.sender == FPC Sequencer->>FPA: verify that FPC has >= funds required from tx object FPA->>Sequencer: FPC has >= funds required from tx object Sequencer->>App: app logic - App->>Sequencer: + App->>Sequencer: response Sequencer->>FPA: FPA.private_fee_payment(max_fee) FPA->>FPA: calculate fee based on inputs to VM circuit @@ -282,35 +280,34 @@ sequenceDiagram end Alice->>AccountContract: run entrypoint - AccountContract->>AccountContract: pulic auth witness for AST transfer + AccountContract->>AccountContract: public auth witness for AST transfer AccountContract->>FPC: public_fee_entrypoint(AST, max_fee, nonce) activate FPC FPC->>FPC: enqueue FPC.public_fee_preparation(Alice, AST, max_fee, nonce) as fee preparation with msg_sender == FPC FPC->>FPC: enqueue FPC.public_fee_payment(Alice, AST, max_fee) as fee distribution with msg_sender == FPC - FPC->>AccountContract: - deactivate FPC + FPC->>AccountContract: deactivate FPC AccountContract->>App: app logic - App->>AccountContract: + App->>AccountContract: response AccountContract->>Alice: finished private execution Alice->>Sequencer: tx object - Sequencer->>Sequencer: Recognise whitelisted function FPC.public_fee_preparation(Alice, AST, max_fee, nonce) and msg.sender == FPC + Sequencer->>Sequencer: Recognize whitelisted function FPC.public_fee_preparation(Alice, AST, max_fee, nonce) and msg.sender == FPC Sequencer->>FPC: FPC.public_fee_preparation(Alice, AST, max_fee, nonce) activate FPC FPC->>AST: AST.transfer_public(Alice, FPC, max_fee + commission, nonce) AST->>AccountContract: check auth witness - AccountContract->>AST: - AST->>FPC: + AccountContract->>AST: response + AST->>FPC: response FPC->>FPA: FPA.check_balance(max_fee) - FPA->>FPC: + FPA->>FPC: response FPC->>Sequencer: FPC has the funds deactivate FPC Sequencer->>App: app logic - App->>Sequencer: + App->>Sequencer: response - Sequencer->>Sequencer: Recognise whitelisted function FPC.public_fee_payment(Alice, AST, max_fee) and msg.sender == FPC + Sequencer->>Sequencer: Recognize whitelisted function FPC.public_fee_payment(Alice, AST, max_fee) and msg.sender == FPC Sequencer->>FPC: FPC.public_fee_payment(Alice, AST, max_fee) activate FPC FPC->>FPA: FPA.pay_fee(max_fee) @@ -318,14 +315,14 @@ sequenceDiagram FPA->>Sequencer: Sequencer's balance is increased by fee amount FPA->>FPC: rebate value FPC->>AST: AST.transfer_public(FPC, Alice, rebate, 0) - AST->>FPC: + AST->>FPC: response FPC->>Alice: Alice's balance is increased by rebate value deactivate FPC ``` ### DApp Sponsorship -In this scenario a DApp wishes to pay the fee on behalf of a user for interactng with it. The DApp has a balance of FPA from which it wishes to pay for the transaction. It shares many similarities with the previous native asset fee payment scenario. +In this scenario a DApp wishes to pay the fee on behalf of a user for interacting with it. The DApp has a balance of FPA from which it wishes to pay for the transaction. It shares many similarities with the previous native asset fee payment scenario. ```mermaid sequenceDiagram @@ -342,7 +339,7 @@ sequenceDiagram Alice->>DApp: run entrypoint DApp->>AccountContract: check auth witness - AccountContract->>DApp: + AccountContract->>DApp: app logic DApp->>DApp: check if will sponsor action DApp->>FPA: enqueue FPA.pay_fee(max_fee) and msg_sender == DApp as fee distribution DApp->>DApp: app logic @@ -350,13 +347,12 @@ sequenceDiagram Alice->>Sequencer: tx object - Sequencer->>Sequencer: Recognise whitelisted function FPA.pay_fee(max_fee) and msg.sender == DApp + Sequencer->>Sequencer: Recognize whitelisted function FPA.pay_fee(max_fee) and msg.sender == DApp Sequencer->>FPA: verify that DApp has >= funds required from tx object FPA->>Sequencer: DApp has >= funds required from tx object Sequencer->>DApp: app logic - DApp->>Sequencer: - + DApp->>Sequencer: response Sequencer->>FPA: FPA.pay_fee(max_fee) FPA->>FPA: calculate fee based on inputs to VM circuit FPA->>DApp: DApp's balance is reduced by fee amount diff --git a/docs/docs/protocol-specs/l1-smart-contracts/index.md b/docs/docs/protocol-specs/l1-smart-contracts/index.md index 0a2f7a924d8..a7ea92cc4b6 100644 --- a/docs/docs/protocol-specs/l1-smart-contracts/index.md +++ b/docs/docs/protocol-specs/l1-smart-contracts/index.md @@ -12,7 +12,8 @@ The purpose of the L1 contracts are simple: - Facilitate cross-chain communication such that L1 liquidity can be used on L2 - Act as a validating light node for L2 that every L1 node implicitly run - ::: + +::: ## Overview @@ -41,10 +42,12 @@ def process(block: ProvenBlock, proof: Proof): ``` :::info Why `math.ceil(log2(MAX_NEW_L2_TO_L1_MSGS_PER_TX))`? + The argument to the `insert` function is the `outbox` is the heigh of the message tree. Since every transaction can hold more than 1 message, it might add multiple layers to the tree. For a binary tree, the number of extra layers to add is computed as `math.ceil(log2(MAX_NEW_L2_TO_L1_MSGS_PER_TX))`. Currently, `MAX_NEW_L2_TO_L1_MSGS_PER_TX = 2` which means that we are simply adding 1 extra layer. + ::: While the `ProvenBlock` must be published and available for nodes to build the state of the rollup, we can build the validating light node (the contract) such that as long as the node can be _convinced_ that the data is available we can progress the state. From d8254efe958898d28dbe25474b9eb21cebb4ed2c Mon Sep 17 00:00:00 2001 From: ludamad Date: Mon, 22 Apr 2024 12:15:35 -0500 Subject: [PATCH 061/102] chore(ci): move yarn-project-test to new CI (#5850) to debug yarn-project-test failures locally: `earthly -i ./yarn-project/+test` then once it fails you will be in a local session, poke around and see if you can find the wrong artifact version --------- Co-authored-by: Santiago Palladino --- .circleci/config.yml | 14 ------------ .github/workflows/ci.yml | 36 +++++++++++++++++++++++++----- .github/workflows/setup-runner.yml | 2 +- yarn-project/Earthfile | 8 +++++++ 4 files changed, 40 insertions(+), 20 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 317c9158f6c..ac54d75ec06 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -407,18 +407,6 @@ jobs: command: create_ecr_manifest yarn-project x86_64,arm64 aztec_manifest_key: yarn-project - yarn-project-test: - docker: - - image: aztecprotocol/alpine-build-image - resource_class: small - steps: - - *checkout - - *setup_env - - run: - name: "Build and test" - command: cond_spot_run_build yarn-project-test 64 - aztec_manifest_key: yarn-project-test - prover-client-test: docker: - image: aztecprotocol/alpine-build-image @@ -755,7 +743,6 @@ workflows: - end-to-end: *defaults_yarn_project - build-docs: *defaults_yarn_project_pre_join - prover-client-test: *defaults_yarn_project - - yarn-project-test: *defaults_yarn_project - yarn-project-x86_64: *defaults_yarn_project_pre_join - yarn-project-arm64: *defaults_yarn_project_pre_join - yarn-project-ecr-manifest: @@ -804,7 +791,6 @@ workflows: - boxes-vanilla - boxes-react - noir-packages-tests - - yarn-project-test - prover-client-test - e2e-join <<: *defaults diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6fee521f74c..23c4d074d2f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -77,8 +77,6 @@ jobs: bb-native-tests: needs: setup runs-on: ${{ inputs.username || github.actor }}-x86 - strategy: - fail-fast: false steps: - {uses: actions/checkout@v4, with: { ref: "${{ github.event.pull_request.head.sha }}"}} # Only allow one memory-hunger prover test to use this runner @@ -93,6 +91,34 @@ jobs: # limit our parallelism to half our cores run: earthly --no-output +test --hardware_concurrency=64 + yarn-project-formatting: + needs: setup + runs-on: ${{ github.actor }}-x86 + steps: + - {uses: actions/checkout@v4, with: { ref: "${{ github.event.pull_request.head.sha }}"}} + # Only allow one memory-hunger prover test to use this runner + - uses: ./.github/ci-setup-action + with: + dockerhub_password: "${{ secrets.DOCKERHUB_PASSWORD }}" + concurrency_key: yarn-project-test-${{ github.actor }}-x86 + - name: "Yarn Project Tests" + timeout-minutes: 25 + run: earthly --no-output ./yarn-project/+format-check + + yarn-project-test: + needs: setup + runs-on: ${{ github.actor }}-x86 + steps: + - {uses: actions/checkout@v4, with: { ref: "${{ github.event.pull_request.head.sha }}"}} + # Only allow one memory-hunger prover test to use this runner + - uses: ./.github/ci-setup-action + with: + dockerhub_password: "${{ secrets.DOCKERHUB_PASSWORD }}" + concurrency_key: yarn-project-test-${{ github.actor }}-x86 + - name: "Yarn Project Tests" + timeout-minutes: 25 + run: earthly --no-output ./yarn-project/+test + # push benchmarking binaries to dockerhub registry bb-bench-binaries: needs: setup @@ -142,13 +168,13 @@ jobs: run: earthly --no-output +bench-ultra-honk --bench_mode=cache merge-check: - runs-on: ${{ inputs.username || github.actor }}-x86 - needs: [e2e, bb-native-tests, bb-bench] + runs-on: ubuntu-latest + needs: [e2e, bb-native-tests, bb-bench, yarn-project-formatting, yarn-project-test] steps: - run: echo Pull request merging now allowed. notify: - needs: [e2e, bb-native-tests, bb-bench] + needs: [e2e, bb-native-tests, bb-bench, yarn-project-formatting, yarn-project-test] runs-on: ubuntu-latest if: ${{ github.ref == 'refs/heads/master' && failure() }} steps: diff --git a/.github/workflows/setup-runner.yml b/.github/workflows/setup-runner.yml index 2863a7a63f2..b0b4139d8bf 100644 --- a/.github/workflows/setup-runner.yml +++ b/.github/workflows/setup-runner.yml @@ -58,7 +58,7 @@ jobs: group: start-builder-${{ inputs.runner_label }} steps: - name: Start EC2 runner - uses: AztecProtocol/ec2-action-builder@v0.15 + uses: AztecProtocol/ec2-action-builder@v0.14e with: github_token: ${{ secrets.GH_SELF_HOSTED_RUNNER_TOKEN }} aws_access_key_id: ${{ secrets.AWS_ACCESS_KEY_ID }} diff --git a/yarn-project/Earthfile b/yarn-project/Earthfile index 0118394dc78..c582587cd7d 100644 --- a/yarn-project/Earthfile +++ b/yarn-project/Earthfile @@ -93,3 +93,11 @@ export-end-to-end: SAVE IMAGE aztecprotocol/end-to-end:$EARTHLY_GIT_HASH FROM +aztec SAVE IMAGE aztecprotocol/aztec:$EARTHLY_GIT_HASH + +format-check: + FROM +build + RUN yarn formatting + +test: + FROM +build + RUN yarn test \ No newline at end of file From f77636f686d5416c9e2f893ed40730a08b48a5ee Mon Sep 17 00:00:00 2001 From: ludamad Date: Mon, 22 Apr 2024 13:07:53 -0500 Subject: [PATCH 062/102] chore(ci): use on-demand for now (#5933) looks like spot instances were spotty --- .github/workflows/setup-runner.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/setup-runner.yml b/.github/workflows/setup-runner.yml index b0b4139d8bf..80d3bd59056 100644 --- a/.github/workflows/setup-runner.yml +++ b/.github/workflows/setup-runner.yml @@ -30,7 +30,7 @@ on: default: sg-0ccd4e5df0dcca0c9 type: string ec2_spot_instance_strategy: - default: BestEffort + default: None type: string aws_region: default: "us-east-2" From 0e8164239b6a1180fd292e37faf1a0e64aa9cff4 Mon Sep 17 00:00:00 2001 From: spypsy Date: Mon, 22 Apr 2024 19:12:27 +0100 Subject: [PATCH 063/102] feat(p2p): DiscV5 Peer Discovery (#5652) --- cspell.json | 8 +- .../sandbox/references/sandbox-reference.md | 2 +- yarn-project/aztec-node/terraform/main.tf | 10 +- yarn-project/aztec/src/cli/texts.ts | 2 +- .../src/flakey_e2e_p2p_network.test.ts | 38 +- yarn-project/p2p/package.json | 22 +- yarn-project/p2p/src/bootstrap/bootstrap.ts | 122 +- yarn-project/p2p/src/client/index.ts | 17 +- yarn-project/p2p/src/client/p2p_client.ts | 2 +- yarn-project/p2p/src/config.ts | 37 +- .../p2p/src/service/discV5_service.ts | 122 + .../p2p/src/service/discv5_service.test.ts | 101 + yarn-project/p2p/src/service/dummy_service.ts | 31 +- .../p2p/src/service/known_txs.test.ts | 2 +- yarn-project/p2p/src/service/known_txs.ts | 2 +- .../p2p/src/service/libp2p_service.ts | 115 +- yarn-project/p2p/src/service/peer_store.ts | 36 + yarn-project/p2p/src/service/service.ts | 32 +- yarn-project/yarn.lock | 3121 +++++++++-------- 19 files changed, 2133 insertions(+), 1689 deletions(-) create mode 100644 yarn-project/p2p/src/service/discV5_service.ts create mode 100644 yarn-project/p2p/src/service/discv5_service.test.ts create mode 100644 yarn-project/p2p/src/service/peer_store.ts diff --git a/cspell.json b/cspell.json index 668e378ad18..b53724fe7ca 100644 --- a/cspell.json +++ b/cspell.json @@ -4,6 +4,7 @@ "accum", "acir", "acvm", + "addrs", "archiver", "assignement", "asyncify", @@ -70,12 +71,14 @@ "devs", "diffie", "direnv", + "discv5", "dockerfiles", "dockerhub", "dockerized", "doesnt", "dont", "elif", + "enrs", "entrypoints", "erc", "falsey", @@ -137,7 +140,10 @@ "mplex", "msgpack", "muldiv", + "multiaddr", + "multiaddrs", "multiarch", + "multiformats", "multivalue", "muxers", "nada", @@ -281,4 +287,4 @@ "flagWords": [ "anonymous" ] -} +} \ No newline at end of file diff --git a/docs/docs/developers/sandbox/references/sandbox-reference.md b/docs/docs/developers/sandbox/references/sandbox-reference.md index e25b3b02eba..8ce365cdf2a 100644 --- a/docs/docs/developers/sandbox/references/sandbox-reference.md +++ b/docs/docs/developers/sandbox/references/sandbox-reference.md @@ -115,6 +115,7 @@ Variables like `DEPLOY_AZTEC_CONTRACTS` & `AZTEC_NODE_PORT` are valid here as de # Configuration variables for connecting a Node to the Aztec Node P2P network. You'll need a running P2P-Bootstrap node to connect to. P2P_ENABLED='false' # A flag to enable P2P networking for this node. (default: false) P2P_BLOCK_CHECK_INTERVAL_MS=100 # The frequency in which to check for new L2 blocks. +P2P_PEER_CHECK_INTERVAL_MS=1000 # The frequency in which to check for peers. P2P_L2_BLOCK_QUEUE_SIZE=1000 # Size of queue of L2 blocks to store. P2P_TCP_LISTEN_PORT=40400 # The tcp port on which the P2P service should listen for connections. P2P_TCP_LISTEN_IP= #The tcp IP on which the P2P service should listen for connections. @@ -122,7 +123,6 @@ PEER_ID_PRIVATE_KEY='' # An optional peer id private key. If blank, will generat BOOTSTRAP_NODES='' # A list of bootstrap peers to connect to, separated by commas P2P_ANNOUNCE_HOSTNAME='' # Hostname to announce to the p2p network P2P_ANNOUNCE_PORT='' # Port to announce to the p2p network -P2P_KAD_CLIENT='false' # Optional specification to run as a client in the Kademlia routing protocol. P2P_NAT_ENABLED='false' # Whether to enable NAT from libp2p P2P_MIN_PEERS=10 # The minimum number of peers (a peer count below this will cause the node to look for more peers) P2P_MAX_PEERS=100 # The maximum number of peers (a peer count above this will cause the node to refuse connection attempts) diff --git a/yarn-project/aztec-node/terraform/main.tf b/yarn-project/aztec-node/terraform/main.tf index 6123b877c30..aa0f09624ed 100644 --- a/yarn-project/aztec-node/terraform/main.tf +++ b/yarn-project/aztec-node/terraform/main.tf @@ -291,7 +291,15 @@ resource "aws_ecs_task_definition" "aztec-node" { { "name": "P2P_MAX_PEERS", "value": "${var.P2P_MAX_PEERS}" - } + }, + { + "name": "P2P_BLOCK_CHECK_INTERVAL_MS", + "value": "1000" + }, + { + "name": "P2P_PEER_CHECK_INTERVAL_MS", + "value": "2000" + }, ], "mountPoints": [ { diff --git a/yarn-project/aztec/src/cli/texts.ts b/yarn-project/aztec/src/cli/texts.ts index effb6912fe5..e65ba2847b9 100644 --- a/yarn-project/aztec/src/cli/texts.ts +++ b/yarn-project/aztec/src/cli/texts.ts @@ -7,6 +7,7 @@ const contractAddresses = 'availabilityOracleAddress:AVAILABILITY_ORACLE_CONTRACT_ADDRESS - string - The deployed L1 availability oracle contract address.\n'; const p2pOptions = 'p2pBlockCheckIntervalMS:P2P_BLOCK_CHECK_INTERVAL_MS - number - The frequency in which to check for blocks. Default: 100\n' + + 'p2pPeerCheckIntervalMS:P2P_PEER_CHECK_INTERVAL_MS - number - The frequency in which to check for peers. Default: 1000\n' + 'p2pL2QueueSize:P2P_L2_QUEUE_SIZE - number - Size of queue of L2 blocks to store. Default: 1000\n' + 'tcpListenPort:TCP_LISTEN_PORT - number - The tcp port on which the P2P service should listen for connections. Default: 40400\n' + 'tcpListenIp:TCP_LISTEN_IP - string - The tcp IP on which the P2P service should listen for connections. Default: 0.0.0.0\n' + @@ -14,7 +15,6 @@ const p2pOptions = 'bootstrapNodes:BOOTSTRAP_NODES - string - A list of bootstrap peers to connect to.\n' + 'announceHostname:P2P_ANNOUNCE_HOSTNAME - string - P2P Hostname to announce.\n' + 'announcePort:P2P_ANNOUNCE_PORT - number - P2P Port to announce.\n' + - 'clientKADRouting:P2P_KAD_CLIENT - boolean - Optional specification to run as a client in the Kademlia routing protocol. Default: false\n' + 'enableNat:P2P_NAT_ENABLED - boolean - Whether to enable NAT from libp2p (ignored for bootstrap node). Default: false\n' + 'minPeerCount:P2P_MIN_PEERS - number - The minimum number of peers to connect to. Default: 10\n' + 'maxPeerCount:P2P_MAX_PEERS - number - The maximum number of peers to connect to. Default: 100\n'; diff --git a/yarn-project/end-to-end/src/flakey_e2e_p2p_network.test.ts b/yarn-project/end-to-end/src/flakey_e2e_p2p_network.test.ts index c4d001c06bb..77e8382ad67 100644 --- a/yarn-project/end-to-end/src/flakey_e2e_p2p_network.test.ts +++ b/yarn-project/end-to-end/src/flakey_e2e_p2p_network.test.ts @@ -9,7 +9,7 @@ import { type SentTx, TxStatus, } from '@aztec/aztec.js'; -import { BootstrapNode, type P2PConfig, createLibP2PPeerId } from '@aztec/p2p'; +import { type BootNodeConfig, BootstrapNode, createLibP2PPeerId } from '@aztec/p2p'; import { type PXEService, createPXEService, getPXEServiceConfig as getRpcConfig } from '@aztec/pxe'; import { mnemonicToAccount } from 'viem/accounts'; @@ -44,16 +44,17 @@ describe('e2e_p2p_network', () => { it('should rollup txs from all peers', async () => { // create the bootstrap node for the network const bootstrapNode = await createBootstrapNode(); - const bootstrapNodeAddress = `/ip4/127.0.0.1/tcp/${BOOT_NODE_TCP_PORT}/p2p/${bootstrapNode - .getPeerId()! - .toString()}`; + const bootstrapNodeEnr = bootstrapNode.getENR(); + if (!bootstrapNodeEnr) { + throw new Error('Bootstrap node ENR is not available'); + } // create our network of nodes and submit txs into each of them // the number of txs per node and the number of txs per rollup // should be set so that the only way for rollups to be built // is if the txs are successfully gossiped around the nodes. const contexts: NodeContext[] = []; for (let i = 0; i < NUM_NODES; i++) { - const node = await createNode(i + 1 + BOOT_NODE_TCP_PORT, bootstrapNodeAddress, i); + const node = await createNode(i + 1 + BOOT_NODE_TCP_PORT, bootstrapNodeEnr?.encodeTxt(), i); const context = await createPXEServiceAndSubmitTransactions(node, NUM_TXS_PER_NODE); contexts.push(context); } @@ -71,23 +72,16 @@ describe('e2e_p2p_network', () => { const createBootstrapNode = async () => { const peerId = await createLibP2PPeerId(); - const bootstrapNode = new BootstrapNode(logger); - const config: P2PConfig = { - p2pEnabled: true, - tcpListenPort: BOOT_NODE_TCP_PORT, - tcpListenIp: '0.0.0.0', - announceHostname: '/tcp/127.0.0.1', + const bootstrapNode = new BootstrapNode(); + const config: BootNodeConfig = { + udpListenPort: BOOT_NODE_TCP_PORT, + udpListenIp: '0.0.0.0', + announceHostname: '/ip4/127.0.0.1', announcePort: BOOT_NODE_TCP_PORT, peerIdPrivateKey: Buffer.from(peerId.privateKey!).toString('hex'), - clientKADRouting: false, minPeerCount: 10, maxPeerCount: 100, - - // TODO: the following config options are not applicable to bootstrap nodes - p2pBlockCheckIntervalMS: 1000, - p2pL2QueueSize: 1, - transactionProtocol: '', - bootstrapNodes: [''], + p2pPeerCheckIntervalMS: 100, }; await bootstrapNode.start(config); @@ -105,13 +99,17 @@ describe('e2e_p2p_network', () => { const newConfig: AztecNodeConfig = { ...config, tcpListenPort, + udpListenPort: tcpListenPort, tcpListenIp: '0.0.0.0', - enableNat: false, + udpListenIp: '0.0.0.0', + announceHostname: '/ip4/127.0.0.1', bootstrapNodes: [bootstrapNode], minTxsPerBlock: NUM_TXS_PER_BLOCK, maxTxsPerBlock: NUM_TXS_PER_BLOCK, p2pEnabled: true, - clientKADRouting: false, + p2pBlockCheckIntervalMS: 1000, + p2pL2QueueSize: 1, + transactionProtocol: '', }; return await AztecNodeService.createAndSync(newConfig); }; diff --git a/yarn-project/p2p/package.json b/yarn-project/p2p/package.json index 61c052d6f1f..8ba5ec40883 100644 --- a/yarn-project/p2p/package.json +++ b/yarn-project/p2p/package.json @@ -43,19 +43,23 @@ "@aztec/circuits.js": "workspace:^", "@aztec/foundation": "workspace:^", "@aztec/kv-store": "workspace:^", - "@chainsafe/libp2p-noise": "^13.0.0", - "@chainsafe/libp2p-yamux": "^5.0.0", + "@chainsafe/discv5": "^9.0.0", + "@chainsafe/enr": "^3.0.0", + "@chainsafe/libp2p-noise": "^15.0.0", + "@chainsafe/libp2p-yamux": "^6.0.2", "@libp2p/bootstrap": "^9.0.4", - "@libp2p/interface": "^0.1.2", + "@libp2p/crypto": "^4.0.3", + "@libp2p/identify": "^1.0.15", + "@libp2p/interface": "^1.1.4", "@libp2p/interface-libp2p": "^3.2.0", - "@libp2p/interface-peer-id": "^2.0.2", "@libp2p/kad-dht": "^10.0.4", - "@libp2p/mplex": "^9.0.4", - "@libp2p/peer-id": "^3.0.2", - "@libp2p/peer-id-factory": "^3.0.3", - "@libp2p/tcp": "^8.0.4", + "@libp2p/mplex": "^10.0.16", + "@libp2p/peer-id": "^4.0.7", + "@libp2p/peer-id-factory": "^4.0.7", + "@libp2p/tcp": "^9.0.16", + "@multiformats/multiaddr": "^12.1.14", "it-pipe": "^3.0.1", - "libp2p": "^0.46.6", + "libp2p": "^1.2.4", "sha3": "^2.1.4", "tslib": "^2.4.0" }, diff --git a/yarn-project/p2p/src/bootstrap/bootstrap.ts b/yarn-project/p2p/src/bootstrap/bootstrap.ts index 30145ff9d82..1e80f9ecc8b 100644 --- a/yarn-project/p2p/src/bootstrap/bootstrap.ts +++ b/yarn-project/p2p/src/bootstrap/bootstrap.ts @@ -1,99 +1,71 @@ import { createDebugLogger } from '@aztec/foundation/log'; -import { noise } from '@chainsafe/libp2p-noise'; -import { yamux } from '@chainsafe/libp2p-yamux'; -import type { ServiceMap } from '@libp2p/interface-libp2p'; -import { kadDHT } from '@libp2p/kad-dht'; -import { mplex } from '@libp2p/mplex'; -import { tcp } from '@libp2p/tcp'; -import { type Libp2p, type Libp2pOptions, type ServiceFactoryMap, createLibp2p } from 'libp2p'; -import { identifyService } from 'libp2p/identify'; -import { format } from 'util'; +import { Discv5, type Discv5EventEmitter } from '@chainsafe/discv5'; +import { SignableENR } from '@chainsafe/enr'; +import type { PeerId } from '@libp2p/interface'; +import { type Multiaddr, multiaddr } from '@multiformats/multiaddr'; import { type P2PConfig } from '../config.js'; import { createLibP2PPeerId } from '../service/index.js'; +/** + * Required P2P config values for a bootstrap node. + */ +export type BootNodeConfig = Partial & + Pick & + Required>; + /** * Encapsulates a 'Bootstrap' node, used for the purpose of assisting new joiners in acquiring peers. */ export class BootstrapNode { - private node?: Libp2p = undefined; + private node?: Discv5 = undefined; + private peerId?: PeerId; constructor(private logger = createDebugLogger('aztec:p2p_bootstrap')) {} /** * Starts the bootstrap node. - * @param config - The P2P configuration. + * @param config - A partial P2P configuration. No need for TCP values as well as aztec node specific values. * @returns An empty promise. */ - public async start(config: P2PConfig) { - const { peerIdPrivateKey, tcpListenIp, tcpListenPort, announceHostname, announcePort, minPeerCount, maxPeerCount } = - config; + public async start(config: BootNodeConfig) { + const { peerIdPrivateKey, udpListenIp, udpListenPort, announceHostname, announcePort } = config; const peerId = await createLibP2PPeerId(peerIdPrivateKey); - this.logger.info( - `Starting bootstrap node ${peerId} on ${tcpListenIp}:${tcpListenPort} announced at ${announceHostname}:${ - announcePort ?? tcpListenPort - }`, - ); + this.peerId = peerId; + const enr = SignableENR.createFromPeerId(peerId); - const opts: Libp2pOptions = { - start: false, - peerId, - addresses: { - listen: [`/ip4/${tcpListenIp}/tcp/${tcpListenPort}`], - announce: announceHostname ? [`${announceHostname}/tcp/${announcePort ?? tcpListenPort}`] : [], - }, - transports: [tcp()], - streamMuxers: [yamux(), mplex()], - connectionEncryption: [noise()], - connectionManager: { - minConnections: minPeerCount, - maxConnections: maxPeerCount, - }, - }; + const listenAddrUdp = multiaddr(`/ip4/${udpListenIp}/udp/${udpListenPort}`); + const publicAddr = multiaddr(`${announceHostname}/udp/${announcePort}`); + enr.setLocationMultiaddr(publicAddr); - const services: ServiceFactoryMap = { - identify: identifyService({ - protocolPrefix: 'aztec', - }), - kadDHT: kadDHT({ - protocolPrefix: 'aztec', - clientMode: false, - }), - // The autonat service seems quite problematic in that using it seems to cause a lot of attempts - // to dial ephemeral ports. I suspect that it works better if you can get the uPNPnat service to - // work as then you would have a permanent port to be dialled. - // Alas, I struggled to get this to work reliably either. - // autoNAT: autoNATService({ - // protocolPrefix: 'aztec', - // }), - }; + this.logger.info(`Starting bootstrap node ${peerId}, listening on ${listenAddrUdp.toString()}`); - this.node = await createLibp2p({ - ...opts, - services, + this.node = Discv5.create({ + enr, + peerId, + bindAddrs: { ip4: listenAddrUdp }, + config: { + lookupTimeout: 2000, + }, }); - await this.node.start(); - this.logger.debug(`lib p2p has started`); - - // print out listening addresses - this.logger.info('Listening on addresses:'); - this.node.getMultiaddrs().forEach(addr => { - this.logger.info(addr.toString()); + (this.node as Discv5EventEmitter).on('multiaddrUpdated', (addr: Multiaddr) => { + this.logger.info('Advertised socket address updated', { addr: addr.toString() }); }); - - this.node.addEventListener('peer:discovery', evt => { - this.logger.verbose(format('Discovered %s', evt.detail.id.toString())); // Log discovered peer + (this.node as Discv5EventEmitter).on('discovered', async (enr: SignableENR) => { + const addr = await enr.getFullMultiaddr('udp'); + this.logger.verbose(`Discovered new peer, enr: ${enr.encodeTxt()}, addr: ${addr?.toString()}`); }); - this.node.addEventListener('peer:connect', evt => { - this.logger.verbose(format('Connected to %s', evt.detail.toString())); // Log connected peer - }); + try { + await this.node.start(); + this.logger.info('Discv5 started'); + } catch (e) { + this.logger.error('Error starting Discv5', e); + } - this.node.addEventListener('peer:disconnect', evt => { - this.logger.verbose(format('Disconnected from %s', evt.detail.toString())); // Log connected peer - }); + this.logger.info(`ENR: ${this.node?.enr.encodeTxt()}`); } /** @@ -111,6 +83,16 @@ export class BootstrapNode { * @returns The node's peer Id */ public getPeerId() { - return this.node?.peerId; + if (!this.peerId) { + throw new Error('Node not started'); + } + return this.peerId; + } + + public getENR() { + if (!this.node) { + throw new Error('Node not started'); + } + return this.node?.enr.toENR(); } } diff --git a/yarn-project/p2p/src/client/index.ts b/yarn-project/p2p/src/client/index.ts index a31752544ef..366a199e79b 100644 --- a/yarn-project/p2p/src/client/index.ts +++ b/yarn-project/p2p/src/client/index.ts @@ -3,8 +3,9 @@ import { type AztecKVStore } from '@aztec/kv-store'; import { P2PClient } from '../client/p2p_client.js'; import { type P2PConfig } from '../config.js'; -import { DummyP2PService } from '../service/dummy_service.js'; -import { LibP2PService } from '../service/index.js'; +import { DiscV5Service } from '../service/discV5_service.js'; +import { DummyP2PService, DummyPeerDiscoveryService } from '../service/dummy_service.js'; +import { LibP2PService, createLibP2PPeerId } from '../service/index.js'; import { type TxPool } from '../tx_pool/index.js'; export * from './p2p_client.js'; @@ -15,6 +16,16 @@ export const createP2PClient = async ( txPool: TxPool, l2BlockSource: L2BlockSource, ) => { - const p2pService = config.p2pEnabled ? await LibP2PService.new(config, txPool) : new DummyP2PService(); + let discv5Service; + let p2pService; + if (config.p2pEnabled) { + // Create peer discovery service] + const peerId = await createLibP2PPeerId(config.peerIdPrivateKey); + discv5Service = new DiscV5Service(peerId, config); + p2pService = await LibP2PService.new(config, discv5Service, peerId, txPool, store); + } else { + p2pService = new DummyP2PService(); + discv5Service = new DummyPeerDiscoveryService(); + } return new P2PClient(store, l2BlockSource, txPool, p2pService); }; diff --git a/yarn-project/p2p/src/client/p2p_client.ts b/yarn-project/p2p/src/client/p2p_client.ts index 1320e741a08..fe3c58db602 100644 --- a/yarn-project/p2p/src/client/p2p_client.ts +++ b/yarn-project/p2p/src/client/p2p_client.ts @@ -4,7 +4,7 @@ import { createDebugLogger } from '@aztec/foundation/log'; import { type AztecKVStore, type AztecSingleton } from '@aztec/kv-store'; import { getP2PConfigEnvVars } from '../config.js'; -import { type P2PService } from '../service/service.js'; +import type { P2PService } from '../service/service.js'; import { type TxPool } from '../tx_pool/index.js'; /** diff --git a/yarn-project/p2p/src/config.ts b/yarn-project/p2p/src/config.ts index a995bcb8195..7b1e5e5682f 100644 --- a/yarn-project/p2p/src/config.ts +++ b/yarn-project/p2p/src/config.ts @@ -8,10 +8,15 @@ export interface P2PConfig { p2pEnabled: boolean; /** - * The frequency in which to check. + * The frequency in which to check for new L2 blocks. */ p2pBlockCheckIntervalMS: number; + /** + * The frequency in which to check for new peers. + */ + p2pPeerCheckIntervalMS: number; + /** * Size of queue of L2 blocks to store. */ @@ -27,6 +32,16 @@ export interface P2PConfig { */ tcpListenIp: string; + /** + * The udp port on which the P2P service should listen for connections. Used for Discv5 peer discovery. + */ + udpListenPort: number; + + /** + * The udp IP on which the P2P service should listen for connections. Used for Discv5 peer discovery. + */ + udpListenIp: string; + /** * An optional peer id private key. If blank, will generate a random key. */ @@ -52,11 +67,6 @@ export interface P2PConfig { */ announcePort?: number; - /** - * Optional specification to run as a client in the Kademlia routing protocol. - */ - clientKADRouting: boolean; - /** * Whether to enable NAT from libp2p (ignored for bootstrap node). */ @@ -71,6 +81,11 @@ export interface P2PConfig { * The maximum number of peers (a peer count above this will cause the node to refuse connection attempts) */ maxPeerCount: number; + + /** + * Data directory for peer & tx databases. + */ + dataDirectory?: string; } /** @@ -81,33 +96,39 @@ export function getP2PConfigEnvVars(): P2PConfig { const { P2P_ENABLED, P2P_BLOCK_CHECK_INTERVAL_MS, + P2P_PEER_CHECK_INTERVAL_MS, P2P_L2_BLOCK_QUEUE_SIZE, P2P_TCP_LISTEN_PORT, P2P_TCP_LISTEN_IP, + P2P_UDP_LISTEN_PORT, + P2P_UDP_LISTEN_IP, PEER_ID_PRIVATE_KEY, BOOTSTRAP_NODES, P2P_ANNOUNCE_HOSTNAME, P2P_ANNOUNCE_PORT, - P2P_KAD_CLIENT, P2P_NAT_ENABLED, P2P_MIN_PEERS, P2P_MAX_PEERS, + DATA_DIRECTORY, } = process.env; const envVars: P2PConfig = { p2pEnabled: P2P_ENABLED === 'true', p2pBlockCheckIntervalMS: P2P_BLOCK_CHECK_INTERVAL_MS ? +P2P_BLOCK_CHECK_INTERVAL_MS : 100, + p2pPeerCheckIntervalMS: P2P_PEER_CHECK_INTERVAL_MS ? +P2P_PEER_CHECK_INTERVAL_MS : 1000, p2pL2QueueSize: P2P_L2_BLOCK_QUEUE_SIZE ? +P2P_L2_BLOCK_QUEUE_SIZE : 1000, tcpListenPort: P2P_TCP_LISTEN_PORT ? +P2P_TCP_LISTEN_PORT : 40400, tcpListenIp: P2P_TCP_LISTEN_IP ? P2P_TCP_LISTEN_IP : '0.0.0.0', + udpListenPort: P2P_UDP_LISTEN_PORT ? +P2P_UDP_LISTEN_PORT : 40400, + udpListenIp: P2P_UDP_LISTEN_IP ? P2P_UDP_LISTEN_IP : '0.0.0.0', peerIdPrivateKey: PEER_ID_PRIVATE_KEY, bootstrapNodes: BOOTSTRAP_NODES ? BOOTSTRAP_NODES.split(',') : [], transactionProtocol: '', announceHostname: P2P_ANNOUNCE_HOSTNAME, announcePort: P2P_ANNOUNCE_PORT ? +P2P_ANNOUNCE_PORT : undefined, - clientKADRouting: P2P_KAD_CLIENT === 'true', enableNat: P2P_NAT_ENABLED === 'true', minPeerCount: P2P_MIN_PEERS ? +P2P_MIN_PEERS : 10, maxPeerCount: P2P_MAX_PEERS ? +P2P_MAX_PEERS : 100, + dataDirectory: DATA_DIRECTORY, }; return envVars; } diff --git a/yarn-project/p2p/src/service/discV5_service.ts b/yarn-project/p2p/src/service/discV5_service.ts new file mode 100644 index 00000000000..8c3024d8a0f --- /dev/null +++ b/yarn-project/p2p/src/service/discV5_service.ts @@ -0,0 +1,122 @@ +import { createDebugLogger } from '@aztec/foundation/log'; +import { RunningPromise } from '@aztec/foundation/running-promise'; + +import { Discv5, type Discv5EventEmitter } from '@chainsafe/discv5'; +import { type ENR, SignableENR } from '@chainsafe/enr'; +import type { PeerId } from '@libp2p/interface'; +import { multiaddr } from '@multiformats/multiaddr'; +import EventEmitter from 'events'; + +import type { P2PConfig } from '../config.js'; +import type { PeerDiscoveryService } from './service.js'; + +export enum PeerDiscoveryState { + RUNNING = 'running', + STOPPED = 'stopped', +} + +/** + * Peer discovery service using Discv5. + */ +export class DiscV5Service extends EventEmitter implements PeerDiscoveryService { + /** The Discv5 instance */ + private discv5: Discv5; + + /** This instance's ENR */ + private enr: SignableENR; + + /** The interval for checking for new peers */ + private discoveryInterval: NodeJS.Timeout | null = null; + + private runningPromise: RunningPromise; + + private currentState = PeerDiscoveryState.STOPPED; + + constructor(private peerId: PeerId, config: P2PConfig, private logger = createDebugLogger('aztec:discv5_service')) { + super(); + const { announceHostname, tcpListenPort, udpListenIp, udpListenPort, bootstrapNodes } = config; + // create ENR from PeerId + this.enr = SignableENR.createFromPeerId(peerId); + + const multiAddrUdp = multiaddr(`${announceHostname}/udp/${udpListenPort}/p2p/${peerId.toString()}`); + const multiAddrTcp = multiaddr(`${announceHostname}/tcp/${tcpListenPort}/p2p/${peerId.toString()}`); + + const listenMultiAddrUdp = multiaddr(`/ip4/${udpListenIp}/udp/${udpListenPort}`); + + // set location multiaddr in ENR record + this.enr.setLocationMultiaddr(multiAddrUdp); + this.enr.setLocationMultiaddr(multiAddrTcp); + + this.discv5 = Discv5.create({ + enr: this.enr, + peerId, + bindAddrs: { ip4: listenMultiAddrUdp }, + config: { + lookupTimeout: 2000, + }, + }); + + this.logger.info(`ENR NodeId: ${this.enr.nodeId}`); + this.logger.info(`ENR UDP: ${multiAddrUdp.toString()}`); + + (this.discv5 as Discv5EventEmitter).on('discovered', (enr: ENR) => this.onDiscovered(enr)); + (this.discv5 as Discv5EventEmitter).on('enrAdded', async (enr: ENR) => { + const multiAddrTcp = await enr.getFullMultiaddr('tcp'); + const multiAddrUdp = await enr.getFullMultiaddr('udp'); + this.logger.debug(`ENR multiaddr: ${multiAddrTcp?.toString()}, ${multiAddrUdp?.toString()}`); + }); + + // Add bootnode ENR if provided + if (bootstrapNodes?.length) { + this.logger.info(`Adding bootstrap ENRs: ${bootstrapNodes.join(', ')}`); + try { + bootstrapNodes.forEach(enr => { + this.discv5.addEnr(enr); + }); + } catch (e) { + this.logger.error(`Error adding bootnode ENRs: ${e}`); + } + } + + this.runningPromise = new RunningPromise(async () => { + await this.discv5.findRandomNode(); + }, config.p2pPeerCheckIntervalMS); + } + + public async start(): Promise { + if (this.currentState === PeerDiscoveryState.RUNNING) { + throw new Error('DiscV5Service already started'); + } + this.logger.info('Starting DiscV5'); + await this.discv5.start(); + this.logger.info('DiscV5 started'); + this.currentState = PeerDiscoveryState.RUNNING; + this.runningPromise.start(); + } + + public getAllPeers(): ENR[] { + return this.discv5.kadValues(); + } + + public getEnr(): ENR { + return this.enr.toENR(); + } + + public getPeerId(): PeerId { + return this.peerId; + } + + public getStatus(): PeerDiscoveryState { + return this.currentState; + } + + public async stop(): Promise { + await this.runningPromise.stop(); + await this.discv5.stop(); + this.currentState = PeerDiscoveryState.STOPPED; + } + + private onDiscovered(enr: ENR) { + this.emit('peer:discovered', enr); + } +} diff --git a/yarn-project/p2p/src/service/discv5_service.test.ts b/yarn-project/p2p/src/service/discv5_service.test.ts new file mode 100644 index 00000000000..974ca9c0238 --- /dev/null +++ b/yarn-project/p2p/src/service/discv5_service.test.ts @@ -0,0 +1,101 @@ +import { sleep } from '@aztec/foundation/sleep'; + +import type { PeerId } from '@libp2p/interface'; + +import { BootstrapNode } from '../bootstrap/bootstrap.js'; +import { DiscV5Service, PeerDiscoveryState } from './discV5_service.js'; +import { createLibP2PPeerId } from './libp2p_service.js'; + +describe('Discv5Service', () => { + let bootNode: BootstrapNode; + let bootNodePeerId: PeerId; + let port = 1234; + const baseConfig = { + announceHostname: '/ip4/127.0.0.1', + announcePort: port, + tcpListenPort: port, + udpListenIp: '0.0.0.0', + udpListenPort: port, + minPeerCount: 1, + maxPeerCount: 100, + }; + + beforeEach(async () => { + bootNode = new BootstrapNode(); + await bootNode.start(baseConfig); + bootNodePeerId = bootNode.getPeerId(); + }); + + afterEach(async () => { + await bootNode.stop(); + }); + + it('should initialize with default values', async () => { + port++; + const node = await createNode(port); + const peers = node.getAllPeers(); + const bootnode = peers[0]; + expect((await bootnode.peerId()).toString()).toEqual(bootNodePeerId.toString()); + expect(node.getStatus()).toEqual(PeerDiscoveryState.STOPPED); // not started yet + await node.start(); + expect(node.getStatus()).toEqual(PeerDiscoveryState.RUNNING); + }); + + it('should discover & add a peer', async () => { + port++; + const node1 = await createNode(port); + port++; + const node2 = await createNode(port); + await node1.start(); + await node2.start(); + await sleep(100); + const node1Peers = await Promise.all(node1.getAllPeers().map(async peer => (await peer.peerId()).toString())); + const node2Peers = await Promise.all(node2.getAllPeers().map(async peer => (await peer.peerId()).toString())); + + expect(node1Peers).toHaveLength(2); + expect(node2Peers).toHaveLength(2); + expect(node1Peers).toContain(node2.getPeerId().toString()); + expect(node2Peers).toContain(node1.getPeerId().toString()); + + await node1.stop(); + await node2.stop(); + }); + + it('should persist peers without bootnode', async () => { + port++; + const node1 = await createNode(port); + port++; + const node2 = await createNode(port); + await node1.start(); + await node2.start(); + await sleep(100); + + await node2.stop(); + await bootNode.stop(); + + await node2.start(); + await sleep(100); + + const node2Peers = await Promise.all(node2.getAllPeers().map(async peer => (await peer.peerId()).toString())); + expect(node2Peers).toHaveLength(1); + expect(node2Peers).toContain(node1.getPeerId().toString()); + }); + + const createNode = async (port: number) => { + const peerId = await createLibP2PPeerId(); + const config = { + ...baseConfig, + tcpListenIp: '0.0.0.0', + bootstrapNodes: [bootNode.getENR().encodeTxt()], + tcpListenPort: port, + udpListenPort: port, + announcePort: port, + p2pBlockCheckIntervalMS: 50, + p2pPeerCheckIntervalMS: 50, + transactionProtocol: 'aztec/1.0.0', + p2pEnabled: true, + p2pL2QueueSize: 100, + }; + return new DiscV5Service(peerId, config); + }; +}); diff --git a/yarn-project/p2p/src/service/dummy_service.ts b/yarn-project/p2p/src/service/dummy_service.ts index aff96c9cdf8..d6da8ba8361 100644 --- a/yarn-project/p2p/src/service/dummy_service.ts +++ b/yarn-project/p2p/src/service/dummy_service.ts @@ -1,6 +1,8 @@ import { type Tx, type TxHash } from '@aztec/circuit-types'; -import { type P2PService } from './service.js'; +import EventEmitter from 'events'; + +import type { P2PService, PeerDiscoveryService } from './service.js'; /** * A dummy implementation of the P2P Service. @@ -34,3 +36,30 @@ export class DummyP2PService implements P2PService { */ public settledTxs(_: TxHash[]) {} } + +/** + * A dummy implementation of the Peer Discovery Service. + */ +export class DummyPeerDiscoveryService extends EventEmitter implements PeerDiscoveryService { + /** + * Starts the dummy implementation. + * @returns A resolved promise. + */ + public start() { + return Promise.resolve(); + } + /** + * Stops the dummy implementation. + * @returns A resolved promise. + */ + public stop() { + return Promise.resolve(); + } + /** + * Called to discover peers in the network. + * @returns An array of discovered peer addresses. + */ + public getAllPeers() { + return []; + } +} diff --git a/yarn-project/p2p/src/service/known_txs.test.ts b/yarn-project/p2p/src/service/known_txs.test.ts index a0c2772feec..7c93b085320 100644 --- a/yarn-project/p2p/src/service/known_txs.test.ts +++ b/yarn-project/p2p/src/service/known_txs.test.ts @@ -1,7 +1,7 @@ import { randomTxHash } from '@aztec/circuit-types'; import { expect } from '@jest/globals'; -import { type Ed25519PeerId, type PeerId } from '@libp2p/interface-peer-id'; +import type { Ed25519PeerId, PeerId } from '@libp2p/interface'; import { mock } from 'jest-mock-extended'; import { KnownTxLookup } from './known_txs.js'; diff --git a/yarn-project/p2p/src/service/known_txs.ts b/yarn-project/p2p/src/service/known_txs.ts index 6ee37d7d697..d25c866aebe 100644 --- a/yarn-project/p2p/src/service/known_txs.ts +++ b/yarn-project/p2p/src/service/known_txs.ts @@ -1,4 +1,4 @@ -import { type PeerId } from '@libp2p/interface-peer-id'; +import { type PeerId } from '@libp2p/interface'; /** * Keeps a record of which Peers have 'seen' which transactions. diff --git a/yarn-project/p2p/src/service/libp2p_service.ts b/yarn-project/p2p/src/service/libp2p_service.ts index 9c7974e3410..e9ca39f234f 100644 --- a/yarn-project/p2p/src/service/libp2p_service.ts +++ b/yarn-project/p2p/src/service/libp2p_service.ts @@ -1,25 +1,27 @@ import { type Tx, type TxHash } from '@aztec/circuit-types'; import { SerialQueue } from '@aztec/foundation/fifo'; import { createDebugLogger } from '@aztec/foundation/log'; +import { type AztecKVStore } from '@aztec/kv-store'; +import { ENR } from '@chainsafe/enr'; import { noise } from '@chainsafe/libp2p-noise'; import { yamux } from '@chainsafe/libp2p-yamux'; -import { bootstrap } from '@libp2p/bootstrap'; +import { identify } from '@libp2p/identify'; +import type { IncomingStreamData, PeerId, Stream } from '@libp2p/interface'; import type { ServiceMap } from '@libp2p/interface-libp2p'; -import { type PeerId } from '@libp2p/interface-peer-id'; -import { type IncomingStreamData } from '@libp2p/interface/stream-handler'; -import { type DualKadDHT, kadDHT } from '@libp2p/kad-dht'; +import '@libp2p/kad-dht'; import { mplex } from '@libp2p/mplex'; +import { peerIdFromString } from '@libp2p/peer-id'; import { createFromJSON, createSecp256k1PeerId, exportToProtobuf } from '@libp2p/peer-id-factory'; import { tcp } from '@libp2p/tcp'; import { pipe } from 'it-pipe'; import { type Libp2p, type Libp2pOptions, type ServiceFactoryMap, createLibp2p } from 'libp2p'; -import { identifyService } from 'libp2p/identify'; import { type P2PConfig } from '../config.js'; import { type TxPool } from '../tx_pool/index.js'; import { KnownTxLookup } from './known_txs.js'; -import { type P2PService } from './service.js'; +import { AztecPeerDb, type AztecPeerStore } from './peer_store.js'; +import type { P2PService, PeerDiscoveryService } from './service.js'; import { Messages, createGetTransactionsRequestMessage, @@ -65,8 +67,11 @@ export class LibP2PService implements P2PService { constructor( private config: P2PConfig, private node: Libp2p, + private peerDiscoveryService: PeerDiscoveryService, + private peerStore: AztecPeerStore, private protocolId: string, private txPool: TxPool, + private bootstrapPeerIds: PeerId[] = [], private logger = createDebugLogger('aztec:libp2p_service'), ) {} @@ -75,7 +80,7 @@ export class LibP2PService implements P2PService { * @returns An empty promise. */ public async start() { - if (this.node.isStarted()) { + if (this.node.status === 'started') { throw new Error('P2P service already started'); } const { enableNat, tcpListenIp, tcpListenPort, announceHostname, announcePort } = this.config; @@ -87,6 +92,11 @@ export class LibP2PService implements P2PService { this.logger.info(`Enabling NAT in libp2p module`); } + // handle discovered peers from external discovery service + this.peerDiscoveryService.on('peer:discovered', async (enr: ENR) => { + await this.addPeer(enr); + }); + this.node.addEventListener('peer:discovery', evt => { const peerId = evt.detail.id; if (this.isBootstrapPeer(peerId)) { @@ -109,12 +119,12 @@ export class LibP2PService implements P2PService { }); this.jobQueue.start(); + await this.peerDiscoveryService.start(); await this.node.start(); await this.node.handle(this.protocolId, (incoming: IncomingStreamData) => this.jobQueue.put(() => Promise.resolve(this.handleProtocolDial(incoming))), ); - const dht = this.node.services['kadDHT'] as DualKadDHT; - this.logger.info(`Started P2P client as ${await dht.getMode()} with Peer ID ${this.node.peerId.toString()}`); + this.logger.info(`Started P2P client with Peer ID ${this.node.peerId.toString()}`); } /** @@ -135,25 +145,19 @@ export class LibP2PService implements P2PService { * @param txPool - The transaction pool to be accessed by the service. * @returns The new service. */ - public static async new(config: P2PConfig, txPool: TxPool) { - const { - tcpListenIp, - tcpListenPort, - announceHostname, - announcePort, - clientKADRouting, - minPeerCount, - maxPeerCount, - peerIdPrivateKey, - } = config; - const peerId = await createLibP2PPeerId(peerIdPrivateKey); - + public static async new( + config: P2PConfig, + peerDiscoveryService: PeerDiscoveryService, + peerId: PeerId, + txPool: TxPool, + store: AztecKVStore, + ) { + const { tcpListenIp, tcpListenPort, minPeerCount, maxPeerCount } = config; const opts: Libp2pOptions = { start: false, peerId, addresses: { listen: [`/ip4/${tcpListenIp}/tcp/${tcpListenPort}`], - announce: announceHostname ? [`${announceHostname}/tcp/${announcePort ?? tcpListenPort}`] : [], }, transports: [tcp()], streamMuxers: [yamux(), mplex()], @@ -162,21 +166,12 @@ export class LibP2PService implements P2PService { minConnections: minPeerCount, maxConnections: maxPeerCount, }, - peerDiscovery: [ - bootstrap({ - list: config.bootstrapNodes, - }), - ], }; const services: ServiceFactoryMap = { - identify: identifyService({ + identify: identify({ protocolPrefix: 'aztec', }), - kadDHT: kadDHT({ - protocolPrefix: 'aztec', - clientMode: clientKADRouting, - }), }; // The autonat service seems quite problematic in that using it seems to cause a lot of attempts @@ -198,7 +193,19 @@ export class LibP2PService implements P2PService { services, }); const protocolId = config.transactionProtocol; - return new LibP2PService(config, node, protocolId, txPool); + + // Create an LMDB peer store + const peerDb = new AztecPeerDb(store); + + // extract bootstrap node peer IDs + let bootstrapPeerIds: PeerId[] = []; + if (config.bootstrapNodes.length) { + bootstrapPeerIds = await Promise.all( + config.bootstrapNodes.map(bootnodeEnr => ENR.decodeTxt(bootnodeEnr).peerId()), + ); + } + + return new LibP2PService(config, node, peerDiscoveryService, peerDb, protocolId, txPool, bootstrapPeerIds); } /** @@ -217,6 +224,44 @@ export class LibP2PService implements P2PService { this.knownTxLookup.handleSettledTxs(txHashes.map(x => x.toString())); } + private async addPeer(enr: ENR) { + const peerMultiAddr = await enr.getFullMultiaddr('tcp'); + if (!peerMultiAddr) { + // No TCP address, can't connect + return; + } + const peerIdStr = peerMultiAddr.getPeerId(); + + if (!peerIdStr) { + this.logger.debug(`Peer ID not found in discovered node's multiaddr: ${peerMultiAddr}`); + return; + } + + // check if peer is already known + const peerId = peerIdFromString(peerIdStr); + const hasPeer = await this.node.peerStore.has(peerId); + + // add to peer store if not already known + if (!hasPeer) { + this.logger.info(`Discovered peer ${enr.peerId().toString()}. Adding to libp2p peer list`); + let stream: Stream | undefined; + try { + stream = await this.node.dialProtocol(peerMultiAddr, this.protocolId); + + // dial successful, add to DB as well + if (!this.peerStore.getPeer(peerIdStr)) { + await this.peerStore.addPeer(peerIdStr, enr); + } + } catch (err) { + this.logger.error(`Failed to dial peer ${peerIdStr}`, err); + } finally { + if (stream) { + await stream.close(); + } + } + } + } + private async handleProtocolDial(incomingStreamData: IncomingStreamData) { try { const { message, peer } = await this.consumeInboundStream(incomingStreamData); @@ -392,6 +437,6 @@ export class LibP2PService implements P2PService { } private isBootstrapPeer(peer: PeerId) { - return this.config.bootstrapNodes.findIndex(bootstrap => bootstrap.includes(peer.toString())) != -1; + return this.bootstrapPeerIds.some(bootstrapPeer => bootstrapPeer.equals(peer)); } } diff --git a/yarn-project/p2p/src/service/peer_store.ts b/yarn-project/p2p/src/service/peer_store.ts new file mode 100644 index 00000000000..9644e4b47ff --- /dev/null +++ b/yarn-project/p2p/src/service/peer_store.ts @@ -0,0 +1,36 @@ +import type { AztecKVStore, AztecMap } from '@aztec/kv-store'; + +import type { ENR } from '@chainsafe/enr'; + +export interface AztecPeerStore { + addPeer(peerId: string, enr: ENR): Promise; + removePeer(peerId: string): Promise; + getPeer(peerId: string): ENR | undefined; + getAllPeers(): IterableIterator; +} + +export class AztecPeerDb implements AztecPeerStore { + #peers: AztecMap; + + constructor(private db: AztecKVStore) { + this.#peers = db.openMap('p2p_peers'); + } + + async addPeer(peerId: string, enr: ENR): Promise { + void (await this.#peers.set(peerId, enr)); + } + + async removePeer(peerId: string): Promise { + void (await this.#peers.delete(peerId)); + } + + getPeer(peerId: string): ENR | undefined { + return this.#peers.get(peerId); + } + + *getAllPeers(): IterableIterator { + for (const enr of this.#peers.values()) { + yield enr; + } + } +} diff --git a/yarn-project/p2p/src/service/service.ts b/yarn-project/p2p/src/service/service.ts index fc9580d9b6d..645b1eb80d0 100644 --- a/yarn-project/p2p/src/service/service.ts +++ b/yarn-project/p2p/src/service/service.ts @@ -1,4 +1,7 @@ -import { type Tx, type TxHash } from '@aztec/circuit-types'; +import type { Tx, TxHash } from '@aztec/circuit-types'; + +import type { ENR } from '@chainsafe/enr'; +import type EventEmitter from 'events'; /** * The interface for a P2P service implementation. @@ -28,3 +31,30 @@ export interface P2PService { */ settledTxs(txHashes: TxHash[]): void; } + +/** + * The interface for a peer discovery service implementation. + */ +export interface PeerDiscoveryService extends EventEmitter { + /** + * Starts the service. + * */ + start(): Promise; + + /** + * Stops the service. + * */ + stop(): Promise; + + /** + * Gets all peers. + * @returns An array of peer ENRs. + */ + getAllPeers(): ENR[]; + + /** + * Event emitted when a new peer is discovered. + */ + on(event: 'peer:discovered', listener: (enr: ENR) => void): this; + emit(event: 'peer:discovered', enr: ENR): boolean; +} diff --git a/yarn-project/yarn.lock b/yarn-project/yarn.lock index 65368a59d0d..01b7cd8f4e7 100644 --- a/yarn-project/yarn.lock +++ b/yarn-project/yarn.lock @@ -12,34 +12,6 @@ __metadata: languageName: node linkType: hard -"@achingbrain/nat-port-mapper@npm:^1.0.9": - version: 1.0.13 - resolution: "@achingbrain/nat-port-mapper@npm:1.0.13" - dependencies: - "@achingbrain/ssdp": ^4.0.1 - "@libp2p/logger": ^4.0.1 - default-gateway: ^7.2.2 - err-code: ^3.0.1 - it-first: ^3.0.1 - p-defer: ^4.0.0 - p-timeout: ^6.1.1 - xml2js: ^0.6.0 - checksum: 0ece5a52be65fcb26e75918c39a5dad76a7752103bb32686e564e4c8f10e658e80e0e0d82acca6653cff4bac938faae06d71ceaef7a38916b9928b68a78c2c2b - languageName: node - linkType: hard - -"@achingbrain/ssdp@npm:^4.0.1": - version: 4.0.6 - resolution: "@achingbrain/ssdp@npm:4.0.6" - dependencies: - event-iterator: ^2.0.0 - freeport-promise: ^2.0.0 - merge-options: ^3.0.4 - xml2js: ^0.6.2 - checksum: 18af3ebf0ddd331531730b3c998729cb3db8f915b7f8296e503babf813a42af284e62b271148ac3ac85aa2420bb1c813c2d3b661c90e75f2e6d8700f9302f50b - languageName: node - linkType: hard - "@adraffy/ens-normalize@npm:1.10.0": version: 1.10.0 resolution: "@adraffy/ens-normalize@npm:1.10.0" @@ -48,12 +20,12 @@ __metadata: linkType: hard "@ampproject/remapping@npm:^2.2.0": - version: 2.2.1 - resolution: "@ampproject/remapping@npm:2.2.1" + version: 2.3.0 + resolution: "@ampproject/remapping@npm:2.3.0" dependencies: - "@jridgewell/gen-mapping": ^0.3.0 - "@jridgewell/trace-mapping": ^0.3.9 - checksum: 03c04fd526acc64a1f4df22651186f3e5ef0a9d6d6530ce4482ec9841269cf7a11dbb8af79237c282d721c5312024ff17529cd72cc4768c11e999b58e2302079 + "@jridgewell/gen-mapping": ^0.3.5 + "@jridgewell/trace-mapping": ^0.3.24 + checksum: d3ad7b89d973df059c4e8e6d7c972cbeb1bb2f18f002a3bd04ae0707da214cb06cc06929b65aa2313b9347463df2914772298bae8b1d7973f246bb3f2ab3e8f0 languageName: node linkType: hard @@ -655,24 +627,28 @@ __metadata: "@aztec/circuits.js": "workspace:^" "@aztec/foundation": "workspace:^" "@aztec/kv-store": "workspace:^" - "@chainsafe/libp2p-noise": ^13.0.0 - "@chainsafe/libp2p-yamux": ^5.0.0 + "@chainsafe/discv5": ^9.0.0 + "@chainsafe/enr": ^3.0.0 + "@chainsafe/libp2p-noise": ^15.0.0 + "@chainsafe/libp2p-yamux": ^6.0.2 "@jest/globals": ^29.5.0 "@libp2p/bootstrap": ^9.0.4 - "@libp2p/interface": ^0.1.2 + "@libp2p/crypto": ^4.0.3 + "@libp2p/identify": ^1.0.15 + "@libp2p/interface": ^1.1.4 "@libp2p/interface-libp2p": ^3.2.0 - "@libp2p/interface-peer-id": ^2.0.2 "@libp2p/kad-dht": ^10.0.4 - "@libp2p/mplex": ^9.0.4 - "@libp2p/peer-id": ^3.0.2 - "@libp2p/peer-id-factory": ^3.0.3 - "@libp2p/tcp": ^8.0.4 + "@libp2p/mplex": ^10.0.16 + "@libp2p/peer-id": ^4.0.7 + "@libp2p/peer-id-factory": ^4.0.7 + "@libp2p/tcp": ^9.0.16 + "@multiformats/multiaddr": ^12.1.14 "@types/jest": ^29.5.0 "@types/node": ^18.14.6 it-pipe: ^3.0.1 jest: ^29.5.0 jest-mock-extended: ^3.0.4 - libp2p: ^0.46.6 + libp2p: ^1.2.4 sha3: ^2.1.4 ts-node: ^10.9.1 tslib: ^2.4.0 @@ -918,43 +894,43 @@ __metadata: languageName: unknown linkType: soft -"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.22.13, @babel/code-frame@npm:^7.23.5": - version: 7.23.5 - resolution: "@babel/code-frame@npm:7.23.5" +"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.22.13, @babel/code-frame@npm:^7.23.5, @babel/code-frame@npm:^7.24.1, @babel/code-frame@npm:^7.24.2": + version: 7.24.2 + resolution: "@babel/code-frame@npm:7.24.2" dependencies: - "@babel/highlight": ^7.23.4 - chalk: ^2.4.2 - checksum: d90981fdf56a2824a9b14d19a4c0e8db93633fd488c772624b4e83e0ceac6039a27cd298a247c3214faa952bf803ba23696172ae7e7235f3b97f43ba278c569a + "@babel/highlight": ^7.24.2 + picocolors: ^1.0.0 + checksum: 70e867340cfe09ca5488b2f36372c45cabf43c79a5b6426e6df5ef0611ff5dfa75a57dda841895693de6008f32c21a7c97027a8c7bcabd63a7d17416cbead6f8 languageName: node linkType: hard "@babel/compat-data@npm:^7.23.5": - version: 7.23.5 - resolution: "@babel/compat-data@npm:7.23.5" - checksum: 06ce244cda5763295a0ea924728c09bae57d35713b675175227278896946f922a63edf803c322f855a3878323d48d0255a2a3023409d2a123483c8a69ebb4744 + version: 7.24.4 + resolution: "@babel/compat-data@npm:7.24.4" + checksum: 52ce371658dc7796c9447c9cb3b9c0659370d141b76997f21c5e0028cca4d026ca546b84bc8d157ce7ca30bd353d89f9238504eb8b7aefa9b1f178b4c100c2d4 languageName: node linkType: hard -"@babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3": - version: 7.23.9 - resolution: "@babel/core@npm:7.23.9" +"@babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3, @babel/core@npm:^7.23.9": + version: 7.24.4 + resolution: "@babel/core@npm:7.24.4" dependencies: "@ampproject/remapping": ^2.2.0 - "@babel/code-frame": ^7.23.5 - "@babel/generator": ^7.23.6 + "@babel/code-frame": ^7.24.2 + "@babel/generator": ^7.24.4 "@babel/helper-compilation-targets": ^7.23.6 "@babel/helper-module-transforms": ^7.23.3 - "@babel/helpers": ^7.23.9 - "@babel/parser": ^7.23.9 - "@babel/template": ^7.23.9 - "@babel/traverse": ^7.23.9 - "@babel/types": ^7.23.9 + "@babel/helpers": ^7.24.4 + "@babel/parser": ^7.24.4 + "@babel/template": ^7.24.0 + "@babel/traverse": ^7.24.1 + "@babel/types": ^7.24.0 convert-source-map: ^2.0.0 debug: ^4.1.0 gensync: ^1.0.0-beta.2 json5: ^2.2.3 semver: ^6.3.1 - checksum: 634a511f74db52a5f5a283c1121f25e2227b006c095b84a02a40a9213842489cd82dc7d61cdc74e10b5bcd9bb0a4e28bab47635b54c7e2256d47ab57356e2a76 + checksum: 15ecad7581f3329995956ba461961b1af7bed48901f14fe962ccd3217edca60049e9e6ad4ce48134618397e6c90230168c842e2c28e47ef1f16c97dbbf663c61 languageName: node linkType: hard @@ -969,15 +945,15 @@ __metadata: languageName: node linkType: hard -"@babel/generator@npm:^7.23.0, @babel/generator@npm:^7.23.6, @babel/generator@npm:^7.7.2": - version: 7.23.6 - resolution: "@babel/generator@npm:7.23.6" +"@babel/generator@npm:^7.23.0, @babel/generator@npm:^7.24.1, @babel/generator@npm:^7.24.4, @babel/generator@npm:^7.7.2": + version: 7.24.4 + resolution: "@babel/generator@npm:7.24.4" dependencies: - "@babel/types": ^7.23.6 - "@jridgewell/gen-mapping": ^0.3.2 - "@jridgewell/trace-mapping": ^0.3.17 + "@babel/types": ^7.24.0 + "@jridgewell/gen-mapping": ^0.3.5 + "@jridgewell/trace-mapping": ^0.3.25 jsesc: ^2.5.1 - checksum: 1a1a1c4eac210f174cd108d479464d053930a812798e09fee069377de39a893422df5b5b146199ead7239ae6d3a04697b45fc9ac6e38e0f6b76374390f91fc6c + checksum: 1b6146c31386c9df3eb594a2c36b5c98da4f67f7c06edb3d68a442b92516b21bb5ba3ad7dbe0058fe76625ed24d66923e15c95b0df75ef1907d4068921a699b8 languageName: node linkType: hard @@ -1021,11 +997,11 @@ __metadata: linkType: hard "@babel/helper-module-imports@npm:^7.22.15": - version: 7.22.15 - resolution: "@babel/helper-module-imports@npm:7.22.15" + version: 7.24.3 + resolution: "@babel/helper-module-imports@npm:7.24.3" dependencies: - "@babel/types": ^7.22.15 - checksum: ecd7e457df0a46f889228f943ef9b4a47d485d82e030676767e6a2fdcbdaa63594d8124d4b55fd160b41c201025aec01fc27580352b1c87a37c9c6f33d116702 + "@babel/types": ^7.24.0 + checksum: c23492189ba97a1ec7d37012336a5661174e8b88194836b6bbf90d13c3b72c1db4626263c654454986f924c6da8be7ba7f9447876d709cd00bd6ffde6ec00796 languageName: node linkType: hard @@ -1044,10 +1020,10 @@ __metadata: languageName: node linkType: hard -"@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.10.4, @babel/helper-plugin-utils@npm:^7.12.13, @babel/helper-plugin-utils@npm:^7.14.5, @babel/helper-plugin-utils@npm:^7.22.5, @babel/helper-plugin-utils@npm:^7.8.0": - version: 7.22.5 - resolution: "@babel/helper-plugin-utils@npm:7.22.5" - checksum: c0fc7227076b6041acd2f0e818145d2e8c41968cc52fb5ca70eed48e21b8fe6dd88a0a91cbddf4951e33647336eb5ae184747ca706817ca3bef5e9e905151ff5 +"@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.10.4, @babel/helper-plugin-utils@npm:^7.12.13, @babel/helper-plugin-utils@npm:^7.14.5, @babel/helper-plugin-utils@npm:^7.24.0, @babel/helper-plugin-utils@npm:^7.8.0": + version: 7.24.0 + resolution: "@babel/helper-plugin-utils@npm:7.24.0" + checksum: e2baa0eede34d2fa2265947042aa84d444aa48dc51e9feedea55b67fc1bc3ab051387e18b33ca7748285a6061390831ab82f8a2c767d08470b93500ec727e9b9 languageName: node linkType: hard @@ -1070,9 +1046,9 @@ __metadata: linkType: hard "@babel/helper-string-parser@npm:^7.23.4": - version: 7.23.4 - resolution: "@babel/helper-string-parser@npm:7.23.4" - checksum: c0641144cf1a7e7dc93f3d5f16d5327465b6cf5d036b48be61ecba41e1eece161b48f46b7f960951b67f8c3533ce506b16dece576baef4d8b3b49f8c65410f90 + version: 7.24.1 + resolution: "@babel/helper-string-parser@npm:7.24.1" + checksum: 8404e865b06013979a12406aab4c0e8d2e377199deec09dfe9f57b833b0c9ce7b6e8c1c553f2da8d0bcd240c5005bd7a269f4fef0d628aeb7d5fe035c436fb67 languageName: node linkType: hard @@ -1090,34 +1066,35 @@ __metadata: languageName: node linkType: hard -"@babel/helpers@npm:^7.23.9": - version: 7.23.9 - resolution: "@babel/helpers@npm:7.23.9" +"@babel/helpers@npm:^7.24.4": + version: 7.24.4 + resolution: "@babel/helpers@npm:7.24.4" dependencies: - "@babel/template": ^7.23.9 - "@babel/traverse": ^7.23.9 - "@babel/types": ^7.23.9 - checksum: 2678231192c0471dbc2fc403fb19456cc46b1afefcfebf6bc0f48b2e938fdb0fef2e0fe90c8c8ae1f021dae5012b700372e4b5d15867f1d7764616532e4a6324 + "@babel/template": ^7.24.0 + "@babel/traverse": ^7.24.1 + "@babel/types": ^7.24.0 + checksum: ecd2dc0b3b32e24b97fa3bcda432dd3235b77c2be1e16eafc35b8ef8f6c461faa99796a8bc2431a408c98b4aabfd572c160e2b67ecea4c5c9dd3a8314a97994a languageName: node linkType: hard -"@babel/highlight@npm:^7.23.4": - version: 7.23.4 - resolution: "@babel/highlight@npm:7.23.4" +"@babel/highlight@npm:^7.24.2": + version: 7.24.2 + resolution: "@babel/highlight@npm:7.24.2" dependencies: "@babel/helper-validator-identifier": ^7.22.20 chalk: ^2.4.2 js-tokens: ^4.0.0 - checksum: 643acecdc235f87d925979a979b539a5d7d1f31ae7db8d89047269082694122d11aa85351304c9c978ceeb6d250591ccadb06c366f358ccee08bb9c122476b89 + picocolors: ^1.0.0 + checksum: 5f17b131cc3ebf3ab285a62cf98a404aef1bd71a6be045e748f8d5bf66d6a6e1aefd62f5972c84369472e8d9f22a614c58a89cd331eb60b7ba965b31b1bbeaf5 languageName: node linkType: hard -"@babel/parser@npm:^7.0.0, @babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.5, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.21.4, @babel/parser@npm:^7.23.0, @babel/parser@npm:^7.23.9": - version: 7.23.9 - resolution: "@babel/parser@npm:7.23.9" +"@babel/parser@npm:^7.0.0, @babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.5, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.21.4, @babel/parser@npm:^7.23.0, @babel/parser@npm:^7.23.9, @babel/parser@npm:^7.24.0, @babel/parser@npm:^7.24.1, @babel/parser@npm:^7.24.4": + version: 7.24.4 + resolution: "@babel/parser@npm:7.24.4" bin: parser: ./bin/babel-parser.js - checksum: e7cd4960ac8671774e13803349da88d512f9292d7baa952173260d3e8f15620a28a3701f14f709d769209022f9e7b79965256b8be204fc550cfe783cdcabe7c7 + checksum: 94c9e3e592894cd6fc57c519f4e06b65463df9be5f01739bb0d0bfce7ffcf99b3c2fdadd44dc59cc858ba2739ce6e469813a941c2f2dfacf333a3b2c9c5c8465 languageName: node linkType: hard @@ -1177,13 +1154,13 @@ __metadata: linkType: hard "@babel/plugin-syntax-jsx@npm:^7.7.2": - version: 7.23.3 - resolution: "@babel/plugin-syntax-jsx@npm:7.23.3" + version: 7.24.1 + resolution: "@babel/plugin-syntax-jsx@npm:7.24.1" dependencies: - "@babel/helper-plugin-utils": ^7.22.5 + "@babel/helper-plugin-utils": ^7.24.0 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 89037694314a74e7f0e7a9c8d3793af5bf6b23d80950c29b360db1c66859d67f60711ea437e70ad6b5b4b29affe17eababda841b6c01107c2b638e0493bafb4e + checksum: 712f7e7918cb679f106769f57cfab0bc99b311032665c428b98f4c3e2e6d567601d45386a4f246df6a80d741e1f94192b3f008800d66c4f1daae3ad825c243f0 languageName: node linkType: hard @@ -1265,33 +1242,33 @@ __metadata: linkType: hard "@babel/plugin-syntax-typescript@npm:^7.7.2": - version: 7.23.3 - resolution: "@babel/plugin-syntax-typescript@npm:7.23.3" + version: 7.24.1 + resolution: "@babel/plugin-syntax-typescript@npm:7.24.1" dependencies: - "@babel/helper-plugin-utils": ^7.22.5 + "@babel/helper-plugin-utils": ^7.24.0 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: abfad3a19290d258b028e285a1f34c9b8a0cbe46ef79eafed4ed7ffce11b5d0720b5e536c82f91cbd8442cde35a3dd8e861fa70366d87ff06fdc0d4756e30876 + checksum: bf4bd70788d5456b5f75572e47a2e31435c7c4e43609bd4dffd2cc0c7a6cf90aabcf6cd389e351854de9a64412a07d30effef5373251fe8f6a4c9db0c0163bda languageName: node linkType: hard "@babel/runtime@npm:^7.21.0": - version: 7.23.9 - resolution: "@babel/runtime@npm:7.23.9" + version: 7.24.4 + resolution: "@babel/runtime@npm:7.24.4" dependencies: regenerator-runtime: ^0.14.0 - checksum: 6bbebe8d27c0c2dd275d1ac197fc1a6c00e18dab68cc7aaff0adc3195b45862bae9c4cc58975629004b0213955b2ed91e99eccb3d9b39cabea246c657323d667 + checksum: 2f27d4c0ffac7ae7999ac0385e1106f2a06992a8bdcbf3da06adcac7413863cd08c198c2e4e970041bbea849e17f02e1df18875539b6afba76c781b6b59a07c3 languageName: node linkType: hard -"@babel/template@npm:^7.22.15, @babel/template@npm:^7.23.9, @babel/template@npm:^7.3.3": - version: 7.23.9 - resolution: "@babel/template@npm:7.23.9" +"@babel/template@npm:^7.22.15, @babel/template@npm:^7.24.0, @babel/template@npm:^7.3.3": + version: 7.24.0 + resolution: "@babel/template@npm:7.24.0" dependencies: "@babel/code-frame": ^7.23.5 - "@babel/parser": ^7.23.9 - "@babel/types": ^7.23.9 - checksum: 6e67414c0f7125d7ecaf20c11fab88085fa98a96c3ef10da0a61e962e04fdf3a18a496a66047005ddd1bb682a7cc7842d556d1db2f3f3f6ccfca97d5e445d342 + "@babel/parser": ^7.24.0 + "@babel/types": ^7.24.0 + checksum: f257b003c071a0cecdbfceca74185f18fe62c055469ab5c1d481aab12abeebed328e67e0a19fd978a2a8de97b28953fa4bc3da6d038a7345fdf37923b9fcdec8 languageName: node linkType: hard @@ -1313,21 +1290,21 @@ __metadata: languageName: node linkType: hard -"@babel/traverse@npm:^7.23.9": - version: 7.23.9 - resolution: "@babel/traverse@npm:7.23.9" +"@babel/traverse@npm:^7.24.1": + version: 7.24.1 + resolution: "@babel/traverse@npm:7.24.1" dependencies: - "@babel/code-frame": ^7.23.5 - "@babel/generator": ^7.23.6 + "@babel/code-frame": ^7.24.1 + "@babel/generator": ^7.24.1 "@babel/helper-environment-visitor": ^7.22.20 "@babel/helper-function-name": ^7.23.0 "@babel/helper-hoist-variables": ^7.22.5 "@babel/helper-split-export-declaration": ^7.22.6 - "@babel/parser": ^7.23.9 - "@babel/types": ^7.23.9 + "@babel/parser": ^7.24.1 + "@babel/types": ^7.24.0 debug: ^4.3.1 globals: ^11.1.0 - checksum: a932f7aa850e158c00c97aad22f639d48c72805c687290f6a73e30c5c4957c07f5d28310c9bf59648e2980fe6c9d16adeb2ff92a9ca0f97fa75739c1328fc6c3 + checksum: 92a5ca906abfba9df17666d2001ab23f18600035f706a687055a0e392a690ae48d6fec67c8bd4ef19ba18699a77a5b7f85727e36b83f7d110141608fe0c24fe9 languageName: node linkType: hard @@ -1341,14 +1318,14 @@ __metadata: languageName: node linkType: hard -"@babel/types@npm:^7.0.0, @babel/types@npm:^7.17.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.22.15, @babel/types@npm:^7.22.5, @babel/types@npm:^7.23.0, @babel/types@npm:^7.23.6, @babel/types@npm:^7.23.9, @babel/types@npm:^7.3.3, @babel/types@npm:^7.8.3": - version: 7.23.9 - resolution: "@babel/types@npm:7.23.9" +"@babel/types@npm:^7.0.0, @babel/types@npm:^7.17.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.22.5, @babel/types@npm:^7.23.0, @babel/types@npm:^7.24.0, @babel/types@npm:^7.3.3, @babel/types@npm:^7.8.3": + version: 7.24.0 + resolution: "@babel/types@npm:7.24.0" dependencies: "@babel/helper-string-parser": ^7.23.4 "@babel/helper-validator-identifier": ^7.22.20 to-fast-properties: ^2.0.0 - checksum: 0a9b008e9bfc89beb8c185e620fa0f8ed6c771f1e1b2e01e1596870969096fec7793898a1d64a035176abf1dd13e2668ee30bf699f2d92c210a8128f4b151e65 + checksum: 4b574a37d490f621470ff36a5afaac6deca5546edcb9b5e316d39acbb20998e9c2be42f3fc0bf2b55906fc49ff2a5a6a097e8f5a726ee3f708a0b0ca93aed807 languageName: node linkType: hard @@ -1373,6 +1350,41 @@ __metadata: languageName: node linkType: hard +"@chainsafe/discv5@npm:^9.0.0": + version: 9.0.0 + resolution: "@chainsafe/discv5@npm:9.0.0" + dependencies: + "@chainsafe/enr": ^3.0.0 + "@libp2p/crypto": ^4.0.1 + "@libp2p/interface": ^1.1.1 + "@multiformats/multiaddr": ^12.1.10 + bcrypto: ^5.4.0 + bigint-buffer: ^1.1.5 + debug: ^4.3.1 + lru-cache: ^10.1.0 + rlp: ^2.2.6 + strict-event-emitter-types: ^2.0.0 + checksum: 3c5a953231c8f62a45447186cded1177485e2461b026be8ce3bafad2901def422f1cccd530c427395dbf31a39df3817bdb9d1a3efbfa3a211d785a6011bc6585 + languageName: node + linkType: hard + +"@chainsafe/enr@npm:^3.0.0": + version: 3.0.0 + resolution: "@chainsafe/enr@npm:3.0.0" + dependencies: + "@libp2p/crypto": ^4.0.1 + "@libp2p/interface": ^1.1.1 + "@libp2p/peer-id": ^4.0.4 + "@multiformats/multiaddr": ^12.1.10 + bigint-buffer: ^1.1.5 + ethereum-cryptography: ^2.1.3 + rlp: ^2.2.6 + uint8-varint: ^2.0.2 + uint8arrays: ^5.0.1 + checksum: 247a4c3f21c64c6872654576e933f9e76ae6bfdd078ef1264e2b1d364d7bc31b7c11214d77fcb2d774da2fb7b6b2425487ccb1eee02ff8ad03bc5d30c298c20f + languageName: node + linkType: hard + "@chainsafe/is-ip@npm:^2.0.1, @chainsafe/is-ip@npm:^2.0.2": version: 2.0.2 resolution: "@chainsafe/is-ip@npm:2.0.2" @@ -1380,20 +1392,18 @@ __metadata: languageName: node linkType: hard -"@chainsafe/libp2p-noise@npm:^13.0.0": - version: 13.0.5 - resolution: "@chainsafe/libp2p-noise@npm:13.0.5" +"@chainsafe/libp2p-noise@npm:^15.0.0": + version: 15.0.0 + resolution: "@chainsafe/libp2p-noise@npm:15.0.0" dependencies: "@chainsafe/as-chacha20poly1305": ^0.1.0 "@chainsafe/as-sha256": ^0.4.1 - "@libp2p/crypto": ^2.0.0 - "@libp2p/interface": ^0.1.0 - "@libp2p/logger": ^3.0.0 - "@libp2p/peer-id": ^3.0.0 + "@libp2p/crypto": ^4.0.0 + "@libp2p/interface": ^1.0.0 + "@libp2p/peer-id": ^4.0.0 "@noble/ciphers": ^0.4.0 "@noble/curves": ^1.1.0 "@noble/hashes": ^1.3.1 - it-byte-stream: ^1.0.0 it-length-prefixed: ^9.0.1 it-length-prefixed-stream: ^1.0.0 it-pair: ^2.0.6 @@ -1401,24 +1411,24 @@ __metadata: it-stream-types: ^2.0.1 protons-runtime: ^5.0.0 uint8arraylist: ^2.4.3 - uint8arrays: ^4.0.4 + uint8arrays: ^5.0.0 wherearewe: ^2.0.1 - checksum: 98dd78bfd547501280c7a318acfa81624016351f18e0a28debe451340418fd263f90ce8d7358d5b83f61429522de6631321606b98eda35609114041853057af1 + checksum: 25ebb33b40f016d4b2006d61998392a0c59f26b6c165b26541c8f226130988ec642986166597baef9bf1dcb0c3bb264a7a0ea6f868a1d9d53b110a2df2729c5f languageName: node linkType: hard -"@chainsafe/libp2p-yamux@npm:^5.0.0": - version: 5.0.4 - resolution: "@chainsafe/libp2p-yamux@npm:5.0.4" +"@chainsafe/libp2p-yamux@npm:^6.0.2": + version: 6.0.2 + resolution: "@chainsafe/libp2p-yamux@npm:6.0.2" dependencies: - "@libp2p/interface": ^0.1.0 - "@libp2p/logger": ^3.0.0 + "@libp2p/interface": ^1.1.3 + "@libp2p/utils": ^5.2.5 get-iterator: ^2.0.1 - it-foreach: ^2.0.3 + it-foreach: ^2.0.6 it-pipe: ^3.0.1 - it-pushable: ^3.2.0 - uint8arraylist: ^2.4.3 - checksum: 58c33b28d8da2b8c6813127de2cc4005f2f09d845cf535c56a3db0495774a2feb935d2813d2141bb6a747f3c1181dfde415945821d489ac7f987e36df744721f + it-pushable: ^3.2.3 + uint8arraylist: ^2.4.8 + checksum: bcbfa0a2f63fd16853a699ba6ec20835f2ee015d104559c16ea71d0cd93baa39a02bf558d877e764a9ecd7eb080f09a689e93b7afacf97af5f58fde887a1b92b languageName: node linkType: hard @@ -1675,14 +1685,14 @@ __metadata: languageName: node linkType: hard -"@eslint/js@npm:8.56.0": - version: 8.56.0 - resolution: "@eslint/js@npm:8.56.0" - checksum: 5804130574ef810207bdf321c265437814e7a26f4e6fac9b496de3206afd52f533e09ec002a3be06cd9adcc9da63e727f1883938e663c4e4751c007d5b58e539 +"@eslint/js@npm:8.57.0": + version: 8.57.0 + resolution: "@eslint/js@npm:8.57.0" + checksum: 315dc65b0e9893e2bff139bddace7ea601ad77ed47b4550e73da8c9c2d2766c7a575c3cddf17ef85b8fd6a36ff34f91729d0dcca56e73ca887c10df91a41b0bb languageName: node linkType: hard -"@humanwhocodes/config-array@npm:^0.11.13": +"@humanwhocodes/config-array@npm:^0.11.14": version: 0.11.14 resolution: "@humanwhocodes/config-array@npm:0.11.14" dependencies: @@ -1701,9 +1711,9 @@ __metadata: linkType: hard "@humanwhocodes/object-schema@npm:^2.0.2": - version: 2.0.2 - resolution: "@humanwhocodes/object-schema@npm:2.0.2" - checksum: 2fc11503361b5fb4f14714c700c02a3f4c7c93e9acd6b87a29f62c522d90470f364d6161b03d1cc618b979f2ae02aed1106fd29d302695d8927e2fc8165ba8ee + version: 2.0.3 + resolution: "@humanwhocodes/object-schema@npm:2.0.3" + checksum: d3b78f6c5831888c6ecc899df0d03bcc25d46f3ad26a11d7ea52944dc36a35ef543fad965322174238d677a43d5c694434f6607532cff7077062513ad7022631 languageName: node linkType: hard @@ -1741,7 +1751,7 @@ __metadata: languageName: node linkType: hard -"@istanbuljs/schema@npm:^0.1.2": +"@istanbuljs/schema@npm:^0.1.2, @istanbuljs/schema@npm:^0.1.3": version: 0.1.3 resolution: "@istanbuljs/schema@npm:0.1.3" checksum: 5282759d961d61350f33d9118d16bcaed914ebf8061a52f4fa474b2cb08720c9c81d165e13b82f2e5a8a212cc5af482f0c6fc1ac27b9e067e5394c9a6ed186c9 @@ -1987,38 +1997,38 @@ __metadata: languageName: node linkType: hard -"@jridgewell/gen-mapping@npm:^0.3.0, @jridgewell/gen-mapping@npm:^0.3.2": - version: 0.3.3 - resolution: "@jridgewell/gen-mapping@npm:0.3.3" +"@jridgewell/gen-mapping@npm:^0.3.5": + version: 0.3.5 + resolution: "@jridgewell/gen-mapping@npm:0.3.5" dependencies: - "@jridgewell/set-array": ^1.0.1 + "@jridgewell/set-array": ^1.2.1 "@jridgewell/sourcemap-codec": ^1.4.10 - "@jridgewell/trace-mapping": ^0.3.9 - checksum: 4a74944bd31f22354fc01c3da32e83c19e519e3bbadafa114f6da4522ea77dd0c2842607e923a591d60a76699d819a2fbb6f3552e277efdb9b58b081390b60ab + "@jridgewell/trace-mapping": ^0.3.24 + checksum: ff7a1764ebd76a5e129c8890aa3e2f46045109dabde62b0b6c6a250152227647178ff2069ea234753a690d8f3c4ac8b5e7b267bbee272bffb7f3b0a370ab6e52 languageName: node linkType: hard "@jridgewell/resolve-uri@npm:^3.0.3, @jridgewell/resolve-uri@npm:^3.1.0": - version: 3.1.1 - resolution: "@jridgewell/resolve-uri@npm:3.1.1" - checksum: f5b441fe7900eab4f9155b3b93f9800a916257f4e8563afbcd3b5a5337b55e52bd8ae6735453b1b745457d9f6cdb16d74cd6220bbdd98cf153239e13f6cbb653 + version: 3.1.2 + resolution: "@jridgewell/resolve-uri@npm:3.1.2" + checksum: 83b85f72c59d1c080b4cbec0fef84528963a1b5db34e4370fa4bd1e3ff64a0d80e0cee7369d11d73c704e0286fb2865b530acac7a871088fbe92b5edf1000870 languageName: node linkType: hard -"@jridgewell/set-array@npm:^1.0.1": - version: 1.1.2 - resolution: "@jridgewell/set-array@npm:1.1.2" - checksum: 69a84d5980385f396ff60a175f7177af0b8da4ddb81824cb7016a9ef914eee9806c72b6b65942003c63f7983d4f39a5c6c27185bbca88eb4690b62075602e28e +"@jridgewell/set-array@npm:^1.2.1": + version: 1.2.1 + resolution: "@jridgewell/set-array@npm:1.2.1" + checksum: 832e513a85a588f8ed4f27d1279420d8547743cc37fcad5a5a76fc74bb895b013dfe614d0eed9cb860048e6546b798f8f2652020b4b2ba0561b05caa8c654b10 languageName: node linkType: hard "@jridgewell/source-map@npm:^0.3.3": - version: 0.3.5 - resolution: "@jridgewell/source-map@npm:0.3.5" + version: 0.3.6 + resolution: "@jridgewell/source-map@npm:0.3.6" dependencies: - "@jridgewell/gen-mapping": ^0.3.0 - "@jridgewell/trace-mapping": ^0.3.9 - checksum: 1ad4dec0bdafbade57920a50acec6634f88a0eb735851e0dda906fa9894e7f0549c492678aad1a10f8e144bfe87f238307bf2a914a1bc85b7781d345417e9f6f + "@jridgewell/gen-mapping": ^0.3.5 + "@jridgewell/trace-mapping": ^0.3.25 + checksum: c9dc7d899397df95e3c9ec287b93c0b56f8e4453cd20743e2b9c8e779b1949bc3cccf6c01bb302779e46560eb45f62ea38d19fedd25370d814734268450a9f30 languageName: node linkType: hard @@ -2039,13 +2049,13 @@ __metadata: languageName: node linkType: hard -"@jridgewell/trace-mapping@npm:^0.3.12, @jridgewell/trace-mapping@npm:^0.3.17, @jridgewell/trace-mapping@npm:^0.3.18, @jridgewell/trace-mapping@npm:^0.3.20, @jridgewell/trace-mapping@npm:^0.3.9": - version: 0.3.22 - resolution: "@jridgewell/trace-mapping@npm:0.3.22" +"@jridgewell/trace-mapping@npm:^0.3.12, @jridgewell/trace-mapping@npm:^0.3.18, @jridgewell/trace-mapping@npm:^0.3.20, @jridgewell/trace-mapping@npm:^0.3.24, @jridgewell/trace-mapping@npm:^0.3.25": + version: 0.3.25 + resolution: "@jridgewell/trace-mapping@npm:0.3.25" dependencies: "@jridgewell/resolve-uri": ^3.1.0 "@jridgewell/sourcemap-codec": ^1.4.14 - checksum: ac7dd2cfe0b479aa1b81776d40d789243131cc792dc8b6b6a028c70fcd6171958ae1a71bf67b618ffe3c0c3feead9870c095ee46a5e30319410d92976b28f498 + checksum: 9d3c40d225e139987b50c48988f8717a54a8c994d8a948ee42e1412e08988761d0754d7d10b803061cc3aebf35f92a5dbbab493bd0e1a9ef9e89a2130e83ba34 languageName: node linkType: hard @@ -2058,6 +2068,13 @@ __metadata: languageName: node linkType: hard +"@leichtgewicht/ip-codec@npm:^2.0.1": + version: 2.0.5 + resolution: "@leichtgewicht/ip-codec@npm:2.0.5" + checksum: 4fcd025d0a923cb6b87b631a83436a693b255779c583158bbeacde6b4dd75b94cc1eba1c9c188de5fc36c218d160524ea08bfe4ef03a056b00ff14126d66f881 + languageName: node + linkType: hard + "@libp2p/bootstrap@npm:^9.0.4": version: 9.0.12 resolution: "@libp2p/bootstrap@npm:9.0.12" @@ -2071,7 +2088,7 @@ __metadata: languageName: node linkType: hard -"@libp2p/crypto@npm:^2.0.0, @libp2p/crypto@npm:^2.0.8": +"@libp2p/crypto@npm:^2.0.8": version: 2.0.8 resolution: "@libp2p/crypto@npm:2.0.8" dependencies: @@ -2087,6 +2104,41 @@ __metadata: languageName: node linkType: hard +"@libp2p/crypto@npm:^4.0.0, @libp2p/crypto@npm:^4.0.1, @libp2p/crypto@npm:^4.0.3, @libp2p/crypto@npm:^4.0.6": + version: 4.0.6 + resolution: "@libp2p/crypto@npm:4.0.6" + dependencies: + "@libp2p/interface": ^1.2.0 + "@noble/curves": ^1.4.0 + "@noble/hashes": ^1.4.0 + asn1js: ^3.0.5 + multiformats: ^13.1.0 + protons-runtime: ^5.4.0 + uint8arraylist: ^2.4.8 + uint8arrays: ^5.0.3 + checksum: f3ef3ebdfae517e6c3b9fef9c7aab2941ac77fdc82cc10a0444561f9fac7836239b48183f52fed39a0f23fa7b373ac19ffab74ea8589d6d70acacb5a5a29c84e + languageName: node + linkType: hard + +"@libp2p/identify@npm:^1.0.15": + version: 1.0.19 + resolution: "@libp2p/identify@npm:1.0.19" + dependencies: + "@libp2p/interface": ^1.2.0 + "@libp2p/interface-internal": ^1.1.0 + "@libp2p/peer-id": ^4.0.10 + "@libp2p/peer-record": ^7.0.14 + "@multiformats/multiaddr": ^12.2.1 + "@multiformats/multiaddr-matcher": ^1.2.0 + it-protobuf-stream: ^1.1.2 + protons-runtime: ^5.4.0 + uint8arraylist: ^2.4.8 + uint8arrays: ^5.0.3 + wherearewe: ^2.0.1 + checksum: c4e2f7d3cd5355b66c9495f7d092abf962721760877c8ad2bdc01198b15e0f1d1aa0505cdb0c7a2886f7b08c0e0253b80c5d3ec269455e841665423b7e50e63a + languageName: node + linkType: hard + "@libp2p/interface-connection@npm:^5.0.0": version: 5.1.1 resolution: "@libp2p/interface-connection@npm:5.1.1" @@ -2123,6 +2175,18 @@ __metadata: languageName: node linkType: hard +"@libp2p/interface-internal@npm:^1.1.0": + version: 1.1.0 + resolution: "@libp2p/interface-internal@npm:1.1.0" + dependencies: + "@libp2p/interface": ^1.2.0 + "@libp2p/peer-collections": ^5.1.10 + "@multiformats/multiaddr": ^12.2.1 + uint8arraylist: ^2.4.8 + checksum: 40e25e3fa2ee70376d3f70b627f0c096e71929dede7c87f80b8ac75b56131b4293d0665e7164e0935f201e0e4d1febac8b43ca1cd3cfeea79581242dde992727 + languageName: node + linkType: hard + "@libp2p/interface-keychain@npm:^2.0.0": version: 2.0.5 resolution: "@libp2p/interface-keychain@npm:2.0.5" @@ -2241,7 +2305,7 @@ __metadata: languageName: node linkType: hard -"@libp2p/interface@npm:^0.1.0, @libp2p/interface@npm:^0.1.2, @libp2p/interface@npm:^0.1.6": +"@libp2p/interface@npm:^0.1.6": version: 0.1.6 resolution: "@libp2p/interface@npm:0.1.6" dependencies: @@ -2257,17 +2321,17 @@ __metadata: languageName: node linkType: hard -"@libp2p/interface@npm:^1.0.0, @libp2p/interface@npm:^1.1.2": - version: 1.1.2 - resolution: "@libp2p/interface@npm:1.1.2" +"@libp2p/interface@npm:^1.0.0, @libp2p/interface@npm:^1.1.1, @libp2p/interface@npm:^1.1.3, @libp2p/interface@npm:^1.1.4, @libp2p/interface@npm:^1.2.0": + version: 1.2.0 + resolution: "@libp2p/interface@npm:1.2.0" dependencies: - "@multiformats/multiaddr": ^12.1.10 + "@multiformats/multiaddr": ^12.2.1 it-pushable: ^3.2.3 it-stream-types: ^2.0.1 - multiformats: ^13.0.0 + multiformats: ^13.1.0 progress-events: ^1.0.0 - uint8arraylist: ^2.4.7 - checksum: 99e257281fde4a226124344f24eb246b2a1f0639be3a73aae4478e97267f4fa5d9f86754291b16d5da01179d0fa11066477a7e1b6bb4ddfa025442b0fdc90809 + uint8arraylist: ^2.4.8 + checksum: 622a5bb7f0ffcca4a418afc7e52b4c8dceb48af763c317290fdf747335166f65615eba6947419daa76351afbb66e0b17b630aa40f10164155e76524b46b18fe6 languageName: node linkType: hard @@ -2321,22 +2385,6 @@ __metadata: languageName: node linkType: hard -"@libp2p/keychain@npm:^3.0.8": - version: 3.0.8 - resolution: "@libp2p/keychain@npm:3.0.8" - dependencies: - "@libp2p/crypto": ^2.0.8 - "@libp2p/interface": ^0.1.6 - "@libp2p/logger": ^3.1.0 - "@libp2p/peer-id": ^3.0.6 - interface-datastore: ^8.2.0 - merge-options: ^3.0.4 - sanitize-filename: ^1.6.3 - uint8arrays: ^4.0.6 - checksum: 765971d2ef29cdc781ff2447f28501b9f58c8a9d0e4339c17b01de5a57d50344f58b40928c3b0ad85534a416ac1055a0c1ca59852ca26329118d423d7e305e66 - languageName: node - linkType: hard - "@libp2p/logger@npm:^2.0.7": version: 2.1.1 resolution: "@libp2p/logger@npm:2.1.1" @@ -2350,7 +2398,7 @@ __metadata: languageName: node linkType: hard -"@libp2p/logger@npm:^3.0.0, @libp2p/logger@npm:^3.1.0": +"@libp2p/logger@npm:^3.1.0": version: 3.1.0 resolution: "@libp2p/logger@npm:3.1.0" dependencies: @@ -2363,57 +2411,49 @@ __metadata: languageName: node linkType: hard -"@libp2p/logger@npm:^4.0.1": - version: 4.0.5 - resolution: "@libp2p/logger@npm:4.0.5" +"@libp2p/logger@npm:^4.0.10, @libp2p/logger@npm:^4.0.6": + version: 4.0.10 + resolution: "@libp2p/logger@npm:4.0.10" dependencies: - "@libp2p/interface": ^1.1.2 - "@multiformats/multiaddr": ^12.1.10 + "@libp2p/interface": ^1.2.0 + "@multiformats/multiaddr": ^12.2.1 debug: ^4.3.4 - interface-datastore: ^8.2.0 - multiformats: ^13.0.0 - checksum: e0bc60e3ac6f3ab017eb16b26eb3badc3c728291fdbea28cf9ef2f9fbfc1161d562acfa4c4fbd148d6ad0de8a4417f02d1ffada611af5255fff8495df2d65707 + interface-datastore: ^8.2.11 + multiformats: ^13.1.0 + checksum: 9897edd36cdb13e200249a77077c18c21b58cc11056f7efc30ade2bb399130100ea7a23864d1ddcf1805b71d2404b834e1620b5a129b193b299ee94373bd991a languageName: node linkType: hard -"@libp2p/mplex@npm:^9.0.4": - version: 9.0.12 - resolution: "@libp2p/mplex@npm:9.0.12" +"@libp2p/mplex@npm:^10.0.16": + version: 10.0.20 + resolution: "@libp2p/mplex@npm:10.0.20" dependencies: - "@libp2p/interface": ^0.1.6 - "@libp2p/logger": ^3.1.0 - abortable-iterator: ^5.0.1 - benchmark: ^2.1.4 - it-batched-bytes: ^2.0.2 - it-pushable: ^3.2.0 + "@libp2p/interface": ^1.2.0 + "@libp2p/utils": ^5.3.1 + it-pipe: ^3.0.1 + it-pushable: ^3.2.3 it-stream-types: ^2.0.1 - rate-limiter-flexible: ^3.0.0 - uint8-varint: ^2.0.0 - uint8arraylist: ^2.4.3 - uint8arrays: ^4.0.6 - checksum: 13c9c8a1826d81fc0497f84bfff97d75563602ea7bf07ac64f29bb3f6c13129610e825bca1bda8d63de62945009a0dc91b607c4979d2e91ad6c2e10f8008ec10 + uint8-varint: ^2.0.4 + uint8arraylist: ^2.4.8 + uint8arrays: ^5.0.3 + checksum: 091875301433de10a9ba5f92c00720330c2a3f9ba2b693b28792b080712f28cc44bad0de0bbdf91a8c2c5324ed0d9f95baf55f6758827d353a6b2b7a4570d12b languageName: node linkType: hard -"@libp2p/multistream-select@npm:^4.0.6": - version: 4.0.10 - resolution: "@libp2p/multistream-select@npm:4.0.10" +"@libp2p/multistream-select@npm:^5.1.7": + version: 5.1.7 + resolution: "@libp2p/multistream-select@npm:5.1.7" dependencies: - "@libp2p/interface": ^0.1.6 - "@libp2p/logger": ^3.1.0 - abortable-iterator: ^5.0.1 - it-first: ^3.0.1 - it-handshake: ^4.1.3 - it-length-prefixed: ^9.0.1 - it-merge: ^3.0.0 - it-pipe: ^3.0.1 - it-pushable: ^3.2.0 - it-reader: ^6.0.1 + "@libp2p/interface": ^1.2.0 + it-length-prefixed: ^9.0.4 + it-length-prefixed-stream: ^1.1.6 it-stream-types: ^2.0.1 - uint8-varint: ^2.0.0 - uint8arraylist: ^2.4.3 - uint8arrays: ^4.0.6 - checksum: 3a3d32cc3605f73cef4039712b394c1bf18d5ca624f9b8b43c880b4d65b8bbc0491273a970183febd52c3f30dfbdbd2f6ac4aa102a117661e057749e67910bb6 + p-defer: ^4.0.1 + race-signal: ^1.0.2 + uint8-varint: ^2.0.4 + uint8arraylist: ^2.4.8 + uint8arrays: ^5.0.3 + checksum: 663a5f858a96dd0fe59083ea297573c3e778deb3936f2ac51ce4c932a4f29c5571ccdb74bfb13acb5cc9a3521d3312fb9f411c6c5aa7d2299993009900ea5255 languageName: node linkType: hard @@ -2427,22 +2467,31 @@ __metadata: languageName: node linkType: hard -"@libp2p/peer-id-factory@npm:^3.0.3, @libp2p/peer-id-factory@npm:^3.0.8": - version: 3.0.11 - resolution: "@libp2p/peer-id-factory@npm:3.0.11" +"@libp2p/peer-collections@npm:^5.1.10": + version: 5.1.10 + resolution: "@libp2p/peer-collections@npm:5.1.10" dependencies: - "@libp2p/crypto": ^2.0.8 - "@libp2p/interface": ^0.1.6 - "@libp2p/peer-id": ^3.0.6 - multiformats: ^12.0.1 - protons-runtime: ^5.0.0 - uint8arraylist: ^2.4.3 - uint8arrays: ^4.0.6 - checksum: bdcee4fef7f8aace6a8316e523e8c82753986a42c58b51f59d04534a1095c9c1eec8193e859614aa2589a7f5e43e64e529bb0b475e7bad7150b2034b2ebc0aa2 + "@libp2p/interface": ^1.2.0 + "@libp2p/peer-id": ^4.0.10 + checksum: 959ca7d53961fd2da6c90f6938c7b25cecd07ca0a2a57e43a23c34b8406834b15f1a56e86ca15d79d77508ab04700a586a80850541b1f07d3d5fa8b3a3758280 + languageName: node + linkType: hard + +"@libp2p/peer-id-factory@npm:^4.0.10, @libp2p/peer-id-factory@npm:^4.0.7": + version: 4.0.10 + resolution: "@libp2p/peer-id-factory@npm:4.0.10" + dependencies: + "@libp2p/crypto": ^4.0.6 + "@libp2p/interface": ^1.2.0 + "@libp2p/peer-id": ^4.0.10 + protons-runtime: ^5.4.0 + uint8arraylist: ^2.4.8 + uint8arrays: ^5.0.3 + checksum: b08ef471f730af54e9e50ca9225fb221b850936fe453ca33c89c8bea0a91fdb06d7065d57cc2921ca26948b470c5449c8b91ddeb364bcd05671a3694fe7dc756 languageName: node linkType: hard -"@libp2p/peer-id@npm:^3.0.0, @libp2p/peer-id@npm:^3.0.2, @libp2p/peer-id@npm:^3.0.6": +"@libp2p/peer-id@npm:^3.0.6": version: 3.0.6 resolution: "@libp2p/peer-id@npm:3.0.6" dependencies: @@ -2453,74 +2502,88 @@ __metadata: languageName: node linkType: hard -"@libp2p/peer-record@npm:^6.0.9": - version: 6.0.12 - resolution: "@libp2p/peer-record@npm:6.0.12" +"@libp2p/peer-id@npm:^4.0.0, @libp2p/peer-id@npm:^4.0.10, @libp2p/peer-id@npm:^4.0.4, @libp2p/peer-id@npm:^4.0.7": + version: 4.0.10 + resolution: "@libp2p/peer-id@npm:4.0.10" dependencies: - "@libp2p/crypto": ^2.0.8 - "@libp2p/interface": ^0.1.6 - "@libp2p/peer-id": ^3.0.6 - "@libp2p/utils": ^4.0.7 - "@multiformats/multiaddr": ^12.1.5 - protons-runtime: ^5.0.0 - uint8-varint: ^2.0.0 - uint8arraylist: ^2.4.3 - uint8arrays: ^4.0.6 - checksum: d252cafa7c63fc05c8715cb4de8e340bbd76e5438b3eaf309f6e2de5a41d550f399f4ddba110ef2edcb4e667659baa20d4da2cc4d9f19611ae4402f72eb87006 + "@libp2p/interface": ^1.2.0 + multiformats: ^13.1.0 + uint8arrays: ^5.0.3 + checksum: 5816e043a0cc5f753ed177fa63bcfbbcc1b236e93f5984943bc4107dab3bb023f6631b3d884554046315eb074fd7cb903bb0ead5bd462f998f5ba49009e5201f languageName: node linkType: hard -"@libp2p/peer-store@npm:^9.0.9": - version: 9.0.12 - resolution: "@libp2p/peer-store@npm:9.0.12" +"@libp2p/peer-record@npm:^7.0.14": + version: 7.0.14 + resolution: "@libp2p/peer-record@npm:7.0.14" dependencies: - "@libp2p/interface": ^0.1.6 - "@libp2p/logger": ^3.1.0 - "@libp2p/peer-collections": ^4.0.8 - "@libp2p/peer-id": ^3.0.6 - "@libp2p/peer-id-factory": ^3.0.8 - "@libp2p/peer-record": ^6.0.9 - "@multiformats/multiaddr": ^12.1.5 - interface-datastore: ^8.2.0 - it-all: ^3.0.2 - mortice: ^3.0.1 - multiformats: ^12.0.1 - protons-runtime: ^5.0.0 - uint8arraylist: ^2.4.3 - uint8arrays: ^4.0.6 - checksum: b4d3ee98781742a7f46d50afc43f6b530058c9d8f2db04fd66c391d59427eaa4b49eb9d4df26e6bd4e6ae8d9a60e90686ae522f13e9ad517da4860c3f868a778 + "@libp2p/crypto": ^4.0.6 + "@libp2p/interface": ^1.2.0 + "@libp2p/peer-id": ^4.0.10 + "@libp2p/utils": ^5.3.1 + "@multiformats/multiaddr": ^12.2.1 + protons-runtime: ^5.4.0 + uint8-varint: ^2.0.4 + uint8arraylist: ^2.4.8 + uint8arrays: ^5.0.3 + checksum: 9fc253f1c7f605f777b5238c1798997882f5d62fdc7b9a9678d4843050e60ff6fe105f64b002f76e1a84af100795dec6e653c4d6ec8922fa86898982a93da1c3 languageName: node linkType: hard -"@libp2p/tcp@npm:^8.0.4": - version: 8.0.13 - resolution: "@libp2p/tcp@npm:8.0.13" +"@libp2p/peer-store@npm:^10.0.15": + version: 10.0.15 + resolution: "@libp2p/peer-store@npm:10.0.15" dependencies: - "@libp2p/interface": ^0.1.6 - "@libp2p/logger": ^3.1.0 - "@libp2p/utils": ^4.0.7 - "@multiformats/mafmt": ^12.1.2 - "@multiformats/multiaddr": ^12.1.5 - "@types/sinon": ^17.0.0 - stream-to-it: ^0.2.2 - checksum: cceff8633265c3bee7b0a246808fe26a61cb5876ca3363ae3278ebd9d2bd4775e3d3057c5ef8f18b8dd78368a0fd6359c94e7f8cd3f747ad4ebc89fce80db274 + "@libp2p/interface": ^1.2.0 + "@libp2p/peer-collections": ^5.1.10 + "@libp2p/peer-id": ^4.0.10 + "@libp2p/peer-record": ^7.0.14 + "@multiformats/multiaddr": ^12.2.1 + interface-datastore: ^8.2.11 + it-all: ^3.0.4 + mortice: ^3.0.4 + multiformats: ^13.1.0 + protons-runtime: ^5.4.0 + uint8arraylist: ^2.4.8 + uint8arrays: ^5.0.3 + checksum: 3fa3bb7a03d79dc61802d0d97deb04aec70288494cc6ed54a12ef7a164d4ad248d5a848177bea7c4accbd833e8d2ea2b2575be9b3daa81ed8ba6640e84bc62a3 languageName: node linkType: hard -"@libp2p/utils@npm:^4.0.7": - version: 4.0.7 - resolution: "@libp2p/utils@npm:4.0.7" +"@libp2p/tcp@npm:^9.0.16": + version: 9.0.22 + resolution: "@libp2p/tcp@npm:9.0.22" + dependencies: + "@libp2p/interface": ^1.2.0 + "@libp2p/utils": ^5.3.1 + "@multiformats/mafmt": ^12.1.6 + "@multiformats/multiaddr": ^12.2.1 + "@types/sinon": ^17.0.3 + stream-to-it: ^1.0.0 + checksum: bf9c8e26385bbcf4b112b6d69eae6cf9a74537059b153b7163022221bd1eeb8b1600a6d622186257f8ffc57c4eac73458206f3ff577f4743ff01d004af91800a + languageName: node + linkType: hard + +"@libp2p/utils@npm:^5.2.5, @libp2p/utils@npm:^5.3.1": + version: 5.3.1 + resolution: "@libp2p/utils@npm:5.3.1" dependencies: "@chainsafe/is-ip": ^2.0.2 - "@libp2p/interface": ^0.1.6 - "@libp2p/logger": ^3.1.0 - "@multiformats/multiaddr": ^12.1.5 - "@multiformats/multiaddr-matcher": ^1.0.1 - is-loopback-addr: ^2.0.1 + "@libp2p/interface": ^1.2.0 + "@libp2p/logger": ^4.0.10 + "@multiformats/multiaddr": ^12.2.1 + "@multiformats/multiaddr-matcher": ^1.2.0 + delay: ^6.0.0 + get-iterator: ^2.0.1 + is-loopback-addr: ^2.0.2 + it-pushable: ^3.2.3 it-stream-types: ^2.0.1 - private-ip: ^3.0.0 - uint8arraylist: ^2.4.3 - checksum: df883f04b9efda532009ae0b2f03d918567277479e6f115a02673394e4239605bbaa0718e7cea7bd4c70307b44cd782492b6fa4ad9f03c7c4621f12cbb1f7d4c + netmask: ^2.0.2 + p-defer: ^4.0.1 + race-event: ^1.2.0 + race-signal: ^1.0.2 + uint8arraylist: ^2.4.8 + checksum: 6183d2207209e150fe415077cc80635119ea2d94fe7ca6e4881644ce0500ff2039844061bcce9496ee5704bb67b9268d27ae2108eeb1bef55f7541257daef2a8 languageName: node linkType: hard @@ -2654,7 +2717,22 @@ __metadata: languageName: node linkType: hard -"@multiformats/mafmt@npm:^12.1.2": +"@multiformats/dns@npm:^1.0.3, @multiformats/dns@npm:^1.0.5": + version: 1.0.6 + resolution: "@multiformats/dns@npm:1.0.6" + dependencies: + "@types/dns-packet": ^5.6.5 + buffer: ^6.0.3 + dns-packet: ^5.6.1 + hashlru: ^2.3.0 + p-queue: ^8.0.1 + progress-events: ^1.0.0 + uint8arrays: ^5.0.2 + checksum: bcd4b7a6260a0e7a1d3f149142e06b66318cc2f141ccc454772dcaf288f898dc652f8bb249e3d717e01292583c3ebab2a0a644bc5d91dfcc17b18eff5c93c53a + languageName: node + linkType: hard + +"@multiformats/mafmt@npm:^12.1.2, @multiformats/mafmt@npm:^12.1.6": version: 12.1.6 resolution: "@multiformats/mafmt@npm:12.1.6" dependencies: @@ -2663,29 +2741,29 @@ __metadata: languageName: node linkType: hard -"@multiformats/multiaddr-matcher@npm:^1.0.0, @multiformats/multiaddr-matcher@npm:^1.0.1": - version: 1.1.2 - resolution: "@multiformats/multiaddr-matcher@npm:1.1.2" +"@multiformats/multiaddr-matcher@npm:^1.2.0": + version: 1.2.0 + resolution: "@multiformats/multiaddr-matcher@npm:1.2.0" dependencies: "@chainsafe/is-ip": ^2.0.1 "@multiformats/multiaddr": ^12.0.0 multiformats: ^13.0.0 - checksum: ae0619211ad1a4f1021993c1372f6498cbaec07897559b0b8644e0c8e53a3fc209136d3faf4f6cef5b1533f952b55b232fd6eb089d578a3594fa92d01802d4c3 + checksum: 0546bcb8105e9c146b577d481232226aa751e2fb0b3d13d0a182ea3e5b9d4e69308cb50f1a3e73531ccb1b2b265d083b4ee127b511f8125a0745229eeb847aec languageName: node linkType: hard -"@multiformats/multiaddr@npm:^12.0.0, @multiformats/multiaddr@npm:^12.1.10, @multiformats/multiaddr@npm:^12.1.3, @multiformats/multiaddr@npm:^12.1.5": - version: 12.1.14 - resolution: "@multiformats/multiaddr@npm:12.1.14" +"@multiformats/multiaddr@npm:^12.0.0, @multiformats/multiaddr@npm:^12.1.10, @multiformats/multiaddr@npm:^12.1.14, @multiformats/multiaddr@npm:^12.1.3, @multiformats/multiaddr@npm:^12.1.5, @multiformats/multiaddr@npm:^12.2.1": + version: 12.2.1 + resolution: "@multiformats/multiaddr@npm:12.2.1" dependencies: "@chainsafe/is-ip": ^2.0.1 "@chainsafe/netmask": ^2.0.0 "@libp2p/interface": ^1.0.0 - dns-over-http-resolver: ^3.0.2 + "@multiformats/dns": ^1.0.3 multiformats: ^13.0.0 uint8-varint: ^2.0.1 uint8arrays: ^5.0.0 - checksum: 6c48bb1c467b36c030b2c746574b81f7e3a8fba46987471b5f6714dac1ceea120759383be37c1cacc8d1fbb9c8666eb28ad0041c5737eaf457bd8d58f0d520fa + checksum: 8d0e1e50c80f4baeb088001a37864987e1a0447783a3411c6f7bd678bd3818d1183563a36076a98f3ebbb8d3c81d4203a609dac510a2370c77e450430b44e5ec languageName: node linkType: hard @@ -2705,7 +2783,7 @@ __metadata: languageName: node linkType: hard -"@noble/curves@npm:^1.0.0, @noble/curves@npm:^1.1.0, @noble/curves@npm:^1.2.0": +"@noble/curves@npm:1.3.0, @noble/curves@npm:~1.3.0": version: 1.3.0 resolution: "@noble/curves@npm:1.3.0" dependencies: @@ -2714,6 +2792,15 @@ __metadata: languageName: node linkType: hard +"@noble/curves@npm:^1.0.0, @noble/curves@npm:^1.1.0, @noble/curves@npm:^1.2.0, @noble/curves@npm:^1.4.0": + version: 1.4.0 + resolution: "@noble/curves@npm:1.4.0" + dependencies: + "@noble/hashes": 1.4.0 + checksum: 0014ff561d16e98da4a57e2310a4015e4bdab3b1e1eafcd18d3f9b955c29c3501452ca5d702fddf8ca92d570bbeadfbe53fe16ebbd81a319c414f739154bb26b + languageName: node + linkType: hard + "@noble/hashes@npm:1.3.2": version: 1.3.2 resolution: "@noble/hashes@npm:1.3.2" @@ -2721,13 +2808,20 @@ __metadata: languageName: node linkType: hard -"@noble/hashes@npm:1.3.3, @noble/hashes@npm:^1.3.1, @noble/hashes@npm:~1.3.0, @noble/hashes@npm:~1.3.2": +"@noble/hashes@npm:1.3.3, @noble/hashes@npm:~1.3.0, @noble/hashes@npm:~1.3.2": version: 1.3.3 resolution: "@noble/hashes@npm:1.3.3" checksum: 8a6496d1c0c64797339bc694ad06cdfaa0f9e56cd0c3f68ae3666cfb153a791a55deb0af9c653c7ed2db64d537aa3e3054629740d2f2338bb1dcb7ab60cd205b languageName: node linkType: hard +"@noble/hashes@npm:1.4.0, @noble/hashes@npm:^1.3.1, @noble/hashes@npm:^1.4.0": + version: 1.4.0 + resolution: "@noble/hashes@npm:1.4.0" + checksum: 8ba816ae26c90764b8c42493eea383716396096c5f7ba6bea559993194f49d80a73c081f315f4c367e51bd2d5891700bcdfa816b421d24ab45b41cb03e4f3342 + languageName: node + linkType: hard + "@nodelib/fs.scandir@npm:2.1.5": version: 2.1.5 resolution: "@nodelib/fs.scandir@npm:2.1.5" @@ -2776,15 +2870,15 @@ __metadata: linkType: soft "@npmcli/agent@npm:^2.0.0": - version: 2.2.0 - resolution: "@npmcli/agent@npm:2.2.0" + version: 2.2.2 + resolution: "@npmcli/agent@npm:2.2.2" dependencies: agent-base: ^7.1.0 http-proxy-agent: ^7.0.0 https-proxy-agent: ^7.0.1 lru-cache: ^10.0.1 - socks-proxy-agent: ^8.0.1 - checksum: 3b25312edbdfaa4089af28e2d423b6f19838b945e47765b0c8174c1395c79d43c3ad6d23cb364b43f59fd3acb02c93e3b493f72ddbe3dfea04c86843a7311fc4 + socks-proxy-agent: ^8.0.3 + checksum: 67de7b88cc627a79743c88bab35e023e23daf13831a8aa4e15f998b92f5507b644d8ffc3788afc8e64423c612e0785a6a92b74782ce368f49a6746084b50d874 languageName: node linkType: hard @@ -2804,9 +2898,9 @@ __metadata: languageName: node linkType: hard -"@puppeteer/browsers@npm:2.1.0": - version: 2.1.0 - resolution: "@puppeteer/browsers@npm:2.1.0" +"@puppeteer/browsers@npm:2.2.2": + version: 2.2.2 + resolution: "@puppeteer/browsers@npm:2.2.2" dependencies: debug: 4.3.4 extract-zip: 2.0.1 @@ -2818,14 +2912,14 @@ __metadata: yargs: 17.7.2 bin: browsers: lib/cjs/main-cli.js - checksum: 318740056fc716cf26179f053eb47e119bc01658f59382a19fb7d39e5b9232a7ad7d82e33445e0519683c13e22b328193fc9952c99d09cdc09f6539391d4749c + checksum: 328a10ceb432784ec4cd524c461799936603b8436e50eed6a61127022f4c8a36ba31143b0d4d311190d619968f2e9db9fa7ac046757cff2c9f81d301110560be languageName: node linkType: hard -"@scure/base@npm:~1.1.0, @scure/base@npm:~1.1.2": - version: 1.1.5 - resolution: "@scure/base@npm:1.1.5" - checksum: 9e9ee6088cb3aa0fb91f5a48497d26682c7829df3019b1251d088d166d7a8c0f941c68aaa8e7b96bbad20c71eb210397cb1099062cde3e29d4bad6b975c18519 +"@scure/base@npm:~1.1.0, @scure/base@npm:~1.1.2, @scure/base@npm:~1.1.4": + version: 1.1.6 + resolution: "@scure/base@npm:1.1.6" + checksum: d6deaae91deba99e87939af9e55d80edba302674983f32bba57f942e22b1726a83c62dc50d8f4370a5d5d35a212dda167fb169f4b0d0c297488d8604608fc3d3 languageName: node linkType: hard @@ -2840,6 +2934,17 @@ __metadata: languageName: node linkType: hard +"@scure/bip32@npm:1.3.3": + version: 1.3.3 + resolution: "@scure/bip32@npm:1.3.3" + dependencies: + "@noble/curves": ~1.3.0 + "@noble/hashes": ~1.3.2 + "@scure/base": ~1.1.4 + checksum: f939ca733972622fcc1e61d4fdf170a0ad294b24ddb7ed7cdd4c467e1ef283b970154cb101cf5f1a7b64cf5337e917ad31135911dfc36b1d76625320167df2fa + languageName: node + linkType: hard + "@scure/bip39@npm:1.2.1": version: 1.2.1 resolution: "@scure/bip39@npm:1.2.1" @@ -2850,6 +2955,16 @@ __metadata: languageName: node linkType: hard +"@scure/bip39@npm:1.2.2": + version: 1.2.2 + resolution: "@scure/bip39@npm:1.2.2" + dependencies: + "@noble/hashes": ~1.3.2 + "@scure/base": ~1.1.4 + checksum: cb99505e6d2deef8e55e81df8c563ce8dbfdf1595596dc912bceadcf366c91b05a98130e928ecb090df74efdb20150b64acc4be55bc42768cab4d39a2833d234 + languageName: node + linkType: hard + "@sinclair/typebox@npm:^0.27.8": version: 0.27.8 resolution: "@sinclair/typebox@npm:0.27.8" @@ -2875,90 +2990,90 @@ __metadata: languageName: node linkType: hard -"@swc/core-darwin-arm64@npm:1.4.11": - version: 1.4.11 - resolution: "@swc/core-darwin-arm64@npm:1.4.11" +"@swc/core-darwin-arm64@npm:1.4.16": + version: 1.4.16 + resolution: "@swc/core-darwin-arm64@npm:1.4.16" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@swc/core-darwin-x64@npm:1.4.11": - version: 1.4.11 - resolution: "@swc/core-darwin-x64@npm:1.4.11" +"@swc/core-darwin-x64@npm:1.4.16": + version: 1.4.16 + resolution: "@swc/core-darwin-x64@npm:1.4.16" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@swc/core-linux-arm-gnueabihf@npm:1.4.11": - version: 1.4.11 - resolution: "@swc/core-linux-arm-gnueabihf@npm:1.4.11" +"@swc/core-linux-arm-gnueabihf@npm:1.4.16": + version: 1.4.16 + resolution: "@swc/core-linux-arm-gnueabihf@npm:1.4.16" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@swc/core-linux-arm64-gnu@npm:1.4.11": - version: 1.4.11 - resolution: "@swc/core-linux-arm64-gnu@npm:1.4.11" +"@swc/core-linux-arm64-gnu@npm:1.4.16": + version: 1.4.16 + resolution: "@swc/core-linux-arm64-gnu@npm:1.4.16" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-arm64-musl@npm:1.4.11": - version: 1.4.11 - resolution: "@swc/core-linux-arm64-musl@npm:1.4.11" +"@swc/core-linux-arm64-musl@npm:1.4.16": + version: 1.4.16 + resolution: "@swc/core-linux-arm64-musl@npm:1.4.16" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@swc/core-linux-x64-gnu@npm:1.4.11": - version: 1.4.11 - resolution: "@swc/core-linux-x64-gnu@npm:1.4.11" +"@swc/core-linux-x64-gnu@npm:1.4.16": + version: 1.4.16 + resolution: "@swc/core-linux-x64-gnu@npm:1.4.16" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-x64-musl@npm:1.4.11": - version: 1.4.11 - resolution: "@swc/core-linux-x64-musl@npm:1.4.11" +"@swc/core-linux-x64-musl@npm:1.4.16": + version: 1.4.16 + resolution: "@swc/core-linux-x64-musl@npm:1.4.16" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@swc/core-win32-arm64-msvc@npm:1.4.11": - version: 1.4.11 - resolution: "@swc/core-win32-arm64-msvc@npm:1.4.11" +"@swc/core-win32-arm64-msvc@npm:1.4.16": + version: 1.4.16 + resolution: "@swc/core-win32-arm64-msvc@npm:1.4.16" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@swc/core-win32-ia32-msvc@npm:1.4.11": - version: 1.4.11 - resolution: "@swc/core-win32-ia32-msvc@npm:1.4.11" +"@swc/core-win32-ia32-msvc@npm:1.4.16": + version: 1.4.16 + resolution: "@swc/core-win32-ia32-msvc@npm:1.4.16" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@swc/core-win32-x64-msvc@npm:1.4.11": - version: 1.4.11 - resolution: "@swc/core-win32-x64-msvc@npm:1.4.11" +"@swc/core-win32-x64-msvc@npm:1.4.16": + version: 1.4.16 + resolution: "@swc/core-win32-x64-msvc@npm:1.4.16" conditions: os=win32 & cpu=x64 languageName: node linkType: hard "@swc/core@npm:^1.4.11": - version: 1.4.11 - resolution: "@swc/core@npm:1.4.11" - dependencies: - "@swc/core-darwin-arm64": 1.4.11 - "@swc/core-darwin-x64": 1.4.11 - "@swc/core-linux-arm-gnueabihf": 1.4.11 - "@swc/core-linux-arm64-gnu": 1.4.11 - "@swc/core-linux-arm64-musl": 1.4.11 - "@swc/core-linux-x64-gnu": 1.4.11 - "@swc/core-linux-x64-musl": 1.4.11 - "@swc/core-win32-arm64-msvc": 1.4.11 - "@swc/core-win32-ia32-msvc": 1.4.11 - "@swc/core-win32-x64-msvc": 1.4.11 + version: 1.4.16 + resolution: "@swc/core@npm:1.4.16" + dependencies: + "@swc/core-darwin-arm64": 1.4.16 + "@swc/core-darwin-x64": 1.4.16 + "@swc/core-linux-arm-gnueabihf": 1.4.16 + "@swc/core-linux-arm64-gnu": 1.4.16 + "@swc/core-linux-arm64-musl": 1.4.16 + "@swc/core-linux-x64-gnu": 1.4.16 + "@swc/core-linux-x64-musl": 1.4.16 + "@swc/core-win32-arm64-msvc": 1.4.16 + "@swc/core-win32-ia32-msvc": 1.4.16 + "@swc/core-win32-x64-msvc": 1.4.16 "@swc/counter": ^0.1.2 "@swc/types": ^0.1.5 peerDependencies: @@ -2987,7 +3102,7 @@ __metadata: peerDependenciesMeta: "@swc/helpers": optional: true - checksum: 3af0cbfc89c2fc06ac7796e4c7e584a534fb21d2a9e688fe9b53192b09b41f5c7c9b6aa39ac89c32aead245966f00283240c898de501ea8908d2f392e999dc9b + checksum: 67b72646a70c7b5967b0e2f3511bab9451285c7c24f107347ff92cea04ae61c76eb6e8c688f04d1bff2541134519f4a625005811be3b0f7670d1dad1167cc1fc languageName: node linkType: hard @@ -3048,9 +3163,9 @@ __metadata: linkType: hard "@tsconfig/node10@npm:^1.0.7": - version: 1.0.9 - resolution: "@tsconfig/node10@npm:1.0.9" - checksum: a33ae4dc2a621c0678ac8ac4bceb8e512ae75dac65417a2ad9b022d9b5411e863c4c198b6ba9ef659e14b9fb609bbec680841a2e84c1172df7a5ffcf076539df + version: 1.0.11 + resolution: "@tsconfig/node10@npm:1.0.11" + checksum: 51fe47d55fe1b80ec35e6e5ed30a13665fd3a531945350aa74a14a1e82875fb60b350c2f2a5e72a64831b1b6bc02acb6760c30b3738b54954ec2dea82db7a267 languageName: node linkType: hard @@ -3175,14 +3290,14 @@ __metadata: linkType: hard "@types/cookies@npm:*": - version: 0.7.10 - resolution: "@types/cookies@npm:0.7.10" + version: 0.9.0 + resolution: "@types/cookies@npm:0.9.0" dependencies: "@types/connect": "*" "@types/express": "*" "@types/keygrip": "*" "@types/node": "*" - checksum: 99cd44a193398932ff7926cfaac1eb4441d3dc47c3f64fdfb28861acbeb290b6db6a20376f993defc9d302db92bb1d36189b89ba447a633f960535f3f0d34e2d + checksum: ce59bfdf3a5d750400ac32aa93157ec7be997dc632660cf0bbfd76df23d71a70bb5f0820558cd26b9a5576f86b6664a2fd23ae211b51202a5b2f9a15995d7331 languageName: node linkType: hard @@ -3202,6 +3317,15 @@ __metadata: languageName: node linkType: hard +"@types/dns-packet@npm:^5.6.5": + version: 5.6.5 + resolution: "@types/dns-packet@npm:5.6.5" + dependencies: + "@types/node": "*" + checksum: f7708c16ec367b14d75f3e662279911c17b5fdc2347389a21fc3c5d2b46400efd5446a3a45b6940a404e90d2e7b260d01041ca7764970d917241a5d4a5073936 + languageName: node + linkType: hard + "@types/elliptic@npm:^6.4.16": version: 6.4.18 resolution: "@types/elliptic@npm:6.4.18" @@ -3222,12 +3346,12 @@ __metadata: linkType: hard "@types/eslint@npm:*": - version: 8.56.2 - resolution: "@types/eslint@npm:8.56.2" + version: 8.56.10 + resolution: "@types/eslint@npm:8.56.10" dependencies: "@types/estree": "*" "@types/json-schema": "*" - checksum: 38e054971596f5c0413f66a62dc26b10e0a21ac46ceacb06fbf8cfb838d20820787209b17218b3916e4c23d990ff77cfdb482d655cac0e0d2b837d430fcc5db8 + checksum: fb7137dd263ce1130b42d14452bdd0266ef81f52cb55ba1a5e9750e65da1f0596dc598c88bffc7e415458b6cb611a876dcc132bcf40ea48701c6d05b40c57be5 languageName: node linkType: hard @@ -3239,14 +3363,14 @@ __metadata: linkType: hard "@types/express-serve-static-core@npm:^4.17.33": - version: 4.17.42 - resolution: "@types/express-serve-static-core@npm:4.17.42" + version: 4.19.0 + resolution: "@types/express-serve-static-core@npm:4.19.0" dependencies: "@types/node": "*" "@types/qs": "*" "@types/range-parser": "*" "@types/send": "*" - checksum: 58273f80fcc94de42691f48e22542e69f0b17863378e3216ce8b782ace012f32241bfeb02a2be837f0e2b4ef96e916979adc30bbfea13f6545bd3ab81b7d2773 + checksum: 39c09fcb3f61de96ed56d97273874cafe50e6675ac254af4d77014e569e4fdc29d1d0d1dd12e11f008cb9a52785b07c2801c6ba91397965392b20c75ee01fb4e languageName: node linkType: hard @@ -3321,12 +3445,12 @@ __metadata: linkType: hard "@types/jest@npm:^29.5.0": - version: 29.5.11 - resolution: "@types/jest@npm:29.5.11" + version: 29.5.12 + resolution: "@types/jest@npm:29.5.12" dependencies: expect: ^29.0.0 pretty-format: ^29.0.0 - checksum: f892a06ec9f0afa9a61cd7fa316ec614e21d4df1ad301b5a837787e046fcb40dfdf7f264a55e813ac6b9b633cb9d366bd5b8d1cea725e84102477b366df23fdd + checksum: 19b1efdeed9d9a60a81edc8226cdeae5af7479e493eaed273e01243891c9651f7b8b4c08fc633a7d0d1d379b091c4179bbaa0807af62542325fd72f2dd17ce1c languageName: node linkType: hard @@ -3426,8 +3550,8 @@ __metadata: linkType: hard "@types/koa@npm:*, @types/koa@npm:^2.13.5, @types/koa@npm:^2.13.6, @types/koa@npm:^2.13.9": - version: 2.14.0 - resolution: "@types/koa@npm:2.14.0" + version: 2.15.0 + resolution: "@types/koa@npm:2.15.0" dependencies: "@types/accepts": "*" "@types/content-disposition": "*" @@ -3437,7 +3561,7 @@ __metadata: "@types/keygrip": "*" "@types/koa-compose": "*" "@types/node": "*" - checksum: 57d809e42350c9ddefa2150306355e40757877468bb027e0bd99f5aeb43cfaf8ba8b14761ea65e419d6fb4c2403a1f3ed0762872a9cf040dbd14357caca56548 + checksum: f429b92f36f96c8f5ceb5333f982400d0db20e177b7d89a7a576ac6f63aff8c964f7ab313e2e281a07bbb93931c66327fb42614cd4984b2ef33dfe7cbd76d741 languageName: node linkType: hard @@ -3596,9 +3720,9 @@ __metadata: linkType: hard "@types/lodash@npm:*": - version: 4.14.202 - resolution: "@types/lodash@npm:4.14.202" - checksum: a91acf3564a568c6f199912f3eb2c76c99c5a0d7e219394294213b3f2d54f672619f0fde4da22b29dc5d4c31457cd799acc2e5cb6bd90f9af04a1578483b6ff7 + version: 4.17.0 + resolution: "@types/lodash@npm:4.17.0" + checksum: 3f98c0b67a93994cbc3403d4fa9dbaf52b0b6bb7f07a764d73875c2dcd5ef91222621bd5bcf8eee7b417a74d175c2f7191b9f595f8603956fd06f0674c0cba93 languageName: node linkType: hard @@ -3618,13 +3742,6 @@ __metadata: languageName: node linkType: hard -"@types/mime@npm:*": - version: 3.0.4 - resolution: "@types/mime@npm:3.0.4" - checksum: a6139c8e1f705ef2b064d072f6edc01f3c099023ad7c4fce2afc6c2bf0231888202adadbdb48643e8e20da0ce409481a49922e737eca52871b3dc08017455843 - languageName: node - linkType: hard - "@types/mime@npm:^1": version: 1.3.5 resolution: "@types/mime@npm:1.3.5" @@ -3647,20 +3764,20 @@ __metadata: linkType: hard "@types/node@npm:*": - version: 20.11.7 - resolution: "@types/node@npm:20.11.7" + version: 20.12.7 + resolution: "@types/node@npm:20.12.7" dependencies: undici-types: ~5.26.4 - checksum: 61ea0718bccda31110c643190518407b7c50d26698a20e3522871608db5fa3d2d43d1ae57c609068eae6996d563db43326045a90f22a9aacc825e8d6c7aea2ce + checksum: 7cc979f7e2ca9a339ec71318c3901b9978555257929ef3666987f3e447123bc6dc92afcc89f6347e09e07d602fde7d51bcddea626c23aa2bb74aeaacfd1e1686 languageName: node linkType: hard "@types/node@npm:^18.14.6, @types/node@npm:^18.15.11, @types/node@npm:^18.15.3, @types/node@npm:^18.7.23": - version: 18.19.10 - resolution: "@types/node@npm:18.19.10" + version: 18.19.31 + resolution: "@types/node@npm:18.19.31" dependencies: undici-types: ~5.26.4 - checksum: eea429c1fe8d25702c1e860f5c4ac053db3c52a5884646f458513b622a507660a6c88c717ee4f106e63c82f4ec6cafbf999e3f3f1d3083f7a40b4f715e03332b + checksum: 949bddfd7071bd47300d1f33d380ee34695ccd5f046f1a03e4d2be0d953ace896905144d44a6f483f241b5ef34b86f0e40a0e312201117782eecf89e81a4ff13 languageName: node linkType: hard @@ -3679,9 +3796,9 @@ __metadata: linkType: hard "@types/qs@npm:*": - version: 6.9.11 - resolution: "@types/qs@npm:6.9.11" - checksum: 620ca1628bf3da65662c54ed6ebb120b18a3da477d0bfcc872b696685a9bb1893c3c92b53a1190a8f54d52eaddb6af8b2157755699ac83164604329935e8a7f2 + version: 6.9.15 + resolution: "@types/qs@npm:6.9.15" + checksum: 97d8208c2b82013b618e7a9fc14df6bd40a73e1385ac479b6896bafc7949a46201c15f42afd06e86a05e914f146f495f606b6fb65610cc60cf2e0ff743ec38a2 languageName: node linkType: hard @@ -3692,17 +3809,10 @@ __metadata: languageName: node linkType: hard -"@types/retry@npm:0.12.2": - version: 0.12.2 - resolution: "@types/retry@npm:0.12.2" - checksum: e5675035717b39ce4f42f339657cae9637cf0c0051cf54314a6a2c44d38d91f6544be9ddc0280587789b6afd056be5d99dbe3e9f4df68c286c36321579b1bf4a - languageName: node - linkType: hard - "@types/semver@npm:^7.5.0, @types/semver@npm:^7.5.4": - version: 7.5.6 - resolution: "@types/semver@npm:7.5.6" - checksum: 563a0120ec0efcc326567db2ed920d5d98346f3638b6324ea6b50222b96f02a8add3c51a916b6897b51523aad8ac227d21d3dcf8913559f1bfc6c15b14d23037 + version: 7.5.8 + resolution: "@types/semver@npm:7.5.8" + checksum: ea6f5276f5b84c55921785a3a27a3cd37afee0111dfe2bcb3e03c31819c197c782598f17f0b150a69d453c9584cd14c4c4d7b9a55d2c5e6cacd4d66fdb3b3663 languageName: node linkType: hard @@ -3717,13 +3827,13 @@ __metadata: linkType: hard "@types/serve-static@npm:*": - version: 1.15.5 - resolution: "@types/serve-static@npm:1.15.5" + version: 1.15.7 + resolution: "@types/serve-static@npm:1.15.7" dependencies: "@types/http-errors": "*" - "@types/mime": "*" "@types/node": "*" - checksum: 0ff4b3703cf20ba89c9f9e345bc38417860a88e85863c8d6fe274a543220ab7f5f647d307c60a71bb57dc9559f0890a661e8dc771a6ec5ef195d91c8afc4a893 + "@types/send": "*" + checksum: bbbf00dbd84719da2250a462270dc68964006e8d62f41fe3741abd94504ba3688f420a49afb2b7478921a1544d3793183ffa097c5724167da777f4e0c7f1a7d6 languageName: node linkType: hard @@ -3736,7 +3846,7 @@ __metadata: languageName: node linkType: hard -"@types/sinon@npm:^17.0.0": +"@types/sinon@npm:^17.0.0, @types/sinon@npm:^17.0.3": version: 17.0.3 resolution: "@types/sinon@npm:17.0.3" dependencies: @@ -3769,13 +3879,13 @@ __metadata: linkType: hard "@types/superagent@npm:*": - version: 8.1.3 - resolution: "@types/superagent@npm:8.1.3" + version: 8.1.6 + resolution: "@types/superagent@npm:8.1.6" dependencies: "@types/cookiejar": ^2.1.5 "@types/methods": ^1.1.4 "@types/node": "*" - checksum: 284307f88986b733fc22ede29d0660f26e7e2d4f8ee7bf772544633404e5d21026bfb202b7c3aedab1bedf6e9276e96fbebc6e07cc2163e6729d5a36dc842215 + checksum: 240ea5a58bb3c9e53f0dbe1ccd1bfe046e084fffdb4eaf44f0bf846fb98dad98ce03d057fdfb555bfa06afbb76a0e5877fe639750b798edac594bc7e19833934 languageName: node linkType: hard @@ -3830,14 +3940,14 @@ __metadata: linkType: hard "@typescript-eslint/eslint-plugin@npm:^6.2.1": - version: 6.19.1 - resolution: "@typescript-eslint/eslint-plugin@npm:6.19.1" + version: 6.21.0 + resolution: "@typescript-eslint/eslint-plugin@npm:6.21.0" dependencies: "@eslint-community/regexpp": ^4.5.1 - "@typescript-eslint/scope-manager": 6.19.1 - "@typescript-eslint/type-utils": 6.19.1 - "@typescript-eslint/utils": 6.19.1 - "@typescript-eslint/visitor-keys": 6.19.1 + "@typescript-eslint/scope-manager": 6.21.0 + "@typescript-eslint/type-utils": 6.21.0 + "@typescript-eslint/utils": 6.21.0 + "@typescript-eslint/visitor-keys": 6.21.0 debug: ^4.3.4 graphemer: ^1.4.0 ignore: ^5.2.4 @@ -3850,44 +3960,44 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: ad04000cd6c15d864ff92655baa3aec99bb0ccf4714fedd145fedde60a27590a5feafe480beb2f0f3864b416098bde1e9431bada7480eb7ca4efad891e1d2f6f + checksum: 5ef2c502255e643e98051e87eb682c2a257e87afd8ec3b9f6274277615e1c2caf3131b352244cfb1987b8b2c415645eeacb9113fa841fc4c9b2ac46e8aed6efd languageName: node linkType: hard "@typescript-eslint/parser@npm:^6.2.1": - version: 6.19.1 - resolution: "@typescript-eslint/parser@npm:6.19.1" + version: 6.21.0 + resolution: "@typescript-eslint/parser@npm:6.21.0" dependencies: - "@typescript-eslint/scope-manager": 6.19.1 - "@typescript-eslint/types": 6.19.1 - "@typescript-eslint/typescript-estree": 6.19.1 - "@typescript-eslint/visitor-keys": 6.19.1 + "@typescript-eslint/scope-manager": 6.21.0 + "@typescript-eslint/types": 6.21.0 + "@typescript-eslint/typescript-estree": 6.21.0 + "@typescript-eslint/visitor-keys": 6.21.0 debug: ^4.3.4 peerDependencies: eslint: ^7.0.0 || ^8.0.0 peerDependenciesMeta: typescript: optional: true - checksum: cd29619da08a2d9b7123ba4d8240989c747f8e0d5672179d8b147e413ee1334d1fa48570b0c37cf0ae4e26a275fd2d268cbe702c6fed639d3331abbb3292570a + checksum: 162fe3a867eeeffda7328bce32dae45b52283c68c8cb23258fb9f44971f761991af61f71b8c9fe1aa389e93dfe6386f8509c1273d870736c507d76dd40647b68 languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:6.19.1": - version: 6.19.1 - resolution: "@typescript-eslint/scope-manager@npm:6.19.1" +"@typescript-eslint/scope-manager@npm:6.21.0": + version: 6.21.0 + resolution: "@typescript-eslint/scope-manager@npm:6.21.0" dependencies: - "@typescript-eslint/types": 6.19.1 - "@typescript-eslint/visitor-keys": 6.19.1 - checksum: 848cdebc16a3803e8a6d6035a7067605309a652bb2425f475f755b5ace4d80d2c17c8c8901f0f4759556da8d0a5b71024d472b85c3f3c70d0e6dcfe2a972ef35 + "@typescript-eslint/types": 6.21.0 + "@typescript-eslint/visitor-keys": 6.21.0 + checksum: 71028b757da9694528c4c3294a96cc80bc7d396e383a405eab3bc224cda7341b88e0fc292120b35d3f31f47beac69f7083196c70616434072fbcd3d3e62d3376 languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:6.19.1": - version: 6.19.1 - resolution: "@typescript-eslint/type-utils@npm:6.19.1" +"@typescript-eslint/type-utils@npm:6.21.0": + version: 6.21.0 + resolution: "@typescript-eslint/type-utils@npm:6.21.0" dependencies: - "@typescript-eslint/typescript-estree": 6.19.1 - "@typescript-eslint/utils": 6.19.1 + "@typescript-eslint/typescript-estree": 6.21.0 + "@typescript-eslint/utils": 6.21.0 debug: ^4.3.4 ts-api-utils: ^1.0.1 peerDependencies: @@ -3895,7 +4005,7 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: eab1a30f8d85f7c6e2545de5963fbec2f3bb91913d59623069b4b0db372a671ab048c7018376fc853c3af06ea39417f3e7b27dd665027dd812347a5e64cecd77 + checksum: 77025473f4d80acf1fafcce99c5c283e557686a61861febeba9c9913331f8a41e930bf5cd8b7a54db502a57b6eb8ea6d155cbd4f41349ed00e3d7aeb1f477ddc languageName: node linkType: hard @@ -3913,19 +4023,19 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/types@npm:6.19.1": - version: 6.19.1 - resolution: "@typescript-eslint/types@npm:6.19.1" - checksum: 598ce222b59c20432d06f60703d0c2dd16d9b2151569c192852136c57b8188e3ef6ef9fddaa2c136c9a756fcc7d873c0e29ec41cfd340564842287ef7b4571cd +"@typescript-eslint/types@npm:6.21.0": + version: 6.21.0 + resolution: "@typescript-eslint/types@npm:6.21.0" + checksum: 9501b47d7403417af95fc1fb72b2038c5ac46feac0e1598a46bcb43e56a606c387e9dcd8a2a0abe174c91b509f2d2a8078b093786219eb9a01ab2fbf9ee7b684 languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:6.19.1": - version: 6.19.1 - resolution: "@typescript-eslint/typescript-estree@npm:6.19.1" +"@typescript-eslint/typescript-estree@npm:6.21.0": + version: 6.21.0 + resolution: "@typescript-eslint/typescript-estree@npm:6.21.0" dependencies: - "@typescript-eslint/types": 6.19.1 - "@typescript-eslint/visitor-keys": 6.19.1 + "@typescript-eslint/types": 6.21.0 + "@typescript-eslint/visitor-keys": 6.21.0 debug: ^4.3.4 globby: ^11.1.0 is-glob: ^4.0.3 @@ -3935,7 +4045,7 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: fb71a14aeee0468780219c5b8d39075f85d360b04ccd0ee88f4f0a615d2c232a6d3016e36d8c6eda2d9dfda86b4f4cc2c3d7582940fb29d33c7cf305e124d4e2 + checksum: dec02dc107c4a541e14fb0c96148f3764b92117c3b635db3a577b5a56fc48df7a556fa853fb82b07c0663b4bf2c484c9f245c28ba3e17e5cb0918ea4cab2ea21 languageName: node linkType: hard @@ -3975,20 +4085,20 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/utils@npm:6.19.1": - version: 6.19.1 - resolution: "@typescript-eslint/utils@npm:6.19.1" +"@typescript-eslint/utils@npm:6.21.0": + version: 6.21.0 + resolution: "@typescript-eslint/utils@npm:6.21.0" dependencies: "@eslint-community/eslint-utils": ^4.4.0 "@types/json-schema": ^7.0.12 "@types/semver": ^7.5.0 - "@typescript-eslint/scope-manager": 6.19.1 - "@typescript-eslint/types": 6.19.1 - "@typescript-eslint/typescript-estree": 6.19.1 + "@typescript-eslint/scope-manager": 6.21.0 + "@typescript-eslint/types": 6.21.0 + "@typescript-eslint/typescript-estree": 6.21.0 semver: ^7.5.4 peerDependencies: eslint: ^7.0.0 || ^8.0.0 - checksum: fe72e75c3ea17a85772b83f148555ea94ff5d55d13586f3fc038833197a74f8071e14c2bbf1781c40eec20005f052f4be2513a725eea82a15da3cb9af3046c70 + checksum: b129b3a4aebec8468259f4589985cb59ea808afbfdb9c54f02fad11e17d185e2bf72bb332f7c36ec3c09b31f18fc41368678b076323e6e019d06f74ee93f7bf2 languageName: node linkType: hard @@ -4012,13 +4122,13 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:6.19.1": - version: 6.19.1 - resolution: "@typescript-eslint/visitor-keys@npm:6.19.1" +"@typescript-eslint/visitor-keys@npm:6.21.0": + version: 6.21.0 + resolution: "@typescript-eslint/visitor-keys@npm:6.21.0" dependencies: - "@typescript-eslint/types": 6.19.1 + "@typescript-eslint/types": 6.21.0 eslint-visitor-keys: ^3.4.1 - checksum: bdf057a42e776970a89cdd568e493e3ea7ec085544d8f318d33084da63c3395ad2c0fb9cef9f61ceeca41f5dab54ab064b7078fe596889005e412ec74d2d1ae4 + checksum: 67c7e6003d5af042d8703d11538fca9d76899f0119130b373402819ae43f0bc90d18656aa7add25a24427ccf1a0efd0804157ba83b0d4e145f06107d7d1b7433 languageName: node linkType: hard @@ -4041,13 +4151,13 @@ __metadata: languageName: node linkType: hard -"@webassemblyjs/ast@npm:1.11.6, @webassemblyjs/ast@npm:^1.11.5": - version: 1.11.6 - resolution: "@webassemblyjs/ast@npm:1.11.6" +"@webassemblyjs/ast@npm:1.12.1, @webassemblyjs/ast@npm:^1.12.1": + version: 1.12.1 + resolution: "@webassemblyjs/ast@npm:1.12.1" dependencies: "@webassemblyjs/helper-numbers": 1.11.6 "@webassemblyjs/helper-wasm-bytecode": 1.11.6 - checksum: 38ef1b526ca47c210f30975b06df2faf1a8170b1636ce239fc5738fc231ce28389dd61ecedd1bacfc03cbe95b16d1af848c805652080cb60982836eb4ed2c6cf + checksum: 31bcc64147236bd7b1b6d29d1f419c1f5845c785e1e42dc9e3f8ca2e05a029e9393a271b84f3a5bff2a32d35f51ff59e2181a6e5f953fe88576acd6750506202 languageName: node linkType: hard @@ -4065,10 +4175,10 @@ __metadata: languageName: node linkType: hard -"@webassemblyjs/helper-buffer@npm:1.11.6": - version: 1.11.6 - resolution: "@webassemblyjs/helper-buffer@npm:1.11.6" - checksum: b14d0573bf680d22b2522e8a341ec451fddd645d1f9c6bd9012ccb7e587a2973b86ab7b89fe91e1c79939ba96095f503af04369a3b356c8023c13a5893221644 +"@webassemblyjs/helper-buffer@npm:1.12.1": + version: 1.12.1 + resolution: "@webassemblyjs/helper-buffer@npm:1.12.1" + checksum: c3ffb723024130308db608e86e2bdccd4868bbb62dffb0a9a1530606496f79c87f8565bd8e02805ce64912b71f1a70ee5fb00307258b0c082c3abf961d097eca languageName: node linkType: hard @@ -4090,15 +4200,15 @@ __metadata: languageName: node linkType: hard -"@webassemblyjs/helper-wasm-section@npm:1.11.6": - version: 1.11.6 - resolution: "@webassemblyjs/helper-wasm-section@npm:1.11.6" +"@webassemblyjs/helper-wasm-section@npm:1.12.1": + version: 1.12.1 + resolution: "@webassemblyjs/helper-wasm-section@npm:1.12.1" dependencies: - "@webassemblyjs/ast": 1.11.6 - "@webassemblyjs/helper-buffer": 1.11.6 + "@webassemblyjs/ast": 1.12.1 + "@webassemblyjs/helper-buffer": 1.12.1 "@webassemblyjs/helper-wasm-bytecode": 1.11.6 - "@webassemblyjs/wasm-gen": 1.11.6 - checksum: b2cf751bf4552b5b9999d27bbb7692d0aca75260140195cb58ea6374d7b9c2dc69b61e10b211a0e773f66209c3ddd612137ed66097e3684d7816f854997682e9 + "@webassemblyjs/wasm-gen": 1.12.1 + checksum: c19810cdd2c90ff574139b6d8c0dda254d42d168a9e5b3d353d1bc085f1d7164ccd1b3c05592a45a939c47f7e403dc8d03572bb686642f06a3d02932f6f0bc8f languageName: node linkType: hard @@ -4127,68 +4237,68 @@ __metadata: languageName: node linkType: hard -"@webassemblyjs/wasm-edit@npm:^1.11.5": - version: 1.11.6 - resolution: "@webassemblyjs/wasm-edit@npm:1.11.6" +"@webassemblyjs/wasm-edit@npm:^1.12.1": + version: 1.12.1 + resolution: "@webassemblyjs/wasm-edit@npm:1.12.1" dependencies: - "@webassemblyjs/ast": 1.11.6 - "@webassemblyjs/helper-buffer": 1.11.6 + "@webassemblyjs/ast": 1.12.1 + "@webassemblyjs/helper-buffer": 1.12.1 "@webassemblyjs/helper-wasm-bytecode": 1.11.6 - "@webassemblyjs/helper-wasm-section": 1.11.6 - "@webassemblyjs/wasm-gen": 1.11.6 - "@webassemblyjs/wasm-opt": 1.11.6 - "@webassemblyjs/wasm-parser": 1.11.6 - "@webassemblyjs/wast-printer": 1.11.6 - checksum: 29ce75870496d6fad864d815ebb072395a8a3a04dc9c3f4e1ffdc63fc5fa58b1f34304a1117296d8240054cfdbc38aca88e71fb51483cf29ffab0a61ef27b481 + "@webassemblyjs/helper-wasm-section": 1.12.1 + "@webassemblyjs/wasm-gen": 1.12.1 + "@webassemblyjs/wasm-opt": 1.12.1 + "@webassemblyjs/wasm-parser": 1.12.1 + "@webassemblyjs/wast-printer": 1.12.1 + checksum: ae23642303f030af888d30c4ef37b08dfec7eab6851a9575a616e65d1219f880d9223913a39056dd654e49049d76e97555b285d1f7e56935047abf578cce0692 languageName: node linkType: hard -"@webassemblyjs/wasm-gen@npm:1.11.6": - version: 1.11.6 - resolution: "@webassemblyjs/wasm-gen@npm:1.11.6" +"@webassemblyjs/wasm-gen@npm:1.12.1": + version: 1.12.1 + resolution: "@webassemblyjs/wasm-gen@npm:1.12.1" dependencies: - "@webassemblyjs/ast": 1.11.6 + "@webassemblyjs/ast": 1.12.1 "@webassemblyjs/helper-wasm-bytecode": 1.11.6 "@webassemblyjs/ieee754": 1.11.6 "@webassemblyjs/leb128": 1.11.6 "@webassemblyjs/utf8": 1.11.6 - checksum: a645a2eecbea24833c3260a249704a7f554ef4a94c6000984728e94bb2bc9140a68dfd6fd21d5e0bbb09f6dfc98e083a45760a83ae0417b41a0196ff6d45a23a + checksum: 5787626bb7f0b033044471ddd00ce0c9fe1ee4584e8b73e232051e3a4c99ba1a102700d75337151c8b6055bae77eefa4548960c610a5e4a504e356bd872138ff languageName: node linkType: hard -"@webassemblyjs/wasm-opt@npm:1.11.6": - version: 1.11.6 - resolution: "@webassemblyjs/wasm-opt@npm:1.11.6" +"@webassemblyjs/wasm-opt@npm:1.12.1": + version: 1.12.1 + resolution: "@webassemblyjs/wasm-opt@npm:1.12.1" dependencies: - "@webassemblyjs/ast": 1.11.6 - "@webassemblyjs/helper-buffer": 1.11.6 - "@webassemblyjs/wasm-gen": 1.11.6 - "@webassemblyjs/wasm-parser": 1.11.6 - checksum: b4557f195487f8e97336ddf79f7bef40d788239169aac707f6eaa2fa5fe243557c2d74e550a8e57f2788e70c7ae4e7d32f7be16101afe183d597b747a3bdd528 + "@webassemblyjs/ast": 1.12.1 + "@webassemblyjs/helper-buffer": 1.12.1 + "@webassemblyjs/wasm-gen": 1.12.1 + "@webassemblyjs/wasm-parser": 1.12.1 + checksum: 0e8fa8a0645304a1e18ff40d3db5a2e9233ebaa169b19fcc651d6fc9fe2cac0ce092ddee927318015ae735d9cd9c5d97c0cafb6a51dcd2932ac73587b62df991 languageName: node linkType: hard -"@webassemblyjs/wasm-parser@npm:1.11.6, @webassemblyjs/wasm-parser@npm:^1.11.5": - version: 1.11.6 - resolution: "@webassemblyjs/wasm-parser@npm:1.11.6" +"@webassemblyjs/wasm-parser@npm:1.12.1, @webassemblyjs/wasm-parser@npm:^1.12.1": + version: 1.12.1 + resolution: "@webassemblyjs/wasm-parser@npm:1.12.1" dependencies: - "@webassemblyjs/ast": 1.11.6 + "@webassemblyjs/ast": 1.12.1 "@webassemblyjs/helper-api-error": 1.11.6 "@webassemblyjs/helper-wasm-bytecode": 1.11.6 "@webassemblyjs/ieee754": 1.11.6 "@webassemblyjs/leb128": 1.11.6 "@webassemblyjs/utf8": 1.11.6 - checksum: 8200a8d77c15621724a23fdabe58d5571415cda98a7058f542e670ea965dd75499f5e34a48675184947c66f3df23adf55df060312e6d72d57908e3f049620d8a + checksum: 176015de3551ac068cd4505d837414f258d9ade7442bd71efb1232fa26c9f6d7d4e11a5c816caeed389943f409af7ebff6899289a992d7a70343cb47009d21a8 languageName: node linkType: hard -"@webassemblyjs/wast-printer@npm:1.11.6": - version: 1.11.6 - resolution: "@webassemblyjs/wast-printer@npm:1.11.6" +"@webassemblyjs/wast-printer@npm:1.12.1": + version: 1.12.1 + resolution: "@webassemblyjs/wast-printer@npm:1.12.1" dependencies: - "@webassemblyjs/ast": 1.11.6 + "@webassemblyjs/ast": 1.12.1 "@xtuc/long": 4.2.2 - checksum: d2fa6a4c427325ec81463e9c809aa6572af6d47f619f3091bf4c4a6fc34f1da3df7caddaac50b8e7a457f8784c62cd58c6311b6cb69b0162ccd8d4c072f79cf8 + checksum: 2974b5dda8d769145ba0efd886ea94a601e61fb37114c14f9a9a7606afc23456799af652ac3052f284909bd42edc3665a76bc9b50f95f0794c053a8a1757b713 languageName: node linkType: hard @@ -4342,12 +4452,12 @@ __metadata: languageName: node linkType: hard -"agent-base@npm:^7.0.2, agent-base@npm:^7.1.0": - version: 7.1.0 - resolution: "agent-base@npm:7.1.0" +"agent-base@npm:^7.0.2, agent-base@npm:^7.1.0, agent-base@npm:^7.1.1": + version: 7.1.1 + resolution: "agent-base@npm:7.1.1" dependencies: debug: ^4.3.4 - checksum: f7828f991470a0cc22cb579c86a18cbae83d8a3cbed39992ab34fc7217c4d126017f1c74d0ab66be87f71455318a8ea3e757d6a37881b8d0f2a2c6aa55e5418f + checksum: 51c158769c5c051482f9ca2e6e1ec085ac72b5a418a9b31b4e82fe6c0a6699adb94c1c42d246699a587b3335215037091c79e0de512c516f73b6ea844202f037 languageName: node linkType: hard @@ -4482,13 +4592,6 @@ __metadata: languageName: node linkType: hard -"arg@npm:^5.0.2": - version: 5.0.2 - resolution: "arg@npm:5.0.2" - checksum: 6c69ada1a9943d332d9e5382393e897c500908d91d5cb735a01120d5f71daf1b339b7b8980cbeaba8fd1afc68e658a739746179e4315a26e8a28951ff9930078 - languageName: node - linkType: hard - "argparse@npm:^1.0.7": version: 1.0.10 resolution: "argparse@npm:1.0.10" @@ -4505,26 +4608,27 @@ __metadata: languageName: node linkType: hard -"array-buffer-byte-length@npm:^1.0.0": - version: 1.0.0 - resolution: "array-buffer-byte-length@npm:1.0.0" +"array-buffer-byte-length@npm:^1.0.1": + version: 1.0.1 + resolution: "array-buffer-byte-length@npm:1.0.1" dependencies: - call-bind: ^1.0.2 - is-array-buffer: ^3.0.1 - checksum: 044e101ce150f4804ad19c51d6c4d4cfa505c5b2577bd179256e4aa3f3f6a0a5e9874c78cd428ee566ac574c8a04d7ce21af9fe52e844abfdccb82b33035a7c3 + call-bind: ^1.0.5 + is-array-buffer: ^3.0.4 + checksum: 53524e08f40867f6a9f35318fafe467c32e45e9c682ba67b11943e167344d2febc0f6977a17e699b05699e805c3e8f073d876f8bbf1b559ed494ad2cd0fae09e languageName: node linkType: hard "array-includes@npm:^3.1.7": - version: 3.1.7 - resolution: "array-includes@npm:3.1.7" + version: 3.1.8 + resolution: "array-includes@npm:3.1.8" dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - get-intrinsic: ^1.2.1 + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-abstract: ^1.23.2 + es-object-atoms: ^1.0.0 + get-intrinsic: ^1.2.4 is-string: ^1.0.7 - checksum: 06f9e4598fac12a919f7c59a3f04f010ea07f0b7f0585465ed12ef528a60e45f374e79d1bddbb34cdd4338357d00023ddbd0ac18b0be36964f5e726e8965d7fc + checksum: eb39ba5530f64e4d8acab39297c11c1c5be2a4ea188ab2b34aba5fb7224d918f77717a9d57a3e2900caaa8440e59431bdaf5c974d5212ef65d97f132e38e2d91 languageName: node linkType: hard @@ -4536,15 +4640,16 @@ __metadata: linkType: hard "array.prototype.findlastindex@npm:^1.2.3": - version: 1.2.3 - resolution: "array.prototype.findlastindex@npm:1.2.3" + version: 1.2.5 + resolution: "array.prototype.findlastindex@npm:1.2.5" dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - es-shim-unscopables: ^1.0.0 - get-intrinsic: ^1.2.1 - checksum: 31f35d7b370c84db56484618132041a9af401b338f51899c2e78ef7690fbba5909ee7ca3c59a7192085b328cc0c68c6fd1f6d1553db01a689a589ae510f3966e + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-abstract: ^1.23.2 + es-errors: ^1.3.0 + es-object-atoms: ^1.0.0 + es-shim-unscopables: ^1.0.2 + checksum: 2c81cff2a75deb95bf1ed89b6f5f2bfbfb882211e3b7cc59c3d6b87df774cd9d6b36949a8ae39ac476e092c1d4a4905f5ee11a86a456abb10f35f8211ae4e710 languageName: node linkType: hard @@ -4572,18 +4677,19 @@ __metadata: languageName: node linkType: hard -"arraybuffer.prototype.slice@npm:^1.0.2": - version: 1.0.2 - resolution: "arraybuffer.prototype.slice@npm:1.0.2" +"arraybuffer.prototype.slice@npm:^1.0.3": + version: 1.0.3 + resolution: "arraybuffer.prototype.slice@npm:1.0.3" dependencies: - array-buffer-byte-length: ^1.0.0 - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - get-intrinsic: ^1.2.1 - is-array-buffer: ^3.0.2 + array-buffer-byte-length: ^1.0.1 + call-bind: ^1.0.5 + define-properties: ^1.2.1 + es-abstract: ^1.22.3 + es-errors: ^1.2.1 + get-intrinsic: ^1.2.3 + is-array-buffer: ^3.0.4 is-shared-array-buffer: ^1.0.2 - checksum: c200faf437786f5b2c80d4564ff5481c886a16dee642ef02abdc7306c7edd523d1f01d1dd12b769c7eb42ac9bc53874510db19a92a2c035c0f6696172aafa5d3 + checksum: 352259cba534dcdd969c92ab002efd2ba5025b2e3b9bead3973150edbdf0696c629d7f4b3f061c5931511e8207bdc2306da614703c820b45dabce39e3daf7e3e languageName: node linkType: hard @@ -4601,15 +4707,25 @@ __metadata: languageName: node linkType: hard -"asn1.js@npm:^5.2.0": - version: 5.4.1 - resolution: "asn1.js@npm:5.4.1" +"asn1.js@npm:^4.10.1": + version: 4.10.1 + resolution: "asn1.js@npm:4.10.1" dependencies: bn.js: ^4.0.0 inherits: ^2.0.1 minimalistic-assert: ^1.0.0 - safer-buffer: ^2.1.0 - checksum: 3786a101ac6f304bd4e9a7df79549a7561950a13d4bcaec0c7790d44c80d147c1a94ba3d4e663673406064642a40b23fcd6c82a9952468e386c1a1376d747f9a + checksum: 9289a1a55401238755e3142511d7b8f6fc32f08c86ff68bd7100da8b6c186179dd6b14234fba2f7f6099afcd6758a816708485efe44bc5b2a6ec87d9ceeddbb5 + languageName: node + linkType: hard + +"asn1js@npm:^3.0.5": + version: 3.0.5 + resolution: "asn1js@npm:3.0.5" + dependencies: + pvtsutils: ^1.3.2 + pvutils: ^1.1.3 + tslib: ^2.4.0 + checksum: 3b6af1bbadd5762ef8ead5daf2f6bda1bc9e23bc825c4dcc996aa1f9521ad7390a64028565d95d98090d69c8431f004c71cccb866004759169d7c203cf9075eb languageName: node linkType: hard @@ -4657,17 +4773,19 @@ __metadata: languageName: node linkType: hard -"available-typed-arrays@npm:^1.0.5": - version: 1.0.5 - resolution: "available-typed-arrays@npm:1.0.5" - checksum: 20eb47b3cefd7db027b9bbb993c658abd36d4edd3fe1060e83699a03ee275b0c9b216cc076ff3f2db29073225fb70e7613987af14269ac1fe2a19803ccc97f1a +"available-typed-arrays@npm:^1.0.7": + version: 1.0.7 + resolution: "available-typed-arrays@npm:1.0.7" + dependencies: + possible-typed-array-names: ^1.0.0 + checksum: 1aa3ffbfe6578276996de660848b6e95669d9a95ad149e3dd0c0cda77db6ee1dbd9d1dd723b65b6d277b882dd0c4b91a654ae9d3cf9e1254b7e93e4908d78fd3 languageName: node linkType: hard "b4a@npm:^1.6.4": - version: 1.6.4 - resolution: "b4a@npm:1.6.4" - checksum: 81b086f9af1f8845fbef4476307236bda3d660c158c201db976f19cdce05f41f93110ab6b12fd7a2696602a490cc43d5410ee36a56d6eef93afb0d6ca69ac3b2 + version: 1.6.6 + resolution: "b4a@npm:1.6.6" + checksum: c46a27e3ac9c84426ae728f0fc46a6ae7703a7bc03e771fa0bef4827fd7cf3bb976d1a3d5afff54606248372ab8fdf595bd0114406690edf37f14d120630cf7f languageName: node linkType: hard @@ -4755,37 +4873,36 @@ __metadata: linkType: hard "bare-events@npm:^2.0.0, bare-events@npm:^2.2.0": - version: 2.2.0 - resolution: "bare-events@npm:2.2.0" - checksum: b3001d61cbb7e6c91c7e47ed1d5701512f94c68955a88c1fe368ff313ba68f372fd701f422d1604fd6ac6e2237024d99373aa14e43a92696755a1f7ae46a8626 + version: 2.2.2 + resolution: "bare-events@npm:2.2.2" + checksum: 154d3fc044cc171d3b85a89b768e626417b60c050123ac2ac10fc002152b4bdeb359ed1453ad54c0f1d05a7786f780d3b976af68e55c09fe4579d8466d3ff256 languageName: node linkType: hard "bare-fs@npm:^2.1.1": - version: 2.1.5 - resolution: "bare-fs@npm:2.1.5" + version: 2.2.3 + resolution: "bare-fs@npm:2.2.3" dependencies: bare-events: ^2.0.0 - bare-os: ^2.0.0 bare-path: ^2.0.0 streamx: ^2.13.0 - checksum: 268bc03dd97c2e039f3396d79993640a10bbb5ad30bc7a3a2d406ceb538333b0f79eab33f1db288bcf55fde52c767fa1f25332ac606c27555cc62951c236d346 + checksum: 598f1998f08b19c7f1eea76291e5c93664c82b60b997e56aa0e6dea05193d74d3865cfe1172d05684893253ef700ce3abb4e76c55da799fed2ee7a82597a5c44 languageName: node linkType: hard -"bare-os@npm:^2.0.0, bare-os@npm:^2.1.0": - version: 2.2.0 - resolution: "bare-os@npm:2.2.0" - checksum: ed78e2f3ea498e35c7565532ae3aa3b85a7e5e223ab6353de64864823cadff02a2a8b7722e9a6c1a0ff56cb9f21f23ada8e88a085cc0a5d38a7c1bcf65e8f7fd +"bare-os@npm:^2.1.0": + version: 2.2.1 + resolution: "bare-os@npm:2.2.1" + checksum: 7d870d8955531809253dfbceeda5b68e8396ef640166f8ff6c4c5e344f18a6bc9253f6d5e7d9ae2841426b66e9b7b1a39b2a102e6b23e1ddff26ad8a8981af81 languageName: node linkType: hard "bare-path@npm:^2.0.0, bare-path@npm:^2.1.0": - version: 2.1.0 - resolution: "bare-path@npm:2.1.0" + version: 2.1.1 + resolution: "bare-path@npm:2.1.1" dependencies: bare-os: ^2.1.0 - checksum: 03f260e72bd0ae0df4cd712322a2d3c8c16701ffaa55cf2d517ae62b7f78c64b7ec5bba81ec579367f966472481f5160db282e6663bd0fc8cfb09ebe272d8bba + checksum: f25710be4ee4106f15b405b85ceea5c8da799f803b237008dc4a3533c0db01acd2500742f2204a37909c6871949725fb1907cf95434d80710bf832716d0da8df languageName: node linkType: hard @@ -4797,19 +4914,39 @@ __metadata: linkType: hard "basic-ftp@npm:^5.0.2": - version: 5.0.4 - resolution: "basic-ftp@npm:5.0.4" - checksum: 57725f24debd8c1b36f9bad1bfee39c5d9f5997f32a23e5c957389dcc64373a13b41711e5723b4a3b616a93530b345686119f480c27a115b2fde944c1652ceb1 + version: 5.0.5 + resolution: "basic-ftp@npm:5.0.5" + checksum: bc82d1c1c61cd838eaca96d68ece888bacf07546642fb6b9b8328ed410756f5935f8cf43a42cb44bb343e0565e28e908adc54c298bd2f1a6e0976871fb11fec6 languageName: node linkType: hard -"benchmark@npm:^2.1.4": - version: 2.1.4 - resolution: "benchmark@npm:2.1.4" +"bcrypto@npm:^5.4.0": + version: 5.5.2 + resolution: "bcrypto@npm:5.5.2" + dependencies: + bufio: ~1.0.7 + loady: ~0.0.5 + node-gyp: latest + checksum: 6eb78e0e6f8b06afb55174407df9b5395451519bab2dcec139fb8dbe3480c4a83be74d15cbe503904d3d98314e384a35cb47fe4a779f4f8188da0e944d188f24 + languageName: node + linkType: hard + +"bigint-buffer@npm:^1.1.5": + version: 1.1.5 + resolution: "bigint-buffer@npm:1.1.5" + dependencies: + bindings: ^1.3.0 + node-gyp: latest + checksum: d010c9f57758bcdaccb435d88b483ffcc95fe8bbc6e7fb3a44fb5221f29c894ffaf4a3c5a4a530e0e7d6608203c2cde9b79ee4f2386cd6d4462d1070bc8c9f4e + languageName: node + linkType: hard + +"bindings@npm:^1.3.0": + version: 1.5.0 + resolution: "bindings@npm:1.5.0" dependencies: - lodash: ^4.17.4 - platform: ^1.3.3 - checksum: aa466561d4f2b0a2419a3069b8f90fd35ffacf26849697eea9de525ecfbd10b44da11070cc51c88d772076db8cb2415641b493de7d6c024fdf8551019c6fcf1c + file-uri-to-path: 1.0.0 + checksum: 65b6b48095717c2e6105a021a7da4ea435aa8d3d3cd085cb9e85bcb6e5773cf318c4745c3f7c504412855940b585bdf9b918236612a1c7a7942491de176f1ae7 languageName: node linkType: hard @@ -4831,7 +4968,7 @@ __metadata: languageName: node linkType: hard -"bn.js@npm:^5.0.0, bn.js@npm:^5.2.1": +"bn.js@npm:^5.0.0, bn.js@npm:^5.2.0, bn.js@npm:^5.2.1": version: 5.2.1 resolution: "bn.js@npm:5.2.1" checksum: 3dd8c8d38055fedfa95c1d5fc3c99f8dd547b36287b37768db0abab3c239711f88ff58d18d155dd8ad902b0b0cee973747b7ae20ea12a09473272b0201c9edd3 @@ -4873,7 +5010,7 @@ __metadata: languageName: node linkType: hard -"browserify-aes@npm:^1.0.0, browserify-aes@npm:^1.0.4": +"browserify-aes@npm:^1.0.4, browserify-aes@npm:^1.2.0": version: 1.2.0 resolution: "browserify-aes@npm:1.2.0" dependencies: @@ -4921,33 +5058,34 @@ __metadata: linkType: hard "browserify-sign@npm:^4.0.0": - version: 4.2.2 - resolution: "browserify-sign@npm:4.2.2" + version: 4.2.3 + resolution: "browserify-sign@npm:4.2.3" dependencies: bn.js: ^5.2.1 browserify-rsa: ^4.1.0 create-hash: ^1.2.0 create-hmac: ^1.1.7 - elliptic: ^6.5.4 + elliptic: ^6.5.5 + hash-base: ~3.0 inherits: ^2.0.4 - parse-asn1: ^5.1.6 - readable-stream: ^3.6.2 + parse-asn1: ^5.1.7 + readable-stream: ^2.3.8 safe-buffer: ^5.2.1 - checksum: b622730c0fc183328c3a1c9fdaaaa5118821ed6822b266fa6b0375db7e20061ebec87301d61931d79b9da9a96ada1cab317fce3c68f233e5e93ed02dbb35544c + checksum: 403a8061d229ae31266670345b4a7c00051266761d2c9bbeb68b1a9bcb05f68143b16110cf23a171a5d6716396a1f41296282b3e73eeec0a1871c77f0ff4ee6b languageName: node linkType: hard "browserslist@npm:^4.21.10, browserslist@npm:^4.22.2": - version: 4.22.2 - resolution: "browserslist@npm:4.22.2" + version: 4.23.0 + resolution: "browserslist@npm:4.23.0" dependencies: - caniuse-lite: ^1.0.30001565 - electron-to-chromium: ^1.4.601 + caniuse-lite: ^1.0.30001587 + electron-to-chromium: ^1.4.668 node-releases: ^2.0.14 update-browserslist-db: ^1.0.13 bin: browserslist: cli.js - checksum: 33ddfcd9145220099a7a1ac533cecfe5b7548ffeb29b313e1b57be6459000a1f8fa67e781cf4abee97268ac594d44134fcc4a6b2b4750ceddc9796e3a22076d9 + checksum: 436f49e796782ca751ebab7edc010cfc9c29f68536f387666cd70ea22f7105563f04dd62c6ff89cb24cc3254d17cba385f979eeeb3484d43e012412ff7e75def languageName: node linkType: hard @@ -5001,6 +5139,13 @@ __metadata: languageName: node linkType: hard +"bufio@npm:~1.0.7": + version: 1.0.7 + resolution: "bufio@npm:1.0.7" + checksum: 4871b8060a8d3bc04de8722f5cc5575b77f4cb18af389eab62d51bf42b08f43fe75159126ef11f15fe4045dc8c20e0e344406ca8388cb1371e558b986e971a57 + languageName: node + linkType: hard + "bytes@npm:3.1.2, bytes@npm:^3.1.2": version: 3.1.2 resolution: "bytes@npm:3.1.2" @@ -5038,14 +5183,16 @@ __metadata: languageName: node linkType: hard -"call-bind@npm:^1.0.0, call-bind@npm:^1.0.2, call-bind@npm:^1.0.4, call-bind@npm:^1.0.5": - version: 1.0.5 - resolution: "call-bind@npm:1.0.5" +"call-bind@npm:^1.0.2, call-bind@npm:^1.0.5, call-bind@npm:^1.0.6, call-bind@npm:^1.0.7": + version: 1.0.7 + resolution: "call-bind@npm:1.0.7" dependencies: + es-define-property: ^1.0.0 + es-errors: ^1.3.0 function-bind: ^1.1.2 - get-intrinsic: ^1.2.1 - set-function-length: ^1.1.1 - checksum: 449e83ecbd4ba48e7eaac5af26fea3b50f8f6072202c2dd7c5a6e7a6308f2421abe5e13a3bbd55221087f76320c5e09f25a8fdad1bab2b77c68ae74d92234ea5 + get-intrinsic: ^1.2.4 + set-function-length: ^1.2.1 + checksum: 295c0c62b90dd6522e6db3b0ab1ce26bdf9e7404215bda13cfee25b626b5ff1a7761324d58d38b1ef1607fc65aca2d06e44d2e18d0dfc6c14b465b00d8660029 languageName: node linkType: hard @@ -5081,10 +5228,10 @@ __metadata: languageName: node linkType: hard -"caniuse-lite@npm:^1.0.30001565": - version: 1.0.30001580 - resolution: "caniuse-lite@npm:1.0.30001580" - checksum: 8d287d1e2a64348365f55562457b52afc8c5e0e8ddf040e18e53395ca165241a697205611dc209dace5c7f7d1d3ee8d566672cce6f9668d658d7930b7a200875 +"caniuse-lite@npm:^1.0.30001587": + version: 1.0.30001612 + resolution: "caniuse-lite@npm:1.0.30001612" + checksum: 2b6ab6a19c72bdf8dccac824944e828a2a1fae52c6dfeb2d64ccecfd60d0466d2e5a392e996da2150d92850188a5034666dceed34a38d978177f6934e0bf106d languageName: node linkType: hard @@ -5137,15 +5284,16 @@ __metadata: languageName: node linkType: hard -"chromium-bidi@npm:0.5.9": - version: 0.5.9 - resolution: "chromium-bidi@npm:0.5.9" +"chromium-bidi@npm:0.5.17": + version: 0.5.17 + resolution: "chromium-bidi@npm:0.5.17" dependencies: mitt: 3.0.1 urlpattern-polyfill: 10.0.0 + zod: 3.22.4 peerDependencies: devtools-protocol: "*" - checksum: 5885a5ab93ddccc2b64ec6fe5455258c440e235daf7c9fb55e1de32ad95b514b721fae8bb7ddaee48d5c7745b57bdcf8a7114f012a41af3ea34b5fe6f1c22646 + checksum: 522da996ed5abfb47707583cc24785f9aa05d87bd968dbd520f245cf8972fa3ec102f8d1d72fa07558daa70495d8c6f2bf364d8599eb60b77504e528601d8a30 languageName: node linkType: hard @@ -5521,7 +5669,7 @@ __metadata: languageName: node linkType: hard -"core-util-is@npm:^1.0.2": +"core-util-is@npm:^1.0.2, core-util-is@npm:~1.0.0": version: 1.0.3 resolution: "core-util-is@npm:1.0.3" checksum: 9de8597363a8e9b9952491ebe18167e3b36e7707569eed0ebf14f8bba773611376466ae34575bca8cfe3c767890c859c74056084738f09d4e4a6f902b2ad7d99 @@ -5606,15 +5754,6 @@ __metadata: languageName: node linkType: hard -"cross-fetch@npm:4.0.0": - version: 4.0.0 - resolution: "cross-fetch@npm:4.0.0" - dependencies: - node-fetch: ^2.6.12 - checksum: ecca4f37ffa0e8283e7a8a590926b66713a7ef7892757aa36c2d20ffa27b0ac5c60dcf453119c809abe5923fc0bae3702a4d896bfb406ef1077b0d0018213e24 - languageName: node - linkType: hard - "cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.2, cross-spawn@npm:^7.0.3": version: 7.0.3 resolution: "cross-spawn@npm:7.0.3" @@ -5645,31 +5784,63 @@ __metadata: languageName: node linkType: hard -"data-uri-to-buffer@npm:^6.0.0": - version: 6.0.1 - resolution: "data-uri-to-buffer@npm:6.0.1" - checksum: 9140e68c585ae33d950f5943bd476751346c8b789ae80b01a578a33cb8f7f706d1ca7378aff2b1878b2a6d9a8c88c55cc286d88191c8b8ead8255c3c4d934530 +"data-uri-to-buffer@npm:^6.0.2": + version: 6.0.2 + resolution: "data-uri-to-buffer@npm:6.0.2" + checksum: 8b6927c33f9b54037f442856be0aa20e5fd49fa6c9c8ceece408dc306445d593ad72d207d57037c529ce65f413b421da800c6827b1dbefb607b8056f17123a61 + languageName: node + linkType: hard + +"data-view-buffer@npm:^1.0.1": + version: 1.0.1 + resolution: "data-view-buffer@npm:1.0.1" + dependencies: + call-bind: ^1.0.6 + es-errors: ^1.3.0 + is-data-view: ^1.0.1 + checksum: ce24348f3c6231223b216da92e7e6a57a12b4af81a23f27eff8feabdf06acfb16c00639c8b705ca4d167f761cfc756e27e5f065d0a1f840c10b907fdaf8b988c + languageName: node + linkType: hard + +"data-view-byte-length@npm:^1.0.1": + version: 1.0.1 + resolution: "data-view-byte-length@npm:1.0.1" + dependencies: + call-bind: ^1.0.7 + es-errors: ^1.3.0 + is-data-view: ^1.0.1 + checksum: dbb3200edcb7c1ef0d68979834f81d64fd8cab2f7691b3a4c6b97e67f22182f3ec2c8602efd7b76997b55af6ff8bce485829c1feda4fa2165a6b71fb7baa4269 + languageName: node + linkType: hard + +"data-view-byte-offset@npm:^1.0.0": + version: 1.0.0 + resolution: "data-view-byte-offset@npm:1.0.0" + dependencies: + call-bind: ^1.0.6 + es-errors: ^1.3.0 + is-data-view: ^1.0.1 + checksum: 7f0bf8720b7414ca719eedf1846aeec392f2054d7af707c5dc9a753cc77eb8625f067fa901e0b5127e831f9da9056138d894b9c2be79c27a21f6db5824f009c2 languageName: node linkType: hard -"datastore-core@npm:^9.0.1": - version: 9.2.7 - resolution: "datastore-core@npm:9.2.7" +"datastore-core@npm:^9.0.1, datastore-core@npm:^9.2.9": + version: 9.2.9 + resolution: "datastore-core@npm:9.2.9" dependencies: - "@libp2p/logger": ^4.0.1 + "@libp2p/logger": ^4.0.6 err-code: ^3.0.1 + interface-datastore: ^8.0.0 interface-store: ^5.0.0 - it-all: ^3.0.1 - it-drain: ^3.0.1 - it-filter: ^3.0.0 - it-map: ^3.0.1 - it-merge: ^3.0.1 - it-pipe: ^3.0.0 - it-pushable: ^3.0.0 - it-sort: ^3.0.1 - it-take: ^3.0.1 - uint8arrays: ^5.0.0 - checksum: 593f40d8e5ccbc80b073b4ec1553e70bc061d4656ca238c10eb47d799ff8a137f19698268b0639cc5a26cf5e036f72946dad0bd20cd37e57f713c9d7a1b32a67 + it-drain: ^3.0.5 + it-filter: ^3.0.4 + it-map: ^3.0.5 + it-merge: ^3.0.3 + it-pipe: ^3.0.1 + it-pushable: ^3.2.3 + it-sort: ^3.0.4 + it-take: ^3.0.4 + checksum: 82311198971b0603c7ca5a3275a2ef7df82981d29fd0c120d190c7902d3b08afa5497cbe80551a363a9d6b9b1a1f587147df600a5c217765e50d9f1b0d9db338 languageName: node linkType: hard @@ -5721,14 +5892,14 @@ __metadata: linkType: hard "dedent@npm:^1.0.0": - version: 1.5.1 - resolution: "dedent@npm:1.5.1" + version: 1.5.3 + resolution: "dedent@npm:1.5.3" peerDependencies: babel-plugin-macros: ^3.1.0 peerDependenciesMeta: babel-plugin-macros: optional: true - checksum: c3c300a14edf1bdf5a873f9e4b22e839d62490bc5c8d6169c1f15858a1a76733d06a9a56930e963d677a2ceeca4b6b0894cc5ea2f501aa382ca5b92af3413c2a + checksum: 045b595557b2a8ea2eb9b0b4623d764e9a87326486fe2b61191b4342ed93dc01245644d8a09f3108a50c0ee7965f1eedd92e4a3a503ed89ea8e810566ea27f9a languageName: node linkType: hard @@ -5760,15 +5931,6 @@ __metadata: languageName: node linkType: hard -"default-gateway@npm:^7.2.2": - version: 7.2.2 - resolution: "default-gateway@npm:7.2.2" - dependencies: - execa: ^7.1.1 - checksum: eec8a2a338677322bcdbf339bbdede61225f6145eedd0c3d4948deadfc929dc0e04b153b33674873d36efa403f76649aaacbfc728a438ee9f538a28723515478 - languageName: node - linkType: hard - "defaults@npm:^1.0.3": version: 1.0.4 resolution: "defaults@npm:1.0.4" @@ -5788,14 +5950,14 @@ __metadata: languageName: node linkType: hard -"define-data-property@npm:^1.0.1, define-data-property@npm:^1.1.1": - version: 1.1.1 - resolution: "define-data-property@npm:1.1.1" +"define-data-property@npm:^1.0.1, define-data-property@npm:^1.1.4": + version: 1.1.4 + resolution: "define-data-property@npm:1.1.4" dependencies: - get-intrinsic: ^1.2.1 + es-define-property: ^1.0.0 + es-errors: ^1.3.0 gopd: ^1.0.1 - has-property-descriptors: ^1.0.0 - checksum: a29855ad3f0630ea82e3c5012c812efa6ca3078d5c2aa8df06b5f597c1cde6f7254692df41945851d903e05a1668607b6d34e778f402b9ff9ffb38111f1a3f0d + checksum: 8068ee6cab694d409ac25936eb861eea704b7763f7f342adbdfe337fc27c78d7ae0eff2364b2917b58c508d723c7a074326d068eef2e45c4edcd85cf94d0313b languageName: node linkType: hard @@ -5889,9 +6051,9 @@ __metadata: linkType: hard "detect-libc@npm:^2.0.1": - version: 2.0.2 - resolution: "detect-libc@npm:2.0.2" - checksum: 2b2cd3649b83d576f4be7cc37eb3b1815c79969c8b1a03a40a4d55d83bc74d010753485753448eacb98784abf22f7dbd3911fd3b60e29fda28fed2d1a997944d + version: 2.0.3 + resolution: "detect-libc@npm:2.0.3" + checksum: 2ba6a939ae55f189aea996ac67afceb650413c7a34726ee92c40fb0deb2400d57ef94631a8a3f052055eea7efb0f99a9b5e6ce923415daa3e68221f963cfc27d languageName: node linkType: hard @@ -6094,10 +6256,10 @@ __metadata: languageName: node linkType: hard -"devtools-protocol@npm:0.0.1249869": - version: 0.0.1249869 - resolution: "devtools-protocol@npm:0.0.1249869" - checksum: 549dda02f6d778741930e5abdde3f8e5d39e16fdbe8af38597a974e9c239798dd464250bd7ab4360d77e3d059620e95be7cf05150142473bf9b661ed28a616ed +"devtools-protocol@npm:0.0.1262051": + version: 0.0.1262051 + resolution: "devtools-protocol@npm:0.0.1262051" + checksum: beaad00059964a661ab056d5e993492742c612c0370c6f08acd91490181c4d4ecf57d316eedb5a37fb6bb59321901d09ce50762f79ea09a50751d86f601b8f8e languageName: node linkType: hard @@ -6145,13 +6307,12 @@ __metadata: languageName: node linkType: hard -"dns-over-http-resolver@npm:^3.0.2": - version: 3.0.2 - resolution: "dns-over-http-resolver@npm:3.0.2" +"dns-packet@npm:^5.6.1": + version: 5.6.1 + resolution: "dns-packet@npm:5.6.1" dependencies: - debug: ^4.3.4 - receptacle: ^1.3.2 - checksum: 782739450bae3329fdbafcb3c53b497eeb0b3af3bdd8de91977a513d4fe797446597a09d6e042a2c5da99cfc0039c4acac8a7efb93aca5b3424b58f4174d4a4f + "@leichtgewicht/ip-codec": ^2.0.1 + checksum: 64c06457f0c6e143f7a0946e0aeb8de1c5f752217cfa143ef527467c00a6d78db1835cfdb6bb68333d9f9a4963cf23f410439b5262a8935cce1236f45e344b81 languageName: node linkType: hard @@ -6174,9 +6335,9 @@ __metadata: linkType: hard "dotenv@npm:^16.0.3": - version: 16.4.1 - resolution: "dotenv@npm:16.4.1" - checksum: a343f0a1d156deef8c60034f797969867af4dbccfacedd4ac15fad04547e7ffe0553b58fc3b27a5837950f0d977e38e9234943fbcec4aeced4e3d044309a76ab + version: 16.4.5 + resolution: "dotenv@npm:16.4.5" + checksum: 301a12c3d44fd49888b74eb9ccf9f07a1f5df43f489e7fcb89647a2edcd84c42d6bc349dc8df099cd18f07c35c7b04685c1a4f3e6a6a9e6b30f8d48c15b7f49c languageName: node linkType: hard @@ -6201,16 +6362,16 @@ __metadata: languageName: node linkType: hard -"electron-to-chromium@npm:^1.4.601": - version: 1.4.647 - resolution: "electron-to-chromium@npm:1.4.647" - checksum: fd79098e08a03025fb64a0608dd20942a7004bb38a8c7fd6d18d8b1767712866a3dae2df7e69ddbc7c627352278cbd07ce1a7368b6c037129e68a042802e108c +"electron-to-chromium@npm:^1.4.668": + version: 1.4.745 + resolution: "electron-to-chromium@npm:1.4.745" + checksum: f73b576108863cad160deb22b8e8c6754a8b16b22cda90cfce038a755f886be9c03fb8360bbd7c9d28ddd184800d0d6bd430a11f9289316145f0b28321dfe71d languageName: node linkType: hard -"elliptic@npm:^6.5.3, elliptic@npm:^6.5.4": - version: 6.5.4 - resolution: "elliptic@npm:6.5.4" +"elliptic@npm:^6.5.3, elliptic@npm:^6.5.4, elliptic@npm:^6.5.5": + version: 6.5.5 + resolution: "elliptic@npm:6.5.5" dependencies: bn.js: ^4.11.9 brorand: ^1.1.0 @@ -6219,7 +6380,7 @@ __metadata: inherits: ^2.0.4 minimalistic-assert: ^1.0.1 minimalistic-crypto-utils: ^1.0.1 - checksum: d56d21fd04e97869f7ffcc92e18903b9f67f2d4637a23c860492fbbff5a3155fd9ca0184ce0c865dd6eb2487d234ce9551335c021c376cd2d3b7cb749c7d10f4 + checksum: ec9105e4469eb3b32b0ee2579756c888ddf3f99d259aa0d65fccb906ee877768aaf8880caae73e3e669c9a4adeb3eb1945703aa974ec5000d2d33a239f4567eb languageName: node linkType: hard @@ -6276,13 +6437,13 @@ __metadata: languageName: node linkType: hard -"enhanced-resolve@npm:^5.0.0, enhanced-resolve@npm:^5.12.0, enhanced-resolve@npm:^5.15.0, enhanced-resolve@npm:^5.8.3": - version: 5.15.0 - resolution: "enhanced-resolve@npm:5.15.0" +"enhanced-resolve@npm:^5.0.0, enhanced-resolve@npm:^5.12.0, enhanced-resolve@npm:^5.16.0, enhanced-resolve@npm:^5.8.3": + version: 5.16.0 + resolution: "enhanced-resolve@npm:5.16.0" dependencies: graceful-fs: ^4.2.4 tapable: ^2.2.0 - checksum: fbd8cdc9263be71cc737aa8a7d6c57b43d6aa38f6cc75dde6fcd3598a130cc465f979d2f4d01bb3bf475acb43817749c79f8eef9be048683602ca91ab52e4f11 + checksum: ccfd01850ecf2aa51e8554d539973319ff7d8a539ef1e0ba3460a0ccad6223c4ef6e19165ee64161b459cd8a48df10f52af4434c60023c65fde6afa32d475f7e languageName: node linkType: hard @@ -6294,11 +6455,11 @@ __metadata: linkType: hard "envinfo@npm:^7.7.3": - version: 7.11.0 - resolution: "envinfo@npm:7.11.0" + version: 7.12.0 + resolution: "envinfo@npm:7.12.0" bin: envinfo: dist/cli.js - checksum: c45a7d20409d5f4cda72483b150d3816b15b434f2944d72c1495d8838bd7c4e7b2f32c12128ffb9b92b5f66f436237b8a525eb3a9a5da2d20013bc4effa28aef + checksum: 4c83a55768cf8b7e553155c29e7fa7bbdb0fb2c1156208efc373fc030045c6aca5e8e642e96027d3eb0c752156922ea3fca6183d9e13f38507f0e02ec82c23a1 languageName: node linkType: hard @@ -6325,72 +6486,104 @@ __metadata: languageName: node linkType: hard -"es-abstract@npm:^1.22.1": - version: 1.22.3 - resolution: "es-abstract@npm:1.22.3" +"es-abstract@npm:^1.22.1, es-abstract@npm:^1.22.3, es-abstract@npm:^1.23.0, es-abstract@npm:^1.23.2": + version: 1.23.3 + resolution: "es-abstract@npm:1.23.3" dependencies: - array-buffer-byte-length: ^1.0.0 - arraybuffer.prototype.slice: ^1.0.2 - available-typed-arrays: ^1.0.5 - call-bind: ^1.0.5 - es-set-tostringtag: ^2.0.1 + array-buffer-byte-length: ^1.0.1 + arraybuffer.prototype.slice: ^1.0.3 + available-typed-arrays: ^1.0.7 + call-bind: ^1.0.7 + data-view-buffer: ^1.0.1 + data-view-byte-length: ^1.0.1 + data-view-byte-offset: ^1.0.0 + es-define-property: ^1.0.0 + es-errors: ^1.3.0 + es-object-atoms: ^1.0.0 + es-set-tostringtag: ^2.0.3 es-to-primitive: ^1.2.1 function.prototype.name: ^1.1.6 - get-intrinsic: ^1.2.2 - get-symbol-description: ^1.0.0 + get-intrinsic: ^1.2.4 + get-symbol-description: ^1.0.2 globalthis: ^1.0.3 gopd: ^1.0.1 - has-property-descriptors: ^1.0.0 - has-proto: ^1.0.1 + has-property-descriptors: ^1.0.2 + has-proto: ^1.0.3 has-symbols: ^1.0.3 - hasown: ^2.0.0 - internal-slot: ^1.0.5 - is-array-buffer: ^3.0.2 + hasown: ^2.0.2 + internal-slot: ^1.0.7 + is-array-buffer: ^3.0.4 is-callable: ^1.2.7 - is-negative-zero: ^2.0.2 + is-data-view: ^1.0.1 + is-negative-zero: ^2.0.3 is-regex: ^1.1.4 - is-shared-array-buffer: ^1.0.2 + is-shared-array-buffer: ^1.0.3 is-string: ^1.0.7 - is-typed-array: ^1.1.12 + is-typed-array: ^1.1.13 is-weakref: ^1.0.2 object-inspect: ^1.13.1 object-keys: ^1.1.1 - object.assign: ^4.1.4 - regexp.prototype.flags: ^1.5.1 - safe-array-concat: ^1.0.1 - safe-regex-test: ^1.0.0 - string.prototype.trim: ^1.2.8 - string.prototype.trimend: ^1.0.7 - string.prototype.trimstart: ^1.0.7 - typed-array-buffer: ^1.0.0 - typed-array-byte-length: ^1.0.0 - typed-array-byte-offset: ^1.0.0 - typed-array-length: ^1.0.4 + object.assign: ^4.1.5 + regexp.prototype.flags: ^1.5.2 + safe-array-concat: ^1.1.2 + safe-regex-test: ^1.0.3 + string.prototype.trim: ^1.2.9 + string.prototype.trimend: ^1.0.8 + string.prototype.trimstart: ^1.0.8 + typed-array-buffer: ^1.0.2 + typed-array-byte-length: ^1.0.1 + typed-array-byte-offset: ^1.0.2 + typed-array-length: ^1.0.6 unbox-primitive: ^1.0.2 - which-typed-array: ^1.1.13 - checksum: b1bdc962856836f6e72be10b58dc128282bdf33771c7a38ae90419d920fc3b36cc5d2b70a222ad8016e3fc322c367bf4e9e89fc2bc79b7e933c05b218e83d79a + which-typed-array: ^1.1.15 + checksum: f840cf161224252512f9527306b57117192696571e07920f777cb893454e32999206198b4f075516112af6459daca282826d1735c450528470356d09eff3a9ae + languageName: node + linkType: hard + +"es-define-property@npm:^1.0.0": + version: 1.0.0 + resolution: "es-define-property@npm:1.0.0" + dependencies: + get-intrinsic: ^1.2.4 + checksum: f66ece0a887b6dca71848fa71f70461357c0e4e7249696f81bad0a1f347eed7b31262af4a29f5d726dc026426f085483b6b90301855e647aa8e21936f07293c6 + languageName: node + linkType: hard + +"es-errors@npm:^1.2.1, es-errors@npm:^1.3.0": + version: 1.3.0 + resolution: "es-errors@npm:1.3.0" + checksum: ec1414527a0ccacd7f15f4a3bc66e215f04f595ba23ca75cdae0927af099b5ec865f9f4d33e9d7e86f512f252876ac77d4281a7871531a50678132429b1271b5 languageName: node linkType: hard "es-module-lexer@npm:^1.2.1": - version: 1.4.1 - resolution: "es-module-lexer@npm:1.4.1" - checksum: a11b5a256d4e8e9c7d94c2fd87415ccd1591617b6edd847e064503f8eaece2d25e2e9078a02c5ce3ed5e83bb748f5b4820efbe78072c8beb07ac619c2edec35d + version: 1.5.0 + resolution: "es-module-lexer@npm:1.5.0" + checksum: adbe0772701e226b4b853f758fd89c0bbfe8357ab93babde7b1cdb4f88c3a31460c908cbe578817e241d116cc4fcf569f7c6f29c4fbfa0aadb0def90f1ad4dd2 languageName: node linkType: hard -"es-set-tostringtag@npm:^2.0.1": - version: 2.0.2 - resolution: "es-set-tostringtag@npm:2.0.2" +"es-object-atoms@npm:^1.0.0": + version: 1.0.0 + resolution: "es-object-atoms@npm:1.0.0" dependencies: - get-intrinsic: ^1.2.2 - has-tostringtag: ^1.0.0 - hasown: ^2.0.0 - checksum: afcec3a4c9890ae14d7ec606204858441c801ff84f312538e1d1ccf1e5493c8b17bd672235df785f803756472cb4f2d49b87bde5237aef33411e74c22f194e07 + es-errors: ^1.3.0 + checksum: 26f0ff78ab93b63394e8403c353842b2272836968de4eafe97656adfb8a7c84b9099bf0fe96ed58f4a4cddc860f6e34c77f91649a58a5daa4a9c40b902744e3c languageName: node linkType: hard -"es-shim-unscopables@npm:^1.0.0": +"es-set-tostringtag@npm:^2.0.3": + version: 2.0.3 + resolution: "es-set-tostringtag@npm:2.0.3" + dependencies: + get-intrinsic: ^1.2.4 + has-tostringtag: ^1.0.2 + hasown: ^2.0.1 + checksum: 7227fa48a41c0ce83e0377b11130d324ac797390688135b8da5c28994c0165be8b252e15cd1de41e1325e5a5412511586960213e88f9ab4a5e7d028895db5129 + languageName: node + linkType: hard + +"es-shim-unscopables@npm:^1.0.0, es-shim-unscopables@npm:^1.0.2": version: 1.0.2 resolution: "es-shim-unscopables@npm:1.0.2" dependencies: @@ -6488,9 +6681,9 @@ __metadata: linkType: hard "escalade@npm:^3.1.1": - version: 3.1.1 - resolution: "escalade@npm:3.1.1" - checksum: a3e2a99f07acb74b3ad4989c48ca0c3140f69f923e56d0cba0526240ee470b91010f9d39001f2a4a313841d237ede70a729e92125191ba5d21e74b106800b133 + version: 3.1.2 + resolution: "escalade@npm:3.1.2" + checksum: 1ec0977aa2772075493002bdbd549d595ff6e9393b1cb0d7d6fcaf78c750da0c158f180938365486f75cb69fba20294351caddfce1b46552a7b6c3cde52eaa02 languageName: node linkType: hard @@ -6581,14 +6774,14 @@ __metadata: linkType: hard "eslint-module-utils@npm:^2.7.4, eslint-module-utils@npm:^2.8.0": - version: 2.8.0 - resolution: "eslint-module-utils@npm:2.8.0" + version: 2.8.1 + resolution: "eslint-module-utils@npm:2.8.1" dependencies: debug: ^3.2.7 peerDependenciesMeta: eslint: optional: true - checksum: 74c6dfea7641ebcfe174be61168541a11a14aa8d72e515f5f09af55cd0d0862686104b0524aa4b8e0ce66418a44aa38a94d2588743db5fd07a6b49ffd16921d2 + checksum: 3cecd99b6baf45ffc269167da0f95dcb75e5aa67b93d73a3bab63e2a7eedd9cdd6f188eed048e2f57c1b77db82c9cbf2adac20b512fa70e597d863dd3720170d languageName: node linkType: hard @@ -6688,14 +6881,14 @@ __metadata: linkType: hard "eslint@npm:^8.21.0, eslint@npm:^8.35.0, eslint@npm:^8.37.0": - version: 8.56.0 - resolution: "eslint@npm:8.56.0" + version: 8.57.0 + resolution: "eslint@npm:8.57.0" dependencies: "@eslint-community/eslint-utils": ^4.2.0 "@eslint-community/regexpp": ^4.6.1 "@eslint/eslintrc": ^2.1.4 - "@eslint/js": 8.56.0 - "@humanwhocodes/config-array": ^0.11.13 + "@eslint/js": 8.57.0 + "@humanwhocodes/config-array": ^0.11.14 "@humanwhocodes/module-importer": ^1.0.1 "@nodelib/fs.walk": ^1.2.8 "@ungap/structured-clone": ^1.2.0 @@ -6731,7 +6924,7 @@ __metadata: text-table: ^0.2.0 bin: eslint: bin/eslint.js - checksum: 883436d1e809b4a25d9eb03d42f584b84c408dbac28b0019f6ea07b5177940bf3cca86208f749a6a1e0039b63e085ee47aca1236c30721e91f0deef5cc5a5136 + checksum: 3a48d7ff85ab420a8447e9810d8087aea5b1df9ef68c9151732b478de698389ee656fd895635b5f2871c89ee5a2652b3f343d11e9db6f8486880374ebc74a2d9 languageName: node linkType: hard @@ -6795,10 +6988,15 @@ __metadata: languageName: node linkType: hard -"event-iterator@npm:^2.0.0": - version: 2.0.0 - resolution: "event-iterator@npm:2.0.0" - checksum: ffa76b1a6b53255e4b08a271da7dba12c8377a1b6018ef6e9e41c30fd8c5f83d12fad6205cfeec3967a9df57362ed0f81335571d13dca537c12eab1d5daf5866 +"ethereum-cryptography@npm:^2.1.3": + version: 2.1.3 + resolution: "ethereum-cryptography@npm:2.1.3" + dependencies: + "@noble/curves": 1.3.0 + "@noble/hashes": 1.3.3 + "@scure/bip32": 1.3.3 + "@scure/bip39": 1.2.2 + checksum: 7f9c14f868a588641179cace3eb86c332c4743290865db699870710253cabc4dc74bd4bce5e7bc6db667482e032e94d6f79521219eb6be5dc422059d279a27b7 languageName: node linkType: hard @@ -6983,11 +7181,11 @@ __metadata: linkType: hard "fastq@npm:^1.6.0": - version: 1.16.0 - resolution: "fastq@npm:1.16.0" + version: 1.17.1 + resolution: "fastq@npm:1.17.1" dependencies: reusify: ^1.0.4 - checksum: 1d40ed1f100ae625e5720484e8602b7ad07649370f1cbc3e34a6b9630a0bfed6946bab0322d8a368a1e3cde87bb9bbb8d3bc2ae01a0c1f022fac1d07c04e4feb + checksum: a8c5b26788d5a1763f88bae56a8ddeee579f935a831c5fe7a8268cea5b0a91fbfe705f612209e02d639b881d7b48e461a50da4a10cfaa40da5ca7cc9da098d88 languageName: node linkType: hard @@ -7034,6 +7232,13 @@ __metadata: languageName: node linkType: hard +"file-uri-to-path@npm:1.0.0": + version: 1.0.0 + resolution: "file-uri-to-path@npm:1.0.0" + checksum: b648580bdd893a008c92c7ecc96c3ee57a5e7b6c4c18a9a09b44fb5d36d79146f8e442578bc0e173dc027adf3987e254ba1dfd6e3ec998b7c282873010502144 + languageName: node + linkType: hard + "filing-cabinet@npm:^3.0.1": version: 3.3.1 resolution: "filing-cabinet@npm:3.3.1" @@ -7107,9 +7312,9 @@ __metadata: linkType: hard "flatted@npm:^3.2.9": - version: 3.2.9 - resolution: "flatted@npm:3.2.9" - checksum: f14167fbe26a9d20f6fca8d998e8f1f41df72c8e81f9f2c9d61ed2bea058248f5e1cbd05e7f88c0e5087a6a0b822a1e5e2b446e879f3cfbe0b07ba2d7f80b026 + version: 3.3.1 + resolution: "flatted@npm:3.3.1" + checksum: 85ae7181650bb728c221e7644cbc9f4bf28bc556f2fc89bb21266962bdf0ce1029cc7acc44bb646cd469d9baac7c317f64e841c4c4c00516afa97320cdac7f94 languageName: node linkType: hard @@ -7179,13 +7384,6 @@ __metadata: languageName: node linkType: hard -"freeport-promise@npm:^2.0.0": - version: 2.0.0 - resolution: "freeport-promise@npm:2.0.0" - checksum: 4f8baa9ba8d304b6018213261948260f8a5b15b262d1439e629cae702baf98d1bc3dbbe57e2ef6a1cbca864b5f75a0556a2566ae22de76f13247c4e9c932f948 - languageName: node - linkType: hard - "fresh@npm:~0.5.2": version: 0.5.2 resolution: "fresh@npm:0.5.2" @@ -7211,17 +7409,6 @@ __metadata: languageName: node linkType: hard -"fs-extra@npm:^8.1.0": - version: 8.1.0 - resolution: "fs-extra@npm:8.1.0" - dependencies: - graceful-fs: ^4.2.0 - jsonfile: ^4.0.0 - universalify: ^0.1.0 - checksum: bf44f0e6cea59d5ce071bba4c43ca76d216f89e402dc6285c128abc0902e9b8525135aa808adad72c9d5d218e9f4bcc63962815529ff2f684ad532172a284880 - languageName: node - linkType: hard - "fs-minipass@npm:^2.0.0": version: 2.1.0 resolution: "fs-minipass@npm:2.1.0" @@ -7333,22 +7520,16 @@ __metadata: languageName: node linkType: hard -"get-intrinsic@npm:^1.0.2, get-intrinsic@npm:^1.1.1, get-intrinsic@npm:^1.1.3, get-intrinsic@npm:^1.2.0, get-intrinsic@npm:^1.2.1, get-intrinsic@npm:^1.2.2": - version: 1.2.2 - resolution: "get-intrinsic@npm:1.2.2" +"get-intrinsic@npm:^1.1.3, get-intrinsic@npm:^1.2.1, get-intrinsic@npm:^1.2.3, get-intrinsic@npm:^1.2.4": + version: 1.2.4 + resolution: "get-intrinsic@npm:1.2.4" dependencies: + es-errors: ^1.3.0 function-bind: ^1.1.2 has-proto: ^1.0.1 has-symbols: ^1.0.3 hasown: ^2.0.0 - checksum: 447ff0724df26829908dc033b62732359596fcf66027bc131ab37984afb33842d9cd458fd6cecadfe7eac22fd8a54b349799ed334cf2726025c921c7250e7417 - languageName: node - linkType: hard - -"get-iterator@npm:^1.0.2": - version: 1.0.2 - resolution: "get-iterator@npm:1.0.2" - checksum: 4a819aa91ecb61f4fd507bd62e3468d55f642f06011f944c381a739a21f685c36a37feb9324c8971e7c0fc70ca172066c45874fa2d1dcdf4b4fb8e43f16058c2 + checksum: 414e3cdf2c203d1b9d7d33111df746a4512a1aa622770b361dadddf8ed0b5aeb26c560f49ca077e24bfafb0acb55ca908d1f709216ccba33ffc548ec8a79a951 languageName: node linkType: hard @@ -7403,34 +7584,35 @@ __metadata: languageName: node linkType: hard -"get-symbol-description@npm:^1.0.0": - version: 1.0.0 - resolution: "get-symbol-description@npm:1.0.0" +"get-symbol-description@npm:^1.0.2": + version: 1.0.2 + resolution: "get-symbol-description@npm:1.0.2" dependencies: - call-bind: ^1.0.2 - get-intrinsic: ^1.1.1 - checksum: 9ceff8fe968f9270a37a1f73bf3f1f7bda69ca80f4f80850670e0e7b9444ff99323f7ac52f96567f8b5f5fbe7ac717a0d81d3407c7313e82810c6199446a5247 + call-bind: ^1.0.5 + es-errors: ^1.3.0 + get-intrinsic: ^1.2.4 + checksum: e1cb53bc211f9dbe9691a4f97a46837a553c4e7caadd0488dc24ac694db8a390b93edd412b48dcdd0b4bbb4c595de1709effc75fc87c0839deedc6968f5bd973 languageName: node linkType: hard "get-tsconfig@npm:^4.5.0": - version: 4.7.2 - resolution: "get-tsconfig@npm:4.7.2" + version: 4.7.3 + resolution: "get-tsconfig@npm:4.7.3" dependencies: resolve-pkg-maps: ^1.0.0 - checksum: 172358903250eff0103943f816e8a4e51d29b8e5449058bdf7266714a908a48239f6884308bd3a6ff28b09f692b9533dbebfd183ab63e4e14f073cda91f1bca9 + checksum: d124e6900f8beb3b71f215941096075223158d0abb09fb5daa8d83299f6c17d5e95a97d12847b387e9e716bb9bd256a473f918fb8020f3b1acc0b1e5c2830bbf languageName: node linkType: hard "get-uri@npm:^6.0.1": - version: 6.0.2 - resolution: "get-uri@npm:6.0.2" + version: 6.0.3 + resolution: "get-uri@npm:6.0.3" dependencies: basic-ftp: ^5.0.2 - data-uri-to-buffer: ^6.0.0 + data-uri-to-buffer: ^6.0.2 debug: ^4.3.4 - fs-extra: ^8.1.0 - checksum: 762de3b0e3d4e7afc966e4ce93be587d70c270590da9b4c8fbff888362656c055838d926903d1774cbfeed4d392b4d6def4b2c06d48c050580070426a3a8629b + fs-extra: ^11.2.0 + checksum: 3eda448a59fa1ba82ad4f252e58490fec586b644f2dc9c98ba3ab20e801ecc8a1bc1784829c474c9d188edb633d4dfd81c33894ca6117a33a16e8e013b41b40f languageName: node linkType: hard @@ -7460,17 +7642,17 @@ __metadata: linkType: hard "glob@npm:^10.2.2, glob@npm:^10.3.10": - version: 10.3.10 - resolution: "glob@npm:10.3.10" + version: 10.3.12 + resolution: "glob@npm:10.3.12" dependencies: foreground-child: ^3.1.0 - jackspeak: ^2.3.5 + jackspeak: ^2.3.6 minimatch: ^9.0.1 - minipass: ^5.0.0 || ^6.0.2 || ^7.0.0 - path-scurry: ^1.10.1 + minipass: ^7.0.4 + path-scurry: ^1.10.2 bin: glob: dist/esm/bin.mjs - checksum: 4f2fe2511e157b5a3f525a54092169a5f92405f24d2aed3142f4411df328baca13059f4182f1db1bf933e2c69c0bd89e57ae87edd8950cba8c7ccbe84f721cf3 + checksum: 2b0949d6363021aaa561b108ac317bf5a97271b8a5d7a5fac1a176e40e8068ecdcccc992f8a7e958593d501103ac06d673de92adc1efcbdab45edefe35f8d7c6 languageName: node linkType: hard @@ -7547,7 +7729,7 @@ __metadata: languageName: node linkType: hard -"graceful-fs@npm:^4.1.15, graceful-fs@npm:^4.1.2, graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6, graceful-fs@npm:^4.2.9": +"graceful-fs@npm:^4.1.15, graceful-fs@npm:^4.1.2, graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.11, graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6, graceful-fs@npm:^4.2.9": version: 4.2.11 resolution: "graceful-fs@npm:4.2.11" checksum: ac85f94da92d8eb6b7f5a8b20ce65e43d66761c55ce85ac96df6865308390da45a8d3f0296dd3a663de65d30ba497bd46c696cc1e248c72b13d6d567138a4fc7 @@ -7596,19 +7778,19 @@ __metadata: languageName: node linkType: hard -"has-property-descriptors@npm:^1.0.0, has-property-descriptors@npm:^1.0.1": - version: 1.0.1 - resolution: "has-property-descriptors@npm:1.0.1" +"has-property-descriptors@npm:^1.0.0, has-property-descriptors@npm:^1.0.2": + version: 1.0.2 + resolution: "has-property-descriptors@npm:1.0.2" dependencies: - get-intrinsic: ^1.2.2 - checksum: 2bcc6bf6ec6af375add4e4b4ef586e43674850a91ad4d46666d0b28ba8e1fd69e424c7677d24d60f69470ad0afaa2f3197f508b20b0bb7dd99a8ab77ffc4b7c4 + es-define-property: ^1.0.0 + checksum: fcbb246ea2838058be39887935231c6d5788babed499d0e9d0cc5737494c48aba4fe17ba1449e0d0fbbb1e36175442faa37f9c427ae357d6ccb1d895fbcd3de3 languageName: node linkType: hard -"has-proto@npm:^1.0.1": - version: 1.0.1 - resolution: "has-proto@npm:1.0.1" - checksum: febc5b5b531de8022806ad7407935e2135f1cc9e64636c3916c6842bd7995994ca3b29871ecd7954bd35f9e2986c17b3b227880484d22259e2f8e6ce63fd383e +"has-proto@npm:^1.0.1, has-proto@npm:^1.0.3": + version: 1.0.3 + resolution: "has-proto@npm:1.0.3" + checksum: fe7c3d50b33f50f3933a04413ed1f69441d21d2d2944f81036276d30635cad9279f6b43bc8f32036c31ebdfcf6e731150f46c1907ad90c669ffe9b066c3ba5c4 languageName: node linkType: hard @@ -7619,12 +7801,12 @@ __metadata: languageName: node linkType: hard -"has-tostringtag@npm:^1.0.0": - version: 1.0.0 - resolution: "has-tostringtag@npm:1.0.0" +"has-tostringtag@npm:^1.0.0, has-tostringtag@npm:^1.0.2": + version: 1.0.2 + resolution: "has-tostringtag@npm:1.0.2" dependencies: - has-symbols: ^1.0.2 - checksum: cc12eb28cb6ae22369ebaad3a8ab0799ed61270991be88f208d508076a1e99abe4198c965935ce85ea90b60c94ddda73693b0920b58e7ead048b4a391b502c1c + has-symbols: ^1.0.3 + checksum: 999d60bb753ad714356b2c6c87b7fb74f32463b8426e159397da4bde5bca7e598ab1073f4d8d4deafac297f2eb311484cd177af242776bf05f0d11565680468d languageName: node linkType: hard @@ -7639,6 +7821,16 @@ __metadata: languageName: node linkType: hard +"hash-base@npm:~3.0": + version: 3.0.4 + resolution: "hash-base@npm:3.0.4" + dependencies: + inherits: ^2.0.1 + safe-buffer: ^5.0.1 + checksum: 878465a0dfcc33cce195c2804135352c590d6d10980adc91a9005fd377e77f2011256c2b7cfce472e3f2e92d561d1bf3228d2da06348a9017ce9a258b3b49764 + languageName: node + linkType: hard + "hash.js@npm:^1.0.0, hash.js@npm:^1.0.3, hash.js@npm:^1.1.7": version: 1.1.7 resolution: "hash.js@npm:1.1.7" @@ -7656,12 +7848,12 @@ __metadata: languageName: node linkType: hard -"hasown@npm:^2.0.0": - version: 2.0.0 - resolution: "hasown@npm:2.0.0" +"hasown@npm:^2.0.0, hasown@npm:^2.0.1, hasown@npm:^2.0.2": + version: 2.0.2 + resolution: "hasown@npm:2.0.2" dependencies: function-bind: ^1.1.2 - checksum: 6151c75ca12554565098641c98a40f4cc86b85b0fd5b6fe92360967e4605a4f9610f7757260b4e8098dd1c2ce7f4b095f2006fe72a570e3b6d2d28de0298c176 + checksum: e8516f776a15149ca6c6ed2ae3110c417a00b62260e222590e54aa367cbcd6ed99122020b37b7fbdf05748df57b265e70095d7bf35a47660587619b15ffb93db languageName: node linkType: hard @@ -7752,17 +7944,7 @@ __metadata: languageName: node linkType: hard -"http-proxy-agent@npm:^7.0.0": - version: 7.0.0 - resolution: "http-proxy-agent@npm:7.0.0" - dependencies: - agent-base: ^7.1.0 - debug: ^4.3.4 - checksum: 48d4fac997917e15f45094852b63b62a46d0c8a4f0b9c6c23ca26d27b8df8d178bed88389e604745e748bd9a01f5023e25093722777f0593c3f052009ff438b6 - languageName: node - linkType: hard - -"http-proxy-agent@npm:^7.0.1": +"http-proxy-agent@npm:^7.0.0, http-proxy-agent@npm:^7.0.1": version: 7.0.2 resolution: "http-proxy-agent@npm:7.0.2" dependencies: @@ -7783,17 +7965,7 @@ __metadata: languageName: node linkType: hard -"https-proxy-agent@npm:^7.0.1, https-proxy-agent@npm:^7.0.2": - version: 7.0.2 - resolution: "https-proxy-agent@npm:7.0.2" - dependencies: - agent-base: ^7.0.2 - debug: 4 - checksum: 088969a0dd476ea7a0ed0a2cf1283013682b08f874c3bc6696c83fa061d2c157d29ef0ad3eb70a2046010bb7665573b2388d10fdcb3e410a66995e5248444292 - languageName: node - linkType: hard - -"https-proxy-agent@npm:^7.0.3": +"https-proxy-agent@npm:^7.0.1, https-proxy-agent@npm:^7.0.2, https-proxy-agent@npm:^7.0.3": version: 7.0.4 resolution: "https-proxy-agent@npm:7.0.4" dependencies: @@ -7817,13 +7989,6 @@ __metadata: languageName: node linkType: hard -"hyperdyperid@npm:^1.2.0": - version: 1.2.0 - resolution: "hyperdyperid@npm:1.2.0" - checksum: 210029d1c86926f09109f6317d143f8b056fc38e8dd11b0c3e3205fc6c6ff8429fb55b4b9c2bce065462719ed9d34366eced387aaa0035d93eb76b306a8547ef - languageName: node - linkType: hard - "iconv-lite@npm:0.4.24": version: 0.4.24 resolution: "iconv-lite@npm:0.4.24" @@ -7850,9 +8015,9 @@ __metadata: linkType: hard "ignore@npm:^5.2.0, ignore@npm:^5.2.4": - version: 5.3.0 - resolution: "ignore@npm:5.3.0" - checksum: 2736da6621f14ced652785cb05d86301a66d70248597537176612bd0c8630893564bd5f6421f8806b09e8472e75c591ef01672ab8059c07c6eb2c09cefe04bf9 + version: 5.3.1 + resolution: "ignore@npm:5.3.1" + checksum: 71d7bb4c1dbe020f915fd881108cbe85a0db3d636a0ea3ba911393c53946711d13a9b1143c7e70db06d571a5822c0a324a6bcde5c9904e7ca5047f01f1bf8cd3 languageName: node linkType: hard @@ -7916,7 +8081,7 @@ __metadata: languageName: node linkType: hard -"inherits@npm:2, inherits@npm:2.0.4, inherits@npm:^2.0.1, inherits@npm:^2.0.3, inherits@npm:^2.0.4, inherits@npm:~2.0.4": +"inherits@npm:2, inherits@npm:2.0.4, inherits@npm:^2.0.1, inherits@npm:^2.0.3, inherits@npm:^2.0.4, inherits@npm:~2.0.3, inherits@npm:~2.0.4": version: 2.0.4 resolution: "inherits@npm:2.0.4" checksum: 4a48a733847879d6cf6691860a6b1e3f0f4754176e4d71494c41f3475553768b10f84b5ce1d40fbd0e34e6bfbb864ee35858ad4dd2cf31e02fc4a154b724d7f1 @@ -7937,31 +8102,31 @@ __metadata: languageName: node linkType: hard -"interface-datastore@npm:^8.2.0": - version: 8.2.10 - resolution: "interface-datastore@npm:8.2.10" +"interface-datastore@npm:^8.0.0, interface-datastore@npm:^8.2.0, interface-datastore@npm:^8.2.11": + version: 8.2.11 + resolution: "interface-datastore@npm:8.2.11" dependencies: interface-store: ^5.0.0 - uint8arrays: ^5.0.0 - checksum: 16e12820b8423e457a6255377f373ea20132d7080809756b350e8914fde9abb73c4dd226cb3a9dda31bff790c181a02382bdde0482f9385ea4d2168c35ae93d8 + uint8arrays: ^5.0.2 + checksum: 24c906277c21d8d74d981fe08cc5a2dde727e60d7d77b82930a09d0c8315a63e30e1e4a4b9f781f2c2e2a2e905f4dbb8e6db9184bd305bd4174c94c4dad3aefb languageName: node linkType: hard "interface-store@npm:^5.0.0": - version: 5.1.7 - resolution: "interface-store@npm:5.1.7" - checksum: aeddcdbfe8601f127c485ede6c6323bf2b302c713a1661036403dfd01b6b91e19a314ecf002477f108cb9c94d67781f88d386d3688f1e9c7cd1464a756ac28fa + version: 5.1.8 + resolution: "interface-store@npm:5.1.8" + checksum: 7b3b67e5fc3e2d9286db94e1941893176a989f89e6cb8027425acfbb5509b8d9845aaa614bac1b03514f6e7852cc713e568c67e3ab349bf56b3c9ffdc516e9bb languageName: node linkType: hard -"internal-slot@npm:^1.0.5": - version: 1.0.6 - resolution: "internal-slot@npm:1.0.6" +"internal-slot@npm:^1.0.7": + version: 1.0.7 + resolution: "internal-slot@npm:1.0.7" dependencies: - get-intrinsic: ^1.2.2 + es-errors: ^1.3.0 hasown: ^2.0.0 side-channel: ^1.0.4 - checksum: 7872454888047553ce97a3fa1da7cc054a28ec5400a9c2e9f4dbe4fe7c1d041cb8e8301467614b80d4246d50377aad2fb58860b294ed74d6700cc346b6f89549 + checksum: cadc5eea5d7d9bc2342e93aae9f31f04c196afebb11bde97448327049f492cd7081e18623ae71388aac9cd237b692ca3a105be9c68ac39c1dec679d7409e33eb languageName: node linkType: hard @@ -7972,6 +8137,16 @@ __metadata: languageName: node linkType: hard +"ip-address@npm:^9.0.5": + version: 9.0.5 + resolution: "ip-address@npm:9.0.5" + dependencies: + jsbn: 1.1.0 + sprintf-js: ^1.1.3 + checksum: aa15f12cfd0ef5e38349744e3654bae649a34c3b10c77a674a167e99925d1549486c5b14730eebce9fea26f6db9d5e42097b00aa4f9f612e68c79121c71652dc + languageName: node + linkType: hard + "ip-regex@npm:^5.0.0": version: 5.0.0 resolution: "ip-regex@npm:5.0.0" @@ -7979,24 +8154,10 @@ __metadata: languageName: node linkType: hard -"ip@npm:^1.1.8": - version: 1.1.8 - resolution: "ip@npm:1.1.8" - checksum: a2ade53eb339fb0cbe9e69a44caab10d6e3784662285eb5d2677117ee4facc33a64679051c35e0dfdb1a3983a51ce2f5d2cb36446d52e10d01881789b76e28fb - languageName: node - linkType: hard - -"ip@npm:^2.0.0": - version: 2.0.0 - resolution: "ip@npm:2.0.0" - checksum: cfcfac6b873b701996d71ec82a7dd27ba92450afdb421e356f44044ed688df04567344c36cbacea7d01b1c39a4c732dc012570ebe9bebfb06f27314bca625349 - languageName: node - linkType: hard - "ipaddr.js@npm:^2.1.0": - version: 2.1.0 - resolution: "ipaddr.js@npm:2.1.0" - checksum: 807a054f2bd720c4d97ee479d6c9e865c233bea21f139fb8dabd5a35c4226d2621c42e07b4ad94ff3f82add926a607d8d9d37c625ad0319f0e08f9f2bd1968e2 + version: 2.2.0 + resolution: "ipaddr.js@npm:2.2.0" + checksum: 770ba8451fd9bf78015e8edac0d5abd7a708cbf75f9429ca9147a9d2f3a2d60767cd5de2aab2b1e13ca6e4445bdeff42bf12ef6f151c07a5c6cf8a44328e2859 languageName: node linkType: hard @@ -8010,14 +8171,13 @@ __metadata: languageName: node linkType: hard -"is-array-buffer@npm:^3.0.1, is-array-buffer@npm:^3.0.2": - version: 3.0.2 - resolution: "is-array-buffer@npm:3.0.2" +"is-array-buffer@npm:^3.0.4": + version: 3.0.4 + resolution: "is-array-buffer@npm:3.0.4" dependencies: call-bind: ^1.0.2 - get-intrinsic: ^1.2.0 - is-typed-array: ^1.1.10 - checksum: dcac9dda66ff17df9cabdc58214172bf41082f956eab30bb0d86bc0fab1e44b690fc8e1f855cf2481245caf4e8a5a006a982a71ddccec84032ed41f9d8da8c14 + get-intrinsic: ^1.2.1 + checksum: e4e3e6ef0ff2239e75371d221f74bc3c26a03564a22efb39f6bb02609b598917ddeecef4e8c877df2a25888f247a98198959842a5e73236bc7f22cabdf6351a7 languageName: node linkType: hard @@ -8077,6 +8237,15 @@ __metadata: languageName: node linkType: hard +"is-data-view@npm:^1.0.1": + version: 1.0.1 + resolution: "is-data-view@npm:1.0.1" + dependencies: + is-typed-array: ^1.1.13 + checksum: 4ba4562ac2b2ec005fefe48269d6bd0152785458cd253c746154ffb8a8ab506a29d0cfb3b74af87513843776a88e4981ae25c89457bf640a33748eab1a7216b5 + languageName: node + linkType: hard + "is-date-object@npm:^1.0.1": version: 1.0.5 resolution: "is-date-object@npm:1.0.5" @@ -8146,24 +8315,17 @@ __metadata: languageName: node linkType: hard -"is-loopback-addr@npm:^2.0.1": +"is-loopback-addr@npm:^2.0.2": version: 2.0.2 resolution: "is-loopback-addr@npm:2.0.2" checksum: c7818bd2815aa7aad1efd410d38f58647759e206b43fcf5b3a35db866ceff9af0b0145f1dcba472267c6e1b965883d1ebf321f3eb18c6a8c1c609c4f91092f2f languageName: node linkType: hard -"is-negative-zero@npm:^2.0.2": - version: 2.0.2 - resolution: "is-negative-zero@npm:2.0.2" - checksum: f3232194c47a549da60c3d509c9a09be442507616b69454716692e37ae9f37c4dea264fb208ad0c9f3efd15a796a46b79df07c7e53c6227c32170608b809149a - languageName: node - linkType: hard - -"is-network-error@npm:^1.0.0": - version: 1.0.1 - resolution: "is-network-error@npm:1.0.1" - checksum: 165d61500c4186c62db5a3a693d6bfa14ca40fe9b471ef4cd4f27b20ef6760880faf5386dc01ca9867531631782941fedaa94521d09959edf71f046e393c7b91 +"is-negative-zero@npm:^2.0.3": + version: 2.0.3 + resolution: "is-negative-zero@npm:2.0.3" + checksum: c1e6b23d2070c0539d7b36022d5a94407132411d01aba39ec549af824231f3804b1aea90b5e4e58e807a65d23ceb538ed6e355ce76b267bdd86edb757ffcbdcd languageName: node linkType: hard @@ -8244,12 +8406,12 @@ __metadata: languageName: node linkType: hard -"is-shared-array-buffer@npm:^1.0.2": - version: 1.0.2 - resolution: "is-shared-array-buffer@npm:1.0.2" +"is-shared-array-buffer@npm:^1.0.2, is-shared-array-buffer@npm:^1.0.3": + version: 1.0.3 + resolution: "is-shared-array-buffer@npm:1.0.3" dependencies: - call-bind: ^1.0.2 - checksum: 9508929cf14fdc1afc9d61d723c6e8d34f5e117f0bffda4d97e7a5d88c3a8681f633a74f8e3ad1fe92d5113f9b921dc5ca44356492079612f9a247efbce7032a + call-bind: ^1.0.7 + checksum: a4fff602c309e64ccaa83b859255a43bb011145a42d3f56f67d9268b55bc7e6d98a5981a1d834186ad3105d6739d21547083fe7259c76c0468483fc538e716d8 languageName: node linkType: hard @@ -8285,12 +8447,12 @@ __metadata: languageName: node linkType: hard -"is-typed-array@npm:^1.1.10, is-typed-array@npm:^1.1.12, is-typed-array@npm:^1.1.3, is-typed-array@npm:^1.1.9": - version: 1.1.12 - resolution: "is-typed-array@npm:1.1.12" +"is-typed-array@npm:^1.1.13, is-typed-array@npm:^1.1.3": + version: 1.1.13 + resolution: "is-typed-array@npm:1.1.13" dependencies: - which-typed-array: ^1.1.11 - checksum: 4c89c4a3be07186caddadf92197b17fda663a9d259ea0d44a85f171558270d36059d1c386d34a12cba22dfade5aba497ce22778e866adc9406098c8fc4771796 + which-typed-array: ^1.1.14 + checksum: 150f9ada183a61554c91e1c4290086d2c100b0dff45f60b028519be72a8db964da403c48760723bf5253979b8dffe7b544246e0e5351dcd05c5fdb1dcc1dc0f0 languageName: node linkType: hard @@ -8331,6 +8493,13 @@ __metadata: languageName: node linkType: hard +"isarray@npm:~1.0.0": + version: 1.0.0 + resolution: "isarray@npm:1.0.0" + checksum: f032df8e02dce8ec565cf2eb605ea939bdccea528dbcf565cdf92bfa2da9110461159d86a537388ef1acef8815a330642d7885b29010e8f7eac967c9993b65ab + languageName: node + linkType: hard + "isexe@npm:^2.0.0": version: 2.0.0 resolution: "isexe@npm:2.0.0" @@ -8382,15 +8551,15 @@ __metadata: linkType: hard "istanbul-lib-instrument@npm:^6.0.0": - version: 6.0.1 - resolution: "istanbul-lib-instrument@npm:6.0.1" + version: 6.0.2 + resolution: "istanbul-lib-instrument@npm:6.0.2" dependencies: - "@babel/core": ^7.12.3 - "@babel/parser": ^7.14.7 - "@istanbuljs/schema": ^0.1.2 + "@babel/core": ^7.23.9 + "@babel/parser": ^7.23.9 + "@istanbuljs/schema": ^0.1.3 istanbul-lib-coverage: ^3.2.0 semver: ^7.5.4 - checksum: fb23472e739cfc9b027cefcd7d551d5e7ca7ff2817ae5150fab99fe42786a7f7b56a29a2aa8309c37092e18297b8003f9c274f50ca4360949094d17fbac81472 + checksum: c10aa1e93a022f9767d7f41e6c07d244cc0a5c090fbb5522d70a5f21fcb98c52b7038850276c6fd1a7a17d1868c14a9d4eb8a24efe58a0ebb9a06f3da68131fe languageName: node linkType: hard @@ -8417,52 +8586,42 @@ __metadata: linkType: hard "istanbul-reports@npm:^3.1.3": - version: 3.1.6 - resolution: "istanbul-reports@npm:3.1.6" + version: 3.1.7 + resolution: "istanbul-reports@npm:3.1.7" dependencies: html-escaper: ^2.0.0 istanbul-lib-report: ^3.0.0 - checksum: 44c4c0582f287f02341e9720997f9e82c071627e1e862895745d5f52ec72c9b9f38e1d12370015d2a71dcead794f34c7732aaef3fab80a24bc617a21c3d911d6 + checksum: 2072db6e07bfbb4d0eb30e2700250636182398c1af811aea5032acb219d2080f7586923c09fa194029efd6b92361afb3dcbe1ebcc3ee6651d13340f7c6c4ed95 languageName: node linkType: hard -"it-all@npm:^3.0.0, it-all@npm:^3.0.1, it-all@npm:^3.0.2": +"it-all@npm:^3.0.0, it-all@npm:^3.0.2, it-all@npm:^3.0.4": version: 3.0.4 resolution: "it-all@npm:3.0.4" checksum: fb7259660b6555ae268ffde6f0245026e9d4e8afccf9c43a088bb0ff0483aaca95954b6074c1c96d46a57b572bce35fa1bb8542934ce9aee477e1dba46293891 languageName: node linkType: hard -"it-batched-bytes@npm:^2.0.2": - version: 2.0.5 - resolution: "it-batched-bytes@npm:2.0.5" - dependencies: - p-defer: ^4.0.0 - uint8arraylist: ^2.4.1 - checksum: c127881de01aae0d1625b2179ba66f7a084466adef0d5b20ab7129040651545e4aacbff01cf372e5118a2836685463732fa52714a16b16856657f8e05861b899 - languageName: node - linkType: hard - "it-byte-stream@npm:^1.0.0": - version: 1.0.7 - resolution: "it-byte-stream@npm:1.0.7" + version: 1.0.8 + resolution: "it-byte-stream@npm:1.0.8" dependencies: it-stream-types: ^2.0.1 p-defer: ^4.0.0 race-signal: ^1.0.1 uint8arraylist: ^2.4.1 - checksum: 9cd63aa3ab2e7ebe1a3cac545f546d9362577901922b7a75803e36caacb0ef46b0cf4bc5334a0acdc548ba976849065527b9467a3c048af64233e70891537aad + checksum: b8fbb98b8beaf8382b1f4c3822cab6587094e1ddeb09769b9f96a078e40e5c0e7fda4fa8b106bc79db608428d79e9786367a220d724ca8acbbd9ba49f809e5c9 languageName: node linkType: hard -"it-drain@npm:^3.0.1, it-drain@npm:^3.0.2": +"it-drain@npm:^3.0.2, it-drain@npm:^3.0.5": version: 3.0.5 resolution: "it-drain@npm:3.0.5" checksum: 6ab86dc487737a0a87556fab52dadd00f376881b633bd00b8c461f1e8eace47c426e8065700946eb066072e33fc7df7f0e9fa12426bd1d8cac914d52c8f44f43 languageName: node linkType: hard -"it-filter@npm:^3.0.0, it-filter@npm:^3.0.1": +"it-filter@npm:^3.0.4": version: 3.0.4 resolution: "it-filter@npm:3.0.4" dependencies: @@ -8478,7 +8637,7 @@ __metadata: languageName: node linkType: hard -"it-foreach@npm:^2.0.3": +"it-foreach@npm:^2.0.6": version: 2.0.6 resolution: "it-foreach@npm:2.0.6" dependencies: @@ -8487,20 +8646,7 @@ __metadata: languageName: node linkType: hard -"it-handshake@npm:^4.1.3": - version: 4.1.3 - resolution: "it-handshake@npm:4.1.3" - dependencies: - it-pushable: ^3.1.0 - it-reader: ^6.0.1 - it-stream-types: ^2.0.1 - p-defer: ^4.0.0 - uint8arraylist: ^2.0.0 - checksum: 508a33e09da02c16ede4453a669bf23fb49d8cc96f3ac85eb36111530da9817c5ada73e7647706400f0f60865afe6164cc51bd39187b786e6736db4b0e587b2f - languageName: node - linkType: hard - -"it-length-prefixed-stream@npm:^1.0.0": +"it-length-prefixed-stream@npm:^1.0.0, it-length-prefixed-stream@npm:^1.1.6": version: 1.1.6 resolution: "it-length-prefixed-stream@npm:1.1.6" dependencies: @@ -8512,7 +8658,7 @@ __metadata: languageName: node linkType: hard -"it-length-prefixed@npm:^9.0.1": +"it-length-prefixed@npm:^9.0.1, it-length-prefixed@npm:^9.0.4": version: 9.0.4 resolution: "it-length-prefixed@npm:9.0.4" dependencies: @@ -8533,7 +8679,7 @@ __metadata: languageName: node linkType: hard -"it-map@npm:^3.0.1, it-map@npm:^3.0.3": +"it-map@npm:^3.0.3, it-map@npm:^3.0.5": version: 3.0.5 resolution: "it-map@npm:3.0.5" dependencies: @@ -8542,7 +8688,7 @@ __metadata: languageName: node linkType: hard -"it-merge@npm:^3.0.0, it-merge@npm:^3.0.1": +"it-merge@npm:^3.0.0, it-merge@npm:^3.0.3": version: 3.0.3 resolution: "it-merge@npm:3.0.3" dependencies: @@ -8561,7 +8707,7 @@ __metadata: languageName: node linkType: hard -"it-parallel@npm:^3.0.0": +"it-parallel@npm:^3.0.0, it-parallel@npm:^3.0.6": version: 3.0.6 resolution: "it-parallel@npm:3.0.6" dependencies: @@ -8577,7 +8723,7 @@ __metadata: languageName: node linkType: hard -"it-pipe@npm:^3.0.0, it-pipe@npm:^3.0.1": +"it-pipe@npm:^3.0.1": version: 3.0.1 resolution: "it-pipe@npm:3.0.1" dependencies: @@ -8588,7 +8734,7 @@ __metadata: languageName: node linkType: hard -"it-protobuf-stream@npm:^1.0.0": +"it-protobuf-stream@npm:^1.1.2": version: 1.1.2 resolution: "it-protobuf-stream@npm:1.1.2" dependencies: @@ -8600,7 +8746,7 @@ __metadata: languageName: node linkType: hard -"it-pushable@npm:^3.0.0, it-pushable@npm:^3.1.0, it-pushable@npm:^3.1.2, it-pushable@npm:^3.1.3, it-pushable@npm:^3.2.0, it-pushable@npm:^3.2.1, it-pushable@npm:^3.2.3": +"it-pushable@npm:^3.1.2, it-pushable@npm:^3.1.3, it-pushable@npm:^3.2.0, it-pushable@npm:^3.2.1, it-pushable@npm:^3.2.3": version: 3.2.3 resolution: "it-pushable@npm:3.2.3" dependencies: @@ -8619,7 +8765,7 @@ __metadata: languageName: node linkType: hard -"it-sort@npm:^3.0.1": +"it-sort@npm:^3.0.4": version: 3.0.4 resolution: "it-sort@npm:3.0.4" dependencies: @@ -8635,14 +8781,14 @@ __metadata: languageName: node linkType: hard -"it-take@npm:^3.0.1": +"it-take@npm:^3.0.1, it-take@npm:^3.0.4": version: 3.0.4 resolution: "it-take@npm:3.0.4" checksum: 69dedde350817cba8de80e0432c9b81c35ff2b91f9c80582e657e382ec8c38af003f575353ae22605c963c28605a48cb994c7dba93fedac732db35ee86d7e516 languageName: node linkType: hard -"jackspeak@npm:^2.3.5": +"jackspeak@npm:^2.3.6": version: 2.3.6 resolution: "jackspeak@npm:2.3.6" dependencies: @@ -8883,14 +9029,14 @@ __metadata: linkType: hard "jest-mock-extended@npm:^3.0.3, jest-mock-extended@npm:^3.0.4, jest-mock-extended@npm:^3.0.5": - version: 3.0.5 - resolution: "jest-mock-extended@npm:3.0.5" + version: 3.0.6 + resolution: "jest-mock-extended@npm:3.0.6" dependencies: - ts-essentials: ^7.0.3 + ts-essentials: ^9.4.2 peerDependencies: jest: ^24.0.0 || ^25.0.0 || ^26.0.0 || ^27.0.0 || ^28.0.0 || ^29.0.0 typescript: ^3.0.0 || ^4.0.0 || ^5.0.0 - checksum: 440c52f743af588493c2cd02fa7e4e42177748ac3f7ae720f414bd58a4a72fad4271878457bf8796b62abcf9cf32cde4dc5151caad0805037bd965cc9ef07ca8 + checksum: 7abff3242f932481561a209b314e0501efa811c7dfd7915d803b897b079d07c5db74b9ca86e1d25110d7cdefa6d7d083d3bc9b431f383182f99d8552fbafbfad languageName: node linkType: hard @@ -9190,7 +9336,14 @@ __metadata: languageName: node linkType: hard -"jsdoc-type-pratt-parser@npm:~4.0.0": +"jsbn@npm:1.1.0": + version: 1.1.0 + resolution: "jsbn@npm:1.1.0" + checksum: 944f924f2bd67ad533b3850eee47603eed0f6ae425fd1ee8c760f477e8c34a05f144c1bd4f5a5dd1963141dc79a2c55f89ccc5ab77d039e7077f3ad196b64965 + languageName: node + linkType: hard + +"jsdoc-type-pratt-parser@npm:~4.0.0": version: 4.0.0 resolution: "jsdoc-type-pratt-parser@npm:4.0.0" checksum: af0629c9517e484be778d8564440fec8de5b7610e0c9c88a3ba4554321364faf72b46689c8d8845faa12c0718437a9ed97e231977efc0f2d50e8a2dbad807eb3 @@ -9213,29 +9366,6 @@ __metadata: languageName: node linkType: hard -"json-joy@npm:^9.2.0": - version: 9.9.1 - resolution: "json-joy@npm:9.9.1" - dependencies: - arg: ^5.0.2 - hyperdyperid: ^1.2.0 - peerDependencies: - quill-delta: ^5 - rxjs: 7 - tslib: 2 - bin: - jj: bin/jj.js - json-pack: bin/json-pack.js - json-pack-test: bin/json-pack-test.js - json-patch: bin/json-patch.js - json-patch-test: bin/json-patch-test.js - json-pointer: bin/json-pointer.js - json-pointer-test: bin/json-pointer-test.js - json-unpack: bin/json-unpack.js - checksum: d165398682f00019796225faf365cd8d060f3e086af39bb5081c30907b7e52eaf13697d1c0f6ee2b010fe255ae1fd776e05ad7d6ee5fb549e98fe982f560884b - languageName: node - linkType: hard - "json-parse-even-better-errors@npm:^2.3.0, json-parse-even-better-errors@npm:^2.3.1": version: 2.3.1 resolution: "json-parse-even-better-errors@npm:2.3.1" @@ -9284,18 +9414,6 @@ __metadata: languageName: node linkType: hard -"jsonfile@npm:^4.0.0": - version: 4.0.0 - resolution: "jsonfile@npm:4.0.0" - dependencies: - graceful-fs: ^4.1.6 - dependenciesMeta: - graceful-fs: - optional: true - checksum: 6447d6224f0d31623eef9b51185af03ac328a7553efcee30fa423d98a9e276ca08db87d71e17f2310b0263fd3ffa6c2a90a6308367f661dc21580f9469897c9e - languageName: node - linkType: hard - "jsonfile@npm:^6.0.1": version: 6.1.0 resolution: "jsonfile@npm:6.1.0" @@ -9430,8 +9548,8 @@ __metadata: linkType: hard "koa@npm:^2.14.2": - version: 2.15.0 - resolution: "koa@npm:2.15.0" + version: 2.15.3 + resolution: "koa@npm:2.15.3" dependencies: accepts: ^1.3.5 cache-content-type: ^1.0.0 @@ -9456,7 +9574,7 @@ __metadata: statuses: ^1.5.0 type-is: ^1.6.16 vary: ^1.1.2 - checksum: a97741f89f328f25ae94d82d0ee608377d89e086c73f2d868023e6050dea682ef93e0a5c80097f3aaad28121853aea50a7fb3c0c12ecc45798da2fd1255f580b + checksum: 7c3537443b1a588cf5c3e5554b914ff2bad510323d22b41861d5e0c97d47e9c5997965f303ede8be8bd83d309a4eea1f82cd45d35d6838bc21bb1bb6a90d5d25 languageName: node linkType: hard @@ -9543,56 +9661,32 @@ __metadata: languageName: node linkType: hard -"libp2p@npm:^0.46.6": - version: 0.46.21 - resolution: "libp2p@npm:0.46.21" - dependencies: - "@achingbrain/nat-port-mapper": ^1.0.9 - "@libp2p/crypto": ^2.0.8 - "@libp2p/interface": ^0.1.6 - "@libp2p/interface-internal": ^0.1.9 - "@libp2p/keychain": ^3.0.8 - "@libp2p/logger": ^3.1.0 - "@libp2p/multistream-select": ^4.0.6 - "@libp2p/peer-collections": ^4.0.8 - "@libp2p/peer-id": ^3.0.6 - "@libp2p/peer-id-factory": ^3.0.8 - "@libp2p/peer-record": ^6.0.9 - "@libp2p/peer-store": ^9.0.9 - "@libp2p/utils": ^4.0.7 - "@multiformats/mafmt": ^12.1.2 - "@multiformats/multiaddr": ^12.1.5 - "@multiformats/multiaddr-matcher": ^1.0.0 +"libp2p@npm:^1.2.4": + version: 1.4.2 + resolution: "libp2p@npm:1.4.2" + dependencies: + "@libp2p/crypto": ^4.0.6 + "@libp2p/interface": ^1.2.0 + "@libp2p/interface-internal": ^1.1.0 + "@libp2p/logger": ^4.0.10 + "@libp2p/multistream-select": ^5.1.7 + "@libp2p/peer-collections": ^5.1.10 + "@libp2p/peer-id": ^4.0.10 + "@libp2p/peer-id-factory": ^4.0.10 + "@libp2p/peer-store": ^10.0.15 + "@libp2p/utils": ^5.3.1 + "@multiformats/dns": ^1.0.5 + "@multiformats/multiaddr": ^12.2.1 + "@multiformats/multiaddr-matcher": ^1.2.0 any-signal: ^4.1.1 - datastore-core: ^9.0.1 - delay: ^6.0.0 - interface-datastore: ^8.2.0 - it-all: ^3.0.2 - it-drain: ^3.0.2 - it-filter: ^3.0.1 - it-first: ^3.0.1 - it-handshake: ^4.1.3 - it-length-prefixed: ^9.0.1 - it-map: ^3.0.3 - it-merge: ^3.0.0 - it-pair: ^2.0.6 - it-parallel: ^3.0.0 - it-pipe: ^3.0.1 - it-protobuf-stream: ^1.0.0 - it-stream-types: ^2.0.1 + datastore-core: ^9.2.9 + interface-datastore: ^8.2.11 + it-merge: ^3.0.3 + it-parallel: ^3.0.6 merge-options: ^3.0.4 - multiformats: ^12.0.1 - p-defer: ^4.0.0 - p-queue: ^7.3.4 - p-retry: ^6.0.0 - private-ip: ^3.0.0 - protons-runtime: ^5.0.0 - rate-limiter-flexible: ^3.0.0 - uint8arraylist: ^2.4.3 - uint8arrays: ^4.0.6 - wherearewe: ^2.0.1 - xsalsa20: ^1.1.0 - checksum: 6f69e89e8f4ac28ee1b365db878379d28865982bf6d4cec9524d9445975b5eab4fa5dca581e704ce1438b196258e88856cf6778048b59a75ae09ca1b9417fbb8 + multiformats: ^13.1.0 + uint8arrays: ^5.0.3 + checksum: 111b52ddd704361781cb68f3ad6ba4e31120ba633e01a88decc2559cdaecb440b2da7f12435bd262cee886a22e2bfc0b4756400dcffdb537845cfb4c7d7a3532 languageName: node linkType: hard @@ -9657,6 +9751,13 @@ __metadata: languageName: node linkType: hard +"loady@npm:~0.0.5": + version: 0.0.5 + resolution: "loady@npm:0.0.5" + checksum: 3cba2ffa8cef8a082b3d23f22c1269a339e9f268105c30229bb3fed9123bb79830c0c7f3fa79f52286e1de9303b87e4eb3236952a6ee3fcffa83e7c576f7a8f5 + languageName: node + linkType: hard + "locate-path@npm:^5.0.0": version: 5.0.0 resolution: "locate-path@npm:5.0.0" @@ -9773,7 +9874,7 @@ __metadata: languageName: node linkType: hard -"lodash@npm:^4.17.21, lodash@npm:^4.17.4": +"lodash@npm:^4.17.21": version: 4.17.21 resolution: "lodash@npm:4.17.21" checksum: eb835a2e51d381e561e508ce932ea50a8e5a68f4ebdd771ea240d3048244a8d13658acbd502cd4829768c56f2e16bdd4340b9ea141297d472517b83868e677f7 @@ -9804,7 +9905,7 @@ __metadata: languageName: node linkType: hard -"lru-cache@npm:^10.0.1, lru-cache@npm:^9.1.1 || ^10.0.0": +"lru-cache@npm:^10.0.1, lru-cache@npm:^10.1.0, lru-cache@npm:^10.2.0": version: 10.2.0 resolution: "lru-cache@npm:10.2.0" checksum: eee7ddda4a7475deac51ac81d7dd78709095c6fa46e8350dc2d22462559a1faa3b81ed931d5464b13d48cbd7e08b46100b6f768c76833912bc444b99c37e25db @@ -9993,14 +10094,11 @@ __metadata: linkType: hard "memfs@npm:^4.6.0": - version: 4.6.0 - resolution: "memfs@npm:4.6.0" + version: 4.8.2 + resolution: "memfs@npm:4.8.2" dependencies: - json-joy: ^9.2.0 - thingies: ^1.11.1 - peerDependencies: - tslib: 2 - checksum: b32a35bee9f96dc011605f3bb39e74e6d2a5de51c952a77bb38a0dfabd3381c40ae382d27f385aa290edee8081597fb1a3b41a07bb3f775fd55312dc30ac1d9d + tslib: ^2.0.0 + checksum: ffbc79e89542c57ccdd83f906252313a8354fb050bab6500728a60a321ca2f090e70145c324ff1540b27272a34ff5049b2790e7d5a9af9ec4505fffeca19db8f languageName: node linkType: hard @@ -10135,7 +10233,7 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:9.0.3, minimatch@npm:^9.0.0, minimatch@npm:^9.0.1": +"minimatch@npm:9.0.3": version: 9.0.3 resolution: "minimatch@npm:9.0.3" dependencies: @@ -10153,6 +10251,15 @@ __metadata: languageName: node linkType: hard +"minimatch@npm:^9.0.0, minimatch@npm:^9.0.1": + version: 9.0.4 + resolution: "minimatch@npm:9.0.4" + dependencies: + brace-expansion: ^2.0.1 + checksum: cf717f597ec3eed7dabc33153482a2e8d49f4fd3c26e58fd9c71a94c5029a0838728841b93f46bf1263b65a8010e2ee800d0dc9b004ab8ba8b6d1ec07cc115b5 + languageName: node + linkType: hard + "minimist-options@npm:4.1.0": version: 4.1.0 resolution: "minimist-options@npm:4.1.0" @@ -10238,7 +10345,7 @@ __metadata: languageName: node linkType: hard -"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3": +"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3, minipass@npm:^7.0.4": version: 7.0.4 resolution: "minipass@npm:7.0.4" checksum: 87585e258b9488caf2e7acea242fd7856bbe9a2c84a7807643513a338d66f368c7d518200ad7b70a508664d408aa000517647b2930c259a8b1f9f0984f344a21 @@ -10317,7 +10424,7 @@ __metadata: languageName: node linkType: hard -"mortice@npm:^3.0.1": +"mortice@npm:^3.0.4": version: 3.0.4 resolution: "mortice@npm:3.0.4" dependencies: @@ -10399,10 +10506,10 @@ __metadata: languageName: node linkType: hard -"multiformats@npm:^13.0.0": - version: 13.0.1 - resolution: "multiformats@npm:13.0.1" - checksum: 63e5d6ee2c2a1d1e8fbd4b8c76fa41cf3d8204ceed1d57bc44cb30ff3d06b880ad58c3de52ae6d4397a662a6f1e3285dae74ee5d445fd1597516e1baec96d22a +"multiformats@npm:^13.0.0, multiformats@npm:^13.1.0": + version: 13.1.0 + resolution: "multiformats@npm:13.1.0" + checksum: b970e3622a80192a4df8c23378c4854520df8b2d17db773ac8b77c19750019e1c9813cc05e12b0e3b0d03599ff5d073681e847d43b4b273efca5aabbb28eb0e0 languageName: node linkType: hard @@ -10466,20 +10573,6 @@ __metadata: languageName: node linkType: hard -"node-fetch@npm:^2.6.12": - version: 2.7.0 - resolution: "node-fetch@npm:2.7.0" - dependencies: - whatwg-url: ^5.0.0 - peerDependencies: - encoding: ^0.1.0 - peerDependenciesMeta: - encoding: - optional: true - checksum: d76d2f5edb451a3f05b15115ec89fc6be39de37c6089f1b6368df03b91e1633fd379a7e01b7ab05089a25034b2023d959b47e59759cb38d88341b2459e89d6e5 - languageName: node - linkType: hard - "node-forge@npm:^1.1.0": version: 1.3.1 resolution: "node-forge@npm:1.3.1" @@ -10523,8 +10616,8 @@ __metadata: linkType: hard "node-gyp@npm:latest": - version: 10.0.1 - resolution: "node-gyp@npm:10.0.1" + version: 10.1.0 + resolution: "node-gyp@npm:10.1.0" dependencies: env-paths: ^2.2.0 exponential-backoff: ^3.1.1 @@ -10538,7 +10631,7 @@ __metadata: which: ^4.0.0 bin: node-gyp: bin/node-gyp.js - checksum: 60a74e66d364903ce02049966303a57f898521d139860ac82744a5fdd9f7b7b3b61f75f284f3bfe6e6add3b8f1871ce305a1d41f775c7482de837b50c792223f + checksum: 72e2ab4b23fc32007a763da94018f58069fc0694bf36115d49a2b195c8831e12cf5dd1e7a3718fa85c06969aedf8fc126722d3b672ec1cb27e06ed33caee3c60 languageName: node linkType: hard @@ -10614,11 +10707,11 @@ __metadata: linkType: hard "npm-run-path@npm:^5.1.0": - version: 5.2.0 - resolution: "npm-run-path@npm:5.2.0" + version: 5.3.0 + resolution: "npm-run-path@npm:5.3.0" dependencies: path-key: ^4.0.0 - checksum: c5325e016014e715689c4014f7e0be16cc4cbf529f32a1723e511bc4689b5f823b704d2bca61ac152ce2bda65e0205dc8b3ba0ec0f5e4c3e162d302f6f5b9efb + checksum: ae8e7a89da9594fb9c308f6555c73f618152340dcaae423e5fb3620026fefbec463618a8b761920382d666fa7a2d8d240b6fe320e8a6cdd54dc3687e2b659d25 languageName: node linkType: hard @@ -10629,7 +10722,7 @@ __metadata: languageName: node linkType: hard -"object-inspect@npm:^1.13.1, object-inspect@npm:^1.9.0": +"object-inspect@npm:^1.13.1": version: 1.13.1 resolution: "object-inspect@npm:1.13.1" checksum: 7d9fa9221de3311dcb5c7c307ee5dc011cdd31dc43624b7c184b3840514e118e05ef0002be5388304c416c0eb592feb46e983db12577fc47e47d5752fbbfb61f @@ -10643,7 +10736,7 @@ __metadata: languageName: node linkType: hard -"object.assign@npm:^4.1.4": +"object.assign@npm:^4.1.5": version: 4.1.5 resolution: "object.assign@npm:4.1.5" dependencies: @@ -10656,36 +10749,36 @@ __metadata: linkType: hard "object.fromentries@npm:^2.0.7": - version: 2.0.7 - resolution: "object.fromentries@npm:2.0.7" + version: 2.0.8 + resolution: "object.fromentries@npm:2.0.8" dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - checksum: 7341ce246e248b39a431b87a9ddd331ff52a454deb79afebc95609f94b1f8238966cf21f52188f2a353f0fdf83294f32f1ebf1f7826aae915ebad21fd0678065 + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-abstract: ^1.23.2 + es-object-atoms: ^1.0.0 + checksum: 29b2207a2db2782d7ced83f93b3ff5d425f901945f3665ffda1821e30a7253cd1fd6b891a64279976098137ddfa883d748787a6fea53ecdb51f8df8b8cec0ae1 languageName: node linkType: hard "object.groupby@npm:^1.0.1": - version: 1.0.1 - resolution: "object.groupby@npm:1.0.1" + version: 1.0.3 + resolution: "object.groupby@npm:1.0.3" dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - get-intrinsic: ^1.2.1 - checksum: d7959d6eaaba358b1608066fc67ac97f23ce6f573dc8fc661f68c52be165266fcb02937076aedb0e42722fdda0bdc0bbf74778196ac04868178888e9fd3b78b5 + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-abstract: ^1.23.2 + checksum: 0d30693ca3ace29720bffd20b3130451dca7a56c612e1926c0a1a15e4306061d84410bdb1456be2656c5aca53c81b7a3661eceaa362db1bba6669c2c9b6d1982 languageName: node linkType: hard "object.values@npm:^1.1.7": - version: 1.1.7 - resolution: "object.values@npm:1.1.7" + version: 1.2.0 + resolution: "object.values@npm:1.2.0" dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - checksum: f3e4ae4f21eb1cc7cebb6ce036d4c67b36e1c750428d7b7623c56a0db90edced63d08af8a316d81dfb7c41a3a5fa81b05b7cc9426e98d7da986b1682460f0777 + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-object-atoms: ^1.0.0 + checksum: 51fef456c2a544275cb1766897f34ded968b22adfc13ba13b5e4815fdaf4304a90d42a3aee114b1f1ede048a4890381d47a5594d84296f2767c6a0364b9da8fa languageName: node linkType: hard @@ -10786,19 +10879,19 @@ __metadata: languageName: node linkType: hard -"p-defer@npm:^4.0.0": - version: 4.0.0 - resolution: "p-defer@npm:4.0.0" - checksum: 646c9e86e62d2299ee9e8722b9857c9a2918afb8626c4eaf072d956de0d5b33c1cb132e5754516c923fc691eb33aa216755e168f848b045c1279186c8e2d852f +"p-defer@npm:^4.0.0, p-defer@npm:^4.0.1": + version: 4.0.1 + resolution: "p-defer@npm:4.0.1" + checksum: a561e7b581b76e6dce8ae763b4980004dbc795781de327d0b760e5341f035b0fa2c14e892a66d6d8122e2e114815a26f5ad154061374df84f88e75405ea4b0bb languageName: node linkType: hard "p-event@npm:^6.0.0": - version: 6.0.0 - resolution: "p-event@npm:6.0.0" + version: 6.0.1 + resolution: "p-event@npm:6.0.1" dependencies: p-timeout: ^6.1.2 - checksum: def3e49cd896fbf51264524959adf3f4542402541fda9c9681702308683df23bf0e75f7512db9509eeafe0bfef5d13b4eea0b6e13c6437766470caef01548654 + checksum: 0fcc0c656d76b164a575131b3f5abe1baec08488e37f5e39494106ce5bf1309d7b4b8ebde82d8c3f3261c55122530d95da5da4a00476bf26a9ea4e24a32a27be languageName: node linkType: hard @@ -10867,17 +10960,6 @@ __metadata: languageName: node linkType: hard -"p-retry@npm:^6.0.0": - version: 6.2.0 - resolution: "p-retry@npm:6.2.0" - dependencies: - "@types/retry": 0.12.2 - is-network-error: ^1.0.0 - retry: ^0.13.1 - checksum: 6003573c559ee812329c9c3ede7ba12a783fdc8dd70602116646e850c920b4597dc502fe001c3f9526fca4e93275045db7a27341c458e51db179c1374a01ac44 - languageName: node - linkType: hard - "p-timeout@npm:^5.0.2": version: 5.1.0 resolution: "p-timeout@npm:5.1.0" @@ -10885,7 +10967,7 @@ __metadata: languageName: node linkType: hard -"p-timeout@npm:^6.0.0, p-timeout@npm:^6.1.1, p-timeout@npm:^6.1.2": +"p-timeout@npm:^6.0.0, p-timeout@npm:^6.1.2": version: 6.1.2 resolution: "p-timeout@npm:6.1.2" checksum: 887b805eb72c217dbc3c55a60a7f3b89a46cab14f04af62224f253ec84716cbd0880758be13b35444a4fa12d64d37d4c8a300f0b12a57c004d289f0a574cfe91 @@ -10916,13 +10998,12 @@ __metadata: linkType: hard "pac-resolver@npm:^7.0.0": - version: 7.0.0 - resolution: "pac-resolver@npm:7.0.0" + version: 7.0.1 + resolution: "pac-resolver@npm:7.0.1" dependencies: degenerator: ^5.0.0 - ip: ^1.1.8 netmask: ^2.0.2 - checksum: fa3a898c09848e93e35f5e23443fea36ddb393a851c76a23664a5bf3fcbe58ff77a0bcdae1e4f01b9ea87ea493c52e14d97a0fe39f92474d14cd45559c6e3cde + checksum: 839134328781b80d49f9684eae1f5c74f50a1d4482076d44c84fc2f3ca93da66fa11245a4725a057231e06b311c20c989fd0681e662a0792d17f644d8fe62a5e languageName: node linkType: hard @@ -10942,16 +11023,17 @@ __metadata: languageName: node linkType: hard -"parse-asn1@npm:^5.0.0, parse-asn1@npm:^5.1.6": - version: 5.1.6 - resolution: "parse-asn1@npm:5.1.6" +"parse-asn1@npm:^5.0.0, parse-asn1@npm:^5.1.7": + version: 5.1.7 + resolution: "parse-asn1@npm:5.1.7" dependencies: - asn1.js: ^5.2.0 - browserify-aes: ^1.0.0 - evp_bytestokey: ^1.0.0 - pbkdf2: ^3.0.3 - safe-buffer: ^5.1.1 - checksum: 9243311d1f88089bc9f2158972aa38d1abd5452f7b7cabf84954ed766048fe574d434d82c6f5a39b988683e96fb84cd933071dda38927e03469dc8c8d14463c7 + asn1.js: ^4.10.1 + browserify-aes: ^1.2.0 + evp_bytestokey: ^1.0.3 + hash-base: ~3.0 + pbkdf2: ^3.1.2 + safe-buffer: ^5.2.1 + checksum: 93c7194c1ed63a13e0b212d854b5213ad1aca0ace41c66b311e97cca0519cf9240f79435a0306a3b412c257f0ea3f1953fd0d9549419a0952c9e995ab361fd6c languageName: node linkType: hard @@ -11016,20 +11098,20 @@ __metadata: languageName: node linkType: hard -"path-scurry@npm:^1.10.1": - version: 1.10.1 - resolution: "path-scurry@npm:1.10.1" +"path-scurry@npm:^1.10.2": + version: 1.10.2 + resolution: "path-scurry@npm:1.10.2" dependencies: - lru-cache: ^9.1.1 || ^10.0.0 + lru-cache: ^10.2.0 minipass: ^5.0.0 || ^6.0.2 || ^7.0.0 - checksum: e2557cff3a8fb8bc07afdd6ab163a92587884f9969b05bbbaf6fe7379348bfb09af9ed292af12ed32398b15fb443e81692047b786d1eeb6d898a51eb17ed7d90 + checksum: 6739b4290f7d1a949c61c758b481c07ac7d1a841964c68cf5e1fa153d7e18cbde4872b37aadf9c5173c800d627f219c47945859159de36c977dd82419997b9b8 languageName: node linkType: hard "path-to-regexp@npm:^6.2.1": - version: 6.2.1 - resolution: "path-to-regexp@npm:6.2.1" - checksum: f0227af8284ea13300f4293ba111e3635142f976d4197f14d5ad1f124aebd9118783dd2e5f1fe16f7273743cc3dbeddfb7493f237bb27c10fdae07020cc9b698 + version: 6.2.2 + resolution: "path-to-regexp@npm:6.2.2" + checksum: b7b0005c36f5099f9ed1fb20a820d2e4ed1297ffe683ea1d678f5e976eb9544f01debb281369dabdc26da82e6453901bf71acf2c7ed14b9243536c2a45286c33 languageName: node linkType: hard @@ -11049,7 +11131,7 @@ __metadata: languageName: node linkType: hard -"pbkdf2@npm:^3.0.3": +"pbkdf2@npm:^3.0.3, pbkdf2@npm:^3.1.2": version: 3.1.2 resolution: "pbkdf2@npm:3.1.2" dependencies: @@ -11099,13 +11181,6 @@ __metadata: languageName: node linkType: hard -"platform@npm:^1.3.3": - version: 1.3.6 - resolution: "platform@npm:1.3.6" - checksum: 6f472a09c61d418c7e26c1c16d0bdc029549d512dbec6526216a1e59ec68100d07007d0097dcba69dddad883d6f2a83361b4bdfe0094a3d9a2af24158643d85e - languageName: node - linkType: hard - "pluralize@npm:^8.0.0": version: 8.0.0 resolution: "pluralize@npm:8.0.0" @@ -11113,6 +11188,13 @@ __metadata: languageName: node linkType: hard +"possible-typed-array-names@npm:^1.0.0": + version: 1.0.0 + resolution: "possible-typed-array-names@npm:1.0.0" + checksum: b32d403ece71e042385cc7856385cecf1cd8e144fa74d2f1de40d1e16035dba097bc189715925e79b67bdd1472796ff168d3a90d296356c9c94d272d5b95f3ae + languageName: node + linkType: hard + "postcss-values-parser@npm:^2.0.1": version: 2.0.1 resolution: "postcss-values-parser@npm:2.0.1" @@ -11138,13 +11220,13 @@ __metadata: linkType: hard "postcss@npm:^8.1.7, postcss@npm:^8.4.23, postcss@npm:^8.4.27": - version: 8.4.33 - resolution: "postcss@npm:8.4.33" + version: 8.4.38 + resolution: "postcss@npm:8.4.38" dependencies: nanoid: ^3.3.7 picocolors: ^1.0.0 - source-map-js: ^1.0.2 - checksum: 6f98b2af4b76632a3de20c4f47bf0e984a1ce1a531cf11adcb0b1d63a6cbda0aae4165e578b66c32ca4879038e3eaad386a6be725a8fb4429c78e3c1ab858fe9 + source-map-js: ^1.2.0 + checksum: 649f9e60a763ca4b5a7bbec446a069edf07f057f6d780a5a0070576b841538d1ecf7dd888f2fbfd1f76200e26c969e405aeeae66332e6927dbdc8bdcb90b9451 languageName: node linkType: hard @@ -11248,6 +11330,13 @@ __metadata: languageName: node linkType: hard +"process-nextick-args@npm:~2.0.0": + version: 2.0.1 + resolution: "process-nextick-args@npm:2.0.1" + checksum: 1d38588e520dab7cea67cbbe2efdd86a10cc7a074c09657635e34f035277b59fbb57d09d8638346bf7090f8e8ebc070c96fa5fd183b777fff4f5edff5e9466cf + languageName: node + linkType: hard + "process@npm:^0.11.10": version: 0.11.10 resolution: "process@npm:0.11.10" @@ -11289,13 +11378,14 @@ __metadata: languageName: node linkType: hard -"protons-runtime@npm:^5.0.0": - version: 5.2.2 - resolution: "protons-runtime@npm:5.2.2" +"protons-runtime@npm:^5.0.0, protons-runtime@npm:^5.4.0": + version: 5.4.0 + resolution: "protons-runtime@npm:5.4.0" dependencies: + uint8-varint: ^2.0.2 uint8arraylist: ^2.4.3 uint8arrays: ^5.0.1 - checksum: b2c0c3612406eb49539e3f2be7e51bbb3333969b6c1052c8e2cf5cb3eb3aed86eb825eeecd3b5c579e02a545b658b90f046b7e06cc624a843130782bc8e22f6b + checksum: d0eb62eb3a319319d1bdd678ebbf4272ab6b10662df0f97c13480959721e8b81ee302d07489c0a2e1dcdad574dd51068c3d96297d7631a7f60925d164f4211d9 languageName: node linkType: hard @@ -11364,46 +11454,62 @@ __metadata: languageName: node linkType: hard -"puppeteer-core@npm:22.2.0": - version: 22.2.0 - resolution: "puppeteer-core@npm:22.2.0" +"puppeteer-core@npm:22.6.5": + version: 22.6.5 + resolution: "puppeteer-core@npm:22.6.5" dependencies: - "@puppeteer/browsers": 2.1.0 - chromium-bidi: 0.5.9 - cross-fetch: 4.0.0 + "@puppeteer/browsers": 2.2.2 + chromium-bidi: 0.5.17 debug: 4.3.4 - devtools-protocol: 0.0.1249869 + devtools-protocol: 0.0.1262051 ws: 8.16.0 - checksum: 270d765169224d1ef8864cb0e8519e1c99cc979ba56c05c2b207fdf5862322c6c3e817885e12af6996d3ce21e9a2d62ff73ab531872febd1d2b3fccc0f86fab1 + checksum: 4dc58083179eae79397d2c55c8cf12b27228278c5ab2d4928dd44a954af17f0f55be0b91e0e442fd282fa96574a2403e6397b3ae10bedf6ff2b38bffed164ff2 languageName: node linkType: hard "puppeteer@npm:^22.2": - version: 22.2.0 - resolution: "puppeteer@npm:22.2.0" + version: 22.6.5 + resolution: "puppeteer@npm:22.6.5" dependencies: - "@puppeteer/browsers": 2.1.0 + "@puppeteer/browsers": 2.2.2 cosmiconfig: 9.0.0 - puppeteer-core: 22.2.0 + devtools-protocol: 0.0.1262051 + puppeteer-core: 22.6.5 bin: puppeteer: lib/esm/puppeteer/node/cli.js - checksum: a5d604367f9b6432b5d6318b60d1b789b4af53e658bd423c1f5e3e35d85dc10bde6536450b1a04cb2f0af2c5485c38a99466eed8917d31ea840ce23c9fdec5c0 + checksum: d6361ae4e5dd7c55e244b98aca345745b147c434b3636896e1f01103de2994c48274a0ed2febf8ba917692f086d44e4d9a820007acc814e5dba7e8d18ad1aedd languageName: node linkType: hard "pure-rand@npm:^6.0.0": - version: 6.0.4 - resolution: "pure-rand@npm:6.0.4" - checksum: e1c4e69f8bf7303e5252756d67c3c7551385cd34d94a1f511fe099727ccbab74c898c03a06d4c4a24a89b51858781057b83ebbfe740d984240cdc04fead36068 + version: 6.1.0 + resolution: "pure-rand@npm:6.1.0" + checksum: 8d53bc02bed99eca0b65b505090152ee7e9bd67dd74f8ff32ba1c883b87234067c5bf68d2614759fb217d82594d7a92919e6df80f97885e7b12b42af4bd3316a + languageName: node + linkType: hard + +"pvtsutils@npm:^1.3.2": + version: 1.3.5 + resolution: "pvtsutils@npm:1.3.5" + dependencies: + tslib: ^2.6.1 + checksum: e734516b3cb26086c18bd9c012fefe818928a5073178842ab7e62885a090f1dd7bda9c7bb8cd317167502cb8ec86c0b1b0ccd71dac7ab469382a4518157b0d12 + languageName: node + linkType: hard + +"pvutils@npm:^1.1.3": + version: 1.1.3 + resolution: "pvutils@npm:1.1.3" + checksum: 2ee26a9e5176c348977d6ec00d8ee80bff62f51743b1c5fe8abeeb4c5d29d9959cdfe0ce146707a9e6801bce88190fed3002d720b072dc87d031c692820b44c9 languageName: node linkType: hard "qs@npm:^6.11.0, qs@npm:^6.5.2": - version: 6.11.2 - resolution: "qs@npm:6.11.2" + version: 6.12.1 + resolution: "qs@npm:6.12.1" dependencies: - side-channel: ^1.0.4 - checksum: e812f3c590b2262548647d62f1637b6989cc56656dc960b893fe2098d96e1bd633f36576f4cd7564dfbff9db42e17775884db96d846bebe4f37420d073ecdc0b + side-channel: ^1.0.6 + checksum: aa761d99e65b6936ba2dd2187f2d9976afbcda38deb3ff1b3fe331d09b0c578ed79ca2abdde1271164b5be619c521ec7db9b34c23f49a074e5921372d16242d5 languageName: node linkType: hard @@ -11435,7 +11541,14 @@ __metadata: languageName: node linkType: hard -"race-signal@npm:^1.0.0, race-signal@npm:^1.0.1": +"race-event@npm:^1.2.0": + version: 1.2.0 + resolution: "race-event@npm:1.2.0" + checksum: b3468019959adb74859e4f153f7952a3c031d5435de1a031467cf85e9d5d9d1be3c8b7a58a7e07116e06bf5d82c55bae4be1d0029f582802aaee0b18f1e19cbb + languageName: node + linkType: hard + +"race-signal@npm:^1.0.0, race-signal@npm:^1.0.1, race-signal@npm:^1.0.2": version: 1.0.2 resolution: "race-signal@npm:1.0.2" checksum: 01ea1f70059673cd239acbe9523eaf1649f3b02ec786b5266770d9b045018aa96e316150447f0a12e7b0f8aa02522deb23e7d3a2c3a58d37135c505f595f2e49 @@ -11461,13 +11574,6 @@ __metadata: languageName: node linkType: hard -"rate-limiter-flexible@npm:^3.0.0": - version: 3.0.6 - resolution: "rate-limiter-flexible@npm:3.0.6" - checksum: 65cf8edacde55b78255d5de0286b1297ec897fee128f4f18734f36a230297d75433fa599ea423f7726b61b8f8ebf108d66ee09e7155e37aa25f506015b5166a4 - languageName: node - linkType: hard - "raw-body@npm:^2.3.3": version: 2.5.2 resolution: "raw-body@npm:2.5.2" @@ -11524,7 +11630,22 @@ __metadata: languageName: node linkType: hard -"readable-stream@npm:^3.4.0, readable-stream@npm:^3.5.0, readable-stream@npm:^3.6.0, readable-stream@npm:^3.6.2": +"readable-stream@npm:^2.3.8": + version: 2.3.8 + resolution: "readable-stream@npm:2.3.8" + dependencies: + core-util-is: ~1.0.0 + inherits: ~2.0.3 + isarray: ~1.0.0 + process-nextick-args: ~2.0.0 + safe-buffer: ~5.1.1 + string_decoder: ~1.1.1 + util-deprecate: ~1.0.1 + checksum: 65645467038704f0c8aaf026a72fbb588a9e2ef7a75cd57a01702ee9db1c4a1e4b03aaad36861a6a0926546a74d174149c8c207527963e0c2d3eee2f37678a42 + languageName: node + linkType: hard + +"readable-stream@npm:^3.4.0, readable-stream@npm:^3.5.0, readable-stream@npm:^3.6.0": version: 3.6.2 resolution: "readable-stream@npm:3.6.2" dependencies: @@ -11535,15 +11656,6 @@ __metadata: languageName: node linkType: hard -"receptacle@npm:^1.3.2": - version: 1.3.2 - resolution: "receptacle@npm:1.3.2" - dependencies: - ms: ^2.1.1 - checksum: 7c5011f19e6ddcb759c1e6756877cee3c9eb78fbd1278eca4572d75f74993f0ccdc1e5f7761de6e682dff5344ee94f7a69bc492e2e8eb81d8777774a2399ce9c - languageName: node - linkType: hard - "rechoir@npm:^0.8.0": version: 0.8.0 resolution: "rechoir@npm:0.8.0" @@ -11570,14 +11682,15 @@ __metadata: languageName: node linkType: hard -"regexp.prototype.flags@npm:^1.5.1": - version: 1.5.1 - resolution: "regexp.prototype.flags@npm:1.5.1" +"regexp.prototype.flags@npm:^1.5.2": + version: 1.5.2 + resolution: "regexp.prototype.flags@npm:1.5.2" dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - set-function-name: ^2.0.0 - checksum: 869edff00288442f8d7fa4c9327f91d85f3b3acf8cbbef9ea7a220345cf23e9241b6def9263d2c1ebcf3a316b0aa52ad26a43a84aa02baca3381717b3e307f47 + call-bind: ^1.0.6 + define-properties: ^1.2.1 + es-errors: ^1.3.0 + set-function-name: ^2.0.1 + checksum: d7f333667d5c564e2d7a97c56c3075d64c722c9bb51b2b4df6822b2e8096d623a5e63088fb4c83df919b6951ef8113841de8b47de7224872fa6838bc5d8a7d64 languageName: node linkType: hard @@ -11750,13 +11863,6 @@ __metadata: languageName: node linkType: hard -"retry@npm:^0.13.1": - version: 0.13.1 - resolution: "retry@npm:0.13.1" - checksum: 47c4d5be674f7c13eee4cfe927345023972197dbbdfba5d3af7e461d13b44de1bfd663bfc80d2f601f8ef3fc8164c16dd99655a221921954a65d044a2fc1233b - languageName: node - linkType: hard - "reusify@npm:^1.0.4": version: 1.0.4 resolution: "reusify@npm:1.0.4" @@ -11785,6 +11891,17 @@ __metadata: languageName: node linkType: hard +"rlp@npm:^2.2.6": + version: 2.2.7 + resolution: "rlp@npm:2.2.7" + dependencies: + bn.js: ^5.2.0 + bin: + rlp: bin/rlp + checksum: 3db4dfe5c793f40ac7e0be689a1f75d05e6f2ca0c66189aeb62adab8c436b857ab4420a419251ee60370d41d957a55698fc5e23ab1e1b41715f33217bc4bb558 + languageName: node + linkType: hard + "rollup@npm:^3.27.1": version: 3.29.4 resolution: "rollup@npm:3.29.4" @@ -11817,15 +11934,15 @@ __metadata: languageName: node linkType: hard -"safe-array-concat@npm:^1.0.1": - version: 1.1.0 - resolution: "safe-array-concat@npm:1.1.0" +"safe-array-concat@npm:^1.1.2": + version: 1.1.2 + resolution: "safe-array-concat@npm:1.1.2" dependencies: - call-bind: ^1.0.5 - get-intrinsic: ^1.2.2 + call-bind: ^1.0.7 + get-intrinsic: ^1.2.4 has-symbols: ^1.0.3 isarray: ^2.0.5 - checksum: 5c71eaa999168ee7474929f1cd3aae80f486353a651a094d9968936692cf90aa065224929a6486dcda66334a27dce4250a83612f9e0fef6dced1a925d3ac7296 + checksum: a3b259694754ddfb73ae0663829e396977b99ff21cbe8607f35a469655656da8e271753497e59da8a7575baa94d2e684bea3e10ddd74ba046c0c9b4418ffa0c4 languageName: node linkType: hard @@ -11836,14 +11953,21 @@ __metadata: languageName: node linkType: hard -"safe-regex-test@npm:^1.0.0": - version: 1.0.2 - resolution: "safe-regex-test@npm:1.0.2" +"safe-buffer@npm:~5.1.0, safe-buffer@npm:~5.1.1": + version: 5.1.2 + resolution: "safe-buffer@npm:5.1.2" + checksum: f2f1f7943ca44a594893a852894055cf619c1fbcb611237fc39e461ae751187e7baf4dc391a72125e0ac4fb2d8c5c0b3c71529622e6a58f46b960211e704903c + languageName: node + linkType: hard + +"safe-regex-test@npm:^1.0.3": + version: 1.0.3 + resolution: "safe-regex-test@npm:1.0.3" dependencies: - call-bind: ^1.0.5 - get-intrinsic: ^1.2.2 + call-bind: ^1.0.6 + es-errors: ^1.3.0 is-regex: ^1.1.4 - checksum: 4af5ce05a2daa4f6d4bfd5a3c64fc33d6b886f6592122e93c0efad52f7147b9b605e5ffc03c269a1e3d1f8db2a23bc636628a961c9fd65bafdc09503330673fd + checksum: 6c7d392ff1ae7a3ae85273450ed02d1d131f1d2c76e177d6b03eb88e6df8fa062639070e7d311802c1615f351f18dc58f9454501c58e28d5ffd9b8f502ba6489 languageName: node linkType: hard @@ -11854,22 +11978,13 @@ __metadata: languageName: node linkType: hard -"safer-buffer@npm:>= 2.1.2 < 3, safer-buffer@npm:>= 2.1.2 < 3.0.0, safer-buffer@npm:^2.1.0": +"safer-buffer@npm:>= 2.1.2 < 3, safer-buffer@npm:>= 2.1.2 < 3.0.0": version: 2.1.2 resolution: "safer-buffer@npm:2.1.2" checksum: cab8f25ae6f1434abee8d80023d7e72b598cf1327164ddab31003c51215526801e40b66c5e65d658a0af1e9d6478cadcb4c745f4bd6751f97d8644786c0978b0 languageName: node linkType: hard -"sanitize-filename@npm:^1.6.3": - version: 1.6.3 - resolution: "sanitize-filename@npm:1.6.3" - dependencies: - truncate-utf8-bytes: ^1.0.0 - checksum: aa733c012b7823cf65730603cf3b503c641cee6b239771d3164ca482f22d81a50e434a713938d994071db18e4202625669cc56bccc9d13d818b4c983b5f47fde - languageName: node - linkType: hard - "sass-lookup@npm:^3.0.0": version: 3.0.0 resolution: "sass-lookup@npm:3.0.0" @@ -11881,13 +11996,6 @@ __metadata: languageName: node linkType: hard -"sax@npm:>=0.6.0": - version: 1.3.0 - resolution: "sax@npm:1.3.0" - checksum: 238ab3a9ba8c8f8aaf1c5ea9120386391f6ee0af52f1a6a40bbb6df78241dd05d782f2359d614ac6aae08c4c4125208b456548a6cf68625aa4fe178486e63ecd - languageName: node - linkType: hard - "schema-utils@npm:^3.1.1, schema-utils@npm:^3.2.0": version: 3.3.0 resolution: "schema-utils@npm:3.3.0" @@ -11917,7 +12025,7 @@ __metadata: languageName: node linkType: hard -"semver@npm:7.6.0": +"semver@npm:7.6.0, semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.3.8, semver@npm:^7.5.3, semver@npm:^7.5.4": version: 7.6.0 resolution: "semver@npm:7.6.0" dependencies: @@ -11937,17 +12045,6 @@ __metadata: languageName: node linkType: hard -"semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.3.8, semver@npm:^7.5.3, semver@npm:^7.5.4": - version: 7.5.4 - resolution: "semver@npm:7.5.4" - dependencies: - lru-cache: ^6.0.0 - bin: - semver: bin/semver.js - checksum: 12d8ad952fa353b0995bf180cdac205a4068b759a140e5d3c608317098b3575ac2f1e09182206bf2eb26120e1c0ed8fb92c48c592f6099680de56bb071423ca3 - languageName: node - linkType: hard - "serialize-javascript@npm:^6.0.1": version: 6.0.2 resolution: "serialize-javascript@npm:6.0.2" @@ -11957,27 +12054,29 @@ __metadata: languageName: node linkType: hard -"set-function-length@npm:^1.1.1": - version: 1.2.0 - resolution: "set-function-length@npm:1.2.0" +"set-function-length@npm:^1.2.1": + version: 1.2.2 + resolution: "set-function-length@npm:1.2.2" dependencies: - define-data-property: ^1.1.1 + define-data-property: ^1.1.4 + es-errors: ^1.3.0 function-bind: ^1.1.2 - get-intrinsic: ^1.2.2 + get-intrinsic: ^1.2.4 gopd: ^1.0.1 - has-property-descriptors: ^1.0.1 - checksum: 63e34b45a2ff9abb419f52583481bf8ba597d33c0c85e56999085eb6078a0f7fbb4222051981c287feceeb358aa7789e7803cea2c82ac94c0ab37059596aff79 + has-property-descriptors: ^1.0.2 + checksum: a8248bdacdf84cb0fab4637774d9fb3c7a8e6089866d04c817583ff48e14149c87044ce683d7f50759a8c50fb87c7a7e173535b06169c87ef76f5fb276dfff72 languageName: node linkType: hard -"set-function-name@npm:^2.0.0": - version: 2.0.1 - resolution: "set-function-name@npm:2.0.1" +"set-function-name@npm:^2.0.1": + version: 2.0.2 + resolution: "set-function-name@npm:2.0.2" dependencies: - define-data-property: ^1.0.1 + define-data-property: ^1.1.4 + es-errors: ^1.3.0 functions-have-names: ^1.2.3 - has-property-descriptors: ^1.0.0 - checksum: 4975d17d90c40168eee2c7c9c59d023429f0a1690a89d75656306481ece0c3c1fb1ebcc0150ea546d1913e35fbd037bace91372c69e543e51fc5d1f31a9fa126 + has-property-descriptors: ^1.0.2 + checksum: d6229a71527fd0404399fc6227e0ff0652800362510822a291925c9d7b48a1ca1a468b11b281471c34cd5a2da0db4f5d7ff315a61d26655e77f6e971e6d0c80f languageName: node linkType: hard @@ -12070,14 +12169,15 @@ __metadata: languageName: node linkType: hard -"side-channel@npm:^1.0.4": - version: 1.0.4 - resolution: "side-channel@npm:1.0.4" +"side-channel@npm:^1.0.4, side-channel@npm:^1.0.6": + version: 1.0.6 + resolution: "side-channel@npm:1.0.6" dependencies: - call-bind: ^1.0.0 - get-intrinsic: ^1.0.2 - object-inspect: ^1.9.0 - checksum: 351e41b947079c10bd0858364f32bb3a7379514c399edb64ab3dce683933483fc63fb5e4efe0a15a2e8a7e3c436b6a91736ddb8d8c6591b0460a24bb4a1ee245 + call-bind: ^1.0.7 + es-errors: ^1.3.0 + get-intrinsic: ^1.2.4 + object-inspect: ^1.13.1 + checksum: bfc1afc1827d712271453e91b7cd3878ac0efd767495fd4e594c4c2afaa7963b7b510e249572bfd54b0527e66e4a12b61b80c061389e129755f34c493aad9b97 languageName: node linkType: hard @@ -12125,31 +12225,31 @@ __metadata: languageName: node linkType: hard -"socks-proxy-agent@npm:^8.0.1, socks-proxy-agent@npm:^8.0.2": - version: 8.0.2 - resolution: "socks-proxy-agent@npm:8.0.2" +"socks-proxy-agent@npm:^8.0.2, socks-proxy-agent@npm:^8.0.3": + version: 8.0.3 + resolution: "socks-proxy-agent@npm:8.0.3" dependencies: - agent-base: ^7.0.2 + agent-base: ^7.1.1 debug: ^4.3.4 socks: ^2.7.1 - checksum: 4fb165df08f1f380881dcd887b3cdfdc1aba3797c76c1e9f51d29048be6e494c5b06d68e7aea2e23df4572428f27a3ec22b3d7c75c570c5346507433899a4b6d + checksum: 8fab38821c327c190c28f1658087bc520eb065d55bc07b4a0fdf8d1e0e7ad5d115abbb22a95f94f944723ea969dd771ad6416b1e3cde9060c4c71f705c8b85c5 languageName: node linkType: hard "socks@npm:^2.7.1": - version: 2.7.1 - resolution: "socks@npm:2.7.1" + version: 2.8.3 + resolution: "socks@npm:2.8.3" dependencies: - ip: ^2.0.0 + ip-address: ^9.0.5 smart-buffer: ^4.2.0 - checksum: 259d9e3e8e1c9809a7f5c32238c3d4d2a36b39b83851d0f573bfde5f21c4b1288417ce1af06af1452569cd1eb0841169afd4998f0e04ba04656f6b7f0e46d748 + checksum: 7a6b7f6eedf7482b9e4597d9a20e09505824208006ea8f2c49b71657427f3c137ca2ae662089baa73e1971c62322d535d9d0cf1c9235cf6f55e315c18203eadd languageName: node linkType: hard -"source-map-js@npm:^1.0.2": - version: 1.0.2 - resolution: "source-map-js@npm:1.0.2" - checksum: c049a7fc4deb9a7e9b481ae3d424cc793cb4845daa690bc5a05d428bf41bf231ced49b4cf0c9e77f9d42fdb3d20d6187619fc586605f5eabe995a316da8d377c +"source-map-js@npm:^1.2.0": + version: 1.2.0 + resolution: "source-map-js@npm:1.2.0" + checksum: 791a43306d9223792e84293b00458bf102a8946e7188f3db0e4e22d8d530b5f80a4ce468eb5ec0bf585443ad55ebbd630bf379c98db0b1f317fd902500217f97 languageName: node linkType: hard @@ -12212,9 +12312,9 @@ __metadata: linkType: hard "spdx-exceptions@npm:^2.1.0": - version: 2.4.0 - resolution: "spdx-exceptions@npm:2.4.0" - checksum: b1b650a8d94424473bf9629cf972c86a91c03cccc260f5c901bce0e4b92d831627fec28c9e0a1e9c34c5ebad0a12cf2eab887bec088e0a862abb9d720c2fd0a1 + version: 2.5.0 + resolution: "spdx-exceptions@npm:2.5.0" + checksum: bb127d6e2532de65b912f7c99fc66097cdea7d64c10d3ec9b5e96524dbbd7d20e01cba818a6ddb2ae75e62bb0c63d5e277a7e555a85cbc8ab40044984fa4ae15 languageName: node linkType: hard @@ -12229,9 +12329,9 @@ __metadata: linkType: hard "spdx-license-ids@npm:^3.0.0": - version: 3.0.16 - resolution: "spdx-license-ids@npm:3.0.16" - checksum: 5cdaa85aaa24bd02f9353a2e357b4df0a4f205cb35655f3fd0a5674a4fb77081f28ffd425379214bc3be2c2b7593ce1215df6bcc75884aeee0a9811207feabe2 + version: 3.0.17 + resolution: "spdx-license-ids@npm:3.0.17" + checksum: 0aba5d16292ff604dd20982200e23b4d425f6ba364765039bdbde2f6c956b9909fce1ad040a897916a5f87388e85e001f90cb64bf706b6e319f3908cfc445a59 languageName: node linkType: hard @@ -12244,6 +12344,13 @@ __metadata: languageName: node linkType: hard +"sprintf-js@npm:^1.1.3": + version: 1.1.3 + resolution: "sprintf-js@npm:1.1.3" + checksum: a3fdac7b49643875b70864a9d9b469d87a40dfeaf5d34d9d0c5b1cda5fd7d065531fcb43c76357d62254c57184a7b151954156563a4d6a747015cfb41021cad0 + languageName: node + linkType: hard + "sprintf-js@npm:~1.0.2": version: 1.0.3 resolution: "sprintf-js@npm:1.0.3" @@ -12318,16 +12425,16 @@ __metadata: languageName: node linkType: hard -"stream-to-it@npm:^0.2.2": - version: 0.2.4 - resolution: "stream-to-it@npm:0.2.4" +"stream-to-it@npm:^1.0.0": + version: 1.0.1 + resolution: "stream-to-it@npm:1.0.1" dependencies: - get-iterator: ^1.0.2 - checksum: 0725dd8ddb889829cab70b81a883d5a09cd34272ccd44fad195de9fb900a8588fbf801490b6418ae5e234c128743ad829c50cfcd6686fab3b50bb6e76d59238c + it-stream-types: ^2.0.1 + checksum: ef62b9a850b374d2bf426e96f2782fabe0ad9d513cb65f37bdd386b5669704c8d58aa7194c88d890c8fa4d000eebf3be331fcf79da9f40288cc5d5ea6d7fe47f languageName: node linkType: hard -"streamx@npm:^2.13.0": +"streamx@npm:^2.13.0, streamx@npm:^2.15.0": version: 2.16.1 resolution: "streamx@npm:2.16.1" dependencies: @@ -12341,13 +12448,10 @@ __metadata: languageName: node linkType: hard -"streamx@npm:^2.15.0": - version: 2.15.6 - resolution: "streamx@npm:2.15.6" - dependencies: - fast-fifo: ^1.1.0 - queue-tick: ^1.0.1 - checksum: 37a245f5cee4c33fcb8b018ccb935bad6eab423f05b0d14d018e63dbd2670bb109a69442e961a195b750c2c774f613c19476d11bd727d645eedb655d2dba234b +"strict-event-emitter-types@npm:^2.0.0": + version: 2.0.0 + resolution: "strict-event-emitter-types@npm:2.0.0" + checksum: 91ef62364cad9ece9ab9984e806b1c6d947d0617437a25605fff0cbfae59ac6a8d641257a168c1d5f2909809a467c714f027fdccb70b6155d68eac0dc1535299 languageName: node linkType: hard @@ -12390,36 +12494,37 @@ __metadata: languageName: node linkType: hard -"string.prototype.trim@npm:^1.2.8": - version: 1.2.8 - resolution: "string.prototype.trim@npm:1.2.8" +"string.prototype.trim@npm:^1.2.9": + version: 1.2.9 + resolution: "string.prototype.trim@npm:1.2.9" dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - checksum: 49eb1a862a53aba73c3fb6c2a53f5463173cb1f4512374b623bcd6b43ad49dd559a06fb5789bdec771a40fc4d2a564411c0a75d35fb27e76bbe738c211ecff07 + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-abstract: ^1.23.0 + es-object-atoms: ^1.0.0 + checksum: ea2df6ec1e914c9d4e2dc856fa08228e8b1be59b59e50b17578c94a66a176888f417264bb763d4aac638ad3b3dad56e7a03d9317086a178078d131aa293ba193 languageName: node linkType: hard -"string.prototype.trimend@npm:^1.0.7": - version: 1.0.7 - resolution: "string.prototype.trimend@npm:1.0.7" +"string.prototype.trimend@npm:^1.0.8": + version: 1.0.8 + resolution: "string.prototype.trimend@npm:1.0.8" dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - checksum: 2375516272fd1ba75992f4c4aa88a7b5f3c7a9ca308d963bcd5645adf689eba6f8a04ebab80c33e30ec0aefc6554181a3a8416015c38da0aa118e60ec896310c + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-object-atoms: ^1.0.0 + checksum: cc3bd2de08d8968a28787deba9a3cb3f17ca5f9f770c91e7e8fa3e7d47f079bad70fadce16f05dda9f261788be2c6e84a942f618c3bed31e42abc5c1084f8dfd languageName: node linkType: hard -"string.prototype.trimstart@npm:^1.0.7": - version: 1.0.7 - resolution: "string.prototype.trimstart@npm:1.0.7" +"string.prototype.trimstart@npm:^1.0.8": + version: 1.0.8 + resolution: "string.prototype.trimstart@npm:1.0.8" dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - checksum: 13d0c2cb0d5ff9e926fa0bec559158b062eed2b68cd5be777ffba782c96b2b492944e47057274e064549b94dd27cf81f48b27a31fee8af5b574cff253e7eb613 + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-object-atoms: ^1.0.0 + checksum: df1007a7f580a49d692375d996521dc14fd103acda7f3034b3c558a60b82beeed3a64fa91e494e164581793a8ab0ae2f59578a49896a7af6583c1f20472bce96 languageName: node linkType: hard @@ -12432,6 +12537,15 @@ __metadata: languageName: node linkType: hard +"string_decoder@npm:~1.1.1": + version: 1.1.1 + resolution: "string_decoder@npm:1.1.1" + dependencies: + safe-buffer: ~5.1.0 + checksum: 9ab7e56f9d60a28f2be697419917c50cac19f3e8e6c28ef26ed5f4852289fe0de5d6997d29becf59028556f2c62983790c1d9ba1e2a3cc401768ca12d5183a5b + languageName: node + linkType: hard + "stringify-object@npm:^3.2.1": version: 3.3.0 resolution: "stringify-object@npm:3.3.0" @@ -12622,8 +12736,8 @@ __metadata: linkType: hard "tar@npm:^6.1.11, tar@npm:^6.1.2": - version: 6.2.0 - resolution: "tar@npm:6.2.0" + version: 6.2.1 + resolution: "tar@npm:6.2.1" dependencies: chownr: ^2.0.0 fs-minipass: ^2.0.0 @@ -12631,7 +12745,7 @@ __metadata: minizlib: ^2.1.1 mkdirp: ^1.0.3 yallist: ^4.0.0 - checksum: db4d9fe74a2082c3a5016630092c54c8375ff3b280186938cfd104f2e089c4fd9bad58688ef6be9cf186a889671bf355c7cda38f09bbf60604b281715ca57f5c + checksum: f1322768c9741a25356c11373bce918483f40fa9a25c69c59410c8a1247632487edef5fe76c5f12ac51a6356d2f1829e96d2bc34098668a2fc34d76050ac2b6c languageName: node linkType: hard @@ -12658,8 +12772,8 @@ __metadata: linkType: hard "terser@npm:^5.26.0": - version: 5.27.0 - resolution: "terser@npm:5.27.0" + version: 5.30.3 + resolution: "terser@npm:5.30.3" dependencies: "@jridgewell/source-map": ^0.3.3 acorn: ^8.8.2 @@ -12667,7 +12781,7 @@ __metadata: source-map-support: ~0.5.20 bin: terser: bin/terser - checksum: c165052cfea061e8512e9b9ba42a098c2ff6382886ae122b040fd5b6153443070cc2dcb4862269f1669c09c716763e856125a355ff984aa72be525d6fffd8729 + checksum: 8c680ed32a948f806fade0969c52aab94b6de174e4a78610f5d3abf9993b161eb19b88b2ceadff09b153858727c02deb6709635e4bfbd519f67d54e0394e2983 languageName: node linkType: hard @@ -12696,15 +12810,6 @@ __metadata: languageName: node linkType: hard -"thingies@npm:^1.11.1": - version: 1.16.0 - resolution: "thingies@npm:1.16.0" - peerDependencies: - tslib: ^2 - checksum: 9afbe70a9777fc31ac2567d06c9f64511585437298948330c39c076c6bd54bae6a700dee4cf4074486ef26c83f51031241ef4f4309c386555fb016a93be8aa06 - languageName: node - linkType: hard - "through@npm:2, through@npm:^2.3.8, through@npm:~2.3, through@npm:~2.3.1": version: 2.3.8 resolution: "through@npm:2.3.8" @@ -12742,13 +12847,6 @@ __metadata: languageName: node linkType: hard -"tr46@npm:~0.0.3": - version: 0.0.3 - resolution: "tr46@npm:0.0.3" - checksum: 726321c5eaf41b5002e17ffbd1fb7245999a073e8979085dacd47c4b4e8068ff5777142fc6726d6ca1fd2ff16921b48788b87225cbc57c72636f6efa8efbffe3 - languageName: node - linkType: hard - "tree-kill@npm:^1.2.2": version: 1.2.2 resolution: "tree-kill@npm:1.2.2" @@ -12772,37 +12870,31 @@ __metadata: languageName: node linkType: hard -"truncate-utf8-bytes@npm:^1.0.0": - version: 1.0.2 - resolution: "truncate-utf8-bytes@npm:1.0.2" - dependencies: - utf8-byte-length: ^1.0.1 - checksum: ad097314709ea98444ad9c80c03aac8da805b894f37ceb5685c49ad297483afe3a5ec9572ebcaff699dda72b6cd447a2ba2a3fd10e96c2628cd16d94abeb328a - languageName: node - linkType: hard - "ts-api-utils@npm:^1.0.1": - version: 1.0.3 - resolution: "ts-api-utils@npm:1.0.3" + version: 1.3.0 + resolution: "ts-api-utils@npm:1.3.0" peerDependencies: typescript: ">=4.2.0" - checksum: 441cc4489d65fd515ae6b0f4eb8690057add6f3b6a63a36073753547fb6ce0c9ea0e0530220a0b282b0eec535f52c4dfc315d35f8a4c9a91c0def0707a714ca6 + checksum: c746ddabfdffbf16cb0b0db32bb287236a19e583057f8649ee7c49995bb776e1d3ef384685181c11a1a480369e022ca97512cb08c517b2d2bd82c83754c97012 languageName: node linkType: hard -"ts-essentials@npm:^7.0.3": - version: 7.0.3 - resolution: "ts-essentials@npm:7.0.3" +"ts-essentials@npm:^9.4.2": + version: 9.4.2 + resolution: "ts-essentials@npm:9.4.2" peerDependencies: - typescript: ">=3.7.0" - checksum: 74d75868acf7f8b95e447d8b3b7442ca21738c6894e576df9917a352423fde5eb43c5651da5f78997da6061458160ae1f6b279150b42f47ccc58b73e55acaa2f + typescript: ">=4.1.0" + peerDependenciesMeta: + typescript: + optional: true + checksum: ef9a15cef66e4c23942cd6a64ab1aa15108cabea187904ba8345bab309f5b5d8f4fc076950391af8fd3914df0349ce11dc716930949f7f5d24ec3a5851ccfe73 languageName: node linkType: hard "ts-graphviz@npm:^1.5.0": - version: 1.8.1 - resolution: "ts-graphviz@npm:1.8.1" - checksum: c560fc3a70fc7743bb1cacd21fdeb68661e78132cad4c0cb53c071d2485b1e5975350f0a754c2a797912e9d9022dc375b47e6b023a2eafe4b824c0bb9b7d58ed + version: 1.8.2 + resolution: "ts-graphviz@npm:1.8.2" + checksum: 73723d6d9b9b29073ff659b38e8a8443a024d515a30fd77dfb00a9df0e835739f2522c303a353e63bbd39115e23b34c9d92dd66f72590cf5f92d3a447255f9b9 languageName: node linkType: hard @@ -12861,8 +12953,8 @@ __metadata: linkType: hard "tsc-watch@npm:^6.0.0": - version: 6.0.4 - resolution: "tsc-watch@npm:6.0.4" + version: 6.2.0 + resolution: "tsc-watch@npm:6.2.0" dependencies: cross-spawn: ^7.0.3 node-cleanup: ^2.1.2 @@ -12872,7 +12964,7 @@ __metadata: typescript: "*" bin: tsc-watch: dist/lib/tsc-watch.js - checksum: f7bf7eefbc5a8bbf7c989edd1e5199ac95ad1654b11ea39bfe7fc2e5a83480926928bd405aebe2cbd783fc6ffac521b9ad650cb300d51d4a9b616b7c69da02da + checksum: e1028c45a4e47ae28e0ad68370f95d7410de2e0feaa8cf0ed4a701488a538eccef99b3d6bb2d11b995fbdc4f5a9e938c78037e345c6b3ee46b58d7cef781efb9 languageName: node linkType: hard @@ -12902,7 +12994,7 @@ __metadata: languageName: node linkType: hard -"tslib@npm:^2.0.1, tslib@npm:^2.1.0, tslib@npm:^2.4.0, tslib@npm:^2.5.0": +"tslib@npm:^2.0.0, tslib@npm:^2.0.1, tslib@npm:^2.1.0, tslib@npm:^2.4.0, tslib@npm:^2.5.0, tslib@npm:^2.6.1": version: 2.6.2 resolution: "tslib@npm:2.6.2" checksum: 329ea56123005922f39642318e3d1f0f8265d1e7fcb92c633e0809521da75eeaca28d2cf96d7248229deb40e5c19adf408259f4b9640afd20d13aecc1430f3ad @@ -12995,50 +13087,55 @@ __metadata: languageName: node linkType: hard -"typed-array-buffer@npm:^1.0.0": - version: 1.0.0 - resolution: "typed-array-buffer@npm:1.0.0" +"typed-array-buffer@npm:^1.0.2": + version: 1.0.2 + resolution: "typed-array-buffer@npm:1.0.2" dependencies: - call-bind: ^1.0.2 - get-intrinsic: ^1.2.1 - is-typed-array: ^1.1.10 - checksum: 3e0281c79b2a40cd97fe715db803884301993f4e8c18e8d79d75fd18f796e8cd203310fec8c7fdb5e6c09bedf0af4f6ab8b75eb3d3a85da69328f28a80456bd3 + call-bind: ^1.0.7 + es-errors: ^1.3.0 + is-typed-array: ^1.1.13 + checksum: 02ffc185d29c6df07968272b15d5319a1610817916ec8d4cd670ded5d1efe72901541ff2202fcc622730d8a549c76e198a2f74e312eabbfb712ed907d45cbb0b languageName: node linkType: hard -"typed-array-byte-length@npm:^1.0.0": - version: 1.0.0 - resolution: "typed-array-byte-length@npm:1.0.0" +"typed-array-byte-length@npm:^1.0.1": + version: 1.0.1 + resolution: "typed-array-byte-length@npm:1.0.1" dependencies: - call-bind: ^1.0.2 + call-bind: ^1.0.7 for-each: ^0.3.3 - has-proto: ^1.0.1 - is-typed-array: ^1.1.10 - checksum: b03db16458322b263d87a702ff25388293f1356326c8a678d7515767ef563ef80e1e67ce648b821ec13178dd628eb2afdc19f97001ceae7a31acf674c849af94 + gopd: ^1.0.1 + has-proto: ^1.0.3 + is-typed-array: ^1.1.13 + checksum: f65e5ecd1cf76b1a2d0d6f631f3ea3cdb5e08da106c6703ffe687d583e49954d570cc80434816d3746e18be889ffe53c58bf3e538081ea4077c26a41055b216d languageName: node linkType: hard -"typed-array-byte-offset@npm:^1.0.0": - version: 1.0.0 - resolution: "typed-array-byte-offset@npm:1.0.0" +"typed-array-byte-offset@npm:^1.0.2": + version: 1.0.2 + resolution: "typed-array-byte-offset@npm:1.0.2" dependencies: - available-typed-arrays: ^1.0.5 - call-bind: ^1.0.2 + available-typed-arrays: ^1.0.7 + call-bind: ^1.0.7 for-each: ^0.3.3 - has-proto: ^1.0.1 - is-typed-array: ^1.1.10 - checksum: 04f6f02d0e9a948a95fbfe0d5a70b002191fae0b8fe0fe3130a9b2336f043daf7a3dda56a31333c35a067a97e13f539949ab261ca0f3692c41603a46a94e960b + gopd: ^1.0.1 + has-proto: ^1.0.3 + is-typed-array: ^1.1.13 + checksum: c8645c8794a621a0adcc142e0e2c57b1823bbfa4d590ad2c76b266aa3823895cf7afb9a893bf6685e18454ab1b0241e1a8d885a2d1340948efa4b56add4b5f67 languageName: node linkType: hard -"typed-array-length@npm:^1.0.4": - version: 1.0.4 - resolution: "typed-array-length@npm:1.0.4" +"typed-array-length@npm:^1.0.6": + version: 1.0.6 + resolution: "typed-array-length@npm:1.0.6" dependencies: - call-bind: ^1.0.2 + call-bind: ^1.0.7 for-each: ^0.3.3 - is-typed-array: ^1.1.9 - checksum: 2228febc93c7feff142b8c96a58d4a0d7623ecde6c7a24b2b98eb3170e99f7c7eff8c114f9b283085cd59dcd2bd43aadf20e25bba4b034a53c5bb292f71f8956 + gopd: ^1.0.1 + has-proto: ^1.0.3 + is-typed-array: ^1.1.13 + possible-typed-array-names: ^1.0.0 + checksum: f0315e5b8f0168c29d390ff410ad13e4d511c78e6006df4a104576844812ee447fcc32daab1f3a76c9ef4f64eff808e134528b5b2439de335586b392e9750e5c languageName: node linkType: hard @@ -13079,12 +13176,12 @@ __metadata: linkType: hard "typescript@npm:^5.0.4": - version: 5.3.3 - resolution: "typescript@npm:5.3.3" + version: 5.4.5 + resolution: "typescript@npm:5.4.5" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 2007ccb6e51bbbf6fde0a78099efe04dc1c3dfbdff04ca3b6a8bc717991862b39fd6126c0c3ebf2d2d98ac5e960bcaa873826bb2bb241f14277034148f41f6a2 + checksum: 53c879c6fa1e3bcb194b274d4501ba1985894b2c2692fa079db03c5a5a7140587a1e04e1ba03184605d35f439b40192d9e138eb3279ca8eee313c081c8bcd9b0 languageName: node linkType: hard @@ -13109,26 +13206,26 @@ __metadata: linkType: hard "typescript@patch:typescript@^5.0.4#~builtin": - version: 5.3.3 - resolution: "typescript@patch:typescript@npm%3A5.3.3#~builtin::version=5.3.3&hash=f3b441" + version: 5.4.5 + resolution: "typescript@patch:typescript@npm%3A5.4.5#~builtin::version=5.4.5&hash=f3b441" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: f61375590b3162599f0f0d5b8737877ac0a7bc52761dbb585d67e7b8753a3a4c42d9a554c4cc929f591ffcf3a2b0602f65ae3ce74714fd5652623a816862b610 + checksum: 2373c693f3b328f3b2387c3efafe6d257b057a142f9a79291854b14ff4d5367d3d730810aee981726b677ae0fd8329b23309da3b6aaab8263dbdccf1da07a3ba languageName: node linkType: hard -"uint8-varint@npm:^2.0.0, uint8-varint@npm:^2.0.1": - version: 2.0.3 - resolution: "uint8-varint@npm:2.0.3" +"uint8-varint@npm:^2.0.0, uint8-varint@npm:^2.0.1, uint8-varint@npm:^2.0.2, uint8-varint@npm:^2.0.4": + version: 2.0.4 + resolution: "uint8-varint@npm:2.0.4" dependencies: uint8arraylist: ^2.0.0 uint8arrays: ^5.0.0 - checksum: 8c20b02f803ade88d3aad0c01368e8bfebedca3cb43f2d74347f32b92a219ab734b8df4bb0dee5540261de984896ef4ffb3c58e83b200d4b1d01a7e3f7757dee + checksum: fef8205bec41fdbc5166a7a106e34d54ac4e574512e497783951d60983a7b0c27a740b287522c6ad9e1a9ed27c5481cddd92caaa93ac7aac96b57364a7e1d20e languageName: node linkType: hard -"uint8arraylist@npm:^2.0.0, uint8arraylist@npm:^2.4.1, uint8arraylist@npm:^2.4.3, uint8arraylist@npm:^2.4.7": +"uint8arraylist@npm:^2.0.0, uint8arraylist@npm:^2.4.1, uint8arraylist@npm:^2.4.3, uint8arraylist@npm:^2.4.8": version: 2.4.8 resolution: "uint8arraylist@npm:2.4.8" dependencies: @@ -13137,7 +13234,7 @@ __metadata: languageName: node linkType: hard -"uint8arrays@npm:^4.0.4, uint8arrays@npm:^4.0.6": +"uint8arrays@npm:^4.0.6": version: 4.0.10 resolution: "uint8arrays@npm:4.0.10" dependencies: @@ -13146,12 +13243,12 @@ __metadata: languageName: node linkType: hard -"uint8arrays@npm:^5.0.0, uint8arrays@npm:^5.0.1": - version: 5.0.1 - resolution: "uint8arrays@npm:5.0.1" +"uint8arrays@npm:^5.0.0, uint8arrays@npm:^5.0.1, uint8arrays@npm:^5.0.2, uint8arrays@npm:^5.0.3": + version: 5.0.3 + resolution: "uint8arrays@npm:5.0.3" dependencies: multiformats: ^13.0.0 - checksum: 29b27d41e1b5fe2b3de0ce502556e9ac7caabf53c0a40f27d3654c4cb08f06913b14b7722325a1a4287664d15938abf48dd987340d966ca61c2daa40030b5f82 + checksum: e3c8afa183f2bac2e271891c00de18100168cddf01310297f9dd56d6356d865e5cc96c4ad567d9435ddaa080b3e31ca068997f1a5a7ae8998d4fc0326343475a languageName: node linkType: hard @@ -13209,13 +13306,6 @@ __metadata: languageName: node linkType: hard -"universalify@npm:^0.1.0": - version: 0.1.2 - resolution: "universalify@npm:0.1.2" - checksum: 40cdc60f6e61070fe658ca36016a8f4ec216b29bf04a55dce14e3710cc84c7448538ef4dad3728d0bfe29975ccd7bfb5f414c45e7b78883567fb31b246f02dff - languageName: node - linkType: hard - "universalify@npm:^2.0.0": version: 2.0.1 resolution: "universalify@npm:2.0.1" @@ -13276,14 +13366,7 @@ __metadata: languageName: node linkType: hard -"utf8-byte-length@npm:^1.0.1": - version: 1.0.4 - resolution: "utf8-byte-length@npm:1.0.4" - checksum: f188ca076ec094d58e7009fcc32623c5830c7f0f3e15802bfa4fdd1e759454a481fc4ac05e0fa83b7736e77af628a9ee0e57dcc89683d688fde3811473e42143 - languageName: node - linkType: hard - -"util-deprecate@npm:^1.0.1": +"util-deprecate@npm:^1.0.1, util-deprecate@npm:~1.0.1": version: 1.0.2 resolution: "util-deprecate@npm:1.0.2" checksum: 474acf1146cb2701fe3b074892217553dfcf9a031280919ba1b8d651a068c9b15d863b7303cb15bd00a862b498e6cf4ad7b4a08fb134edd5a6f7641681cb54a2 @@ -13346,8 +13429,8 @@ __metadata: linkType: hard "viem@npm:^2.7.15": - version: 2.7.15 - resolution: "viem@npm:2.7.15" + version: 2.9.25 + resolution: "viem@npm:2.9.25" dependencies: "@adraffy/ens-normalize": 1.10.0 "@noble/curves": 1.2.0 @@ -13362,13 +13445,13 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: d0d3a9b48fcf64298c08d57dd782fdf6f21538c6472ebc87953928d860f5fd6296a7e22f46f230d68b667df6505fa472414cc3d8e7a041ea2a7f1fd45bc013de + checksum: f9dbcc00a63b223a5ae213da5fd16ae8549d851f069065ace7072fb0c264d295a56fde547ec6c154c71d36011944c5fa600315131ea2c0fc34a94283ae4f40b3 languageName: node linkType: hard "vite@npm:^4.2.3": - version: 4.5.2 - resolution: "vite@npm:4.5.2" + version: 4.5.3 + resolution: "vite@npm:4.5.3" dependencies: esbuild: ^0.18.10 fsevents: ~2.3.2 @@ -13402,7 +13485,7 @@ __metadata: optional: true bin: vite: bin/vite.js - checksum: 9d1f84f703c2660aced34deee7f309278ed368880f66e9570ac115c793d91f7fffb80ab19c602b3c8bc1341fe23437d86a3fcca2a9ef82f7ef0cdac5a40d0c86 + checksum: fd3f512ce48ca2a1fe60ad0376283b832de9272725fdbc65064ae9248f792de87b0f27a89573115e23e26784800daca329f8a9234d298ba6f60e808a9c63883c languageName: node linkType: hard @@ -13436,13 +13519,13 @@ __metadata: languageName: node linkType: hard -"watchpack@npm:^2.4.0": - version: 2.4.0 - resolution: "watchpack@npm:2.4.0" +"watchpack@npm:^2.4.1": + version: 2.4.1 + resolution: "watchpack@npm:2.4.1" dependencies: glob-to-regexp: ^0.4.1 graceful-fs: ^4.1.2 - checksum: 23d4bc58634dbe13b86093e01c6a68d8096028b664ab7139d58f0c37d962d549a940e98f2f201cecdabd6f9c340338dc73ef8bf094a2249ef582f35183d1a131 + checksum: 5b0179348655dcdf19cac7cb4ff923fdc024d630650c0bf6bec8899cf47c60e19d4f810a88dba692ed0e7f684cf0fcffea86efdbf6c35d81f031e328043b7fab languageName: node linkType: hard @@ -13462,13 +13545,6 @@ __metadata: languageName: node linkType: hard -"webidl-conversions@npm:^3.0.0": - version: 3.0.1 - resolution: "webidl-conversions@npm:3.0.1" - checksum: c92a0a6ab95314bde9c32e1d0a6dfac83b578f8fa5f21e675bc2706ed6981bc26b7eb7e6a1fab158e5ce4adf9caa4a0aee49a52505d4d13c7be545f15021b17c - languageName: node - linkType: hard - "webpack-cli@npm:^5.1.4": version: 5.1.4 resolution: "webpack-cli@npm:5.1.4" @@ -13520,24 +13596,24 @@ __metadata: linkType: hard "webpack@npm:^5.88.2": - version: 5.90.0 - resolution: "webpack@npm:5.90.0" + version: 5.91.0 + resolution: "webpack@npm:5.91.0" dependencies: "@types/eslint-scope": ^3.7.3 "@types/estree": ^1.0.5 - "@webassemblyjs/ast": ^1.11.5 - "@webassemblyjs/wasm-edit": ^1.11.5 - "@webassemblyjs/wasm-parser": ^1.11.5 + "@webassemblyjs/ast": ^1.12.1 + "@webassemblyjs/wasm-edit": ^1.12.1 + "@webassemblyjs/wasm-parser": ^1.12.1 acorn: ^8.7.1 acorn-import-assertions: ^1.9.0 browserslist: ^4.21.10 chrome-trace-event: ^1.0.2 - enhanced-resolve: ^5.15.0 + enhanced-resolve: ^5.16.0 es-module-lexer: ^1.2.1 eslint-scope: 5.1.1 events: ^3.2.0 glob-to-regexp: ^0.4.1 - graceful-fs: ^4.2.9 + graceful-fs: ^4.2.11 json-parse-even-better-errors: ^2.3.1 loader-runner: ^4.2.0 mime-types: ^2.1.27 @@ -13545,24 +13621,14 @@ __metadata: schema-utils: ^3.2.0 tapable: ^2.1.1 terser-webpack-plugin: ^5.3.10 - watchpack: ^2.4.0 + watchpack: ^2.4.1 webpack-sources: ^3.2.3 peerDependenciesMeta: webpack-cli: optional: true bin: webpack: bin/webpack.js - checksum: 178a0e7e9e5b26264a19dd5fe554a3508a8afafc9cce972bfd4452b5128d0db1b37832f5e615be1cff1934f24da0de967929f199be2b3fe283ca1951f98ea3fe - languageName: node - linkType: hard - -"whatwg-url@npm:^5.0.0": - version: 5.0.0 - resolution: "whatwg-url@npm:5.0.0" - dependencies: - tr46: ~0.0.3 - webidl-conversions: ^3.0.0 - checksum: b8daed4ad3356cc4899048a15b2c143a9aed0dfae1f611ebd55073310c7b910f522ad75d727346ad64203d7e6c79ef25eafd465f4d12775ca44b90fa82ed9e2c + checksum: f1073715dbb1ed5c070affef293d800a867708bcbc5aba4d8baee87660e0cf53c55966a6f36fab078d1d6c9567cdcd0a9086bdfb607cab87ea68c6449791b9a3 languageName: node linkType: hard @@ -13588,16 +13654,16 @@ __metadata: languageName: node linkType: hard -"which-typed-array@npm:^1.1.11, which-typed-array@npm:^1.1.13, which-typed-array@npm:^1.1.2": - version: 1.1.13 - resolution: "which-typed-array@npm:1.1.13" +"which-typed-array@npm:^1.1.14, which-typed-array@npm:^1.1.15, which-typed-array@npm:^1.1.2": + version: 1.1.15 + resolution: "which-typed-array@npm:1.1.15" dependencies: - available-typed-arrays: ^1.0.5 - call-bind: ^1.0.4 + available-typed-arrays: ^1.0.7 + call-bind: ^1.0.7 for-each: ^0.3.3 gopd: ^1.0.1 - has-tostringtag: ^1.0.0 - checksum: 3828a0d5d72c800e369d447e54c7620742a4cc0c9baf1b5e8c17e9b6ff90d8d861a3a6dd4800f1953dbf80e5e5cec954a289e5b4a223e3bee4aeb1f8c5f33309 + has-tostringtag: ^1.0.2 + checksum: 65227dcbfadf5677aacc43ec84356d17b5500cb8b8753059bb4397de5cd0c2de681d24e1a7bd575633f976a95f88233abfd6549c2105ef4ebd58af8aa1807c75 languageName: node linkType: hard @@ -13644,20 +13710,20 @@ __metadata: languageName: node linkType: hard -"winston-transport@npm:^4.4.0, winston-transport@npm:^4.5.0": - version: 4.6.0 - resolution: "winston-transport@npm:4.6.0" +"winston-transport@npm:^4.4.0, winston-transport@npm:^4.7.0": + version: 4.7.0 + resolution: "winston-transport@npm:4.7.0" dependencies: logform: ^2.3.2 readable-stream: ^3.6.0 triple-beam: ^1.3.0 - checksum: 19f06ebdbb57cb14cdd48a23145d418d3bbe538851053303f84f04a8a849bb530b78b1495a175059c1299f92945dc61d5421c4914fee32d9a41bc397d84f26d7 + checksum: ce074b5c76a99bee5236cf2b4d30fadfaf1e551d566f654f1eba303dc5b5f77169c21545ff5c5e4fdad9f8e815fc6d91b989f1db34161ecca6e860e62fd3a862 languageName: node linkType: hard "winston@npm:^3.10.0": - version: 3.11.0 - resolution: "winston@npm:3.11.0" + version: 3.13.0 + resolution: "winston@npm:3.13.0" dependencies: "@colors/colors": ^1.6.0 "@dabh/diagnostics": ^2.0.2 @@ -13669,8 +13735,8 @@ __metadata: safe-stable-stringify: ^2.3.1 stack-trace: 0.0.x triple-beam: ^1.3.0 - winston-transport: ^4.5.0 - checksum: ca4454070f7a71b19f53c8c1765c59a013dab220edb49161b2e81917751d3e9edc3382430e4fb050feda04fb8463290ecab7cbc9240ec8d3d3b32a121849bbb0 + winston-transport: ^4.7.0 + checksum: 66f9fbbadb58e1632701e9c89391f217310c9455462148e163e060dcd25aed21351b0413bdbbf90e5c5fe9bc945fc5de6f53875ac7c7ef3061133a354fc678c0 languageName: node linkType: hard @@ -13743,30 +13809,6 @@ __metadata: languageName: node linkType: hard -"xml2js@npm:^0.6.0, xml2js@npm:^0.6.2": - version: 0.6.2 - resolution: "xml2js@npm:0.6.2" - dependencies: - sax: ">=0.6.0" - xmlbuilder: ~11.0.0 - checksum: 458a83806193008edff44562c0bdb982801d61ee7867ae58fd35fab781e69e17f40dfeb8fc05391a4648c9c54012066d3955fe5d993ffbe4dc63399023f32ac2 - languageName: node - linkType: hard - -"xmlbuilder@npm:~11.0.0": - version: 11.0.1 - resolution: "xmlbuilder@npm:11.0.1" - checksum: 7152695e16f1a9976658215abab27e55d08b1b97bca901d58b048d2b6e106b5af31efccbdecf9b07af37c8377d8e7e821b494af10b3a68b0ff4ae60331b415b0 - languageName: node - linkType: hard - -"xsalsa20@npm:^1.1.0": - version: 1.2.0 - resolution: "xsalsa20@npm:1.2.0" - checksum: 488fac04877d18cef54a49325277470685ba410e1b2fadc2108ae91a04ca474fdae682789bf13eb800e56e5a7017bb11187261f64253ea990281e86c59319617 - languageName: node - linkType: hard - "y18n@npm:^5.0.5": version: 5.0.8 resolution: "y18n@npm:5.0.8" @@ -13789,9 +13831,11 @@ __metadata: linkType: hard "yaml@npm:^2.1.3": - version: 2.3.4 - resolution: "yaml@npm:2.3.4" - checksum: e6d1dae1c6383bcc8ba11796eef3b8c02d5082911c6723efeeb5ba50fc8e881df18d645e64de68e421b577296000bea9c75d6d9097c2f6699da3ae0406c030d8 + version: 2.4.1 + resolution: "yaml@npm:2.4.1" + bin: + yaml: bin.mjs + checksum: 4c391d07a5d5e935e058babb71026c9cdc9a6fd889e35dd91b53cfb0a12691b67c6c5c740858e71345fef18cd9c13c554a6dda9196f59820d769d94041badb0b languageName: node linkType: hard @@ -13838,9 +13882,9 @@ __metadata: linkType: hard "ylru@npm:^1.2.0": - version: 1.3.2 - resolution: "ylru@npm:1.3.2" - checksum: b6bb3931144424114f2350c072cfeb180f205add93509c605ae025cbed8059846f8a5767655feeeab890d288b5b4c4b36f5d5d867ee4e6946c16bcc7ec3ddaee + version: 1.4.0 + resolution: "ylru@npm:1.4.0" + checksum: e0bf797476487e3d57a6e8790cbb749cff2089e2afc87e46bc84ce7605c329d578ff422c8e8c2ddf167681ddd218af0f58e099733ae1044cba9e9472ebedc01d languageName: node linkType: hard @@ -13858,9 +13902,16 @@ __metadata: languageName: node linkType: hard -"zod@npm:^3.22.4": +"zod@npm:3.22.4": version: 3.22.4 resolution: "zod@npm:3.22.4" checksum: 80bfd7f8039b24fddeb0718a2ec7c02aa9856e4838d6aa4864335a047b6b37a3273b191ef335bf0b2002e5c514ef261ffcda5a589fb084a48c336ffc4cdbab7f languageName: node linkType: hard + +"zod@npm:^3.22.4": + version: 3.23.0 + resolution: "zod@npm:3.23.0" + checksum: ba3ae4d2320bfba1207475cac77c3449db55ae345ec737c4fdff794c6851619adebac1e0f5413311f4e80cf98ca6669b7f7c4336a64fde8fa8c6345c6288506d + languageName: node + linkType: hard From 41fa87e1216eeb6ff774eb1925797f9ae721c70b Mon Sep 17 00:00:00 2001 From: ludamad Date: Mon, 22 Apr 2024 13:16:34 -0500 Subject: [PATCH 064/102] chore: redo typo script (#5926) Formalizing our policy of dissuading metrics farming through typo PRs while accepting the contribution Example output https://github.com/AztecProtocol/aztec-packages/pull/5925 --- scripts/redo-typo-pr | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100755 scripts/redo-typo-pr diff --git a/scripts/redo-typo-pr b/scripts/redo-typo-pr new file mode 100755 index 00000000000..d265ade3f7b --- /dev/null +++ b/scripts/redo-typo-pr @@ -0,0 +1,32 @@ +#!/bin/bash + +set -eux + +# Configuration +ORIGINAL_PR_NUMBER=$1 +REPO='AztecProtocol/aztec-packages' +NEW_BRANCH="chore/typo-redo-$ORIGINAL_PR_NUMBER" +AUTHOR=`gh pr view $ORIGINAL_PR_NUMBER --json author --jq '.author.login'` + +# Step 1: Checkout the PR locally +echo "Checking out PR #$ORIGINAL_PR_NUMBER" +gh pr checkout $ORIGINAL_PR_NUMBER + +# Step 2: Create a new local branch +echo "Creating new local branch $NEW_BRANCH" +git checkout -b $NEW_BRANCH + +# Step 3: Push the new branch to GitHub +echo "Pushing new branch $NEW_BRANCH to GitHub" +git commit --amend --author="AztecBot " --no-edit +git push origin $NEW_BRANCH + +# Step 4: create a new pull request +echo "Creating a new pull request for $NEW_BRANCH" +gh pr create --base master --head $NEW_BRANCH --title "chore: redo typo PR by $AUTHOR" --body "Thanks $AUTHOR for https://github.com/$REPO/pull/$ORIGINAL_PR_NUMBER. Our policy is to redo typo changes to dissuade metric farming. This is an automated script." + +# Step 5: Close the original PR +echo "Closing original PR #$ORIGINAL_PR_NUMBER" +gh pr close $ORIGINAL_PR_NUMBER --delete-branch + +echo "Script completed." From d28b1cbc0364c1d760187ffa7263c147e9295dd4 Mon Sep 17 00:00:00 2001 From: ludamad Date: Mon, 22 Apr 2024 13:32:30 -0500 Subject: [PATCH 065/102] chore: redo typo PR by satyambnsal (#5929) Thanks satyambnsal for https://github.com/AztecProtocol/aztec-packages/pull/5769. Our policy is to redo typo changes to dissuade metric farming. This is an automated script. Co-authored-by: AztecBot --- docs/docs/developers/tutorials/writing_token_contract.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/developers/tutorials/writing_token_contract.md b/docs/docs/developers/tutorials/writing_token_contract.md index a9b9e942391..67dfcce6d19 100644 --- a/docs/docs/developers/tutorials/writing_token_contract.md +++ b/docs/docs/developers/tutorials/writing_token_contract.md @@ -176,7 +176,7 @@ Transactions are initiated in the private context, then move to the L2 public co Step 1. Private Execution -Users provide inputs and execute locally on a their device for privacy reasons. Outputs of the private execution are commitment and nullifier updates, a proof of correct execution and any return data to pass to the public execution context. +Users provide inputs and execute locally on their device for privacy reasons. Outputs of the private execution are commitment and nullifier updates, a proof of correct execution and any return data to pass to the public execution context. Step 2. Public Execution From b23e42f5f897936bb9607ba94e57f31723d9984b Mon Sep 17 00:00:00 2001 From: ludamad Date: Mon, 22 Apr 2024 13:36:59 -0500 Subject: [PATCH 066/102] chore: redo typo PR by dockercui (#5930) Thanks dockercui for https://github.com/AztecProtocol/aztec-packages/pull/5913. Our policy is to redo typo changes to dissuade metric farming. This is an automated script. --------- Co-authored-by: AztecBot --- .../noir-contracts/contracts/auth_contract/src/main.nr | 2 +- noir/noir-repo/tooling/nargo/src/ops/execute.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/noir-projects/noir-contracts/contracts/auth_contract/src/main.nr b/noir-projects/noir-contracts/contracts/auth_contract/src/main.nr index 765107b0ea9..04385202409 100644 --- a/noir-projects/noir-contracts/contracts/auth_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/auth_contract/src/main.nr @@ -20,7 +20,7 @@ contract Auth { assert(!admin.is_zero(), "invalid admin"); storage.admin.initialize(admin); // Note that we don't initialize authorized with any value: because storage defaults to 0 it'll have a 'post' - // value of 0 and block of change 0, meaning it is effectively autoinitialized at the zero adddress. + // value of 0 and block of change 0, meaning it is effectively autoinitialized at the zero address. } #[aztec(public)] diff --git a/noir/noir-repo/tooling/nargo/src/ops/execute.rs b/noir/noir-repo/tooling/nargo/src/ops/execute.rs index 97584aff150..34755d14ed2 100644 --- a/noir/noir-repo/tooling/nargo/src/ops/execute.rs +++ b/noir/noir-repo/tooling/nargo/src/ops/execute.rs @@ -106,7 +106,7 @@ impl<'a, B: BlackBoxFunctionSolver, F: ForeignCallExecutor> ProgramExecutor<'a, return Err(NargoError::ExecutionError(match call_stack { Some(call_stack) => { // First check whether we have a runtime assertion message that should be resolved on an ACVM failure - // If we do not have a runtime assertion message, we check wether the error is a brillig error with a user-defined message, + // If we do not have a runtime assertion message, we check whether the error is a brillig error with a user-defined message, // and finally we should check whether the circuit has any hardcoded messages associated with a specific `OpcodeLocation`. // Otherwise return the provided opcode resolution error. if let Some(assert_message) = assert_message { From e817f78158e895807151f6b451cb506cab9c2510 Mon Sep 17 00:00:00 2001 From: ludamad Date: Mon, 22 Apr 2024 13:37:15 -0500 Subject: [PATCH 067/102] chore: redo typo PR by socialsister (#5931) Thanks socialsister for https://github.com/AztecProtocol/aztec-packages/pull/5892. Our policy is to redo typo changes to dissuade metric farming. This is an automated script. Co-authored-by: AztecBot --- .../developers/tutorials/token_portal/minting_on_aztec.md | 2 +- .../developers/tutorials/token_portal/withdrawing_to_l1.md | 2 +- docs/docs/protocol-specs/bytecode/index.md | 2 +- docs/docs/protocol-specs/circuits/private-function.md | 2 +- docs/docs/protocol-specs/circuits/private-kernel-initial.mdx | 4 ++-- .../data-publication-and-availability/overview.md | 2 +- docs/docs/protocol-specs/rollup-circuits/tree-parity.md | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/docs/developers/tutorials/token_portal/minting_on_aztec.md b/docs/docs/developers/tutorials/token_portal/minting_on_aztec.md index 0eb400f0acb..b7dc91be5b4 100644 --- a/docs/docs/developers/tutorials/token_portal/minting_on_aztec.md +++ b/docs/docs/developers/tutorials/token_portal/minting_on_aztec.md @@ -24,7 +24,7 @@ The `claim_public` function enables anyone to consume the message on the user's **What’s happening here?** 1. We first recompute the L1->L2 message content by calling `get_mint_public_content_hash()`. Note that the method does exactly the same as what the TokenPortal contract does in `depositToAztecPublic()` to create the content hash. -2. We then attempt to consume the L1->L2 message by passing the `msg_key`, the the content hash, and the "secret". Since we are depositing to Aztec publicly, this secret is public, anyone can know this and is usually 0. +2. We then attempt to consume the L1->L2 message by passing the `msg_key`, the content hash, and the "secret". Since we are depositing to Aztec publicly, this secret is public, anyone can know this and is usually 0. - `context.consume_l1_to_l2_message()` takes in the content_hash and secret to recreate the original message. The L1 to L2 message consists of: - Sender - who on L1 sent the message + chain ID of L1. The context variable knows the portal address on L1 and adds that - Recipient - i.e. this aztec contract address which is consuming the message + the current version of the aztec rollup. diff --git a/docs/docs/developers/tutorials/token_portal/withdrawing_to_l1.md b/docs/docs/developers/tutorials/token_portal/withdrawing_to_l1.md index 524e106ef51..2742b97a832 100644 --- a/docs/docs/developers/tutorials/token_portal/withdrawing_to_l1.md +++ b/docs/docs/developers/tutorials/token_portal/withdrawing_to_l1.md @@ -48,7 +48,7 @@ Paste this in your `TokenPortal.sol`: } ``` -Here we reconstruct the L2 to L1 message and check that this message exists on the outbox. If so, we consume it and transfer the funds to the recipient. As part of the reconstruction, the content hash looks similar to what we did in our bridge contract on aztec where we pass the amount and recipient to the the hash. This way a malicious actor can’t change the recipient parameter to the address and withdraw funds to themselves. +Here we reconstruct the L2 to L1 message and check that this message exists on the outbox. If so, we consume it and transfer the funds to the recipient. As part of the reconstruction, the content hash looks similar to what we did in our bridge contract on aztec where we pass the amount and recipient to the hash. This way a malicious actor can’t change the recipient parameter to the address and withdraw funds to themselves. We also use a `_withCaller` parameter to determine the appropriate party that can execute this function on behalf of the recipient. If `withCaller` is false, then anyone can call the method and hence we use address(0), otherwise only msg.sender should be able to execute. This address should match the `callerOnL1` address we passed in aztec when withdrawing from L2. diff --git a/docs/docs/protocol-specs/bytecode/index.md b/docs/docs/protocol-specs/bytecode/index.md index 4f54d240c5f..c94d9789fc5 100644 --- a/docs/docs/protocol-specs/bytecode/index.md +++ b/docs/docs/protocol-specs/bytecode/index.md @@ -144,7 +144,7 @@ If the function is public, the entry will be its ABI. If the function is private | `width?` | `number` | The width of the integer in bits. Applies to integers only. | | `length?` | `number` | The length of the array or string. Applies to arrays and strings only. | | `type?` | [AbiType](#abi-type) | The types of the array elements. Applies to arrays only. | -| `fields?` | [ABIVariable[]](#abi-variable) | The The fields of the struct. Applies to structs only. | +| `fields?` | [ABIVariable[]](#abi-variable) | the fields of the struct. Applies to structs only. | ### Bytecode in the artifact diff --git a/docs/docs/protocol-specs/circuits/private-function.md b/docs/docs/protocol-specs/circuits/private-function.md index 79051d9b81c..3f5696c83ba 100644 --- a/docs/docs/protocol-specs/circuits/private-function.md +++ b/docs/docs/protocol-specs/circuits/private-function.md @@ -16,7 +16,7 @@ The private inputs of a private function circuit are customizable. SCRIPT STALE NOW! - * ------------------- * L2 Body Data Specification * ------------------- * | byte start | num bytes | name * | --- | --- | --- * | 0x0 | 0x4 | len(numTxs) (denoted t) * | | | TxEffect 0 { - * | 0x4 | 0x1 | len(newNoteHashes) (denoted b) - * | 0x4 + 0x1 | b * 0x20 | newNoteHashes - * | 0x4 + 0x1 + b * 0x20 | 0x1 | len(newNullifiers) (denoted c) - * | 0x4 + 0x1 + b * 0x20 + 0x1 | c * 0x20 | newNullifiers - * | 0x4 + 0x1 + b * 0x20 + 0x1 + c * 0x20 | 0x1 | len(newL2ToL1Msgs) (denoted d) - * | 0x4 + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 | d * 0x20 | newL2ToL1Msgs - * | 0x4 + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 | 0x1 | len(newPublicDataWrites) (denoted e) - * | 0x4 + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 + 0x01 | e * 0x40 | newPublicDataWrites - * | 0x4 + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 + 0x01 + e * 0x40 | 0x04 | byteLen(newEncryptedLogs) (denoted f) - * | 0x4 + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 + 0x01 + e * 0x40 + 0x4 | f | newEncryptedLogs - * | 0x4 + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 + 0x01 + e * 0x40 + 0x4 + f | 0x04 | byteLen(newUnencryptedLogs) (denoted g) - * | 0x4 + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 + 0x01 + e * 0x40 + 0x4 + f + 0x4 | g | newUnencryptedLogs + * | 0x4 | 0x1 | revertCode + * | 0x5 | 0x1 | len(newNoteHashes) (denoted b) + * | 0x5 + 0x1 | b * 0x20 | newNoteHashes + * | 0x5 + 0x1 + b * 0x20 | 0x1 | len(newNullifiers) (denoted c) + * | 0x5 + 0x1 + b * 0x20 + 0x1 | c * 0x20 | newNullifiers + * | 0x5 + 0x1 + b * 0x20 + 0x1 + c * 0x20 | 0x1 | len(newL2ToL1Msgs) (denoted d) + * | 0x5 + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 | d * 0x20 | newL2ToL1Msgs + * | 0x5 + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 | 0x1 | len(newPublicDataWrites) (denoted e) + * | 0x5 + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 + 0x01 | e * 0x40 | newPublicDataWrites + * | 0x5 + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 + 0x01 + e * 0x40 | 0x04 | byteLen(newEncryptedLogs) (denoted f) + * | 0x5 + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 + 0x01 + e * 0x40 + 0x4 | f | newEncryptedLogs + * | 0x5 + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 + 0x01 + e * 0x40 + 0x4 + f | 0x04 | byteLen(newUnencryptedLogs) (denoted g) + * | 0x5 + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 + 0x01 + e * 0x40 + 0x4 + f + 0x4 | g | newUnencryptedLogs * | | | }, * | | | TxEffect 1 { * | | | ... @@ -93,11 +92,8 @@ library TxsDecoder { * revertCode, * newNoteHashesKernel, * newNullifiersKernel, - * newPublicDataWritesKernel, * newL2ToL1MsgsKernel, - * newContractLeafKernel, - * newContractDataKernel.aztecAddress, - * newContractDataKernel.ethAddress (padded to 32 bytes), + * newPublicDataWritesKernel, * encryptedLogsHash, | * unencryptedLogsHash, ____|=> Computed below from logs' preimages. * ); diff --git a/noir-projects/aztec-nr/aztec/src/context/avm_context.nr b/noir-projects/aztec-nr/aztec/src/context/avm_context.nr index 1df9863af65..16d7de0223b 100644 --- a/noir-projects/aztec-nr/aztec/src/context/avm_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/avm_context.nr @@ -181,9 +181,6 @@ impl ContextInterface for AvmContext { fn this_address(self) -> AztecAddress { address() } - fn this_portal_address(self) -> EthAddress { - portal() - } fn chain_id(self) -> Field { chain_id() } diff --git a/noir-projects/aztec-nr/aztec/src/context/interface.nr b/noir-projects/aztec-nr/aztec/src/context/interface.nr index 83494f8153e..f13e5d6df5e 100644 --- a/noir-projects/aztec-nr/aztec/src/context/interface.nr +++ b/noir-projects/aztec-nr/aztec/src/context/interface.nr @@ -14,7 +14,6 @@ trait ContextInterface { fn push_new_nullifier(&mut self, nullifier: Field, nullified_commitment: Field); fn msg_sender(self) -> AztecAddress; fn this_address(self) -> AztecAddress; - fn this_portal_address(self) -> EthAddress; fn chain_id(self) -> Field; fn version(self) -> Field; fn selector(self) -> FunctionSelector; diff --git a/noir-projects/aztec-nr/aztec/src/context/private_context.nr b/noir-projects/aztec-nr/aztec/src/context/private_context.nr index a5c7f782e38..c161ae99399 100644 --- a/noir-projects/aztec-nr/aztec/src/context/private_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/private_context.nr @@ -82,10 +82,6 @@ impl ContextInterface for PrivateContext { self.inputs.call_context.storage_contract_address } - fn this_portal_address(self) -> EthAddress { - self.inputs.call_context.portal_contract_address - } - fn chain_id(self) -> Field { self.inputs.tx_context.chain_id } diff --git a/noir-projects/aztec-nr/aztec/src/context/public_context.nr b/noir-projects/aztec-nr/aztec/src/context/public_context.nr index eab245d65ab..acda01b17b6 100644 --- a/noir-projects/aztec-nr/aztec/src/context/public_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/public_context.nr @@ -186,10 +186,6 @@ impl ContextInterface for PublicContext { self.inputs.call_context.storage_contract_address } - fn this_portal_address(self) -> EthAddress { - self.inputs.call_context.portal_contract_address - } - fn chain_id(self) -> Field { self.inputs.public_global_variables.chain_id } diff --git a/noir-projects/aztec-nr/aztec/src/deploy.nr b/noir-projects/aztec-nr/aztec/src/deploy.nr index 60f7fef0620..53fda2bee03 100644 --- a/noir-projects/aztec-nr/aztec/src/deploy.nr +++ b/noir-projects/aztec-nr/aztec/src/deploy.nr @@ -20,9 +20,8 @@ pub fn deploy_contract(context: &mut PrivateContext, target: AztecAddress) { serialized_args[0] = instance.salt; serialized_args[1] = instance.contract_class_id.to_field(); serialized_args[2] = instance.initialization_hash; - serialized_args[3] = instance.portal_contract_address.to_field(); - serialized_args[4] = instance.public_keys_hash.to_field(); - serialized_args[5] = universal_deploy as Field; + serialized_args[3] = instance.public_keys_hash.to_field(); + serialized_args[4] = universal_deploy as Field; let _call_result = context.call_private_function( AztecAddress::from_field(DEPLOYER_CONTRACT_ADDRESS), diff --git a/noir-projects/noir-contracts/contracts/avm_test_contract/src/main.nr b/noir-projects/noir-contracts/contracts/avm_test_contract/src/main.nr index 7eb12dd0e7c..f3f6cce1948 100644 --- a/noir-projects/noir-contracts/contracts/avm_test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/avm_test_contract/src/main.nr @@ -24,6 +24,7 @@ contract AvmTest { global big_field_136_bits: Field = 0x991234567890abcdef1234567890abcdef; // Libs + use dep::aztec::protocol_types::constants::CONTRACT_INSTANCE_LENGTH; use dep::aztec::prelude::{Map, Deserialize}; use dep::aztec::state_vars::PublicMutable; use dep::aztec::protocol_types::{address::{AztecAddress, EthAddress}, constants::L1_TO_L2_MESSAGE_LENGTH}; @@ -172,14 +173,14 @@ contract AvmTest { #[aztec(public-vm)] fn test_get_contract_instance_raw() { let fields = get_contract_instance_internal_avm(context.this_address()); - assert(fields.len() == 7); + // The values here should match those in `avm_simulator.test.ts>Contract>GETCONTRACTINSTANCE deserializes correctly` + assert(fields.len() == CONTRACT_INSTANCE_LENGTH + 1); assert(fields[0] == 0x1); assert(fields[1] == 0x123); assert(fields[2] == 0x456); assert(fields[3] == 0x789); assert(fields[4] == 0x101112); - assert(fields[5] == 0x131415); - assert(fields[6] == 0x161718); + assert(fields[5] == 0x161718); } #[aztec(public-vm)] @@ -206,11 +207,6 @@ contract AvmTest { context.msg_sender() } - #[aztec(public-vm)] - fn get_portal() -> pub EthAddress { - context.this_portal_address() - } - #[aztec(public-vm)] fn get_fee_per_l1_gas() -> pub Field { context.fee_per_l1_gas() diff --git a/noir-projects/noir-contracts/contracts/contract_instance_deployer_contract/src/events/instance_deployed.nr b/noir-projects/noir-contracts/contracts/contract_instance_deployer_contract/src/events/instance_deployed.nr index 0438fef4ca6..638a08db001 100644 --- a/noir-projects/noir-contracts/contracts/contract_instance_deployer_contract/src/events/instance_deployed.nr +++ b/noir-projects/noir-contracts/contracts/contract_instance_deployer_contract/src/events/instance_deployed.nr @@ -11,12 +11,11 @@ struct ContractInstanceDeployed { salt: Field, contract_class_id: ContractClassId, initialization_hash: Field, - portal_contract_address: EthAddress, public_keys_hash: PublicKeysHash, deployer: AztecAddress, } -global CONTRACT_INSTANCE_DEPLOYED_SERIALIZED_SIZE: Field = 9; +global CONTRACT_INSTANCE_DEPLOYED_SERIALIZED_SIZE: Field = 8; impl Serialize for ContractInstanceDeployed { fn serialize(self: Self) -> [Field; CONTRACT_INSTANCE_DEPLOYED_SERIALIZED_SIZE] { @@ -27,7 +26,6 @@ impl Serialize for ContractInstanceD self.salt, self.contract_class_id.to_field(), self.initialization_hash, - self.portal_contract_address.to_field(), self.public_keys_hash.to_field(), self.deployer.to_field(), ] diff --git a/noir-projects/noir-contracts/contracts/contract_instance_deployer_contract/src/main.nr b/noir-projects/noir-contracts/contracts/contract_instance_deployer_contract/src/main.nr index be9f464ea3a..2c152e5f746 100644 --- a/noir-projects/noir-contracts/contracts/contract_instance_deployer_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/contract_instance_deployer_contract/src/main.nr @@ -14,7 +14,6 @@ contract ContractInstanceDeployer { salt: Field, contract_class_id: ContractClassId, initialization_hash: Field, - portal_contract_address: EthAddress, public_keys_hash: PublicKeysHash, universal_deploy: bool ) { @@ -26,13 +25,7 @@ contract ContractInstanceDeployer { context.msg_sender() }; - let partial_address = PartialAddress::compute( - contract_class_id, - salt, - initialization_hash, - portal_contract_address, - deployer - ); + let partial_address = PartialAddress::compute(contract_class_id, salt, initialization_hash, deployer); let address = AztecAddress::compute(public_keys_hash, partial_address); @@ -40,16 +33,7 @@ contract ContractInstanceDeployer { context.push_new_nullifier(address.to_field(), 0); // Broadcast the event - let event = ContractInstanceDeployed { - contract_class_id, - address, - public_keys_hash, - portal_contract_address, - initialization_hash, - salt, - deployer, - version: 1 - }; + let event = ContractInstanceDeployed { contract_class_id, address, public_keys_hash, initialization_hash, salt, deployer, version: 1 }; let event_payload = event.serialize(); dep::aztec::oracle::debug_log::debug_log_array_with_prefix("ContractInstanceDeployed", event_payload); context.emit_unencrypted_log(event_payload); diff --git a/noir-projects/noir-contracts/contracts/gas_token_contract/src/main.nr b/noir-projects/noir-contracts/contracts/gas_token_contract/src/main.nr index ec1adf32116..cc19bf9f5f2 100644 --- a/noir-projects/noir-contracts/contracts/gas_token_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/gas_token_contract/src/main.nr @@ -2,13 +2,20 @@ mod lib; contract GasToken { use dep::aztec::protocol_types::{abis::function_selector::FunctionSelector, address::{AztecAddress, EthAddress}}; - use dep::aztec::{hash::compute_secret_hash, state_vars::{PublicMutable, Map}}; + use dep::aztec::{hash::compute_secret_hash, state_vars::{SharedImmutable, PublicMutable, Map}}; use crate::lib::{calculate_fee, get_bridge_gas_msg_hash}; #[aztec(storage)] struct Storage { balances: Map>, + portal_address: SharedImmutable, + } + + #[aztec(public)] + #[aztec(initializer)] + fn constructor(portal_address: EthAddress) { + storage.portal_address.initialize(portal_address); } #[aztec(public)] @@ -16,7 +23,12 @@ contract GasToken { let content_hash = get_bridge_gas_msg_hash(to, amount); // Consume message and emit nullifier - context.consume_l1_to_l2_message(content_hash, secret, context.this_portal_address(), leaf_index); + context.consume_l1_to_l2_message( + content_hash, + secret, + storage.portal_address.read_public(), + leaf_index + ); let new_balance = storage.balances.at(to).read() + U128::from_integer(amount); storage.balances.at(to).write(new_balance); diff --git a/noir-projects/noir-contracts/contracts/test_contract/src/main.nr b/noir-projects/noir-contracts/contracts/test_contract/src/main.nr index 43a0d80c528..a7e897ad564 100644 --- a/noir-projects/noir-contracts/contracts/test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/test_contract/src/main.nr @@ -2,7 +2,7 @@ contract Test { use dep::aztec::prelude::{ AztecAddress, EthAddress, FunctionSelector, NoteHeader, NoteGetterOptions, NoteViewerOptions, - PrivateContext, PrivateImmutable, PrivateSet + PrivateContext, PrivateImmutable, PrivateSet, SharedImmutable }; use dep::aztec::protocol_types::{ @@ -46,17 +46,6 @@ contract Test { [pub_key.x, pub_key.y] } - #[aztec(private)] - fn get_portal_contract_address() -> EthAddress { - context.this_portal_address() - } - - // Get the address of the l1 portal for this contract (taken from the input context) - #[aztec(private)] - fn get_this_portal_address() -> EthAddress { - context.this_portal_address() - } - // Get the address of this contract (taken from the input context) #[aztec(private)] fn get_this_address() -> AztecAddress { @@ -194,12 +183,12 @@ contract Test { // Purely exists for testing #[aztec(public)] - fn create_l2_to_l1_message_public(amount: Field, secret_hash: Field) { + fn create_l2_to_l1_message_public(amount: Field, secret_hash: Field, portal_address: EthAddress) { // Create a commitment to the amount let note = DummyNote::new(amount, secret_hash); // Public oracle call to emit new commitment. - context.message_portal(context.this_portal_address(), note.get_commitment()); + context.message_portal(portal_address, note.get_commitment()); } #[aztec(public)] @@ -262,30 +251,27 @@ contract Test { to: AztecAddress, amount: Field, secret: Field, - message_leaf_index: Field + message_leaf_index: Field, + portal_address: EthAddress ) { let content_hash = get_mint_public_content_hash(to, amount); // Consume message and emit nullifier - context.consume_l1_to_l2_message( - content_hash, - secret, - context.this_portal_address(), - message_leaf_index - ); + context.consume_l1_to_l2_message(content_hash, secret, portal_address, message_leaf_index); } #[aztec(private)] fn consume_mint_private_message( secret_hash_for_redeeming_minted_notes: Field, amount: Field, - secret_for_L1_to_L2_message_consumption: Field + secret_for_L1_to_L2_message_consumption: Field, + portal_address: EthAddress ) { // Consume L1 to L2 message and emit nullifier let content_hash = get_mint_private_content_hash(secret_hash_for_redeeming_minted_notes, amount); context.consume_l1_to_l2_message( content_hash, secret_for_L1_to_L2_message_consumption, - context.this_portal_address() + portal_address ); } diff --git a/noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr b/noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr index 28226b5b10b..7cb053fb512 100644 --- a/noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr @@ -6,7 +6,7 @@ // Bridge has to be set as a minter on the token before it can be used contract TokenBridge { - use dep::aztec::prelude::{FunctionSelector, AztecAddress, EthAddress, PublicMutable}; + use dep::aztec::prelude::{FunctionSelector, AztecAddress, EthAddress, PublicMutable, SharedImmutable}; use dep::aztec::{context::Context, hash::compute_secret_hash}; @@ -20,25 +20,26 @@ contract TokenBridge { #[aztec(storage)] struct Storage { token: PublicMutable, + portal_address: SharedImmutable, } // Constructs the contract. - #[aztec(private)] + #[aztec(public)] #[aztec(initializer)] - fn constructor(token: AztecAddress) { - let selector = FunctionSelector::from_signature("_initialize((Field))"); - context.call_public_function(context.this_address(), selector, [token.to_field()]); + fn constructor(token: AztecAddress, portal_address: EthAddress) { + storage.token.write(token); + storage.portal_address.initialize(portal_address); } // docs:end:token_bridge_storage_and_constructor #[aztec(private)] fn get_portal_address() -> EthAddress { - context.this_portal_address() + storage.portal_address.read_private() } #[aztec(public)] fn get_portal_address_public() -> EthAddress { - context.this_portal_address() + storage.portal_address.read_public() } // docs:start:claim_public @@ -51,7 +52,7 @@ contract TokenBridge { context.consume_l1_to_l2_message( content_hash, secret, - context.this_portal_address(), + storage.portal_address.read_public(), message_leaf_index ); @@ -72,7 +73,7 @@ contract TokenBridge { ) { // Send an L2 to L1 message let content = get_withdraw_content_hash(recipient, amount, caller_on_l1); - context.message_portal(context.this_portal_address(), content); + context.message_portal(storage.portal_address.read_public(), content); // Burn tokens Token::at(storage.token.read()).burn_public(context.msg_sender(), amount, nonce).call(&mut context); @@ -92,7 +93,7 @@ contract TokenBridge { context.consume_l1_to_l2_message( content_hash, secret_for_L1_to_L2_message_consumption, - context.this_portal_address() + storage.portal_address.read_private() ); // Mint tokens on L2 @@ -120,7 +121,7 @@ contract TokenBridge { ) { // Send an L2 to L1 message let content = get_withdraw_content_hash(recipient, amount, caller_on_l1); - context.message_portal(context.this_portal_address(), content); + context.message_portal(storage.portal_address.read_private(), content); // docs:start:call_assert_token_is_same // Assert that user provided token address is same as seen in storage. @@ -138,10 +139,12 @@ contract TokenBridge { // View function that is callable by other contracts. // Unconstrained can't be called by others since it isn't safe. + // docs:start:get_token #[aztec(public)] fn get_token() -> AztecAddress { storage.token.read() } + // docs:end:get_token // /// Unconstrained /// @@ -151,13 +154,6 @@ contract TokenBridge { } // docs:end:read_token - #[aztec(public)] - #[aztec(internal)] - #[aztec(noinitcheck)] - fn _initialize(token: AztecAddress) { - storage.token.write(token); - } - // docs:start:call_mint_on_token // This is a public call as we need to read from public storage. // Also, note that user hashes their secret in private and only sends the hash in public diff --git a/noir-projects/noir-contracts/contracts/uniswap_contract/src/main.nr b/noir-projects/noir-contracts/contracts/uniswap_contract/src/main.nr index 35d9e573379..f8227136c67 100644 --- a/noir-projects/noir-contracts/contracts/uniswap_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/uniswap_contract/src/main.nr @@ -5,7 +5,7 @@ mod util; // Has two separate flows for private and public respectively // Uses the token bridge contract, which tells which input token we need to talk to and handles the exit funds to L1 contract Uniswap { - use dep::aztec::prelude::{FunctionSelector, AztecAddress, EthAddress, Map, PublicMutable}; + use dep::aztec::prelude::{FunctionSelector, AztecAddress, EthAddress, Map, PublicMutable, SharedImmutable}; use dep::aztec::context::gas::GasOpts; use dep::authwit::auth::{ @@ -24,9 +24,16 @@ contract Uniswap { // tracks the nonce used to create the approval message for burning funds // gets incremented each time after use to prevent replay attacks nonce_for_burn_approval: PublicMutable, + portal_address: SharedImmutable, } // docs:end:uniswap_setup + #[aztec(public)] + #[aztec(initializer)] + fn constructor(portal_address: EthAddress) { + storage.portal_address.initialize(portal_address); + } + // docs:start:swap_public #[aztec(public)] fn swap_public( @@ -84,7 +91,7 @@ contract Uniswap { secret_hash_for_L1_to_l2_message, caller_on_L1 ); - context.message_portal(context.this_portal_address(), content_hash); + context.message_portal(storage.portal_address.read_public(), content_hash); } // docs:end:swap_public @@ -142,7 +149,7 @@ contract Uniswap { secret_hash_for_L1_to_l2_message, caller_on_L1 ); - context.message_portal(context.this_portal_address(), content_hash); + context.message_portal(storage.portal_address.read_private(), content_hash); } // docs:end:swap_private @@ -197,11 +204,12 @@ contract Uniswap { // increment nonce_for_burn_approval so it won't be used again storage.nonce_for_burn_approval.write(nonce_for_burn_approval + 1); + let this_portal_address = storage.portal_address.read_public(); // Exit to L1 Uniswap Portal ! TokenBridge::at(token_bridge).exit_to_l1_public( - context.this_portal_address(), + this_portal_address, amount, - context.this_portal_address(), + this_portal_address, nonce_for_burn_approval ).call(&mut context) } diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_app_logic.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_app_logic.nr index fe42b435064..f722f087618 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_app_logic.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_app_logic.nr @@ -268,7 +268,7 @@ mod tests { let mut builder = PublicKernelAppLogicCircuitPrivateInputsBuilder::new(); let contract_address = builder.public_call.contract_address; - let portal_contract_address = builder.public_call.portal_contract_address; + let portal_contract_address = EthAddress::from_field(0xdead); // Setup 1 new l2 to l1 message on the previous kernel. let previous = [12345]; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/call_context.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/call_context.nr index 006b805fbc3..72a7a5f9f32 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/call_context.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/call_context.nr @@ -9,7 +9,6 @@ use crate::{ struct CallContext { msg_sender : AztecAddress, storage_contract_address : AztecAddress, - portal_contract_address : EthAddress, function_selector : FunctionSelector, is_delegate_call : bool, @@ -47,7 +46,6 @@ impl Serialize for CallContext { serialized.push(self.msg_sender.to_field()); serialized.push(self.storage_contract_address.to_field()); - serialized.push(self.portal_contract_address.to_field()); serialized.push(self.function_selector.to_field()); serialized.push(self.is_delegate_call as Field); serialized.push(self.is_static_call as Field); @@ -63,7 +61,6 @@ impl Deserialize for CallContext { CallContext { msg_sender: AztecAddress::from_field(reader.read()), storage_contract_address: AztecAddress::from_field(reader.read()), - portal_contract_address: EthAddress::from_field(reader.read()), function_selector: FunctionSelector::from_field(reader.read()), is_delegate_call: reader.read() as bool, is_static_call: reader.read() as bool, @@ -77,7 +74,6 @@ impl Empty for CallContext { CallContext { msg_sender: AztecAddress::empty(), storage_contract_address: AztecAddress::empty(), - portal_contract_address: EthAddress::empty(), function_selector: FunctionSelector::empty(), is_delegate_call: false, is_static_call: false, diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr index 11035fb5580..e3d17abef66 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr @@ -85,6 +85,6 @@ fn empty_hash() { let hash = item.hash(); // Value from private_call_stack_item.test.ts "computes empty item hash" test - let test_data_empty_hash = 0x25d9c6ba3de2cf8baec904e5c1ba76e130c5181bc2d6c4f1ceea4663287ba9ba; + let test_data_empty_hash = 0x138c6ad441864ce43487e99d5e1e122c38b4b55d893edec04a32f5aacecc856c; assert_eq(hash, test_data_empty_hash); } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr index e3331c59c96..fb499f46f0c 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr @@ -211,6 +211,6 @@ fn empty_hash() { let inputs = PrivateCircuitPublicInputs::empty(); let hash = inputs.hash(); // Value from private_circuit_public_inputs.test.ts "computes empty item hash" test - let test_data_empty_hash = 0x0a61fd8a00a3d160e723b316437484bf643f8ed7952031e493717e1f0f1f9345; + let test_data_empty_hash = 0x2517b9a84487bde68e18647e59530c6ffe4a7a88c5c556f013d09fd22b84ba35; assert_eq(hash, test_data_empty_hash); } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel/private_call_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel/private_call_data.nr index 40ffa87a975..21f91844959 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel/private_call_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel/private_call_data.nr @@ -27,6 +27,5 @@ struct PrivateCallData { note_hash_read_request_membership_witnesses: [NoteHashReadRequestMembershipWitness; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL], - portal_contract_address: EthAddress, acir_hash: Field, } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_data.nr index 8d762839c99..2509462b6ce 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_data.nr @@ -8,6 +8,5 @@ struct PublicCallData { call_stack_item: PublicCallStackItem, public_call_stack: [CallRequest; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL], proof: Proof, - portal_contract_address: EthAddress, bytecode_hash: Field, } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_stack_item.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_stack_item.nr index 2ef46661fb1..d176bfa53e1 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_stack_item.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_stack_item.nr @@ -69,7 +69,7 @@ mod tests { let call_stack_item = PublicCallStackItem { contract_address, public_inputs, is_execution_request: true, function_data }; // Value from public_call_stack_item.test.ts "Computes a callstack item request hash" test - let test_data_call_stack_item_request_hash = 0x18e440e4e58ed510c02062986f71ef37ed610fc300b8baab334fd543758b9f11; + let test_data_call_stack_item_request_hash = 0x1b06f4a4960455e9f01c20d4cb01afbf8c8f39eb50094c5d1ad6725ced0f7d08; assert_eq(call_stack_item.hash(), test_data_call_stack_item_request_hash); } @@ -87,7 +87,7 @@ mod tests { let call_stack_item = PublicCallStackItem { contract_address, public_inputs, is_execution_request: false, function_data }; // Value from public_call_stack_item.test.ts "Computes a callstack item hash" test - let test_data_call_stack_item_hash = 0x2bf24099a6954a9bb9be6689fd765366fbb94fb25328d7e3942698ae891bbfad; + let test_data_call_stack_item_hash = 0x1f3f1902ca41ffd6fd7191fa5a52edd677444a9b6ae8f4448336fa71a4b2d5cc; assert_eq(call_stack_item.hash(), test_data_call_stack_item_hash); } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_circuit_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_circuit_public_inputs.nr index af908e1f3c5..154b3e05a77 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_circuit_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_circuit_public_inputs.nr @@ -189,6 +189,6 @@ fn empty_hash() { let hash = inputs.hash(); // Value from public_circuit_public_inputs.test.ts "computes empty item hash" test - let test_data_empty_hash = 0x19eaa0a5aea3d131456d0daffc2d79fd27db9c201e91475ab620801b78504d79; + let test_data_empty_hash = 0x237c89f8b29c3fb169b889940a714b3c72017cb2941d0724d4668a030794d2fb; assert_eq(hash, test_data_empty_hash); } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/address/partial_address.nr b/noir-projects/noir-protocol-circuits/crates/types/src/address/partial_address.nr index 359fae794ba..3829d951a8d 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/address/partial_address.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/address/partial_address.nr @@ -41,12 +41,11 @@ impl PartialAddress { contract_class_id: ContractClassId, salt: Field, initialization_hash: Field, - portal_contract_address: EthAddress, deployer: AztecAddress ) -> Self { PartialAddress::compute_from_salted_initialization_hash( contract_class_id, - SaltedInitializationHash::compute(salt, initialization_hash, portal_contract_address, deployer) + SaltedInitializationHash::compute(salt, initialization_hash, deployer) ) } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/address/salted_initialization_hash.nr b/noir-projects/noir-protocol-circuits/crates/types/src/address/salted_initialization_hash.nr index 88af664b86b..ca916f85ac7 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/address/salted_initialization_hash.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/address/salted_initialization_hash.nr @@ -19,19 +19,13 @@ impl SaltedInitializationHash { Self { inner: field } } - pub fn compute( - salt: Field, - initialization_hash: Field, - portal_contract_address: EthAddress, - deployer: AztecAddress - ) -> Self { + pub fn compute(salt: Field, initialization_hash: Field, deployer: AztecAddress) -> Self { SaltedInitializationHash::from_field( pedersen_hash( [ salt, initialization_hash, - deployer.to_field(), - portal_contract_address.to_field() + deployer.to_field() ], GENERATOR_INDEX__PARTIAL_ADDRESS ) diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr index 7faf3c22c0e..e324d2d231d 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr @@ -126,7 +126,7 @@ global REGISTERER_UNCONSTRAINED_FUNCTION_BROADCASTED_MAGIC_VALUE = 0xe7af8166354 // CONTRACT INSTANCE CONSTANTS // sha224sum 'struct ContractInstanceDeployed' global DEPLOYER_CONTRACT_INSTANCE_DEPLOYED_MAGIC_VALUE = 0x85864497636cf755ae7bde03f267ce01a520981c21c3682aaf82a631; -global DEPLOYER_CONTRACT_ADDRESS = 0x0cde95a10e1160d0ff69ac8212cb5902fa5add38d8596595631fcf3a667798e0; +global DEPLOYER_CONTRACT_ADDRESS = 0x1236d27f14d2934fd666beff34a0b4b746949f5d51a149eb67f908eb95092f54; // GAS DEFAULTS global DEFAULT_GAS_LIMIT: u32 = 1_000_000_000; @@ -139,9 +139,9 @@ global AZTEC_ADDRESS_LENGTH = 1; global GAS_FEES_LENGTH: u64 = 3; global GAS_LENGTH: u64 = 3; global GAS_SETTINGS_LENGTH: u64 = GAS_LENGTH * 2 + GAS_FEES_LENGTH + /* inclusion_fee */ 1; -global CALL_CONTEXT_LENGTH: u64 = 7; +global CALL_CONTEXT_LENGTH: u64 = 6; global CONTENT_COMMITMENT_LENGTH: u64 = 4; -global CONTRACT_INSTANCE_LENGTH: u64 = 6; +global CONTRACT_INSTANCE_LENGTH: u64 = 5; global CONTRACT_STORAGE_READ_LENGTH: u64 = 2; global CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH: u64 = 2; global ETH_ADDRESS_LENGTH = 1; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/contract_instance.nr b/noir-projects/noir-protocol-circuits/crates/types/src/contract_instance.nr index 9e7fc39d8bc..1780cbd12ab 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/contract_instance.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/contract_instance.nr @@ -13,7 +13,6 @@ struct ContractInstance { deployer: AztecAddress, contract_class_id : ContractClassId, initialization_hash : Field, - portal_contract_address : EthAddress, public_keys_hash : PublicKeysHash, } @@ -22,8 +21,7 @@ impl Eq for ContractInstance { self.public_keys_hash.eq(other.public_keys_hash) & self.initialization_hash.eq(other.initialization_hash) & self.contract_class_id.eq(other.contract_class_id) & - self.salt.eq(other.salt) & - self.portal_contract_address.eq(other.portal_contract_address) + self.salt.eq(other.salt) } } @@ -34,7 +32,6 @@ impl Serialize for ContractInstance { self.deployer.to_field(), self.contract_class_id.to_field(), self.initialization_hash, - self.portal_contract_address.to_field(), self.public_keys_hash.to_field() ] } @@ -47,8 +44,7 @@ impl Deserialize for ContractInstance { deployer: AztecAddress::from_field(serialized[1]), contract_class_id: ContractClassId::from_field(serialized[2]), initialization_hash: serialized[3], - portal_contract_address: EthAddress::from_field(serialized[4]), - public_keys_hash: PublicKeysHash::from_field(serialized[5]), + public_keys_hash: PublicKeysHash::from_field(serialized[4]), } } } @@ -67,7 +63,6 @@ impl ContractInstance { self.contract_class_id, self.salt, self.initialization_hash, - self.portal_contract_address, self.deployer ) ) diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures/contracts.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures/contracts.nr index 5a78d4382f6..bc9aec40b02 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures/contracts.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures/contracts.nr @@ -7,7 +7,6 @@ struct ContractData { artifact_hash: Field, contract_address_salt: Field, contract_class_id: ContractClassId, - portal_contract_address: EthAddress, private_functions_root: Field, public_bytecode_commitment: Field, public_keys_hash: PublicKeysHash, @@ -24,7 +23,6 @@ global default_contract = ContractData { private_functions_root: 0x19a3cc0b714976fb35d58b684ba36e86f82bac8b87517904a2727e5113fb4cba, address: AztecAddress { inner: 0x2d941148ee5adeece35991d32acbcf4200742991c61990dee965bedf729d21a9 }, partial_address: PartialAddress { inner: 0x23a6933a485200a8d34b9929d61868c9635793f878d67ce86a1b1355c0ab0d47 }, - portal_contract_address: EthAddress { inner: 0x0000000000000000000000000000000000005ba0 }, contract_class_id: ContractClassId { inner: 0x0ce2a998337b1e6da1ac1d802a8bb9e10b7d705d210e61efb9642855009814a6 }, public_keys_hash: PublicKeysHash { inner: 0x000000000000000000000000000000000000000000000000000000000000b26e }, salted_initialization_hash: SaltedInitializationHash { inner: 0x0b095458845137ebf1e6061c8c0ba1d907241a3b56dc1d3e73d2fea78f04a036 }, @@ -39,7 +37,6 @@ global parent_contract = ContractData { private_functions_root: 0x2c1c949cb226995de94b7b8b5aeaab440739f2dfeb06d358441f60932cf243a7, address: AztecAddress { inner: 0x24692d7dbb532557c7466e8782d1fe99077e4787570414bd1a5e8fa5300caad8 }, partial_address: PartialAddress { inner: 0x127bbd73a3cf497fb2d85342571695d894985b449a9343eec55485e9cbc514f8 }, - portal_contract_address: EthAddress { inner: 0x0000000000000000000000000000000000000913 }, contract_class_id: ContractClassId { inner: 0x1f1f963a350e2c883cc6730c19fc5d5b47a40694d805cbb0720fa76fe295df90 }, public_keys_hash: PublicKeysHash { inner: 0x00000000000000000000000000000000000000000000000000000000000011c1 }, salted_initialization_hash: SaltedInitializationHash { inner: 0x04643e65513869350552499ed3412df59540dffe3cd698203deee8900b53bcec }, diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/private_call_data_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/private_call_data_builder.nr index 47338325790..c9844fd07ab 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/private_call_data_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/private_call_data_builder.nr @@ -34,7 +34,6 @@ struct PrivateCallDataBuilder { contract_class_public_bytecode_commitment: Field, function_leaf_membership_witness: FunctionLeafMembershipWitness, note_hash_read_request_membership_witnesses: BoundedVec, - portal_contract_address: EthAddress, acir_hash: Field, gas_settings: GasSettings, } @@ -62,7 +61,6 @@ impl PrivateCallDataBuilder { contract_class_artifact_hash: contract_data.artifact_hash, contract_class_public_bytecode_commitment: contract_data.public_bytecode_commitment, note_hash_read_request_membership_witnesses: BoundedVec::new(), - portal_contract_address: public_inputs.call_context.portal_contract_address, acir_hash: contract_function.acir_hash, gas_settings: public_inputs.gas_settings } @@ -71,7 +69,6 @@ impl PrivateCallDataBuilder { pub fn is_delegate_call(&mut self) -> Self { self.public_inputs.call_context.is_delegate_call = true; self.public_inputs.call_context.storage_contract_address = fixtures::contracts::parent_contract.address; - self.public_inputs.call_context.portal_contract_address = fixtures::contracts::parent_contract.portal_contract_address; self.public_inputs.call_context.msg_sender = fixtures::MSG_SENDER; *self } @@ -201,7 +198,6 @@ impl PrivateCallDataBuilder { contract_class_artifact_hash: self.contract_class_artifact_hash, contract_class_public_bytecode_commitment: self.contract_class_public_bytecode_commitment, note_hash_read_request_membership_witnesses: self.note_hash_read_request_membership_witnesses.storage, - portal_contract_address: self.portal_contract_address, acir_hash: self.acir_hash } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/private_circuit_public_inputs_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/private_circuit_public_inputs_builder.nr index 61c14a8a5fb..f29d76fceab 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/private_circuit_public_inputs_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/private_circuit_public_inputs_builder.nr @@ -61,7 +61,6 @@ impl PrivateCircuitPublicInputsBuilder { let args_hash = 0; let contract_data = fixtures::contracts::default_contract; - let portal_contract_address = contract_data.portal_contract_address; let contract_function = fixtures::contract_functions::default_private_function; let function_data = contract_function.data; @@ -71,7 +70,6 @@ impl PrivateCircuitPublicInputsBuilder { let call_context = CallContext { msg_sender: fixtures::contracts::parent_contract.address, storage_contract_address: contract_address, - portal_contract_address, function_selector: function_data.selector, is_delegate_call: false, is_static_call: false, diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/public_call_data_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/public_call_data_builder.nr index 6c875c049e3..40c379f0d7c 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/public_call_data_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/public_call_data_builder.nr @@ -21,7 +21,6 @@ struct PublicCallDataBuilder { function_data: FunctionData, public_call_stack: BoundedVec, proof: Proof, - portal_contract_address: EthAddress, bytecode_hash: Field, } @@ -29,7 +28,6 @@ impl PublicCallDataBuilder { pub fn new() -> Self { let contract_data = fixtures::contracts::default_contract; let contract_address = contract_data.address; - let portal_contract_address = contract_data.portal_contract_address; let contract_function = fixtures::contract_functions::default_public_function; let function_data = contract_function.data; @@ -39,7 +37,6 @@ impl PublicCallDataBuilder { public_inputs.call_context = CallContext { msg_sender: fixtures::contracts::parent_contract.address, storage_contract_address: contract_address, - portal_contract_address, function_selector: function_data.selector, is_delegate_call: false, is_static_call: false, @@ -53,7 +50,6 @@ impl PublicCallDataBuilder { function_data, public_call_stack: BoundedVec::new(), proof: Proof {}, - portal_contract_address, bytecode_hash: contract_function.acir_hash } } @@ -61,7 +57,6 @@ impl PublicCallDataBuilder { pub fn is_delegate_call(&mut self) -> Self { self.public_inputs.call_context.is_delegate_call = true; self.public_inputs.call_context.storage_contract_address = fixtures::contracts::parent_contract.address; - self.public_inputs.call_context.portal_contract_address = fixtures::contracts::parent_contract.portal_contract_address; self.public_inputs.call_context.msg_sender = fixtures::MSG_SENDER; *self } @@ -165,7 +160,6 @@ impl PublicCallDataBuilder { }, public_call_stack: self.public_call_stack.storage, proof: self.proof, - portal_contract_address: self.portal_contract_address, bytecode_hash: self.bytecode_hash } } diff --git a/yarn-project/aztec.js/src/contract/contract.ts b/yarn-project/aztec.js/src/contract/contract.ts index 333335a35d2..66c946579c9 100644 --- a/yarn-project/aztec.js/src/contract/contract.ts +++ b/yarn-project/aztec.js/src/contract/contract.ts @@ -19,7 +19,6 @@ export class Contract extends ContractBase { * @param address - The deployed contract's address. * @param artifact - Build artifact of the contract. * @param wallet - The wallet to use when interacting with the contract. - * @param portalContract - The portal contract address on L1, if any. * @returns A promise that resolves to a new Contract instance. */ public static async at(address: AztecAddress, artifact: ContractArtifact, wallet: Wallet): Promise { diff --git a/yarn-project/aztec.js/src/contract/deploy_method.ts b/yarn-project/aztec.js/src/contract/deploy_method.ts index 6c7d632afa9..40fd67bbcf4 100644 --- a/yarn-project/aztec.js/src/contract/deploy_method.ts +++ b/yarn-project/aztec.js/src/contract/deploy_method.ts @@ -6,7 +6,6 @@ import { getContractInstanceFromDeployParams, } from '@aztec/circuits.js'; import { type ContractArtifact, type FunctionArtifact, getInitializer } from '@aztec/foundation/abi'; -import { type EthAddress } from '@aztec/foundation/eth-address'; import { type Fr } from '@aztec/foundation/fields'; import { createDebugLogger } from '@aztec/foundation/log'; import { type ContractInstanceWithAddress } from '@aztec/types/contracts'; @@ -23,11 +22,9 @@ import { DeploySentTx } from './deploy_sent_tx.js'; /** * Options for deploying a contract on the Aztec network. - * Allows specifying a portal contract, contract address salt, and additional send method options. + * Allows specifying a contract address salt, and additional send method options. */ export type DeployOptions = { - /** The Ethereum address of the Portal contract. */ - portalContract?: EthAddress; /** An optional salt value used to deterministically calculate the contract address. */ contractAddressSalt?: Fr; /** Set to true to *not* include the sender in the address computation. */ @@ -76,7 +73,7 @@ export class DeployMethod extends Bas * the transaction for deployment. The resulting signed transaction can be * later sent using the `send()` method. * - * @param options - An object containing optional deployment settings, including portalContract, contractAddressSalt, and from. + * @param options - An object containing optional deployment settings, contractAddressSalt, and from. * @returns A Promise resolving to an object containing the signed transaction data and other relevant information. */ public async create(options: DeployOptions = {}): Promise { @@ -186,7 +183,7 @@ export class DeployMethod extends Bas * This function extends the 'send' method from the ContractFunctionInteraction class, * allowing us to send a transaction specifically for contract deployment. * - * @param options - An object containing various deployment options such as portalContract, contractAddressSalt, and from. + * @param options - An object containing various deployment options such as contractAddressSalt and from. * @returns A SentTx object that returns the receipt and the deployed contract instance. */ public override send(options: DeployOptions = {}): DeploySentTx { @@ -209,7 +206,6 @@ export class DeployMethod extends Bas this.instance = getContractInstanceFromDeployParams(this.artifact, { constructorArgs: this.args, salt: options.contractAddressSalt, - portalAddress: options.portalContract, publicKeysHash: this.publicKeysHash, constructorArtifact: this.constructorArtifact, deployer: options.universalDeploy ? AztecAddress.ZERO : this.wallet.getAddress(), diff --git a/yarn-project/aztec.js/src/deployment/deploy_instance.ts b/yarn-project/aztec.js/src/deployment/deploy_instance.ts index c6ff64a9992..fe8ec9ae42d 100644 --- a/yarn-project/aztec.js/src/deployment/deploy_instance.ts +++ b/yarn-project/aztec.js/src/deployment/deploy_instance.ts @@ -11,7 +11,7 @@ import { getDeployerContract } from './protocol_contracts.js'; */ export function deployInstance(wallet: Wallet, instance: ContractInstanceWithAddress): ContractFunctionInteraction { const deployerContract = getDeployerContract(wallet); - const { salt, contractClassId, portalContractAddress, publicKeysHash, deployer } = instance; + const { salt, contractClassId, publicKeysHash, deployer } = instance; const isUniversalDeploy = deployer.isZero(); if (!isUniversalDeploy && !wallet.getAddress().equals(deployer)) { throw new Error( @@ -22,7 +22,6 @@ export function deployInstance(wallet: Wallet, instance: ContractInstanceWithAdd salt, contractClassId, instance.initializationHash, - portalContractAddress, publicKeysHash, isUniversalDeploy, ); diff --git a/yarn-project/aztec/src/sandbox.ts b/yarn-project/aztec/src/sandbox.ts index 25493c9d5f6..18d2f792c23 100644 --- a/yarn-project/aztec/src/sandbox.ts +++ b/yarn-project/aztec/src/sandbox.ts @@ -1,7 +1,6 @@ #!/usr/bin/env -S node --no-warnings import { type AztecNodeConfig, AztecNodeService, getConfigEnvVars } from '@aztec/aztec-node'; -import { type AztecAddress, BatchCall, SignerlessWallet, type Wallet } from '@aztec/aztec.js'; -import { deployInstance, registerContractClass } from '@aztec/aztec.js/deployment'; +import { type AztecAddress, SignerlessWallet, type Wallet } from '@aztec/aztec.js'; import { DefaultMultiCallEntrypoint } from '@aztec/aztec.js/entrypoint'; import { type AztecNode } from '@aztec/circuit-types'; import { @@ -30,6 +29,7 @@ import { RollupAbi, RollupBytecode, } from '@aztec/l1-artifacts'; +import { GasTokenContract } from '@aztec/noir-contracts.js/GasToken'; import { getCanonicalGasToken } from '@aztec/protocol-contracts/gas-token'; import { type PXEServiceConfig, createPXEService, getPXEServiceConfig } from '@aztec/pxe'; @@ -172,12 +172,15 @@ async function deployCanonicalL2GasToken(deployer: Wallet, l1ContractAddresses: return; } - const batch = new BatchCall(deployer, [ - (await registerContractClass(deployer, canonicalGasToken.artifact)).request(), - deployInstance(deployer, canonicalGasToken.instance).request(), - ]); + const gasToken = await GasTokenContract.deploy(deployer, gasPortalAddress) + .send({ contractAddressSalt: canonicalGasToken.instance.salt, universalDeploy: true }) + .deployed(); - await batch.send().wait(); + if (gasToken.address !== canonicalGasToken.address) { + throw new Error( + `Deployed Gas Token address ${gasToken.address} does not match expected address ${canonicalGasToken.address}`, + ); + } logger.info(`Deployed Gas Token on L2 at ${canonicalGasToken.address}`); } diff --git a/yarn-project/circuit-types/src/interfaces/pxe.ts b/yarn-project/circuit-types/src/interfaces/pxe.ts index 0eba3e00512..87081769ed8 100644 --- a/yarn-project/circuit-types/src/interfaces/pxe.ts +++ b/yarn-project/circuit-types/src/interfaces/pxe.ts @@ -300,7 +300,7 @@ export interface PXE { getSyncStatus(): Promise; /** - * Returns a Contact Instance given its address, which includes the contract class identifier, portal address, + * Returns a Contact Instance given its address, which includes the contract class identifier, * initialization hash, deployment salt, and public keys hash. * TODO(@spalladino): Should we return the public keys in plain as well here? * @param address - Deployment address of the contract. diff --git a/yarn-project/circuits.js/src/constants.gen.ts b/yarn-project/circuits.js/src/constants.gen.ts index 4a8b78294c1..1ebe97036c4 100644 --- a/yarn-project/circuits.js/src/constants.gen.ts +++ b/yarn-project/circuits.js/src/constants.gen.ts @@ -74,7 +74,7 @@ export const REGISTERER_UNCONSTRAINED_FUNCTION_BROADCASTED_MAGIC_VALUE = 0xe7af816635466f128568edb04c9fa024f6c87fb9010fdbffa68b3d99n; export const DEPLOYER_CONTRACT_INSTANCE_DEPLOYED_MAGIC_VALUE = 0x85864497636cf755ae7bde03f267ce01a520981c21c3682aaf82a631n; -export const DEPLOYER_CONTRACT_ADDRESS = 0x0cde95a10e1160d0ff69ac8212cb5902fa5add38d8596595631fcf3a667798e0n; +export const DEPLOYER_CONTRACT_ADDRESS = 0x1236d27f14d2934fd666beff34a0b4b746949f5d51a149eb67f908eb95092f54n; export const DEFAULT_GAS_LIMIT = 1_000_000_000; export const DEFAULT_TEARDOWN_GAS_LIMIT = 100_000_000; export const DEFAULT_MAX_FEE_PER_GAS = 10; @@ -83,9 +83,9 @@ export const AZTEC_ADDRESS_LENGTH = 1; export const GAS_FEES_LENGTH = 3; export const GAS_LENGTH = 3; export const GAS_SETTINGS_LENGTH = GAS_LENGTH * 2 + GAS_FEES_LENGTH + /* inclusion_fee */ 1; -export const CALL_CONTEXT_LENGTH = 7; +export const CALL_CONTEXT_LENGTH = 6; export const CONTENT_COMMITMENT_LENGTH = 4; -export const CONTRACT_INSTANCE_LENGTH = 6; +export const CONTRACT_INSTANCE_LENGTH = 5; export const CONTRACT_STORAGE_READ_LENGTH = 2; export const CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH = 2; export const ETH_ADDRESS_LENGTH = 1; diff --git a/yarn-project/circuits.js/src/contract/__snapshots__/contract_address.test.ts.snap b/yarn-project/circuits.js/src/contract/__snapshots__/contract_address.test.ts.snap index ee1d1bf8cb9..dc6ef757820 100644 --- a/yarn-project/circuits.js/src/contract/__snapshots__/contract_address.test.ts.snap +++ b/yarn-project/circuits.js/src/contract/__snapshots__/contract_address.test.ts.snap @@ -4,10 +4,10 @@ exports[`ContractAddress Address from partial matches Noir 1`] = `"0x1b6ead051e7 exports[`ContractAddress Public key hash matches Noir 1`] = `"0x22d83a089d7650514c2de24cd30185a414d943eaa19817c67bffe2c3183006a3"`; -exports[`ContractAddress computeContractAddressFromInstance 1`] = `"0x1b61d59f21fcb9653c56b86f5e45f2d0b69dcbb7efebfbcda6f53eb7abaaa4eb"`; +exports[`ContractAddress computeContractAddressFromInstance 1`] = `"0x0bed63221d281713007bfb0c063e1f61d0646404fb3701b99bb92f41b6390604"`; exports[`ContractAddress computeInitializationHash 1`] = `Fr<0x109865e4b959adba34b722e72a69baaf9ee78e31bb1042318f0d91006ed86780>`; exports[`ContractAddress computePartialAddress 1`] = `Fr<0x1923a6246e305720b6aaf751fde0342613e93c82e455c3831e28375c16dd40d8>`; -exports[`ContractAddress computeSaltedInitializationHash 1`] = `Fr<0x25e70e2b5cf1171b74aa1ab4bf1973859a65949a4c83a5365d71434d2062b2b4>`; +exports[`ContractAddress computeSaltedInitializationHash 1`] = `Fr<0x15cf30c8f37df5115e0cafbccce8f46a86e5e76487d7d9be48e0fd641c46e77c>`; diff --git a/yarn-project/circuits.js/src/contract/contract_address.test.ts b/yarn-project/circuits.js/src/contract/contract_address.test.ts index 7551c55394a..6199e69a25d 100644 --- a/yarn-project/circuits.js/src/contract/contract_address.test.ts +++ b/yarn-project/circuits.js/src/contract/contract_address.test.ts @@ -2,7 +2,7 @@ import { ABIParameterVisibility, type FunctionAbi, FunctionType } from '@aztec/f import { Fr } from '@aztec/foundation/fields'; import { setupCustomSnapshotSerializers, updateInlineTestData } from '@aztec/foundation/testing'; -import { AztecAddress, EthAddress, deriveKeys } from '../index.js'; +import { AztecAddress, deriveKeys } from '../index.js'; import { computeContractAddressFromInstance, computeContractAddressFromPartial, @@ -26,7 +26,6 @@ describe('ContractAddress', () => { const mockInstance = { initializationHash: new Fr(1), salt: new Fr(2), - portalContractAddress: EthAddress.fromField(new Fr(3)), deployer: AztecAddress.fromField(new Fr(4)), }; const result = computeSaltedInitializationHash(mockInstance); @@ -57,7 +56,6 @@ describe('ContractAddress', () => { const salt = new Fr(3n); const contractClassId = new Fr(4n); const initializationHash = new Fr(5n); - const portalContractAddress = EthAddress.fromField(new Fr(6n)); const deployer = AztecAddress.fromField(new Fr(7)); const publicKeysHash = deriveKeys(secretKey).publicKeysHash; @@ -66,7 +64,6 @@ describe('ContractAddress', () => { salt, contractClassId, initializationHash, - portalContractAddress, deployer, version: 1, }).toString(); diff --git a/yarn-project/circuits.js/src/contract/contract_address.ts b/yarn-project/circuits.js/src/contract/contract_address.ts index 11a58dbf24a..11c4dade226 100644 --- a/yarn-project/circuits.js/src/contract/contract_address.ts +++ b/yarn-project/circuits.js/src/contract/contract_address.ts @@ -13,7 +13,7 @@ import { deriveKeys } from '../keys/index.js'; /** * Returns the deployment address for a given contract instance as defined on the [Protocol Specs](../../../../docs/docs/protocol-specs/addresses-and-keys/specification.md). * ``` - * salted_initialization_hash = pedersen([salt, initialization_hash, deployer, portal_contract_address as Field], GENERATOR__SALTED_INITIALIZATION_HASH) + * salted_initialization_hash = pedersen([salt, initialization_hash, deployer], GENERATOR__SALTED_INITIALIZATION_HASH) * partial_address = pedersen([contract_class_id, salted_initialization_hash], GENERATOR__CONTRACT_PARTIAL_ADDRESS_V1) * address = poseidon2Hash([public_keys_hash, partial_address, GENERATOR__CONTRACT_ADDRESS_V1]) * ``` @@ -35,7 +35,7 @@ export function computeContractAddressFromInstance( */ export function computePartialAddress( instance: - | Pick + | Pick | { contractClassId: Fr; saltedInitializationHash: Fr }, ): Fr { const saltedInitializationHash = @@ -47,16 +47,13 @@ export function computePartialAddress( } /** - * Computes the salted initialization hash for an address, defined as the hash of the salt, initialization hash, and portal address. + * Computes the salted initialization hash for an address, defined as the hash of the salt and initialization hash. * @param instance - Contract instance for which to compute the salted initialization hash. */ export function computeSaltedInitializationHash( - instance: Pick, + instance: Pick, ): Fr { - return pedersenHash( - [instance.salt, instance.initializationHash, instance.deployer, instance.portalContractAddress], - GeneratorIndex.PARTIAL_ADDRESS, - ); + return pedersenHash([instance.salt, instance.initializationHash, instance.deployer], GeneratorIndex.PARTIAL_ADDRESS); } /** diff --git a/yarn-project/circuits.js/src/contract/contract_instance.ts b/yarn-project/circuits.js/src/contract/contract_instance.ts index 3a300c06dcd..1d45791cdab 100644 --- a/yarn-project/circuits.js/src/contract/contract_instance.ts +++ b/yarn-project/circuits.js/src/contract/contract_instance.ts @@ -1,6 +1,5 @@ import { type ContractArtifact, type FunctionArtifact, getDefaultInitializer } from '@aztec/foundation/abi'; import { AztecAddress } from '@aztec/foundation/aztec-address'; -import { EthAddress } from '@aztec/foundation/eth-address'; import { Fr } from '@aztec/foundation/fields'; import { type ContractInstance, type ContractInstanceWithAddress } from '@aztec/types/contracts'; @@ -21,13 +20,11 @@ export function getContractInstanceFromDeployParams( constructorArgs?: any[]; salt?: Fr; publicKeysHash?: Fr; - portalAddress?: EthAddress; deployer?: AztecAddress; }, ): ContractInstanceWithAddress { const args = opts.constructorArgs ?? []; const salt = opts.salt ?? Fr.random(); - const portalContractAddress = opts.portalAddress ?? EthAddress.ZERO; const constructorArtifact = getConstructorArtifact(artifact, opts.constructorArtifact); const deployer = opts.deployer ?? AztecAddress.ZERO; @@ -39,7 +36,6 @@ export function getContractInstanceFromDeployParams( const instance: ContractInstance = { contractClassId, initializationHash, - portalContractAddress, publicKeysHash, salt, deployer, diff --git a/yarn-project/circuits.js/src/contract/events/contract_instance_deployed_event.ts b/yarn-project/circuits.js/src/contract/events/contract_instance_deployed_event.ts index 19de6205fc6..95376bcd588 100644 --- a/yarn-project/circuits.js/src/contract/events/contract_instance_deployed_event.ts +++ b/yarn-project/circuits.js/src/contract/events/contract_instance_deployed_event.ts @@ -1,6 +1,5 @@ import { AztecAddress } from '@aztec/foundation/aztec-address'; import { toBigIntBE } from '@aztec/foundation/bigint-buffer'; -import { EthAddress } from '@aztec/foundation/eth-address'; import { Fr } from '@aztec/foundation/fields'; import { BufferReader } from '@aztec/foundation/serialize'; import { type ContractInstanceWithAddress } from '@aztec/types/contracts'; @@ -15,7 +14,6 @@ export class ContractInstanceDeployedEvent { public readonly salt: Fr, public readonly contractClassId: Fr, public readonly initializationHash: Fr, - public readonly portalContractAddress: EthAddress, public readonly publicKeysHash: Fr, public readonly deployer: AztecAddress, ) {} @@ -42,7 +40,6 @@ export class ContractInstanceDeployedEvent { const salt = reader.readObject(Fr); const contractClassId = reader.readObject(Fr); const initializationHash = reader.readObject(Fr); - const portalContractAddress = EthAddress.fromField(reader.readObject(Fr)); const publicKeysHash = reader.readObject(Fr); const deployer = reader.readObject(AztecAddress); @@ -52,7 +49,6 @@ export class ContractInstanceDeployedEvent { salt, contractClassId, initializationHash, - portalContractAddress, publicKeysHash, deployer, ); @@ -68,7 +64,6 @@ export class ContractInstanceDeployedEvent { version: this.version, contractClassId: this.contractClassId, initializationHash: this.initializationHash, - portalContractAddress: this.portalContractAddress, publicKeysHash: this.publicKeysHash, salt: this.salt, deployer: this.deployer, diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/private_call_stack_item.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/private_call_stack_item.test.ts.snap index 7e5834b450f..b8e9c3e8a75 100644 --- a/yarn-project/circuits.js/src/structs/__snapshots__/private_call_stack_item.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/__snapshots__/private_call_stack_item.test.ts.snap @@ -1,5 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`PrivateCallStackItem computes empty item hash 1`] = `Fr<0x25d9c6ba3de2cf8baec904e5c1ba76e130c5181bc2d6c4f1ceea4663287ba9ba>`; +exports[`PrivateCallStackItem computes empty item hash 1`] = `Fr<0x138c6ad441864ce43487e99d5e1e122c38b4b55d893edec04a32f5aacecc856c>`; -exports[`PrivateCallStackItem computes hash 1`] = `Fr<0x1b183e4ba97199f9b205f7748e363d628a8624156f95ebf306c5da1925a79ddc>`; +exports[`PrivateCallStackItem computes hash 1`] = `Fr<0x05d108b08c41f27b8cd03753347993a77a0e7637ed2afdd03c3813ab92bfbb78>`; diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/private_circuit_public_inputs.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/private_circuit_public_inputs.test.ts.snap index 65fa6ed6f6c..befc50ad5fc 100644 --- a/yarn-project/circuits.js/src/structs/__snapshots__/private_circuit_public_inputs.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/__snapshots__/private_circuit_public_inputs.test.ts.snap @@ -1,5 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`PrivateCircuitPublicInputs computes empty inputs hash 1`] = `Fr<0x0a61fd8a00a3d160e723b316437484bf643f8ed7952031e493717e1f0f1f9345>`; +exports[`PrivateCircuitPublicInputs computes empty inputs hash 1`] = `Fr<0x2517b9a84487bde68e18647e59530c6ffe4a7a88c5c556f013d09fd22b84ba35>`; -exports[`PrivateCircuitPublicInputs hash matches snapshot 1`] = `Fr<0x16cda30b8402ab87d4892f801a91868ec9571748441c6e4abc796d17418bd1cc>`; +exports[`PrivateCircuitPublicInputs hash matches snapshot 1`] = `Fr<0x0edeaf808ed3d5e61d2fffa2bf089f9e9109eba5c5d42d3523b5470734d56347>`; diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/public_call_stack_item.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/public_call_stack_item.test.ts.snap index 117139972e0..18794323156 100644 --- a/yarn-project/circuits.js/src/structs/__snapshots__/public_call_stack_item.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/__snapshots__/public_call_stack_item.test.ts.snap @@ -1,9 +1,9 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`PublicCallStackItem Computes a callstack item hash 1`] = `"0x2bf24099a6954a9bb9be6689fd765366fbb94fb25328d7e3942698ae891bbfad"`; +exports[`PublicCallStackItem Computes a callstack item hash 1`] = `"0x1f3f1902ca41ffd6fd7191fa5a52edd677444a9b6ae8f4448336fa71a4b2d5cc"`; -exports[`PublicCallStackItem Computes a callstack item request hash 1`] = `"0x18e440e4e58ed510c02062986f71ef37ed610fc300b8baab334fd543758b9f11"`; +exports[`PublicCallStackItem Computes a callstack item request hash 1`] = `"0x1b06f4a4960455e9f01c20d4cb01afbf8c8f39eb50094c5d1ad6725ced0f7d08"`; -exports[`PublicCallStackItem computes empty item hash 1`] = `Fr<0x14d45139af9cc8f9a5a8537de0615a093ec755974d3460ce921eb78f9a533863>`; +exports[`PublicCallStackItem computes empty item hash 1`] = `Fr<0x040c3667dd703bad4465ba5d12e7a422959395f76299794aa9eeaf5044d9e157>`; -exports[`PublicCallStackItem computes hash 1`] = `Fr<0x15fd7b945b88bba32060703eee30a4db98c35b291c5c0c211c03cd4a77436953>`; +exports[`PublicCallStackItem computes hash 1`] = `Fr<0x0f3fde3c615e9d95337fbbf3f835b3e26187de0de9f199320b53355f4089bb88>`; diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/public_circuit_public_inputs.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/public_circuit_public_inputs.test.ts.snap index ed74b387c27..55e7a236787 100644 --- a/yarn-project/circuits.js/src/structs/__snapshots__/public_circuit_public_inputs.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/__snapshots__/public_circuit_public_inputs.test.ts.snap @@ -1,5 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`PublicCircuitPublicInputs computes empty inputs hash 1`] = `Fr<0x19eaa0a5aea3d131456d0daffc2d79fd27db9c201e91475ab620801b78504d79>`; +exports[`PublicCircuitPublicInputs computes empty inputs hash 1`] = `Fr<0x237c89f8b29c3fb169b889940a714b3c72017cb2941d0724d4668a030794d2fb>`; -exports[`PublicCircuitPublicInputs hash matches snapshot 1`] = `Fr<0x090fe4de8ca3cb2395490ef4e8e3ca0fc722168719726cdf7ee6999de3295767>`; +exports[`PublicCircuitPublicInputs hash matches snapshot 1`] = `Fr<0x0d22cf387fb73386318033d92d07d203ad5c3d1e332734fa58b9ec08fbf0ceac>`; diff --git a/yarn-project/circuits.js/src/structs/call_context.ts b/yarn-project/circuits.js/src/structs/call_context.ts index 68aaaa99c1a..556c2b97461 100644 --- a/yarn-project/circuits.js/src/structs/call_context.ts +++ b/yarn-project/circuits.js/src/structs/call_context.ts @@ -1,6 +1,5 @@ import { FunctionSelector } from '@aztec/foundation/abi'; import { AztecAddress } from '@aztec/foundation/aztec-address'; -import { EthAddress } from '@aztec/foundation/eth-address'; import { Fr } from '@aztec/foundation/fields'; import { BufferReader, FieldReader, serializeToBuffer, serializeToFields } from '@aztec/foundation/serialize'; import { type FieldsOf } from '@aztec/foundation/types'; @@ -22,10 +21,6 @@ export class CallContext { * modified. */ public storageContractAddress: AztecAddress, - /** - * Address of the portal contract to the storage contract. - */ - public portalContractAddress: EthAddress, /** * Function selector of the function being called. */ @@ -45,28 +40,16 @@ export class CallContext { ) {} /** - * Returns a new instance of CallContext with zero msg sender, storage contract address and portal contract address. - * @returns A new instance of CallContext with zero msg sender, storage contract address and portal contract address. + * Returns a new instance of CallContext with zero msg sender, storage contract address. + * @returns A new instance of CallContext with zero msg sender, storage contract address. */ public static empty(): CallContext { - return new CallContext( - AztecAddress.ZERO, - AztecAddress.ZERO, - EthAddress.ZERO, - FunctionSelector.empty(), - false, - false, - 0, - ); + return new CallContext(AztecAddress.ZERO, AztecAddress.ZERO, FunctionSelector.empty(), false, false, 0); } isEmpty() { return ( - this.msgSender.isZero() && - this.storageContractAddress.isZero() && - this.portalContractAddress.isZero() && - this.functionSelector.isEmpty() && - Fr.ZERO + this.msgSender.isZero() && this.storageContractAddress.isZero() && this.functionSelector.isEmpty() && Fr.ZERO ); } @@ -78,7 +61,6 @@ export class CallContext { return [ fields.msgSender, fields.storageContractAddress, - fields.portalContractAddress, fields.functionSelector, fields.isDelegateCall, fields.isStaticCall, @@ -114,7 +96,6 @@ export class CallContext { return new CallContext( reader.readObject(AztecAddress), reader.readObject(AztecAddress), - reader.readObject(EthAddress), reader.readObject(FunctionSelector), reader.readBoolean(), reader.readBoolean(), @@ -127,7 +108,6 @@ export class CallContext { return new CallContext( reader.readObject(AztecAddress), reader.readObject(AztecAddress), - reader.readObject(EthAddress), reader.readObject(FunctionSelector), reader.readBoolean(), reader.readBoolean(), @@ -139,7 +119,6 @@ export class CallContext { return ( callContext.msgSender.equals(this.msgSender) && callContext.storageContractAddress.equals(this.storageContractAddress) && - callContext.portalContractAddress.equals(this.portalContractAddress) && callContext.functionSelector.equals(this.functionSelector) && callContext.isDelegateCall === this.isDelegateCall && callContext.isStaticCall === this.isStaticCall && diff --git a/yarn-project/circuits.js/src/structs/kernel/private_call_data.ts b/yarn-project/circuits.js/src/structs/kernel/private_call_data.ts index 7026461a997..475b927725c 100644 --- a/yarn-project/circuits.js/src/structs/kernel/private_call_data.ts +++ b/yarn-project/circuits.js/src/structs/kernel/private_call_data.ts @@ -67,10 +67,6 @@ export class PrivateCallData { NoteHashReadRequestMembershipWitness, typeof MAX_NOTE_HASH_READ_REQUESTS_PER_CALL >, - /** - * The address of the portal contract corresponding to the contract on which the function is being invoked. - */ - public portalContractAddress: Fr, /** * The hash of the ACIR of the function being invoked. */ @@ -95,7 +91,6 @@ export class PrivateCallData { fields.saltedInitializationHash, fields.functionLeafMembershipWitness, fields.noteHashReadRequestMembershipWitnesses, - fields.portalContractAddress, fields.acirHash, ] as const; } @@ -132,7 +127,6 @@ export class PrivateCallData { reader.readObject(MembershipWitness.deserializer(FUNCTION_TREE_HEIGHT)), reader.readArray(MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, NoteHashReadRequestMembershipWitness), reader.readObject(Fr), - reader.readObject(Fr), ); } } diff --git a/yarn-project/circuits.js/src/structs/kernel/public_call_data.ts b/yarn-project/circuits.js/src/structs/kernel/public_call_data.ts index 249bd3fa1a8..3afdf41d3c7 100644 --- a/yarn-project/circuits.js/src/structs/kernel/public_call_data.ts +++ b/yarn-project/circuits.js/src/structs/kernel/public_call_data.ts @@ -23,10 +23,6 @@ export class PublicCallData { * Proof of the call stack item execution. */ public readonly proof: Proof, - /** - * Address of the corresponding portal contract. - */ - public readonly portalContractAddress: Fr, /** * Hash of the L2 contract bytecode. */ @@ -34,13 +30,7 @@ export class PublicCallData { ) {} toBuffer() { - return serializeToBuffer( - this.callStackItem, - this.publicCallStack, - this.proof, - this.portalContractAddress, - this.bytecodeHash, - ); + return serializeToBuffer(this.callStackItem, this.publicCallStack, this.proof, this.bytecodeHash); } static fromBuffer(buffer: BufferReader | Buffer) { @@ -53,7 +43,6 @@ export class PublicCallData { ), reader.readObject(Proof), reader.readObject(Fr), - reader.readObject(Fr), ); } } diff --git a/yarn-project/circuits.js/src/tests/factories.ts b/yarn-project/circuits.js/src/tests/factories.ts index ead75b997c1..c6a1a81b2ef 100644 --- a/yarn-project/circuits.js/src/tests/factories.ts +++ b/yarn-project/circuits.js/src/tests/factories.ts @@ -404,7 +404,6 @@ export function makeCallContext(seed = 0, overrides: Partial { }); it('mint u128', async () => { - // @todo @LHerskind this one don't make sense. It fails because of total supply overflowing. const amount = 2n ** 128n - tokenSim.balanceOfPrivate(wallets[0].getAddress()); expect(amount).toBeLessThan(2n ** 128n); await expect(asset.methods.mint_private(amount, secretHash).prove()).rejects.toThrow(U128_OVERFLOW_ERROR); diff --git a/yarn-project/end-to-end/src/e2e_fees.test.ts b/yarn-project/end-to-end/src/e2e_fees.test.ts index e22cd633fd4..1d4ecce5e3d 100644 --- a/yarn-project/end-to-end/src/e2e_fees.test.ts +++ b/yarn-project/end-to-end/src/e2e_fees.test.ts @@ -647,6 +647,7 @@ describe('e2e_fees', () => { // Mint bananas privately const secret = Fr.random(); const secretHash = computeMessageSecretHash(secret); + logger.debug(`Minting ${amount} bananas privately for ${address} with secret ${secretHash.toString()}`); const receipt = await bananaCoin.methods.mint_private(amount, secretHash).send().wait(); // Setup auth wit diff --git a/yarn-project/end-to-end/src/fixtures/utils.ts b/yarn-project/end-to-end/src/fixtures/utils.ts index fd42cf1e688..802f3925c9d 100644 --- a/yarn-project/end-to-end/src/fixtures/utils.ts +++ b/yarn-project/end-to-end/src/fixtures/utils.ts @@ -46,6 +46,7 @@ import { RollupAbi, RollupBytecode, } from '@aztec/l1-artifacts'; +import { GasTokenContract } from '@aztec/noir-contracts.js/GasToken'; import { getCanonicalGasToken, getCanonicalGasTokenAddress } from '@aztec/protocol-contracts/gas-token'; import { PXEService, type PXEServiceConfig, createPXEService, getPXEServiceConfig } from '@aztec/pxe'; import { type SequencerClient } from '@aztec/sequencer-client'; @@ -577,13 +578,11 @@ export async function deployCanonicalGasToken(deployer: Wallet) { return; } - await new BatchCall(deployer, [ - (await registerContractClass(deployer, canonicalGasToken.artifact)).request(), - deployInstance(deployer, canonicalGasToken.instance).request(), - ]) - .send() - .wait(); + const gasToken = await GasTokenContract.deploy(deployer, gasPortalAddress) + .send({ contractAddressSalt: canonicalGasToken.instance.salt, universalDeploy: true }) + .deployed(); - await expect(deployer.isContractClassPubliclyRegistered(canonicalGasToken.contractClass.id)).resolves.toBe(true); - await expect(deployer.getContractInstance(canonicalGasToken.instance.address)).resolves.toBeDefined(); + await expect(deployer.isContractClassPubliclyRegistered(gasToken.instance.contractClassId)).resolves.toBe(true); + await expect(deployer.getContractInstance(gasToken.address)).resolves.toBeDefined(); + await expect(deployer.isContractPubliclyDeployed(gasToken.address)).resolves.toBe(true); } diff --git a/yarn-project/end-to-end/src/flakey_e2e_deploy_contract/contract_class_registration.test.ts b/yarn-project/end-to-end/src/flakey_e2e_deploy_contract/contract_class_registration.test.ts index 7c723d2ad0b..5c6d418a535 100644 --- a/yarn-project/end-to-end/src/flakey_e2e_deploy_contract/contract_class_registration.test.ts +++ b/yarn-project/end-to-end/src/flakey_e2e_deploy_contract/contract_class_registration.test.ts @@ -5,7 +5,6 @@ import { type ContractClassWithId, type ContractInstanceWithAddress, type DebugLogger, - EthAddress, Fr, type PXE, TxStatus, @@ -96,13 +95,11 @@ describe('e2e_deploy_contract contract class registration', () => { const deployInstance = async (opts: { constructorName?: string; deployer?: AztecAddress } = {}) => { const initArgs = [wallet.getAddress(), 42] as StatefulContractCtorArgs; const salt = Fr.random(); - const portalAddress = EthAddress.random(); const publicKeysHash = Fr.random(); const instance = getContractInstanceFromDeployParams(artifact, { constructorArgs: initArgs, salt, publicKeysHash, - portalAddress, constructorArtifact: opts.constructorName, deployer: opts.deployer, }); @@ -122,7 +119,6 @@ describe('e2e_deploy_contract contract class registration', () => { const registered = await t.registerContract(wallet, StatefulTestContract, { constructorName: opts.constructorName, salt: instance.salt, - portalAddress: instance.portalContractAddress, publicKeysHash, initArgs, deployer: opts.deployer, @@ -143,7 +139,6 @@ describe('e2e_deploy_contract contract class registration', () => { expect(deployed!.address).toEqual(instance.address); expect(deployed!.contractClassId).toEqual(contractClass.id); expect(deployed!.initializationHash).toEqual(instance.initializationHash); - expect(deployed!.portalContractAddress).toEqual(instance.portalContractAddress); expect(deployed!.publicKeysHash).toEqual(instance.publicKeysHash); expect(deployed!.salt).toEqual(instance.salt); expect(deployed!.deployer).toEqual(instance.deployer); diff --git a/yarn-project/end-to-end/src/flakey_e2e_deploy_contract/deploy_test.ts b/yarn-project/end-to-end/src/flakey_e2e_deploy_contract/deploy_test.ts index cb659cf3695..cc44a09b51f 100644 --- a/yarn-project/end-to-end/src/flakey_e2e_deploy_contract/deploy_test.ts +++ b/yarn-project/end-to-end/src/flakey_e2e_deploy_contract/deploy_test.ts @@ -7,7 +7,6 @@ import { type ContractArtifact, type ContractBase, type DebugLogger, - type EthAddress, type Fr, type PXE, type Wallet, @@ -64,19 +63,17 @@ export class DeployTest { opts: { salt?: Fr; publicKeysHash?: Fr; - portalAddress?: EthAddress; initArgs?: any[]; constructorName?: string; deployer?: AztecAddress; } = {}, ): Promise { - const { salt, publicKeysHash, portalAddress, initArgs, constructorName, deployer } = opts; + const { salt, publicKeysHash, initArgs, constructorName, deployer } = opts; const instance = getContractInstanceFromDeployParams(contractArtifact.artifact, { constructorArgs: initArgs ?? [], constructorArtifact: constructorName, salt, publicKeysHash, - portalAddress, deployer, }); await wallet.registerContract({ artifact: contractArtifact.artifact, instance }); diff --git a/yarn-project/end-to-end/src/flakey_e2e_deploy_contract/legacy.test.ts b/yarn-project/end-to-end/src/flakey_e2e_deploy_contract/legacy.test.ts index ae9e823f52f..8dda2e91815 100644 --- a/yarn-project/end-to-end/src/flakey_e2e_deploy_contract/legacy.test.ts +++ b/yarn-project/end-to-end/src/flakey_e2e_deploy_contract/legacy.test.ts @@ -2,7 +2,6 @@ import { AztecAddress, ContractDeployer, type DebugLogger, - EthAddress, Fr, type PXE, TxStatus, @@ -85,18 +84,6 @@ describe('e2e_deploy_contract legacy', () => { await expect(deployer.deploy().send({ contractAddressSalt }).wait()).rejects.toThrow(/dropped/); }, 60_000); - it('should deploy a contract connected to a portal contract', async () => { - const deployer = new ContractDeployer(TestContractArtifact, wallet); - const portalContract = EthAddress.random(); - - // ContractDeployer was instantiated with wallet so we don't have to pass it to wait(...) - const receipt = await deployer.deploy().send({ portalContract }).wait(); - const address = receipt.contract.address; - - const expectedPortal = portalContract.toString(); - expect((await pxe.getContractInstance(address))?.portalContractAddress.toString()).toEqual(expectedPortal); - }, 60_000); - it('should not deploy a contract which failed the public part of the execution', async () => { // This test requires at least another good transaction to go through in the same block as the bad one. const artifact = TokenContractArtifact; diff --git a/yarn-project/end-to-end/src/flakey_e2e_deploy_contract/private_initialization.test.ts b/yarn-project/end-to-end/src/flakey_e2e_deploy_contract/private_initialization.test.ts index 5a2883f112a..7ea721c21dd 100644 --- a/yarn-project/end-to-end/src/flakey_e2e_deploy_contract/private_initialization.test.ts +++ b/yarn-project/end-to-end/src/flakey_e2e_deploy_contract/private_initialization.test.ts @@ -57,11 +57,11 @@ describe('e2e_deploy_contract private initialization', () => { // Tests privately initializing multiple undeployed contracts on the same tx through an account contract. it('initializes multiple undeployed contracts in a single tx', async () => { const owner = await t.registerRandomAccount(); - const initArgss: StatefulContractCtorArgs[] = [42, 52].map(value => [owner, value]); + const initArgs: StatefulContractCtorArgs[] = [42, 52].map(value => [owner, value]); const contracts = await Promise.all( - initArgss.map(initArgs => t.registerContract(wallet, StatefulTestContract, { initArgs })), + initArgs.map(initArgs => t.registerContract(wallet, StatefulTestContract, { initArgs })), ); - const calls = contracts.map((c, i) => c.methods.constructor(...initArgss[i]).request()); + const calls = contracts.map((c, i) => c.methods.constructor(...initArgs[i]).request()); await new BatchCall(wallet, calls).send().wait(); expect(await contracts[0].methods.summed_values(owner).simulate()).toEqual(42n); expect(await contracts[1].methods.summed_values(owner).simulate()).toEqual(52n); diff --git a/yarn-project/end-to-end/src/shared/cross_chain_test_harness.ts b/yarn-project/end-to-end/src/shared/cross_chain_test_harness.ts index 63975935c91..5da650d74d4 100644 --- a/yarn-project/end-to-end/src/shared/cross_chain_test_harness.ts +++ b/yarn-project/end-to-end/src/shared/cross_chain_test_harness.ts @@ -101,9 +101,7 @@ export async function deployAndInitializeTokenAndBridgeContracts( const token = await TokenContract.deploy(wallet, owner, 'TokenName', 'TokenSymbol', 18).send().deployed(); // deploy l2 token bridge and attach to the portal - const bridge = await TokenBridgeContract.deploy(wallet, token.address) - .send({ portalContract: tokenPortalAddress }) - .deployed(); + const bridge = await TokenBridgeContract.deploy(wallet, token.address, tokenPortalAddress).send().deployed(); if ((await token.methods.admin().simulate()) !== owner.toBigInt()) { throw new Error(`Token admin is not ${owner}`); diff --git a/yarn-project/end-to-end/src/shared/gas_portal_test_harness.ts b/yarn-project/end-to-end/src/shared/gas_portal_test_harness.ts index fbc95e97416..ff3a4dc4389 100644 --- a/yarn-project/end-to-end/src/shared/gas_portal_test_harness.ts +++ b/yarn-project/end-to-end/src/shared/gas_portal_test_harness.ts @@ -43,7 +43,8 @@ export class GasPortalTestingHarnessFactory { private async createMock() { const wallet = this.config.wallet; - const gasL2 = await GasTokenContract.deploy(wallet) + // In this case we are not using a portal we just yolo it. + const gasL2 = await GasTokenContract.deploy(wallet, EthAddress.ZERO) .send({ contractAddressSalt: getCanonicalGasToken(EthAddress.ZERO).instance.salt, }) diff --git a/yarn-project/end-to-end/src/shared/uniswap_l1_l2.ts b/yarn-project/end-to-end/src/shared/uniswap_l1_l2.ts index f23c35ea442..d9944d99b54 100644 --- a/yarn-project/end-to-end/src/shared/uniswap_l1_l2.ts +++ b/yarn-project/end-to-end/src/shared/uniswap_l1_l2.ts @@ -146,9 +146,7 @@ export const uniswapL1L2TestSuite = ( client: walletClient, }); // deploy l2 uniswap contract and attach to portal - uniswapL2Contract = await UniswapContract.deploy(ownerWallet) - .send({ portalContract: uniswapPortalAddress }) - .deployed(); + uniswapL2Contract = await UniswapContract.deploy(ownerWallet, uniswapPortalAddress).send().deployed(); const registryAddress = (await pxe.getNodeInfo()).l1ContractAddresses.registryAddress; diff --git a/yarn-project/noir-protocol-circuits-types/src/__snapshots__/noir_test_gen.test.ts.snap b/yarn-project/noir-protocol-circuits-types/src/__snapshots__/noir_test_gen.test.ts.snap index f2476be262e..c1eac3dcf71 100644 --- a/yarn-project/noir-protocol-circuits-types/src/__snapshots__/noir_test_gen.test.ts.snap +++ b/yarn-project/noir-protocol-circuits-types/src/__snapshots__/noir_test_gen.test.ts.snap @@ -4366,12 +4366,11 @@ exports[`Data generation for noir tests Computes contract info for defaultContra artifact_hash: 0x0000000000000000000000000000000000000000000000000000000000003039, public_bytecode_commitment: 0x129a3438653fe147133b2c274757920e37896305e7664c8c1eb380be3efd5fed, private_functions_root: 0x19a3cc0b714976fb35d58b684ba36e86f82bac8b87517904a2727e5113fb4cba, - address: AztecAddress { inner: 0x2d941148ee5adeece35991d32acbcf4200742991c61990dee965bedf729d21a9 }, - partial_address: PartialAddress { inner: 0x23a6933a485200a8d34b9929d61868c9635793f878d67ce86a1b1355c0ab0d47 }, - portal_contract_address: EthAddress { inner: 0x0000000000000000000000000000000000005ba0 }, + address: AztecAddress { inner: 0x0efbcdd92da9729c276193e01399cd12a30c2ea0774feec95de486cb3986c0a0 }, + partial_address: PartialAddress { inner: 0x30248868d815221789c5f173462ee99637ac9748000d31c5f311dbc3d996eb71 }, contract_class_id: ContractClassId { inner: 0x0ce2a998337b1e6da1ac1d802a8bb9e10b7d705d210e61efb9642855009814a6 }, public_keys_hash: PublicKeysHash { inner: 0x000000000000000000000000000000000000000000000000000000000000b26e }, - salted_initialization_hash: SaltedInitializationHash { inner: 0x0b095458845137ebf1e6061c8c0ba1d907241a3b56dc1d3e73d2fea78f04a036 }, + salted_initialization_hash: SaltedInitializationHash { inner: 0x25765504545d2cdaaa6544eb24bc78a3e20384452f2525669f196a1a42f45906 }, deployer: AztecAddress { inner: 0x0000000000000000000000000000000000000000000000000000000000000000 } }" `; @@ -4382,12 +4381,11 @@ exports[`Data generation for noir tests Computes contract info for parentContrac artifact_hash: 0x00000000000000000000000000000000000000000000000000000000000004bc, public_bytecode_commitment: 0x1435ed970b275bebf95de3df53f23f3d2e97c9b54cf442bb03a3fa17a0ee3cd7, private_functions_root: 0x2c1c949cb226995de94b7b8b5aeaab440739f2dfeb06d358441f60932cf243a7, - address: AztecAddress { inner: 0x24692d7dbb532557c7466e8782d1fe99077e4787570414bd1a5e8fa5300caad8 }, - partial_address: PartialAddress { inner: 0x127bbd73a3cf497fb2d85342571695d894985b449a9343eec55485e9cbc514f8 }, - portal_contract_address: EthAddress { inner: 0x0000000000000000000000000000000000000913 }, + address: AztecAddress { inner: 0x2dbb8c3db287eef6758cc13b1702ff6c5a4b534a8d0f08d76106e28aa0f4bd3c }, + partial_address: PartialAddress { inner: 0x20ac96f5da24137797077661d4222c8caf97d2d3fdeadbf4cad8f529a96eb610 }, contract_class_id: ContractClassId { inner: 0x1f1f963a350e2c883cc6730c19fc5d5b47a40694d805cbb0720fa76fe295df90 }, public_keys_hash: PublicKeysHash { inner: 0x00000000000000000000000000000000000000000000000000000000000011c1 }, - salted_initialization_hash: SaltedInitializationHash { inner: 0x04643e65513869350552499ed3412df59540dffe3cd698203deee8900b53bcec }, + salted_initialization_hash: SaltedInitializationHash { inner: 0x0b1d457cdacb66e76eccb29a4e34dff5ae10b9d3d2f0d85b59aa8cf68bd1cf86 }, deployer: AztecAddress { inner: 0x0000000000000000000000000000000000000000000000000000000000000000 } }" `; diff --git a/yarn-project/noir-protocol-circuits-types/src/noir_test_gen.test.ts b/yarn-project/noir-protocol-circuits-types/src/noir_test_gen.test.ts index 6453b0313e0..d046e58a862 100644 --- a/yarn-project/noir-protocol-circuits-types/src/noir_test_gen.test.ts +++ b/yarn-project/noir-protocol-circuits-types/src/noir_test_gen.test.ts @@ -1,7 +1,6 @@ import { MerkleTreeId } from '@aztec/circuit-types'; import { AztecAddress, - EthAddress, FunctionSelector, NOTE_HASH_TREE_HEIGHT, computeContractAddressFromInstance, @@ -22,12 +21,11 @@ describe('Data generation for noir tests', () => { setupCustomSnapshotSerializers(expect); type FixtureContractData = Omit & - Pick & + Pick & Pick & { toString: () => string }; const defaultContract: FixtureContractData = { artifactHash: new Fr(12345), - portalContractAddress: EthAddress.fromField(new Fr(23456)), packedBytecode: Buffer.from([3, 4, 5, 6, 7]), publicKeysHash: new Fr(45678), salt: new Fr(56789), @@ -40,7 +38,6 @@ describe('Data generation for noir tests', () => { const parentContract: FixtureContractData = { artifactHash: new Fr(1212), - portalContractAddress: EthAddress.fromField(new Fr(2323)), packedBytecode: Buffer.from([3, 4, 3, 4]), publicKeysHash: new Fr(4545), salt: new Fr(5656), @@ -75,7 +72,6 @@ describe('Data generation for noir tests', () => { private_functions_root: privateFunctionsRoot.toString(), address: `AztecAddress { inner: ${address.toString()} }`, partial_address: `PartialAddress { inner: ${partialAddress.toString()} }`, - portal_contract_address: `EthAddress { inner: ${contract.portalContractAddress.toString()} }`, contract_class_id: `ContractClassId { inner: ${contractClassId.toString()} }`, public_keys_hash: `PublicKeysHash { inner: ${contract.publicKeysHash.toString()} }`, salted_initialization_hash: `SaltedInitializationHash { inner: ${saltedInitializationHash.toString()} }`, diff --git a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts index 51265ed43e6..3b3e0a2385a 100644 --- a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts +++ b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts @@ -426,7 +426,6 @@ export function mapCallContextFromNoir(callContext: CallContextNoir): CallContex return new CallContext( mapAztecAddressFromNoir(callContext.msg_sender), mapAztecAddressFromNoir(callContext.storage_contract_address), - mapEthAddressFromNoir(callContext.portal_contract_address), mapFunctionSelectorFromNoir(callContext.function_selector), callContext.is_delegate_call, callContext.is_static_call, @@ -443,7 +442,6 @@ export function mapCallContextToNoir(callContext: CallContext): CallContextNoir return { msg_sender: mapAztecAddressToNoir(callContext.msgSender), storage_contract_address: mapAztecAddressToNoir(callContext.storageContractAddress), - portal_contract_address: mapEthAddressToNoir(callContext.portalContractAddress), function_selector: mapFunctionSelectorToNoir(callContext.functionSelector), is_delegate_call: callContext.isDelegateCall, is_static_call: callContext.isStaticCall, @@ -793,8 +791,6 @@ export function mapPrivateCallDataToNoir(privateCallData: PrivateCallData): Priv contract_class_public_bytecode_commitment: mapFieldToNoir(privateCallData.contractClassPublicBytecodeCommitment), public_keys_hash: mapWrappedFieldToNoir(privateCallData.publicKeysHash), salted_initialization_hash: mapWrappedFieldToNoir(privateCallData.saltedInitializationHash), - //TODO this seems like the wrong type in circuits.js - portal_contract_address: mapEthAddressToNoir(EthAddress.fromField(privateCallData.portalContractAddress)), acir_hash: mapFieldToNoir(privateCallData.acirHash), }; } @@ -1618,7 +1614,6 @@ export function mapPublicCallDataToNoir(publicCall: PublicCallData): PublicCallD call_stack_item: mapPublicCallStackItemToNoir(publicCall.callStackItem), public_call_stack: mapTuple(publicCall.publicCallStack, mapCallRequestToNoir), proof: {}, - portal_contract_address: mapEthAddressToNoir(EthAddress.fromField(publicCall.portalContractAddress)), bytecode_hash: mapFieldToNoir(publicCall.bytecodeHash), }; } diff --git a/yarn-project/protocol-contracts/src/gas-token/index.ts b/yarn-project/protocol-contracts/src/gas-token/index.ts index b31573a235c..838ca1affca 100644 --- a/yarn-project/protocol-contracts/src/gas-token/index.ts +++ b/yarn-project/protocol-contracts/src/gas-token/index.ts @@ -5,7 +5,7 @@ import { GasTokenArtifact } from './artifact.js'; /** Returns the canonical deployment of the gas token. */ export function getCanonicalGasToken(l1Bridge: EthAddress): ProtocolContract { - return getCanonicalProtocolContract(GasTokenArtifact, 1, [], l1Bridge); + return getCanonicalProtocolContract(GasTokenArtifact, 1, [l1Bridge]); } export function getCanonicalGasTokenAddress(l1Bridge: EthAddress): AztecAddress { diff --git a/yarn-project/protocol-contracts/src/multi-call-entrypoint/index.ts b/yarn-project/protocol-contracts/src/multi-call-entrypoint/index.ts index 160f408ee26..ceed7241aae 100644 --- a/yarn-project/protocol-contracts/src/multi-call-entrypoint/index.ts +++ b/yarn-project/protocol-contracts/src/multi-call-entrypoint/index.ts @@ -1,10 +1,10 @@ -import { type AztecAddress, EthAddress } from '@aztec/circuits.js'; +import { type AztecAddress } from '@aztec/circuits.js'; import { type ProtocolContract, getCanonicalProtocolContract } from '../protocol_contract.js'; import { MultiCallEntrypointArtifact } from './artifact.js'; export function getCanonicalMultiCallEntrypointContract(): ProtocolContract { - return getCanonicalProtocolContract(MultiCallEntrypointArtifact, 1, [], EthAddress.ZERO); + return getCanonicalProtocolContract(MultiCallEntrypointArtifact, 1, []); } export function getCanonicalMultiCallEntrypointAddress(): AztecAddress { diff --git a/yarn-project/protocol-contracts/src/protocol_contract.ts b/yarn-project/protocol-contracts/src/protocol_contract.ts index 2ce2b31c064..6ee8a47bf88 100644 --- a/yarn-project/protocol-contracts/src/protocol_contract.ts +++ b/yarn-project/protocol-contracts/src/protocol_contract.ts @@ -1,6 +1,5 @@ import { type AztecAddress, - EthAddress, getContractClassFromArtifact, getContractInstanceFromDeployParams, } from '@aztec/circuits.js'; @@ -25,14 +24,12 @@ export function getCanonicalProtocolContract( artifact: ContractArtifact, salt: Fr | number | bigint, constructorArgs: any[] = [], - portalAddress = EthAddress.ZERO, ): ProtocolContract { // TODO(@spalladino): This computes the contract class from the artifact twice. const contractClass = getContractClassFromArtifact(artifact); const instance = getContractInstanceFromDeployParams(artifact, { constructorArgs, salt: new Fr(salt), - portalAddress, }); return { instance, diff --git a/yarn-project/pxe/src/contract_data_oracle/index.ts b/yarn-project/pxe/src/contract_data_oracle/index.ts index eaf53cb9be6..4dbf3ebcdec 100644 --- a/yarn-project/pxe/src/contract_data_oracle/index.ts +++ b/yarn-project/pxe/src/contract_data_oracle/index.ts @@ -52,20 +52,6 @@ export class ContractDataOracle { return tree.getArtifact(); } - /** - * Retrieve the portal contract address associated with the given contract address. - * This function searches for the corresponding contract tree in the local cache and returns the portal contract address. - * If the contract tree is not found in the cache, it fetches the contract data from the database and creates a new ContractTree instance. - * Throws an error if the contract address is not found in the database. - * - * @param contractAddress - The AztecAddress of the contract whose portal contract address needs to be retrieved. - * @returns A Promise that resolves to the portal contract address. - */ - public async getPortalContractAddress(contractAddress: AztecAddress) { - const instance = await this.getContractInstance(contractAddress); - return instance.portalContractAddress; - } - /** * Retrieves the artifact of a specified function within a given contract. * The function is identified by its selector, which is a unique code generated from the function's signature. diff --git a/yarn-project/pxe/src/kernel_prover/kernel_prover.ts b/yarn-project/pxe/src/kernel_prover/kernel_prover.ts index 1632ebc3164..000d26e72e4 100644 --- a/yarn-project/pxe/src/kernel_prover/kernel_prover.ts +++ b/yarn-project/pxe/src/kernel_prover/kernel_prover.ts @@ -207,8 +207,7 @@ export class KernelProver { publicCallRequests: CallRequest[], noteHashReadRequestMembershipWitnesses: NoteHashReadRequestMembershipWitness[], ) { - const { contractAddress, functionData, publicInputs } = callStackItem; - const { portalContractAddress } = publicInputs.callContext; + const { contractAddress, functionData } = callStackItem; // Pad with empty items to reach max/const length expected by circuit. const privateCallStack = padArrayEnd( @@ -251,7 +250,6 @@ export class KernelProver { i => noteHashReadRequestMembershipWitnesses[i], 0, ), - portalContractAddress: portalContractAddress.toField(), acirHash, }); } diff --git a/yarn-project/pxe/src/pxe_service/pxe_service.ts b/yarn-project/pxe/src/pxe_service/pxe_service.ts index 5f90b66be33..c3d5de0c33d 100644 --- a/yarn-project/pxe/src/pxe_service/pxe_service.ts +++ b/yarn-project/pxe/src/pxe_service/pxe_service.ts @@ -537,10 +537,10 @@ export class PXEService implements PXE { /** * Retrieves the simulation parameters required to run an ACIR simulation. - * This includes the contract address, function artifact, portal contract address, and historical tree roots. + * This includes the contract address, function artifact, and historical tree roots. * * @param execRequest - The transaction request object containing details of the contract call. - * @returns An object containing the contract address, function artifact, portal contract address, and historical tree roots. + * @returns An object containing the contract address, function artifact, and historical tree roots. */ async #getSimulationParameters(execRequest: FunctionCall | TxExecutionRequest) { const contractAddress = (execRequest as FunctionCall).to ?? (execRequest as TxExecutionRequest).origin; @@ -552,7 +552,6 @@ export class PXEService implements PXE { contractAddress, execRequest.functionData.selector, ); - const portalContract = await this.contractDataOracle.getPortalContractAddress(contractAddress); return { contractAddress, @@ -560,18 +559,17 @@ export class PXEService implements PXE { ...functionArtifact, debug, }, - portalContract, }; } async #simulate(txRequest: TxExecutionRequest, msgSender?: AztecAddress): Promise { // TODO - Pause syncing while simulating. - const { contractAddress, functionArtifact, portalContract } = await this.#getSimulationParameters(txRequest); + const { contractAddress, functionArtifact } = await this.#getSimulationParameters(txRequest); this.log.debug('Executing simulator...'); try { - const result = await this.simulator.run(txRequest, functionArtifact, contractAddress, portalContract, msgSender); + const result = await this.simulator.run(txRequest, functionArtifact, contractAddress, msgSender); this.log.verbose(`Simulation completed for ${contractAddress.toString()}:${functionArtifact.name}`); return result; } catch (err) { diff --git a/yarn-project/pxe/src/simulator_oracle/index.ts b/yarn-project/pxe/src/simulator_oracle/index.ts index da0891190f6..827f37111f6 100644 --- a/yarn-project/pxe/src/simulator_oracle/index.ts +++ b/yarn-project/pxe/src/simulator_oracle/index.ts @@ -11,7 +11,6 @@ import { import { type AztecAddress, type CompleteAddress, - type EthAddress, type Fr, type FunctionSelector, type Header, @@ -117,10 +116,6 @@ export class SimulatorOracle implements DBOracle { return artifact && getFunctionArtifactWithDebugMetadata(artifact, functionName); } - async getPortalContractAddress(contractAddress: AztecAddress): Promise { - return await this.contractDataOracle.getPortalContractAddress(contractAddress); - } - /** * Fetches a message from the db, given its key. * @param contractAddress - Address of a contract by which the message was emitted. diff --git a/yarn-project/simulator/src/acvm/oracle/oracle.ts b/yarn-project/simulator/src/acvm/oracle/oracle.ts index f1271b791dd..ac88228ef08 100644 --- a/yarn-project/simulator/src/acvm/oracle/oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/oracle.ts @@ -68,7 +68,6 @@ export class Oracle { instance.deployer, instance.contractClassId, instance.initializationHash, - instance.portalContractAddress, instance.publicKeysHash, ].map(toACVMField); } diff --git a/yarn-project/simulator/src/avm/avm_execution_environment.ts b/yarn-project/simulator/src/avm/avm_execution_environment.ts index def966f15ed..3d26ff7a175 100644 --- a/yarn-project/simulator/src/avm/avm_execution_environment.ts +++ b/yarn-project/simulator/src/avm/avm_execution_environment.ts @@ -1,7 +1,6 @@ import { FunctionSelector, type GasSettings, type GlobalVariables, type Header } from '@aztec/circuits.js'; import { computeVarArgsHash } from '@aztec/circuits.js/hash'; import { type AztecAddress } from '@aztec/foundation/aztec-address'; -import { type EthAddress } from '@aztec/foundation/eth-address'; import { type Fr } from '@aztec/foundation/fields'; export class AvmContextInputs { @@ -24,7 +23,6 @@ export class AvmExecutionEnvironment { public readonly address: AztecAddress, public readonly storageAddress: AztecAddress, public readonly sender: AztecAddress, - public readonly portal: EthAddress, public readonly feePerL1Gas: Fr, public readonly feePerL2Gas: Fr, public readonly feePerDaGas: Fr, @@ -57,7 +55,6 @@ export class AvmExecutionEnvironment { targetAddress, /*storageAddress=*/ targetAddress, this.address, - this.portal, this.feePerL1Gas, this.feePerL2Gas, this.feePerDaGas, @@ -82,7 +79,6 @@ export class AvmExecutionEnvironment { address, /*storageAddress=*/ address, this.sender, - this.portal, this.feePerL1Gas, this.feePerL2Gas, this.feePerDaGas, @@ -107,7 +103,6 @@ export class AvmExecutionEnvironment { address, this.storageAddress, this.sender, - this.portal, this.feePerL1Gas, this.feePerL2Gas, this.feePerDaGas, diff --git a/yarn-project/simulator/src/avm/avm_gas.ts b/yarn-project/simulator/src/avm/avm_gas.ts index 77ee6173996..5d7bae10514 100644 --- a/yarn-project/simulator/src/avm/avm_gas.ts +++ b/yarn-project/simulator/src/avm/avm_gas.ts @@ -79,7 +79,6 @@ export const GasCosts: Record = { [Opcode.ADDRESS]: TemporaryDefaultGasCost, [Opcode.STORAGEADDRESS]: TemporaryDefaultGasCost, [Opcode.SENDER]: TemporaryDefaultGasCost, - [Opcode.PORTAL]: TemporaryDefaultGasCost, [Opcode.FEEPERL1GAS]: TemporaryDefaultGasCost, [Opcode.FEEPERL2GAS]: TemporaryDefaultGasCost, [Opcode.FEEPERDAGAS]: TemporaryDefaultGasCost, diff --git a/yarn-project/simulator/src/avm/avm_simulator.test.ts b/yarn-project/simulator/src/avm/avm_simulator.test.ts index 783089c16dd..0b8b128cc38 100644 --- a/yarn-project/simulator/src/avm/avm_simulator.test.ts +++ b/yarn-project/simulator/src/avm/avm_simulator.test.ts @@ -3,7 +3,6 @@ import { computeVarArgsHash } from '@aztec/circuits.js/hash'; import { EventSelector, FunctionSelector } from '@aztec/foundation/abi'; import { AztecAddress } from '@aztec/foundation/aztec-address'; import { keccak256, pedersenHash, poseidon2Hash, sha256 } from '@aztec/foundation/crypto'; -import { EthAddress } from '@aztec/foundation/eth-address'; import { Fr } from '@aztec/foundation/fields'; import { type Fieldable } from '@aztec/foundation/serialize'; import { AvmNestedCallsTestContractArtifact, AvmTestContractArtifact } from '@aztec/noir-contracts.js'; @@ -188,11 +187,6 @@ describe('AVM simulator: transpiled Noir contracts', () => { await testEnvGetter('sender', sender, 'get_sender'); }); - it('portal', async () => { - const portal = EthAddress.fromField(new Fr(1)); - await testEnvGetter('portal', portal, 'get_portal'); - }); - it('getFeePerL1Gas', async () => { const fee = new Fr(1); await testEnvGetter('feePerL1Gas', fee, 'get_fee_per_l1_gas'); @@ -772,7 +766,6 @@ describe('AVM simulator: transpiled Noir contracts', () => { deployer: AztecAddress.fromBigInt(0x456n), contractClassId: new Fr(0x789), initializationHash: new Fr(0x101112), - portalContractAddress: EthAddress.fromField(new Fr(0x131415)), publicKeysHash: new Fr(0x161718), }; diff --git a/yarn-project/simulator/src/avm/fixtures/index.ts b/yarn-project/simulator/src/avm/fixtures/index.ts index ef9233bb686..2800a605bb3 100644 --- a/yarn-project/simulator/src/avm/fixtures/index.ts +++ b/yarn-project/simulator/src/avm/fixtures/index.ts @@ -56,7 +56,6 @@ export function initExecutionEnvironment(overrides?: Partial { salt: new Fr(20), contractClassId: new Fr(30), initializationHash: new Fr(40), - portalContractAddress: EthAddress.random(), publicKeysHash: new Fr(50), deployer: AztecAddress.random(), }; @@ -56,14 +55,13 @@ describe('Contract opcodes', () => { await new GetContractInstance(/*indirect=*/ 0, /*addressOffset=*/ 0, /*dstOffset=*/ 1).execute(context); - const actual = context.machineState.memory.getSlice(1, 7); + const actual = context.machineState.memory.getSlice(1, 6); expect(actual).toEqual([ new Field(1), // found new Field(contractInstance.salt), new Field(contractInstance.deployer), new Field(contractInstance.contractClassId), new Field(contractInstance.initializationHash), - new Field(contractInstance.portalContractAddress.toField()), new Field(contractInstance.publicKeysHash), ]); }); @@ -74,7 +72,7 @@ describe('Contract opcodes', () => { await new GetContractInstance(/*indirect=*/ 0, /*addressOffset=*/ 0, /*dstOffset=*/ 1).execute(context); - const actual = context.machineState.memory.getSlice(1, 7); + const actual = context.machineState.memory.getSlice(1, 6); expect(actual).toEqual([ new Field(0), // found new Field(0), @@ -82,7 +80,6 @@ describe('Contract opcodes', () => { new Field(0), new Field(0), new Field(0), - new Field(0), ]); }); }); diff --git a/yarn-project/simulator/src/avm/opcodes/contract.ts b/yarn-project/simulator/src/avm/opcodes/contract.ts index 5e24dcf0d50..a0b41705bfd 100644 --- a/yarn-project/simulator/src/avm/opcodes/contract.ts +++ b/yarn-project/simulator/src/avm/opcodes/contract.ts @@ -39,7 +39,6 @@ export class GetContractInstance extends Instruction { new Field(0), new Field(0), new Field(0), - new Field(0), ] : [ new Fr(1), // found @@ -47,7 +46,6 @@ export class GetContractInstance extends Instruction { instance.deployer.toField(), instance.contractClassId, instance.initializationHash, - instance.portalContractAddress.toField(), instance.publicKeysHash, ].map(f => new Field(f)); diff --git a/yarn-project/simulator/src/avm/opcodes/environment_getters.test.ts b/yarn-project/simulator/src/avm/opcodes/environment_getters.test.ts index 96818cd7a71..7eaff3e408d 100644 --- a/yarn-project/simulator/src/avm/opcodes/environment_getters.test.ts +++ b/yarn-project/simulator/src/avm/opcodes/environment_getters.test.ts @@ -8,7 +8,6 @@ import { FeePerDAGas, FeePerL1Gas, FeePerL2Gas, - Portal, Sender, StorageAddress, Timestamp, @@ -16,7 +15,6 @@ import { } from './environment_getters.js'; type EnvInstruction = - | typeof Portal | typeof FeePerL1Gas | typeof FeePerL2Gas | typeof FeePerDAGas @@ -24,7 +22,6 @@ type EnvInstruction = | typeof StorageAddress | typeof Address; describe.each([ - [Portal, 'portal'], [FeePerL1Gas, 'feePerL1Gas'], [FeePerL2Gas, 'feePerL2Gas'], [FeePerDAGas, 'feePerDaGas'], diff --git a/yarn-project/simulator/src/avm/opcodes/environment_getters.ts b/yarn-project/simulator/src/avm/opcodes/environment_getters.ts index b105fd20d77..d9316c03ca8 100644 --- a/yarn-project/simulator/src/avm/opcodes/environment_getters.ts +++ b/yarn-project/simulator/src/avm/opcodes/environment_getters.ts @@ -68,15 +68,6 @@ export class FeePerDAGas extends EnvironmentGetterInstruction { } } -export class Portal extends EnvironmentGetterInstruction { - static type: string = 'PORTAL'; - static readonly opcode: Opcode = Opcode.PORTAL; - - protected getEnvironmentValue(env: AvmExecutionEnvironment) { - return env.portal.toField(); - } -} - export class ChainId extends EnvironmentGetterInstruction { static type: string = 'CHAINID'; static readonly opcode: Opcode = Opcode.CHAINID; diff --git a/yarn-project/simulator/src/avm/serialization/bytecode_serialization.ts b/yarn-project/simulator/src/avm/serialization/bytecode_serialization.ts index 6a95dac7fed..d3245a24d5b 100644 --- a/yarn-project/simulator/src/avm/serialization/bytecode_serialization.ts +++ b/yarn-project/simulator/src/avm/serialization/bytecode_serialization.ts @@ -33,7 +33,6 @@ import { NoteHashExists, NullifierExists, Or, - Portal, Return, Revert, SLoad, @@ -82,7 +81,6 @@ const INSTRUCTION_SET = () => [Address.opcode, Address], [StorageAddress.opcode, StorageAddress], [Sender.opcode, Sender], - [Portal.opcode, Portal], [FeePerL1Gas.opcode, FeePerL1Gas], [FeePerL2Gas.opcode, FeePerL2Gas], [FeePerDAGas.opcode, FeePerDAGas], diff --git a/yarn-project/simulator/src/avm/serialization/instruction_serialization.ts b/yarn-project/simulator/src/avm/serialization/instruction_serialization.ts index 6f5bb70eb41..6dcc877194d 100644 --- a/yarn-project/simulator/src/avm/serialization/instruction_serialization.ts +++ b/yarn-project/simulator/src/avm/serialization/instruction_serialization.ts @@ -27,7 +27,6 @@ export enum Opcode { ADDRESS, STORAGEADDRESS, SENDER, - PORTAL, FEEPERL1GAS, FEEPERL2GAS, FEEPERDAGAS, diff --git a/yarn-project/simulator/src/client/client_execution_context.ts b/yarn-project/simulator/src/client/client_execution_context.ts index 1363fe615e7..88720fba6f8 100644 --- a/yarn-project/simulator/src/client/client_execution_context.ts +++ b/yarn-project/simulator/src/client/client_execution_context.ts @@ -382,7 +382,7 @@ export class ClientExecutionContext extends ViewDataOracle { const derivedTxContext = this.txContext.clone(); - const derivedCallContext = await this.deriveCallContext( + const derivedCallContext = this.deriveCallContext( targetContractAddress, targetArtifact, sideEffectCounter, @@ -443,7 +443,7 @@ export class ClientExecutionContext extends ViewDataOracle { isStaticCall = isStaticCall || this.callContext.isStaticCall; const targetArtifact = await this.db.getFunctionArtifact(targetContractAddress, functionSelector); - const derivedCallContext = await this.deriveCallContext( + const derivedCallContext = this.deriveCallContext( targetContractAddress, targetArtifact, sideEffectCounter, @@ -481,18 +481,16 @@ export class ClientExecutionContext extends ViewDataOracle { * @param isStaticCall - Whether the call is a static call. * @returns The derived call context. */ - private async deriveCallContext( + private deriveCallContext( targetContractAddress: AztecAddress, targetArtifact: FunctionArtifact, startSideEffectCounter: number, isDelegateCall = false, isStaticCall = false, ) { - const portalContractAddress = await this.db.getPortalContractAddress(targetContractAddress); return new CallContext( isDelegateCall ? this.callContext.msgSender : this.contractAddress, isDelegateCall ? this.contractAddress : targetContractAddress, - portalContractAddress, FunctionSelector.fromNameAndParameters(targetArtifact.name, targetArtifact.parameters), isDelegateCall, isStaticCall, diff --git a/yarn-project/simulator/src/client/db_oracle.ts b/yarn-project/simulator/src/client/db_oracle.ts index 3c3d5126814..d03e152bde9 100644 --- a/yarn-project/simulator/src/client/db_oracle.ts +++ b/yarn-project/simulator/src/client/db_oracle.ts @@ -8,7 +8,6 @@ import { import { type CompleteAddress, type Header } from '@aztec/circuits.js'; import { type FunctionArtifactWithDebugMetadata, type FunctionSelector } from '@aztec/foundation/abi'; import { type AztecAddress } from '@aztec/foundation/aztec-address'; -import { type EthAddress } from '@aztec/foundation/eth-address'; import { type Fr } from '@aztec/foundation/fields'; import { type ContractInstance } from '@aztec/types/contracts'; @@ -113,15 +112,6 @@ export interface DBOracle extends CommitmentsDB { functionName: string, ): Promise; - /** - * Retrieves the portal contract address associated with the given contract address. - * Throws an error if the input contract address is not found or invalid. - * - * @param contractAddress - The address of the contract whose portal address is to be fetched. - * @returns A Promise that resolves to an EthAddress instance, representing the portal contract address. - */ - getPortalContractAddress(contractAddress: AztecAddress): Promise; - /** * Gets the index of a nullifier in the nullifier tree. * @param nullifier - The nullifier. diff --git a/yarn-project/simulator/src/client/private_execution.test.ts b/yarn-project/simulator/src/client/private_execution.test.ts index 5cbf65ec767..7156422a39b 100644 --- a/yarn-project/simulator/src/client/private_execution.test.ts +++ b/yarn-project/simulator/src/client/private_execution.test.ts @@ -100,13 +100,11 @@ describe('Private Execution test suite', () => { args = [], msgSender = AztecAddress.ZERO, contractAddress = defaultContractAddress, - portalContractAddress = EthAddress.ZERO, txContext = {}, }: { artifact: FunctionArtifact; msgSender?: AztecAddress; contractAddress?: AztecAddress; - portalContractAddress?: EthAddress; args?: any[]; txContext?: Partial>; }) => { @@ -121,7 +119,7 @@ describe('Private Execution test suite', () => { authWitnesses: [], }); - return acirSimulator.run(txRequest, artifact, contractAddress, portalContractAddress, msgSender); + return acirSimulator.run(txRequest, artifact, contractAddress, msgSender); }; const insertLeaves = async (leaves: Fr[], name = 'noteHash') => { @@ -280,8 +278,6 @@ describe('Private Execution test suite', () => { oracle.getFunctionArtifact.mockImplementation((_, selector: FunctionSelector) => Promise.resolve(getFunctionArtifact(StatefulTestContractArtifact, selector)), ); - - oracle.getPortalContractAddress.mockResolvedValue(EthAddress.ZERO); }); it('should have a constructor with arguments that inserts notes', async () => { @@ -445,7 +441,6 @@ describe('Private Execution test suite', () => { const childSelector = FunctionSelector.fromNameAndParameters(childArtifact.name, childArtifact.parameters); oracle.getFunctionArtifact.mockImplementation(() => Promise.resolve(childArtifact)); - oracle.getPortalContractAddress.mockImplementation(() => Promise.resolve(EthAddress.ZERO)); logger.info(`Parent deployed at ${parentAddress.toShortString()}`); logger.info(`Calling child function ${childSelector.toString()} at ${childAddress.toShortString()}`); @@ -456,7 +451,6 @@ describe('Private Execution test suite', () => { expect(result.returnValues).toEqual([new Fr(privateIncrement)]); expect(oracle.getFunctionArtifact.mock.calls[0]).toEqual([childAddress, childSelector]); - expect(oracle.getPortalContractAddress.mock.calls[0]).toEqual([childAddress]); expect(result.nestedExecutions).toHaveLength(1); expect(result.nestedExecutions[0].returnValues).toEqual([new Fr(privateIncrement)]); @@ -499,7 +493,6 @@ describe('Private Execution test suite', () => { ); oracle.getFunctionArtifact.mockResolvedValue(testCodeGenArtifact); - oracle.getPortalContractAddress.mockResolvedValue(EthAddress.ZERO); logger.info(`Calling importer main function`); const args = [testAddress]; @@ -507,7 +500,6 @@ describe('Private Execution test suite', () => { expect(result.returnValues).toEqual([argsHash]); expect(oracle.getFunctionArtifact.mock.calls[0]).toEqual([testAddress, testCodeGenSelector]); - expect(oracle.getPortalContractAddress.mock.calls[0]).toEqual([testAddress]); expect(result.nestedExecutions).toHaveLength(1); expect(result.nestedExecutions[0].returnValues).toEqual([argsHash]); }); @@ -556,7 +548,12 @@ describe('Private Execution test suite', () => { ); const computeArgs = () => - encodeArguments(artifact, [secretHashForRedeemingNotes, bridgedAmount, secretForL1ToL2MessageConsumption]); + encodeArguments(artifact, [ + secretHashForRedeemingNotes, + bridgedAmount, + secretForL1ToL2MessageConsumption, + crossChainMsgSender ?? preimage.sender.sender, + ]); const mockOracles = async (updateHeader = true) => { const tree = await insertLeaves([preimage.hash()], 'l1ToL2Messages'); @@ -577,7 +574,6 @@ describe('Private Execution test suite', () => { contractAddress, artifact, args, - portalContractAddress: crossChainMsgSender ?? preimage.sender.sender, txContext: { version: new Fr(1n), chainId: new Fr(1n) }, }); @@ -602,7 +598,6 @@ describe('Private Execution test suite', () => { contractAddress, artifact, args, - portalContractAddress: crossChainMsgSender ?? preimage.sender.sender, txContext: { version: new Fr(1n), chainId: new Fr(1n) }, }), ).rejects.toThrow('Message not in state'); @@ -624,7 +619,6 @@ describe('Private Execution test suite', () => { contractAddress, artifact, args, - portalContractAddress: crossChainMsgSender ?? preimage.sender.sender, txContext: { version: new Fr(1n), chainId: new Fr(1n) }, }), ).rejects.toThrow('Message not in state'); @@ -645,7 +639,6 @@ describe('Private Execution test suite', () => { contractAddress, artifact, args, - portalContractAddress: crossChainMsgSender ?? preimage.sender.sender, txContext: { version: new Fr(1n), chainId: new Fr(1n) }, }), ).rejects.toThrow('Message not in state'); @@ -665,7 +658,6 @@ describe('Private Execution test suite', () => { contractAddress, artifact, args, - portalContractAddress: crossChainMsgSender ?? preimage.sender.sender, txContext: { version: new Fr(1n), chainId: new Fr(2n) }, }), ).rejects.toThrow('Message not in state'); @@ -685,7 +677,6 @@ describe('Private Execution test suite', () => { contractAddress, artifact, args, - portalContractAddress: crossChainMsgSender ?? preimage.sender.sender, txContext: { version: new Fr(2n), chainId: new Fr(1n) }, }), ).rejects.toThrow('Message not in state'); @@ -706,7 +697,6 @@ describe('Private Execution test suite', () => { contractAddress, artifact, args, - portalContractAddress: crossChainMsgSender ?? preimage.sender.sender, txContext: { version: new Fr(1n), chainId: new Fr(1n) }, }), ).rejects.toThrow('Message not in state'); @@ -727,7 +717,6 @@ describe('Private Execution test suite', () => { contractAddress, artifact, args, - portalContractAddress: crossChainMsgSender ?? preimage.sender.sender, txContext: { version: new Fr(1n), chainId: new Fr(1n) }, }), ).rejects.toThrow('Message not in state'); @@ -776,14 +765,12 @@ describe('Private Execution test suite', () => { const childContractArtifact = ChildContractArtifact.functions.find(fn => fn.name === 'pub_set_value')!; expect(childContractArtifact).toBeDefined(); const childAddress = AztecAddress.random(); - const childPortalContractAddress = EthAddress.random(); const childSelector = FunctionSelector.fromNameAndParameters( childContractArtifact.name, childContractArtifact.parameters, ); const parentAddress = AztecAddress.random(); - oracle.getPortalContractAddress.mockImplementation(() => Promise.resolve(childPortalContractAddress)); oracle.getFunctionArtifact.mockImplementation(() => Promise.resolve({ ...childContractArtifact, isInternal })); const args = [childAddress, childSelector, 42n]; @@ -804,7 +791,6 @@ describe('Private Execution test suite', () => { callContext: CallContext.from({ msgSender: parentAddress, storageContractAddress: childAddress, - portalContractAddress: childPortalContractAddress, functionSelector: childSelector, isDelegateCall: false, isStaticCall: false, @@ -813,7 +799,6 @@ describe('Private Execution test suite', () => { parentCallContext: CallContext.from({ msgSender: parentAddress, storageContractAddress: parentAddress, - portalContractAddress: EthAddress.ZERO, functionSelector: FunctionSelector.fromNameAndParameters(parentArtifact.name, parentArtifact.parameters), isDelegateCall: false, isStaticCall: false, @@ -920,8 +905,6 @@ describe('Private Execution test suite', () => { getThenNullifyArtifact.parameters, ); - oracle.getPortalContractAddress.mockImplementation(() => Promise.resolve(EthAddress.ZERO)); - const args = [amountToTransfer, owner, insertFnSelector.toField(), getThenNullifyFnSelector.toField()]; const result = await runSimulator({ args: args, @@ -1020,18 +1003,6 @@ describe('Private Execution test suite', () => { }); describe('Context oracles', () => { - it("Should be able to get and return the contract's portal contract address", async () => { - const portalContractAddress = EthAddress.random(); - - // Tweak the contract artifact so we can extract return values - const artifact = getFunctionArtifact(TestContractArtifact, 'get_portal_contract_address'); - - const args: Fr[] = []; - - const result = await runSimulator({ artifact, args, portalContractAddress }); - expect(result.returnValues).toEqual([portalContractAddress.toField()]); - }); - it('this_address should return the current context address', async () => { const contractAddress = AztecAddress.random(); @@ -1042,17 +1013,6 @@ describe('Private Execution test suite', () => { const result = await runSimulator({ artifact, args: [], contractAddress }); expect(result.returnValues).toEqual([contractAddress.toField()]); }); - - it("this_portal_address should return the current context's portal address", async () => { - const portalContractAddress = EthAddress.random(); - - // Tweak the contract artifact so we can extract return values - const artifact = getFunctionArtifact(TestContractArtifact, 'get_this_portal_address'); - - // Overwrite the oracle return value - const result = await runSimulator({ artifact, args: [], portalContractAddress }); - expect(result.returnValues).toEqual([portalContractAddress.toField()]); - }); }); describe('Private global variables', () => { diff --git a/yarn-project/simulator/src/client/simulator.ts b/yarn-project/simulator/src/client/simulator.ts index 38831db4601..cc9d58a0b4e 100644 --- a/yarn-project/simulator/src/client/simulator.ts +++ b/yarn-project/simulator/src/client/simulator.ts @@ -9,7 +9,6 @@ import { encodeArguments, } from '@aztec/foundation/abi'; import { AztecAddress } from '@aztec/foundation/aztec-address'; -import { type EthAddress } from '@aztec/foundation/eth-address'; import { Fr } from '@aztec/foundation/fields'; import { type DebugLogger, createDebugLogger } from '@aztec/foundation/log'; @@ -61,7 +60,6 @@ export class AcirSimulator { * @param request - The transaction request. * @param entryPointArtifact - The artifact of the entry point function. * @param contractAddress - The address of the contract (should match request.origin) - * @param portalContractAddress - The address of the portal contract. * @param msgSender - The address calling the function. This can be replaced to simulate a call from another contract or a specific account. * @returns The result of the execution. */ @@ -69,7 +67,6 @@ export class AcirSimulator { request: TxExecutionRequest, entryPointArtifact: FunctionArtifactWithDebugMetadata, contractAddress: AztecAddress, - portalContractAddress: EthAddress, msgSender = AztecAddress.ZERO, ): Promise { if (entryPointArtifact.functionType !== FunctionType.SECRET) { @@ -92,7 +89,6 @@ export class AcirSimulator { const callContext = new CallContext( msgSender, contractAddress, - portalContractAddress, FunctionSelector.fromNameAndParameters(entryPointArtifact.name, entryPointArtifact.parameters), false, false, diff --git a/yarn-project/simulator/src/mocks/fixtures.ts b/yarn-project/simulator/src/mocks/fixtures.ts index a68a2181eb8..2930fd627d0 100644 --- a/yarn-project/simulator/src/mocks/fixtures.ts +++ b/yarn-project/simulator/src/mocks/fixtures.ts @@ -5,7 +5,6 @@ import { CallContext, CallRequest, type ContractStorageUpdateRequest, - EthAddress, Fr, FunctionData, Gas, @@ -66,7 +65,7 @@ export class PublicExecutionResultBuilder { revertReason?: SimulationError; }) { const builder = new PublicExecutionResultBuilder({ - callContext: new CallContext(from, tx.to, EthAddress.ZERO, tx.functionData.selector, false, false, 0), + callContext: new CallContext(from, tx.to, tx.functionData.selector, false, false, 0), contractAddress: tx.to, functionData: tx.functionData, args: tx.args, diff --git a/yarn-project/simulator/src/public/abstract_phase_manager.ts b/yarn-project/simulator/src/public/abstract_phase_manager.ts index fbd4d95435c..4564b7d4130 100644 --- a/yarn-project/simulator/src/public/abstract_phase_manager.ts +++ b/yarn-project/simulator/src/public/abstract_phase_manager.ts @@ -450,8 +450,7 @@ export abstract class AbstractPhaseManager { c.toCallRequest(callStackItem.publicInputs.callContext), ); const publicCallStack = padArrayEnd(publicCallRequests, CallRequest.empty(), MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL); - const portalContractAddress = result.execution.callContext.portalContractAddress.toField(); - return new PublicCallData(callStackItem, publicCallStack, makeEmptyProof(), portalContractAddress, bytecodeHash); + return new PublicCallData(callStackItem, publicCallStack, makeEmptyProof(), bytecodeHash); } } diff --git a/yarn-project/simulator/src/public/avm_executor.test.ts b/yarn-project/simulator/src/public/avm_executor.test.ts index 036e8d4a00d..a5aad855eb4 100644 --- a/yarn-project/simulator/src/public/avm_executor.test.ts +++ b/yarn-project/simulator/src/public/avm_executor.test.ts @@ -1,4 +1,4 @@ -import { AztecAddress, CallContext, EthAddress, FunctionData, FunctionSelector, type Header } from '@aztec/circuits.js'; +import { AztecAddress, CallContext, FunctionData, FunctionSelector, type Header } from '@aztec/circuits.js'; import { makeHeader } from '@aztec/circuits.js/testing'; import { randomInt } from '@aztec/foundation/crypto'; import { Fr } from '@aztec/foundation/fields'; @@ -20,7 +20,6 @@ describe('AVM WitGen and Proof Generation', () => { const callContext = CallContext.from({ msgSender: AztecAddress.random(), storageContractAddress: AztecAddress.random(), - portalContractAddress: EthAddress.random(), functionSelector: FunctionSelector.empty(), isDelegateCall: false, isStaticCall: false, diff --git a/yarn-project/simulator/src/public/db.ts b/yarn-project/simulator/src/public/db.ts index 68e08315d6b..b316ccaba2f 100644 --- a/yarn-project/simulator/src/public/db.ts +++ b/yarn-project/simulator/src/public/db.ts @@ -1,5 +1,5 @@ import { type NullifierMembershipWitness } from '@aztec/circuit-types'; -import { type EthAddress, type FunctionSelector, type L1_TO_L2_MSG_TREE_HEIGHT } from '@aztec/circuits.js'; +import { type FunctionSelector, type L1_TO_L2_MSG_TREE_HEIGHT } from '@aztec/circuits.js'; import { type AztecAddress } from '@aztec/foundation/aztec-address'; import { type Fr } from '@aztec/foundation/fields'; import { type ContractInstanceWithAddress } from '@aztec/types/contracts'; @@ -61,13 +61,6 @@ export interface PublicContractsDB { */ getBytecode(address: AztecAddress, selector: FunctionSelector): Promise; - /** - * Returns the portal contract address for an L2 address. - * @param address - The L2 contract address. - * @returns The portal contract address or undefined if not found. - */ - getPortalContractAddress(address: AztecAddress): Promise; - /** * Returns a publicly deployed contract instance. * @param address - Address of the contract. diff --git a/yarn-project/simulator/src/public/index.test.ts b/yarn-project/simulator/src/public/index.test.ts index 5a295aef6cb..04568e3a46a 100644 --- a/yarn-project/simulator/src/public/index.test.ts +++ b/yarn-project/simulator/src/public/index.test.ts @@ -90,7 +90,6 @@ describe('ACIR public execution simulator', () => { CallContext.from({ storageContractAddress, msgSender: AztecAddress.random(), - portalContractAddress: EthAddress.random(), functionSelector: FunctionSelector.empty(), isDelegateCall: false, isStaticCall: false, @@ -345,11 +344,10 @@ describe('ACIR public execution simulator', () => { const createL2ToL1MessagePublicArtifact = TestContractArtifact.functions.find( f => f.name === 'create_l2_to_l1_message_public', )!; - const args = encodeArguments(createL2ToL1MessagePublicArtifact, params); - const portalContractAddress = EthAddress.random(); + const args = encodeArguments(createL2ToL1MessagePublicArtifact, [...params, portalContractAddress]); - const callContext = makeCallContext(contractAddress, { portalContractAddress }); + const callContext = makeCallContext(contractAddress); publicContracts.getBytecode.mockResolvedValue(createL2ToL1MessagePublicArtifact.bytecode); @@ -419,12 +417,16 @@ describe('ACIR public execution simulator', () => { secret, ); - const computeArgs = () => encodeArguments(mintPublicArtifact, [tokenRecipient, bridgedAmount, secret, leafIndex]); + const computeArgs = () => + encodeArguments(mintPublicArtifact, [ + tokenRecipient, + bridgedAmount, + secret, + leafIndex, + crossChainMsgSender ?? preimage.sender.sender, + ]); - const computeCallContext = () => - makeCallContext(contractAddress, { - portalContractAddress: crossChainMsgSender ?? preimage.sender.sender, - }); + const computeCallContext = () => makeCallContext(contractAddress); const computeGlobalVariables = () => new GlobalVariables( diff --git a/yarn-project/simulator/src/public/public_execution_context.ts b/yarn-project/simulator/src/public/public_execution_context.ts index 96a5627ca21..c3ac433ce29 100644 --- a/yarn-project/simulator/src/public/public_execution_context.ts +++ b/yarn-project/simulator/src/public/public_execution_context.ts @@ -9,7 +9,6 @@ import { PublicContextInputs, } from '@aztec/circuits.js'; import { type AztecAddress } from '@aztec/foundation/aztec-address'; -import { EthAddress } from '@aztec/foundation/eth-address'; import { Fr } from '@aztec/foundation/fields'; import { createDebugLogger } from '@aztec/foundation/log'; import { type ContractInstance } from '@aztec/types/contracts'; @@ -197,12 +196,10 @@ export class PublicExecutionContext extends TypedOracle { `Public function call: addr=${targetContractAddress} selector=${functionSelector} args=${args.join(',')}`, ); - const portalAddress = (await this.contractsDb.getPortalContractAddress(targetContractAddress)) ?? EthAddress.ZERO; const functionData = new FunctionData(functionSelector, /*isPrivate=*/ false); const callContext = CallContext.from({ msgSender: isDelegateCall ? this.execution.callContext.msgSender : this.execution.contractAddress, storageContractAddress: isDelegateCall ? this.execution.contractAddress : targetContractAddress, - portalContractAddress: portalAddress, functionSelector, isDelegateCall, isStaticCall, diff --git a/yarn-project/simulator/src/public/public_executor.ts b/yarn-project/simulator/src/public/public_executor.ts index c40a815732b..f875322950a 100644 --- a/yarn-project/simulator/src/public/public_executor.ts +++ b/yarn-project/simulator/src/public/public_executor.ts @@ -3,7 +3,6 @@ import { type AztecAddress, ContractClassRegisteredEvent, ContractInstanceDeployedEvent, - type EthAddress, Fr, type FunctionSelector, type L1_TO_L2_MSG_TREE_HEIGHT, @@ -95,11 +94,6 @@ export class ContractsDataSourcePublicDB implements PublicContractsDB { } return contractClass.publicFunctions.find(f => f.selector.equals(selector))?.bytecode; } - - async getPortalContractAddress(address: AztecAddress): Promise { - const contract = await this.getContractInstance(address); - return contract?.portalContractAddress; - } } /** diff --git a/yarn-project/simulator/src/public/transitional_adaptors.ts b/yarn-project/simulator/src/public/transitional_adaptors.ts index 204db746fd8..a3ba62e191f 100644 --- a/yarn-project/simulator/src/public/transitional_adaptors.ts +++ b/yarn-project/simulator/src/public/transitional_adaptors.ts @@ -42,7 +42,6 @@ export function createAvmExecutionEnvironment( current.contractAddress, current.callContext.storageContractAddress, current.callContext.msgSender, - current.callContext.portalContractAddress, globalVariables.gasFees.feePerL1Gas, globalVariables.gasFees.feePerL2Gas, globalVariables.gasFees.feePerDaGas, @@ -63,7 +62,6 @@ export function createPublicExecutionContext(avmContext: AvmContext, calldata: F const callContext = CallContext.from({ msgSender: avmContext.environment.sender, storageContractAddress: avmContext.environment.storageAddress, - portalContractAddress: avmContext.environment.portal, functionSelector: avmContext.environment.temporaryFunctionSelector, isDelegateCall: avmContext.environment.isDelegateCall, isStaticCall: avmContext.environment.isStaticCall, diff --git a/yarn-project/simulator/src/test/utils.ts b/yarn-project/simulator/src/test/utils.ts index 5b611e84602..56231284d8e 100644 --- a/yarn-project/simulator/src/test/utils.ts +++ b/yarn-project/simulator/src/test/utils.ts @@ -23,7 +23,5 @@ export const buildL1ToL2Message = ( const content = sha256ToField([selectorBuf, ...contentPreimage]); const secretHash = computeMessageSecretHash(secret); - // Eventually the kernel will need to prove the kernel portal pair exists within the contract tree, - // EthAddress.random() will need to be replaced when this happens return new L1ToL2Message(new L1Actor(EthAddress.random(), 1), new L2Actor(targetContract, 1), content, secretHash); }; diff --git a/yarn-project/types/src/contracts/contract_instance.ts b/yarn-project/types/src/contracts/contract_instance.ts index 8f14656bc90..1a46d2027af 100644 --- a/yarn-project/types/src/contracts/contract_instance.ts +++ b/yarn-project/types/src/contracts/contract_instance.ts @@ -1,5 +1,4 @@ import { AztecAddress } from '@aztec/foundation/aztec-address'; -import { EthAddress } from '@aztec/foundation/eth-address'; import { Fr } from '@aztec/foundation/fields'; import { BufferReader, numToUInt8, serializeToBuffer } from '@aztec/foundation/serialize'; import { type FieldsOf } from '@aztec/foundation/types'; @@ -16,8 +15,6 @@ export interface ContractInstance { contractClassId: Fr; /** Hash of the selector and arguments to the constructor. */ initializationHash: Fr; - /** Optional address of the L1 portal contract. */ - portalContractAddress: EthAddress; /** Optional hash of the struct of public keys used for encryption and nullifying by this contract. */ publicKeysHash: Fr; /** Optional deployer address or zero if this was a universal deploy. */ @@ -31,7 +28,6 @@ export class SerializableContractInstance { public readonly salt: Fr; public readonly contractClassId: Fr; public readonly initializationHash: Fr; - public readonly portalContractAddress: EthAddress; public readonly publicKeysHash: Fr; public readonly deployer: AztecAddress; @@ -42,7 +38,6 @@ export class SerializableContractInstance { this.salt = instance.salt; this.contractClassId = instance.contractClassId; this.initializationHash = instance.initializationHash; - this.portalContractAddress = instance.portalContractAddress; this.publicKeysHash = instance.publicKeysHash; this.deployer = instance.deployer; } @@ -53,7 +48,6 @@ export class SerializableContractInstance { this.salt, this.contractClassId, this.initializationHash, - this.portalContractAddress, this.publicKeysHash, this.deployer, ); @@ -71,7 +65,6 @@ export class SerializableContractInstance { salt: reader.readObject(Fr), contractClassId: reader.readObject(Fr), initializationHash: reader.readObject(Fr), - portalContractAddress: reader.readObject(EthAddress), publicKeysHash: reader.readObject(Fr), deployer: reader.readObject(AztecAddress), }); @@ -83,7 +76,6 @@ export class SerializableContractInstance { salt: Fr.random(), contractClassId: Fr.random(), initializationHash: Fr.random(), - portalContractAddress: EthAddress.random(), publicKeysHash: Fr.random(), deployer: AztecAddress.random(), ...opts, From 029d1e5d4ff679f73dce72779cb316a1d8c7eda8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Mon, 22 Apr 2024 16:48:16 -0300 Subject: [PATCH 069/102] docs: remove mentions of slow updates (#5884) Part of https://github.com/AztecProtocol/aztec-packages/issues/4760. This removes all mentions of the slow updates tree from the docs. I found it simpler to have separate PRs removing docs, updating dependencies and deleting code since some of those interact with one another. There's some to-do's that will be covered by #5508, which will also feature full-fledged explanations on SharedMutable. --- .../contracts/references/slow_updates_tree.md | 123 ------------------ .../contracts/references/storage/main.md | 4 +- .../resources/common_patterns/main.md | 7 +- .../archive_tree/how_to_prove_history.md | 2 +- .../implement_slow_updates.md | 57 -------- .../historical_data/slow_updates_tree/main.md | 77 ----------- .../developers/debugging/sandbox-errors.md | 4 +- .../learn/about_aztec/technical_overview.md | 2 +- docs/docs/learn/concepts/accounts/keys.md | 8 +- docs/docs/learn/concepts/accounts/main.md | 6 +- .../docs/learn/concepts/communication/main.md | 2 +- .../main.md => public_private_calls.md} | 30 +---- .../public_private_calls/slow_updates_tree.md | 73 ----------- docs/docs/misc/roadmap/engineering_roadmap.md | 9 +- docs/netlify.toml | 4 + docs/sidebars.js | 41 +----- 16 files changed, 41 insertions(+), 408 deletions(-) delete mode 100644 docs/docs/developers/contracts/references/slow_updates_tree.md delete mode 100644 docs/docs/developers/contracts/writing_contracts/historical_data/slow_updates_tree/implement_slow_updates.md delete mode 100644 docs/docs/developers/contracts/writing_contracts/historical_data/slow_updates_tree/main.md rename docs/docs/learn/concepts/communication/{public_private_calls/main.md => public_private_calls.md} (81%) delete mode 100644 docs/docs/learn/concepts/communication/public_private_calls/slow_updates_tree.md diff --git a/docs/docs/developers/contracts/references/slow_updates_tree.md b/docs/docs/developers/contracts/references/slow_updates_tree.md deleted file mode 100644 index a179c54a93d..00000000000 --- a/docs/docs/developers/contracts/references/slow_updates_tree.md +++ /dev/null @@ -1,123 +0,0 @@ ---- -title: Slow Updates Tree ---- - -## Struct `SlowMap` - -### Overview - -The `SlowMap` struct is used to interact with a slow updates tree deployed via the SlowTree smart contract. - -### Fields - -| Name | Type | Description | -| ------- | ------- | ------------------------------------ | -| address | `Field` | The address of the SlowTree contract | - -## Functions - -### at - -Returns an instance of `SlowMap` at the specified address. - -**Parameters** - -| Name | Type | Description | -| --------- | -------------- | --------------------------- | -| `address` | `AztecAddress` | The address of the SlowTree | - -**Return** - -| Name | Type | Description | -| ---- | --------- | ---------------------- | -| - | `SlowMap` | The `SlowMap` instance | - -**Example** - -#include_code slowmap_at noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr rust - -### initialize - -Initializes the `SlowMap`. - -**Parameters** - -| Name | Type | Description | -| --------- | --------------- | --------------------- | -| `context` | `PublicContext` | The execution context | - -**Return** - -| Name | Type | Description | -| ---- | ---- | ----------- | -| - | - | - | - -**Example** - -#include_code slowmap_initialize noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr rust - -### read_at_pub - -Reads a value at a specified index from a public function. - -**Parameters** - -| Name | Type | Description | -| --------- | --------------- | --------------------- | -| `context` | `PublicContext` | The execution context | -| `index` | `Field` | The index to read at | - -**Return** - -| Name | Type | Description | -| -------- | ------- | -------------------- | -| `result` | `Field` | The value at `index` | - -**Example** - -#include_code read_at_pub noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr rust - -### read_at - -Reads a value at a specified index from a private function. - -**Parameters** - -| Name | Type | Description | -| --------- | ---------------- | --------------------- | -| `context` | `PrivateContext` | The execution context | -| `index` | `Field` | The index to read at | - -**Return** - -| Name | Type | Description | -| -------- | ------- | -------------------- | -| `result` | `Field` | The value at `index` | - -**Example** - -#include_code slowmap_read_at noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr rust - -### update_at_private - -Updates a value at a specified index from a private function. Does not return anything. - -**Parameters** - -| Name | Type | Description | -| ----------- | ---------------- | --------------------- | -| `context` | `PrivateContext` | The execution context | -| `index` | `Field` | The index to update | -| `new_value` | `Field` | The new value | - -**Example** - -#include_code get_and_update_private noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr rust - -## Updating from public - -This is not a method in the interface as it can be done using regular Aztec.nr public storage update syntax. - -**Example** - -#include_code write_slow_update_public noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr rust diff --git a/docs/docs/developers/contracts/references/storage/main.md b/docs/docs/developers/contracts/references/storage/main.md index aef6fe7cbf3..439784739f4 100644 --- a/docs/docs/developers/contracts/references/storage/main.md +++ b/docs/docs/developers/contracts/references/storage/main.md @@ -26,7 +26,7 @@ On this and the following pages in this section, you’ll learn: Public state variables can be read by anyone, while private state variables can only be read by their owner (or people whom the owner has shared the decrypted data or note viewing key with). -Public state follows the Ethereum style account model, where each contract has its own key-value datastore. Private state follows a UTXO model, where note contents (pre-images) are only known by the sender and those able to decrypt them - see ([state model](../../../../learn/concepts/hybrid_state/main.md) and [private/public execution](../../../../learn/concepts/communication/public_private_calls/main.md)) for more background. +Public state follows the Ethereum style account model, where each contract has its own key-value datastore. Private state follows a UTXO model, where note contents (pre-images) are only known by the sender and those able to decrypt them - see ([state model](../../../../learn/concepts/hybrid_state/main.md) and [private/public execution](../../../../learn/concepts/communication/public_private_calls.md)) for more background. ## Storage struct @@ -94,5 +94,5 @@ require(minters[msg.sender], "caller is not minter"); ## Concepts mentioned - [State Model](../../../../learn/concepts/hybrid_state/main.md) -- [Public-private execution](../../../../learn/concepts/communication/public_private_calls/main.md) +- [Public-private execution](../../../../learn/concepts/communication/public_private_calls.md) - [Function Contexts](../../writing_contracts/functions/context.md) diff --git a/docs/docs/developers/contracts/resources/common_patterns/main.md b/docs/docs/developers/contracts/resources/common_patterns/main.md index 39763df867d..66c3b9b9138 100644 --- a/docs/docs/developers/contracts/resources/common_patterns/main.md +++ b/docs/docs/developers/contracts/resources/common_patterns/main.md @@ -38,11 +38,12 @@ Note - you could also create a note and send it to the user. The problem is ther ### Reading public storage in private -You can't read public storage in private domain. But nevertheless reading public storage is desirable. There are two ways: +You can't read public storage in private domain. But nevertheless reading public storage is desirable. This is the naive way: -1. For public storage that changes infrequently, use the slow updates tree! Learn more about it [here](../../../../learn/concepts/communication/public_private_calls/slow_updates_tree.md). + -2. You pass the data as a parameter to your private method and later assert in public that the data is correct. E.g.: +- You pass the data as a parameter to your private method and later assert in public that the data is correct. E.g.: ```rust struct Storage { diff --git a/docs/docs/developers/contracts/writing_contracts/historical_data/archive_tree/how_to_prove_history.md b/docs/docs/developers/contracts/writing_contracts/historical_data/archive_tree/how_to_prove_history.md index 8b604ca6863..e0068c9e9df 100644 --- a/docs/docs/developers/contracts/writing_contracts/historical_data/archive_tree/how_to_prove_history.md +++ b/docs/docs/developers/contracts/writing_contracts/historical_data/archive_tree/how_to_prove_history.md @@ -1,5 +1,5 @@ --- -title: How to use the Arhive Tree +title: How to use the Archive Tree --- The Aztec Protocol uses an append-only Merkle tree to store hashes of the headers of all previous blocks in the chain as its leaves. This is known as an archive tree. You can learn more about how it works in the [concepts section](../../../../../learn/concepts/storage/trees/main.md#archive-tree). diff --git a/docs/docs/developers/contracts/writing_contracts/historical_data/slow_updates_tree/implement_slow_updates.md b/docs/docs/developers/contracts/writing_contracts/historical_data/slow_updates_tree/implement_slow_updates.md deleted file mode 100644 index 6de1c8abae6..00000000000 --- a/docs/docs/developers/contracts/writing_contracts/historical_data/slow_updates_tree/implement_slow_updates.md +++ /dev/null @@ -1,57 +0,0 @@ ---- -title: How to implement a Slow Updates Tree ---- - -To learn more about the Slow Updates Tree, go [here](./main.md) - -On this page you will learn how to implement a slow updates tree into your contract, and an example of a token blacklisting contract that uses the slow updates tree. - -# How to implement a slow updates tree - -1. Store the SlowTree address in private storage as a FieldNote - -#include_code constructor noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr rust - -2. Store the SlowTree address in public storage and initialize an instance of SlowMap using this address - -#include_code write_slow_update_public noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr rust - -3. Now you can read and update from private functions: - -#include_code get_and_update_private noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr rust - -4. Or from public functions: - -#include_code get_public noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr rust - -View the [reference](../../../references/slow_updates_tree.md) for more information. - -## Exploring an example integration through a **`TokenBlacklist`** Smart Contract - -The `TokenBlacklist` contract is a token contract that does not allow blacklisted accounts to perform mints or transfers. In this section we will go through how this is achieved through the slow updates tree. - -You can find the full code for the TokenBlacklist smart contract [here](https://github.com/AztecProtocol/aztec-packages/tree/master/noir-projects/noir-contracts/contracts/token_blacklist_contract). - -### Importing SlowMap - -The contract first imports the **`SlowMap`** interface: - -#include_code interface noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr rust - -This interface allows the contract to interact with its attached SlowTree. It abstracts these functions so they do not have to be implemented in the TokenBlacklist contract. - -### Constructor and initialization - -The contract's constructor takes the address of the slow updates contract: - -#include_code constructor noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr rust - -This initialization sets up the connection between the **`TokenBlacklist`** contract and a previously deployed SlowTree, allowing it to use the interface to directly interact with the SlowTree. - -### Private transfer function utilizing the slow updates tree - -In the private transfer function, the contract uses the interface to check if a user is blacklisted: - -#include_code transfer_private noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr rust - -Here, the contract reads the roles of the sender and recipient from the SlowTree using the **`read_at`** function in the interface. It checks if either party is blacklisted, and if so, the transaction does not go ahead. diff --git a/docs/docs/developers/contracts/writing_contracts/historical_data/slow_updates_tree/main.md b/docs/docs/developers/contracts/writing_contracts/historical_data/slow_updates_tree/main.md deleted file mode 100644 index 4edc82d0537..00000000000 --- a/docs/docs/developers/contracts/writing_contracts/historical_data/slow_updates_tree/main.md +++ /dev/null @@ -1,77 +0,0 @@ ---- -title: Slow Updates Tree ---- - -Slow Updates Tree is a data structure that allows for historical public data to be accessed in both private and public domains. Read the high level overview in the [Communication section](../../../../../learn/concepts/communication/public_private_calls/slow_updates_tree.md). This page explains the components involved. - -If you want to integrate it in your contract, follow this [guide](../slow_updates_tree/implement_slow_updates.md). - -The slow updates tree works by having a current tree and a pending tree, and replacing the current tree with the pending tree after an epoch has passed. Public functions can read directly from the current tree, and private functions can perform a membership proof that values are part of a commitment to the current state of the tree. - -# Components involved in implementing a slow updates tree - -There are generally 4 main components involved to make it easier to use a slow updates tree, with 3 already implemented by Aztec. This makes it easier to interact with a slow updates tree through a simple interface. These four components are: - -## Main smart contract - -This is the primary smart contract that will use the slow updates tree. In the example we use a [token with blacklisting features](./implement_slow_updates.md#exploring-an-example-integration-through-a-tokenblacklist-smart-contract). - -## SlowTree.nr contract - -This is a smart contract developed by Aztec that establishes and manages a slow updates tree structure. It allows developers to access and interact with the tree, such as reading and updating data. - -You can find it [here](https://github.com/AztecProtocol/aztec-packages/tree/master/noir-projects/noir-contracts/contracts/slow_tree_contract). - -## SlowMap type - -This is a type in the Aztec.nr library that is utilized by the SlowTree contract. It defines the underlying data structure for the slow updates tree, and handles storing both the current and pending values for each data entry. - -You can find it [here](https://github.com/AztecProtocol/aztec-nr/blob/master/slow-updates-tree/src/slow_map.nr). - -The diagram below describes how these components work together. It does not contain all the functionality. - -```mermaid -graph TD - MSC[Main Smart Contract] --> INT[Interface] - STC --> SMT - - INT_RAP[read_at_pub] <--> STC_RAP[read_at_public] - INT_RA[read_at] <--> STC_RA[read_at] - INT_UAP[update_at_public] <--> STC_UAP[update_at_public] - INT_UA[update_at_private] <--> STC_UA[update_at_private] - - STC_RA <--> VMP[verify_membership_proof] - STC_UA <--> CR[compute_roots] - - subgraph INT[Interface] - INT_RAP - INT_UAP - INT_RA - INT_UA - end - - subgraph STC[SlowTree.nr] - STC_RAP - STC_UAP - STC_RA - STC_UA - end - - subgraph SMT[SlowMap Type] - Change{Epoch Over} -->|True| Current{Current} - Change -->|False| Pending{Pending} - Current --> Current1[Current Commitment 1] - Current --> CurrentM[Current Commitment M] - CurrentM --> Value1[Current Value 1] - CurrentM --> Value2[Current Value 2] - CurrentM --> ValueN[Current Value N] - Pending --> PendingM[Pending Commitment 1] - PendingM --> PValue1[Pending Value 1] - PendingM --> PValue2[Pending Value 2] - PendingM --> PValueN[Pending Value N] - end - - style INT fill:#fff,stroke:#333,stroke-width:1px - style STC fill:#fff,stroke:#333,stroke-width:1px - style SMT fill:#fff,stroke:#333,stroke-width:1px -``` diff --git a/docs/docs/developers/debugging/sandbox-errors.md b/docs/docs/developers/debugging/sandbox-errors.md index a67ecc3c0c8..212e3d80b6d 100644 --- a/docs/docs/developers/debugging/sandbox-errors.md +++ b/docs/docs/developers/debugging/sandbox-errors.md @@ -86,7 +86,7 @@ Calling a private Aztec.nr function in a public kernel is not allowed. #### 3005 - PUBLIC_KERNEL\_\_NON_EMPTY_PRIVATE_CALL_STACK -Public functions are executed after all the private functions are (see [private-public execution](../../learn/concepts/communication/public_private_calls/main.md)). As such, private call stack must be empty when executing in the public kernel. +Public functions are executed after all the private functions are (see [private-public execution](../../learn/concepts/communication/public_private_calls.md)). As such, private call stack must be empty when executing in the public kernel. #### 3011 - PUBLIC_KERNEL\_\_CALCULATED_PRIVATE_CALL_HASH_AND_PROVIDED_PRIVATE_CALL_HASH_MISMATCH @@ -189,7 +189,7 @@ Users may create a proof against a historical state in Aztec. The rollup circuit - "${treeName} tree next available leaf index mismatch" - validating a tree's root is not enough. It also checks that the `next_available_leaf_index` is as expected. This is the next index we can insert new values into. Note that for the public data tree, this test is skipped since as it is a sparse tree unlike the others. -- "Public call stack size exceeded" - In Aztec, the sequencer executes all enqueued public functions in a transaction (to prevent race conditions - see [private-public execution](../../learn/concepts/communication/public_private_calls/main.md)). This error says there are too many public functions requested. +- "Public call stack size exceeded" - In Aztec, the sequencer executes all enqueued public functions in a transaction (to prevent race conditions - see [private-public execution](../../learn/concepts/communication/public_private_calls.md)). This error says there are too many public functions requested. - "Array size exceeds target length" - happens if you add more items than allowed by the constants set due to our circuit limitations (eg sending too many L2 to L1 messages or creating a function that exceeds the call stack length or returns more values than what Aztec.nr functions allow) diff --git a/docs/docs/learn/about_aztec/technical_overview.md b/docs/docs/learn/about_aztec/technical_overview.md index 7192e34d316..eed3e31f36e 100644 --- a/docs/docs/learn/about_aztec/technical_overview.md +++ b/docs/docs/learn/about_aztec/technical_overview.md @@ -40,7 +40,7 @@ A user of the Aztec network will interact with the network through Aztec.js. Azt ### Private Execution Environment -The PXE provides a secure environment for the execution of sensitive operations, ensuring private information and decrypted data are not accessible to unauthorized applications. It hides the details of the [state model](../concepts/hybrid_state/main.md) from end users, but the state model is important for Aztec developers to understand as it has implications for [private/public execution](../concepts/communication/public_private_calls/main.md) and [L1/L2 communication](../concepts/communication/cross_chain_calls.md). The PXE also includes the [ACIR Simulator](../concepts/pxe/acir_simulator.md) for private executions and the KeyStore for secure key management. +The PXE provides a secure environment for the execution of sensitive operations, ensuring private information and decrypted data are not accessible to unauthorized applications. It hides the details of the [state model](../concepts/hybrid_state/main.md) from end users, but the state model is important for Aztec developers to understand as it has implications for [private/public execution](../concepts/communication/public_private_calls.md) and [L1/L2 communication](../concepts/communication/cross_chain_calls.md). The PXE also includes the [ACIR Simulator](../concepts/pxe/acir_simulator.md) for private executions and the KeyStore for secure key management. Procedurally, the PXE sends results of private function execution and requests for public function executions to the [sequencer](../concepts/nodes_clients/sequencer/main.md), which will update the state of the rollup. diff --git a/docs/docs/learn/concepts/accounts/keys.md b/docs/docs/learn/concepts/accounts/keys.md index ed91e7928fe..5864abdc028 100644 --- a/docs/docs/learn/concepts/accounts/keys.md +++ b/docs/docs/learn/concepts/accounts/keys.md @@ -27,9 +27,15 @@ Storing the signing public key in a private note makes it accessible from the en Similar to using a private note, but using an immutable private note removes the need to nullify the note on every read. This generates less nullifiers and commitments per transaction, and does not enforce an order across transactions. However, it does not allow the user to rotate their key should they lose it. + ### Reusing the privacy master key diff --git a/docs/docs/learn/concepts/accounts/main.md b/docs/docs/learn/concepts/accounts/main.md index 6e75172f0bd..deac366c16c 100644 --- a/docs/docs/learn/concepts/accounts/main.md +++ b/docs/docs/learn/concepts/accounts/main.md @@ -129,7 +129,11 @@ These two patterns combined allow an account contract to answer whether an actio Aztec requires users to define [encryption and nullifying keys](./keys.md) that are needed for receiving and spending private notes. Unlike transaction signing, encryption and nullifying is enshrined at the protocol. This means that there is a single scheme used for encryption and nullifying. These keys are derived from a master public key. This master public key, in turn, is used when deterministically deriving the account's address. -A side effect of committing to a master public key as part of the address is that _this key cannot be rotated_. While an account contract implementation could include methods for rotating the signing key, this is unfortunately not possible for encryption and nullifying keys (note that rotating nullifying keys also creates other challenges such as preventing double spends). We are exploring usage of the [slow updates tree](../communication/public_private_calls/slow_updates_tree.md) to enable rotating these keys. +A side effect of committing to a master public key as part of the address is that _this key cannot be rotated_. While an account contract implementation could include methods for rotating the signing key, this is unfortunately not possible for encryption and nullifying keys (note that rotating nullifying keys also creates other challenges such as preventing double spends). + + NOTE: While we entertained the idea of abstracting note encryption, where account contracts would define an `encrypt` method that would use a user-defined scheme, there are two main reasons we decided against this. First is that this entailed that, in order to receive funds, a user had to first deploy their account contract, which is a major UX issue. Second, users could define malicious `encrypt` methods that failed in certain circumstances, breaking application flows that required them to receive a private note. While this issue already exists in Ethereum when transferring ETH (see the [king of the hill](https://coinsbench.com/27-king-ethernaut-da5021cd4aa6)), its impact is made worse in Aztec since any execution failure in a private function makes the entire transaction unprovable (ie it is not possible to catch errors in calls to other private functions), and furthermore because encryption is required for any private state (not just for transferring ETH). Nevertheless, both of these problems are solvable. Initialization can be worked around by embedding a commitment to the bytecode in the address and removing the need for actually deploying contracts before interacting with them, and the king of the hill issue can be mitigated by introducing a full private VM that allows catching reverts. As such, we may be able to abstract encryption in the future as well. diff --git a/docs/docs/learn/concepts/communication/main.md b/docs/docs/learn/concepts/communication/main.md index 99588c9bc7c..a893fe7484d 100644 --- a/docs/docs/learn/concepts/communication/main.md +++ b/docs/docs/learn/concepts/communication/main.md @@ -4,6 +4,6 @@ title: Contract Communication This section will walk over communication types that behaves differently than normal function calls. -Namely, if functions are in different domains, private vs. public, their execution behaves a little differently to what you might expect! See [Private <--> Public execution](./public_private_calls/main.md). +Namely, if functions are in different domains, private vs. public, their execution behaves a little differently to what you might expect! See [Private <--> Public execution](./public_private_calls.md). Likewise, executing a function on a different domain than its origin needs a bit extra thought. See [L1 <--> L2 communication](./cross_chain_calls.md). diff --git a/docs/docs/learn/concepts/communication/public_private_calls/main.md b/docs/docs/learn/concepts/communication/public_private_calls.md similarity index 81% rename from docs/docs/learn/concepts/communication/public_private_calls/main.md rename to docs/docs/learn/concepts/communication/public_private_calls.md index eca7d2ccb54..2bd3d02e037 100644 --- a/docs/docs/learn/concepts/communication/public_private_calls/main.md +++ b/docs/docs/learn/concepts/communication/public_private_calls.md @@ -1,10 +1,10 @@ --- -title: Private - Public execution +title: Private <> Public Communication --- import Image from "@theme/IdealImage"; -import Disclaimer from "../../../../misc/common/\_disclaimer.mdx"; +import Disclaimer from "../../../misc/common/\_disclaimer.mdx"; @@ -78,32 +78,10 @@ Theoretically the builder has all the state trees after the public function has From the above, we should have a decent idea about what private and public functions can do inside the L2, and how they might interact. + diff --git a/docs/docs/learn/concepts/communication/public_private_calls/slow_updates_tree.md b/docs/docs/learn/concepts/communication/public_private_calls/slow_updates_tree.md deleted file mode 100644 index 1e0d44ae666..00000000000 --- a/docs/docs/learn/concepts/communication/public_private_calls/slow_updates_tree.md +++ /dev/null @@ -1,73 +0,0 @@ ---- -title: Privately access Historical Public Data ---- - -In Aztec, private and public execution environments are completely separate and operate with distinct state management. It is not possible for private functions to reliably access the most recent public data public state - only sequencers can do that. You'll want to [read the previous section](./main.md) to understand this before reading this page. - -But, what about historical public data (or public data that changes infrequently)? Through a **slow updates tree**, private functions can access historical public state. Please note that we are still experimenting with this feature. - -On this page you will learn: - -1. Why a slow updates tree exists & use cases -2. How it works -3. How it can be used to access historical public data -4. Limitations - -## The need for a slow updates tree - -This structure was created specifically to privately & publicly access historical public data. It should be used to store public data that doesn't change often. - -- Access historical public data from a private function -- Access historical public data from a public function -- Update public data (that does not need updated often) from public and private functions - -This data structure is ideal for these use cases: - -- Address Registry: Enabling contracts to interact with other contracts more easily requires address storage accessible in both public and private executions. This can be particularly helpful in things such as proxy contracts. -- Access Control: Managing privileges in contracts, such as a token contract owner’s ability to mint new tokens, is streamlined when control information is shared between public and private executions. This might include things like blacklists and whitelists. - -## How it works - -We developed the Slow Updates Tree to help balance public and private execution in a blockchain context. Earlier systems typically used either fully public or entirely private state trees. - -The Slow Updates Tree is a dual-tree structure - a current tree and a pending tree. Any updates are added to the pending tree, which then becomes the current tree at the end of an epoch. The pending tree is replicated from the current tree, and the cycle begins again. - -```mermaid -graph TD; - Change{Epoch Over} -->|True| Current{Current} - Change -->|False| Pending{Pending} - Current --> Current1[Current Commitment 1] - Current --> CurrentM[Current Commitment 2] - CurrentM --> Value1[Current Value 1] - CurrentM --> Value2[Current Value 2] - CurrentM --> ValueN[Current Value n] - Pending --> PendingM[Pending Note Hash 1] - PendingM --> PValue1[Pending Value 1] - PendingM --> PValue2[Pending Value 2] - PendingM --> PValueN[Pending Value n] -``` - -This way, we can ensure that the values are stable throughout the epoch, and that the membership proofs are not invalidated by changes in other contracts more than once every epoch. - -## Reads and Writes - -### Accessing Data - -*From public state:* Accessed directly from the state -*From private state:* Performs a membership proof for the values in the tree, ensuring that they are part of the commitment. - -### Updating Data - -Updates are made to the pending tree. Then at the end of each epoch, the updates in the pending tree are committed and it becomes the current tree. - -## Limitations - -### Delayed State Finality - -Updates in the Slow Updates Tree are only finalized at the end of an epoch. - -Developers are used to instant state updates, so the Slow Updates Tree might take some getting used to. But we believe this won't take long! - -## Dive into the code - -For a code walkthrough of how a token blacklist contract can use a slow updates tree, read [this](../../../../developers/contracts/writing_contracts/historical_data/slow_updates_tree/implement_slow_updates.md). \ No newline at end of file diff --git a/docs/docs/misc/roadmap/engineering_roadmap.md b/docs/docs/misc/roadmap/engineering_roadmap.md index 2e232a2c023..51e49405774 100644 --- a/docs/docs/misc/roadmap/engineering_roadmap.md +++ b/docs/docs/misc/roadmap/engineering_roadmap.md @@ -19,7 +19,7 @@ The engineering roadmap is long. There are no timings assigned here. In a loose ## Standardization efforts - Recommended Aztec smart contract coding patterns -- Access Control (whitelists/blacklists) - probably needs the Slow Updates tree (or something similar). +- Access Control (whitelists/blacklists) - probably needs the Shared Mutable. - Basic _example_ private tokens - Including recursive calls to 'get_notes'. - Compliant private tokens @@ -117,11 +117,10 @@ CI takes up a significant amount of time. It gets its own section here, so we re - Do a RFC from the external community - Implement -## Slow Updates tree? +## Shared Mutable State -We _need_ a way to read mutable public data from a private function. - -Note: we just published the [Slow Updates Tree](../../learn/concepts/communication/public_private_calls/slow_updates_tree.md). +We _need_ a way to read mutable public data from a private function. We are moving away from the old Slow Updates Tree in favor of Shared Mutable. + ## Contract classes and instances? diff --git a/docs/netlify.toml b/docs/netlify.toml index 4a2b63e0e92..736bb7fbec2 100644 --- a/docs/netlify.toml +++ b/docs/netlify.toml @@ -154,6 +154,10 @@ from="/concepts/foundation/communication/public_private_calls" to="/learn/concepts/communication/public_private_calls/main" +[[redirects]] + from="/learn/concepts/communication/public_private_calls/main" + to="/learn/concepts/communication/public_private_calls" + [[redirects]] from = "/aztec/how-it-works/l1-l2-messaging" to = "/learn/concepts/communication/cross_chain_calls" diff --git a/docs/sidebars.js b/docs/sidebars.js index f4725933719..c10514ddbe9 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -138,18 +138,12 @@ const sidebars = { { label: "Communication", type: "category", + link: { + type: "doc", + id: "learn/concepts/communication/main", + }, items: [ - { - label: "Public <> Private Communication", - type: "category", - link: { - type: "doc", - id: "learn/concepts/communication/public_private_calls/main", - }, - items: [ - "learn/concepts/communication/public_private_calls/slow_updates_tree", - ], - }, + "learn/concepts/communication/public_private_calls", "learn/concepts/communication/cross_chain_calls", ], }, @@ -406,29 +400,7 @@ const sidebars = { label: "Historical Data", type: "category", items: [ - { - label: "Historical Blockchain Data (Archive Tree)", - type: "category", - link: { - type: "doc", - id: "developers/contracts/writing_contracts/historical_data/slow_updates_tree/main", - }, - items: [ - "developers/contracts/writing_contracts/historical_data/archive_tree/how_to_prove_history", - ], - }, - ], - }, - { - label: - "Access public data from private state (Slow Updates Tree)", - type: "category", - link: { - type: "doc", - id: "developers/contracts/writing_contracts/historical_data/slow_updates_tree/main", - }, - items: [ - "developers/contracts/writing_contracts/historical_data/slow_updates_tree/implement_slow_updates", + "developers/contracts/writing_contracts/historical_data/archive_tree/how_to_prove_history", ], }, ], @@ -482,7 +454,6 @@ const sidebars = { items: aztecNRSidebar, }, "developers/contracts/references/history_lib_reference", - "developers/contracts/references/slow_updates_tree", ], }, { From 26c1eecc76613c7c7883031691672ba36fb16152 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Mon, 22 Apr 2024 17:33:22 -0300 Subject: [PATCH 070/102] chore: migrate blacklist token to use shared mutable (#5885) Closes https://github.com/AztecProtocol/aztec-packages/issues/4760 This fully migrates the `TokenBlacklist` contract to use a `SharedMutable` state variable instead of the slow updates tree. It mostly consists of deleting things we no longer need, like tree simulation, initialization, capsule creation and pushing, etc. The only relevant change is that `SharedMutable` does not allow for scheduling from private. This is trivially achievable though by making an internal public function that does this and then privately call it (which is what the slow tree did), but this hardly seemed relevant so I simply made the `set_roles` function public. --- ## Macros and Storage Slots This PR also references https://github.com/AztecProtocol/aztec-packages/issues/5736, since it shows how that forces us to implement `Serialize` even when we don't need to. It also ends up being useless, since what we need to store is a `ScheduledValueChange`, which has a serialize length of 3, and not a `UserFlags` (even though the state variable is `SharedMutable`). It's a good example of state variables implementing custom data structures that may require storage separate from the underlying type. --------- Co-authored-by: ludamad --- .../token_blacklist_contract/src/main.nr | 105 ++-- .../src/types/roles.nr | 61 ++- .../src/e2e_blacklist_token_contract.test.ts | 507 +++++------------- 3 files changed, 213 insertions(+), 460 deletions(-) diff --git a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr index ddb115c721e..5ec01d4f26a 100644 --- a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr @@ -1,14 +1,12 @@ mod types; -// Minimal token implementation that supports `AuthWit` accounts and the slow update tree. + +// Minimal token implementation that supports `AuthWit` accounts and SharedMutable variables. // The auth message follows a similar pattern to the cross-chain message and includes a designated caller. // The designated caller is ALWAYS used here, and not based on a flag as cross-chain. // message hash = H([caller, contract, selector, ...args]) // To be read as `caller` calls function at `contract` defined by `selector` with `args` // Including a nonce in the message hash ensures that the message can only be used once. -// The slow updates tree are used for access control related to minters and blacklist. - -// TODO's: https://github.com/AztecProtocol/aztec-packages/issues/3210 -// We are currently unable to do constructor -> private calls +// The SharedMutables are used for access control related to minters and blacklist. contract TokenBlacklist { // Libs @@ -16,7 +14,8 @@ contract TokenBlacklist { use dep::aztec::protocol_types::{abis::function_selector::FunctionSelector, address::AztecAddress}; use dep::aztec::{ note::{note_getter_options::NoteGetterOptions, note_header::NoteHeader}, - hash::compute_secret_hash, state_vars::{Map, PublicMutable, PrivateSet, SharedImmutable} + hash::compute_secret_hash, + state_vars::{Map, PublicMutable, PrivateSet, SharedMutable, SharedImmutable} }; use dep::field_note::field_note::FieldNote; @@ -24,77 +23,46 @@ contract TokenBlacklist { use dep::authwit::{auth::{assert_current_call_valid_authwit, assert_current_call_valid_authwit_public}}; use crate::types::{transparent_note::TransparentNote, token_note::TokenNote, balances_map::BalancesMap, roles::UserFlags}; - // docs:start:interface - use dep::slow_tree::SlowTree; - // docs:end:interface + + // Changing an address' roles has a certain block delay before it goes into effect. + global CHANGE_ROLES_DELAY_BLOCKS = 5; #[aztec(storage)] struct Storage { - admin: PublicMutable, balances: BalancesMap, total_supply: PublicMutable, pending_shields: PrivateSet, public_balances: Map>, - slow_update: SharedImmutable, + roles: Map>, } // docs:start:constructor #[aztec(public)] #[aztec(initializer)] - fn constructor(admin: AztecAddress, slow_updates_contract: AztecAddress) { - // docs:end:constructor - assert(!admin.is_zero(), "invalid admin"); - storage.admin.write(admin); - // docs:start:write_slow_update_public - storage.slow_update.initialize(slow_updates_contract); - // docs:end:write_slow_update_public - // docs:start:slowmap_initialize - SlowTree::at(slow_updates_contract).initialize().call(&mut context); - // docs:end:slowmap_initialize - // We cannot do the following atm - // let roles = UserFlags { is_admin: true, is_minter: false, is_blacklisted: false }.get_value().to_field(); - // SlowTree::at(slow_updates_contract).update_at_private(&mut context, admin.to_field(), roles); - } - - #[aztec(private)] - fn init_slow_tree(user: AztecAddress) { - let roles = UserFlags { is_admin: true, is_minter: false, is_blacklisted: false }.get_value().to_field(); - // docs:start:get_and_update_private - SlowTree::at(storage.slow_update.read_private()).update_at_private(user.to_field(), roles).call(&mut context); - // docs:end:get_and_update_private - TokenBlacklist::at(context.this_address())._init_slow_tree(context.msg_sender()).enqueue(&mut context); + fn constructor(admin: AztecAddress) { + let admin_roles = UserFlags { is_admin: true, is_minter: false, is_blacklisted: false }; + storage.roles.at(admin).schedule_value_change(admin_roles); } #[aztec(public)] - #[aztec(internal)] - fn _init_slow_tree(caller: AztecAddress) { - assert(storage.admin.read().eq(caller), "caller is not admin"); + fn get_roles(user: AztecAddress) -> UserFlags { + storage.roles.at(user).get_current_value_in_public() } - #[aztec(private)] - fn update_roles(user: AztecAddress, roles: Field) { - // docs:start:slowmap_at - let slow = SlowTree::at(storage.slow_update.read_private()); - // docs:end:slowmap_at - let role = slow.read_at(context.msg_sender().to_field()).call(&mut context); - - let caller_roles = UserFlags::new(U128::from_integer(role)); + #[aztec(public)] + fn update_roles(user: AztecAddress, roles: UserFlags) { + let caller_roles = storage.roles.at(context.msg_sender()).get_current_value_in_public(); assert(caller_roles.is_admin, "caller is not admin"); - slow.update_at_private(user.to_field(), roles).call(&mut context); + storage.roles.at(user).schedule_value_change(roles); } #[aztec(public)] fn mint_public(to: AztecAddress, amount: Field) { - // docs:start:get_public - let slow = SlowTree::at(storage.slow_update.read_public()); - // docs:end:get_public - // docs:start:read_at_pub - let to_roles = UserFlags::new(U128::from_integer(slow.read_at_pub(to.to_field()).call(&mut context))); - // docs:end:read_at_pub + let to_roles = storage.roles.at(to).get_current_value_in_public(); assert(!to_roles.is_blacklisted, "Blacklisted: Recipient"); - let caller_roles = UserFlags::new(U128::from_integer(slow.read_at_pub(context.msg_sender().to_field()).call(&mut context))); + let caller_roles = storage.roles.at(context.msg_sender()).get_current_value_in_public(); assert(caller_roles.is_minter, "caller is not minter"); let amount = U128::from_integer(amount); @@ -107,8 +75,7 @@ contract TokenBlacklist { #[aztec(public)] fn mint_private(amount: Field, secret_hash: Field) { - let slow = SlowTree::at(storage.slow_update.read_public()); - let caller_roles = UserFlags::new(U128::from_integer(slow.read_at_pub(context.msg_sender().to_field()).call(&mut context))); + let caller_roles = storage.roles.at(context.msg_sender()).get_current_value_in_public(); assert(caller_roles.is_minter, "caller is not minter"); let pending_shields = storage.pending_shields; @@ -121,8 +88,7 @@ contract TokenBlacklist { #[aztec(public)] fn shield(from: AztecAddress, amount: Field, secret_hash: Field, nonce: Field) { - let slow = SlowTree::at(storage.slow_update.read_public()); - let from_roles = UserFlags::new(U128::from_integer(slow.read_at_pub(from.to_field()).call(&mut context))); + let from_roles = storage.roles.at(from).get_current_value_in_public(); assert(!from_roles.is_blacklisted, "Blacklisted: Sender"); if (!from.eq(context.msg_sender())) { @@ -144,10 +110,9 @@ contract TokenBlacklist { #[aztec(public)] fn transfer_public(from: AztecAddress, to: AztecAddress, amount: Field, nonce: Field) { - let slow = SlowTree::at(storage.slow_update.read_public()); - let from_roles = UserFlags::new(U128::from_integer(slow.read_at_pub(from.to_field()).call(&mut context))); + let from_roles = storage.roles.at(from).get_current_value_in_public(); assert(!from_roles.is_blacklisted, "Blacklisted: Sender"); - let to_roles = UserFlags::new(U128::from_integer(slow.read_at_pub(to.to_field()).call(&mut context))); + let to_roles = storage.roles.at(to).get_current_value_in_public(); assert(!to_roles.is_blacklisted, "Blacklisted: Recipient"); if (!from.eq(context.msg_sender())) { @@ -166,8 +131,7 @@ contract TokenBlacklist { #[aztec(public)] fn burn_public(from: AztecAddress, amount: Field, nonce: Field) { - let slow = SlowTree::at(storage.slow_update.read_public()); - let from_roles = UserFlags::new(U128::from_integer(slow.read_at_pub(from.to_field()).call(&mut context))); + let from_roles = storage.roles.at(from).get_current_value_in_public(); assert(!from_roles.is_blacklisted, "Blacklisted: Sender"); if (!from.eq(context.msg_sender())) { @@ -186,10 +150,7 @@ contract TokenBlacklist { #[aztec(private)] fn redeem_shield(to: AztecAddress, amount: Field, secret: Field) { - let slow = SlowTree::at(storage.slow_update.read_private()); - // docs:start:slowmap_read_at - let to_roles = UserFlags::new(U128::from_integer(slow.read_at(to.to_field()).call(&mut context))); - // docs:end:slowmap_read_at + let to_roles = storage.roles.at(to).get_current_value_in_private(); assert(!to_roles.is_blacklisted, "Blacklisted: Recipient"); let pending_shields = storage.pending_shields; @@ -213,10 +174,9 @@ contract TokenBlacklist { #[aztec(private)] fn unshield(from: AztecAddress, to: AztecAddress, amount: Field, nonce: Field) { - let slow = SlowTree::at(storage.slow_update.read_private()); - let from_roles = UserFlags::new(U128::from_integer(slow.read_at(from.to_field()).call(&mut context))); + let from_roles = storage.roles.at(from).get_current_value_in_private(); assert(!from_roles.is_blacklisted, "Blacklisted: Sender"); - let to_roles = UserFlags::new(U128::from_integer(slow.read_at(to.to_field()).call(&mut context))); + let to_roles = storage.roles.at(to).get_current_value_in_private(); assert(!to_roles.is_blacklisted, "Blacklisted: Recipient"); if (!from.eq(context.msg_sender())) { @@ -234,12 +194,10 @@ contract TokenBlacklist { // docs:start:transfer_private #[aztec(private)] fn transfer(from: AztecAddress, to: AztecAddress, amount: Field, nonce: Field) { - let slow = SlowTree::at(storage.slow_update.read_private()); - let from_roles = UserFlags::new(U128::from_integer(slow.read_at(from.to_field()).call(&mut context))); + let from_roles = storage.roles.at(from).get_current_value_in_private(); assert(!from_roles.is_blacklisted, "Blacklisted: Sender"); - let to_roles = UserFlags::new(U128::from_integer(slow.read_at(to.to_field()).call(&mut context))); + let to_roles = storage.roles.at(to).get_current_value_in_private(); assert(!to_roles.is_blacklisted, "Blacklisted: Recipient"); - // docs:end:transfer_private if (!from.eq(context.msg_sender())) { assert_current_call_valid_authwit(&mut context, from); @@ -254,8 +212,7 @@ contract TokenBlacklist { #[aztec(private)] fn burn(from: AztecAddress, amount: Field, nonce: Field) { - let slow = SlowTree::at(storage.slow_update.read_private()); - let from_roles = UserFlags::new(U128::from_integer(slow.read_at(from.to_field()).call(&mut context))); + let from_roles = storage.roles.at(from).get_current_value_in_private(); assert(!from_roles.is_blacklisted, "Blacklisted: Sender"); if (!from.eq(context.msg_sender())) { diff --git a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/roles.nr b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/roles.nr index 8f010dc43b6..a2fe3bd8727 100644 --- a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/roles.nr +++ b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/roles.nr @@ -1,6 +1,8 @@ -global BLACKLIST_FLAG: U128 = U128::from_integer(1); -global MINTER_FLAG: U128 = U128::from_integer(2); -global ADMIN_FLAG: U128 = U128::from_integer(4); +use dep::aztec::protocol_types::traits::{FromField, ToField, Serialize}; + +global ADMIN_FLAG: u64 = 1; +global MINTER_FLAG: u64 = 2; +global BLACKLIST_FLAG: u64 = 4; struct UserFlags { is_admin: bool, @@ -8,18 +10,20 @@ struct UserFlags { is_blacklisted: bool, } -impl UserFlags { - - pub fn new(value: U128) -> Self { +impl FromField for UserFlags { + fn from_field(value: Field) -> UserFlags { + let value: u64 = value as u64; let is_admin = value & ADMIN_FLAG == ADMIN_FLAG; let is_minter = value & MINTER_FLAG == MINTER_FLAG; let is_blacklisted = value & BLACKLIST_FLAG == BLACKLIST_FLAG; Self { is_admin, is_minter, is_blacklisted } } +} - pub fn get_value(self) -> U128 { - let mut value: U128 = U128::from_integer(0); +impl ToField for UserFlags { + fn to_field(self) -> Field { + let mut value: u64 = 0; if self.is_admin { value = value | ADMIN_FLAG; @@ -33,6 +37,45 @@ impl UserFlags { value = value | BLACKLIST_FLAG; } - value + value.to_field() + } +} + +// We don't actually need to implement this trait, but the current macros system requires that all types that are +// contained by a state variable are serializable in order to determine their length. +// Once https://github.com/AztecProtocol/aztec-packages/issues/5736 is closed we'll be able to remove this (unless +// https://github.com/AztecProtocol/aztec-packages/issues/5491 is addressed first, in which case we'd remove the to/from +// field traits instead). +impl Serialize<1> for UserFlags { + fn serialize(self) -> [Field; 1] { + [self.to_field()] + } +} + +mod test { + use crate::types::roles::UserFlags; + + fn assert_to_from_field(is_minter: bool, is_admin: bool, is_blacklisted: bool) { + let flags = UserFlags { is_minter, is_admin, is_blacklisted }; + let converted = UserFlags::from_field(flags.to_field()); + + assert_eq(converted.is_minter, is_minter); + assert_eq(converted.is_admin, is_admin); + assert_eq(converted.is_blacklisted, is_blacklisted); + } + + #[test] + fn test_to_from_field() { + assert_to_from_field(false, false, false); + assert_to_from_field(false, false, true); + + assert_to_from_field(false, true, false); + assert_to_from_field(false, true, true); + + assert_to_from_field(true, false, false); + assert_to_from_field(true, false, true); + + assert_to_from_field(true, true, false); + assert_to_from_field(true, true, true); } } diff --git a/yarn-project/end-to-end/src/e2e_blacklist_token_contract.test.ts b/yarn-project/end-to-end/src/e2e_blacklist_token_contract.test.ts index 023fafb8cd1..8f1d8735bc6 100644 --- a/yarn-project/end-to-end/src/e2e_blacklist_token_contract.test.ts +++ b/yarn-project/end-to-end/src/e2e_blacklist_token_contract.test.ts @@ -1,7 +1,6 @@ import { type AccountWallet, AztecAddress, - type CheatCodes, type DebugLogger, ExtendedNote, Fr, @@ -12,9 +11,7 @@ import { computeAuthWitMessageHash, computeMessageSecretHash, } from '@aztec/aztec.js'; -import { openTmpStore } from '@aztec/kv-store/utils'; -import { Pedersen, SparseTree, newTree } from '@aztec/merkle-tree'; -import { SlowTreeContract, TokenBlacklistContract, type TokenContract } from '@aztec/noir-contracts.js'; +import { TokenBlacklistContract, type TokenContract } from '@aztec/noir-contracts.js'; import { jest } from '@jest/globals'; @@ -32,57 +29,68 @@ describe('e2e_blacklist_token_contract', () => { let logger: DebugLogger; let asset: TokenBlacklistContract; - let slowTree: SlowTreeContract; + + let admin: Wallet; + let other: Wallet; + let blacklisted: Wallet; let tokenSim: TokenSimulator; - let slowUpdateTreeSimulator: SparseTree; + const DELAY = 5; - let cheatCodes: CheatCodes; + async function mineBlock() { + await asset.methods.get_roles(admin.getAddress()).send().wait(); + } - const getMembershipProof = async (index: bigint, includeUncommitted: boolean) => { - return { - index, - value: slowUpdateTreeSimulator.getLeafValue(index, includeUncommitted)!, - // eslint-disable-next-line camelcase - sibling_path: (await slowUpdateTreeSimulator.getSiblingPath(index, includeUncommitted)).toFields(), - }; - }; + async function mineBlocks(amount: number) { + for (let i = 0; i < amount; ++i) { + await mineBlock(); + } + } - const getMembershipCapsule = (proof: { index: bigint; value: Fr; sibling_path: Fr[] }) => { - return [new Fr(proof.index), proof.value, ...proof.sibling_path]; - }; + class Role { + private isAdmin = false; + private isMinter = false; + private isBlacklisted = false; - const getUpdateProof = async (newValue: bigint, index: bigint) => { - const beforeProof = await getMembershipProof(index, false); - const afterProof = await getMembershipProof(index, true); - - return { - index, - // eslint-disable-next-line camelcase - new_value: newValue, - // eslint-disable-next-line camelcase - before: { value: beforeProof.value, sibling_path: beforeProof.sibling_path }, - // eslint-disable-next-line camelcase - after: { value: afterProof.value, sibling_path: afterProof.sibling_path }, - }; - }; + withAdmin() { + this.isAdmin = true; + return this; + } - const getUpdateCapsule = (proof: { - index: bigint; - new_value: bigint; - before: { value: Fr; sibling_path: Fr[] }; - after: { value: Fr; sibling_path: Fr[] }; - }) => { - return [ - new Fr(proof.index), - new Fr(proof.new_value), - proof.before.value, - ...proof.before.sibling_path, - proof.after.value, - ...proof.after.sibling_path, - ]; - }; + withMinter() { + this.isMinter = true; + return this; + } + + withBlacklisted() { + this.isBlacklisted = true; + return this; + } + + toCallValue() { + return { is_admin: this.isAdmin, is_minter: this.isMinter, is_blacklisted: this.isBlacklisted }; + } + + toReturnValue() { + // This matches the result of the serialize() function in the Noir struct + + let value = 0; + if (this.isAdmin) { + value += 1; + } + + if (this.isMinter) { + value += 2; + } + + if (this.isBlacklisted) { + value += 4; + } + + return [BigInt(value)]; + } + } const addPendingShieldNoteToPXE = async (accountIndex: number, amount: bigint, secretHash: Fr, txHash: TxHash) => { const note = new Note([new Fr(amount), secretHash]); @@ -97,38 +105,23 @@ describe('e2e_blacklist_token_contract', () => { await wallets[accountIndex].addNote(extendedNote); }; - const updateSlowTree = async (tree: SparseTree, wallet: Wallet, index: AztecAddress, value: bigint) => { - await wallet.addCapsule(getUpdateCapsule(await getUpdateProof(value, index.toBigInt()))); - await tree.updateLeaf(new Fr(value), index.toBigInt()); - }; - beforeAll(async () => { - ({ teardown, logger, wallets, cheatCodes } = await setup(4)); - await publicDeployAccounts(wallets[0], wallets.slice(0, 3)); - - slowTree = await SlowTreeContract.deploy(wallets[0]).send().deployed(); - - const depth = 254; - slowUpdateTreeSimulator = await newTree(SparseTree, openTmpStore(), new Pedersen(), 'test', Fr, depth); + ({ teardown, logger, wallets } = await setup(4)); + admin = wallets[0]; + other = wallets[1]; + blacklisted = wallets[2]; - // Add account[0] as admin - await updateSlowTree(slowUpdateTreeSimulator, wallets[0], wallets[0].getAddress(), 4n); + await publicDeployAccounts(admin, wallets.slice(0, 3)); - const deployTx = TokenBlacklistContract.deploy(wallets[0], wallets[0].getAddress(), slowTree.address).send({}); + const deployTx = TokenBlacklistContract.deploy(admin, admin.getAddress()).send(); const receipt = await deployTx.wait(); asset = receipt.contract; - await asset.methods.init_slow_tree(wallets[0].getAddress()).send().wait(); + await mineBlocks(DELAY); // This gets us past the block of change - // Progress to next "epoch" - const time = await cheatCodes.eth.timestamp(); - await cheatCodes.aztec.warp(time + 200); - await slowUpdateTreeSimulator.commit(); - - const roleLeaf = await slowTree.methods.un_read_leaf_at(asset.address, wallets[0].getAddress()).simulate(); - expect(roleLeaf['next_change']).toBeGreaterThan(0n); - expect(roleLeaf['before']).toEqual(0n); - expect(roleLeaf['after']).toEqual(4n); + expect(await asset.methods.get_roles(admin.getAddress()).simulate()).toEqual( + new Role().withAdmin().toReturnValue(), + ); logger.info(`Token deployed to ${asset.address}`); tokenSim = new TokenSimulator( @@ -154,140 +147,63 @@ describe('e2e_blacklist_token_contract', () => { }, TIMEOUT); describe('Access controlled functions', () => { - it('Extend account[0] roles with minter as admin', async () => { - const newMinter = wallets[0].getAddress(); - const newRoles = 2n + 4n; - - const beforeLeaf = await slowTree.methods.un_read_leaf_at(asset.address, newMinter).simulate(); - // eslint-disable-next-line camelcase - expect(beforeLeaf['next_change']).toBeGreaterThan(0n); - expect(beforeLeaf['before']).toEqual(0n); - expect(beforeLeaf['after']).toEqual(4n); - - await updateSlowTree(slowUpdateTreeSimulator, wallets[0], newMinter, newRoles); - await wallets[0].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[0].getAddress().toBigInt(), false)), - ); + it('grant mint permission to the admin', async () => { + const adminMinterRole = new Role().withAdmin().withMinter(); + await asset + .withWallet(admin) + .methods.update_roles(admin.getAddress(), adminMinterRole.toCallValue()) + .send() + .wait(); - await asset.methods.update_roles(newMinter, newRoles).send().wait(); - await slowUpdateTreeSimulator.commit(); + await mineBlocks(DELAY); // This gets us past the block of change - const afterLeaf = await slowTree.methods.un_read_leaf_at(asset.address, newMinter).simulate(); - expect(afterLeaf['next_change']).toBeGreaterThan(beforeLeaf['next_change']); - expect(afterLeaf['before']).toEqual(4n); - expect(afterLeaf['after']).toEqual(newRoles); - - const time = await cheatCodes.eth.timestamp(); - await cheatCodes.aztec.warp(time + 200); + expect(await asset.methods.get_roles(admin.getAddress()).simulate()).toEqual(adminMinterRole.toReturnValue()); }); - it('Make account[1] admin', async () => { - const newAdmin = wallets[1].getAddress(); - const newRoles = 4n; - - let v = await slowTree.methods.un_read_leaf_at(asset.address, newAdmin).simulate(); - // eslint-disable-next-line camelcase - expect(v).toEqual({ next_change: 0n, before: 0n, after: 0n }); - - await updateSlowTree(slowUpdateTreeSimulator, wallets[0], newAdmin, newRoles); - await wallets[0].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[0].getAddress().toBigInt(), false)), - ); - - await asset.methods.update_roles(newAdmin, newRoles).send().wait(); - await slowUpdateTreeSimulator.commit(); + it('create a new admin', async () => { + const adminRole = new Role().withAdmin(); + await asset.withWallet(admin).methods.update_roles(other.getAddress(), adminRole.toCallValue()).send().wait(); - v = await slowTree.methods.un_read_leaf_at(asset.address, newAdmin).simulate(); - expect(v['next_change']).toBeGreaterThan(0n); - expect(v['before']).toEqual(0n); - expect(v['after']).toEqual(newRoles); + await mineBlocks(DELAY); // This gets us past the block of change - // Progress to next "epoch" - const time = await cheatCodes.eth.timestamp(); - await cheatCodes.aztec.warp(time + 200); + expect(await asset.methods.get_roles(other.getAddress()).simulate()).toEqual(adminRole.toReturnValue()); }); - it('Revoke admin as admin', async () => { - const actor = wallets[1].getAddress(); - const newRoles = 0n; - const currentRoles = 4n; - - const beforeLeaf = await slowTree.methods.un_read_leaf_at(asset.address, actor).simulate(); - // eslint-disable-next-line camelcase - expect(beforeLeaf['next_change']).toBeGreaterThan(0n); - expect(beforeLeaf['before']).toEqual(0n); - expect(beforeLeaf['after']).toEqual(currentRoles); + it('revoke the new admin', async () => { + const noRole = new Role(); + await asset.withWallet(admin).methods.update_roles(other.getAddress(), noRole.toCallValue()).send().wait(); - await updateSlowTree(slowUpdateTreeSimulator, wallets[0], actor, newRoles); - await wallets[0].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[0].getAddress().toBigInt(), false)), - ); - - await asset.methods.update_roles(actor, newRoles).send().wait(); - await slowUpdateTreeSimulator.commit(); + await mineBlocks(DELAY); // This gets us past the block of change - const afterLeaf = await slowTree.methods.un_read_leaf_at(asset.address, actor).simulate(); - expect(afterLeaf['next_change']).toBeGreaterThan(beforeLeaf['next_change']); - expect(afterLeaf['before']).toEqual(currentRoles); - expect(afterLeaf['after']).toEqual(newRoles); - - const time = await cheatCodes.eth.timestamp(); - await cheatCodes.aztec.warp(time + 200); + expect(await asset.methods.get_roles(other.getAddress()).simulate()).toEqual(noRole.toReturnValue()); }); - it('Add account[3] to blacklist', async () => { - let v = await slowTree.methods.un_read_leaf_at(asset.address, wallets[3].getAddress()).simulate(); - // eslint-disable-next-line camelcase - expect(v).toEqual({ next_change: 0n, before: 0n, after: 0n }); + it('blacklist account', async () => { + const blacklistRole = new Role().withBlacklisted(); + await asset + .withWallet(admin) + .methods.update_roles(blacklisted.getAddress(), blacklistRole.toCallValue()) + .send() + .wait(); - await updateSlowTree(slowUpdateTreeSimulator, wallets[0], wallets[3].getAddress(), 1n); - await wallets[0].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[0].getAddress().toBigInt(), false)), - ); + await mineBlocks(DELAY); // This gets us past the block of change - await asset.methods.update_roles(wallets[3].getAddress(), 1n).send().wait(); - await slowUpdateTreeSimulator.commit(); - - v = await slowTree.methods.un_read_leaf_at(asset.address, wallets[3].getAddress()).simulate(); - expect(v['next_change']).toBeGreaterThan(0n); - expect(v['before']).toEqual(0n); - expect(v['after']).toEqual(1n); - - const time = await cheatCodes.eth.timestamp(); - await cheatCodes.aztec.warp(time + 200); + expect(await asset.methods.get_roles(blacklisted.getAddress()).simulate()).toEqual(blacklistRole.toReturnValue()); }); describe('failure cases', () => { - it('Set admin (not admin)', async () => { - const account = AztecAddress.random(); - const v = await slowTree.methods.un_read_leaf_at(asset.address, account).simulate(); - const newRoles = 4n; - // eslint-disable-next-line camelcase - expect(v).toEqual({ next_change: 0n, before: 0n, after: 0n }); - - await wallets[3].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[3].getAddress().toBigInt(), false)), - ); - await expect(asset.withWallet(wallets[3]).methods.update_roles(account, newRoles).prove()).rejects.toThrow( - "Assertion failed: caller is not admin 'caller_roles.is_admin'", - ); + it('set roles from non admin', async () => { + const newRole = new Role().withAdmin().withAdmin(); + await expect( + asset.withWallet(other).methods.update_roles(AztecAddress.random(), newRole.toCallValue()).prove(), + ).rejects.toThrow("Assertion failed: caller is not admin 'caller_roles.isAdmin'"); }); - it('Revoke minter not as admin', async () => { - const adminAccount = wallets[0].getAddress(); - const v = await slowTree.methods.un_read_leaf_at(asset.address, adminAccount).simulate(); - const newRoles = 0n; - // eslint-disable-next-line camelcase - expect(v['next_change']).toBeGreaterThan(0n); - expect(v['before']).toEqual(4n); - expect(v['after']).toEqual(6n); - - await wallets[3].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[3].getAddress().toBigInt(), false)), - ); - await expect(asset.withWallet(wallets[3]).methods.update_roles(adminAccount, newRoles).prove()).rejects.toThrow( - "Assertion failed: caller is not admin 'caller_roles.is_admin'", - ); + it('revoke minter from non admin', async () => { + const noRole = new Role(); + await expect( + asset.withWallet(other).methods.update_roles(admin.getAddress(), noRole.toCallValue()).prove(), + ).rejects.toThrow("Assertion failed: caller is not admin 'caller_roles.isAdmin'"); }); }); }); @@ -336,8 +252,8 @@ describe('e2e_blacklist_token_contract', () => { it('mint to blacklisted entity', async () => { await expect( - asset.withWallet(wallets[1]).methods.mint_public(wallets[3].getAddress(), 1n).prove(), - ).rejects.toThrow("Assertion failed: Blacklisted: Recipient '!to_roles.is_blacklisted'"); + asset.withWallet(wallets[1]).methods.mint_public(blacklisted.getAddress(), 1n).prove(), + ).rejects.toThrow("Assertion failed: Blacklisted: Recipient '!to_roles.isBlacklisted'"); }); }); }); @@ -361,13 +277,12 @@ describe('e2e_blacklist_token_contract', () => { it('redeem as recipient', async () => { await addPendingShieldNoteToPXE(0, amount, secretHash, txHash); - await wallets[0].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[0].getAddress().toBigInt(), true)), - ); + const receiptClaim = await asset.methods .redeem_shield(wallets[0].getAddress(), amount, secret) .send() .wait({ debug: true }); + tokenSim.redeemShield(wallets[0].getAddress(), amount); // 1 note should be created containing `amount` of tokens const { visibleNotes } = receiptClaim.debugInfo!; @@ -381,9 +296,6 @@ describe('e2e_blacklist_token_contract', () => { await expect(addPendingShieldNoteToPXE(0, amount, secretHash, txHash)).rejects.toThrow( 'The note has been destroyed.', ); - await wallets[0].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[0].getAddress().toBigInt(), true)), - ); await expect(asset.methods.redeem_shield(wallets[0].getAddress(), amount, secret).prove()).rejects.toThrow( `Assertion failed: Cannot return zero notes`, ); @@ -412,11 +324,8 @@ describe('e2e_blacklist_token_contract', () => { }); it('mint and try to redeem at blacklist', async () => { - await wallets[3].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[3].getAddress().toBigInt(), true)), - ); - await expect(asset.methods.redeem_shield(wallets[3].getAddress(), amount, secret).prove()).rejects.toThrow( - "Assertion failed: Blacklisted: Recipient '!to_roles.is_blacklisted'", + await expect(asset.methods.redeem_shield(blacklisted.getAddress(), amount, secret).prove()).rejects.toThrow( + "Assertion failed: Blacklisted: Recipient '!to_roles.isBlacklisted'", ); }); }); @@ -572,14 +481,14 @@ describe('e2e_blacklist_token_contract', () => { it('transfer from a blacklisted account', async () => { await expect( - asset.methods.transfer_public(wallets[3].getAddress(), wallets[0].getAddress(), 1n, 0n).prove(), - ).rejects.toThrow("Assertion failed: Blacklisted: Sender '!from_roles.is_blacklisted'"); + asset.methods.transfer_public(blacklisted.getAddress(), wallets[0].getAddress(), 1n, 0n).prove(), + ).rejects.toThrow("Assertion failed: Blacklisted: Sender '!from_roles.isBlacklisted'"); }); it('transfer to a blacklisted account', async () => { await expect( - asset.methods.transfer_public(wallets[0].getAddress(), wallets[3].getAddress(), 1n, 0n).prove(), - ).rejects.toThrow("Assertion failed: Blacklisted: Recipient '!to_roles.is_blacklisted'"); + asset.methods.transfer_public(wallets[0].getAddress(), blacklisted.getAddress(), 1n, 0n).prove(), + ).rejects.toThrow("Assertion failed: Blacklisted: Recipient '!to_roles.isBlacklisted'"); }); }); }); @@ -589,12 +498,6 @@ describe('e2e_blacklist_token_contract', () => { const balance0 = await asset.methods.balance_of_private(wallets[0].getAddress()).simulate(); const amount = balance0 / 2n; expect(amount).toBeGreaterThan(0n); - await wallets[0].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[1].getAddress().toBigInt(), true)), - ); - await wallets[0].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[0].getAddress().toBigInt(), true)), - ); await asset.methods.transfer(wallets[0].getAddress(), wallets[1].getAddress(), amount, 0).send().wait(); tokenSim.transferPrivate(wallets[0].getAddress(), wallets[1].getAddress(), amount); }); @@ -603,12 +506,7 @@ describe('e2e_blacklist_token_contract', () => { const balance0 = await asset.methods.balance_of_private(wallets[0].getAddress()).simulate(); const amount = balance0 / 2n; expect(amount).toBeGreaterThan(0n); - await wallets[0].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[0].getAddress().toBigInt(), true)), - ); - await wallets[0].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[0].getAddress().toBigInt(), true)), - ); + await asset.methods.transfer(wallets[0].getAddress(), wallets[0].getAddress(), amount, 0).send().wait(); tokenSim.transferPrivate(wallets[0].getAddress(), wallets[0].getAddress(), amount); }); @@ -630,24 +528,11 @@ describe('e2e_blacklist_token_contract', () => { const witness = await wallets[0].createAuthWit({ caller: wallets[1].getAddress(), action }); await wallets[1].addAuthWitness(witness); // docs:end:authwit_transfer_example - await wallets[1].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[1].getAddress().toBigInt(), true)), - ); - await wallets[1].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[0].getAddress().toBigInt(), true)), - ); // Perform the transfer await action.send().wait(); tokenSim.transferPrivate(wallets[0].getAddress(), wallets[1].getAddress(), amount); - await wallets[1].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[1].getAddress().toBigInt(), true)), - ); - await wallets[1].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[0].getAddress().toBigInt(), true)), - ); - // Perform the transfer again, should fail const txReplay = asset .withWallet(wallets[1]) @@ -661,12 +546,7 @@ describe('e2e_blacklist_token_contract', () => { const balance0 = await asset.methods.balance_of_private(wallets[0].getAddress()).simulate(); const amount = balance0 + 1n; expect(amount).toBeGreaterThan(0n); - await wallets[0].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[1].getAddress().toBigInt(), true)), - ); - await wallets[0].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[0].getAddress().toBigInt(), true)), - ); + await expect( asset.methods.transfer(wallets[0].getAddress(), wallets[1].getAddress(), amount, 0).prove(), ).rejects.toThrow('Assertion failed: Balance too low'); @@ -676,12 +556,7 @@ describe('e2e_blacklist_token_contract', () => { const balance0 = await asset.methods.balance_of_private(wallets[0].getAddress()).simulate(); const amount = balance0 - 1n; expect(amount).toBeGreaterThan(0n); - await wallets[0].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[1].getAddress().toBigInt(), true)), - ); - await wallets[0].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[0].getAddress().toBigInt(), true)), - ); + await expect( asset.methods.transfer(wallets[0].getAddress(), wallets[1].getAddress(), amount, 1).prove(), ).rejects.toThrow('Assertion failed: invalid nonce'); @@ -703,12 +578,6 @@ describe('e2e_blacklist_token_contract', () => { // But doing it in two actions to show the flow. const witness = await wallets[0].createAuthWit({ caller: wallets[1].getAddress(), action }); await wallets[1].addAuthWitness(witness); - await wallets[1].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[1].getAddress().toBigInt(), true)), - ); - await wallets[1].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[0].getAddress().toBigInt(), true)), - ); // Perform the transfer await expect(action.prove()).rejects.toThrow('Assertion failed: Balance too low'); @@ -739,12 +608,6 @@ describe('e2e_blacklist_token_contract', () => { wallets[0].getVersion(), action.request(), ); - await wallets[1].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[1].getAddress().toBigInt(), true)), - ); - await wallets[1].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[0].getAddress().toBigInt(), true)), - ); await expect(action.prove()).rejects.toThrow( `Unknown auth witness for message hash ${messageHash.toString()}`, @@ -770,12 +633,6 @@ describe('e2e_blacklist_token_contract', () => { const witness = await wallets[0].createAuthWit({ caller: wallets[1].getAddress(), action }); await wallets[2].addAuthWitness(witness); - await wallets[2].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[1].getAddress().toBigInt(), true)), - ); - await wallets[2].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[0].getAddress().toBigInt(), true)), - ); await expect(action.prove()).rejects.toThrow( `Unknown auth witness for message hash ${expectedMessageHash.toString()}`, @@ -784,27 +641,15 @@ describe('e2e_blacklist_token_contract', () => { }); it('transfer from a blacklisted account', async () => { - await wallets[3].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[0].getAddress().toBigInt(), true)), - ); - await wallets[3].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[3].getAddress().toBigInt(), true)), - ); await expect( - asset.methods.transfer(wallets[3].getAddress(), wallets[0].getAddress(), 1n, 0).prove(), - ).rejects.toThrow("Assertion failed: Blacklisted: Sender '!from_roles.is_blacklisted'"); + asset.methods.transfer(blacklisted.getAddress(), wallets[0].getAddress(), 1n, 0).prove(), + ).rejects.toThrow("Assertion failed: Blacklisted: Sender '!from_roles.isBlacklisted'"); }); it('transfer to a blacklisted account', async () => { - await wallets[0].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[3].getAddress().toBigInt(), true)), - ); - await wallets[0].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[0].getAddress().toBigInt(), true)), - ); await expect( - asset.methods.transfer(wallets[0].getAddress(), wallets[3].getAddress(), 1n, 0).prove(), - ).rejects.toThrow("Assertion failed: Blacklisted: Recipient '!to_roles.is_blacklisted'"); + asset.methods.transfer(wallets[0].getAddress(), blacklisted.getAddress(), 1n, 0).prove(), + ).rejects.toThrow("Assertion failed: Blacklisted: Recipient '!to_roles.isBlacklisted'"); }); }); }); @@ -830,9 +675,6 @@ describe('e2e_blacklist_token_contract', () => { // Redeem it await addPendingShieldNoteToPXE(0, amount, secretHash, receipt.txHash); - await wallets[0].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[0].getAddress().toBigInt(), true)), - ); await asset.methods.redeem_shield(wallets[0].getAddress(), amount, secret).send().wait(); tokenSim.redeemShield(wallets[0].getAddress(), amount); @@ -862,9 +704,6 @@ describe('e2e_blacklist_token_contract', () => { // Redeem it await addPendingShieldNoteToPXE(0, amount, secretHash, receipt.txHash); - await wallets[0].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[0].getAddress().toBigInt(), true)), - ); await asset.methods.redeem_shield(wallets[0].getAddress(), amount, secret).send().wait(); tokenSim.redeemShield(wallets[0].getAddress(), amount); @@ -929,12 +768,9 @@ describe('e2e_blacklist_token_contract', () => { }); it('shielding from blacklisted account', async () => { - await wallets[0].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[3].getAddress().toBigInt(), true)), - ); await expect( - asset.withWallet(wallets[3]).methods.shield(wallets[3].getAddress(), 1n, secretHash, 0).prove(), - ).rejects.toThrow("Assertion failed: Blacklisted: Sender '!from_roles.is_blacklisted'"); + asset.withWallet(blacklisted).methods.shield(blacklisted.getAddress(), 1n, secretHash, 0).prove(), + ).rejects.toThrow("Assertion failed: Blacklisted: Sender '!from_roles.isBlacklisted'"); }); }); }); @@ -945,12 +781,6 @@ describe('e2e_blacklist_token_contract', () => { const amount = balancePriv / 2n; expect(amount).toBeGreaterThan(0n); - await wallets[1].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[0].getAddress().toBigInt(), true)), - ); - await wallets[1].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[0].getAddress().toBigInt(), true)), - ); await asset.methods.unshield(wallets[0].getAddress(), wallets[0].getAddress(), amount, 0).send().wait(); tokenSim.unshield(wallets[0].getAddress(), wallets[0].getAddress(), amount); @@ -963,12 +793,6 @@ describe('e2e_blacklist_token_contract', () => { expect(amount).toBeGreaterThan(0n); // We need to compute the message we want to sign and add it to the wallet as approved - await wallets[1].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[1].getAddress().toBigInt(), true)), - ); - await wallets[1].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[0].getAddress().toBigInt(), true)), - ); const action = asset .withWallet(wallets[1]) .methods.unshield(wallets[0].getAddress(), wallets[1].getAddress(), amount, nonce); @@ -982,12 +806,6 @@ describe('e2e_blacklist_token_contract', () => { tokenSim.unshield(wallets[0].getAddress(), wallets[1].getAddress(), amount); // Perform the transfer again, should fail - await wallets[1].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[1].getAddress().toBigInt(), true)), - ); - await wallets[1].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[0].getAddress().toBigInt(), true)), - ); const txReplay = asset .withWallet(wallets[1]) .methods.unshield(wallets[0].getAddress(), wallets[1].getAddress(), amount, nonce) @@ -1002,13 +820,6 @@ describe('e2e_blacklist_token_contract', () => { const amount = balancePriv + 1n; expect(amount).toBeGreaterThan(0n); - await wallets[0].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[0].getAddress().toBigInt(), true)), - ); - await wallets[0].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[0].getAddress().toBigInt(), true)), - ); - await expect( asset.methods.unshield(wallets[0].getAddress(), wallets[0].getAddress(), amount, 0).prove(), ).rejects.toThrow('Assertion failed: Balance too low'); @@ -1019,13 +830,6 @@ describe('e2e_blacklist_token_contract', () => { const amount = balancePriv + 1n; expect(amount).toBeGreaterThan(0n); - await wallets[0].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[0].getAddress().toBigInt(), true)), - ); - await wallets[0].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[0].getAddress().toBigInt(), true)), - ); - await expect( asset.methods.unshield(wallets[0].getAddress(), wallets[0].getAddress(), amount, 1).prove(), ).rejects.toThrow('Assertion failed: invalid nonce'); @@ -1046,12 +850,6 @@ describe('e2e_blacklist_token_contract', () => { // But doing it in two actions to show the flow. const witness = await wallets[0].createAuthWit({ caller: wallets[1].getAddress(), action }); await wallets[1].addAuthWitness(witness); - await wallets[1].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[1].getAddress().toBigInt(), true)), - ); - await wallets[1].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[0].getAddress().toBigInt(), true)), - ); await expect(action.prove()).rejects.toThrow('Assertion failed: Balance too low'); }); @@ -1077,12 +875,6 @@ describe('e2e_blacklist_token_contract', () => { // But doing it in two actions to show the flow. const witness = await wallets[0].createAuthWit({ caller: wallets[1].getAddress(), action }); await wallets[2].addAuthWitness(witness); - await wallets[2].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[1].getAddress().toBigInt(), true)), - ); - await wallets[2].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[0].getAddress().toBigInt(), true)), - ); await expect(action.prove()).rejects.toThrow( `Unknown auth witness for message hash ${expectedMessageHash.toString()}`, @@ -1090,27 +882,15 @@ describe('e2e_blacklist_token_contract', () => { }); it('unshield from blacklisted account', async () => { - await wallets[0].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[0].getAddress().toBigInt(), true)), - ); - await wallets[0].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[3].getAddress().toBigInt(), true)), - ); await expect( - asset.methods.unshield(wallets[3].getAddress(), wallets[0].getAddress(), 1n, 0).prove(), - ).rejects.toThrow("Assertion failed: Blacklisted: Sender '!from_roles.is_blacklisted'"); + asset.methods.unshield(blacklisted.getAddress(), wallets[0].getAddress(), 1n, 0).prove(), + ).rejects.toThrow("Assertion failed: Blacklisted: Sender '!from_roles.isBlacklisted'"); }); it('unshield to blacklisted account', async () => { - await wallets[0].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[3].getAddress().toBigInt(), true)), - ); - await wallets[0].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[0].getAddress().toBigInt(), true)), - ); await expect( - asset.methods.unshield(wallets[0].getAddress(), wallets[3].getAddress(), 1n, 0).prove(), - ).rejects.toThrow("Assertion failed: Blacklisted: Recipient '!to_roles.is_blacklisted'"); + asset.methods.unshield(wallets[0].getAddress(), blacklisted.getAddress(), 1n, 0).prove(), + ).rejects.toThrow("Assertion failed: Blacklisted: Recipient '!to_roles.isBlacklisted'"); }); }); }); @@ -1206,8 +986,8 @@ describe('e2e_blacklist_token_contract', () => { }); it('burn from blacklisted account', async () => { - await expect(asset.methods.burn_public(wallets[3].getAddress(), 1n, 0).prove()).rejects.toThrow( - "Assertion failed: Blacklisted: Sender '!from_roles.is_blacklisted'", + await expect(asset.methods.burn_public(blacklisted.getAddress(), 1n, 0).prove()).rejects.toThrow( + "Assertion failed: Blacklisted: Sender '!from_roles.isBlacklisted'", ); }); }); @@ -1218,9 +998,6 @@ describe('e2e_blacklist_token_contract', () => { const balance0 = await asset.methods.balance_of_private(wallets[0].getAddress()).simulate(); const amount = balance0 / 2n; expect(amount).toBeGreaterThan(0n); - await wallets[0].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[0].getAddress().toBigInt(), true)), - ); await asset.methods.burn(wallets[0].getAddress(), amount, 0).send().wait(); tokenSim.burnPrivate(wallets[0].getAddress(), amount); }); @@ -1238,17 +1015,11 @@ describe('e2e_blacklist_token_contract', () => { // But doing it in two actions to show the flow. const witness = await wallets[0].createAuthWit({ caller: wallets[1].getAddress(), action }); await wallets[1].addAuthWitness(witness); - await wallets[1].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[0].getAddress().toBigInt(), true)), - ); await asset.withWallet(wallets[1]).methods.burn(wallets[0].getAddress(), amount, nonce).send().wait(); tokenSim.burnPrivate(wallets[0].getAddress(), amount); // Perform the transfer again, should fail - await wallets[1].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[0].getAddress().toBigInt(), true)), - ); const txReplay = asset.withWallet(wallets[1]).methods.burn(wallets[0].getAddress(), amount, nonce).send(); await expect(txReplay.wait()).rejects.toThrow('Transaction '); }); @@ -1258,9 +1029,6 @@ describe('e2e_blacklist_token_contract', () => { const balance0 = await asset.methods.balance_of_private(wallets[0].getAddress()).simulate(); const amount = balance0 + 1n; expect(amount).toBeGreaterThan(0n); - await wallets[0].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[0].getAddress().toBigInt(), true)), - ); await expect(asset.methods.burn(wallets[0].getAddress(), amount, 0).prove()).rejects.toThrow( 'Assertion failed: Balance too low', ); @@ -1270,9 +1038,6 @@ describe('e2e_blacklist_token_contract', () => { const balance0 = await asset.methods.balance_of_private(wallets[0].getAddress()).simulate(); const amount = balance0 - 1n; expect(amount).toBeGreaterThan(0n); - await wallets[0].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[0].getAddress().toBigInt(), true)), - ); await expect(asset.methods.burn(wallets[0].getAddress(), amount, 1).prove()).rejects.toThrow( 'Assertion failed: invalid nonce', ); @@ -1291,9 +1056,6 @@ describe('e2e_blacklist_token_contract', () => { // But doing it in two actions to show the flow. const witness = await wallets[0].createAuthWit({ caller: wallets[1].getAddress(), action }); await wallets[1].addAuthWitness(witness); - await wallets[1].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[0].getAddress().toBigInt(), true)), - ); await expect(action.prove()).rejects.toThrow('Assertion failed: Balance too low'); }); @@ -1305,9 +1067,6 @@ describe('e2e_blacklist_token_contract', () => { expect(amount).toBeGreaterThan(0n); // We need to compute the message we want to sign and add it to the wallet as approved - await wallets[1].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[0].getAddress().toBigInt(), true)), - ); const action = asset.withWallet(wallets[1]).methods.burn(wallets[0].getAddress(), amount, nonce); const messageHash = computeAuthWitMessageHash( wallets[1].getAddress(), @@ -1328,9 +1087,6 @@ describe('e2e_blacklist_token_contract', () => { expect(amount).toBeGreaterThan(0n); // We need to compute the message we want to sign and add it to the wallet as approved - await wallets[2].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[0].getAddress().toBigInt(), true)), - ); const action = asset.withWallet(wallets[2]).methods.burn(wallets[0].getAddress(), amount, nonce); const expectedMessageHash = computeAuthWitMessageHash( wallets[2].getAddress(), @@ -1348,11 +1104,8 @@ describe('e2e_blacklist_token_contract', () => { }); it('burn from blacklisted account', async () => { - await wallets[0].addCapsule( - getMembershipCapsule(await getMembershipProof(wallets[3].getAddress().toBigInt(), true)), - ); - await expect(asset.methods.burn(wallets[3].getAddress(), 1n, 0).prove()).rejects.toThrow( - "Assertion failed: Blacklisted: Sender '!from_roles.is_blacklisted'", + await expect(asset.methods.burn(blacklisted.getAddress(), 1n, 0).prove()).rejects.toThrow( + "Assertion failed: Blacklisted: Sender '!from_roles.isBlacklisted'", ); }); }); From 49c45c38f01e5a2034f81506089640d93c87744d Mon Sep 17 00:00:00 2001 From: Santiago Palladino Date: Mon, 22 Apr 2024 18:41:27 -0300 Subject: [PATCH 071/102] chore: Reenable account init fees e2e (#5938) Seems to have been fixed by #5911 --- ...2e_account_init_fees.test.ts => e2e_account_init_fees.test.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename yarn-project/end-to-end/src/{flakey_e2e_account_init_fees.test.ts => e2e_account_init_fees.test.ts} (100%) diff --git a/yarn-project/end-to-end/src/flakey_e2e_account_init_fees.test.ts b/yarn-project/end-to-end/src/e2e_account_init_fees.test.ts similarity index 100% rename from yarn-project/end-to-end/src/flakey_e2e_account_init_fees.test.ts rename to yarn-project/end-to-end/src/e2e_account_init_fees.test.ts From 1d3af93f26d7b09389debe4b7046ae3359ff1893 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Bene=C5=A1?= Date: Tue, 23 Apr 2024 00:17:51 +0200 Subject: [PATCH 072/102] chore: nuking unused keys.nr (#5910) --- .../private_validation_request_processor.nr | 3 +-- .../crates/types/src/keys.nr | 26 ------------------- .../crates/types/src/lib.nr | 1 - 3 files changed, 1 insertion(+), 29 deletions(-) delete mode 100644 noir-projects/noir-protocol-circuits/crates/types/src/keys.nr diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/private_validation_request_processor.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/private_validation_request_processor.nr index 7fc2e3929d7..8cfa430a8a0 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/private_validation_request_processor.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/private_validation_request_processor.nr @@ -5,8 +5,7 @@ use dep::types::{ MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_NOTE_HASH_READ_REQUESTS_PER_TX, MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, GENERATOR_INDEX__NSK_M }, - grumpkin_private_key::GrumpkinPrivateKey, keys::compute_siloed_nullifier_secret_key, - hash::poseidon2_hash, traits::is_empty + grumpkin_private_key::GrumpkinPrivateKey, hash::poseidon2_hash, traits::is_empty }; struct PrivateValidationRequestProcessor { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/keys.nr b/noir-projects/noir-protocol-circuits/crates/types/src/keys.nr deleted file mode 100644 index 0e93ffe7841..00000000000 --- a/noir-projects/noir-protocol-circuits/crates/types/src/keys.nr +++ /dev/null @@ -1,26 +0,0 @@ -use crate::{address::AztecAddress, grumpkin_private_key::GrumpkinPrivateKey, hash::pedersen_hash}; - -fn field_to_grumpkin_private_key(val: Field) -> GrumpkinPrivateKey { - let bytes = val.to_be_bytes(32); - let mut v = 1; - let mut high = 0; - let mut low = 0; - - for i in 0..16 { - high = high + (bytes[15 - i] as Field) * v; - low = low + (bytes[16 + 15 - i] as Field) * v; - v = v * 256; - } - - GrumpkinPrivateKey { high, low } -} - -pub fn compute_siloed_nullifier_secret_key(secret_key: GrumpkinPrivateKey, contract_address: AztecAddress) -> GrumpkinPrivateKey { - // TODO: Temporary hack. Should replace it with a secure way to derive the secret key. - // Match the way keys are derived in circuits.js/src/keys/index.ts - let hash = pedersen_hash( - [secret_key.high, secret_key.low, contract_address.to_field()], - 0 - ); - field_to_grumpkin_private_key(hash) -} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/lib.nr b/noir-projects/noir-protocol-circuits/crates/types/src/lib.nr index 5e7a03c0f96..5530e831352 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/lib.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/lib.nr @@ -13,7 +13,6 @@ mod constants; mod contract_class_id; mod merkle_tree; mod contract_instance; -mod keys; mod messaging; mod mocked; From 42371b23c85e081ff9abfb0c2abc4f37e5b86cd9 Mon Sep 17 00:00:00 2001 From: AztecBot Date: Tue, 23 Apr 2024 02:11:02 +0000 Subject: [PATCH 073/102] git subrepo push --branch=master barretenberg subrepo: subdir: "barretenberg" merged: "9f614992f" upstream: origin: "https://github.com/AztecProtocol/barretenberg" branch: "master" commit: "9f614992f" git-subrepo: version: "0.4.6" origin: "???" commit: "???" [skip ci] --- barretenberg/.gitrepo | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/barretenberg/.gitrepo b/barretenberg/.gitrepo index cc89e603d40..9a0026683b9 100644 --- a/barretenberg/.gitrepo +++ b/barretenberg/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = https://github.com/AztecProtocol/barretenberg branch = master - commit = 1b2ec21d9f8372ec5d79a510273e043bd3d79bb2 - parent = ec21fb8251c34d535fd0c5e08f354cfa22c25320 + commit = 9f614992fee549b4e3bd90d208faf2c68ea2cbcc + parent = 1d3af93f26d7b09389debe4b7046ae3359ff1893 method = merge cmdver = 0.4.6 From c0c8e3f880076d20cca96a3c92a1484abdcc66a0 Mon Sep 17 00:00:00 2001 From: AztecBot Date: Tue, 23 Apr 2024 02:11:27 +0000 Subject: [PATCH 074/102] chore: replace relative paths to noir-protocol-circuits --- noir-projects/aztec-nr/aztec/Nargo.toml | 2 +- noir-projects/aztec-nr/tests/Nargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/Nargo.toml b/noir-projects/aztec-nr/aztec/Nargo.toml index 7a1f1af5863..2cbb43ab278 100644 --- a/noir-projects/aztec-nr/aztec/Nargo.toml +++ b/noir-projects/aztec-nr/aztec/Nargo.toml @@ -5,4 +5,4 @@ compiler_version = ">=0.18.0" type = "lib" [dependencies] -protocol_types = { path = "../../noir-protocol-circuits/crates/types" } +protocol_types = { git="https://github.com/AztecProtocol/aztec-packages", tag="aztec-packages-v0.35.1", directory="noir-projects/noir-protocol-circuits/crates/types" } diff --git a/noir-projects/aztec-nr/tests/Nargo.toml b/noir-projects/aztec-nr/tests/Nargo.toml index 13404b37324..dfed895aad0 100644 --- a/noir-projects/aztec-nr/tests/Nargo.toml +++ b/noir-projects/aztec-nr/tests/Nargo.toml @@ -6,4 +6,4 @@ type = "lib" [dependencies] aztec = { path = "../aztec" } -protocol_types = { path = "../../noir-protocol-circuits/crates/types" } +protocol_types = { git="https://github.com/AztecProtocol/aztec-packages", tag="aztec-packages-v0.35.1", directory="noir-projects/noir-protocol-circuits/crates/types" } From f5e9efabbdaf03e6b16506c8e50e5c4b46284a3e Mon Sep 17 00:00:00 2001 From: AztecBot Date: Tue, 23 Apr 2024 02:11:27 +0000 Subject: [PATCH 075/102] git_subrepo.sh: Fix parent in .gitrepo file. [skip ci] --- noir-projects/aztec-nr/.gitrepo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noir-projects/aztec-nr/.gitrepo b/noir-projects/aztec-nr/.gitrepo index 1db63baeb42..433e134d064 100644 --- a/noir-projects/aztec-nr/.gitrepo +++ b/noir-projects/aztec-nr/.gitrepo @@ -9,4 +9,4 @@ commit = 24dd2f62869ceae261082ed6fc2a05adbe288b57 method = merge cmdver = 0.4.6 - parent = e7b29d130cdc03cbc1bb94b26740f2c8176c72bc + parent = 473b24facca6abdeef516cba26227741f918ba10 From 8a13f3a293f11eba172911f807121594717e78d2 Mon Sep 17 00:00:00 2001 From: AztecBot Date: Tue, 23 Apr 2024 02:11:32 +0000 Subject: [PATCH 076/102] git subrepo push --branch=master noir-projects/aztec-nr subrepo: subdir: "noir-projects/aztec-nr" merged: "ae7ae6194" upstream: origin: "https://github.com/AztecProtocol/aztec-nr" branch: "master" commit: "ae7ae6194" git-subrepo: version: "0.4.6" origin: "???" commit: "???" [skip ci] --- noir-projects/aztec-nr/.gitrepo | 4 ++-- noir-projects/aztec-nr/aztec/Nargo.toml | 2 +- noir-projects/aztec-nr/tests/Nargo.toml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/noir-projects/aztec-nr/.gitrepo b/noir-projects/aztec-nr/.gitrepo index 433e134d064..d4ca16357d6 100644 --- a/noir-projects/aztec-nr/.gitrepo +++ b/noir-projects/aztec-nr/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = https://github.com/AztecProtocol/aztec-nr branch = master - commit = 24dd2f62869ceae261082ed6fc2a05adbe288b57 + commit = ae7ae61940773b35fe5ed5cfa0c00e0efe3aa3f7 method = merge cmdver = 0.4.6 - parent = 473b24facca6abdeef516cba26227741f918ba10 + parent = fc6676ce51fb25463bb32c35575232ca151f89cb diff --git a/noir-projects/aztec-nr/aztec/Nargo.toml b/noir-projects/aztec-nr/aztec/Nargo.toml index 2cbb43ab278..7a1f1af5863 100644 --- a/noir-projects/aztec-nr/aztec/Nargo.toml +++ b/noir-projects/aztec-nr/aztec/Nargo.toml @@ -5,4 +5,4 @@ compiler_version = ">=0.18.0" type = "lib" [dependencies] -protocol_types = { git="https://github.com/AztecProtocol/aztec-packages", tag="aztec-packages-v0.35.1", directory="noir-projects/noir-protocol-circuits/crates/types" } +protocol_types = { path = "../../noir-protocol-circuits/crates/types" } diff --git a/noir-projects/aztec-nr/tests/Nargo.toml b/noir-projects/aztec-nr/tests/Nargo.toml index dfed895aad0..13404b37324 100644 --- a/noir-projects/aztec-nr/tests/Nargo.toml +++ b/noir-projects/aztec-nr/tests/Nargo.toml @@ -6,4 +6,4 @@ type = "lib" [dependencies] aztec = { path = "../aztec" } -protocol_types = { git="https://github.com/AztecProtocol/aztec-packages", tag="aztec-packages-v0.35.1", directory="noir-projects/noir-protocol-circuits/crates/types" } +protocol_types = { path = "../../noir-protocol-circuits/crates/types" } From da67f181b09439e2e2e04209ed3d84c21c7cc6bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Tue, 23 Apr 2024 05:27:30 -0300 Subject: [PATCH 077/102] chore: fix formatting and serialization that fails CI run (#5942) Fixes the formatting error accidentally introduced by 26c1eecc76613c7c7883031691672ba36fb16152. --------- Co-authored-by: LHerskind --- .../src/types/roles.nr | 30 +++++--- .../src/e2e_blacklist_token_contract.test.ts | 73 +++++++------------ 2 files changed, 48 insertions(+), 55 deletions(-) diff --git a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/roles.nr b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/roles.nr index a2fe3bd8727..4321a2a7f28 100644 --- a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/roles.nr +++ b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/roles.nr @@ -1,4 +1,4 @@ -use dep::aztec::protocol_types::traits::{FromField, ToField, Serialize}; +use dep::aztec::protocol_types::traits::{FromField, ToField, Serialize, Deserialize}; global ADMIN_FLAG: u64 = 1; global MINTER_FLAG: u64 = 2; @@ -41,14 +41,26 @@ impl ToField for UserFlags { } } -// We don't actually need to implement this trait, but the current macros system requires that all types that are -// contained by a state variable are serializable in order to determine their length. -// Once https://github.com/AztecProtocol/aztec-packages/issues/5736 is closed we'll be able to remove this (unless -// https://github.com/AztecProtocol/aztec-packages/issues/5491 is addressed first, in which case we'd remove the to/from -// field traits instead). -impl Serialize<1> for UserFlags { - fn serialize(self) -> [Field; 1] { - [self.to_field()] +// We implement this as it is used when serializing the state variable into return values +// This is very inefficient if used to store the state variable. +// We are currently "abusing" that the `to_field` is called in the `scheduled_value_change` +// where we are using this value. +impl Serialize<3> for UserFlags { + fn serialize(self) -> [Field; 3] { + [self.is_admin.to_field(), self.is_minter.to_field(), self.is_blacklisted.to_field()] + // [self.to_field()] + } +} + +// We implement this as it is required for other contracts to be able to "rebuild" the variable +// after having received the serialized value as a return-value +impl Deserialize<3> for UserFlags { + fn deserialize(fields: [Field; 3]) -> Self { + Self { + is_admin: fields[0] as bool, + is_minter: fields[1] as bool, + is_blacklisted: fields[2] as bool, + } } } diff --git a/yarn-project/end-to-end/src/e2e_blacklist_token_contract.test.ts b/yarn-project/end-to-end/src/e2e_blacklist_token_contract.test.ts index 8f1d8735bc6..a10290d717c 100644 --- a/yarn-project/end-to-end/src/e2e_blacklist_token_contract.test.ts +++ b/yarn-project/end-to-end/src/e2e_blacklist_token_contract.test.ts @@ -68,28 +68,11 @@ describe('e2e_blacklist_token_contract', () => { return this; } - toCallValue() { + toNoirStruct() { + // We need to use lowercase identifiers as those are what the noir interface expects + // eslint-disable-next-line camelcase return { is_admin: this.isAdmin, is_minter: this.isMinter, is_blacklisted: this.isBlacklisted }; } - - toReturnValue() { - // This matches the result of the serialize() function in the Noir struct - - let value = 0; - if (this.isAdmin) { - value += 1; - } - - if (this.isMinter) { - value += 2; - } - - if (this.isBlacklisted) { - value += 4; - } - - return [BigInt(value)]; - } } const addPendingShieldNoteToPXE = async (accountIndex: number, amount: bigint, secretHash: Fr, txHash: TxHash) => { @@ -119,9 +102,7 @@ describe('e2e_blacklist_token_contract', () => { await mineBlocks(DELAY); // This gets us past the block of change - expect(await asset.methods.get_roles(admin.getAddress()).simulate()).toEqual( - new Role().withAdmin().toReturnValue(), - ); + expect(await asset.methods.get_roles(admin.getAddress()).simulate()).toEqual(new Role().withAdmin().toNoirStruct()); logger.info(`Token deployed to ${asset.address}`); tokenSim = new TokenSimulator( @@ -151,59 +132,59 @@ describe('e2e_blacklist_token_contract', () => { const adminMinterRole = new Role().withAdmin().withMinter(); await asset .withWallet(admin) - .methods.update_roles(admin.getAddress(), adminMinterRole.toCallValue()) + .methods.update_roles(admin.getAddress(), adminMinterRole.toNoirStruct()) .send() .wait(); await mineBlocks(DELAY); // This gets us past the block of change - expect(await asset.methods.get_roles(admin.getAddress()).simulate()).toEqual(adminMinterRole.toReturnValue()); + expect(await asset.methods.get_roles(admin.getAddress()).simulate()).toEqual(adminMinterRole.toNoirStruct()); }); it('create a new admin', async () => { const adminRole = new Role().withAdmin(); - await asset.withWallet(admin).methods.update_roles(other.getAddress(), adminRole.toCallValue()).send().wait(); + await asset.withWallet(admin).methods.update_roles(other.getAddress(), adminRole.toNoirStruct()).send().wait(); await mineBlocks(DELAY); // This gets us past the block of change - expect(await asset.methods.get_roles(other.getAddress()).simulate()).toEqual(adminRole.toReturnValue()); + expect(await asset.methods.get_roles(other.getAddress()).simulate()).toEqual(adminRole.toNoirStruct()); }); it('revoke the new admin', async () => { const noRole = new Role(); - await asset.withWallet(admin).methods.update_roles(other.getAddress(), noRole.toCallValue()).send().wait(); + await asset.withWallet(admin).methods.update_roles(other.getAddress(), noRole.toNoirStruct()).send().wait(); await mineBlocks(DELAY); // This gets us past the block of change - expect(await asset.methods.get_roles(other.getAddress()).simulate()).toEqual(noRole.toReturnValue()); + expect(await asset.methods.get_roles(other.getAddress()).simulate()).toEqual(noRole.toNoirStruct()); }); it('blacklist account', async () => { const blacklistRole = new Role().withBlacklisted(); await asset .withWallet(admin) - .methods.update_roles(blacklisted.getAddress(), blacklistRole.toCallValue()) + .methods.update_roles(blacklisted.getAddress(), blacklistRole.toNoirStruct()) .send() .wait(); await mineBlocks(DELAY); // This gets us past the block of change - expect(await asset.methods.get_roles(blacklisted.getAddress()).simulate()).toEqual(blacklistRole.toReturnValue()); + expect(await asset.methods.get_roles(blacklisted.getAddress()).simulate()).toEqual(blacklistRole.toNoirStruct()); }); describe('failure cases', () => { it('set roles from non admin', async () => { const newRole = new Role().withAdmin().withAdmin(); await expect( - asset.withWallet(other).methods.update_roles(AztecAddress.random(), newRole.toCallValue()).prove(), - ).rejects.toThrow("Assertion failed: caller is not admin 'caller_roles.isAdmin'"); + asset.withWallet(other).methods.update_roles(AztecAddress.random(), newRole.toNoirStruct()).prove(), + ).rejects.toThrow("Assertion failed: caller is not admin 'caller_roles.is_admin'"); }); it('revoke minter from non admin', async () => { const noRole = new Role(); await expect( - asset.withWallet(other).methods.update_roles(admin.getAddress(), noRole.toCallValue()).prove(), - ).rejects.toThrow("Assertion failed: caller is not admin 'caller_roles.isAdmin'"); + asset.withWallet(other).methods.update_roles(admin.getAddress(), noRole.toNoirStruct()).prove(), + ).rejects.toThrow("Assertion failed: caller is not admin 'caller_roles.is_admin'"); }); }); }); @@ -253,7 +234,7 @@ describe('e2e_blacklist_token_contract', () => { it('mint to blacklisted entity', async () => { await expect( asset.withWallet(wallets[1]).methods.mint_public(blacklisted.getAddress(), 1n).prove(), - ).rejects.toThrow("Assertion failed: Blacklisted: Recipient '!to_roles.isBlacklisted'"); + ).rejects.toThrow("Assertion failed: Blacklisted: Recipient '!to_roles.is_blacklisted'"); }); }); }); @@ -325,7 +306,7 @@ describe('e2e_blacklist_token_contract', () => { it('mint and try to redeem at blacklist', async () => { await expect(asset.methods.redeem_shield(blacklisted.getAddress(), amount, secret).prove()).rejects.toThrow( - "Assertion failed: Blacklisted: Recipient '!to_roles.isBlacklisted'", + "Assertion failed: Blacklisted: Recipient '!to_roles.is_blacklisted'", ); }); }); @@ -482,13 +463,13 @@ describe('e2e_blacklist_token_contract', () => { it('transfer from a blacklisted account', async () => { await expect( asset.methods.transfer_public(blacklisted.getAddress(), wallets[0].getAddress(), 1n, 0n).prove(), - ).rejects.toThrow("Assertion failed: Blacklisted: Sender '!from_roles.isBlacklisted'"); + ).rejects.toThrow("Assertion failed: Blacklisted: Sender '!from_roles.is_blacklisted'"); }); it('transfer to a blacklisted account', async () => { await expect( asset.methods.transfer_public(wallets[0].getAddress(), blacklisted.getAddress(), 1n, 0n).prove(), - ).rejects.toThrow("Assertion failed: Blacklisted: Recipient '!to_roles.isBlacklisted'"); + ).rejects.toThrow("Assertion failed: Blacklisted: Recipient '!to_roles.is_blacklisted'"); }); }); }); @@ -643,13 +624,13 @@ describe('e2e_blacklist_token_contract', () => { it('transfer from a blacklisted account', async () => { await expect( asset.methods.transfer(blacklisted.getAddress(), wallets[0].getAddress(), 1n, 0).prove(), - ).rejects.toThrow("Assertion failed: Blacklisted: Sender '!from_roles.isBlacklisted'"); + ).rejects.toThrow("Assertion failed: Blacklisted: Sender '!from_roles.is_blacklisted'"); }); it('transfer to a blacklisted account', async () => { await expect( asset.methods.transfer(wallets[0].getAddress(), blacklisted.getAddress(), 1n, 0).prove(), - ).rejects.toThrow("Assertion failed: Blacklisted: Recipient '!to_roles.isBlacklisted'"); + ).rejects.toThrow("Assertion failed: Blacklisted: Recipient '!to_roles.is_blacklisted'"); }); }); }); @@ -770,7 +751,7 @@ describe('e2e_blacklist_token_contract', () => { it('shielding from blacklisted account', async () => { await expect( asset.withWallet(blacklisted).methods.shield(blacklisted.getAddress(), 1n, secretHash, 0).prove(), - ).rejects.toThrow("Assertion failed: Blacklisted: Sender '!from_roles.isBlacklisted'"); + ).rejects.toThrow("Assertion failed: Blacklisted: Sender '!from_roles.is_blacklisted'"); }); }); }); @@ -884,13 +865,13 @@ describe('e2e_blacklist_token_contract', () => { it('unshield from blacklisted account', async () => { await expect( asset.methods.unshield(blacklisted.getAddress(), wallets[0].getAddress(), 1n, 0).prove(), - ).rejects.toThrow("Assertion failed: Blacklisted: Sender '!from_roles.isBlacklisted'"); + ).rejects.toThrow("Assertion failed: Blacklisted: Sender '!from_roles.is_blacklisted'"); }); it('unshield to blacklisted account', async () => { await expect( asset.methods.unshield(wallets[0].getAddress(), blacklisted.getAddress(), 1n, 0).prove(), - ).rejects.toThrow("Assertion failed: Blacklisted: Recipient '!to_roles.isBlacklisted'"); + ).rejects.toThrow("Assertion failed: Blacklisted: Recipient '!to_roles.is_blacklisted'"); }); }); }); @@ -987,7 +968,7 @@ describe('e2e_blacklist_token_contract', () => { it('burn from blacklisted account', async () => { await expect(asset.methods.burn_public(blacklisted.getAddress(), 1n, 0).prove()).rejects.toThrow( - "Assertion failed: Blacklisted: Sender '!from_roles.isBlacklisted'", + "Assertion failed: Blacklisted: Sender '!from_roles.is_blacklisted'", ); }); }); @@ -1105,7 +1086,7 @@ describe('e2e_blacklist_token_contract', () => { it('burn from blacklisted account', async () => { await expect(asset.methods.burn(blacklisted.getAddress(), 1n, 0).prove()).rejects.toThrow( - "Assertion failed: Blacklisted: Sender '!from_roles.isBlacklisted'", + "Assertion failed: Blacklisted: Sender '!from_roles.is_blacklisted'", ); }); }); From d1350da9e3d78fa53ccd5663219f70c67df4c66d Mon Sep 17 00:00:00 2001 From: James Zaki Date: Tue, 23 Apr 2024 10:11:01 +0100 Subject: [PATCH 078/102] docs: addition around Nargo.toml search (#5943) --- .../compiling_contracts/how_to_compile_contract.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/docs/docs/developers/contracts/compiling_contracts/how_to_compile_contract.md b/docs/docs/developers/contracts/compiling_contracts/how_to_compile_contract.md index 3f53b1b55d7..6f047087f03 100644 --- a/docs/docs/developers/contracts/compiling_contracts/how_to_compile_contract.md +++ b/docs/docs/developers/contracts/compiling_contracts/how_to_compile_contract.md @@ -20,6 +20,17 @@ aztec-nargo compile This will output a JSON [artifact](./artifacts.md) for each contract in the project to a `target` folder containing the Noir ABI artifacts. +:::note +This command looks for `Nargo.toml` files by ascending up the parent directories, and will compile the top-most Nargo.toml file it finds. +Eg: if you are in `/hobbies/cool-game/contracts/easter-egg/`, and both `cool-game` and `easter-egg` contain a Nargo.toml file, then `aztec-compile` will be performed on `cool-game/Nargo.toml` and compile the project(s) specified within it. Eg +``` +[workspace] +members = [ + "contracts/easter-egg", +] +``` +::: + ### Typescript Interfaces You can use the code generator to autogenerate type-safe typescript classes for each of your contracts. These classes define type-safe methods for deploying and interacting with your contract based on their artifact. From 4465e3be870963ea435d9a0cd063397020442f0b Mon Sep 17 00:00:00 2001 From: Jean M <132435771+jeanmon@users.noreply.github.com> Date: Tue, 23 Apr 2024 11:11:23 +0200 Subject: [PATCH 079/102] test(avm): Negative unit tests for AVM CAST opcode (#5907) Resolves #5908 --- .../barretenberg/vm/tests/avm_cast.test.cpp | 212 ++++++++++++++++-- 1 file changed, 196 insertions(+), 16 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_cast.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_cast.test.cpp index fbb35c11b5e..c31805f6fca 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_cast.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_cast.test.cpp @@ -9,11 +9,12 @@ using namespace bb::avm_trace; using namespace testing; class AvmCastTests : public ::testing::Test { - public: - AvmTraceBuilder trace_builder; - protected: + AvmTraceBuilder trace_builder; std::vector trace; + size_t main_idx; + size_t alu_idx; + size_t mem_idx_c; // TODO(640): The Standard Honk on Grumpkin test suite fails unless the SRS is initialised for every test. void SetUp() override { srs::init_crs_factory("../srs_db/ignition"); }; @@ -25,6 +26,28 @@ class AvmCastTests : public ::testing::Test { trace_builder.op_cast(0, src_address, dst_address, dst_tag); trace_builder.return_op(0, 0, 0); trace = trace_builder.finalize(); + gen_indices(); + } + + void gen_indices() + { + auto row = + std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_cast == FF(1); }); + ASSERT_TRUE(row != trace.end()); + main_idx = static_cast(row - trace.begin()); + + // Find the corresponding Alu trace row + auto clk = row->avm_main_clk; + auto alu_row = std::ranges::find_if(trace.begin(), trace.end(), [clk](Row r) { return r.avm_alu_clk == clk; }); + ASSERT_TRUE(alu_row != trace.end()); + alu_idx = static_cast(alu_row - trace.begin()); + + // Mem entry output ic write operation + auto mem_row_c = std::ranges::find_if(trace.begin(), trace.end(), [clk](Row r) { + return r.avm_mem_clk == clk && r.avm_mem_sub_clk == AvmMemTraceBuilder::SUB_CLK_STORE_C; + }); + ASSERT_TRUE(mem_row_c != trace.end()); + mem_idx_c = static_cast(mem_row_c - trace.begin()); } void validate_cast_trace(FF const& a, @@ -36,11 +59,8 @@ class AvmCastTests : public ::testing::Test { ) { - auto row = - std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_cast == FF(1); }); - ASSERT_TRUE(row != trace.end()); - - EXPECT_THAT(*row, + auto const& row = trace.at(main_idx); + EXPECT_THAT(row, AllOf(Field("sel_op_cast", &Row::avm_main_sel_op_cast, 1), Field("ia", &Row::avm_main_ia, a), Field("ib", &Row::avm_main_ib, 0), @@ -59,12 +79,8 @@ class AvmCastTests : public ::testing::Test { Field("sel_rng_8", &Row::avm_main_sel_rng_8, 1), Field("sel_rng_16", &Row::avm_main_sel_rng_16, 1))); - // Find the corresponding Alu trace row - auto clk = row->avm_main_clk; - auto alu_row = std::ranges::find_if(trace.begin(), trace.end(), [clk](Row r) { return r.avm_alu_clk == clk; }); - ASSERT_TRUE(alu_row != trace.end()); - - EXPECT_THAT(*alu_row, + auto const& alu_row = trace.at(alu_idx); + EXPECT_THAT(alu_row, AllOf(Field("op_cast", &Row::avm_alu_op_cast, 1), Field("alu_ia", &Row::avm_alu_ia, a), Field("alu_ib", &Row::avm_alu_ib, 0), @@ -81,15 +97,17 @@ class AvmCastTests : public ::testing::Test { Field("alu_sel", &Row::avm_alu_alu_sel, 1))); // Check that there is a second ALU row - auto alu_row_next = alu_row + 1; + auto alu_row_next = trace.at(alu_idx + 1); EXPECT_THAT( - *alu_row_next, + alu_row_next, AllOf(Field("op_cast", &Row::avm_alu_op_cast, 0), Field("op_cast_prev", &Row::avm_alu_op_cast_prev, 1))); validate_trace(std::move(trace)); } }; +class AvmCastNegativeTests : public AvmCastTests {}; + TEST_F(AvmCastTests, basicU8ToU16) { gen_trace(237, 0, 1, AvmMemoryTag::U8, AvmMemoryTag::U16); @@ -135,6 +153,7 @@ TEST_F(AvmCastTests, truncationFFToU16ModMinus1) trace_builder.op_cast(0, 0, 1, AvmMemoryTag::U16); trace_builder.return_op(0, 0, 0); trace = trace_builder.finalize(); + gen_indices(); validate_cast_trace(FF::modulus - 1, 0, 0, 1, AvmMemoryTag::FF, AvmMemoryTag::U16); } @@ -145,6 +164,7 @@ TEST_F(AvmCastTests, truncationFFToU16ModMinus2) trace_builder.op_cast(0, 0, 1, AvmMemoryTag::U16); trace_builder.return_op(0, 0, 0); trace = trace_builder.finalize(); + gen_indices(); validate_cast_trace(FF::modulus_minus_two, UINT16_MAX, 0, 1, AvmMemoryTag::FF, AvmMemoryTag::U16); } @@ -168,6 +188,7 @@ TEST_F(AvmCastTests, indirectAddrTruncationU64ToU8) trace_builder.op_cast(3, 0, 1, AvmMemoryTag::U8); trace_builder.return_op(0, 0, 0); trace = trace_builder.finalize(); + gen_indices(); validate_cast_trace(256'000'000'203UL, 203, 10, 11, AvmMemoryTag::U64, AvmMemoryTag::U8); } @@ -205,4 +226,163 @@ TEST_F(AvmCastTests, indirectAddrWrongResolutionU64ToU8) validate_trace(std::move(trace)); } +TEST_F(AvmCastNegativeTests, nonTruncatedOutputMainIc) +{ + gen_trace(300, 0, 1, AvmMemoryTag::U16, AvmMemoryTag::U8); + ASSERT_EQ(trace.at(main_idx).avm_main_ic, 44); + + // Replace the output in main trace with the non-truncated value + trace.at(main_idx).avm_main_ic = 300; + + // Adapt the memory trace entry + trace.at(mem_idx_c).avm_mem_val = 300; + + EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "PERM_MAIN_ALU"); +} + +TEST_F(AvmCastNegativeTests, wrongOutputMainIc) +{ + gen_trace(151515, 0, 1, AvmMemoryTag::U32, AvmMemoryTag::FF); + ASSERT_EQ(trace.at(main_idx).avm_main_ic, 151515); + + // Replace the output in main trace with a wrong value + trace.at(main_idx).avm_main_ic = 151516; + + // Adapt the memory trace entry + trace.at(mem_idx_c).avm_mem_val = 151516; + + EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "PERM_MAIN_ALU"); +} + +TEST_F(AvmCastNegativeTests, wrongOutputAluIc) +{ + gen_trace(6582736, 0, 1, AvmMemoryTag::U128, AvmMemoryTag::U16); + ASSERT_EQ(trace.at(alu_idx).avm_alu_ic, 29136); + + // Replace output in ALU, MAIN, and MEM trace + trace.at(alu_idx).avm_alu_ic = 33; + trace.at(main_idx).avm_main_ic = 33; + trace.at(mem_idx_c).avm_mem_val = 33; + + EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "ALU_OP_CAST"); +} + +TEST_F(AvmCastNegativeTests, wrongLimbDecompositionInput) +{ + trace_builder.calldata_copy(0, 0, 1, 0, { FF(FF::modulus_minus_two) }); + trace_builder.op_cast(0, 0, 1, AvmMemoryTag::U16); + trace_builder.return_op(0, 0, 0); + trace = trace_builder.finalize(); + gen_indices(); + + trace.at(alu_idx).avm_alu_a_lo -= 23; + + EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "INPUT_DECOMP_1"); +} + +TEST_F(AvmCastNegativeTests, wrongPSubALo) +{ + gen_trace(12345, 0, 1, AvmMemoryTag::U32, AvmMemoryTag::U16); + ASSERT_EQ(trace.at(alu_idx).avm_alu_ic, 12345); + + trace.at(alu_idx).avm_alu_p_sub_a_lo += 3; + + EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "SUB_LO_1"); +} + +TEST_F(AvmCastNegativeTests, wrongPSubAHi) +{ + trace_builder.calldata_copy(0, 0, 1, 0, { FF(FF::modulus_minus_two - 987) }); + trace_builder.op_cast(0, 0, 1, AvmMemoryTag::U16); + trace_builder.return_op(0, 0, 0); + trace = trace_builder.finalize(); + gen_indices(); + + trace.at(alu_idx).avm_alu_p_sub_a_hi += 3; + + EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "SUB_HI_1"); +} + +TEST_F(AvmCastNegativeTests, disableRangecheck) +{ + gen_trace(123, 23, 43, AvmMemoryTag::U8, AvmMemoryTag::U8); + + trace.at(alu_idx).avm_alu_rng_chk_lookup_selector = 0; + EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "RNG_CHK_LOOKUP_SELECTOR"); +} + +TEST_F(AvmCastNegativeTests, disableRangecheckSub) +{ + gen_trace(123, 23, 43, AvmMemoryTag::U8, AvmMemoryTag::U8); + + trace.at(alu_idx + 1).avm_alu_rng_chk_lookup_selector = 0; + EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "RNG_CHK_LOOKUP_SELECTOR"); +} + +TEST_F(AvmCastNegativeTests, wrongRangeCheckDecompositionLo) +{ + gen_trace(987344323, 23, 43, AvmMemoryTag::FF, AvmMemoryTag::U128); + ASSERT_EQ(trace.at(alu_idx).avm_alu_ic, 987344323); + + trace.at(alu_idx).avm_alu_u16_r0 = 5555; + EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "LOWER_CMP_RNG_CHK"); +} + +TEST_F(AvmCastNegativeTests, wrongRangeCheckDecompositionHi) +{ + trace_builder.calldata_copy(0, 0, 1, 0, { FF(FF::modulus_minus_two - 987) }); + trace_builder.op_cast(0, 0, 1, AvmMemoryTag::U16); + trace_builder.return_op(0, 0, 0); + trace = trace_builder.finalize(); + gen_indices(); + + trace.at(alu_idx).avm_alu_u16_r9 = 5555; + EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "UPPER_CMP_RNG_CHK"); +} + +TEST_F(AvmCastNegativeTests, outOfRangeU8Registers) +{ + gen_trace(987344323, 23, 43, AvmMemoryTag::FF, AvmMemoryTag::U128); + ASSERT_EQ(trace.at(alu_idx).avm_alu_ic, 987344323); + + trace.at(alu_idx).avm_alu_u8_r0 += 256; + trace.at(alu_idx).avm_alu_u8_r1 -= 1; // Adjust so that the decomposition is correct. + + EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "Lookup LOOKUP_U8_0"); +} + +TEST_F(AvmCastNegativeTests, outOfRangeU16Registers) +{ + gen_trace(987344323, 23, 43, AvmMemoryTag::FF, AvmMemoryTag::U128); + ASSERT_EQ(trace.at(alu_idx).avm_alu_ic, 987344323); + + trace.at(alu_idx).avm_alu_u16_r0 += 65536; + trace.at(alu_idx).avm_alu_u16_r1 -= 1; // Adjust so that the decomposition is correct. + + EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "Lookup LOOKUP_U16_0"); +} + +TEST_F(AvmCastNegativeTests, wrongCopySubLoForRangeCheck) +{ + gen_trace(987344323, 23, 43, AvmMemoryTag::U64, AvmMemoryTag::U128); + ASSERT_EQ(trace.at(alu_idx).avm_alu_ic, 987344323); + + ASSERT_EQ(trace.at(alu_idx + 1).avm_alu_a_lo, trace.at(alu_idx).avm_alu_p_sub_a_lo); + trace.at(alu_idx + 1).avm_alu_a_lo -= 1; + EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "OP_CAST_RNG_CHECK_P_SUB_A_LOW"); +} + +TEST_F(AvmCastNegativeTests, wrongCopySubHiForRangeCheck) +{ + trace_builder.calldata_copy(0, 0, 1, 0, { FF(FF::modulus_minus_two - 972836) }); + trace_builder.op_cast(0, 0, 1, AvmMemoryTag::U128); + trace_builder.return_op(0, 0, 0); + trace = trace_builder.finalize(); + gen_indices(); + + ASSERT_EQ(trace.at(alu_idx + 1).avm_alu_a_hi, trace.at(alu_idx).avm_alu_p_sub_a_hi); + trace.at(alu_idx + 1).avm_alu_a_hi += 2; + EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "OP_CAST_RNG_CHECK_P_SUB_A_HIGH"); +} + } // namespace tests_avm From 13153d02c8b0eb9cae1b7c0436fe1a1ddb49734f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Bene=C5=A1?= Date: Tue, 23 Apr 2024 13:29:59 +0200 Subject: [PATCH 080/102] feat: re-introducing update command (#5946) --- yarn-project/noir-compiler/src/cli.ts | 47 +++++- .../add_noir_compiler_commander_actions.ts | 21 --- yarn-project/noir-compiler/src/cli/index.ts | 1 - .../noir-compiler/src/cli/update/common.ts | 16 ++ .../noir-compiler/src/cli/update/github.ts | 3 + .../noir-compiler/src/cli/update/noir.ts | 57 +++++++ .../noir-compiler/src/cli/update/npm.ts | 154 ++++++++++++++++++ .../noir-compiler/src/cli/update/update.ts | 79 +++++++++ .../noir-compiler/src/cli/update/utils.ts | 50 ++++++ .../p2p/src/service/discv5_service.test.ts | 9 +- 10 files changed, 408 insertions(+), 29 deletions(-) delete mode 100644 yarn-project/noir-compiler/src/cli/add_noir_compiler_commander_actions.ts delete mode 100644 yarn-project/noir-compiler/src/cli/index.ts create mode 100644 yarn-project/noir-compiler/src/cli/update/common.ts create mode 100644 yarn-project/noir-compiler/src/cli/update/github.ts create mode 100644 yarn-project/noir-compiler/src/cli/update/noir.ts create mode 100644 yarn-project/noir-compiler/src/cli/update/npm.ts create mode 100644 yarn-project/noir-compiler/src/cli/update/update.ts create mode 100644 yarn-project/noir-compiler/src/cli/update/utils.ts diff --git a/yarn-project/noir-compiler/src/cli.ts b/yarn-project/noir-compiler/src/cli.ts index 7416abed4cc..931512a63d5 100644 --- a/yarn-project/noir-compiler/src/cli.ts +++ b/yarn-project/noir-compiler/src/cli.ts @@ -1,16 +1,55 @@ #!/usr/bin/env node import { createConsoleLogger } from '@aztec/foundation/log'; -import { Command } from 'commander'; - -import { addNoirCompilerCommanderActions } from './cli/add_noir_compiler_commander_actions.js'; +import { Command, Option } from 'commander'; +import { lookup } from 'dns/promises'; +import { dirname } from 'path'; const program = new Command(); const log = createConsoleLogger('aztec:compiler-cli'); +/** + * If we can successfully resolve 'host.docker.internal', then we are running in a container, and we should treat + * localhost as being host.docker.internal. + */ +const getLocalhost = () => + lookup('host.docker.internal') + .then(() => 'host.docker.internal') + .catch(() => 'localhost'); + +const LOCALHOST = await getLocalhost(); + const main = async () => { + const pxeOption = new Option('-u, --rpc-url ', 'URL of the PXE') + .env('PXE_URL') + .default(`http://${LOCALHOST}:8080`) + .makeOptionMandatory(true); + program.name('aztec-compile'); - addNoirCompilerCommanderActions(program, log); + program + .command('codegen') + .argument('', 'Path to the Noir ABI or project dir.') + .option('-o, --outdir ', 'Output folder for the generated code.') + .option('--force', 'Force code generation even when the contract has not changed.') + .description('Validates and generates an Aztec Contract ABI from Noir ABI.') + .action(async (noirAbiPath: string, { outdir, force }) => { + const { generateCode } = await import('./cli/codegen.js'); + generateCode(outdir || dirname(noirAbiPath), noirAbiPath, { force }); + }); + + program + .command('update') + .description('Updates Nodejs and Noir dependencies') + .argument('[projectPath]', 'Path to the project directory', process.cwd()) + .option('--contract [paths...]', 'Paths to contracts to update dependencies', []) + .option('--aztec-version ', 'The version to update Aztec packages to. Defaults to latest', 'latest') + .addOption(pxeOption) + .action(async (projectPath: string, options) => { + const { update } = await import('./cli/update/update.js'); + const { contract, aztecVersion, rpcUrl } = options; + await update(projectPath, contract, rpcUrl, aztecVersion, log); + }); + await program.parseAsync(process.argv); }; diff --git a/yarn-project/noir-compiler/src/cli/add_noir_compiler_commander_actions.ts b/yarn-project/noir-compiler/src/cli/add_noir_compiler_commander_actions.ts deleted file mode 100644 index a3330b8368f..00000000000 --- a/yarn-project/noir-compiler/src/cli/add_noir_compiler_commander_actions.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { type LogFn } from '@aztec/foundation/log'; - -import { type Command } from 'commander'; -import { dirname } from 'path'; - -export function addNoirCompilerCommanderActions(program: Command, log: LogFn = () => {}) { - addCodegenCommanderAction(program, log); -} - -export function addCodegenCommanderAction(program: Command, _: LogFn = () => {}) { - program - .command('codegen') - .argument('', 'Path to the Noir ABI or project dir.') - .option('-o, --outdir ', 'Output folder for the generated code.') - .option('--force', 'Force code generation even when the contract has not changed.') - .description('Validates and generates an Aztec Contract ABI from Noir ABI.') - .action(async (noirAbiPath: string, { outdir, force }) => { - const { generateCode } = await import('./codegen.js'); - generateCode(outdir || dirname(noirAbiPath), noirAbiPath, { force }); - }); -} diff --git a/yarn-project/noir-compiler/src/cli/index.ts b/yarn-project/noir-compiler/src/cli/index.ts deleted file mode 100644 index 4868340b60d..00000000000 --- a/yarn-project/noir-compiler/src/cli/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './add_noir_compiler_commander_actions.js'; diff --git a/yarn-project/noir-compiler/src/cli/update/common.ts b/yarn-project/noir-compiler/src/cli/update/common.ts new file mode 100644 index 00000000000..6041c1266e4 --- /dev/null +++ b/yarn-project/noir-compiler/src/cli/update/common.ts @@ -0,0 +1,16 @@ +/** + * Tracks changes to dependencies + */ +export type DependencyChanges = { + /** Which file was changed */ + file: string; + /** changes done to the file */ + dependencies: Array<{ + /** Name of the dependency being changed */ + name: string; + /** Previous version of the dependency */ + from: string; + /** New version of the dependency (after the update) */ + to: string; + }>; +}; diff --git a/yarn-project/noir-compiler/src/cli/update/github.ts b/yarn-project/noir-compiler/src/cli/update/github.ts new file mode 100644 index 00000000000..0486c382369 --- /dev/null +++ b/yarn-project/noir-compiler/src/cli/update/github.ts @@ -0,0 +1,3 @@ +export const GITHUB_OWNER = 'AztecProtocol'; +export const GITHUB_REPO = 'aztec-packages'; +export const GITHUB_TAG_PREFIX = 'aztec-packages'; diff --git a/yarn-project/noir-compiler/src/cli/update/noir.ts b/yarn-project/noir-compiler/src/cli/update/noir.ts new file mode 100644 index 00000000000..9b31189085d --- /dev/null +++ b/yarn-project/noir-compiler/src/cli/update/noir.ts @@ -0,0 +1,57 @@ +import { type LogFn } from '@aztec/foundation/log'; +import { parseNoirPackageConfig } from '@aztec/foundation/noir'; + +import TOML from '@iarna/toml'; +import { readFile } from 'fs/promises'; +import { join, relative, resolve } from 'path'; + +import { type DependencyChanges } from './common.js'; +import { atomicUpdateFile, prettyPrintNargoToml } from './utils.js'; + +/** + * Updates Aztec.nr dependencies + * @param contractPath - Path to the contract to be updated + * @param tag - The tag to update to + * @param log - Logging function + */ +export async function updateAztecNr(contractPath: string, tag: string, log: LogFn): Promise { + const configFilepath = resolve(join(contractPath, 'Nargo.toml')); + const packageConfig = parseNoirPackageConfig(TOML.parse(await readFile(configFilepath, 'utf-8'))); + const changes: DependencyChanges = { + dependencies: [], + file: configFilepath, + }; + + log(`Updating Aztec.nr libraries to ${tag} in ${relative(process.cwd(), changes.file)}`); + for (const dep of Object.values(packageConfig.dependencies)) { + if (!('git' in dep)) { + continue; + } + + // remove trailing slash + const gitUrl = dep.git.toLowerCase().replace(/\/$/, ''); + if (gitUrl !== 'https://github.com/aztecprotocol/aztec-packages') { + continue; + } + + if (dep.tag !== tag) { + // show the Aztec.nr package name rather than the lib name + const dirParts = dep.directory?.split('/') ?? []; + changes.dependencies.push({ + name: dirParts.slice(-2).join('/'), + from: dep.tag, + to: tag, + }); + + dep.tag = tag; + dep.directory = dep.directory?.replace('yarn-project/', 'noir-projects/'); + } + } + + if (changes.dependencies.length > 0) { + const contents = prettyPrintNargoToml(packageConfig); + await atomicUpdateFile(configFilepath, contents); + } + + return changes; +} diff --git a/yarn-project/noir-compiler/src/cli/update/npm.ts b/yarn-project/noir-compiler/src/cli/update/npm.ts new file mode 100644 index 00000000000..4be6e9eb01b --- /dev/null +++ b/yarn-project/noir-compiler/src/cli/update/npm.ts @@ -0,0 +1,154 @@ +import { type LogFn } from '@aztec/foundation/log'; + +import { spawnSync } from 'child_process'; +import { existsSync } from 'fs'; +import { readFile } from 'fs/promises'; +import { join, relative, resolve } from 'path'; +import { type SemVer, parse } from 'semver'; + +import { type DependencyChanges } from './common.js'; +import { atomicUpdateFile } from './utils.js'; + +const deprecatedNpmPackages = new Set(['@aztec/cli', '@aztec/aztec-sandbox']); +const npmDeprecationMessage = ` +The following packages have been deprecated and will no longer be updated on the npm registry: +${Array.from(deprecatedNpmPackages) + .map(pkg => ` - ${pkg}`) + .join('\n')} +Remove them from package.json +`; + +/** + * Looks up a package.json file and returns its contents + * @param projectPath - Path to Nodejs project + * @returns The parsed package.json + */ +export async function readPackageJson(projectPath: string): Promise<{ + /** dependencies */ + dependencies?: Record; + /** devDependencies */ + devDependencies?: Record; +}> { + const configFilepath = resolve(join(projectPath, 'package.json')); + const pkg = JSON.parse(await readFile(configFilepath, 'utf-8')); + + return pkg; +} + +/** + * Queries the npm registry for the latest version of a package + * @param packageName - The package to query + * @param distTag - The distribution tag + * @returns The latest version of the package on that distribution tag + */ +export async function getNewestVersion(packageName: string, distTag = 'latest'): Promise { + const url = new URL(packageName, 'https://registry.npmjs.org/'); + const response = await fetch(url); + if (!response.ok) { + throw new Error(`Failed to fetch ${url}`); + } + + const body = await response.json(); + const latestVersion = parse(body['dist-tags'][distTag]); + if (!latestVersion) { + throw new Error(`Failed to get latest version from registry`); + } + + return latestVersion; +} + +/** + * Updates a project's \@aztec/* dependencies to the specific version + * @param projectPath - Path to Nodejs project + * @param aztecVersion - The version to update to + * @returns True if the project was updated + */ +export async function updateAztecDeps( + projectPath: string, + aztecVersion: SemVer, + log: LogFn, +): Promise { + const pkg = await readPackageJson(projectPath); + const changes: DependencyChanges = { + file: resolve(join(projectPath, 'package.json')), + dependencies: [], + }; + + log(`Updating @aztec packages to ${aztecVersion} in ${relative(process.cwd(), changes.file)}`); + const version = aztecVersion.version; + + let detectedDeprecatedPackages = false; + + for (const depType of ['dependencies', 'devDependencies'] as const) { + const dependencies = pkg[depType]; + if (!dependencies) { + continue; + } + + for (const name of Object.keys(dependencies)) { + if (!name.startsWith('@aztec/')) { + continue; + } + + // different release schedule + if (name === '@aztec/aztec-ui') { + continue; + } + + if (deprecatedNpmPackages.has(name)) { + detectedDeprecatedPackages = true; + continue; + } + + if (dependencies[name] !== version) { + changes.dependencies.push({ + name, + from: dependencies[name], + to: version, + }); + + dependencies[name] = version; + } + } + } + + if (detectedDeprecatedPackages) { + log(npmDeprecationMessage); + } + + if (changes.dependencies.length > 0) { + const contents = JSON.stringify(pkg, null, 2) + '\n'; + await atomicUpdateFile(resolve(join(projectPath, 'package.json')), contents); + } + + return changes; +} + +/** + * Updates a project's yarn.lock or package-lock.json + * @param projectPath - Path to Nodejs project + */ +export function updateLockfile(projectPath: string, log: LogFn): void { + const isNpm = existsSync(resolve(join(projectPath, 'package-lock.json'))); + const isYarn = existsSync(resolve(join(projectPath, 'yarn.lock'))); + const isPnpm = existsSync(resolve(join(projectPath, 'pnpm-lock.yaml'))); + + if (isPnpm) { + spawnSync('pnpm', ['install'], { + cwd: projectPath, + stdio: 'inherit', + }); + } else if (isYarn) { + spawnSync('yarn', ['install'], { + cwd: projectPath, + stdio: 'inherit', + }); + } else if (isNpm) { + spawnSync('npm', ['install'], { + cwd: projectPath, + stdio: 'inherit', + }); + } else { + log(`No lockfile found in ${projectPath}. Skipping lockfile update...`); + } +} diff --git a/yarn-project/noir-compiler/src/cli/update/update.ts b/yarn-project/noir-compiler/src/cli/update/update.ts new file mode 100644 index 00000000000..0bbe96639ad --- /dev/null +++ b/yarn-project/noir-compiler/src/cli/update/update.ts @@ -0,0 +1,79 @@ +/* eslint-disable jsdoc/require-jsdoc */ +import { type LogFn } from '@aztec/foundation/log'; + +import { relative, resolve } from 'path'; +import { parse } from 'semver'; + +import { type DependencyChanges } from './common.js'; +import { GITHUB_TAG_PREFIX } from './github.js'; +import { updateAztecNr } from './noir.js'; +import { getNewestVersion, updateAztecDeps, updateLockfile } from './npm.js'; + +const AZTECJS_PACKAGE = '@aztec/aztec.js'; +const UPDATE_DOCS_URL = 'https://docs.aztec.network/developers/updating'; + +export async function update( + projectPath: string, + contracts: string[], + pxeUrl: string, + aztecVersion: string, + log: LogFn, +): Promise { + const targetAztecVersion = + aztecVersion === 'latest' ? await getNewestVersion(AZTECJS_PACKAGE, 'latest') : parse(aztecVersion); + + if (!targetAztecVersion) { + throw new Error(`Invalid aztec version ${aztecVersion}`); + } + + const projectDependencyChanges: DependencyChanges[] = []; + try { + const npmChanges = await updateAztecDeps(resolve(process.cwd(), projectPath), targetAztecVersion, log); + if (npmChanges.dependencies.length > 0) { + updateLockfile(projectPath, log); + } + + projectDependencyChanges.push(npmChanges); + } catch (err) { + if (err instanceof Error && 'code' in err && err.code === 'ENOENT') { + log(`No package.json found in ${projectPath}. Skipping npm update...`); + } else { + throw err; + } + } + + for (const contract of contracts) { + try { + projectDependencyChanges.push( + await updateAztecNr( + resolve(process.cwd(), projectPath, contract), + `${GITHUB_TAG_PREFIX}-v${targetAztecVersion.version}`, + log, + ), + ); + } catch (err) { + if (err instanceof Error && 'code' in err && err.code === 'ENOENT') { + log(`No Nargo.toml found in ${relative(process.cwd(), contract)}. Skipping...`); + } else { + throw err; + } + } + } + + log(`To update Docker containers follow instructions at ${UPDATE_DOCS_URL}`); + + projectDependencyChanges.forEach(changes => { + printChanges(changes, log); + }); +} + +function printChanges(changes: DependencyChanges, log: LogFn): void { + log(`\nIn ${relative(process.cwd(), changes.file)}:`); + if (changes.dependencies.length === 0) { + log(' No changes'); + } else { + changes.dependencies.forEach(({ name, from, to }) => { + log(` Updated ${name} from ${from} to ${to}`); + }); + } +} diff --git a/yarn-project/noir-compiler/src/cli/update/utils.ts b/yarn-project/noir-compiler/src/cli/update/utils.ts new file mode 100644 index 00000000000..f4bbb302f69 --- /dev/null +++ b/yarn-project/noir-compiler/src/cli/update/utils.ts @@ -0,0 +1,50 @@ +import { type NoirPackageConfig } from '@aztec/foundation/noir'; + +import TOML from '@iarna/toml'; +import { CommanderError } from 'commander'; +import { rename, writeFile } from 'fs/promises'; + +/** + * Updates a file in place atomically. + * @param filePath - Path to file + * @param contents - New contents to write + */ +export async function atomicUpdateFile(filePath: string, contents: string) { + const tmpFilepath = filePath + '.tmp'; + try { + await writeFile(tmpFilepath, contents, { + // let's crash if the tmp file already exists + flag: 'wx', + }); + await rename(tmpFilepath, filePath); + } catch (e) { + if (e instanceof Error && 'code' in e && e.code === 'EEXIST') { + const commanderError = new CommanderError( + 1, + e.code, + `Temporary file already exists: ${tmpFilepath}. Delete this file and try again.`, + ); + commanderError.nestedError = e.message; + throw commanderError; + } else { + throw e; + } + } +} + +/** + * Pretty prints Nargo.toml contents to a string + * @param config - Nargo.toml contents + * @returns The Nargo.toml contents as a string + */ +export function prettyPrintNargoToml(config: NoirPackageConfig): string { + const withoutDependencies = Object.fromEntries(Object.entries(config).filter(([key]) => key !== 'dependencies')); + + const partialToml = TOML.stringify(withoutDependencies); + const dependenciesToml = Object.entries(config.dependencies).map(([name, dep]) => { + const depToml = TOML.stringify.value(dep); + return `${name} = ${depToml}`; + }); + + return partialToml + '\n[dependencies]\n' + dependenciesToml.join('\n') + '\n'; +} diff --git a/yarn-project/p2p/src/service/discv5_service.test.ts b/yarn-project/p2p/src/service/discv5_service.test.ts index 974ca9c0238..9878379ea73 100644 --- a/yarn-project/p2p/src/service/discv5_service.test.ts +++ b/yarn-project/p2p/src/service/discv5_service.test.ts @@ -48,7 +48,7 @@ describe('Discv5Service', () => { const node2 = await createNode(port); await node1.start(); await node2.start(); - await sleep(100); + await sleep(200); const node1Peers = await Promise.all(node1.getAllPeers().map(async peer => (await peer.peerId()).toString())); const node2Peers = await Promise.all(node2.getAllPeers().map(async peer => (await peer.peerId()).toString())); @@ -68,17 +68,20 @@ describe('Discv5Service', () => { const node2 = await createNode(port); await node1.start(); await node2.start(); - await sleep(100); + await sleep(200); await node2.stop(); await bootNode.stop(); await node2.start(); - await sleep(100); + await sleep(200); const node2Peers = await Promise.all(node2.getAllPeers().map(async peer => (await peer.peerId()).toString())); expect(node2Peers).toHaveLength(1); expect(node2Peers).toContain(node1.getPeerId().toString()); + + await node1.stop(); + await node2.stop(); }); const createNode = async (port: number) => { From cea51073be4ecc65a3c8d36cfe107df8390b853f Mon Sep 17 00:00:00 2001 From: Aztec Bot <49558828+AztecBot@users.noreply.github.com> Date: Tue, 23 Apr 2024 13:31:54 +0100 Subject: [PATCH 081/102] feat: Sync from noir (#5935) Automated pull of development from the [noir](https://github.com/noir-lang/noir) programming language, a dependency of Aztec. BEGIN_COMMIT_OVERRIDE chore: remove pub wildcard import of ast into `noirc_frontend` root (https://github.com/noir-lang/noir/pull/4862) chore: remove `SecondaryAttribute::Event` (https://github.com/noir-lang/noir/pull/4868) chore: more explicit `self` parameter in `Into` trait (https://github.com/noir-lang/noir/pull/4867) chore: remove initialisation of logger in `acvm_js` tests (https://github.com/noir-lang/noir/pull/4850) chore: bump MSRV to `1.74.1` (https://github.com/noir-lang/noir/pull/4873) chore: update NoirJS tutorial (https://github.com/noir-lang/noir/pull/4861) chore(docs): remove link to play.noir-lang.org (https://github.com/noir-lang/noir/pull/4872) chore: update noir README (https://github.com/noir-lang/noir/pull/4856) feat(experimental): Add `comptime` keyword (https://github.com/noir-lang/noir/pull/4840) feat: add `min` and `max` functions to the stdlib (https://github.com/noir-lang/noir/pull/4839) feat: Allow numeric generics to non inlined ACIR functions (https://github.com/noir-lang/noir/pull/4834) chore!: Add `as_array` and remove `_slice` variants of hash functions (https://github.com/noir-lang/noir/pull/4675) feat!: reserve keyword `super` (https://github.com/noir-lang/noir/pull/4836) feat: simplify `BoundedVec::eq` (https://github.com/noir-lang/noir/pull/4838) feat: Add comptime Interpreter (https://github.com/noir-lang/noir/pull/4821) feat: Sync from aztec-packages (https://github.com/noir-lang/noir/pull/4833) feat: implement `Eq` trait on `BoundedVec` (https://github.com/noir-lang/noir/pull/4830) chore: add benchmarks for serializing a dummy program (https://github.com/noir-lang/noir/pull/4813) END_COMMIT_OVERRIDE --------- Co-authored-by: TomAFrench Co-authored-by: Tom French <15848336+TomAFrench@users.noreply.github.com> Co-authored-by: Maxim Vezenov --- .noir-sync-commit | 2 +- avm-transpiler/Cargo.lock | 1 + avm-transpiler/rust-toolchain.toml | 2 +- .../contracts/card_game_contract/src/cards.nr | 3 +- .../ecdsa_account_contract/src/main.nr | 3 +- noir/noir-repo/.github/workflows/docs-pr.yml | 2 +- .../.github/workflows/formatting.yml | 4 +- .../.github/workflows/gates_report.yml | 2 +- .../.github/workflows/publish-acvm.yml | 2 +- .../.github/workflows/publish-es-packages.yml | 6 +- .../.github/workflows/publish-nargo.yml | 4 +- .../.github/workflows/test-js-packages.yml | 8 +- .../workflows/test-rust-workspace-msrv.yml | 4 +- .../.github/workflows/test-rust-workspace.yml | 4 +- noir/noir-repo/CHANGELOG.md | 2 +- noir/noir-repo/Cargo.lock | 33 +- noir/noir-repo/Cargo.toml | 11 +- noir/noir-repo/README.md | 61 +- noir/noir-repo/acvm-repo/acir/Cargo.toml | 6 + .../acvm-repo/acir/benches/serialization.rs | 123 ++ noir/noir-repo/acvm-repo/acvm_js/build.sh | 2 - .../test/browser/black_box_solvers.test.ts | 3 - .../compute_note_hash_and_nullifier.rs | 3 +- .../src/transforms/contract_interface.rs | 5 +- .../aztec_macros/src/transforms/events.rs | 6 +- .../aztec_macros/src/transforms/functions.rs | 15 +- .../src/transforms/note_interface.rs | 8 +- .../aztec_macros/src/transforms/storage.rs | 8 +- .../aztec_macros/src/utils/ast_utils.rs | 13 +- .../aztec_macros/src/utils/errors.rs | 9 +- .../aztec_macros/src/utils/hir_utils.rs | 13 +- noir/noir-repo/compiler/fm/Cargo.toml | 1 + .../compiler/noirc_driver/Cargo.toml | 1 + .../compiler/noirc_driver/src/abi_gen.rs | 2 +- .../compiler/noirc_errors/Cargo.toml | 1 + .../compiler/noirc_evaluator/Cargo.toml | 5 +- .../compiler/noirc_evaluator/src/ssa.rs | 5 +- .../noirc_evaluator/src/ssa/acir_gen/mod.rs | 10 +- .../src/ssa/function_builder/data_bus.rs | 5 +- .../src/ssa/ssa_gen/context.rs | 20 +- .../noirc_evaluator/src/ssa/ssa_gen/mod.rs | 16 +- .../compiler/noirc_frontend/Cargo.toml | 2 + .../noirc_frontend/src/ast/expression.rs | 9 +- .../noirc_frontend/src/ast/function.rs | 2 +- .../noirc_frontend/src/ast/statement.rs | 74 +- .../noirc_frontend/src/ast/structure.rs | 4 +- .../compiler/noirc_frontend/src/ast/traits.rs | 7 +- .../noirc_frontend/src/ast/type_alias.rs | 2 +- .../compiler/noirc_frontend/src/debug/mod.rs | 3 + .../src/hir/comptime/hir_to_ast.rs | 19 +- .../src/hir/comptime/interpreter.rs | 1294 +++++++++++++++++ .../noirc_frontend/src/hir/comptime/mod.rs | 2 + .../noirc_frontend/src/hir/comptime/tests.rs | 166 +++ .../src/hir/def_collector/dc_crate.rs | 8 +- .../src/hir/def_collector/dc_mod.rs | 7 +- .../src/hir/def_collector/errors.rs | 3 +- .../src/hir/def_map/item_scope.rs | 7 +- .../src/hir/def_map/module_data.rs | 7 +- .../src/hir/def_map/namespace.rs | 2 +- .../src/hir/resolution/errors.rs | 4 +- .../src/hir/resolution/impls.rs | 3 +- .../src/hir/resolution/import.rs | 2 +- .../src/hir/resolution/path_resolver.rs | 2 +- .../src/hir/resolution/resolver.rs | 35 +- .../src/hir/resolution/structs.rs | 3 +- .../src/hir/resolution/traits.rs | 3 +- .../src/hir/type_check/errors.rs | 5 +- .../noirc_frontend/src/hir/type_check/expr.rs | 17 +- .../noirc_frontend/src/hir/type_check/mod.rs | 76 +- .../noirc_frontend/src/hir/type_check/stmt.rs | 3 +- .../noirc_frontend/src/hir_def/expr.rs | 9 +- .../noirc_frontend/src/hir_def/function.rs | 8 +- .../noirc_frontend/src/hir_def/stmt.rs | 8 +- .../noirc_frontend/src/hir_def/traits.rs | 3 +- .../noirc_frontend/src/hir_def/types.rs | 55 +- .../noirc_frontend/src/lexer/token.rs | 12 +- .../compiler/noirc_frontend/src/lib.rs | 20 +- .../src/monomorphization/ast.rs | 8 +- .../src/monomorphization/mod.rs | 25 +- .../noirc_frontend/src/node_interner.rs | 12 +- .../noirc_frontend/src/noir_parser.lalrpop | 2 +- .../noirc_frontend/src/parser/errors.rs | 3 +- .../compiler/noirc_frontend/src/parser/mod.rs | 9 +- .../noirc_frontend/src/parser/parser.rs | 97 +- .../src/parser/parser/assertion.rs | 4 +- .../src/parser/parser/function.rs | 26 +- .../src/parser/parser/lambdas.rs | 5 +- .../src/parser/parser/literals.rs | 4 +- .../noirc_frontend/src/parser/parser/path.rs | 2 +- .../src/parser/parser/primitives.rs | 2 +- .../src/parser/parser/structs.rs | 2 +- .../src/parser/parser/traits.rs | 6 +- .../compiler/noirc_frontend/src/tests.rs | 3 +- .../compiler/noirc_printable_type/Cargo.toml | 1 + .../noir-repo/compiler/utils/arena/Cargo.toml | 1 + .../compiler/utils/iter-extended/Cargo.toml | 1 + noir/noir-repo/compiler/wasm/Cargo.toml | 1 + .../docs/noir/concepts/data_types/slices.mdx | 25 + .../standard_library/containers/hashmap.md | 5 +- .../cryptographic_primitives/hashes.mdx | 57 +- .../docs/docs/noir/standard_library/traits.md | 2 + .../docs/docs/tutorials/noirjs_app.md | 89 +- .../getting_started/tooling/index.md | 6 +- .../getting_started/tooling/index.mdx | 6 +- .../getting_started/tooling/index.mdx | 6 +- .../getting_started/tooling/index.mdx | 6 +- .../version-v0.25.0/tutorials/noirjs_app.md | 81 +- .../getting_started/tooling/index.mdx | 6 +- .../version-v0.26.0/tutorials/noirjs_app.md | 81 +- .../getting_started/tooling/index.mdx | 6 +- noir/noir-repo/noir-logo.png | Bin 0 -> 224467 bytes noir/noir-repo/noir_stdlib/src/cmp.nr | 52 + .../src/collections/bounded_vec.nr | 36 + noir/noir-repo/noir_stdlib/src/convert.nr | 6 +- noir/noir-repo/noir_stdlib/src/hash.nr | 81 +- noir/noir-repo/noir_stdlib/src/hash/mimc.nr | 13 +- .../noir_stdlib/src/hash/pedersen.nr | 24 - .../noir_stdlib/src/hash/poseidon.nr | 40 +- .../noir_stdlib/src/hash/poseidon2.nr | 15 +- noir/noir-repo/noir_stdlib/src/slice.nr | 10 + noir/noir-repo/rust-toolchain.toml | 2 +- noir/noir-repo/scripts/benchmark_start.sh | 3 + noir/noir-repo/scripts/benchmark_stop.sh | 3 + .../hashmap_load_factor/src/main.nr | 4 +- .../execution_success/eddsa/src/main.nr | 4 - .../fold_numeric_generic_poseidon/Nargo.toml | 7 + .../fold_numeric_generic_poseidon/Prover.toml | 2 + .../fold_numeric_generic_poseidon/src/main.nr | 33 + .../execution_success/hashmap/src/main.nr | 26 +- .../regression_sha256_slice/Nargo.toml | 7 - .../regression_sha256_slice/Prover.toml | 1 - .../regression_sha256_slice/src/main.nr | 12 - .../tooling/backend_interface/Cargo.toml | 2 +- .../tooling/backend_interface/src/cli/info.rs | 2 +- .../tooling/bb_abstraction_leaks/build.rs | 2 +- noir/noir-repo/tooling/debugger/Cargo.toml | 1 + .../tooling/debugger/ignored-tests.txt | 3 + noir/noir-repo/tooling/lsp/Cargo.toml | 3 +- noir/noir-repo/tooling/nargo/Cargo.toml | 4 +- noir/noir-repo/tooling/nargo/build.rs | 12 - noir/noir-repo/tooling/nargo_cli/Cargo.toml | 10 +- noir/noir-repo/tooling/nargo_cli/build.rs | 10 - noir/noir-repo/tooling/nargo_fmt/Cargo.toml | 1 + .../tooling/nargo_fmt/src/rewrite/array.rs | 2 +- .../tooling/nargo_fmt/src/rewrite/expr.rs | 6 +- .../tooling/nargo_fmt/src/rewrite/imports.rs | 14 +- .../tooling/nargo_fmt/src/rewrite/infix.rs | 2 +- .../nargo_fmt/src/rewrite/parenthesized.rs | 3 +- .../tooling/nargo_fmt/src/rewrite/typ.rs | 2 +- noir/noir-repo/tooling/nargo_fmt/src/utils.rs | 2 +- .../tooling/nargo_fmt/src/visitor/expr.rs | 7 +- .../tooling/nargo_fmt/src/visitor/item.rs | 14 +- .../tooling/nargo_fmt/src/visitor/stmt.rs | 168 +-- noir/noir-repo/tooling/nargo_toml/Cargo.toml | 1 + .../noir_js_backend_barretenberg/package.json | 2 +- noir/noir-repo/tooling/noirc_abi/Cargo.toml | 1 + noir/noir-repo/tooling/noirc_abi/src/lib.rs | 3 +- noir/noir-repo/yarn.lock | 13 +- 158 files changed, 2744 insertions(+), 837 deletions(-) create mode 100644 noir/noir-repo/acvm-repo/acir/benches/serialization.rs create mode 100644 noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter.rs create mode 100644 noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/tests.rs create mode 100644 noir/noir-repo/noir-logo.png delete mode 100644 noir/noir-repo/noir_stdlib/src/hash/pedersen.nr create mode 100755 noir/noir-repo/scripts/benchmark_start.sh create mode 100755 noir/noir-repo/scripts/benchmark_stop.sh create mode 100644 noir/noir-repo/test_programs/execution_success/fold_numeric_generic_poseidon/Nargo.toml create mode 100644 noir/noir-repo/test_programs/execution_success/fold_numeric_generic_poseidon/Prover.toml create mode 100644 noir/noir-repo/test_programs/execution_success/fold_numeric_generic_poseidon/src/main.nr delete mode 100644 noir/noir-repo/test_programs/execution_success/regression_sha256_slice/Nargo.toml delete mode 100644 noir/noir-repo/test_programs/execution_success/regression_sha256_slice/Prover.toml delete mode 100644 noir/noir-repo/test_programs/execution_success/regression_sha256_slice/src/main.nr delete mode 100644 noir/noir-repo/tooling/nargo/build.rs diff --git a/.noir-sync-commit b/.noir-sync-commit index 8f6aafb96d3..2863ab07e89 100644 --- a/.noir-sync-commit +++ b/.noir-sync-commit @@ -1 +1 @@ -6cc105ee441e093b4fccdd5fcc3db922eb28a3fb +1969ce39378f633e88adedf43b747724b89ed7d7 diff --git a/avm-transpiler/Cargo.lock b/avm-transpiler/Cargo.lock index 6fc2aa934f5..21ff357893f 100644 --- a/avm-transpiler/Cargo.lock +++ b/avm-transpiler/Cargo.lock @@ -1274,6 +1274,7 @@ dependencies = [ "arena", "chumsky", "fm", + "im", "iter-extended", "lalrpop", "lalrpop-util", diff --git a/avm-transpiler/rust-toolchain.toml b/avm-transpiler/rust-toolchain.toml index c9f40a6577e..77b50d3cfe1 100644 --- a/avm-transpiler/rust-toolchain.toml +++ b/avm-transpiler/rust-toolchain.toml @@ -1,5 +1,5 @@ [toolchain] -channel = "1.73" +channel = "1.74.1" components = ["rust-src"] targets = [] profile = "default" diff --git a/noir-projects/noir-contracts/contracts/card_game_contract/src/cards.nr b/noir-projects/noir-contracts/contracts/card_game_contract/src/cards.nr index e46fb7e8407..7ae2edbda8b 100644 --- a/noir-projects/noir-contracts/contracts/card_game_contract/src/cards.nr +++ b/noir-projects/noir-contracts/contracts/card_game_contract/src/cards.nr @@ -174,7 +174,8 @@ pub fn get_pack_cards( // generate pseudo randomness deterministically from 'seed' and user secret let secret = context.request_app_nullifier_secret_key(owner); let mix = secret + seed; - let random_bytes = std::hash::sha256_slice(mix.to_le_bytes(32)); + let mix_bytes: [u8; 32] = mix.to_le_bytes(32).as_array(); + let random_bytes = std::hash::sha256(mix_bytes); let mut cards = [Card::from_field(0); PACK_CARDS]; // we generate PACK_CARDS cards diff --git a/noir-projects/noir-contracts/contracts/ecdsa_account_contract/src/main.nr b/noir-projects/noir-contracts/contracts/ecdsa_account_contract/src/main.nr index 30fb2737fc8..25f96128b9d 100644 --- a/noir-projects/noir-contracts/contracts/ecdsa_account_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/ecdsa_account_contract/src/main.nr @@ -80,7 +80,8 @@ contract EcdsaAccount { // Verify payload signature using Ethereum's signing scheme // Note that noir expects the hash of the message/challenge as input to the ECDSA verification. - let hashed_message: [u8; 32] = std::hash::sha256_slice(outer_hash.to_be_bytes(32)); + let outer_hash_bytes: [u8; 32] = outer_hash.to_be_bytes(32).as_array(); + let hashed_message: [u8; 32] = std::hash::sha256(outer_hash_bytes); let verification = std::ecdsa_secp256k1::verify_signature(public_key.x, public_key.y, signature, hashed_message); assert(verification == true); diff --git a/noir/noir-repo/.github/workflows/docs-pr.yml b/noir/noir-repo/.github/workflows/docs-pr.yml index 1f9ccdd946b..945ed555639 100644 --- a/noir/noir-repo/.github/workflows/docs-pr.yml +++ b/noir/noir-repo/.github/workflows/docs-pr.yml @@ -55,7 +55,7 @@ jobs: uses: actions/checkout@v4 - name: Setup toolchain - uses: dtolnay/rust-toolchain@1.73.0 + uses: dtolnay/rust-toolchain@1.74.1 - uses: Swatinem/rust-cache@v2 with: diff --git a/noir/noir-repo/.github/workflows/formatting.yml b/noir/noir-repo/.github/workflows/formatting.yml index 279e90f5f6f..8166fb0f7c2 100644 --- a/noir/noir-repo/.github/workflows/formatting.yml +++ b/noir/noir-repo/.github/workflows/formatting.yml @@ -32,7 +32,7 @@ jobs: uses: actions/checkout@v4 - name: Setup toolchain - uses: dtolnay/rust-toolchain@1.73.0 + uses: dtolnay/rust-toolchain@1.74.1 with: targets: ${{ matrix.target }} components: clippy, rustfmt @@ -73,7 +73,7 @@ jobs: uses: actions/checkout@v4 - name: Setup toolchain - uses: dtolnay/rust-toolchain@1.73.0 + uses: dtolnay/rust-toolchain@1.74.1 - uses: Swatinem/rust-cache@v2 with: diff --git a/noir/noir-repo/.github/workflows/gates_report.yml b/noir/noir-repo/.github/workflows/gates_report.yml index be55236c40f..e694e5fad04 100644 --- a/noir/noir-repo/.github/workflows/gates_report.yml +++ b/noir/noir-repo/.github/workflows/gates_report.yml @@ -18,7 +18,7 @@ jobs: uses: actions/checkout@v4 - name: Setup toolchain - uses: dtolnay/rust-toolchain@1.73.0 + uses: dtolnay/rust-toolchain@1.74.1 - uses: Swatinem/rust-cache@v2 with: diff --git a/noir/noir-repo/.github/workflows/publish-acvm.yml b/noir/noir-repo/.github/workflows/publish-acvm.yml index d17d8f294fb..feb4d4216c3 100644 --- a/noir/noir-repo/.github/workflows/publish-acvm.yml +++ b/noir/noir-repo/.github/workflows/publish-acvm.yml @@ -18,7 +18,7 @@ jobs: ref: ${{ inputs.noir-ref }} - name: Setup toolchain - uses: dtolnay/rust-toolchain@1.73.0 + uses: dtolnay/rust-toolchain@1.74.1 # These steps are in a specific order so crate dependencies are updated first - name: Publish acir_field diff --git a/noir/noir-repo/.github/workflows/publish-es-packages.yml b/noir/noir-repo/.github/workflows/publish-es-packages.yml index 819be308169..682fed69c7b 100644 --- a/noir/noir-repo/.github/workflows/publish-es-packages.yml +++ b/noir/noir-repo/.github/workflows/publish-es-packages.yml @@ -24,7 +24,7 @@ jobs: ref: ${{ inputs.noir-ref }} - name: Setup toolchain - uses: dtolnay/rust-toolchain@1.73.0 + uses: dtolnay/rust-toolchain@1.74.1 - uses: Swatinem/rust-cache@v2 with: @@ -58,7 +58,7 @@ jobs: ref: ${{ inputs.noir-ref }} - name: Setup toolchain - uses: dtolnay/rust-toolchain@1.73.0 + uses: dtolnay/rust-toolchain@1.74.1 - uses: Swatinem/rust-cache@v2 with: @@ -95,7 +95,7 @@ jobs: ref: ${{ inputs.noir-ref }} - name: Setup toolchain - uses: dtolnay/rust-toolchain@1.73.0 + uses: dtolnay/rust-toolchain@1.74.1 - uses: Swatinem/rust-cache@v2 with: diff --git a/noir/noir-repo/.github/workflows/publish-nargo.yml b/noir/noir-repo/.github/workflows/publish-nargo.yml index e47e1a13053..85010503b00 100644 --- a/noir/noir-repo/.github/workflows/publish-nargo.yml +++ b/noir/noir-repo/.github/workflows/publish-nargo.yml @@ -46,7 +46,7 @@ jobs: echo "MACOSX_DEPLOYMENT_TARGET=$(xcrun -sdk macosx$(sw_vers -productVersion) --show-sdk-platform-version)" >> $GITHUB_ENV - name: Setup toolchain - uses: dtolnay/rust-toolchain@1.73.0 + uses: dtolnay/rust-toolchain@1.74.1 with: targets: ${{ matrix.target }} @@ -120,7 +120,7 @@ jobs: ref: ${{ inputs.tag || env.GITHUB_REF }} - name: Setup toolchain - uses: dtolnay/rust-toolchain@1.73.0 + uses: dtolnay/rust-toolchain@1.74.1 with: targets: ${{ matrix.target }} diff --git a/noir/noir-repo/.github/workflows/test-js-packages.yml b/noir/noir-repo/.github/workflows/test-js-packages.yml index 06a96ee8932..7fd198d9a89 100644 --- a/noir/noir-repo/.github/workflows/test-js-packages.yml +++ b/noir/noir-repo/.github/workflows/test-js-packages.yml @@ -22,7 +22,7 @@ jobs: uses: actions/checkout@v4 - name: Setup toolchain - uses: dtolnay/rust-toolchain@1.73.0 + uses: dtolnay/rust-toolchain@1.74.1 - uses: Swatinem/rust-cache@v2 with: @@ -55,7 +55,7 @@ jobs: uses: actions/checkout@v4 - name: Setup toolchain - uses: dtolnay/rust-toolchain@1.73.0 + uses: dtolnay/rust-toolchain@1.74.1 - uses: Swatinem/rust-cache@v2 with: @@ -88,7 +88,7 @@ jobs: uses: actions/checkout@v4 - name: Setup toolchain - uses: dtolnay/rust-toolchain@1.73.0 + uses: dtolnay/rust-toolchain@1.74.1 - uses: Swatinem/rust-cache@v2 with: @@ -123,7 +123,7 @@ jobs: uses: actions/checkout@v4 - name: Setup toolchain - uses: dtolnay/rust-toolchain@1.73.0 + uses: dtolnay/rust-toolchain@1.74.1 - uses: Swatinem/rust-cache@v2 with: diff --git a/noir/noir-repo/.github/workflows/test-rust-workspace-msrv.yml b/noir/noir-repo/.github/workflows/test-rust-workspace-msrv.yml index cdd7a064a8d..c13b0815d94 100644 --- a/noir/noir-repo/.github/workflows/test-rust-workspace-msrv.yml +++ b/noir/noir-repo/.github/workflows/test-rust-workspace-msrv.yml @@ -29,7 +29,7 @@ jobs: uses: actions/checkout@v4 - name: Setup toolchain - uses: dtolnay/rust-toolchain@1.73.0 + uses: dtolnay/rust-toolchain@1.74.1 with: targets: x86_64-unknown-linux-gnu @@ -72,7 +72,7 @@ jobs: - uses: actions/checkout@v4 - name: Setup toolchain - uses: dtolnay/rust-toolchain@1.73.0 + uses: dtolnay/rust-toolchain@1.74.1 with: targets: x86_64-unknown-linux-gnu diff --git a/noir/noir-repo/.github/workflows/test-rust-workspace.yml b/noir/noir-repo/.github/workflows/test-rust-workspace.yml index 22684de3044..cf35950fa3e 100644 --- a/noir/noir-repo/.github/workflows/test-rust-workspace.yml +++ b/noir/noir-repo/.github/workflows/test-rust-workspace.yml @@ -23,7 +23,7 @@ jobs: uses: actions/checkout@v4 - name: Setup toolchain - uses: dtolnay/rust-toolchain@1.73.0 + uses: dtolnay/rust-toolchain@1.74.1 with: targets: x86_64-unknown-linux-gnu @@ -59,7 +59,7 @@ jobs: - uses: actions/checkout@v4 - name: Setup toolchain - uses: dtolnay/rust-toolchain@1.73.0 + uses: dtolnay/rust-toolchain@1.74.1 with: targets: x86_64-unknown-linux-gnu diff --git a/noir/noir-repo/CHANGELOG.md b/noir/noir-repo/CHANGELOG.md index 0ab84df44e7..a084811fc21 100644 --- a/noir/noir-repo/CHANGELOG.md +++ b/noir/noir-repo/CHANGELOG.md @@ -109,7 +109,7 @@ * reserve `unchecked` keyword ([#4432](https://github.com/noir-lang/noir/issues/4432)) * Remove empty value from bounded vec ([#4431](https://github.com/noir-lang/noir/issues/4431)) * Ban Fields in for loop indices and bitwise ops ([#4376](https://github.com/noir-lang/noir/issues/4376)) -* bump msrv to 1.73.0 ([#4406](https://github.com/noir-lang/noir/issues/4406)) +* Bump msrv to 1.73.0 ([#4406](https://github.com/noir-lang/noir/issues/4406)) * **ci:** Bump MSRV to 1.72.1 and enforce that ACVM can be published using updated lockfile ([#4385](https://github.com/noir-lang/noir/issues/4385)) * Restrict bit sizes ([#4235](https://github.com/noir-lang/noir/issues/4235)) * move noir out of yarn-project (https://github.com/AztecProtocol/aztec-packages/pull/4479) diff --git a/noir/noir-repo/Cargo.lock b/noir/noir-repo/Cargo.lock index ee83f7f8ddf..35702c8df03 100644 --- a/noir/noir-repo/Cargo.lock +++ b/noir/noir-repo/Cargo.lock @@ -10,8 +10,10 @@ dependencies = [ "base64 0.21.2", "bincode", "brillig", + "criterion", "flate2", "fxhash", + "pprof 0.13.0", "serde", "serde-big-array", "serde-generate", @@ -454,7 +456,7 @@ dependencies = [ [[package]] name = "backend-interface" -version = "0.11.0" +version = "0.27.0" dependencies = [ "acvm", "bb_abstraction_leaks", @@ -624,7 +626,7 @@ dependencies = [ "lazy_static", "noir_grumpkin", "num-bigint", - "pprof", + "pprof 0.12.1", "thiserror", "wasm-bindgen-futures", "wasmer", @@ -2825,7 +2827,6 @@ dependencies = [ "noirc_frontend", "noirc_printable_type", "rayon", - "rustc_version", "serde", "tempfile", "thiserror", @@ -2866,11 +2867,10 @@ dependencies = [ "notify", "notify-debouncer-full", "paste", - "pprof", + "pprof 0.13.0", "predicates 2.1.5", "prettytable-rs", "rayon", - "rustc_version", "serde", "serde_json", "similar-asserts", @@ -3161,6 +3161,7 @@ dependencies = [ "base64 0.21.2", "chumsky", "fm", + "im", "iter-extended", "lalrpop", "lalrpop-util", @@ -3547,6 +3548,28 @@ dependencies = [ "thiserror", ] +[[package]] +name = "pprof" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef5c97c51bd34c7e742402e216abdeb44d415fbe6ae41d56b114723e953711cb" +dependencies = [ + "backtrace", + "cfg-if 1.0.0", + "criterion", + "findshlibs", + "inferno", + "libc", + "log", + "nix 0.26.4", + "once_cell", + "parking_lot 0.12.1", + "smallvec", + "symbolic-demangle", + "tempfile", + "thiserror", +] + [[package]] name = "ppv-lite86" version = "0.2.17" diff --git a/noir/noir-repo/Cargo.toml b/noir/noir-repo/Cargo.toml index 5dd453415aa..132ff181e44 100644 --- a/noir/noir-repo/Cargo.toml +++ b/noir/noir-repo/Cargo.toml @@ -45,7 +45,7 @@ version = "0.27.0" # x-release-please-end authors = ["The Noir Team "] edition = "2021" -rust-version = "1.73.0" +rust-version = "1.74.1" license = "MIT OR Apache-2.0" repository = "https://github.com/noir-lang/noir/" @@ -104,6 +104,14 @@ chumsky = { git = "https://github.com/jfecher/chumsky", rev = "ad9d312", default "ahash", "std", ] } + +# Benchmarking +criterion = "0.5.0" +# Note that using the "frame-pointer" feature breaks framegraphs on linux +# https://github.com/tikv/pprof-rs/pull/172 +pprof = { version = "0.13", features = ["flamegraph","criterion"] } + + dirs = "4" serde = { version = "1.0.136", features = ["derive"] } serde_json = "1.0" @@ -124,6 +132,7 @@ tempfile = "3.6.0" jsonrpc = { version = "0.16.0", features = ["minreq_http"] } flate2 = "1.0.24" +im = { version = "15.1", features = ["serde"] } tracing = "0.1.40" tracing-web = "0.1.3" tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } diff --git a/noir/noir-repo/README.md b/noir/noir-repo/README.md index adf68b290ef..eea2280c50c 100644 --- a/noir/noir-repo/README.md +++ b/noir/noir-repo/README.md @@ -1,3 +1,13 @@ +
+ + The Noir Programming Language + + +[Website][Noir] | [Getting started] | [Documentation] | [Contributing] +
+ + + # The Noir Programming Language Noir is a Domain Specific Language for SNARK proving systems. It has been designed to use any ACIR compatible proving system. @@ -6,58 +16,35 @@ Noir is a Domain Specific Language for SNARK proving systems. It has been design ## Quick Start -Read the installation section [here](https://noir-lang.org/docs/dev/getting_started/installation/). +Read the [installation section][Getting started] from the [Noir docs][Documentation]. Once you have read through the documentation, you can visit [Awesome Noir](https://github.com/noir-lang/awesome-noir) to run some of the examples that others have created. -## Current Features - -Backends: +## Getting Help -- Barretenberg via FFI -- Marlin via arkworks (Note -- latest interfaces may not be updated to support Marlin backend. Please open an issue if this is relevant to your project and requires attention.) +Join the Noir [forum][Forum] or [Discord][Discord] -Compiler: +## Contributing -- Module System -- For expressions -- Arrays -- Bit Operations -- Binary operations (<, <=, >, >=, +, -, \*, /, %) [See documentation for an extensive list] -- Unsigned integers -- If statements -- Structures and Tuples -- Generics - -ACIR Supported OPCODES: - -- Sha256 -- Blake2s -- Schnorr signature verification -- Pedersen -- HashToField +See [CONTRIBUTING.md][CONTRIBUTING]. ## Future Work The current focus is to gather as much feedback as possible while in the alpha phase. The main focuses of Noir are _safety_ and _developer experience_. If you find a feature that does not seem to be in line with these goals, please open an issue! -Concretely the following items are on the road map: - -- General code sanitization and documentation (ongoing effort) -- Prover and Verifier Key logic. (Prover and Verifier pre-process per compile) -- Fallback mechanism for backend unsupported opcodes -- Visibility modifiers -- Signed integers -- Backend integration: (Bulletproofs) -- Recursion -- Big integers - ## Minimum Rust version -This crate's minimum supported rustc version is 1.73.0. +This workspace's minimum supported rustc version is 1.74.1. ## License Noir is free and open source. It is distributed under a dual license. (MIT/APACHE) -Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this repository by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. + +[Noir]: https://www.noir-lang.org/ +[Getting Started]: https://noir-lang.org/docs/getting_started/installation/ +[Forum]: https://forum.aztec.network/c/noir +[Discord]: https://discord.gg/JtqzkdeQ6G +[Documentation]: https://noir-lang.org/docs +[Contributing]: CONTRIBUTING.md \ No newline at end of file diff --git a/noir/noir-repo/acvm-repo/acir/Cargo.toml b/noir/noir-repo/acvm-repo/acir/Cargo.toml index 4fae9ea20ff..d6990f83281 100644 --- a/noir/noir-repo/acvm-repo/acir/Cargo.toml +++ b/noir/noir-repo/acvm-repo/acir/Cargo.toml @@ -29,8 +29,14 @@ strum_macros = "0.24" serde-reflection = "0.3.6" serde-generate = "0.25.1" fxhash.workspace = true +criterion.workspace = true +pprof.workspace = true [features] default = ["bn254"] bn254 = ["acir_field/bn254", "brillig/bn254"] bls12_381 = ["acir_field/bls12_381", "brillig/bls12_381"] + +[[bench]] +name = "serialization" +harness = false diff --git a/noir/noir-repo/acvm-repo/acir/benches/serialization.rs b/noir/noir-repo/acvm-repo/acir/benches/serialization.rs new file mode 100644 index 00000000000..73e3916a73b --- /dev/null +++ b/noir/noir-repo/acvm-repo/acir/benches/serialization.rs @@ -0,0 +1,123 @@ +use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Throughput}; +use std::{collections::BTreeSet, time::Duration}; + +use acir::{ + circuit::{Circuit, ExpressionWidth, Opcode, Program, PublicInputs}, + native_types::{Expression, Witness}, + FieldElement, +}; + +use pprof::criterion::{Output, PProfProfiler}; + +const SIZES: [usize; 9] = [10, 50, 100, 500, 1000, 5000, 10000, 50000, 100000]; + +fn sample_program(num_opcodes: usize) -> Program { + let assert_zero_opcodes: Vec = (0..num_opcodes) + .map(|i| { + Opcode::AssertZero(Expression { + mul_terms: vec![( + FieldElement::from(2 * i), + Witness(i as u32), + Witness(i as u32 + 10), + )], + linear_combinations: vec![ + (FieldElement::from(2 * i), Witness(i as u32)), + (FieldElement::from(3 * i), Witness(i as u32 + 1)), + ], + q_c: FieldElement::from(i), + }) + }) + .collect(); + + Program { + functions: vec![Circuit { + current_witness_index: 4000, + opcodes: assert_zero_opcodes.to_vec(), + expression_width: ExpressionWidth::Bounded { width: 3 }, + private_parameters: BTreeSet::from([Witness(1), Witness(2), Witness(3), Witness(4)]), + public_parameters: PublicInputs(BTreeSet::from([Witness(5)])), + return_values: PublicInputs(BTreeSet::from([Witness(6)])), + assert_messages: Vec::new(), + recursive: false, + }], + } +} + +fn bench_serialization(c: &mut Criterion) { + let mut group = c.benchmark_group("serialize_program"); + for size in SIZES.iter() { + let program = sample_program(*size); + + group.throughput(Throughput::Elements(*size as u64)); + group.bench_with_input(BenchmarkId::from_parameter(size), &program, |b, program| { + b.iter(|| Program::serialize_program(program)); + }); + } + group.finish(); + + let mut group = c.benchmark_group("serialize_program_json"); + for size in SIZES.iter() { + let program = sample_program(*size); + + group.throughput(Throughput::Elements(*size as u64)); + group.bench_with_input(BenchmarkId::from_parameter(size), &program, |b, program| { + b.iter(|| { + let mut bytes = Vec::new(); + let mut serializer = serde_json::Serializer::new(&mut bytes); + Program::serialize_program_base64(program, &mut serializer) + }); + }); + } + group.finish(); +} + +fn bench_deserialization(c: &mut Criterion) { + let mut group = c.benchmark_group("deserialize_program"); + for size in SIZES.iter() { + let program = sample_program(*size); + let serialized_program = Program::serialize_program(&program); + + group.throughput(Throughput::Elements(*size as u64)); + group.bench_with_input( + BenchmarkId::from_parameter(size), + &serialized_program, + |b, program| { + b.iter(|| Program::deserialize_program(program)); + }, + ); + } + group.finish(); + + let mut group = c.benchmark_group("deserialize_program_json"); + for size in SIZES.iter() { + let program = sample_program(*size); + + let serialized_program = { + let mut bytes = Vec::new(); + let mut serializer = serde_json::Serializer::new(&mut bytes); + Program::serialize_program_base64(&program, &mut serializer).expect("should succeed"); + bytes + }; + + group.throughput(Throughput::Elements(*size as u64)); + group.bench_with_input( + BenchmarkId::from_parameter(size), + &serialized_program, + |b, program| { + b.iter(|| { + let mut deserializer = serde_json::Deserializer::from_slice(program); + Program::deserialize_program_base64(&mut deserializer) + }); + }, + ); + } + group.finish(); +} + +criterion_group!( + name = benches; + config = Criterion::default().sample_size(40).measurement_time(Duration::from_secs(20)).with_profiler(PProfProfiler::new(100, Output::Flamegraph(None))); + targets = bench_serialization, bench_deserialization +); + +criterion_main!(benches); diff --git a/noir/noir-repo/acvm-repo/acvm_js/build.sh b/noir/noir-repo/acvm-repo/acvm_js/build.sh index 58724dee02c..7ba69389a9b 100755 --- a/noir/noir-repo/acvm-repo/acvm_js/build.sh +++ b/noir/noir-repo/acvm-repo/acvm_js/build.sh @@ -48,5 +48,3 @@ BROWSER_WASM=${BROWSER_DIR}/${pname}_bg.wasm run_or_fail cargo build --lib --release --target $TARGET --package ${pname} run_or_fail wasm-bindgen $WASM_BINARY --out-dir $NODE_DIR --typescript --target nodejs run_or_fail wasm-bindgen $WASM_BINARY --out-dir $BROWSER_DIR --typescript --target web -run_if_available wasm-opt $NODE_WASM -o $NODE_WASM -O -run_if_available wasm-opt $BROWSER_WASM -o $BROWSER_WASM -O diff --git a/noir/noir-repo/acvm-repo/acvm_js/test/browser/black_box_solvers.test.ts b/noir/noir-repo/acvm-repo/acvm_js/test/browser/black_box_solvers.test.ts index 3c54fe8e38f..695f6b89afc 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/test/browser/black_box_solvers.test.ts +++ b/noir/noir-repo/acvm-repo/acvm_js/test/browser/black_box_solvers.test.ts @@ -4,7 +4,6 @@ import initACVM, { blake2s256, ecdsa_secp256k1_verify, ecdsa_secp256r1_verify, - initLogLevel, keccak256, sha256, xor, @@ -12,8 +11,6 @@ import initACVM, { beforeEach(async () => { await initACVM(); - - initLogLevel('INFO'); }); it('successfully calculates the bitwise AND of two fields', async () => { diff --git a/noir/noir-repo/aztec_macros/src/transforms/compute_note_hash_and_nullifier.rs b/noir/noir-repo/aztec_macros/src/transforms/compute_note_hash_and_nullifier.rs index c8e7e807d87..f624cde9969 100644 --- a/noir/noir-repo/aztec_macros/src/transforms/compute_note_hash_and_nullifier.rs +++ b/noir/noir-repo/aztec_macros/src/transforms/compute_note_hash_and_nullifier.rs @@ -1,8 +1,9 @@ use noirc_errors::{Location, Span}; +use noirc_frontend::ast::{FunctionReturnType, NoirFunction, UnresolvedTypeData}; use noirc_frontend::{ graph::CrateId, macros_api::{FileId, HirContext}, - parse_program, FunctionReturnType, NoirFunction, Type, UnresolvedTypeData, + parse_program, Type, }; use crate::utils::{ diff --git a/noir/noir-repo/aztec_macros/src/transforms/contract_interface.rs b/noir/noir-repo/aztec_macros/src/transforms/contract_interface.rs index 4401c867df9..5f68ce98c8a 100644 --- a/noir/noir-repo/aztec_macros/src/transforms/contract_interface.rs +++ b/noir/noir-repo/aztec_macros/src/transforms/contract_interface.rs @@ -1,9 +1,10 @@ +use noirc_frontend::ast::{NoirFunction, UnresolvedTypeData}; use noirc_frontend::{ graph::CrateId, macros_api::{FileId, HirContext, HirExpression, HirLiteral, HirStatement}, parse_program, parser::SortedModule, - NoirFunction, Type, UnresolvedTypeData, + Type, }; use crate::utils::{ @@ -52,7 +53,7 @@ pub fn stub_function(aztec_visibility: &str, func: &NoirFunction) -> String { }) .collect::>() .join(", "); - let fn_return_type: noirc_frontend::UnresolvedType = func.return_type(); + let fn_return_type: noirc_frontend::ast::UnresolvedType = func.return_type(); let fn_selector = format!("dep::aztec::protocol_types::abis::function_selector::FunctionSelector::from_signature(\"{}\")", SELECTOR_PLACEHOLDER); diff --git a/noir/noir-repo/aztec_macros/src/transforms/events.rs b/noir/noir-repo/aztec_macros/src/transforms/events.rs index b77a5821b81..9c8cd826360 100644 --- a/noir/noir-repo/aztec_macros/src/transforms/events.rs +++ b/noir/noir-repo/aztec_macros/src/transforms/events.rs @@ -1,5 +1,9 @@ use iter_extended::vecmap; use noirc_errors::Span; +use noirc_frontend::ast::{ + ExpressionKind, FunctionDefinition, FunctionReturnType, ItemVisibility, Literal, NoirFunction, + Visibility, +}; use noirc_frontend::{ graph::CrateId, macros_api::{ @@ -8,8 +12,6 @@ use noirc_frontend::{ UnresolvedTypeData, }, token::SecondaryAttribute, - ExpressionKind, FunctionDefinition, FunctionReturnType, ItemVisibility, Literal, NoirFunction, - Visibility, }; use crate::{ diff --git a/noir/noir-repo/aztec_macros/src/transforms/functions.rs b/noir/noir-repo/aztec_macros/src/transforms/functions.rs index 8e90d40aaec..24cad05b866 100644 --- a/noir/noir-repo/aztec_macros/src/transforms/functions.rs +++ b/noir/noir-repo/aztec_macros/src/transforms/functions.rs @@ -1,12 +1,15 @@ use convert_case::{Case, Casing}; use noirc_errors::Span; -use noirc_frontend::{ - macros_api::FieldElement, parse_program, BlockExpression, ConstrainKind, ConstrainStatement, - Distinctness, Expression, ExpressionKind, ForLoopStatement, ForRange, FunctionReturnType, - Ident, Literal, NoirFunction, NoirStruct, Param, PathKind, Pattern, Signedness, Statement, - StatementKind, UnresolvedType, UnresolvedTypeData, Visibility, +use noirc_frontend::ast; +use noirc_frontend::ast::{ + BlockExpression, ConstrainKind, ConstrainStatement, Distinctness, Expression, ExpressionKind, + ForLoopStatement, ForRange, FunctionReturnType, Ident, Literal, NoirFunction, NoirStruct, + Param, PathKind, Pattern, Signedness, Statement, StatementKind, UnresolvedType, + UnresolvedTypeData, Visibility, }; +use noirc_frontend::{macros_api::FieldElement, parse_program}; + use crate::{ chained_dep, chained_path, utils::{ @@ -337,7 +340,7 @@ fn serialize_to_hasher( &UnresolvedType { typ: UnresolvedTypeData::Integer( Signedness::Unsigned, - noirc_frontend::IntegerBitSize::ThirtyTwo, + ast::IntegerBitSize::ThirtyTwo, ), span: None, }, diff --git a/noir/noir-repo/aztec_macros/src/transforms/note_interface.rs b/noir/noir-repo/aztec_macros/src/transforms/note_interface.rs index 4b72759a5db..70db1ebd336 100644 --- a/noir/noir-repo/aztec_macros/src/transforms/note_interface.rs +++ b/noir/noir-repo/aztec_macros/src/transforms/note_interface.rs @@ -1,12 +1,16 @@ use noirc_errors::Span; +use noirc_frontend::ast::{ + ItemVisibility, LetStatement, NoirFunction, NoirStruct, PathKind, TraitImplItem, TypeImpl, + UnresolvedTypeData, UnresolvedTypeExpression, +}; use noirc_frontend::{ graph::CrateId, macros_api::{FileId, HirContext, HirExpression, HirLiteral, HirStatement}, parse_program, parser::SortedModule, - ItemVisibility, LetStatement, NoirFunction, NoirStruct, PathKind, TraitImplItem, Type, - TypeImpl, UnresolvedTypeData, UnresolvedTypeExpression, + Type, }; + use regex::Regex; use crate::{ diff --git a/noir/noir-repo/aztec_macros/src/transforms/storage.rs b/noir/noir-repo/aztec_macros/src/transforms/storage.rs index 66057108517..1e3cc011715 100644 --- a/noir/noir-repo/aztec_macros/src/transforms/storage.rs +++ b/noir/noir-repo/aztec_macros/src/transforms/storage.rs @@ -1,4 +1,8 @@ use noirc_errors::Span; +use noirc_frontend::ast::{ + BlockExpression, Expression, ExpressionKind, FunctionDefinition, Ident, Literal, NoirFunction, + NoirStruct, PathKind, Pattern, StatementKind, TypeImpl, UnresolvedType, UnresolvedTypeData, +}; use noirc_frontend::{ graph::CrateId, macros_api::{ @@ -8,9 +12,7 @@ use noirc_frontend::{ parse_program, parser::SortedModule, token::SecondaryAttribute, - BlockExpression, Expression, ExpressionKind, FunctionDefinition, Ident, Literal, NoirFunction, - NoirStruct, PathKind, Pattern, StatementKind, Type, TypeImpl, UnresolvedType, - UnresolvedTypeData, + Type, }; use crate::{ diff --git a/noir/noir-repo/aztec_macros/src/utils/ast_utils.rs b/noir/noir-repo/aztec_macros/src/utils/ast_utils.rs index 1731dfab49c..ebb4854f86e 100644 --- a/noir/noir-repo/aztec_macros/src/utils/ast_utils.rs +++ b/noir/noir-repo/aztec_macros/src/utils/ast_utils.rs @@ -1,10 +1,11 @@ use noirc_errors::{Span, Spanned}; -use noirc_frontend::{ - token::SecondaryAttribute, BinaryOpKind, CallExpression, CastExpression, Expression, - ExpressionKind, FunctionReturnType, Ident, IndexExpression, InfixExpression, Lambda, - LetStatement, MethodCallExpression, NoirTraitImpl, Path, Pattern, PrefixExpression, Statement, - StatementKind, TraitImplItem, UnaryOp, UnresolvedType, UnresolvedTypeData, +use noirc_frontend::ast::{ + BinaryOpKind, CallExpression, CastExpression, Expression, ExpressionKind, FunctionReturnType, + Ident, IndexExpression, InfixExpression, Lambda, LetStatement, MethodCallExpression, + NoirTraitImpl, Path, Pattern, PrefixExpression, Statement, StatementKind, TraitImplItem, + UnaryOp, UnresolvedType, UnresolvedTypeData, }; +use noirc_frontend::token::SecondaryAttribute; // // Helper macros for creating noir ast nodes @@ -66,6 +67,7 @@ pub fn mutable_assignment(name: &str, assigned_to: Expression) -> Statement { pattern: mutable(name), r#type: make_type(UnresolvedTypeData::Unspecified), expression: assigned_to, + comptime: false, attributes: vec![], })) } @@ -90,6 +92,7 @@ pub fn assignment_with_type( pattern: pattern(name), r#type: make_type(typ), expression: assigned_to, + comptime: false, attributes: vec![], })) } diff --git a/noir/noir-repo/aztec_macros/src/utils/errors.rs b/noir/noir-repo/aztec_macros/src/utils/errors.rs index 4c5411dfe0f..db86012a007 100644 --- a/noir/noir-repo/aztec_macros/src/utils/errors.rs +++ b/noir/noir-repo/aztec_macros/src/utils/errors.rs @@ -1,5 +1,6 @@ use noirc_errors::Span; -use noirc_frontend::{macros_api::MacroError, UnresolvedTypeData}; +use noirc_frontend::ast; +use noirc_frontend::macros_api::MacroError; use super::constants::MAX_CONTRACT_PRIVATE_FUNCTIONS; @@ -7,9 +8,9 @@ use super::constants::MAX_CONTRACT_PRIVATE_FUNCTIONS; pub enum AztecMacroError { AztecDepNotFound, ContractHasTooManyPrivateFunctions { span: Span }, - UnsupportedFunctionArgumentType { span: Span, typ: UnresolvedTypeData }, - UnsupportedFunctionReturnType { span: Span, typ: UnresolvedTypeData }, - UnsupportedStorageType { span: Option, typ: UnresolvedTypeData }, + UnsupportedFunctionArgumentType { span: Span, typ: ast::UnresolvedTypeData }, + UnsupportedFunctionReturnType { span: Span, typ: ast::UnresolvedTypeData }, + UnsupportedStorageType { span: Option, typ: ast::UnresolvedTypeData }, CouldNotAssignStorageSlots { secondary_message: Option }, CouldNotImplementComputeNoteHashAndNullifier { secondary_message: Option }, CouldNotImplementNoteInterface { span: Option, secondary_message: Option }, diff --git a/noir/noir-repo/aztec_macros/src/utils/hir_utils.rs b/noir/noir-repo/aztec_macros/src/utils/hir_utils.rs index 3b2f14fd87e..874640c01c8 100644 --- a/noir/noir-repo/aztec_macros/src/utils/hir_utils.rs +++ b/noir/noir-repo/aztec_macros/src/utils/hir_utils.rs @@ -1,5 +1,6 @@ use iter_extended::vecmap; use noirc_errors::Location; +use noirc_frontend::ast; use noirc_frontend::{ graph::CrateId, hir::{ @@ -12,7 +13,7 @@ use noirc_frontend::{ StructId, }, node_interner::{FuncId, TraitId, TraitImplKind}, - ItemVisibility, LetStatement, NoirFunction, Shared, Signedness, StructType, Type, + Shared, StructType, Type, }; use super::ast_utils::is_custom_attribute; @@ -68,8 +69,8 @@ pub fn collect_traits(context: &HirContext) -> Vec { /// Computes the aztec signature for a resolved type. pub fn signature_of_type(typ: &Type) -> String { match typ { - Type::Integer(Signedness::Signed, bit_size) => format!("i{}", bit_size), - Type::Integer(Signedness::Unsigned, bit_size) => format!("u{}", bit_size), + Type::Integer(ast::Signedness::Signed, bit_size) => format!("i{}", bit_size), + Type::Integer(ast::Signedness::Unsigned, bit_size) => format!("u{}", bit_size), Type::FieldElement => "Field".to_owned(), Type::Bool => "bool".to_owned(), Type::Array(len, typ) => { @@ -168,7 +169,7 @@ pub fn get_contract_module_data( pub fn inject_fn( crate_id: &CrateId, context: &mut HirContext, - func: NoirFunction, + func: ast::NoirFunction, location: Location, module_id: LocalModuleId, file_id: FileId, @@ -182,7 +183,7 @@ pub fn inject_fn( ); context.def_map_mut(crate_id).unwrap().modules_mut()[module_id.0] - .declare_function(func.name_ident().clone(), ItemVisibility::Public, func_id) + .declare_function(func.name_ident().clone(), ast::ItemVisibility::Public, func_id) .map_err(|err| MacroError { primary_message: format!("Failed to declare autogenerated {} function", func.name()), secondary_message: Some(format!("Duplicate definition found {}", err.0)), @@ -217,7 +218,7 @@ pub fn inject_fn( pub fn inject_global( crate_id: &CrateId, context: &mut HirContext, - global: LetStatement, + global: ast::LetStatement, module_id: LocalModuleId, file_id: FileId, ) { diff --git a/noir/noir-repo/compiler/fm/Cargo.toml b/noir/noir-repo/compiler/fm/Cargo.toml index 42e4b0c25d7..f556f305c78 100644 --- a/noir/noir-repo/compiler/fm/Cargo.toml +++ b/noir/noir-repo/compiler/fm/Cargo.toml @@ -3,6 +3,7 @@ name = "fm" version.workspace = true authors.workspace = true edition.workspace = true +rust-version.workspace = true license.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/noir/noir-repo/compiler/noirc_driver/Cargo.toml b/noir/noir-repo/compiler/noirc_driver/Cargo.toml index a7fe0b4b610..495410b7b06 100644 --- a/noir/noir-repo/compiler/noirc_driver/Cargo.toml +++ b/noir/noir-repo/compiler/noirc_driver/Cargo.toml @@ -3,6 +3,7 @@ name = "noirc_driver" version.workspace = true authors.workspace = true edition.workspace = true +rust-version.workspace = true license.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/noir/noir-repo/compiler/noirc_driver/src/abi_gen.rs b/noir/noir-repo/compiler/noirc_driver/src/abi_gen.rs index 86f10818dbc..51fe4986845 100644 --- a/noir/noir-repo/compiler/noirc_driver/src/abi_gen.rs +++ b/noir/noir-repo/compiler/noirc_driver/src/abi_gen.rs @@ -3,12 +3,12 @@ use std::collections::BTreeMap; use acvm::acir::native_types::Witness; use iter_extended::{btree_map, vecmap}; use noirc_abi::{Abi, AbiParameter, AbiReturnType, AbiType, AbiValue}; +use noirc_frontend::ast::Visibility; use noirc_frontend::{ hir::Context, hir_def::{expr::HirArrayLiteral, function::Param, stmt::HirPattern}, macros_api::{HirExpression, HirLiteral}, node_interner::{FuncId, NodeInterner}, - Visibility, }; use std::ops::Range; diff --git a/noir/noir-repo/compiler/noirc_errors/Cargo.toml b/noir/noir-repo/compiler/noirc_errors/Cargo.toml index da18399971e..c9cb7e2709f 100644 --- a/noir/noir-repo/compiler/noirc_errors/Cargo.toml +++ b/noir/noir-repo/compiler/noirc_errors/Cargo.toml @@ -3,6 +3,7 @@ name = "noirc_errors" version.workspace = true authors.workspace = true edition.workspace = true +rust-version.workspace = true license.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/noir/noir-repo/compiler/noirc_evaluator/Cargo.toml b/noir/noir-repo/compiler/noirc_evaluator/Cargo.toml index fad7c3c309e..aa30eef9156 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/Cargo.toml +++ b/noir/noir-repo/compiler/noirc_evaluator/Cargo.toml @@ -3,6 +3,7 @@ name = "noirc_evaluator" version.workspace = true authors.workspace = true edition.workspace = true +rust-version.workspace = true license.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -15,7 +16,7 @@ fxhash.workspace = true iter-extended.workspace = true thiserror.workspace = true num-bigint = "0.4" -im = { version = "15.1", features = ["serde"] } +im.workspace = true serde.workspace = true tracing.workspace = true -chrono = "0.4.37" \ No newline at end of file +chrono = "0.4.37" diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs index 760340f1a88..3482a8c25c7 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs @@ -22,9 +22,8 @@ use acvm::acir::{ use noirc_errors::debug_info::{DebugFunctions, DebugInfo, DebugTypes, DebugVariables}; -use noirc_frontend::{ - hir_def::function::FunctionSignature, monomorphization::ast::Program, Visibility, -}; +use noirc_frontend::ast::Visibility; +use noirc_frontend::{hir_def::function::FunctionSignature, monomorphization::ast::Program}; use tracing::{span, Level}; use self::{acir_gen::GeneratedAcir, ssa_gen::Ssa}; diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs index 02b381d79fc..8b16ad51ca1 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs @@ -39,7 +39,7 @@ use acvm::{ use fxhash::FxHashMap as HashMap; use im::Vector; use iter_extended::{try_vecmap, vecmap}; -use noirc_frontend::Distinctness; +use noirc_frontend::ast::Distinctness; #[derive(Default)] struct SharedContext { @@ -2595,7 +2595,7 @@ mod test { let ssa = builder.finish(); let (acir_functions, _) = ssa - .into_acir(&Brillig::default(), noirc_frontend::Distinctness::Distinct) + .into_acir(&Brillig::default(), noirc_frontend::ast::Distinctness::Distinct) .expect("Should compile manually written SSA into ACIR"); // Expected result: // main f0 @@ -2691,7 +2691,7 @@ mod test { let ssa = builder.finish(); let (acir_functions, _) = ssa - .into_acir(&Brillig::default(), noirc_frontend::Distinctness::Distinct) + .into_acir(&Brillig::default(), noirc_frontend::ast::Distinctness::Distinct) .expect("Should compile manually written SSA into ACIR"); // The expected result should look very similar to the abvoe test expect that the input witnesses of the `Call` // opcodes will be different. The changes can discerned from the checks below. @@ -2782,7 +2782,7 @@ mod test { let ssa = builder.finish(); let (acir_functions, _) = ssa - .into_acir(&Brillig::default(), noirc_frontend::Distinctness::Distinct) + .into_acir(&Brillig::default(), noirc_frontend::ast::Distinctness::Distinct) .expect("Should compile manually written SSA into ACIR"); assert_eq!(acir_functions.len(), 3, "Should have three ACIR functions"); @@ -2894,7 +2894,7 @@ mod test { println!("{}", ssa); let (acir_functions, brillig_functions) = ssa - .into_acir(&brillig, noirc_frontend::Distinctness::Distinct) + .into_acir(&brillig, noirc_frontend::ast::Distinctness::Distinct) .expect("Should compile manually written SSA into ACIR"); assert_eq!(acir_functions.len(), 1, "Should only have a `main` ACIR function"); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/function_builder/data_bus.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/function_builder/data_bus.rs index e785212f8d2..5f0660f5a79 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/function_builder/data_bus.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/function_builder/data_bus.rs @@ -3,6 +3,7 @@ use std::rc::Rc; use crate::ssa::ir::{types::Type, value::ValueId}; use acvm::FieldElement; use fxhash::FxHashMap as HashMap; +use noirc_frontend::ast; use noirc_frontend::hir_def::function::FunctionSignature; use super::FunctionBuilder; @@ -33,8 +34,8 @@ impl DataBusBuilder { for param in &main_signature.0 { let is_databus = match param.2 { - noirc_frontend::Visibility::Public | noirc_frontend::Visibility::Private => false, - noirc_frontend::Visibility::DataBus => true, + ast::Visibility::Public | ast::Visibility::Private => false, + ast::Visibility::DataBus => true, }; let len = param.1.field_count() as usize; params_is_databus.extend(vec![is_databus; len]); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs index 569e543ce40..e591a3d478c 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs @@ -4,9 +4,9 @@ use std::sync::{Mutex, RwLock}; use acvm::FieldElement; use iter_extended::vecmap; use noirc_errors::Location; +use noirc_frontend::ast::{BinaryOpKind, Signedness}; use noirc_frontend::monomorphization::ast::{self, LocalId, Parameters}; use noirc_frontend::monomorphization::ast::{FuncId, Program}; -use noirc_frontend::{BinaryOpKind, Signedness}; use crate::errors::RuntimeError; use crate::ssa::function_builder::FunctionBuilder; @@ -562,7 +562,7 @@ impl<'a> FunctionContext<'a> { pub(super) fn insert_binary( &mut self, mut lhs: ValueId, - operator: noirc_frontend::BinaryOpKind, + operator: BinaryOpKind, mut rhs: ValueId, location: Location, ) -> Values { @@ -625,7 +625,7 @@ impl<'a> FunctionContext<'a> { fn insert_array_equality( &mut self, lhs: ValueId, - operator: noirc_frontend::BinaryOpKind, + operator: BinaryOpKind, rhs: ValueId, location: Location, ) -> Values { @@ -1090,23 +1090,23 @@ impl<'a> FunctionContext<'a> { /// True if the given operator cannot be encoded directly and needs /// to be represented as !(some other operator) -fn operator_requires_not(op: noirc_frontend::BinaryOpKind) -> bool { - use noirc_frontend::BinaryOpKind::*; +fn operator_requires_not(op: BinaryOpKind) -> bool { + use BinaryOpKind::*; matches!(op, NotEqual | LessEqual | GreaterEqual) } /// True if the given operator cannot be encoded directly and needs /// to have its lhs and rhs swapped to be represented with another operator. /// Example: (a > b) needs to be represented as (b < a) -fn operator_requires_swapped_operands(op: noirc_frontend::BinaryOpKind) -> bool { - use noirc_frontend::BinaryOpKind::*; +fn operator_requires_swapped_operands(op: BinaryOpKind) -> bool { + use BinaryOpKind::*; matches!(op, Greater | LessEqual) } /// If the operation requires its result to be truncated because it is an integer, the maximum /// number of bits that result may occupy is returned. fn operator_result_max_bit_size_to_truncate( - op: noirc_frontend::BinaryOpKind, + op: BinaryOpKind, lhs: ValueId, rhs: ValueId, dfg: &DataFlowGraph, @@ -1123,7 +1123,7 @@ fn operator_result_max_bit_size_to_truncate( let lhs_bit_size = get_bit_size(lhs_type)?; let rhs_bit_size = get_bit_size(rhs_type)?; - use noirc_frontend::BinaryOpKind::*; + use BinaryOpKind::*; match op { Add => Some(std::cmp::max(lhs_bit_size, rhs_bit_size) + 1), Subtract => Some(std::cmp::max(lhs_bit_size, rhs_bit_size) + 1), @@ -1173,7 +1173,7 @@ fn operator_result_max_bit_size_to_truncate( /// Take care when using this to insert a binary instruction: this requires /// checking operator_requires_not and operator_requires_swapped_operands /// to represent the full operation correctly. -fn convert_operator(op: noirc_frontend::BinaryOpKind) -> BinaryOp { +fn convert_operator(op: BinaryOpKind) -> BinaryOp { match op { BinaryOpKind::Add => BinaryOp::Add, BinaryOpKind::Subtract => BinaryOp::Sub, diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs index 2a4b5276547..79f7cda4ae2 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs @@ -7,10 +7,8 @@ pub(crate) use program::Ssa; use context::SharedContext; use iter_extended::{try_vecmap, vecmap}; use noirc_errors::Location; -use noirc_frontend::{ - monomorphization::ast::{self, Expression, Program}, - Visibility, -}; +use noirc_frontend::ast::{UnaryOp, Visibility}; +use noirc_frontend::monomorphization::ast::{self, Expression, Program}; use crate::{ errors::{InternalError, RuntimeError}, @@ -306,24 +304,24 @@ impl<'a> FunctionContext<'a> { fn codegen_unary(&mut self, unary: &ast::Unary) -> Result { match unary.operator { - noirc_frontend::UnaryOp::Not => { + UnaryOp::Not => { let rhs = self.codegen_expression(&unary.rhs)?; let rhs = rhs.into_leaf().eval(self); Ok(self.builder.insert_not(rhs).into()) } - noirc_frontend::UnaryOp::Minus => { + UnaryOp::Minus => { let rhs = self.codegen_expression(&unary.rhs)?; let rhs = rhs.into_leaf().eval(self); let typ = self.builder.type_of_value(rhs); let zero = self.builder.numeric_constant(0u128, typ); Ok(self.insert_binary( zero, - noirc_frontend::BinaryOpKind::Subtract, + noirc_frontend::ast::BinaryOpKind::Subtract, rhs, unary.location, )) } - noirc_frontend::UnaryOp::MutableReference => { + UnaryOp::MutableReference => { Ok(self.codegen_reference(&unary.rhs)?.map(|rhs| { match rhs { value::Value::Normal(value) => { @@ -338,7 +336,7 @@ impl<'a> FunctionContext<'a> { } })) } - noirc_frontend::UnaryOp::Dereference { .. } => { + UnaryOp::Dereference { .. } => { let rhs = self.codegen_expression(&unary.rhs)?; Ok(self.dereference(&rhs, &unary.result_type)) } diff --git a/noir/noir-repo/compiler/noirc_frontend/Cargo.toml b/noir/noir-repo/compiler/noirc_frontend/Cargo.toml index e39ab2fe106..84c9393fa37 100644 --- a/noir/noir-repo/compiler/noirc_frontend/Cargo.toml +++ b/noir/noir-repo/compiler/noirc_frontend/Cargo.toml @@ -3,6 +3,7 @@ name = "noirc_frontend" version.workspace = true authors.workspace = true edition.workspace = true +rust-version.workspace = true license.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -17,6 +18,7 @@ iter-extended.workspace = true chumsky.workspace = true thiserror.workspace = true smol_str.workspace = true +im.workspace = true serde_json.workspace = true serde.workspace = true rustc-hash = "1.1.0" diff --git a/noir/noir-repo/compiler/noirc_frontend/src/ast/expression.rs b/noir/noir-repo/compiler/noirc_frontend/src/ast/expression.rs index 0e5919bf7db..92c1add80a6 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/ast/expression.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/ast/expression.rs @@ -1,11 +1,11 @@ use std::borrow::Cow; use std::fmt::Display; -use crate::token::{Attributes, Token}; -use crate::{ +use crate::ast::{ Distinctness, Ident, ItemVisibility, Path, Pattern, Recoverable, Statement, StatementKind, UnresolvedTraitConstraint, UnresolvedType, UnresolvedTypeData, Visibility, }; +use crate::token::{Attributes, Token}; use acvm::FieldElement; use iter_extended::vecmap; use noirc_errors::{Span, Spanned}; @@ -387,6 +387,9 @@ pub struct FunctionDefinition { /// True if this function was defined with the 'unconstrained' keyword pub is_unconstrained: bool, + /// True if this function was defined with the 'comptime' keyword + pub is_comptime: bool, + /// Indicate if this function was defined with the 'pub' keyword pub visibility: ItemVisibility, @@ -679,10 +682,12 @@ impl FunctionDefinition { span: ident.span().merge(unresolved_type.span.unwrap()), }) .collect(); + FunctionDefinition { name: name.clone(), attributes: Attributes::empty(), is_unconstrained: false, + is_comptime: false, visibility: ItemVisibility::Private, generics: generics.clone(), parameters: p, diff --git a/noir/noir-repo/compiler/noirc_frontend/src/ast/function.rs b/noir/noir-repo/compiler/noirc_frontend/src/ast/function.rs index 10d962a23f7..9816218c5f7 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/ast/function.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/ast/function.rs @@ -3,8 +3,8 @@ use std::fmt::Display; use noirc_errors::Span; use crate::{ + ast::{FunctionReturnType, Ident, Param, Visibility}, token::{Attributes, FunctionAttribute, SecondaryAttribute}, - FunctionReturnType, Ident, Param, Visibility, }; use super::{FunctionDefinition, UnresolvedType, UnresolvedTypeData}; diff --git a/noir/noir-repo/compiler/noirc_frontend/src/ast/statement.rs b/noir/noir-repo/compiler/noirc_frontend/src/ast/statement.rs index 753b5a31d32..1831a046f5b 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/ast/statement.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/ast/statement.rs @@ -1,17 +1,18 @@ use std::fmt::Display; use std::sync::atomic::{AtomicU32, Ordering}; +use acvm::FieldElement; +use iter_extended::vecmap; +use noirc_errors::{Span, Spanned}; + +use super::{ + BlockExpression, Expression, ExpressionKind, IndexExpression, MemberAccessExpression, + MethodCallExpression, UnresolvedType, +}; use crate::lexer::token::SpannedToken; use crate::macros_api::SecondaryAttribute; use crate::parser::{ParserError, ParserErrorReason}; use crate::token::Token; -use crate::{ - BlockExpression, Expression, ExpressionKind, IndexExpression, MemberAccessExpression, - MethodCallExpression, UnresolvedType, -}; -use acvm::FieldElement; -use iter_extended::vecmap; -use noirc_errors::{Span, Spanned}; /// This is used when an identifier fails to parse in the parser. /// Instead of failing the parse, we can often recover using this @@ -38,6 +39,8 @@ pub enum StatementKind { For(ForLoopStatement), Break, Continue, + /// This statement should be executed at compile-time + Comptime(Box), // This is an expression with a trailing semi-colon Semi(Expression), // This statement is the result of a recovered parse error. @@ -47,6 +50,19 @@ pub enum StatementKind { } impl Statement { + pub fn add_semicolon( + mut self, + semi: Option, + span: Span, + last_statement_in_block: bool, + emit_error: &mut dyn FnMut(ParserError), + ) -> Self { + self.kind = self.kind.add_semicolon(semi, span, last_statement_in_block, emit_error); + self + } +} + +impl StatementKind { pub fn add_semicolon( self, semi: Option, @@ -57,7 +73,7 @@ impl Statement { let missing_semicolon = ParserError::with_reason(ParserErrorReason::MissingSeparatingSemi, span); - let kind = match self.kind { + match self { StatementKind::Let(_) | StatementKind::Constrain(_) | StatementKind::Assign(_) @@ -69,10 +85,15 @@ impl Statement { if semi.is_none() { emit_error(missing_semicolon); } - self.kind + self + } + StatementKind::Comptime(mut statement) => { + *statement = + statement.add_semicolon(semi, span, last_statement_in_block, emit_error); + StatementKind::Comptime(statement) } // A semicolon on a for loop is optional and does nothing - StatementKind::For(_) => self.kind, + StatementKind::For(_) => self, StatementKind::Expression(expr) => { match (&expr.kind, semi, last_statement_in_block) { @@ -92,9 +113,7 @@ impl Statement { (_, None, true) => StatementKind::Expression(expr), } } - }; - - Statement { kind, span: self.span } + } } } @@ -108,7 +127,13 @@ impl StatementKind { pub fn new_let( ((pattern, r#type), expression): ((Pattern, UnresolvedType), Expression), ) -> StatementKind { - StatementKind::Let(LetStatement { pattern, r#type, expression, attributes: vec![] }) + StatementKind::Let(LetStatement { + pattern, + r#type, + expression, + comptime: false, + attributes: vec![], + }) } /// Create a Statement::Assign value, desugaring any combined operators like += if needed. @@ -124,7 +149,7 @@ impl StatementKind { let lvalue_expr = lvalue.as_expression(); let error_msg = "Token passed to Statement::assign is not a binary operator"; - let infix = crate::InfixExpression { + let infix = crate::ast::InfixExpression { lhs: lvalue_expr, operator: operator.try_into_binary_op(span).expect(error_msg), rhs: expression, @@ -407,17 +432,9 @@ pub struct LetStatement { pub r#type: UnresolvedType, pub expression: Expression, pub attributes: Vec, -} -impl LetStatement { - pub fn new_let( - (((pattern, r#type), expression), attributes): ( - ((Pattern, UnresolvedType), Expression), - Vec, - ), - ) -> LetStatement { - LetStatement { pattern, r#type, expression, attributes } - } + // True if this should only be run during compile-time + pub comptime: bool, } #[derive(Debug, PartialEq, Eq, Clone)] @@ -505,8 +522,8 @@ impl LValue { })) } LValue::Dereference(lvalue, _span) => { - ExpressionKind::Prefix(Box::new(crate::PrefixExpression { - operator: crate::UnaryOp::Dereference { implicitly_added: false }, + ExpressionKind::Prefix(Box::new(crate::ast::PrefixExpression { + operator: crate::ast::UnaryOp::Dereference { implicitly_added: false }, rhs: lvalue.as_expression(), })) } @@ -573,6 +590,7 @@ impl ForRange { pattern: Pattern::Identifier(array_ident.clone()), r#type: UnresolvedType::unspecified(), expression: array, + comptime: false, attributes: vec![], }), span: array_span, @@ -616,6 +634,7 @@ impl ForRange { pattern: Pattern::Identifier(identifier), r#type: UnresolvedType::unspecified(), expression: Expression::new(loop_element, array_span), + comptime: false, attributes: vec![], }), span: array_span, @@ -666,6 +685,7 @@ impl Display for StatementKind { StatementKind::For(for_loop) => for_loop.fmt(f), StatementKind::Break => write!(f, "break"), StatementKind::Continue => write!(f, "continue"), + StatementKind::Comptime(statement) => write!(f, "comptime {statement}"), StatementKind::Semi(semi) => write!(f, "{semi};"), StatementKind::Error => write!(f, "Error"), } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/ast/structure.rs b/noir/noir-repo/compiler/noirc_frontend/src/ast/structure.rs index 6a32fa717f3..bda6b8c0b11 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/ast/structure.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/ast/structure.rs @@ -1,6 +1,8 @@ use std::fmt::Display; -use crate::{token::SecondaryAttribute, Ident, UnresolvedGenerics, UnresolvedType}; +use crate::ast::{Ident, UnresolvedGenerics, UnresolvedType}; +use crate::token::SecondaryAttribute; + use iter_extended::vecmap; use noirc_errors::Span; diff --git a/noir/noir-repo/compiler/noirc_frontend/src/ast/traits.rs b/noir/noir-repo/compiler/noirc_frontend/src/ast/traits.rs index 775f0a5f2b4..772675723b5 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/ast/traits.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/ast/traits.rs @@ -3,10 +3,11 @@ use std::fmt::Display; use iter_extended::vecmap; use noirc_errors::Span; -use crate::{ - node_interner::TraitId, BlockExpression, Expression, FunctionReturnType, Ident, NoirFunction, - Path, UnresolvedGenerics, UnresolvedType, +use crate::ast::{ + BlockExpression, Expression, FunctionReturnType, Ident, NoirFunction, Path, UnresolvedGenerics, + UnresolvedType, }; +use crate::node_interner::TraitId; /// AST node for trait definitions: /// `trait name { ... items ... }` diff --git a/noir/noir-repo/compiler/noirc_frontend/src/ast/type_alias.rs b/noir/noir-repo/compiler/noirc_frontend/src/ast/type_alias.rs index 76a1e5a7e30..3228765170e 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/ast/type_alias.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/ast/type_alias.rs @@ -1,4 +1,4 @@ -use crate::{Ident, UnresolvedGenerics, UnresolvedType}; +use super::{Ident, UnresolvedGenerics, UnresolvedType}; use iter_extended::vecmap; use noirc_errors::Span; use std::fmt::Display; diff --git a/noir/noir-repo/compiler/noirc_frontend/src/debug/mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/debug/mod.rs index 67b52071d7b..3e7d123398b 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/debug/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/debug/mod.rs @@ -145,6 +145,7 @@ impl DebugInstrumenter { pattern: ast::Pattern::Identifier(ident("__debug_expr", ret_expr.span)), r#type: ast::UnresolvedType::unspecified(), expression: ret_expr.clone(), + comptime: false, attributes: vec![], }), span: ret_expr.span, @@ -243,6 +244,7 @@ impl DebugInstrumenter { kind: ast::StatementKind::Let(ast::LetStatement { pattern: ast::Pattern::Tuple(vars_pattern, let_stmt.pattern.span()), r#type: ast::UnresolvedType::unspecified(), + comptime: false, expression: ast::Expression { kind: ast::ExpressionKind::Block(ast::BlockExpression { statements: block_stmts, @@ -275,6 +277,7 @@ impl DebugInstrumenter { pattern: ast::Pattern::Identifier(ident("__debug_expr", assign_stmt.expression.span)), r#type: ast::UnresolvedType::unspecified(), expression: assign_stmt.expression.clone(), + comptime: false, attributes: vec![], }); let expression_span = assign_stmt.expression.span; diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/hir_to_ast.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/hir_to_ast.rs index 8ffcbce7d62..47ca7083ff0 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/hir_to_ast.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/hir_to_ast.rs @@ -1,18 +1,19 @@ use iter_extended::vecmap; use noirc_errors::{Span, Spanned}; +use crate::ast::{ + ArrayLiteral, AssignStatement, BlockExpression, CallExpression, CastExpression, ConstrainKind, + ConstructorExpression, ExpressionKind, ForLoopStatement, ForRange, Ident, IfExpression, + IndexExpression, InfixExpression, LValue, Lambda, LetStatement, Literal, + MemberAccessExpression, MethodCallExpression, Path, Pattern, PrefixExpression, UnresolvedType, + UnresolvedTypeData, UnresolvedTypeExpression, +}; use crate::ast::{ConstrainStatement, Expression, Statement, StatementKind}; use crate::hir_def::expr::{HirArrayLiteral, HirExpression, HirIdent}; use crate::hir_def::stmt::{HirLValue, HirPattern, HirStatement}; +use crate::hir_def::types::Type; use crate::macros_api::HirLiteral; use crate::node_interner::{ExprId, NodeInterner, StmtId}; -use crate::{ - ArrayLiteral, AssignStatement, BlockExpression, CallExpression, CastExpression, ConstrainKind, - ConstructorExpression, ExpressionKind, ForLoopStatement, ForRange, Ident, IfExpression, - IndexExpression, InfixExpression, LValue, Lambda, LetStatement, Literal, - MemberAccessExpression, MethodCallExpression, Path, Pattern, PrefixExpression, Type, - UnresolvedType, UnresolvedTypeData, UnresolvedTypeExpression, -}; // TODO: // - Full path for idents & types @@ -36,6 +37,7 @@ impl StmtId { pattern, r#type, expression, + comptime: false, attributes: Vec::new(), }) } @@ -64,6 +66,9 @@ impl StmtId { HirStatement::Expression(expr) => StatementKind::Expression(expr.to_ast(interner)), HirStatement::Semi(expr) => StatementKind::Semi(expr.to_ast(interner)), HirStatement::Error => StatementKind::Error, + HirStatement::Comptime(statement) => { + StatementKind::Comptime(Box::new(statement.to_ast(interner).kind)) + } }; Statement { kind, span } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter.rs new file mode 100644 index 00000000000..03839c2f0cd --- /dev/null +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter.rs @@ -0,0 +1,1294 @@ +use std::{borrow::Cow, collections::hash_map::Entry, rc::Rc}; + +use acvm::FieldElement; +use im::Vector; +use iter_extended::{try_vecmap, vecmap}; +use noirc_errors::Location; +use rustc_hash::{FxHashMap as HashMap, FxHashSet as HashSet}; + +use crate::ast::{BinaryOpKind, BlockExpression, FunctionKind, IntegerBitSize, Signedness}; +use crate::{ + hir_def::{ + expr::{ + HirArrayLiteral, HirBlockExpression, HirCallExpression, HirCastExpression, + HirConstructorExpression, HirIdent, HirIfExpression, HirIndexExpression, + HirInfixExpression, HirLambda, HirMemberAccess, HirMethodCallExpression, + HirPrefixExpression, + }, + stmt::{ + HirAssignStatement, HirConstrainStatement, HirForStatement, HirLValue, HirLetStatement, + HirPattern, + }, + }, + macros_api::{HirExpression, HirLiteral, HirStatement, NodeInterner}, + node_interner::{DefinitionId, DefinitionKind, ExprId, FuncId, StmtId}, +}; +use crate::{Shared, Type, TypeBinding, TypeBindings, TypeVariableKind}; +#[allow(unused)] +pub(crate) struct Interpreter<'interner> { + /// To expand macros the Interpreter may mutate hir nodes within the NodeInterner + interner: &'interner mut NodeInterner, + + /// Each value currently in scope in the interpreter. + /// Each element of the Vec represents a scope with every scope together making + /// up all currently visible definitions. + scopes: Vec>, + + /// True if we've expanded any macros into any functions and will need + /// to redo name resolution & type checking for that function. + changed_functions: HashSet, + + /// True if we've expanded any macros into global scope and will need + /// to redo name resolution & type checking for everything. + changed_globally: bool, + + in_loop: bool, + + /// True if we're currently in a compile-time context. + /// If this is false code is skipped over instead of executed. + in_comptime_context: bool, +} + +#[allow(unused)] +#[derive(Debug, Clone, PartialEq, Eq)] +pub(crate) enum Value { + Unit, + Bool(bool), + Field(FieldElement), + I8(i8), + I32(i32), + I64(i64), + U8(u8), + U32(u32), + U64(u64), + String(Rc), + Function(FuncId, Type), + Closure(HirLambda, Vec, Type), + Tuple(Vec), + Struct(HashMap, Value>, Type), + Pointer(Shared), + Array(Vector, Type), + Slice(Vector, Type), + Code(Rc), +} + +/// The possible errors that can halt the interpreter. +#[allow(unused)] +#[derive(Debug)] +pub(crate) enum InterpreterError { + ArgumentCountMismatch { expected: usize, actual: usize, call_location: Location }, + TypeMismatch { expected: Type, value: Value, location: Location }, + NoValueForId { id: DefinitionId, location: Location }, + IntegerOutOfRangeForType { value: FieldElement, typ: Type, location: Location }, + ErrorNodeEncountered { location: Location }, + NonFunctionCalled { value: Value, location: Location }, + NonBoolUsedInIf { value: Value, location: Location }, + NonBoolUsedInConstrain { value: Value, location: Location }, + FailingConstraint { message: Option, location: Location }, + NoMethodFound { object: Value, typ: Type, location: Location }, + NonIntegerUsedInLoop { value: Value, location: Location }, + NonPointerDereferenced { value: Value, location: Location }, + NonTupleOrStructInMemberAccess { value: Value, location: Location }, + NonArrayIndexed { value: Value, location: Location }, + NonIntegerUsedAsIndex { value: Value, location: Location }, + NonIntegerIntegerLiteral { typ: Type, location: Location }, + NonIntegerArrayLength { typ: Type, location: Location }, + NonNumericCasted { value: Value, location: Location }, + IndexOutOfBounds { index: usize, length: usize, location: Location }, + ExpectedStructToHaveField { value: Value, field_name: String, location: Location }, + TypeUnsupported { typ: Type, location: Location }, + InvalidValueForUnary { value: Value, operator: &'static str, location: Location }, + InvalidValuesForBinary { lhs: Value, rhs: Value, operator: &'static str, location: Location }, + CastToNonNumericType { typ: Type, location: Location }, + + // Perhaps this should be unreachable! due to type checking also preventing this error? + // Currently it and the Continue variant are the only interpreter errors without a Location field + BreakNotInLoop, + ContinueNotInLoop, + + // These cases are not errors but prevent us from running more code + // until the loop can be resumed properly. + Break, + Continue, +} + +#[allow(unused)] +type IResult = std::result::Result; + +#[allow(unused)] +impl<'a> Interpreter<'a> { + pub(crate) fn new(interner: &'a mut NodeInterner) -> Self { + Self { + interner, + scopes: vec![HashMap::default()], + changed_functions: HashSet::default(), + changed_globally: false, + in_loop: false, + in_comptime_context: false, + } + } + + pub(crate) fn call_function( + &mut self, + function: FuncId, + arguments: Vec<(Value, Location)>, + call_location: Location, + ) -> IResult { + let previous_state = self.enter_function(); + + let meta = self.interner.function_meta(&function); + if meta.kind != FunctionKind::Normal { + todo!("Evaluation for {:?} is unimplemented", meta.kind); + } + + if meta.parameters.len() != arguments.len() { + return Err(InterpreterError::ArgumentCountMismatch { + expected: meta.parameters.len(), + actual: arguments.len(), + call_location, + }); + } + + let parameters = meta.parameters.0.clone(); + for ((parameter, typ, _), (argument, arg_location)) in parameters.iter().zip(arguments) { + self.define_pattern(parameter, typ, argument, arg_location)?; + } + + let function_body = self.interner.function(&function).as_expr(); + let result = self.evaluate(function_body)?; + + self.exit_function(previous_state); + Ok(result) + } + + fn call_closure( + &mut self, + closure: HirLambda, + // TODO: How to define environment here? + _environment: Vec, + arguments: Vec<(Value, Location)>, + call_location: Location, + ) -> IResult { + let previous_state = self.enter_function(); + + if closure.parameters.len() != arguments.len() { + return Err(InterpreterError::ArgumentCountMismatch { + expected: closure.parameters.len(), + actual: arguments.len(), + call_location, + }); + } + + let parameters = closure.parameters.iter().zip(arguments); + for ((parameter, typ), (argument, arg_location)) in parameters { + self.define_pattern(parameter, typ, argument, arg_location)?; + } + + let result = self.evaluate(closure.body)?; + + self.exit_function(previous_state); + Ok(result) + } + + /// Enters a function, pushing a new scope and resetting any required state. + /// Returns the previous values of the internal state, to be reset when + /// `exit_function` is called. + fn enter_function(&mut self) -> (bool, Vec>) { + // Drain every scope except the global scope + let scope = self.scopes.drain(1..).collect(); + self.push_scope(); + (std::mem::take(&mut self.in_loop), scope) + } + + fn exit_function(&mut self, mut state: (bool, Vec>)) { + self.in_loop = state.0; + + // Keep only the global scope + self.scopes.truncate(1); + self.scopes.append(&mut state.1); + } + + fn push_scope(&mut self) { + self.scopes.push(HashMap::default()); + } + + fn pop_scope(&mut self) { + self.scopes.pop(); + } + + fn current_scope_mut(&mut self) -> &mut HashMap { + // the global scope is always at index zero, so this is always Some + self.scopes.last_mut().unwrap() + } + + fn define_pattern( + &mut self, + pattern: &HirPattern, + typ: &Type, + argument: Value, + location: Location, + ) -> IResult<()> { + match pattern { + HirPattern::Identifier(identifier) => { + self.define(identifier.id, typ, argument, location) + } + HirPattern::Mutable(pattern, _) => { + self.define_pattern(pattern, typ, argument, location) + } + HirPattern::Tuple(pattern_fields, _) => match (argument, typ) { + (Value::Tuple(fields), Type::Tuple(type_fields)) + if fields.len() == pattern_fields.len() => + { + for ((pattern, typ), argument) in + pattern_fields.iter().zip(type_fields).zip(fields) + { + self.define_pattern(pattern, typ, argument, location)?; + } + Ok(()) + } + (value, _) => { + Err(InterpreterError::TypeMismatch { expected: typ.clone(), value, location }) + } + }, + HirPattern::Struct(struct_type, pattern_fields, _) => { + self.type_check(typ, &argument, location)?; + self.type_check(struct_type, &argument, location)?; + + match argument { + Value::Struct(fields, struct_type) if fields.len() == pattern_fields.len() => { + for (field_name, field_pattern) in pattern_fields { + let field = fields.get(&field_name.0.contents).ok_or_else(|| { + InterpreterError::ExpectedStructToHaveField { + value: Value::Struct(fields.clone(), struct_type.clone()), + field_name: field_name.0.contents.clone(), + location, + } + })?; + + let field_type = field.get_type().into_owned(); + self.define_pattern( + field_pattern, + &field_type, + field.clone(), + location, + )?; + } + Ok(()) + } + value => Err(InterpreterError::TypeMismatch { + expected: typ.clone(), + value, + location, + }), + } + } + } + } + + /// Define a new variable in the current scope + fn define( + &mut self, + id: DefinitionId, + typ: &Type, + argument: Value, + location: Location, + ) -> IResult<()> { + self.type_check(typ, &argument, location)?; + self.current_scope_mut().insert(id, argument); + Ok(()) + } + + /// Mutate an existing variable, potentially from a prior scope. + /// Also type checks the value being assigned + fn checked_mutate( + &mut self, + id: DefinitionId, + typ: &Type, + argument: Value, + location: Location, + ) -> IResult<()> { + self.type_check(typ, &argument, location)?; + for scope in self.scopes.iter_mut().rev() { + if let Entry::Occupied(mut entry) = scope.entry(id) { + entry.insert(argument); + return Ok(()); + } + } + Err(InterpreterError::NoValueForId { id, location }) + } + + /// Mutate an existing variable, potentially from a prior scope + fn mutate(&mut self, id: DefinitionId, argument: Value, location: Location) -> IResult<()> { + for scope in self.scopes.iter_mut().rev() { + if let Entry::Occupied(mut entry) = scope.entry(id) { + entry.insert(argument); + return Ok(()); + } + } + Err(InterpreterError::NoValueForId { id, location }) + } + + fn lookup(&self, ident: &HirIdent) -> IResult { + for scope in self.scopes.iter().rev() { + if let Some(value) = scope.get(&ident.id) { + return Ok(value.clone()); + } + } + + Err(InterpreterError::NoValueForId { id: ident.id, location: ident.location }) + } + + fn lookup_id(&self, id: DefinitionId, location: Location) -> IResult { + for scope in self.scopes.iter().rev() { + if let Some(value) = scope.get(&id) { + return Ok(value.clone()); + } + } + + Err(InterpreterError::NoValueForId { id, location }) + } + + fn type_check(&self, typ: &Type, value: &Value, location: Location) -> IResult<()> { + let typ = typ.follow_bindings(); + let value_type = value.get_type(); + + typ.try_unify(&value_type, &mut TypeBindings::new()).map_err(|_| { + InterpreterError::TypeMismatch { expected: typ, value: value.clone(), location } + }) + } + + /// Evaluate an expression and return the result + fn evaluate(&mut self, id: ExprId) -> IResult { + match self.interner.expression(&id) { + HirExpression::Ident(ident) => self.evaluate_ident(ident, id), + HirExpression::Literal(literal) => self.evaluate_literal(literal, id), + HirExpression::Block(block) => self.evaluate_block(block), + HirExpression::Prefix(prefix) => self.evaluate_prefix(prefix, id), + HirExpression::Infix(infix) => self.evaluate_infix(infix, id), + HirExpression::Index(index) => self.evaluate_index(index, id), + HirExpression::Constructor(constructor) => self.evaluate_constructor(constructor, id), + HirExpression::MemberAccess(access) => self.evaluate_access(access, id), + HirExpression::Call(call) => self.evaluate_call(call, id), + HirExpression::MethodCall(call) => self.evaluate_method_call(call, id), + HirExpression::Cast(cast) => self.evaluate_cast(cast, id), + HirExpression::If(if_) => self.evaluate_if(if_, id), + HirExpression::Tuple(tuple) => self.evaluate_tuple(tuple), + HirExpression::Lambda(lambda) => self.evaluate_lambda(lambda, id), + HirExpression::Quote(block) => Ok(Value::Code(Rc::new(block))), + HirExpression::Error => { + let location = self.interner.expr_location(&id); + Err(InterpreterError::ErrorNodeEncountered { location }) + } + } + } + + fn evaluate_ident(&mut self, ident: HirIdent, id: ExprId) -> IResult { + let definition = self.interner.definition(ident.id); + + match &definition.kind { + DefinitionKind::Function(function_id) => { + let typ = self.interner.id_type(id); + Ok(Value::Function(*function_id, typ)) + } + DefinitionKind::Local(_) => dbg!(self.lookup(&ident)), + DefinitionKind::Global(global_id) => { + let let_ = self.interner.get_global_let_statement(*global_id).unwrap(); + self.evaluate_let(let_)?; + self.lookup(&ident) + } + DefinitionKind::GenericType(type_variable) => { + let value = match &*type_variable.borrow() { + TypeBinding::Unbound(_) => None, + TypeBinding::Bound(binding) => binding.evaluate_to_u64(), + }; + + if let Some(value) = value { + let typ = self.interner.id_type(id); + self.evaluate_integer((value as u128).into(), false, id) + } else { + let location = self.interner.expr_location(&id); + let typ = Type::TypeVariable(type_variable.clone(), TypeVariableKind::Normal); + Err(InterpreterError::NonIntegerArrayLength { typ, location }) + } + } + } + } + + fn evaluate_literal(&mut self, literal: HirLiteral, id: ExprId) -> IResult { + match literal { + HirLiteral::Unit => Ok(Value::Unit), + HirLiteral::Bool(value) => Ok(Value::Bool(value)), + HirLiteral::Integer(value, is_negative) => { + self.evaluate_integer(value, is_negative, id) + } + HirLiteral::Str(string) => Ok(Value::String(Rc::new(string))), + HirLiteral::FmtStr(_, _) => todo!("Evaluate format strings"), + HirLiteral::Array(array) => self.evaluate_array(array, id), + HirLiteral::Slice(array) => self.evaluate_slice(array, id), + } + } + + fn evaluate_integer( + &self, + value: FieldElement, + is_negative: bool, + id: ExprId, + ) -> IResult { + let typ = self.interner.id_type(id).follow_bindings(); + let location = self.interner.expr_location(&id); + + if let Type::FieldElement = &typ { + Ok(Value::Field(value)) + } else if let Type::Integer(sign, bit_size) = &typ { + match (sign, bit_size) { + (Signedness::Unsigned, IntegerBitSize::One) => { + return Err(InterpreterError::TypeUnsupported { typ, location }); + } + (Signedness::Unsigned, IntegerBitSize::Eight) => { + let value: u8 = + value.try_to_u64().and_then(|value| value.try_into().ok()).ok_or( + InterpreterError::IntegerOutOfRangeForType { value, typ, location }, + )?; + let value = if is_negative { 0u8.wrapping_sub(value) } else { value }; + Ok(Value::U8(value)) + } + (Signedness::Unsigned, IntegerBitSize::ThirtyTwo) => { + let value: u32 = + value.try_to_u64().and_then(|value| value.try_into().ok()).ok_or( + InterpreterError::IntegerOutOfRangeForType { value, typ, location }, + )?; + let value = if is_negative { 0u32.wrapping_sub(value) } else { value }; + Ok(Value::U32(value)) + } + (Signedness::Unsigned, IntegerBitSize::SixtyFour) => { + let value: u64 = + value.try_to_u64().ok_or(InterpreterError::IntegerOutOfRangeForType { + value, + typ, + location, + })?; + let value = if is_negative { 0u64.wrapping_sub(value) } else { value }; + Ok(Value::U64(value)) + } + (Signedness::Signed, IntegerBitSize::One) => { + return Err(InterpreterError::TypeUnsupported { typ, location }); + } + (Signedness::Signed, IntegerBitSize::Eight) => { + let value: i8 = + value.try_to_u64().and_then(|value| value.try_into().ok()).ok_or( + InterpreterError::IntegerOutOfRangeForType { value, typ, location }, + )?; + let value = if is_negative { -value } else { value }; + Ok(Value::I8(value)) + } + (Signedness::Signed, IntegerBitSize::ThirtyTwo) => { + let value: i32 = + value.try_to_u64().and_then(|value| value.try_into().ok()).ok_or( + InterpreterError::IntegerOutOfRangeForType { value, typ, location }, + )?; + let value = if is_negative { -value } else { value }; + Ok(Value::I32(value)) + } + (Signedness::Signed, IntegerBitSize::SixtyFour) => { + let value: i64 = + value.try_to_u64().and_then(|value| value.try_into().ok()).ok_or( + InterpreterError::IntegerOutOfRangeForType { value, typ, location }, + )?; + let value = if is_negative { -value } else { value }; + Ok(Value::I64(value)) + } + } + } else { + Err(InterpreterError::NonIntegerIntegerLiteral { typ, location }) + } + } + + fn evaluate_block(&mut self, mut block: HirBlockExpression) -> IResult { + let last_statement = block.statements.pop(); + self.push_scope(); + + for statement in block.statements { + self.evaluate_statement(statement)?; + } + + let result = if let Some(statement) = last_statement { + self.evaluate_statement(statement) + } else { + Ok(Value::Unit) + }; + + self.pop_scope(); + result + } + + fn evaluate_array(&mut self, array: HirArrayLiteral, id: ExprId) -> IResult { + let typ = self.interner.id_type(id); + + match array { + HirArrayLiteral::Standard(elements) => { + let elements = elements + .into_iter() + .map(|id| self.evaluate(id)) + .collect::>>()?; + + Ok(Value::Array(elements, typ)) + } + HirArrayLiteral::Repeated { repeated_element, length } => { + let element = self.evaluate(repeated_element)?; + + if let Some(length) = length.evaluate_to_u64() { + let elements = (0..length).map(|_| element.clone()).collect(); + Ok(Value::Array(elements, typ)) + } else { + let location = self.interner.expr_location(&id); + Err(InterpreterError::NonIntegerArrayLength { typ: length, location }) + } + } + } + } + + fn evaluate_slice(&mut self, array: HirArrayLiteral, id: ExprId) -> IResult { + self.evaluate_array(array, id).map(|value| match value { + Value::Array(array, typ) => Value::Slice(array, typ), + other => unreachable!("Non-array value returned from evaluate array: {other:?}"), + }) + } + + fn evaluate_prefix(&mut self, prefix: HirPrefixExpression, id: ExprId) -> IResult { + let rhs = self.evaluate(prefix.rhs)?; + match prefix.operator { + crate::ast::UnaryOp::Minus => match rhs { + Value::Field(value) => Ok(Value::Field(FieldElement::zero() - value)), + Value::I8(value) => Ok(Value::I8(-value)), + Value::I32(value) => Ok(Value::I32(-value)), + Value::I64(value) => Ok(Value::I64(-value)), + Value::U8(value) => Ok(Value::U8(0 - value)), + Value::U32(value) => Ok(Value::U32(0 - value)), + Value::U64(value) => Ok(Value::U64(0 - value)), + value => { + let location = self.interner.expr_location(&id); + Err(InterpreterError::InvalidValueForUnary { + value, + location, + operator: "minus", + }) + } + }, + crate::ast::UnaryOp::Not => match rhs { + Value::Bool(value) => Ok(Value::Bool(!value)), + Value::I8(value) => Ok(Value::I8(!value)), + Value::I32(value) => Ok(Value::I32(!value)), + Value::I64(value) => Ok(Value::I64(!value)), + Value::U8(value) => Ok(Value::U8(!value)), + Value::U32(value) => Ok(Value::U32(!value)), + Value::U64(value) => Ok(Value::U64(!value)), + value => { + let location = self.interner.expr_location(&id); + Err(InterpreterError::InvalidValueForUnary { value, location, operator: "not" }) + } + }, + crate::ast::UnaryOp::MutableReference => Ok(Value::Pointer(Shared::new(rhs))), + crate::ast::UnaryOp::Dereference { implicitly_added: _ } => match rhs { + Value::Pointer(element) => Ok(element.borrow().clone()), + value => { + let location = self.interner.expr_location(&id); + Err(InterpreterError::NonPointerDereferenced { value, location }) + } + }, + } + } + + fn evaluate_infix(&mut self, infix: HirInfixExpression, id: ExprId) -> IResult { + let lhs = self.evaluate(infix.lhs)?; + let rhs = self.evaluate(infix.rhs)?; + + // TODO: Need to account for operator overloading + assert!( + self.interner.get_selected_impl_for_expression(id).is_none(), + "Operator overloading is unimplemented in the interpreter" + ); + + use InterpreterError::InvalidValuesForBinary; + match infix.operator.kind { + BinaryOpKind::Add => match (lhs, rhs) { + (Value::Field(lhs), Value::Field(rhs)) => Ok(Value::Field(lhs + rhs)), + (Value::I8(lhs), Value::I8(rhs)) => Ok(Value::I8(lhs + rhs)), + (Value::I32(lhs), Value::I32(rhs)) => Ok(Value::I32(lhs + rhs)), + (Value::I64(lhs), Value::I64(rhs)) => Ok(Value::I64(lhs + rhs)), + (Value::U8(lhs), Value::U8(rhs)) => Ok(Value::U8(lhs + rhs)), + (Value::U32(lhs), Value::U32(rhs)) => Ok(Value::U32(lhs + rhs)), + (Value::U64(lhs), Value::U64(rhs)) => Ok(Value::U64(lhs + rhs)), + (lhs, rhs) => { + let location = self.interner.expr_location(&id); + Err(InvalidValuesForBinary { lhs, rhs, location, operator: "+" }) + } + }, + BinaryOpKind::Subtract => match (lhs, rhs) { + (Value::Field(lhs), Value::Field(rhs)) => Ok(Value::Field(lhs - rhs)), + (Value::I8(lhs), Value::I8(rhs)) => Ok(Value::I8(lhs - rhs)), + (Value::I32(lhs), Value::I32(rhs)) => Ok(Value::I32(lhs - rhs)), + (Value::I64(lhs), Value::I64(rhs)) => Ok(Value::I64(lhs - rhs)), + (Value::U8(lhs), Value::U8(rhs)) => Ok(Value::U8(lhs - rhs)), + (Value::U32(lhs), Value::U32(rhs)) => Ok(Value::U32(lhs - rhs)), + (Value::U64(lhs), Value::U64(rhs)) => Ok(Value::U64(lhs - rhs)), + (lhs, rhs) => { + let location = self.interner.expr_location(&id); + Err(InvalidValuesForBinary { lhs, rhs, location, operator: "-" }) + } + }, + BinaryOpKind::Multiply => match (lhs, rhs) { + (Value::Field(lhs), Value::Field(rhs)) => Ok(Value::Field(lhs * rhs)), + (Value::I8(lhs), Value::I8(rhs)) => Ok(Value::I8(lhs * rhs)), + (Value::I32(lhs), Value::I32(rhs)) => Ok(Value::I32(lhs * rhs)), + (Value::I64(lhs), Value::I64(rhs)) => Ok(Value::I64(lhs * rhs)), + (Value::U8(lhs), Value::U8(rhs)) => Ok(Value::U8(lhs * rhs)), + (Value::U32(lhs), Value::U32(rhs)) => Ok(Value::U32(lhs * rhs)), + (Value::U64(lhs), Value::U64(rhs)) => Ok(Value::U64(lhs * rhs)), + (lhs, rhs) => { + let location = self.interner.expr_location(&id); + Err(InvalidValuesForBinary { lhs, rhs, location, operator: "*" }) + } + }, + BinaryOpKind::Divide => match (lhs, rhs) { + (Value::Field(lhs), Value::Field(rhs)) => Ok(Value::Field(lhs / rhs)), + (Value::I8(lhs), Value::I8(rhs)) => Ok(Value::I8(lhs / rhs)), + (Value::I32(lhs), Value::I32(rhs)) => Ok(Value::I32(lhs / rhs)), + (Value::I64(lhs), Value::I64(rhs)) => Ok(Value::I64(lhs / rhs)), + (Value::U8(lhs), Value::U8(rhs)) => Ok(Value::U8(lhs / rhs)), + (Value::U32(lhs), Value::U32(rhs)) => Ok(Value::U32(lhs / rhs)), + (Value::U64(lhs), Value::U64(rhs)) => Ok(Value::U64(lhs / rhs)), + (lhs, rhs) => { + let location = self.interner.expr_location(&id); + Err(InvalidValuesForBinary { lhs, rhs, location, operator: "/" }) + } + }, + BinaryOpKind::Equal => match (lhs, rhs) { + (Value::Field(lhs), Value::Field(rhs)) => Ok(Value::Bool(lhs == rhs)), + (Value::I8(lhs), Value::I8(rhs)) => Ok(Value::Bool(lhs == rhs)), + (Value::I32(lhs), Value::I32(rhs)) => Ok(Value::Bool(lhs == rhs)), + (Value::I64(lhs), Value::I64(rhs)) => Ok(Value::Bool(lhs == rhs)), + (Value::U8(lhs), Value::U8(rhs)) => Ok(Value::Bool(lhs == rhs)), + (Value::U32(lhs), Value::U32(rhs)) => Ok(Value::Bool(lhs == rhs)), + (Value::U64(lhs), Value::U64(rhs)) => Ok(Value::Bool(lhs == rhs)), + (lhs, rhs) => { + let location = self.interner.expr_location(&id); + Err(InvalidValuesForBinary { lhs, rhs, location, operator: "==" }) + } + }, + BinaryOpKind::NotEqual => match (lhs, rhs) { + (Value::Field(lhs), Value::Field(rhs)) => Ok(Value::Bool(lhs != rhs)), + (Value::I8(lhs), Value::I8(rhs)) => Ok(Value::Bool(lhs != rhs)), + (Value::I32(lhs), Value::I32(rhs)) => Ok(Value::Bool(lhs != rhs)), + (Value::I64(lhs), Value::I64(rhs)) => Ok(Value::Bool(lhs != rhs)), + (Value::U8(lhs), Value::U8(rhs)) => Ok(Value::Bool(lhs != rhs)), + (Value::U32(lhs), Value::U32(rhs)) => Ok(Value::Bool(lhs != rhs)), + (Value::U64(lhs), Value::U64(rhs)) => Ok(Value::Bool(lhs != rhs)), + (lhs, rhs) => { + let location = self.interner.expr_location(&id); + Err(InvalidValuesForBinary { lhs, rhs, location, operator: "!=" }) + } + }, + BinaryOpKind::Less => match (lhs, rhs) { + (Value::Field(lhs), Value::Field(rhs)) => Ok(Value::Bool(lhs < rhs)), + (Value::I8(lhs), Value::I8(rhs)) => Ok(Value::Bool(lhs < rhs)), + (Value::I32(lhs), Value::I32(rhs)) => Ok(Value::Bool(lhs < rhs)), + (Value::I64(lhs), Value::I64(rhs)) => Ok(Value::Bool(lhs < rhs)), + (Value::U8(lhs), Value::U8(rhs)) => Ok(Value::Bool(lhs < rhs)), + (Value::U32(lhs), Value::U32(rhs)) => Ok(Value::Bool(lhs < rhs)), + (Value::U64(lhs), Value::U64(rhs)) => Ok(Value::Bool(lhs < rhs)), + (lhs, rhs) => { + let location = self.interner.expr_location(&id); + Err(InvalidValuesForBinary { lhs, rhs, location, operator: "<" }) + } + }, + BinaryOpKind::LessEqual => match (lhs, rhs) { + (Value::Field(lhs), Value::Field(rhs)) => Ok(Value::Bool(lhs <= rhs)), + (Value::I8(lhs), Value::I8(rhs)) => Ok(Value::Bool(lhs <= rhs)), + (Value::I32(lhs), Value::I32(rhs)) => Ok(Value::Bool(lhs <= rhs)), + (Value::I64(lhs), Value::I64(rhs)) => Ok(Value::Bool(lhs <= rhs)), + (Value::U8(lhs), Value::U8(rhs)) => Ok(Value::Bool(lhs <= rhs)), + (Value::U32(lhs), Value::U32(rhs)) => Ok(Value::Bool(lhs <= rhs)), + (Value::U64(lhs), Value::U64(rhs)) => Ok(Value::Bool(lhs <= rhs)), + (lhs, rhs) => { + let location = self.interner.expr_location(&id); + Err(InvalidValuesForBinary { lhs, rhs, location, operator: "<=" }) + } + }, + BinaryOpKind::Greater => match (lhs, rhs) { + (Value::Field(lhs), Value::Field(rhs)) => Ok(Value::Bool(lhs > rhs)), + (Value::I8(lhs), Value::I8(rhs)) => Ok(Value::Bool(lhs > rhs)), + (Value::I32(lhs), Value::I32(rhs)) => Ok(Value::Bool(lhs > rhs)), + (Value::I64(lhs), Value::I64(rhs)) => Ok(Value::Bool(lhs > rhs)), + (Value::U8(lhs), Value::U8(rhs)) => Ok(Value::Bool(lhs > rhs)), + (Value::U32(lhs), Value::U32(rhs)) => Ok(Value::Bool(lhs > rhs)), + (Value::U64(lhs), Value::U64(rhs)) => Ok(Value::Bool(lhs > rhs)), + (lhs, rhs) => { + let location = self.interner.expr_location(&id); + Err(InvalidValuesForBinary { lhs, rhs, location, operator: ">" }) + } + }, + BinaryOpKind::GreaterEqual => match (lhs, rhs) { + (Value::Field(lhs), Value::Field(rhs)) => Ok(Value::Bool(lhs >= rhs)), + (Value::I8(lhs), Value::I8(rhs)) => Ok(Value::Bool(lhs >= rhs)), + (Value::I32(lhs), Value::I32(rhs)) => Ok(Value::Bool(lhs >= rhs)), + (Value::I64(lhs), Value::I64(rhs)) => Ok(Value::Bool(lhs >= rhs)), + (Value::U8(lhs), Value::U8(rhs)) => Ok(Value::Bool(lhs >= rhs)), + (Value::U32(lhs), Value::U32(rhs)) => Ok(Value::Bool(lhs >= rhs)), + (Value::U64(lhs), Value::U64(rhs)) => Ok(Value::Bool(lhs >= rhs)), + (lhs, rhs) => { + let location = self.interner.expr_location(&id); + Err(InvalidValuesForBinary { lhs, rhs, location, operator: ">=" }) + } + }, + BinaryOpKind::And => match (lhs, rhs) { + (Value::Bool(lhs), Value::Bool(rhs)) => Ok(Value::Bool(lhs & rhs)), + (Value::I8(lhs), Value::I8(rhs)) => Ok(Value::I8(lhs & rhs)), + (Value::I32(lhs), Value::I32(rhs)) => Ok(Value::I32(lhs & rhs)), + (Value::I64(lhs), Value::I64(rhs)) => Ok(Value::I64(lhs & rhs)), + (Value::U8(lhs), Value::U8(rhs)) => Ok(Value::U8(lhs & rhs)), + (Value::U32(lhs), Value::U32(rhs)) => Ok(Value::U32(lhs & rhs)), + (Value::U64(lhs), Value::U64(rhs)) => Ok(Value::U64(lhs & rhs)), + (lhs, rhs) => { + let location = self.interner.expr_location(&id); + Err(InvalidValuesForBinary { lhs, rhs, location, operator: "&" }) + } + }, + BinaryOpKind::Or => match (lhs, rhs) { + (Value::Bool(lhs), Value::Bool(rhs)) => Ok(Value::Bool(lhs | rhs)), + (Value::I8(lhs), Value::I8(rhs)) => Ok(Value::I8(lhs | rhs)), + (Value::I32(lhs), Value::I32(rhs)) => Ok(Value::I32(lhs | rhs)), + (Value::I64(lhs), Value::I64(rhs)) => Ok(Value::I64(lhs | rhs)), + (Value::U8(lhs), Value::U8(rhs)) => Ok(Value::U8(lhs | rhs)), + (Value::U32(lhs), Value::U32(rhs)) => Ok(Value::U32(lhs | rhs)), + (Value::U64(lhs), Value::U64(rhs)) => Ok(Value::U64(lhs | rhs)), + (lhs, rhs) => { + let location = self.interner.expr_location(&id); + Err(InvalidValuesForBinary { lhs, rhs, location, operator: "|" }) + } + }, + BinaryOpKind::Xor => match (lhs, rhs) { + (Value::Bool(lhs), Value::Bool(rhs)) => Ok(Value::Bool(lhs ^ rhs)), + (Value::I8(lhs), Value::I8(rhs)) => Ok(Value::I8(lhs ^ rhs)), + (Value::I32(lhs), Value::I32(rhs)) => Ok(Value::I32(lhs ^ rhs)), + (Value::I64(lhs), Value::I64(rhs)) => Ok(Value::I64(lhs ^ rhs)), + (Value::U8(lhs), Value::U8(rhs)) => Ok(Value::U8(lhs ^ rhs)), + (Value::U32(lhs), Value::U32(rhs)) => Ok(Value::U32(lhs ^ rhs)), + (Value::U64(lhs), Value::U64(rhs)) => Ok(Value::U64(lhs ^ rhs)), + (lhs, rhs) => { + let location = self.interner.expr_location(&id); + Err(InvalidValuesForBinary { lhs, rhs, location, operator: "^" }) + } + }, + BinaryOpKind::ShiftRight => match (lhs, rhs) { + (Value::I8(lhs), Value::I8(rhs)) => Ok(Value::I8(lhs >> rhs)), + (Value::I32(lhs), Value::I32(rhs)) => Ok(Value::I32(lhs >> rhs)), + (Value::I64(lhs), Value::I64(rhs)) => Ok(Value::I64(lhs >> rhs)), + (Value::U8(lhs), Value::U8(rhs)) => Ok(Value::U8(lhs >> rhs)), + (Value::U32(lhs), Value::U32(rhs)) => Ok(Value::U32(lhs >> rhs)), + (Value::U64(lhs), Value::U64(rhs)) => Ok(Value::U64(lhs >> rhs)), + (lhs, rhs) => { + let location = self.interner.expr_location(&id); + Err(InvalidValuesForBinary { lhs, rhs, location, operator: ">>" }) + } + }, + BinaryOpKind::ShiftLeft => match (lhs, rhs) { + (Value::I8(lhs), Value::I8(rhs)) => Ok(Value::I8(lhs << rhs)), + (Value::I32(lhs), Value::I32(rhs)) => Ok(Value::I32(lhs << rhs)), + (Value::I64(lhs), Value::I64(rhs)) => Ok(Value::I64(lhs << rhs)), + (Value::U8(lhs), Value::U8(rhs)) => Ok(Value::U8(lhs << rhs)), + (Value::U32(lhs), Value::U32(rhs)) => Ok(Value::U32(lhs << rhs)), + (Value::U64(lhs), Value::U64(rhs)) => Ok(Value::U64(lhs << rhs)), + (lhs, rhs) => { + let location = self.interner.expr_location(&id); + Err(InvalidValuesForBinary { lhs, rhs, location, operator: "<<" }) + } + }, + BinaryOpKind::Modulo => match (lhs, rhs) { + (Value::I8(lhs), Value::I8(rhs)) => Ok(Value::I8(lhs % rhs)), + (Value::I32(lhs), Value::I32(rhs)) => Ok(Value::I32(lhs % rhs)), + (Value::I64(lhs), Value::I64(rhs)) => Ok(Value::I64(lhs % rhs)), + (Value::U8(lhs), Value::U8(rhs)) => Ok(Value::U8(lhs % rhs)), + (Value::U32(lhs), Value::U32(rhs)) => Ok(Value::U32(lhs % rhs)), + (Value::U64(lhs), Value::U64(rhs)) => Ok(Value::U64(lhs % rhs)), + (lhs, rhs) => { + let location = self.interner.expr_location(&id); + Err(InvalidValuesForBinary { lhs, rhs, location, operator: "%" }) + } + }, + } + } + + fn evaluate_index(&mut self, index: HirIndexExpression, id: ExprId) -> IResult { + let array = self.evaluate(index.collection)?; + let index = self.evaluate(index.index)?; + + let location = self.interner.expr_location(&id); + let (array, index) = self.bounds_check(array, index, location)?; + + Ok(array[index].clone()) + } + + /// Bounds check the given array and index pair. + /// This will also ensure the given arguments are in fact an array and integer. + fn bounds_check( + &self, + array: Value, + index: Value, + location: Location, + ) -> IResult<(Vector, usize)> { + let collection = match array { + Value::Array(array, _) => array, + Value::Slice(array, _) => array, + value => { + return Err(InterpreterError::NonArrayIndexed { value, location }); + } + }; + + let index = match index { + Value::Field(value) => { + value.try_to_u64().expect("index could not fit into u64") as usize + } + Value::I8(value) => value as usize, + Value::I32(value) => value as usize, + Value::I64(value) => value as usize, + Value::U8(value) => value as usize, + Value::U32(value) => value as usize, + Value::U64(value) => value as usize, + value => { + return Err(InterpreterError::NonIntegerUsedAsIndex { value, location }); + } + }; + + if index >= collection.len() { + use InterpreterError::IndexOutOfBounds; + return Err(IndexOutOfBounds { index, location, length: collection.len() }); + } + + Ok((collection, index)) + } + + fn evaluate_constructor( + &mut self, + constructor: HirConstructorExpression, + id: ExprId, + ) -> IResult { + let fields = constructor + .fields + .into_iter() + .map(|(name, expr)| { + let field_value = self.evaluate(expr)?; + Ok((Rc::new(name.0.contents), field_value)) + }) + .collect::>()?; + + let typ = self.interner.id_type(id); + Ok(Value::Struct(fields, typ)) + } + + fn evaluate_access(&mut self, access: HirMemberAccess, id: ExprId) -> IResult { + let (fields, struct_type) = match self.evaluate(access.lhs)? { + Value::Struct(fields, typ) => (fields, typ), + value => { + let location = self.interner.expr_location(&id); + return Err(InterpreterError::NonTupleOrStructInMemberAccess { value, location }); + } + }; + + fields.get(&access.rhs.0.contents).cloned().ok_or_else(|| { + let location = self.interner.expr_location(&id); + let value = Value::Struct(fields, struct_type); + let field_name = access.rhs.0.contents; + InterpreterError::ExpectedStructToHaveField { value, field_name, location } + }) + } + + fn evaluate_call(&mut self, call: HirCallExpression, id: ExprId) -> IResult { + let function = self.evaluate(call.func)?; + let arguments = try_vecmap(call.arguments, |arg| { + Ok((self.evaluate(arg)?, self.interner.expr_location(&arg))) + })?; + let location = self.interner.expr_location(&id); + + match function { + Value::Function(function_id, _) => self.call_function(function_id, arguments, location), + Value::Closure(closure, env, _) => self.call_closure(closure, env, arguments, location), + value => Err(InterpreterError::NonFunctionCalled { value, location }), + } + } + + fn evaluate_method_call( + &mut self, + call: HirMethodCallExpression, + id: ExprId, + ) -> IResult { + let object = self.evaluate(call.object)?; + let arguments = try_vecmap(call.arguments, |arg| { + Ok((self.evaluate(arg)?, self.interner.expr_location(&arg))) + })?; + let location = self.interner.expr_location(&id); + + let typ = object.get_type().follow_bindings(); + let method_name = &call.method.0.contents; + + // TODO: Traits + let method = match &typ { + Type::Struct(struct_def, _) => { + self.interner.lookup_method(&typ, struct_def.borrow().id, method_name, false) + } + _ => self.interner.lookup_primitive_method(&typ, method_name), + }; + + if let Some(method) = method { + self.call_function(method, arguments, location) + } else { + Err(InterpreterError::NoMethodFound { object, typ, location }) + } + } + + fn evaluate_cast(&mut self, cast: HirCastExpression, id: ExprId) -> IResult { + macro_rules! signed_int_to_field { + ($x:expr) => {{ + // Need to convert the signed integer to an i128 before + // we negate it to preserve the MIN value. + let mut value = $x as i128; + let is_negative = value < 0; + if is_negative { + value = -value; + } + ((value as u128).into(), is_negative) + }}; + } + + let (mut lhs, lhs_is_negative) = match self.evaluate(cast.lhs)? { + Value::Field(value) => (value, false), + Value::U8(value) => ((value as u128).into(), false), + Value::U32(value) => ((value as u128).into(), false), + Value::U64(value) => ((value as u128).into(), false), + Value::I8(value) => signed_int_to_field!(value), + Value::I32(value) => signed_int_to_field!(value), + Value::I64(value) => signed_int_to_field!(value), + Value::Bool(value) => { + (if value { FieldElement::one() } else { FieldElement::zero() }, false) + } + value => { + let location = self.interner.expr_location(&id); + return Err(InterpreterError::NonNumericCasted { value, location }); + } + }; + + macro_rules! cast_to_int { + ($x:expr, $method:ident, $typ:ty, $f:ident) => {{ + let mut value = $x.$method() as $typ; + if lhs_is_negative { + value = 0 - value; + } + Ok(Value::$f(value)) + }}; + } + + // Now actually cast the lhs, bit casting and wrapping as necessary + match cast.r#type.follow_bindings() { + Type::FieldElement => { + if lhs_is_negative { + lhs = FieldElement::zero() - lhs; + } + Ok(Value::Field(lhs)) + } + Type::Integer(sign, bit_size) => match (sign, bit_size) { + (Signedness::Unsigned, IntegerBitSize::One) => { + let location = self.interner.expr_location(&id); + Err(InterpreterError::TypeUnsupported { typ: cast.r#type, location }) + } + (Signedness::Unsigned, IntegerBitSize::Eight) => cast_to_int!(lhs, to_u128, u8, U8), + (Signedness::Unsigned, IntegerBitSize::ThirtyTwo) => { + cast_to_int!(lhs, to_u128, u32, U32) + } + (Signedness::Unsigned, IntegerBitSize::SixtyFour) => { + cast_to_int!(lhs, to_u128, u64, U64) + } + (Signedness::Signed, IntegerBitSize::One) => { + let location = self.interner.expr_location(&id); + Err(InterpreterError::TypeUnsupported { typ: cast.r#type, location }) + } + (Signedness::Signed, IntegerBitSize::Eight) => cast_to_int!(lhs, to_i128, i8, I8), + (Signedness::Signed, IntegerBitSize::ThirtyTwo) => { + cast_to_int!(lhs, to_i128, i32, I32) + } + (Signedness::Signed, IntegerBitSize::SixtyFour) => { + cast_to_int!(lhs, to_i128, i64, I64) + } + }, + Type::Bool => Ok(Value::Bool(!lhs.is_zero() || lhs_is_negative)), + typ => { + let location = self.interner.expr_location(&id); + Err(InterpreterError::CastToNonNumericType { typ, location }) + } + } + } + + fn evaluate_if(&mut self, if_: HirIfExpression, id: ExprId) -> IResult { + let condition = match self.evaluate(if_.condition)? { + Value::Bool(value) => value, + value => { + let location = self.interner.expr_location(&id); + return Err(InterpreterError::NonBoolUsedInIf { value, location }); + } + }; + + self.push_scope(); + + let result = if condition { + if if_.alternative.is_some() { + self.evaluate(if_.consequence) + } else { + self.evaluate(if_.consequence)?; + Ok(Value::Unit) + } + } else { + match if_.alternative { + Some(alternative) => self.evaluate(alternative), + None => Ok(Value::Unit), + } + }; + + self.pop_scope(); + result + } + + fn evaluate_tuple(&mut self, tuple: Vec) -> IResult { + let fields = try_vecmap(tuple, |field| self.evaluate(field))?; + Ok(Value::Tuple(fields)) + } + + fn evaluate_lambda(&mut self, lambda: HirLambda, id: ExprId) -> IResult { + let location = self.interner.expr_location(&id); + let environment = + try_vecmap(&lambda.captures, |capture| self.lookup_id(capture.ident.id, location))?; + + let typ = self.interner.id_type(id); + Ok(Value::Closure(lambda, environment, typ)) + } + + fn evaluate_statement(&mut self, statement: StmtId) -> IResult { + match self.interner.statement(&statement) { + HirStatement::Let(let_) => self.evaluate_let(let_), + HirStatement::Constrain(constrain) => self.evaluate_constrain(constrain), + HirStatement::Assign(assign) => self.evaluate_assign(assign), + HirStatement::For(for_) => self.evaluate_for(for_), + HirStatement::Break => self.evaluate_break(), + HirStatement::Continue => self.evaluate_continue(), + HirStatement::Expression(expression) => self.evaluate(expression), + HirStatement::Comptime(statement) => self.evaluate_comptime(statement), + HirStatement::Semi(expression) => { + self.evaluate(expression)?; + Ok(Value::Unit) + } + HirStatement::Error => { + let location = self.interner.id_location(statement); + Err(InterpreterError::ErrorNodeEncountered { location }) + } + } + } + + fn evaluate_let(&mut self, let_: HirLetStatement) -> IResult { + let rhs = self.evaluate(let_.expression)?; + let location = self.interner.expr_location(&let_.expression); + self.define_pattern(&let_.pattern, &let_.r#type, rhs, location)?; + Ok(Value::Unit) + } + + fn evaluate_constrain(&mut self, constrain: HirConstrainStatement) -> IResult { + match self.evaluate(constrain.0)? { + Value::Bool(true) => Ok(Value::Unit), + Value::Bool(false) => { + let location = self.interner.expr_location(&constrain.0); + let message = constrain.2.and_then(|expr| self.evaluate(expr).ok()); + Err(InterpreterError::FailingConstraint { location, message }) + } + value => { + let location = self.interner.expr_location(&constrain.0); + Err(InterpreterError::NonBoolUsedInConstrain { value, location }) + } + } + } + + fn evaluate_assign(&mut self, assign: HirAssignStatement) -> IResult { + let rhs = self.evaluate(assign.expression)?; + self.store_lvalue(assign.lvalue, rhs)?; + Ok(Value::Unit) + } + + fn store_lvalue(&mut self, lvalue: HirLValue, rhs: Value) -> IResult<()> { + match lvalue { + HirLValue::Ident(ident, typ) => { + self.checked_mutate(ident.id, &typ, rhs, ident.location) + } + HirLValue::Dereference { lvalue, element_type: _, location } => { + match self.evaluate_lvalue(&lvalue)? { + Value::Pointer(value) => { + *value.borrow_mut() = rhs; + Ok(()) + } + value => Err(InterpreterError::NonPointerDereferenced { value, location }), + } + } + HirLValue::MemberAccess { object, field_name, field_index, typ: _, location } => { + let index = field_index.expect("The field index should be set after type checking"); + match self.evaluate_lvalue(&object)? { + Value::Tuple(mut fields) => { + fields[index] = rhs; + self.store_lvalue(*object, Value::Tuple(fields)) + } + Value::Struct(mut fields, typ) => { + fields.insert(Rc::new(field_name.0.contents), rhs); + self.store_lvalue(*object, Value::Struct(fields, typ)) + } + value => { + Err(InterpreterError::NonTupleOrStructInMemberAccess { value, location }) + } + } + } + HirLValue::Index { array, index, typ: _, location } => { + let array_value = self.evaluate_lvalue(&array)?; + let index = self.evaluate(index)?; + + let constructor = match &array_value { + Value::Array(..) => Value::Array, + _ => Value::Slice, + }; + + let typ = array_value.get_type().into_owned(); + let (elements, index) = self.bounds_check(array_value, index, location)?; + + let new_array = constructor(elements.update(index, rhs), typ); + self.store_lvalue(*array, new_array) + } + } + } + + fn evaluate_lvalue(&mut self, lvalue: &HirLValue) -> IResult { + match lvalue { + HirLValue::Ident(ident, _) => self.lookup(ident), + HirLValue::Dereference { lvalue, element_type: _, location } => { + match self.evaluate_lvalue(lvalue)? { + Value::Pointer(value) => Ok(value.borrow().clone()), + value => { + Err(InterpreterError::NonPointerDereferenced { value, location: *location }) + } + } + } + HirLValue::MemberAccess { object, field_name, field_index, typ: _, location } => { + let index = field_index.expect("The field index should be set after type checking"); + + match self.evaluate_lvalue(object)? { + Value::Tuple(mut values) => Ok(values.swap_remove(index)), + Value::Struct(fields, _) => Ok(fields[&field_name.0.contents].clone()), + value => Err(InterpreterError::NonTupleOrStructInMemberAccess { + value, + location: *location, + }), + } + } + HirLValue::Index { array, index, typ: _, location } => { + let array = self.evaluate_lvalue(array)?; + let index = self.evaluate(*index)?; + let (elements, index) = self.bounds_check(array, index, *location)?; + Ok(elements[index].clone()) + } + } + } + + fn evaluate_for(&mut self, for_: HirForStatement) -> IResult { + // i128 can store all values from i8 - u64 + let get_index = |this: &mut Self, expr| -> IResult<(_, fn(_) -> _)> { + match this.evaluate(expr)? { + Value::I8(value) => Ok((value as i128, |i| Value::I8(i as i8))), + Value::I32(value) => Ok((value as i128, |i| Value::I32(i as i32))), + Value::I64(value) => Ok((value as i128, |i| Value::I64(i as i64))), + Value::U8(value) => Ok((value as i128, |i| Value::U8(i as u8))), + Value::U32(value) => Ok((value as i128, |i| Value::U32(i as u32))), + Value::U64(value) => Ok((value as i128, |i| Value::U64(i as u64))), + value => { + let location = this.interner.expr_location(&expr); + Err(InterpreterError::NonIntegerUsedInLoop { value, location }) + } + } + }; + + let (start, make_value) = get_index(self, for_.start_range)?; + let (end, _) = get_index(self, for_.end_range)?; + let was_in_loop = std::mem::replace(&mut self.in_loop, true); + + for i in start..end { + self.push_scope(); + self.current_scope_mut().insert(for_.identifier.id, make_value(i)); + + match self.evaluate(for_.block) { + Ok(_) => (), + Err(InterpreterError::Break) => break, + Err(InterpreterError::Continue) => continue, + Err(other) => return Err(other), + } + self.pop_scope(); + } + + self.in_loop = was_in_loop; + Ok(Value::Unit) + } + + fn evaluate_break(&mut self) -> IResult { + if self.in_loop { + Err(InterpreterError::Break) + } else { + Err(InterpreterError::BreakNotInLoop) + } + } + + fn evaluate_continue(&mut self) -> IResult { + if self.in_loop { + Err(InterpreterError::Continue) + } else { + Err(InterpreterError::ContinueNotInLoop) + } + } + + fn evaluate_comptime(&mut self, statement: StmtId) -> IResult { + let was_in_comptime = std::mem::replace(&mut self.in_comptime_context, true); + let result = self.evaluate_statement(statement); + self.in_comptime_context = was_in_comptime; + result + } +} + +impl Value { + fn get_type(&self) -> Cow { + Cow::Owned(match self { + Value::Unit => Type::Unit, + Value::Bool(_) => Type::Bool, + Value::Field(_) => Type::FieldElement, + Value::I8(_) => Type::Integer(Signedness::Signed, IntegerBitSize::Eight), + Value::I32(_) => Type::Integer(Signedness::Signed, IntegerBitSize::ThirtyTwo), + Value::I64(_) => Type::Integer(Signedness::Signed, IntegerBitSize::SixtyFour), + Value::U8(_) => Type::Integer(Signedness::Unsigned, IntegerBitSize::Eight), + Value::U32(_) => Type::Integer(Signedness::Unsigned, IntegerBitSize::ThirtyTwo), + Value::U64(_) => Type::Integer(Signedness::Unsigned, IntegerBitSize::SixtyFour), + Value::String(value) => { + let length = Type::Constant(value.len() as u64); + Type::String(Box::new(length)) + } + Value::Function(_, typ) => return Cow::Borrowed(typ), + Value::Closure(_, _, typ) => return Cow::Borrowed(typ), + Value::Tuple(fields) => { + Type::Tuple(vecmap(fields, |field| field.get_type().into_owned())) + } + Value::Struct(_, typ) => return Cow::Borrowed(typ), + Value::Array(_, typ) => return Cow::Borrowed(typ), + Value::Slice(_, typ) => return Cow::Borrowed(typ), + Value::Code(_) => Type::Code, + Value::Pointer(element) => { + let element = element.borrow().get_type().into_owned(); + Type::MutableReference(Box::new(element)) + } + }) + } +} diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/mod.rs index 91621c857cf..83aaddaa405 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/mod.rs @@ -1 +1,3 @@ mod hir_to_ast; +mod interpreter; +mod tests; diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/tests.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/tests.rs new file mode 100644 index 00000000000..016e7079886 --- /dev/null +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/tests.rs @@ -0,0 +1,166 @@ +#![cfg(test)] + +use noirc_errors::Location; + +use super::interpreter::{Interpreter, InterpreterError, Value}; +use crate::hir::type_check::test::type_check_src_code; + +fn interpret_helper(src: &str, func_namespace: Vec) -> Result { + let (mut interner, main_id) = type_check_src_code(src, func_namespace); + let mut interpreter = Interpreter::new(&mut interner); + + let no_location = Location::dummy(); + interpreter.call_function(main_id, Vec::new(), no_location) +} + +fn interpret(src: &str, func_namespace: Vec) -> Value { + interpret_helper(src, func_namespace).unwrap_or_else(|error| { + panic!("Expected interpreter to exit successfully, but found {error:?}") + }) +} + +fn interpret_expect_error(src: &str, func_namespace: Vec) -> InterpreterError { + interpret_helper(src, func_namespace).expect_err("Expected interpreter to error") +} + +#[test] +fn interpreter_works() { + let program = "fn main() -> pub Field { 3 }"; + let result = interpret(program, vec!["main".into()]); + assert_eq!(result, Value::Field(3u128.into())); +} + +#[test] +fn mutation_works() { + let program = "fn main() -> pub i8 { + let mut x = 3; + x = 4; + x + }"; + let result = interpret(program, vec!["main".into()]); + assert_eq!(result, Value::I8(4)); +} + +#[test] +fn mutating_references() { + let program = "fn main() -> pub i32 { + let x = &mut 3; + *x = 4; + *x + }"; + let result = interpret(program, vec!["main".into()]); + assert_eq!(result, Value::I32(4)); +} + +#[test] +fn mutating_mutable_references() { + let program = "fn main() -> pub i64 { + let mut x = &mut 3; + *x = 4; + *x + }"; + let result = interpret(program, vec!["main".into()]); + assert_eq!(result, Value::I64(4)); +} + +#[test] +fn mutating_arrays() { + let program = "fn main() -> pub u8 { + let mut a1 = [1, 2, 3, 4]; + a1[1] = 22; + a1[1] + }"; + let result = interpret(program, vec!["main".into()]); + assert_eq!(result, Value::U8(22)); +} + +#[test] +fn for_loop() { + let program = "fn main() -> pub u8 { + let mut x = 0; + for i in 0 .. 6 { + x += i; + } + x + }"; + let result = interpret(program, vec!["main".into()]); + assert_eq!(result, Value::U8(15)); +} + +#[test] +fn for_loop_with_break() { + let program = "unconstrained fn main() -> pub u32 { + let mut x = 0; + for i in 0 .. 6 { + if i == 4 { + break; + } + x += i; + } + x + }"; + let result = interpret(program, vec!["main".into()]); + assert_eq!(result, Value::U32(6)); +} + +#[test] +fn for_loop_with_continue() { + let program = "unconstrained fn main() -> pub u64 { + let mut x = 0; + for i in 0 .. 6 { + if i == 4 { + continue; + } + x += i; + } + x + }"; + let result = interpret(program, vec!["main".into()]); + assert_eq!(result, Value::U64(11)); +} + +#[test] +fn assert() { + let program = "fn main() { + assert(1 == 1); + }"; + let result = interpret(program, vec!["main".into()]); + assert_eq!(result, Value::Unit); +} + +#[test] +fn assert_fail() { + let program = "fn main() { + assert(1 == 2); + }"; + let result = interpret_expect_error(program, vec!["main".into()]); + assert!(matches!(result, InterpreterError::FailingConstraint { .. })); +} + +#[test] +fn lambda() { + let program = "fn main() -> pub u8 { + let f = |x: u8| x + 1; + f(1) + }"; + let result = interpret(program, vec!["main".into()]); + assert!(matches!(result, Value::U8(2))); +} + +#[test] +fn non_deterministic_recursion() { + let program = " + fn main() -> pub u64 { + fib(10) + } + + fn fib(x: u64) -> u64 { + if x <= 1 { + x + } else { + fib(x - 1) + fib(x - 2) + } + }"; + let result = interpret(program, vec!["main".into(), "fib".into()]); + assert_eq!(result, Value::U64(55)); +} diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs index 463b8a4b329..4c6b5ab5885 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs @@ -18,11 +18,11 @@ use crate::hir::Context; use crate::macros_api::{MacroError, MacroProcessor}; use crate::node_interner::{FuncId, GlobalId, NodeInterner, StructId, TraitId, TypeAliasId}; -use crate::parser::{ParserError, SortedModule}; -use crate::{ +use crate::ast::{ ExpressionKind, Ident, LetStatement, Literal, NoirFunction, NoirStruct, NoirTrait, NoirTypeAlias, Path, PathKind, UnresolvedGenerics, UnresolvedTraitConstraint, UnresolvedType, }; +use crate::parser::{ParserError, SortedModule}; use fm::FileId; use iter_extended::vecmap; use noirc_errors::{CustomDiagnostic, Span}; @@ -398,11 +398,11 @@ fn inject_prelude( ) { let segments: Vec<_> = "std::prelude" .split("::") - .map(|segment| crate::Ident::new(segment.into(), Span::default())) + .map(|segment| crate::ast::Ident::new(segment.into(), Span::default())) .collect(); let path = - Path { segments: segments.clone(), kind: crate::PathKind::Dep, span: Span::default() }; + Path { segments: segments.clone(), kind: crate::ast::PathKind::Dep, span: Span::default() }; if !crate_id.is_stdlib() { if let Ok(PathResolution { module_def_id, error }) = path_resolver::resolve_path( diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs index 6fbb3b67546..baedb109967 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs @@ -4,14 +4,16 @@ use acvm::acir::acir_field::FieldOptions; use fm::{FileId, FileManager, FILE_EXTENSION}; use noirc_errors::Location; +use crate::ast::{ + FunctionDefinition, Ident, ItemVisibility, LetStatement, ModuleDeclaration, NoirFunction, + NoirStruct, NoirTrait, NoirTraitImpl, NoirTypeAlias, TraitImplItem, TraitItem, TypeImpl, +}; use crate::{ graph::CrateId, hir::def_collector::dc_crate::{UnresolvedStruct, UnresolvedTrait}, macros_api::MacroProcessor, node_interner::{FunctionModifiers, TraitId, TypeAliasId}, parser::{SortedModule, SortedSubModule}, - FunctionDefinition, Ident, ItemVisibility, LetStatement, ModuleDeclaration, NoirFunction, - NoirStruct, NoirTrait, NoirTraitImpl, NoirTypeAlias, TraitImplItem, TraitItem, TypeImpl, }; use super::{ @@ -416,6 +418,7 @@ impl<'a> ModCollector<'a> { // TODO(Maddiaa): Investigate trait implementations with attributes see: https://github.com/noir-lang/noir/issues/2629 attributes: crate::token::Attributes::empty(), is_unconstrained: false, + is_comptime: false, }; let location = Location::new(name.span(), self.file_id); diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/errors.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/errors.rs index 29daf5d6369..59a3051ac70 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/errors.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/errors.rs @@ -1,6 +1,5 @@ +use crate::ast::{Ident, Path}; use crate::hir::resolution::import::PathResolutionError; -use crate::Ident; -use crate::Path; use noirc_errors::CustomDiagnostic as Diagnostic; use noirc_errors::FileDiagnostic; diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_map/item_scope.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_map/item_scope.rs index cd4eafdf669..3ca89e56bbc 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_map/item_scope.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_map/item_scope.rs @@ -1,8 +1,7 @@ use super::{namespace::PerNs, ModuleDefId, ModuleId}; -use crate::{ - node_interner::{FuncId, TraitId}, - Ident, ItemVisibility, -}; +use crate::ast::{Ident, ItemVisibility}; +use crate::node_interner::{FuncId, TraitId}; + use std::collections::{hash_map::Entry, HashMap}; type Scope = HashMap, (ModuleDefId, ItemVisibility, bool /*is_prelude*/)>; diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_map/module_data.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_map/module_data.rs index 4dd38f0e3e5..488ccc476d7 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_map/module_data.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_map/module_data.rs @@ -2,12 +2,9 @@ use std::collections::HashMap; use noirc_errors::Location; -use crate::{ - node_interner::{FuncId, GlobalId, StructId, TraitId, TypeAliasId}, - Ident, ItemVisibility, -}; - use super::{ItemScope, LocalModuleId, ModuleDefId, ModuleId, PerNs}; +use crate::ast::{Ident, ItemVisibility}; +use crate::node_interner::{FuncId, GlobalId, StructId, TraitId, TypeAliasId}; /// Contains the actual contents of a module: its parent (if one exists), /// children, and scope with all definitions defined within the scope. diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_map/namespace.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_map/namespace.rs index 5e349f46e14..6fac6d2b991 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_map/namespace.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_map/namespace.rs @@ -1,5 +1,5 @@ use super::ModuleDefId; -use crate::ItemVisibility; +use crate::ast::ItemVisibility; // This works exactly the same as in r-a, just simplified #[derive(Debug, PartialEq, Eq, Copy, Clone)] diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/errors.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/errors.rs index 71e3f3482fc..0fac6f96086 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/errors.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/errors.rs @@ -2,7 +2,7 @@ pub use noirc_errors::Span; use noirc_errors::{CustomDiagnostic as Diagnostic, FileDiagnostic}; use thiserror::Error; -use crate::{parser::ParserError, Ident, Type}; +use crate::{ast::Ident, parser::ParserError, Type}; use super::import::PathResolutionError; @@ -49,7 +49,7 @@ pub enum ResolverError { #[error("Integer too large to be evaluated in an array length context")] IntegerTooLarge { span: Span }, #[error("No global or generic type parameter found with the given name")] - NoSuchNumericTypeVariable { path: crate::Path }, + NoSuchNumericTypeVariable { path: crate::ast::Path }, #[error("Closures cannot capture mutable variables")] CapturedMutableVariable { span: Span }, #[error("Test functions are not allowed to have any parameters")] diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/impls.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/impls.rs index 72f6adc3770..7efd1eed86e 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/impls.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/impls.rs @@ -2,6 +2,7 @@ use std::collections::BTreeMap; use fm::FileId; +use crate::ast::ItemVisibility; use crate::{ graph::CrateId, hir::{ @@ -13,7 +14,7 @@ use crate::{ Context, }, node_interner::{FuncId, NodeInterner}, - ItemVisibility, Type, + Type, }; use super::{ diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/import.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/import.rs index ade97e2cf42..77e67567f8c 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/import.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/import.rs @@ -4,8 +4,8 @@ use thiserror::Error; use crate::graph::CrateId; use std::collections::BTreeMap; +use crate::ast::{Ident, ItemVisibility, Path, PathKind}; use crate::hir::def_map::{CrateDefMap, LocalModuleId, ModuleDefId, ModuleId, PerNs}; -use crate::{Ident, ItemVisibility, Path, PathKind}; #[derive(Debug, Clone)] pub struct ImportDirective { diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/path_resolver.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/path_resolver.rs index e19af3c732f..e423e10b712 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/path_resolver.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/path_resolver.rs @@ -1,5 +1,5 @@ use super::import::{resolve_import, ImportDirective, PathResolution, PathResolutionResult}; -use crate::Path; +use crate::ast::Path; use std::collections::BTreeMap; use crate::graph::CrateId; diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/resolver.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/resolver.rs index 9180201fe17..0e69b3bdeba 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/resolver.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/resolver.rs @@ -25,25 +25,22 @@ use regex::Regex; use std::collections::{BTreeMap, HashSet}; use std::rc::Rc; +use crate::ast::{ + ArrayLiteral, BinaryOpKind, BlockExpression, Distinctness, Expression, ExpressionKind, + ForRange, FunctionDefinition, FunctionKind, FunctionReturnType, Ident, ItemVisibility, LValue, + LetStatement, Literal, NoirFunction, NoirStruct, NoirTypeAlias, Param, Path, PathKind, Pattern, + Statement, StatementKind, UnaryOp, UnresolvedGenerics, UnresolvedTraitConstraint, + UnresolvedType, UnresolvedTypeData, UnresolvedTypeExpression, Visibility, ERROR_IDENT, +}; use crate::graph::CrateId; use crate::hir::def_map::{ModuleDefId, TryFromModuleDefId, MAIN_FUNCTION}; +use crate::hir::{def_map::CrateDefMap, resolution::path_resolver::PathResolver}; use crate::hir_def::stmt::{HirAssignStatement, HirForStatement, HirLValue, HirPattern}; use crate::node_interner::{ DefinitionId, DefinitionKind, DependencyId, ExprId, FuncId, GlobalId, NodeInterner, StmtId, StructId, TraitId, TraitImplId, TraitMethodId, TypeAliasId, }; -use crate::{ - hir::{def_map::CrateDefMap, resolution::path_resolver::PathResolver}, - BlockExpression, Expression, ExpressionKind, FunctionKind, Ident, Literal, NoirFunction, - StatementKind, -}; -use crate::{ - ArrayLiteral, BinaryOpKind, Distinctness, ForRange, FunctionDefinition, FunctionReturnType, - Generics, ItemVisibility, LValue, NoirStruct, NoirTypeAlias, Param, Path, PathKind, Pattern, - Shared, Statement, StructType, Type, TypeAlias, TypeVariable, TypeVariableKind, UnaryOp, - UnresolvedGenerics, UnresolvedTraitConstraint, UnresolvedType, UnresolvedTypeData, - UnresolvedTypeExpression, Visibility, ERROR_IDENT, -}; +use crate::{Generics, Shared, StructType, Type, TypeAlias, TypeVariable, TypeVariableKind}; use fm::FileId; use iter_extended::vecmap; use noirc_errors::{Location, Span, Spanned}; @@ -246,6 +243,7 @@ impl<'a> Resolver<'a> { name: name.clone(), attributes: Attributes::empty(), is_unconstrained: false, + is_comptime: false, visibility: ItemVisibility::Public, // Trait functions are always public generics: generics.clone(), parameters: vecmap(parameters, |(name, typ)| Param { @@ -477,7 +475,7 @@ impl<'a> Resolver<'a> { /// Translates an UnresolvedType into a Type and appends any /// freshly created TypeVariables created to new_variables. fn resolve_type_inner(&mut self, typ: UnresolvedType, new_variables: &mut Generics) -> Type { - use UnresolvedTypeData::*; + use crate::ast::UnresolvedTypeData::*; let resolved_type = match typ.typ { FieldElement => Type::FieldElement, @@ -928,6 +926,7 @@ impl<'a> Resolver<'a> { let name_ident = HirIdent::non_trait_method(id, location); let attributes = func.attributes().clone(); + let should_fold = attributes.is_foldable(); let mut generics = vecmap(&self.generics, |(_, typevar, _)| typevar.clone()); let mut parameters = vec![]; @@ -1008,8 +1007,6 @@ impl<'a> Resolver<'a> { .map(|(name, typevar, _span)| (name.clone(), typevar.clone())) .collect(); - let should_fold = attributes.is_foldable(); - FuncMeta { name: name_ident, kind: func.kind, @@ -1038,7 +1035,7 @@ impl<'a> Resolver<'a> { /// True if the 'pub' keyword is allowed on parameters in this function /// 'pub' on function parameters is only allowed for entry point functions fn pub_allowed(&self, func: &NoirFunction) -> bool { - self.is_entry_point_function(func) + self.is_entry_point_function(func) || func.attributes().is_foldable() } fn is_entry_point_function(&self, func: &NoirFunction) -> bool { @@ -1171,7 +1168,7 @@ impl<'a> Resolver<'a> { pub fn resolve_global_let( &mut self, - let_stmt: crate::LetStatement, + let_stmt: LetStatement, global_id: GlobalId, ) -> HirStatement { self.current_item = Some(DependencyId::Global(global_id)); @@ -1275,6 +1272,10 @@ impl<'a> Resolver<'a> { HirStatement::Continue } StatementKind::Error => HirStatement::Error, + StatementKind::Comptime(statement) => { + let statement = self.resolve_stmt(*statement, span); + HirStatement::Comptime(self.interner.push_stmt(statement)) + } } } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/structs.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/structs.rs index ed7aa86e718..f62e5589d74 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/structs.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/structs.rs @@ -3,6 +3,7 @@ use std::collections::BTreeMap; use fm::FileId; use iter_extended::vecmap; +use crate::ast::Ident; use crate::{ graph::CrateId, hir::{ @@ -11,7 +12,7 @@ use crate::{ Context, }, node_interner::StructId, - Generics, Ident, Type, + Generics, Type, }; use super::{errors::ResolverError, path_resolver::StandardPathResolver, resolver::Resolver}; diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/traits.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/traits.rs index a7669f57e33..ccae8c6dd03 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/traits.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/traits.rs @@ -4,6 +4,7 @@ use fm::FileId; use iter_extended::vecmap; use noirc_errors::Location; +use crate::ast::{ItemVisibility, Path, TraitItem}; use crate::{ graph::CrateId, hir::{ @@ -16,7 +17,7 @@ use crate::{ }, hir_def::traits::{TraitConstant, TraitFunction, TraitImpl, TraitType}, node_interner::{FuncId, NodeInterner, TraitId}, - Generics, ItemVisibility, Path, Shared, TraitItem, Type, TypeVariable, TypeVariableKind, + Generics, Shared, Type, TypeVariable, TypeVariableKind, }; use super::{ diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/errors.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/errors.rs index 6c28aabe0fb..6c2a1945283 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/errors.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/errors.rs @@ -3,13 +3,10 @@ use noirc_errors::CustomDiagnostic as Diagnostic; use noirc_errors::Span; use thiserror::Error; +use crate::ast::{BinaryOpKind, FunctionReturnType, IntegerBitSize, Signedness}; use crate::hir::resolution::errors::ResolverError; use crate::hir_def::expr::HirBinaryOp; use crate::hir_def::types::Type; -use crate::BinaryOpKind; -use crate::FunctionReturnType; -use crate::IntegerBitSize; -use crate::Signedness; #[derive(Error, Debug, Clone, PartialEq, Eq)] pub enum Source { diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/expr.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/expr.rs index b56e2dce2a9..62330732be4 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/expr.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/expr.rs @@ -1,6 +1,7 @@ use iter_extended::vecmap; use noirc_errors::Span; +use crate::ast::{BinaryOpKind, UnaryOp}; use crate::{ hir::{resolution::resolver::verify_mutable_reference, type_check::errors::Source}, hir_def::{ @@ -11,7 +12,7 @@ use crate::{ types::Type, }, node_interner::{DefinitionKind, ExprId, FuncId, TraitId, TraitImplKind, TraitMethodId}, - BinaryOpKind, TypeBinding, TypeBindings, TypeVariableKind, UnaryOp, + TypeBinding, TypeBindings, TypeVariableKind, }; use super::{errors::TypeCheckError, TypeChecker}; @@ -717,7 +718,7 @@ impl<'interner> TypeChecker<'interner> { let dereference_lhs = |this: &mut Self, lhs_type, element| { let old_lhs = *access_lhs; *access_lhs = this.interner.push_expr(HirExpression::Prefix(HirPrefixExpression { - operator: crate::UnaryOp::Dereference { implicitly_added: true }, + operator: crate::ast::UnaryOp::Dereference { implicitly_added: true }, rhs: old_lhs, })); this.interner.push_expr_type(old_lhs, lhs_type); @@ -1110,7 +1111,7 @@ impl<'interner> TypeChecker<'interner> { if !op.kind.is_valid_for_field_type() && lhs_type.is_numeric() { let target = Type::polymorphic_integer(self.interner); - use BinaryOpKind::*; + use crate::ast::BinaryOpKind::*; use TypeCheckError::*; self.unify(lhs_type, &target, || match op.kind { Less | LessEqual | Greater | GreaterEqual => FieldComparison { span }, @@ -1202,7 +1203,7 @@ impl<'interner> TypeChecker<'interner> { fn type_check_prefix_operand( &mut self, - op: &crate::UnaryOp, + op: &crate::ast::UnaryOp, rhs_type: &Type, span: Span, ) -> Type { @@ -1216,7 +1217,7 @@ impl<'interner> TypeChecker<'interner> { }; match op { - crate::UnaryOp::Minus => { + crate::ast::UnaryOp::Minus => { if rhs_type.is_unsigned() { self.errors .push(TypeCheckError::InvalidUnaryOp { kind: rhs_type.to_string(), span }); @@ -1228,7 +1229,7 @@ impl<'interner> TypeChecker<'interner> { }); expected } - crate::UnaryOp::Not => { + crate::ast::UnaryOp::Not => { let rhs_type = rhs_type.follow_bindings(); // `!` can work on booleans or integers @@ -1238,10 +1239,10 @@ impl<'interner> TypeChecker<'interner> { unify(Type::Bool) } - crate::UnaryOp::MutableReference => { + crate::ast::UnaryOp::MutableReference => { Type::MutableReference(Box::new(rhs_type.follow_bindings())) } - crate::UnaryOp::Dereference { implicitly_added: _ } => { + crate::ast::UnaryOp::Dereference { implicitly_added: _ } => { let element_type = self.interner.next_type_variable(); unify(Type::MutableReference(Box::new(element_type.clone()))); element_type diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/mod.rs index cdfc19b3a33..44dab6dee3d 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/mod.rs @@ -51,8 +51,7 @@ pub fn type_check_func(interner: &mut NodeInterner, func_id: FuncId) -> Vec, ) { let meta = type_checker.interner.function_meta(&func_id); - if (meta.is_entry_point || meta.should_fold) && !param.1.is_valid_for_program_input() { + if (meta.is_entry_point && !param.1.is_valid_for_program_input()) + || (meta.should_fold && !param.1.is_valid_non_inlined_function_input()) + { let span = param.0.span(); errors.push(TypeCheckError::InvalidTypeForEntryPoint { span }); } @@ -424,14 +425,17 @@ impl<'interner> TypeChecker<'interner> { // XXX: These tests are all manual currently. /// We can either build a test apparatus or pass raw code through the resolver #[cfg(test)] -mod test { +pub mod test { use std::collections::{BTreeMap, HashMap}; use std::vec; use fm::FileId; - use iter_extended::vecmap; + use iter_extended::btree_map; use noirc_errors::{Location, Span}; + use crate::ast::{ + BinaryOpKind, Distinctness, FunctionKind, FunctionReturnType, Path, Visibility, + }; use crate::graph::CrateId; use crate::hir::def_map::{ModuleData, ModuleId}; use crate::hir::resolution::import::{ @@ -452,9 +456,8 @@ mod test { def_map::{CrateDefMap, LocalModuleId, ModuleDefId}, resolution::{path_resolver::PathResolver, resolver::Resolver}, }, - parse_program, FunctionKind, Path, + parse_program, }; - use crate::{BinaryOpKind, Distinctness, FunctionReturnType, Visibility}; #[test] fn basic_let() { @@ -601,7 +604,7 @@ mod test { "#; - type_check_src_code(src, vec![String::from("main"), String::from("foo")]); + type_check_src_code(src, vec![String::from("main")]); } #[test] fn basic_closure() { @@ -612,7 +615,7 @@ mod test { } "#; - type_check_src_code(src, vec![String::from("main"), String::from("foo")]); + type_check_src_code(src, vec![String::from("main")]); } #[test] @@ -633,12 +636,23 @@ mod test { #[fold] fn fold(x: &mut Field) -> Field { *x - } + } "#; type_check_src_code_errors_expected(src, vec![String::from("fold")], 1); } + #[test] + fn fold_numeric_generic() { + let src = r#" + #[fold] + fn fold(x: T) -> T { + x + } + "#; + + type_check_src_code(src, vec![String::from("fold")]); + } // This is the same Stub that is in the resolver, maybe we can pull this out into a test module and re-use? struct TestPathResolver(HashMap); @@ -672,8 +686,8 @@ mod test { } } - fn type_check_src_code(src: &str, func_namespace: Vec) { - type_check_src_code_errors_expected(src, func_namespace, 0); + pub fn type_check_src_code(src: &str, func_namespace: Vec) -> (NodeInterner, FuncId) { + type_check_src_code_errors_expected(src, func_namespace, 0) } // This function assumes that there is only one function and this is the @@ -682,7 +696,7 @@ mod test { src: &str, func_namespace: Vec, expected_num_type_check_errs: usize, - ) { + ) -> (NodeInterner, FuncId) { let (program, errors) = parse_program(src); let mut interner = NodeInterner::default(); interner.populate_dummy_operator_traits(); @@ -695,14 +709,16 @@ mod test { errors ); - let main_id = interner.push_test_function_definition("main".into()); + let func_ids = btree_map(&func_namespace, |name| { + (name.to_string(), interner.push_test_function_definition(name.into())) + }); - let func_ids = - vecmap(&func_namespace, |name| interner.push_test_function_definition(name.into())); + let main_id = + *func_ids.get("main").unwrap_or_else(|| func_ids.first_key_value().unwrap().1); let mut path_resolver = TestPathResolver(HashMap::new()); - for (name, id) in func_namespace.into_iter().zip(func_ids.clone()) { - path_resolver.insert_func(name.to_owned(), id); + for (name, id) in func_ids.iter() { + path_resolver.insert_func(name.to_owned(), *id); } let mut def_maps = BTreeMap::new(); @@ -722,20 +738,24 @@ mod test { }, ); - let func_meta = vecmap(program.into_sorted().functions, |nf| { + for nf in program.into_sorted().functions { let resolver = Resolver::new(&mut interner, &path_resolver, &def_maps, file); - let (hir_func, func_meta, resolver_errors) = resolver.resolve_function(nf, main_id); - assert_eq!(resolver_errors, vec![]); - (hir_func, func_meta) - }); - for ((hir_func, meta), func_id) in func_meta.into_iter().zip(func_ids.clone()) { - interner.update_fn(func_id, hir_func); - interner.push_fn_meta(meta, func_id); + let function_id = *func_ids.get(nf.name()).unwrap(); + let (hir_func, func_meta, resolver_errors) = resolver.resolve_function(nf, function_id); + + interner.push_fn_meta(func_meta, function_id); + interner.update_fn(function_id, hir_func); + assert_eq!(resolver_errors, vec![]); } // Type check section - let errors = super::type_check_func(&mut interner, func_ids.first().cloned().unwrap()); + let mut errors = Vec::new(); + + for function in func_ids.values() { + errors.extend(super::type_check_func(&mut interner, *function)); + } + assert_eq!( errors.len(), expected_num_type_check_errs, @@ -744,5 +764,7 @@ mod test { errors.len(), errors ); + + (interner, main_id) } } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/stmt.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/stmt.rs index fb57aa75f89..f5f6e1e8180 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/stmt.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/stmt.rs @@ -1,6 +1,7 @@ use iter_extended::vecmap; use noirc_errors::Span; +use crate::ast::UnaryOp; use crate::hir_def::expr::{HirExpression, HirIdent, HirLiteral}; use crate::hir_def::stmt::{ HirAssignStatement, HirConstrainStatement, HirForStatement, HirLValue, HirLetStatement, @@ -8,7 +9,6 @@ use crate::hir_def::stmt::{ }; use crate::hir_def::types::Type; use crate::node_interner::{DefinitionId, ExprId, StmtId}; -use crate::UnaryOp; use super::errors::{Source, TypeCheckError}; use super::TypeChecker; @@ -51,6 +51,7 @@ impl<'interner> TypeChecker<'interner> { HirStatement::Constrain(constrain_stmt) => self.check_constrain_stmt(constrain_stmt), HirStatement::Assign(assign_stmt) => self.check_assign_stmt(assign_stmt, stmt_id), HirStatement::For(for_loop) => self.check_for_loop(for_loop), + HirStatement::Comptime(statement) => return self.check_statement(&statement), HirStatement::Break | HirStatement::Continue | HirStatement::Error => (), } Type::Unit diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir_def/expr.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir_def/expr.rs index c2f6031bf6d..d88b65d1fce 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir_def/expr.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir_def/expr.rs @@ -2,8 +2,9 @@ use acvm::FieldElement; use fm::FileId; use noirc_errors::Location; +use crate::ast::{BinaryOp, BinaryOpKind, Ident, UnaryOp}; use crate::node_interner::{DefinitionId, ExprId, FuncId, NodeInterner, StmtId, TraitMethodId}; -use crate::{BinaryOp, BinaryOpKind, Ident, Shared, UnaryOp}; +use crate::Shared; use super::stmt::HirPattern; use super::traits::TraitConstraint; @@ -31,7 +32,7 @@ pub enum HirExpression { Tuple(Vec), Lambda(HirLambda), Error, - Quote(crate::BlockExpression), + Quote(crate::ast::BlockExpression), } impl HirExpression { @@ -260,7 +261,7 @@ impl HirBlockExpression { } /// A variable captured inside a closure -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq, Eq)] pub struct HirCapturedVar { pub ident: HirIdent, @@ -274,7 +275,7 @@ pub struct HirCapturedVar { pub transitive_capture_index: Option, } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq, Eq)] pub struct HirLambda { pub parameters: Vec<(HirPattern, Type)>, pub return_type: Type, diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir_def/function.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir_def/function.rs index a3bbc9445a8..67b6412a21c 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir_def/function.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir_def/function.rs @@ -6,9 +6,9 @@ use std::rc::Rc; use super::expr::{HirBlockExpression, HirExpression, HirIdent}; use super::stmt::HirPattern; use super::traits::TraitConstraint; +use crate::ast::{Distinctness, FunctionKind, FunctionReturnType, Visibility}; use crate::node_interner::{ExprId, NodeInterner, TraitImplId}; -use crate::FunctionKind; -use crate::{Distinctness, FunctionReturnType, Type, TypeVariable, Visibility}; +use crate::{Type, TypeVariable}; /// A Hir function is a block expression /// with a list of statements @@ -24,8 +24,8 @@ impl HirFunction { HirFunction(expr_id) } - pub const fn as_expr(&self) -> &ExprId { - &self.0 + pub const fn as_expr(&self) -> ExprId { + self.0 } pub fn block(&self, interner: &NodeInterner) -> HirBlockExpression { diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir_def/stmt.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir_def/stmt.rs index 4c9a33d3dc0..7e22e5ee9c0 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir_def/stmt.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir_def/stmt.rs @@ -1,7 +1,8 @@ use super::expr::HirIdent; +use crate::ast::Ident; use crate::macros_api::SecondaryAttribute; -use crate::node_interner::ExprId; -use crate::{Ident, Type}; +use crate::node_interner::{ExprId, StmtId}; +use crate::Type; use fm::FileId; use noirc_errors::{Location, Span}; @@ -19,6 +20,7 @@ pub enum HirStatement { Continue, Expression(ExprId), Semi(ExprId), + Comptime(StmtId), Error, } @@ -61,7 +63,7 @@ pub struct HirAssignStatement { #[derive(Debug, Clone)] pub struct HirConstrainStatement(pub ExprId, pub FileId, pub Option); -#[derive(Debug, Clone, Hash)] +#[derive(Debug, Clone, Hash, PartialEq, Eq)] pub enum HirPattern { Identifier(HirIdent), Mutable(Box, Location), diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir_def/traits.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir_def/traits.rs index 16b9899039f..e4959cb3dd9 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir_def/traits.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir_def/traits.rs @@ -1,9 +1,10 @@ use std::collections::HashMap; +use crate::ast::{Ident, NoirFunction}; use crate::{ graph::CrateId, node_interner::{FuncId, TraitId, TraitMethodId}, - Generics, Ident, NoirFunction, Type, TypeBindings, TypeVariable, TypeVariableId, + Generics, Type, TypeBindings, TypeVariable, TypeVariableId, }; use fm::FileId; use noirc_errors::{Location, Span}; diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir_def/types.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir_def/types.rs index ec8b54c33b8..8c6e3d48fca 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir_def/types.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir_def/types.rs @@ -6,15 +6,18 @@ use std::{ }; use crate::{ + ast::IntegerBitSize, hir::type_check::TypeCheckError, node_interner::{ExprId, NodeInterner, TraitId, TypeAliasId}, - IntegerBitSize, }; use iter_extended::vecmap; use noirc_errors::{Location, Span}; use noirc_printable_type::PrintableType; -use crate::{node_interner::StructId, Ident, Signedness}; +use crate::{ + ast::{Ident, Signedness}, + node_interner::StructId, +}; use super::expr::{HirCallExpression, HirExpression, HirIdent}; @@ -726,6 +729,54 @@ impl Type { } } + /// True if this type can be used as a parameter to an ACIR function that is not `main` or a contract function. + /// This encapsulates functions for which we may not want to inline during compilation. + /// + /// The inputs allowed for a function entry point differ from those allowed as input to a program as there are + /// certain types which through compilation we know what their size should be. + /// This includes types such as numeric generics. + pub(crate) fn is_valid_non_inlined_function_input(&self) -> bool { + match self { + // Type::Error is allowed as usual since it indicates an error was already issued and + // we don't need to issue further errors about this likely unresolved type + Type::FieldElement + | Type::Integer(_, _) + | Type::Bool + | Type::Unit + | Type::Constant(_) + | Type::TypeVariable(_, _) + | Type::NamedGeneric(_, _) + | Type::Error => true, + + Type::FmtString(_, _) + // To enable this we would need to determine the size of the closure outputs at compile-time. + // This is possible as long as the output size is not dependent upon a witness condition. + | Type::Function(_, _, _) + | Type::Slice(_) + | Type::MutableReference(_) + | Type::Forall(_, _) + // TODO: probably can allow code as it is all compile time + | Type::Code + | Type::TraitAsType(..) => false, + + Type::Alias(alias, generics) => { + let alias = alias.borrow(); + alias.get_type(generics).is_valid_non_inlined_function_input() + } + + Type::Array(length, element) => { + length.is_valid_non_inlined_function_input() && element.is_valid_non_inlined_function_input() + } + Type::String(length) => length.is_valid_non_inlined_function_input(), + Type::Tuple(elements) => elements.iter().all(|elem| elem.is_valid_non_inlined_function_input()), + Type::Struct(definition, generics) => definition + .borrow() + .get_fields(generics) + .into_iter() + .all(|(_, field)| field.is_valid_non_inlined_function_input()), + } + } + /// Returns the number of `Forall`-quantified type variables on this type. /// Returns 0 if this is not a Type::Forall pub fn generic_count(&self) -> usize { diff --git a/noir/noir-repo/compiler/noirc_frontend/src/lexer/token.rs b/noir/noir-repo/compiler/noirc_frontend/src/lexer/token.rs index 86f26fd1c97..ec513d55299 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/lexer/token.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/lexer/token.rs @@ -412,8 +412,8 @@ impl Token { [Plus, Minus, Star, Slash, Percent, Ampersand, Caret, ShiftLeft, ShiftRight, Pipe] } - pub fn try_into_binary_op(self, span: Span) -> Option> { - use crate::BinaryOpKind::*; + pub fn try_into_binary_op(self, span: Span) -> Option> { + use crate::ast::BinaryOpKind::*; let binary_op = match self { Token::Plus => Add, Token::Ampersand => And, @@ -659,7 +659,6 @@ impl Attribute { ["contract_library_method"] => { Attribute::Secondary(SecondaryAttribute::ContractLibraryMethod) } - ["event"] => Attribute::Secondary(SecondaryAttribute::Event), ["abi", tag] => Attribute::Secondary(SecondaryAttribute::Abi(tag.to_string())), ["export"] => Attribute::Secondary(SecondaryAttribute::Export), ["deprecated", name] => { @@ -751,7 +750,6 @@ pub enum SecondaryAttribute { // is a helper method for a contract and should not be seen as // the entry point. ContractLibraryMethod, - Event, Export, Field(String), Custom(String), @@ -767,7 +765,6 @@ impl fmt::Display for SecondaryAttribute { } SecondaryAttribute::Custom(ref k) => write!(f, "#[{k}]"), SecondaryAttribute::ContractLibraryMethod => write!(f, "#[contract_library_method]"), - SecondaryAttribute::Event => write!(f, "#[event]"), SecondaryAttribute::Export => write!(f, "#[export]"), SecondaryAttribute::Field(ref k) => write!(f, "#[field({k})]"), SecondaryAttribute::Abi(ref k) => write!(f, "#[abi({k})]"), @@ -797,7 +794,7 @@ impl AsRef for SecondaryAttribute { | SecondaryAttribute::Field(string) | SecondaryAttribute::Abi(string) => string, SecondaryAttribute::ContractLibraryMethod => "", - SecondaryAttribute::Event | SecondaryAttribute::Export => "", + SecondaryAttribute::Export => "", } } } @@ -839,6 +836,7 @@ pub enum Keyword { ReturnData, String, Struct, + Super, Trait, Type, Unchecked, @@ -883,6 +881,7 @@ impl fmt::Display for Keyword { Keyword::ReturnData => write!(f, "return_data"), Keyword::String => write!(f, "str"), Keyword::Struct => write!(f, "struct"), + Keyword::Super => write!(f, "super"), Keyword::Trait => write!(f, "trait"), Keyword::Type => write!(f, "type"), Keyword::Unchecked => write!(f, "unchecked"), @@ -930,6 +929,7 @@ impl Keyword { "return_data" => Keyword::ReturnData, "str" => Keyword::String, "struct" => Keyword::Struct, + "super" => Keyword::Super, "trait" => Keyword::Trait, "type" => Keyword::Type, "unchecked" => Keyword::Unchecked, diff --git a/noir/noir-repo/compiler/noirc_frontend/src/lib.rs b/noir/noir-repo/compiler/noirc_frontend/src/lib.rs index 93d7960faf5..6c77e3d0545 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/lib.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/lib.rs @@ -28,9 +28,6 @@ pub use lexer::token; // Parser API pub use parser::{parse_program, ParsedModule}; -// AST API -pub use ast::*; - // Type API pub use hir_def::types::*; @@ -52,17 +49,18 @@ pub mod macros_api { pub use crate::parser::{parse_program, SortedModule}; pub use crate::token::SecondaryAttribute; - pub use crate::hir::def_map::ModuleDefId; - pub use crate::{ - hir::Context as HirContext, BlockExpression, CallExpression, CastExpression, Distinctness, - Expression, ExpressionKind, FunctionReturnType, Ident, IndexExpression, ItemVisibility, - LetStatement, Literal, MemberAccessExpression, MethodCallExpression, NoirFunction, Path, - PathKind, Pattern, Statement, UnresolvedType, UnresolvedTypeData, Visibility, + pub use crate::ast::{ + BlockExpression, CallExpression, CastExpression, Distinctness, Expression, ExpressionKind, + FunctionReturnType, Ident, IndexExpression, ItemVisibility, LetStatement, Literal, + MemberAccessExpression, MethodCallExpression, NoirFunction, Path, PathKind, Pattern, + Statement, UnresolvedType, UnresolvedTypeData, Visibility, }; - pub use crate::{ + pub use crate::ast::{ ForLoopStatement, ForRange, FunctionDefinition, ImportStatement, NoirStruct, Param, - PrefixExpression, Signedness, StatementKind, StructType, Type, TypeImpl, UnaryOp, + PrefixExpression, Signedness, StatementKind, TypeImpl, UnaryOp, }; + pub use crate::hir::{def_map::ModuleDefId, Context as HirContext}; + pub use crate::{StructType, Type}; /// Methods to process the AST before and after type checking pub trait MacroProcessor { diff --git a/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/ast.rs b/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/ast.rs index d9c33d8604e..434cc922a05 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/ast.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/ast.rs @@ -5,10 +5,8 @@ use noirc_errors::{ Location, }; -use crate::{ - hir_def::function::FunctionSignature, BinaryOpKind, Distinctness, IntegerBitSize, Signedness, - Visibility, -}; +use crate::ast::{BinaryOpKind, Distinctness, IntegerBitSize, Signedness, Visibility}; +use crate::hir_def::function::FunctionSignature; /// The monomorphized AST is expression-based, all statements are also /// folded into this expression enum. Compared to the HIR, the monomorphized @@ -99,7 +97,7 @@ pub enum Literal { #[derive(Debug, Clone, Hash)] pub struct Unary { - pub operator: crate::UnaryOp, + pub operator: crate::ast::UnaryOp, pub rhs: Box, pub result_type: Type, pub location: Location, diff --git a/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs index 4e779244d30..74a0dd855c0 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs @@ -8,6 +8,7 @@ //! //! The entry point to this pass is the `monomorphize` function which, starting from a given //! function, will monomorphize the entire reachable program. +use crate::ast::{FunctionKind, IntegerBitSize, Signedness, UnaryOp, Visibility}; use crate::{ debug::DebugInstrumenter, hir_def::{ @@ -18,8 +19,7 @@ use crate::{ }, node_interner::{self, DefinitionKind, NodeInterner, StmtId, TraitImplKind, TraitMethodId}, token::FunctionAttribute, - FunctionKind, IntegerBitSize, Signedness, Type, TypeBinding, TypeBindings, TypeVariable, - TypeVariableKind, UnaryOp, Visibility, + Type, TypeBinding, TypeBindings, TypeVariable, TypeVariableKind, }; use acvm::FieldElement; use iter_extended::{btree_map, try_vecmap, vecmap}; @@ -283,12 +283,18 @@ impl<'interner> Monomorphizer<'interner> { } let meta = self.interner.function_meta(&f).clone(); - let func_sig = meta.function_signature(); + let mut func_sig = meta.function_signature(); + // Follow the bindings of the function signature for entry points + // which are not `main` such as foldable functions. + for param in func_sig.0.iter_mut() { + param.1 = param.1.follow_bindings(); + } + func_sig.1 = func_sig.1.map(|return_type| return_type.follow_bindings()); let modifiers = self.interner.function_modifiers(&f); let name = self.interner.function_name(&f).to_owned(); - let body_expr_id = *self.interner.function(&f).as_expr(); + let body_expr_id = self.interner.function(&f).as_expr(); let body_return_type = self.interner.id_type(body_expr_id); let return_type = match meta.return_type() { Type::TraitAsType(..) => &body_return_type, @@ -454,7 +460,7 @@ impl<'interner> Monomorphizer<'interner> { // If this is a comparison operator, the result is a boolean but // the actual method call returns an Ordering - use crate::BinaryOpKind::*; + use crate::ast::BinaryOpKind::*; let ret = if matches!(operator, Less | LessEqual | Greater | GreaterEqual) { self.interner.ordering_type() } else { @@ -618,6 +624,9 @@ impl<'interner> Monomorphizer<'interner> { HirStatement::Break => Ok(ast::Expression::Break), HirStatement::Continue => Ok(ast::Expression::Continue), HirStatement::Error => unreachable!(), + + // All `comptime` statements & expressions should be removed before runtime. + HirStatement::Comptime(_) => unreachable!("comptime statement in runtime code"), } } @@ -1259,7 +1268,7 @@ impl<'interner> Monomorphizer<'interner> { ) -> ast::Expression { use ast::*; - let int_type = Type::Integer(crate::Signedness::Unsigned, arr_elem_bits); + let int_type = Type::Integer(crate::ast::Signedness::Unsigned, arr_elem_bits); let bytes_as_expr = vecmap(bytes, |byte| { Expression::Literal(Literal::Integer((byte as u128).into(), int_type.clone(), location)) @@ -1588,7 +1597,7 @@ impl<'interner> Monomorphizer<'interner> { })) } ast::Type::MutableReference(element) => { - use crate::UnaryOp::MutableReference; + use crate::ast::UnaryOp::MutableReference; let rhs = Box::new(self.zeroed_value_of_type(element, location)); let result_type = typ.clone(); ast::Expression::Unary(ast::Unary { @@ -1673,7 +1682,7 @@ impl<'interner> Monomorphizer<'interner> { let mut result = ast::Expression::Call(ast::Call { func, arguments, return_type, location }); - use crate::BinaryOpKind::*; + use crate::ast::BinaryOpKind::*; match operator.kind { // Negate the result of the == operation NotEqual => { diff --git a/noir/noir-repo/compiler/noirc_frontend/src/node_interner.rs b/noir/noir-repo/compiler/noirc_frontend/src/node_interner.rs index 153c7e45d4a..b0e68be4868 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/node_interner.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/node_interner.rs @@ -16,6 +16,7 @@ use crate::hir::def_collector::dc_crate::CompilationError; use crate::hir::def_collector::dc_crate::{UnresolvedStruct, UnresolvedTrait, UnresolvedTypeAlias}; use crate::hir::def_map::{LocalModuleId, ModuleId}; +use crate::ast::{BinaryOpKind, FunctionDefinition, ItemVisibility}; use crate::hir::resolution::errors::ResolverError; use crate::hir_def::stmt::HirLetStatement; use crate::hir_def::traits::TraitImpl; @@ -28,8 +29,7 @@ use crate::hir_def::{ }; use crate::token::{Attributes, SecondaryAttribute}; use crate::{ - BinaryOpKind, FunctionDefinition, Generics, ItemVisibility, Shared, TypeAlias, TypeBindings, - TypeVariable, TypeVariableId, TypeVariableKind, + Generics, Shared, TypeAlias, TypeBindings, TypeVariable, TypeVariableId, TypeVariableKind, }; /// An arbitrary number to limit the recursion depth when searching for trait impls. @@ -242,6 +242,8 @@ pub struct FunctionModifiers { pub attributes: Attributes, pub is_unconstrained: bool, + + pub is_comptime: bool, } impl FunctionModifiers { @@ -254,6 +256,7 @@ impl FunctionModifiers { visibility: ItemVisibility::Public, attributes: Attributes::empty(), is_unconstrained: false, + is_comptime: false, } } } @@ -759,6 +762,7 @@ impl NodeInterner { visibility: function.visibility, attributes: function.attributes.clone(), is_unconstrained: function.is_unconstrained, + is_comptime: function.is_comptime, }; self.push_function_definition(id, modifiers, module, location) } @@ -818,10 +822,10 @@ impl NodeInterner { self.func_meta.get(func_id) } - pub fn function_ident(&self, func_id: &FuncId) -> crate::Ident { + pub fn function_ident(&self, func_id: &FuncId) -> crate::ast::Ident { let name = self.function_name(func_id).to_owned(); let span = self.function_meta(func_id).name.location.span; - crate::Ident(Spanned::from(span, name)) + crate::ast::Ident(Spanned::from(span, name)) } pub fn function_name(&self, func_id: &FuncId) -> &str { diff --git a/noir/noir-repo/compiler/noirc_frontend/src/noir_parser.lalrpop b/noir/noir-repo/compiler/noirc_frontend/src/noir_parser.lalrpop index c8d293fb72f..ec2b4c8ab46 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/noir_parser.lalrpop +++ b/noir/noir-repo/compiler/noirc_frontend/src/noir_parser.lalrpop @@ -4,7 +4,7 @@ use crate::lexer::token::BorrowedToken; use crate::lexer::token as noir_token; use crate::lexer::errors::LexerErrorKind; use crate::parser::TopLevelStatement; -use crate::{Ident, Path, PathKind, UseTree, UseTreeKind}; +use crate::ast::{Ident, Path, PathKind, UseTree, UseTreeKind}; use lalrpop_util::ErrorRecovery; diff --git a/noir/noir-repo/compiler/noirc_frontend/src/parser/errors.rs b/noir/noir-repo/compiler/noirc_frontend/src/parser/errors.rs index 895d4e07bbd..407b69c818b 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/parser/errors.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/parser/errors.rs @@ -1,7 +1,6 @@ +use crate::ast::{Expression, IntegerBitSize}; use crate::lexer::errors::LexerErrorKind; use crate::lexer::token::Token; -use crate::Expression; -use crate::IntegerBitSize; use small_ord_set::SmallOrdSet; use thiserror::Error; diff --git a/noir/noir-repo/compiler/noirc_frontend/src/parser/mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/parser/mod.rs index 80c5f47f07b..9e60383afee 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/parser/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/parser/mod.rs @@ -11,12 +11,11 @@ mod labels; #[allow(clippy::module_inception)] mod parser; -use crate::token::{Keyword, Token}; -use crate::{ast::ImportStatement, Expression, NoirStruct}; -use crate::{ - Ident, LetStatement, ModuleDeclaration, NoirFunction, NoirTrait, NoirTraitImpl, NoirTypeAlias, - Recoverable, StatementKind, TypeImpl, UseTree, +use crate::ast::{ + Expression, Ident, ImportStatement, LetStatement, ModuleDeclaration, NoirFunction, NoirStruct, + NoirTrait, NoirTraitImpl, NoirTypeAlias, Recoverable, StatementKind, TypeImpl, UseTree, }; +use crate::token::{Keyword, Token}; use chumsky::prelude::*; use chumsky::primitive::Container; diff --git a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser.rs b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser.rs index 5706c3ef12f..603193d1593 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser.rs @@ -33,17 +33,17 @@ use super::{ }; use super::{spanned, Item, ItemKind}; use crate::ast::{ - Expression, ExpressionKind, LetStatement, StatementKind, UnresolvedType, UnresolvedTypeData, -}; -use crate::lexer::{lexer::from_spanned_token_result, Lexer}; -use crate::parser::{force, ignore_then_commit, statement_recovery}; -use crate::token::{Keyword, Token, TokenKind}; -use crate::{ BinaryOp, BinaryOpKind, BlockExpression, Distinctness, ForLoopStatement, ForRange, FunctionReturnType, Ident, IfExpression, InfixExpression, LValue, Literal, ModuleDeclaration, NoirTypeAlias, Param, Path, Pattern, Recoverable, Statement, TraitBound, TypeImpl, UnresolvedTraitConstraint, UnresolvedTypeExpression, UseTree, UseTreeKind, Visibility, }; +use crate::ast::{ + Expression, ExpressionKind, LetStatement, StatementKind, UnresolvedType, UnresolvedTypeData, +}; +use crate::lexer::{lexer::from_spanned_token_result, Lexer}; +use crate::parser::{force, ignore_then_commit, statement_recovery}; +use crate::token::{Keyword, Token, TokenKind}; use chumsky::prelude::*; use iter_extended::vecmap; @@ -234,14 +234,16 @@ fn implementation() -> impl NoirParser { /// global_declaration: 'global' ident global_type_annotation '=' literal fn global_declaration() -> impl NoirParser { let p = attributes::attributes() + .then(maybe_comp_time()) .then_ignore(keyword(Keyword::Global).labelled(ParsingRuleLabel::Global)) .then(ident().map(Pattern::Identifier)); + let p = then_commit(p, optional_type_annotation()); let p = then_commit_ignore(p, just(Token::Assign)); let p = then_commit(p, expression()); - p.validate(|(((attributes, pattern), r#type), expression), span, emit| { + p.validate(|((((attributes, comptime), pattern), r#type), expression), span, emit| { let global_attributes = attributes::validate_secondary_attributes(attributes, span, emit); - LetStatement { pattern, r#type, expression, attributes: global_attributes } + LetStatement { pattern, r#type, comptime, expression, attributes: global_attributes } }) .map(TopLevelStatement::Global) } @@ -498,10 +500,11 @@ where assertion::assertion_eq(expr_parser.clone()), declaration(expr_parser.clone()), assignment(expr_parser.clone()), - for_loop(expr_no_constructors, statement), + for_loop(expr_no_constructors.clone(), statement.clone()), break_statement(), continue_statement(), return_statement(expr_parser.clone()), + comptime_statement(expr_parser.clone(), expr_no_constructors, statement), expr_parser.map(StatementKind::Expression), )) }) @@ -519,6 +522,35 @@ fn continue_statement() -> impl NoirParser { keyword(Keyword::Continue).to(StatementKind::Continue) } +fn comptime_statement<'a, P1, P2, S>( + expr: P1, + expr_no_constructors: P2, + statement: S, +) -> impl NoirParser + 'a +where + P1: ExprParser + 'a, + P2: ExprParser + 'a, + S: NoirParser + 'a, +{ + keyword(Keyword::CompTime) + .ignore_then(choice(( + declaration(expr), + for_loop(expr_no_constructors, statement.clone()), + block(statement).map_with_span(|block, span| { + StatementKind::Expression(Expression::new(ExpressionKind::Block(block), span)) + }), + ))) + .map(|statement| StatementKind::Comptime(Box::new(statement))) +} + +/// Comptime in an expression position only accepts entire blocks +fn comptime_expr<'a, S>(statement: S) -> impl NoirParser + 'a +where + S: NoirParser + 'a, +{ + keyword(Keyword::CompTime).ignore_then(block(statement)).map(ExpressionKind::Block) +} + fn declaration<'a, P>(expr_parser: P) -> impl NoirParser + 'a where P: ExprParser + 'a, @@ -700,24 +732,25 @@ fn optional_distinctness() -> impl NoirParser { }) } -fn maybe_comp_time() -> impl NoirParser<()> { +fn maybe_comp_time() -> impl NoirParser { keyword(Keyword::CompTime).or_not().validate(|opt, span, emit| { if opt.is_some() { - emit(ParserError::with_reason(ParserErrorReason::ComptimeDeprecated, span)); + emit(ParserError::with_reason( + ParserErrorReason::ExperimentalFeature("comptime"), + span, + )); } + opt.is_some() }) } fn field_type() -> impl NoirParser { - maybe_comp_time() - .then_ignore(keyword(Keyword::Field)) + keyword(Keyword::Field) .map_with_span(|_, span| UnresolvedTypeData::FieldElement.with_span(span)) } fn bool_type() -> impl NoirParser { - maybe_comp_time() - .then_ignore(keyword(Keyword::Bool)) - .map_with_span(|_, span| UnresolvedTypeData::Bool.with_span(span)) + keyword(Keyword::Bool).map_with_span(|_, span| UnresolvedTypeData::Bool.with_span(span)) } fn string_type() -> impl NoirParser { @@ -744,21 +777,20 @@ fn format_string_type( } fn int_type() -> impl NoirParser { - maybe_comp_time() - .then(filter_map(|span, token: Token| match token { - Token::IntType(int_type) => Ok(int_type), - unexpected => { - Err(ParserError::expected_label(ParsingRuleLabel::IntegerType, unexpected, span)) - } - })) - .validate(|(_, token), span, emit| { - UnresolvedTypeData::from_int_token(token) - .map(|data| data.with_span(span)) - .unwrap_or_else(|err| { - emit(ParserError::with_reason(ParserErrorReason::InvalidBitSize(err.0), span)); - UnresolvedType::error(span) - }) - }) + filter_map(|span, token: Token| match token { + Token::IntType(int_type) => Ok(int_type), + unexpected => { + Err(ParserError::expected_label(ParsingRuleLabel::IntegerType, unexpected, span)) + } + }) + .validate(|token, span, emit| { + UnresolvedTypeData::from_int_token(token).map(|data| data.with_span(span)).unwrap_or_else( + |err| { + emit(ParserError::with_reason(ParserErrorReason::InvalidBitSize(err.0), span)); + UnresolvedType::error(span) + }, + ) + }) } fn named_type(type_parser: impl NoirParser) -> impl NoirParser { @@ -1236,6 +1268,7 @@ where }, lambdas::lambda(expr_parser.clone()), block(statement.clone()).map(ExpressionKind::Block), + comptime_expr(statement.clone()), quote(statement), variable(), literal(), @@ -1320,7 +1353,7 @@ where mod test { use super::test_helpers::*; use super::*; - use crate::ArrayLiteral; + use crate::ast::ArrayLiteral; #[test] fn parse_infix() { diff --git a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/assertion.rs b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/assertion.rs index f9c8d7aa46b..ed08a4c9922 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/assertion.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/assertion.rs @@ -4,8 +4,8 @@ use crate::parser::{ ParserError, ParserErrorReason, }; +use crate::ast::{BinaryOpKind, ConstrainKind, ConstrainStatement, InfixExpression, Recoverable}; use crate::token::{Keyword, Token}; -use crate::{BinaryOpKind, ConstrainKind, ConstrainStatement, InfixExpression, Recoverable}; use chumsky::prelude::*; use noirc_errors::Spanned; @@ -74,11 +74,11 @@ where mod test { use super::*; use crate::{ + ast::Literal, parser::parser::{ expression, test_helpers::{parse_all, parse_all_failing, parse_with}, }, - Literal, }; /// Deprecated constrain usage test diff --git a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/function.rs b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/function.rs index 06e1a958eb1..f39b2ad6292 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/function.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/function.rs @@ -1,16 +1,16 @@ use super::{ attributes::{attributes, validate_attributes}, - block, fresh_statement, ident, keyword, nothing, optional_distinctness, optional_visibility, - parameter_name_recovery, parameter_recovery, parenthesized, parse_type, pattern, - self_parameter, where_clause, NoirParser, + block, fresh_statement, ident, keyword, maybe_comp_time, nothing, optional_distinctness, + optional_visibility, parameter_name_recovery, parameter_recovery, parenthesized, parse_type, + pattern, self_parameter, where_clause, NoirParser, }; -use crate::parser::labels::ParsingRuleLabel; -use crate::parser::spanned; -use crate::token::{Keyword, Token}; -use crate::{ +use crate::ast::{ Distinctness, FunctionDefinition, FunctionReturnType, Ident, ItemVisibility, NoirFunction, Param, Visibility, }; +use crate::parser::labels::ParsingRuleLabel; +use crate::parser::spanned; +use crate::token::{Keyword, Token}; use chumsky::prelude::*; @@ -37,6 +37,7 @@ pub(super) fn function_definition(allow_self: bool) -> impl NoirParser impl NoirParser { /// function_modifiers: 'unconstrained'? (visibility)? /// /// returns (is_unconstrained, visibility) for whether each keyword was present -fn function_modifiers() -> impl NoirParser<(bool, ItemVisibility)> { +fn function_modifiers() -> impl NoirParser<(bool, ItemVisibility, bool)> { keyword(Keyword::Unconstrained) .or_not() .then(visibility_modifier()) - .map(|(unconstrained, visibility)| (unconstrained.is_some(), visibility)) + .then(maybe_comp_time()) + .map(|((unconstrained, visibility), comptime)| { + (unconstrained.is_some(), visibility, comptime) + }) } /// non_empty_ident_list: ident ',' non_empty_ident_list @@ -171,8 +175,8 @@ mod test { "fn f(f: pub Field, y : T, z : Field) -> u8 { x + a }", "fn func_name(x: [Field], y : [Field;2],y : pub [Field;2], z : pub [u8;5]) {}", "fn main(x: pub u8, y: pub u8) -> distinct pub [u8; 2] { [x, y] }", - "fn f(f: pub Field, y : Field, z : comptime Field) -> u8 { x + a }", - "fn f(f: pub Field, y : T, z : comptime Field) -> u8 { x + a }", + "fn f(f: pub Field, y : Field, z : Field) -> u8 { x + a }", + "fn f(f: pub Field, y : T, z : Field) -> u8 { x + a }", "fn func_name(f: Field, y : T) where T: SomeTrait {}", "fn func_name(f: Field, y : T) where T: SomeTrait + SomeTrait2 {}", "fn func_name(f: Field, y : T) where T: SomeTrait, T: SomeTrait2 {}", diff --git a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/lambdas.rs b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/lambdas.rs index 48ddd41ab44..2b4a1d547c0 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/lambdas.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/lambdas.rs @@ -1,13 +1,12 @@ use chumsky::{primitive::just, Parser}; +use super::{parse_type, pattern}; +use crate::ast::{Expression, ExpressionKind, Lambda, Pattern, UnresolvedType}; use crate::{ parser::{labels::ParsingRuleLabel, parameter_name_recovery, parameter_recovery, NoirParser}, token::Token, - Expression, ExpressionKind, Lambda, Pattern, UnresolvedType, }; -use super::{parse_type, pattern}; - pub(super) fn lambda<'a>( expr_parser: impl NoirParser + 'a, ) -> impl NoirParser + 'a { diff --git a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/literals.rs b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/literals.rs index 83d7b832d27..584224fda46 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/literals.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/literals.rs @@ -1,9 +1,9 @@ use chumsky::Parser; use crate::{ + ast::ExpressionKind, parser::NoirParser, token::{Token, TokenKind}, - ExpressionKind, }; use super::primitives::token_kind; @@ -22,10 +22,10 @@ pub(super) fn literal() -> impl NoirParser { #[cfg(test)] mod test { use super::*; + use crate::ast::Literal; use crate::parser::parser::{ expression, expression_no_constructors, fresh_statement, term, test_helpers::*, }; - use crate::Literal; fn expr_to_lit(expr: ExpressionKind) -> Literal { match expr { diff --git a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/path.rs b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/path.rs index ab812c07dce..47bb11991fa 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/path.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/path.rs @@ -1,5 +1,5 @@ +use crate::ast::{Path, PathKind}; use crate::parser::NoirParser; -use crate::{Path, PathKind}; use crate::token::{Keyword, Token}; diff --git a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/primitives.rs b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/primitives.rs index 34927278038..8413f14ae4d 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/primitives.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/primitives.rs @@ -1,9 +1,9 @@ use chumsky::prelude::*; +use crate::ast::{ExpressionKind, Ident, UnaryOp}; use crate::{ parser::{labels::ParsingRuleLabel, ExprParser, NoirParser, ParserError}, token::{Keyword, Token, TokenKind}, - ExpressionKind, Ident, UnaryOp, }; use super::path; diff --git a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/structs.rs b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/structs.rs index 87e58f69efb..7da956bdfea 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/structs.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/structs.rs @@ -1,5 +1,6 @@ use chumsky::prelude::*; +use crate::ast::{Ident, NoirStruct, UnresolvedType}; use crate::{ parser::{ parser::{ @@ -10,7 +11,6 @@ use crate::{ NoirParser, TopLevelStatement, }, token::{Keyword, Token}, - Ident, NoirStruct, UnresolvedType, }; pub(super) fn struct_definition() -> impl NoirParser { diff --git a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/traits.rs b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/traits.rs index 1e2a6b4d65d..0507dbdbc71 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/traits.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/traits.rs @@ -5,14 +5,16 @@ use super::{ function_return_type, }; +use crate::ast::{ + Expression, ItemVisibility, NoirTrait, NoirTraitImpl, TraitBound, TraitImplItem, TraitItem, + UnresolvedTraitConstraint, UnresolvedType, +}; use crate::{ parser::{ ignore_then_commit, parenthesized, parser::primitives::keyword, NoirParser, ParserError, ParserErrorReason, TopLevelStatement, }, token::{Keyword, Token}, - Expression, ItemVisibility, NoirTrait, NoirTraitImpl, TraitBound, TraitImplItem, TraitItem, - UnresolvedTraitConstraint, UnresolvedType, }; use super::{generic_type_args, parse_type, path, primitives::ident}; diff --git a/noir/noir-repo/compiler/noirc_frontend/src/tests.rs b/noir/noir-repo/compiler/noirc_frontend/src/tests.rs index e4d308fbb6b..31bf2245b1f 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/tests.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/tests.rs @@ -66,7 +66,7 @@ mod test { // Allocate a default Module for the root, giving it a ModuleId let mut modules: Arena = Arena::default(); let location = Location::new(Default::default(), root_file_id); - let root = modules.insert(ModuleData::new(None, None, location, false)); + let root = modules.insert(ModuleData::new(None, location, false)); let def_map = CrateDefMap { root: LocalModuleId(root), @@ -780,6 +780,7 @@ mod test { HirStatement::Error => panic!("Invalid HirStatement!"), HirStatement::Break => panic!("Unexpected break"), HirStatement::Continue => panic!("Unexpected continue"), + HirStatement::Comptime(_) => panic!("Unexpected comptime"), }; let expr = interner.expression(&expr_id); diff --git a/noir/noir-repo/compiler/noirc_printable_type/Cargo.toml b/noir/noir-repo/compiler/noirc_printable_type/Cargo.toml index fbbe778e561..5140f5a5a8c 100644 --- a/noir/noir-repo/compiler/noirc_printable_type/Cargo.toml +++ b/noir/noir-repo/compiler/noirc_printable_type/Cargo.toml @@ -3,6 +3,7 @@ name = "noirc_printable_type" version.workspace = true authors.workspace = true edition.workspace = true +rust-version.workspace = true license.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/noir/noir-repo/compiler/utils/arena/Cargo.toml b/noir/noir-repo/compiler/utils/arena/Cargo.toml index 41c6ebc9a8b..f6bd764ee62 100644 --- a/noir/noir-repo/compiler/utils/arena/Cargo.toml +++ b/noir/noir-repo/compiler/utils/arena/Cargo.toml @@ -3,4 +3,5 @@ name = "arena" version.workspace = true authors.workspace = true edition.workspace = true +rust-version.workspace = true license.workspace = true diff --git a/noir/noir-repo/compiler/utils/iter-extended/Cargo.toml b/noir/noir-repo/compiler/utils/iter-extended/Cargo.toml index c91e5ea6d77..4343311506e 100644 --- a/noir/noir-repo/compiler/utils/iter-extended/Cargo.toml +++ b/noir/noir-repo/compiler/utils/iter-extended/Cargo.toml @@ -3,6 +3,7 @@ name = "iter-extended" version.workspace = true authors.workspace = true edition.workspace = true +rust-version.workspace = true license.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/noir/noir-repo/compiler/wasm/Cargo.toml b/noir/noir-repo/compiler/wasm/Cargo.toml index a20efeeed8a..31ef5161014 100644 --- a/noir/noir-repo/compiler/wasm/Cargo.toml +++ b/noir/noir-repo/compiler/wasm/Cargo.toml @@ -3,6 +3,7 @@ name = "noir_wasm" version.workspace = true authors.workspace = true edition.workspace = true +rust-version.workspace = true license.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/noir/noir-repo/docs/docs/noir/concepts/data_types/slices.mdx b/noir/noir-repo/docs/docs/noir/concepts/data_types/slices.mdx index 828faf4a8f8..4eccc677b80 100644 --- a/noir/noir-repo/docs/docs/noir/concepts/data_types/slices.mdx +++ b/noir/noir-repo/docs/docs/noir/concepts/data_types/slices.mdx @@ -168,3 +168,28 @@ fn main() { assert(slice.len() == 2); } ``` + +### as_array + +Converts this slice into an array. + +Make sure to specify the size of the resulting array. +Panics if the resulting array length is different than the slice's length. + +```rust +fn as_array(self) -> [T; N] +``` + +Example: + +```rust +fn main() { + let slice = &[5, 6]; + + // Always specify the length of the resulting array! + let array: [Field; 2] = slice.as_array(); + + assert(array[0] == slice[0]); + assert(array[1] == slice[1]); +} +``` diff --git a/noir/noir-repo/docs/docs/noir/standard_library/containers/hashmap.md b/noir/noir-repo/docs/docs/noir/standard_library/containers/hashmap.md index 093b6d38d11..2b9f4895722 100644 --- a/noir/noir-repo/docs/docs/noir/standard_library/containers/hashmap.md +++ b/noir/noir-repo/docs/docs/noir/standard_library/containers/hashmap.md @@ -20,8 +20,9 @@ Example: ```rust // Create a mapping from Fields to u32s with a maximum length of 12 -// using a pedersen hash -let mut map: HashMap> = HashMap::default(); +// using a poseidon2 hasher +use dep::std::hash::poseidon2::Poseidon2Hasher; +let mut map: HashMap> = HashMap::default(); map.insert(1, 2); map.insert(3, 4); diff --git a/noir/noir-repo/docs/docs/noir/standard_library/cryptographic_primitives/hashes.mdx b/noir/noir-repo/docs/docs/noir/standard_library/cryptographic_primitives/hashes.mdx index f98c90a97c8..7329880c7a7 100644 --- a/noir/noir-repo/docs/docs/noir/standard_library/cryptographic_primitives/hashes.mdx +++ b/noir/noir-repo/docs/docs/noir/standard_library/cryptographic_primitives/hashes.mdx @@ -13,7 +13,6 @@ import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; ## sha256 Given an array of bytes, returns the resulting sha256 hash. -See sha256_slice for a version that works directly on slices. #include_code sha256 noir_stdlib/src/hash.nr rust @@ -28,18 +27,9 @@ fn main() { -## sha256_slice - -A version of sha256 specialized to slices: - -#include_code sha256_slice noir_stdlib/src/hash.nr rust - - - ## blake2s Given an array of bytes, returns an array with the Blake2 hash -See blake2s_slice for a version that works directly on slices. #include_code blake2s noir_stdlib/src/hash.nr rust @@ -54,18 +44,9 @@ fn main() { -## blake2s_slice - -A version of blake2s specialized to slices: - -#include_code blake2s_slice noir_stdlib/src/hash.nr rust - - - ## blake3 Given an array of bytes, returns an array with the Blake3 hash -See blake3_slice for a version that works directly on slices. #include_code blake3 noir_stdlib/src/hash.nr rust @@ -80,18 +61,9 @@ fn main() { -## blake3_slice - -A version of blake3 specialized to slices: - -#include_code blake3_slice noir_stdlib/src/hash.nr rust - - - ## pedersen_hash Given an array of Fields, returns the Pedersen hash. -See pedersen_hash_slice for a version that works directly on slices. #include_code pedersen_hash noir_stdlib/src/hash.nr rust @@ -101,18 +73,9 @@ example: -## pedersen_hash_slice - -Given a slice of Fields, returns the Pedersen hash. - -#include_code pedersen_hash_slice noir_stdlib/src/hash.nr rust - - - ## pedersen_commitment Given an array of Fields, returns the Pedersen commitment. -See pedersen_commitment_slice for a version that works directly on slices. #include_code pedersen_commitment noir_stdlib/src/hash.nr rust @@ -122,20 +85,11 @@ example: -## pedersen_commitment_slice - -Given a slice of Fields, returns the Pedersen commitment. - -#include_code pedersen_commitment_slice noir_stdlib/src/hash.nr rust - - - ## keccak256 Given an array of bytes (`u8`), returns the resulting keccak hash as an array of 32 bytes (`[u8; 32]`). Specify a message_size to hash only the first -`message_size` bytes of the input. See keccak256_slice for a version that works -directly on slices. +`message_size` bytes of the input. #include_code keccak256 noir_stdlib/src/hash.nr rust @@ -145,15 +99,6 @@ example: -## keccak256_slice - -Given a slice of bytes (`u8`), returns the resulting keccak hash as an array of -32 bytes (`[u8; 32]`). - -#include_code keccak256_slice noir_stdlib/src/hash.nr rust - - - ## poseidon Given an array of Fields, returns a new Field with the Poseidon Hash. Mind that you need to specify diff --git a/noir/noir-repo/docs/docs/noir/standard_library/traits.md b/noir/noir-repo/docs/docs/noir/standard_library/traits.md index e6e7e6d40cb..2536d9a943f 100644 --- a/noir/noir-repo/docs/docs/noir/standard_library/traits.md +++ b/noir/noir-repo/docs/docs/noir/standard_library/traits.md @@ -140,6 +140,8 @@ impl Eq for (A, B, C, D, E) Implementing this trait on a type allows `<`, `<=`, `>`, and `>=` to be used on values of the type. +`std::cmp` also provides `max` and `min` functions for any type which implements the `Ord` trait. + Implementations: ```rust diff --git a/noir/noir-repo/docs/docs/tutorials/noirjs_app.md b/noir/noir-repo/docs/docs/tutorials/noirjs_app.md index 12beb476994..6446e0b2a76 100644 --- a/noir/noir-repo/docs/docs/tutorials/noirjs_app.md +++ b/noir/noir-repo/docs/docs/tutorials/noirjs_app.md @@ -14,9 +14,9 @@ You can find the complete app code for this guide [here](https://github.com/noir :::note -Feel free to use whatever versions, just keep in mind that Nargo and the NoirJS packages are meant to be in sync. For example, Nargo 0.19.x matches `noir_js@0.19.x`, etc. +Feel free to use whatever versions, just keep in mind that Nargo and the NoirJS packages are meant to be in sync. For example, Nargo 0.27.x matches `noir_js@0.27.x`, etc. -In this guide, we will be pinned to 0.19.4. +In this guide, we will be pinned to 0.27.0. ::: @@ -34,7 +34,7 @@ Easy enough. Onwards! ## Our project -ZK is a powerful technology. An app that doesn't reveal one of the inputs to *anyone* is almost unbelievable, yet Noir makes it as easy as a single line of code. +ZK is a powerful technology. An app that doesn't reveal one of the inputs to _anyone_ is almost unbelievable, yet Noir makes it as easy as a single line of code. In fact, it's so simple that it comes nicely packaged in `nargo`. Let's do that! @@ -42,13 +42,13 @@ In fact, it's so simple that it comes nicely packaged in `nargo`. Let's do that! Run: -```nargo new circuit``` +`nargo new circuit` And... That's about it. Your program is ready to be compiled and run. To compile, let's `cd` into the `circuit` folder to enter our project, and call: -```nargo compile``` +`nargo compile` This compiles our circuit into `json` format and add it to a new `target` folder. @@ -77,10 +77,55 @@ Vite is a powerful tool to generate static websites. While it provides all kinds To do this this, go back to the previous folder (`cd ..`) and create a new vite project by running `npm create vite` and choosing "Vanilla" and "Javascript". -You should see `vite-project` appear in your root folder. This seems like a good time to `cd` into it and install our NoirJS packages: +A wild `vite-project` directory should now appear in your root folder! Let's not waste any time and dive right in: ```bash -npm i @noir-lang/backend_barretenberg@0.19.4 @noir-lang/noir_js@0.19.4 +cd vite-project +``` + +### Setting Up Vite and Configuring the Project + +Before we proceed with any coding, let's get our environment tailored for Noir. We'll start by laying down the foundations with a `vite.config.js` file. This little piece of configuration is our secret sauce for making sure everything meshes well with the NoirJS libraries and other special setups we might need, like handling WebAssembly modules. Here’s how you get that going: + +#### Creating the vite.config.js + +In your freshly minted `vite-project` folder, create a new file named `vite.config.js` and open it in your code editor. Paste the following to set the stage: + +```javascript +import { defineConfig } from "vite"; +import copy from "rollup-plugin-copy"; + +export default defineConfig({ + esbuild: { + target: "esnext", + }, + optimizeDeps: { + esbuildOptions: { + target: "esnext", + }, + }, + plugins: [ + copy({ + targets: [ + { src: "node_modules/**/*.wasm", dest: "node_modules/.vite/dist" }, + ], + copySync: true, + hook: "buildStart", + }), + ], + server: { + port: 3000, + }, +}); +``` + +#### Install Dependencies + +Now that our stage is set, install the necessary NoirJS packages along with our other dependencies: + +```bash +npm install && npm install @noir-lang/backend_barretenberg@0.27.0 @noir-lang/noir_js@0.27.0 +npm install rollup-plugin-copy --save-dev ``` :::info @@ -99,7 +144,7 @@ At this point in the tutorial, your folder structure should look like this: #### Some cleanup -`npx create vite` is amazing but it creates a bunch of files we don't really need for our simple example. Actually, let's just delete everything except for `index.html`, `main.js` and `package.json`. I feel lighter already. +`npx create vite` is amazing but it creates a bunch of files we don't really need for our simple example. Actually, let's just delete everything except for `vite.config.js`, `index.html`, `main.js` and `package.json`. I feel lighter already. ![my heart is ready for you, noir.js](@site/static/img/memes/titanic.jpeg) @@ -139,7 +184,7 @@ Our app won't run like this, of course. We need some working HTML, at least. Let ``` -It *could* be a beautiful UI... Depending on which universe you live in. +It _could_ be a beautiful UI... Depending on which universe you live in. ## Some good old vanilla Javascript @@ -150,14 +195,14 @@ Start by pasting in this boilerplate code: ```js const setup = async () => { await Promise.all([ - import("@noir-lang/noirc_abi").then(module => - module.default(new URL("@noir-lang/noirc_abi/web/noirc_abi_wasm_bg.wasm", import.meta.url).toString()) + import('@noir-lang/noirc_abi').then((module) => + module.default(new URL('@noir-lang/noirc_abi/web/noirc_abi_wasm_bg.wasm', import.meta.url).toString()), + ), + import('@noir-lang/acvm_js').then((module) => + module.default(new URL('@noir-lang/acvm_js/web/acvm_js_bg.wasm', import.meta.url).toString()), ), - import("@noir-lang/acvm_js").then(module => - module.default(new URL("@noir-lang/acvm_js/web/acvm_js_bg.wasm", import.meta.url).toString()) - ) ]); -} +}; function display(container, msg) { const c = document.getElementById(container); @@ -169,11 +214,10 @@ function display(container, msg) { document.getElementById('submitGuess').addEventListener('click', async () => { try { // here's where love happens - } catch(err) { - display("logs", "Oh 💔 Wrong guess") + } catch (err) { + display('logs', 'Oh 💔 Wrong guess'); } }); - ``` The display function doesn't do much. We're simply manipulating our website to see stuff happening. For example, if the proof fails, it will simply log a broken heart 😢 @@ -189,6 +233,7 @@ At this point in the tutorial, your folder structure should look like this: └── circuit └── ...same as above └── vite-project + ├── vite.config.js ├── main.js ├── package.json └── index.html @@ -209,7 +254,7 @@ import circuit from '../circuit/target/circuit.json'; [Noir is backend-agnostic](../index.mdx#whats-new-about-noir). We write Noir, but we also need a proving backend. That's why we need to import and instantiate the two dependencies we installed above: `BarretenbergBackend` and `Noir`. Let's import them right below: ```js -import { BarretenbergBackend } from '@noir-lang/backend_barretenberg'; +import { BarretenbergBackend, BarretenbergVerifier as Verifier } from '@noir-lang/backend_barretenberg'; import { Noir } from '@noir-lang/noir_js'; ``` @@ -264,8 +309,10 @@ Time to celebrate, yes! But we shouldn't trust machines so blindly. Let's add th ```js display('logs', 'Verifying proof... ⌛'); -const verification = await noir.verifyProof(proof); -if (verification) display('logs', 'Verifying proof... ✅'); +const verificationKey = await backend.getVerificationKey(); +const verifier = new Verifier(); +const isValid = await verifier.verifyProof(proof, verificationKey); +if (isValid) display('logs', 'Verifying proof... ✅'); ``` You have successfully generated a client-side Noir web app! diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/getting_started/tooling/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/getting_started/tooling/index.md index 55df833005a..16f5f3ca45e 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/getting_started/tooling/index.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/getting_started/tooling/index.md @@ -1,15 +1,11 @@ --- title: Tooling -Description: This section provides information about the various tools and utilities available for Noir development. It covers the Noir playground, IDE tools, Codespaces, and community projects. +Description: This section provides information about the various tools and utilities available for Noir development. It covers IDE tools, Codespaces, and community projects. Keywords: [Noir, Development, Playground, IDE Tools, Language Service Provider, VS Code Extension, Codespaces, noir-starter, Community Projects, Awesome Noir Repository, Developer Tooling] --- Noir is meant to be easy to develop with. For that reason, a number of utilities have been put together to ease the development process as much as feasible in the zero-knowledge world. -## Playground - -The Noir playground is an easy way to test small ideas, share snippets, and integrate in other websites. You can access it at [play.noir-lang.org](https://play.noir-lang.org). - ## IDE tools When you install Nargo, you're also installing a Language Service Provider (LSP), which can be used by IDEs to provide syntax highlighting, codelens, warnings, and more. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/getting_started/tooling/index.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/getting_started/tooling/index.mdx index ac480f3c9f5..ec9ccea4115 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/getting_started/tooling/index.mdx +++ b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/getting_started/tooling/index.mdx @@ -1,15 +1,11 @@ --- title: Tooling -Description: This section provides information about the various tools and utilities available for Noir development. It covers the Noir playground, IDE tools, Codespaces, and community projects. +Description: This section provides information about the various tools and utilities available for Noir development. It covers IDE tools, Codespaces, and community projects. Keywords: [Noir, Development, Playground, IDE Tools, Language Service Provider, VS Code Extension, Codespaces, noir-starter, Community Projects, Awesome Noir Repository, Developer Tooling] --- Noir is meant to be easy to develop with. For that reason, a number of utilities have been put together to ease the development process as much as feasible in the zero-knowledge world. -## Playground - -The Noir playground is an easy way to test small ideas, share snippets, and integrate in other websites. You can access it at [play.noir-lang.org](https://play.noir-lang.org). - ## IDE tools When you install Nargo, you're also installing a Language Service Provider (LSP), which can be used by IDEs to provide syntax highlighting, codelens, warnings, and more. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/getting_started/tooling/index.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/getting_started/tooling/index.mdx index ac480f3c9f5..ec9ccea4115 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/getting_started/tooling/index.mdx +++ b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/getting_started/tooling/index.mdx @@ -1,15 +1,11 @@ --- title: Tooling -Description: This section provides information about the various tools and utilities available for Noir development. It covers the Noir playground, IDE tools, Codespaces, and community projects. +Description: This section provides information about the various tools and utilities available for Noir development. It covers IDE tools, Codespaces, and community projects. Keywords: [Noir, Development, Playground, IDE Tools, Language Service Provider, VS Code Extension, Codespaces, noir-starter, Community Projects, Awesome Noir Repository, Developer Tooling] --- Noir is meant to be easy to develop with. For that reason, a number of utilities have been put together to ease the development process as much as feasible in the zero-knowledge world. -## Playground - -The Noir playground is an easy way to test small ideas, share snippets, and integrate in other websites. You can access it at [play.noir-lang.org](https://play.noir-lang.org). - ## IDE tools When you install Nargo, you're also installing a Language Service Provider (LSP), which can be used by IDEs to provide syntax highlighting, codelens, warnings, and more. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/tooling/index.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/tooling/index.mdx index ac480f3c9f5..ec9ccea4115 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/tooling/index.mdx +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/tooling/index.mdx @@ -1,15 +1,11 @@ --- title: Tooling -Description: This section provides information about the various tools and utilities available for Noir development. It covers the Noir playground, IDE tools, Codespaces, and community projects. +Description: This section provides information about the various tools and utilities available for Noir development. It covers IDE tools, Codespaces, and community projects. Keywords: [Noir, Development, Playground, IDE Tools, Language Service Provider, VS Code Extension, Codespaces, noir-starter, Community Projects, Awesome Noir Repository, Developer Tooling] --- Noir is meant to be easy to develop with. For that reason, a number of utilities have been put together to ease the development process as much as feasible in the zero-knowledge world. -## Playground - -The Noir playground is an easy way to test small ideas, share snippets, and integrate in other websites. You can access it at [play.noir-lang.org](https://play.noir-lang.org). - ## IDE tools When you install Nargo, you're also installing a Language Service Provider (LSP), which can be used by IDEs to provide syntax highlighting, codelens, warnings, and more. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/tutorials/noirjs_app.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/tutorials/noirjs_app.md index 12beb476994..02044cd2ff6 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/tutorials/noirjs_app.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/tutorials/noirjs_app.md @@ -14,9 +14,9 @@ You can find the complete app code for this guide [here](https://github.com/noir :::note -Feel free to use whatever versions, just keep in mind that Nargo and the NoirJS packages are meant to be in sync. For example, Nargo 0.19.x matches `noir_js@0.19.x`, etc. +Feel free to use whatever versions, just keep in mind that Nargo and the NoirJS packages are meant to be in sync. For example, Nargo 0.25.x matches `noir_js@0.25.x`, etc. -In this guide, we will be pinned to 0.19.4. +In this guide, we will be pinned to 0.25.0. ::: @@ -34,7 +34,7 @@ Easy enough. Onwards! ## Our project -ZK is a powerful technology. An app that doesn't reveal one of the inputs to *anyone* is almost unbelievable, yet Noir makes it as easy as a single line of code. +ZK is a powerful technology. An app that doesn't reveal one of the inputs to _anyone_ is almost unbelievable, yet Noir makes it as easy as a single line of code. In fact, it's so simple that it comes nicely packaged in `nargo`. Let's do that! @@ -42,13 +42,13 @@ In fact, it's so simple that it comes nicely packaged in `nargo`. Let's do that! Run: -```nargo new circuit``` +`nargo new circuit` And... That's about it. Your program is ready to be compiled and run. To compile, let's `cd` into the `circuit` folder to enter our project, and call: -```nargo compile``` +`nargo compile` This compiles our circuit into `json` format and add it to a new `target` folder. @@ -77,10 +77,55 @@ Vite is a powerful tool to generate static websites. While it provides all kinds To do this this, go back to the previous folder (`cd ..`) and create a new vite project by running `npm create vite` and choosing "Vanilla" and "Javascript". -You should see `vite-project` appear in your root folder. This seems like a good time to `cd` into it and install our NoirJS packages: +A wild `vite-project` directory should now appear in your root folder! Let's not waste any time and dive right in: ```bash -npm i @noir-lang/backend_barretenberg@0.19.4 @noir-lang/noir_js@0.19.4 +cd vite-project +``` + +### Setting Up Vite and Configuring the Project + +Before we proceed with any coding, let's get our environment tailored for Noir. We'll start by laying down the foundations with a `vite.config.js` file. This little piece of configuration is our secret sauce for making sure everything meshes well with the NoirJS libraries and other special setups we might need, like handling WebAssembly modules. Here’s how you get that going: + +#### Creating the vite.config.js + +In your freshly minted `vite-project` folder, create a new file named `vite.config.js` and open it in your code editor. Paste the following to set the stage: + +```javascript +import { defineConfig } from "vite"; +import copy from "rollup-plugin-copy"; + +export default defineConfig({ + esbuild: { + target: "esnext", + }, + optimizeDeps: { + esbuildOptions: { + target: "esnext", + }, + }, + plugins: [ + copy({ + targets: [ + { src: "node_modules/**/*.wasm", dest: "node_modules/.vite/dist" }, + ], + copySync: true, + hook: "buildStart", + }), + ], + server: { + port: 3000, + }, +}); +``` + +#### Install Dependencies + +Now that our stage is set, install the necessary NoirJS packages along with our other dependencies: + +```bash +npm install && npm install @noir-lang/backend_barretenberg@0.25.0 @noir-lang/noir_js@0.25.0 +npm install rollup-plugin-copy --save-dev ``` :::info @@ -99,7 +144,7 @@ At this point in the tutorial, your folder structure should look like this: #### Some cleanup -`npx create vite` is amazing but it creates a bunch of files we don't really need for our simple example. Actually, let's just delete everything except for `index.html`, `main.js` and `package.json`. I feel lighter already. +`npx create vite` is amazing but it creates a bunch of files we don't really need for our simple example. Actually, let's just delete everything except for `vite.config.js`, `index.html`, `main.js` and `package.json`. I feel lighter already. ![my heart is ready for you, noir.js](@site/static/img/memes/titanic.jpeg) @@ -139,7 +184,7 @@ Our app won't run like this, of course. We need some working HTML, at least. Let ``` -It *could* be a beautiful UI... Depending on which universe you live in. +It _could_ be a beautiful UI... Depending on which universe you live in. ## Some good old vanilla Javascript @@ -150,14 +195,14 @@ Start by pasting in this boilerplate code: ```js const setup = async () => { await Promise.all([ - import("@noir-lang/noirc_abi").then(module => - module.default(new URL("@noir-lang/noirc_abi/web/noirc_abi_wasm_bg.wasm", import.meta.url).toString()) + import('@noir-lang/noirc_abi').then((module) => + module.default(new URL('@noir-lang/noirc_abi/web/noirc_abi_wasm_bg.wasm', import.meta.url).toString()), + ), + import('@noir-lang/acvm_js').then((module) => + module.default(new URL('@noir-lang/acvm_js/web/acvm_js_bg.wasm', import.meta.url).toString()), ), - import("@noir-lang/acvm_js").then(module => - module.default(new URL("@noir-lang/acvm_js/web/acvm_js_bg.wasm", import.meta.url).toString()) - ) ]); -} +}; function display(container, msg) { const c = document.getElementById(container); @@ -169,11 +214,10 @@ function display(container, msg) { document.getElementById('submitGuess').addEventListener('click', async () => { try { // here's where love happens - } catch(err) { - display("logs", "Oh 💔 Wrong guess") + } catch (err) { + display('logs', 'Oh 💔 Wrong guess'); } }); - ``` The display function doesn't do much. We're simply manipulating our website to see stuff happening. For example, if the proof fails, it will simply log a broken heart 😢 @@ -189,6 +233,7 @@ At this point in the tutorial, your folder structure should look like this: └── circuit └── ...same as above └── vite-project + └── vite.config.js ├── main.js ├── package.json └── index.html diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/getting_started/tooling/index.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/getting_started/tooling/index.mdx index ac480f3c9f5..ec9ccea4115 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/getting_started/tooling/index.mdx +++ b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/getting_started/tooling/index.mdx @@ -1,15 +1,11 @@ --- title: Tooling -Description: This section provides information about the various tools and utilities available for Noir development. It covers the Noir playground, IDE tools, Codespaces, and community projects. +Description: This section provides information about the various tools and utilities available for Noir development. It covers IDE tools, Codespaces, and community projects. Keywords: [Noir, Development, Playground, IDE Tools, Language Service Provider, VS Code Extension, Codespaces, noir-starter, Community Projects, Awesome Noir Repository, Developer Tooling] --- Noir is meant to be easy to develop with. For that reason, a number of utilities have been put together to ease the development process as much as feasible in the zero-knowledge world. -## Playground - -The Noir playground is an easy way to test small ideas, share snippets, and integrate in other websites. You can access it at [play.noir-lang.org](https://play.noir-lang.org). - ## IDE tools When you install Nargo, you're also installing a Language Service Provider (LSP), which can be used by IDEs to provide syntax highlighting, codelens, warnings, and more. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/tutorials/noirjs_app.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/tutorials/noirjs_app.md index 12beb476994..d098827e6d9 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/tutorials/noirjs_app.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/tutorials/noirjs_app.md @@ -14,9 +14,9 @@ You can find the complete app code for this guide [here](https://github.com/noir :::note -Feel free to use whatever versions, just keep in mind that Nargo and the NoirJS packages are meant to be in sync. For example, Nargo 0.19.x matches `noir_js@0.19.x`, etc. +Feel free to use whatever versions, just keep in mind that Nargo and the NoirJS packages are meant to be in sync. For example, Nargo 0.26.x matches `noir_js@0.26.x`, etc. -In this guide, we will be pinned to 0.19.4. +In this guide, we will be pinned to 0.26.0. ::: @@ -34,7 +34,7 @@ Easy enough. Onwards! ## Our project -ZK is a powerful technology. An app that doesn't reveal one of the inputs to *anyone* is almost unbelievable, yet Noir makes it as easy as a single line of code. +ZK is a powerful technology. An app that doesn't reveal one of the inputs to _anyone_ is almost unbelievable, yet Noir makes it as easy as a single line of code. In fact, it's so simple that it comes nicely packaged in `nargo`. Let's do that! @@ -42,13 +42,13 @@ In fact, it's so simple that it comes nicely packaged in `nargo`. Let's do that! Run: -```nargo new circuit``` +`nargo new circuit` And... That's about it. Your program is ready to be compiled and run. To compile, let's `cd` into the `circuit` folder to enter our project, and call: -```nargo compile``` +`nargo compile` This compiles our circuit into `json` format and add it to a new `target` folder. @@ -77,10 +77,55 @@ Vite is a powerful tool to generate static websites. While it provides all kinds To do this this, go back to the previous folder (`cd ..`) and create a new vite project by running `npm create vite` and choosing "Vanilla" and "Javascript". -You should see `vite-project` appear in your root folder. This seems like a good time to `cd` into it and install our NoirJS packages: +A wild `vite-project` directory should now appear in your root folder! Let's not waste any time and dive right in: ```bash -npm i @noir-lang/backend_barretenberg@0.19.4 @noir-lang/noir_js@0.19.4 +cd vite-project +``` + +### Setting Up Vite and Configuring the Project + +Before we proceed with any coding, let's get our environment tailored for Noir. We'll start by laying down the foundations with a `vite.config.js` file. This little piece of configuration is our secret sauce for making sure everything meshes well with the NoirJS libraries and other special setups we might need, like handling WebAssembly modules. Here’s how you get that going: + +#### Creating the vite.config.js + +In your freshly minted `vite-project` folder, create a new file named `vite.config.js` and open it in your code editor. Paste the following to set the stage: + +```javascript +import { defineConfig } from "vite"; +import copy from "rollup-plugin-copy"; + +export default defineConfig({ + esbuild: { + target: "esnext", + }, + optimizeDeps: { + esbuildOptions: { + target: "esnext", + }, + }, + plugins: [ + copy({ + targets: [ + { src: "node_modules/**/*.wasm", dest: "node_modules/.vite/dist" }, + ], + copySync: true, + hook: "buildStart", + }), + ], + server: { + port: 3000, + }, +}); +``` + +#### Install Dependencies + +Now that our stage is set, install the necessary NoirJS packages along with our other dependencies: + +```bash +npm install && npm install @noir-lang/backend_barretenberg@0.26.0 @noir-lang/noir_js@0.26.0 +npm install rollup-plugin-copy --save-dev ``` :::info @@ -99,7 +144,7 @@ At this point in the tutorial, your folder structure should look like this: #### Some cleanup -`npx create vite` is amazing but it creates a bunch of files we don't really need for our simple example. Actually, let's just delete everything except for `index.html`, `main.js` and `package.json`. I feel lighter already. +`npx create vite` is amazing but it creates a bunch of files we don't really need for our simple example. Actually, let's just delete everything except for `vite.config.js`, `index.html`, `main.js` and `package.json`. I feel lighter already. ![my heart is ready for you, noir.js](@site/static/img/memes/titanic.jpeg) @@ -139,7 +184,7 @@ Our app won't run like this, of course. We need some working HTML, at least. Let ``` -It *could* be a beautiful UI... Depending on which universe you live in. +It _could_ be a beautiful UI... Depending on which universe you live in. ## Some good old vanilla Javascript @@ -150,14 +195,14 @@ Start by pasting in this boilerplate code: ```js const setup = async () => { await Promise.all([ - import("@noir-lang/noirc_abi").then(module => - module.default(new URL("@noir-lang/noirc_abi/web/noirc_abi_wasm_bg.wasm", import.meta.url).toString()) + import('@noir-lang/noirc_abi').then((module) => + module.default(new URL('@noir-lang/noirc_abi/web/noirc_abi_wasm_bg.wasm', import.meta.url).toString()), + ), + import('@noir-lang/acvm_js').then((module) => + module.default(new URL('@noir-lang/acvm_js/web/acvm_js_bg.wasm', import.meta.url).toString()), ), - import("@noir-lang/acvm_js").then(module => - module.default(new URL("@noir-lang/acvm_js/web/acvm_js_bg.wasm", import.meta.url).toString()) - ) ]); -} +}; function display(container, msg) { const c = document.getElementById(container); @@ -169,11 +214,10 @@ function display(container, msg) { document.getElementById('submitGuess').addEventListener('click', async () => { try { // here's where love happens - } catch(err) { - display("logs", "Oh 💔 Wrong guess") + } catch (err) { + display('logs', 'Oh 💔 Wrong guess'); } }); - ``` The display function doesn't do much. We're simply manipulating our website to see stuff happening. For example, if the proof fails, it will simply log a broken heart 😢 @@ -189,6 +233,7 @@ At this point in the tutorial, your folder structure should look like this: └── circuit └── ...same as above └── vite-project + └── vite.config.js ├── main.js ├── package.json └── index.html diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/getting_started/tooling/index.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/getting_started/tooling/index.mdx index ac480f3c9f5..ec9ccea4115 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/getting_started/tooling/index.mdx +++ b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/getting_started/tooling/index.mdx @@ -1,15 +1,11 @@ --- title: Tooling -Description: This section provides information about the various tools and utilities available for Noir development. It covers the Noir playground, IDE tools, Codespaces, and community projects. +Description: This section provides information about the various tools and utilities available for Noir development. It covers IDE tools, Codespaces, and community projects. Keywords: [Noir, Development, Playground, IDE Tools, Language Service Provider, VS Code Extension, Codespaces, noir-starter, Community Projects, Awesome Noir Repository, Developer Tooling] --- Noir is meant to be easy to develop with. For that reason, a number of utilities have been put together to ease the development process as much as feasible in the zero-knowledge world. -## Playground - -The Noir playground is an easy way to test small ideas, share snippets, and integrate in other websites. You can access it at [play.noir-lang.org](https://play.noir-lang.org). - ## IDE tools When you install Nargo, you're also installing a Language Service Provider (LSP), which can be used by IDEs to provide syntax highlighting, codelens, warnings, and more. diff --git a/noir/noir-repo/noir-logo.png b/noir/noir-repo/noir-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..eabb163ad73f2728f914a1bcc06c23b8832c2f36 GIT binary patch literal 224467 zcmeFYXIN8Pw?C@#Dtk+biUQIiqM}kFA|NHnMnqJkNfRlNE;Z6iLZY$-=_n$dfQWQL zL_lg(ItW223B3gZgdP%-5R%J#&Ux>>AO81zz9067^~~p4^I3EJ#$0obIm&Owm>L@h z9hW$M=+Ggddv|X?Jap*DhkrkR9Q*g1!!5K!ht3_kcU#vY^zdpkzS5`r&0?q6a;Yut z(2r!x?T$RCi$>AC;1s^IFTK0pD&^UqmB21^oj7Oy*)>gW>F}M}8}s*`E1tb2DK~Tc z%~^aG$a!ImGEw?tG>h!+ecR22lLQ*+3G!9jbH_l@T$6)`1K`#l>v*p6L{OaXzZwq9 zaRvk7MWdN`C=U-n^9U4lc!&MwAfaWSZ9UDKD}zNa2x`}k#UFP5CjLJS^Rggvci9@h zqd%1P4E^{24E0~l=B)Up{!rfDvw?^q>-YQ2xT*hq6zU_$JiiiG4Epf@malV^ujREw zsLA16yeVu?V0hmT{Xdc*M-F<}|Ni3tK`YK@^8GpJ!?7vz=es9iHjG(p*nd#X)Tqq- zd+>wN{#&#EhI9HrsOJp$Xejqq#2UzAw{u_Rzg1!W@xQ{EGC;bHM&lO~{zvT>#Et{O z{|4mwpQ$?#@Xh?%fzTJbr)O9K^cuYBByhL$zxADw`*+X(Hyq$rswI2=n3F|>-!?<+y4qDqRsk!1k>xE$^SpDg?}dhf7yutto(n>&VP*TKW672 zoByA+@Xvw!zpaIT4%~mdoqt@-e>=3x z<+)un=h|}99y<`!2+i&%X+OlnU!|%7l*5R?>VI!``r|ySx-m4#-#`2!~pV5160Q!wWs(s0_t6s z_j^K~+`#aa7h#hRtgHZ2%`%0huf(5gB&e zOO3M@p5f)AheeoUP7RE7@$ikf>D9pcRDpm|gbgi^L{FP z#=R@o`yOUMpkcWtqWv;TLBpws8C~AxD7i2Q6o{GNfP6N!)=~p#PN@{Us>y%R zV8MPw9?|AkWvC1vYr!Fg^hB?64VrQYPhQ#Oo+RcVH{bmE*e`o$3jk(zg6L9=WP!2O z_fYSaG^gtB6ans**gMsy-8UqYm~{={+*YokzY>(Re8YKa#TM|1{zOqbT8gUZT@>L| zUTqM*A1@vWQpZg$w@0spj3+Tx3>Q99#?1XKrd;|a*L4*V-z}^@#B7FrCWf}kH09NI__9)@5?k1s>XN`lS3b?lU&7-3VQH1Ek_pU{uW17d;_9V5F{F|63 zB!e#LtejHIR}N_Aew5+f)N64%xA-v$`ELC?K37PR6roqU)4;LabF16-3U7yRFK950 z+_klrgtC$X$>n<+dj%jC!5Ec^A{Uy@jd7;70QG58wptpLR6-vM5pJfo!yy`iJa5@A zj?sXR3NO7H7x}bN75cV)QBGQu%H89Nr%~|FB1%n$2WYUM*i6&3dQ>wDCiYAH5&hv) zjya9r6V-D)gB3TWVhQ+}I%8ubr;^)f!qHcce_iNm`TJTZcec3-p=GSe+TPFNg6~XswxX z4h!hlFI1O`-z<4bU6czxUM6WGqxc;qCqRz!cYg5M5Nmy${1I3+K zMBCj)bLrR?sQQX&6^0u5;Y`eV-`a;!ANr5frMY(9u!V!glb$T8zlJf}{I=3QgQLgd z5|p6GrnJ(WM^uRSPQ;k>H|?CDslJ8M?YltSbZFc3+GKlRvi4YOV zif@!@?^}(B7zj&f2m(ngV=}gpuy;>h}F2ouz~vCQ5vsbjAjq485!dv)1{`Y zStkRvs5%55XK6j?&EqLY#HQW`|B5fon6O!<9@NJ&(FfFmd0uWCQ*uu}5K9@+4IgOw z7He&fcVE0{F|iZ$&gs|MFbU-HSVge?ZTD&alNYZ%1qmWqlot|H8poE`kKQTBhYbxG zKw{3EWtcMW19M93D(kYxSY1WLD=sg0U!gu+f_{NWIHOHld}thNTpfL625knNwn@wF zlmmv~e356T5==~hZI(Elz@u*Z>kvehec5_p~vo!Dc%PA2O`1Cysxuk*XPY;WLKx=p~Z!v4)sXx=Ys9ee-sh}PZ_ zjA~Mo=`mD`#qK3cbWr0j))M}Gf*tw;vW!tQAq<(a#nf%iu<-S5+3ZceP{7{D2v;Rl z9e3*fRu~seqD7w#yBS$DWk6UOU*;6eNh5XIQkfU)w8IFzJqk5$%a7LC__-j$b)S#I zW1PP~pFf+8Ki@}}JbLch;WK|8s;tMPJx@q$NK&>rN&J+8y6VvUu46Q7Ph(q??5Eu( z2I~uk@=Etz*L2sE!@hjIik`)4#Q+m@_uC)uIz@9!k{Z=M>uaD-8IaIa-ifDOH*)ms z7O0_&1$LQl1=<7ZPvlIm7$w1p;Jrs$s$3&VI>ncA9=%e*xZ^J{UAn=V_CjdOH|I7l z?oZJ0v)+ylD-k6b+0D+vs9#HArb-uGtSRC_h5!$u#PM8up}?XqhCj z#P+1IUreV81U<)#?pN0l@~aQirsB^YrtITSo+*+GeW!LU^n9GE(D5myh$j?d%CGi7 zqDPF3)8xXgo3Hz}34%Xz3E1h3bJ=_4Rsy3dbRkm!3&B%}kmBmt90ZRtUE%LjU zXj6~yZJmvKr|3Xd2khJ_g#l4Y8gtrpLq)tE&WhxJx^tO3r@ZH?y{bN*N|xTwUhwFM~JA*+-w@#Ex zln4gz9aUu&%K0PK#tZex#(*gs>)~H?31#F2K3 zjz3X6yj($8*%4tsRk&wm2hW*a7zBOFnvjtX^WO5^ChrdZ#{7hhbkU%Dv|xL}K0qql z?HdjA6&)bD+u$4Vb+CC}6%EgkBbHEjiv@c{5m5;tw-`&?oP2pW-E?{l#Uoy{q!d}KE+wnK<6q(-LfTvWa3J!?Q1tR+jO(v@Q~KE%)2c&N#v4&EpCIW7Ccd+C zU^+l^xF+g65?VZbaYF`{R6_ZHu)#JMqHzgQJBRVxr0pphR=}w)+WslwDECg$TE!mUpgnErjiCgC5qdJ4{2{>B`i37Q!(f{S6|m8JMHE{ z@Bx_iikgS36?7XbdTk9me#(o7m{?7!SpY3m1TTehsqF!o&YL$8dVqWz^YEjoW9#7N zjqh)>YBkEE?ALhRgyb!bH2?r6d4}J_4>y;EfOi=!l^H}pSyV;}dZEOGzze!lGHg|3 z>AdzmvqEF>jO{=#aI6Xt;SG1V&AZPHx!wDWhd#B}6H>F>r_Kbdzh(Wi*#eo>s{ z@4&!aKj;l3nen2IZ`uP@=nXli3{Ae zJ~cbnXxz5)j6sqY_@;UoG7vmRZZan;RJIl#$`}H(6RIy+x2iGUU}yMQMn%L&Y<#zx zc7~jv{pNE}0)Bj)fsi7-nsUnDY@lug4WMG}Sk@D-6tC;r7;+0kTIY2x z*O`&)5G(NC_~nbh@#S4n`D}Tiy4yzWXM~qW&sSUl*UjowF zx#$u;q0~}lG#3?XKdjWa*0i;;R^-raSQ$xNozo_)=;!VgQ_Fppj3$$9xM}#ARIXdd zqE6t|C|CH%sdzUZJ>RZ}SiXyiM#}S=ErFUMcFvKZk-jbCXv0iO8VBy~%95g+qZi~| zyPO9yc-wO6ddkkZ*H?;&v5z5d^9lKlWOd%df*A}!hnJL_)%2*QBTgRtUM8Nl!dmUC zXZ&t_yU{c}UIzOf?leFHsU7BNwf-&&F!?g&^QoZ2hEmbFsSbUa;Md}YWLrY1-i)s- z*`zxr8v_Bx0Sw)Bg_i$t0SNB7ykb_p`dC^P$`U>vHa|UX()bnZi$(y{s}vUf2BC$fA~HgGslDXU~Z{?GBQ>W#o`kZrZD4Ja__ z^w~gcjd)G#^shTdl&Pqr2D@+6eq4GdwFGRbrDd@{t&ae9Qe}MJXxF+z$)kFE`l>8f zME9^^W&ft^yXu741TvwwVpEl}ogcOsPCd#1`TwS=z~2%U5$#RN3!68TSFgZ(e71@~ zP7>Te?$DibTt)R;m1H3EO)~`p3CdKfpm<~9WttJ5@9G5_c5iZmfJBs%pb0Nah)qH& zOZ(rS(0L2Z)kl)fIV8LZD5gx)pj(I6`B90ahf)h{VXyBXNzLdQc<_u~bl)q2CKLy2 zlAdpSDd?Ze+kosZra||@_6Lz(ZC1~e&QrBBk1FqHrP<{~OJ}z7xvyEPrsb^V*S}D7 zzB=yYzIk1pb2MqX+xVp?O9XM;iIcN5lOK)tto!RL>s$YoOZ}m&GC}vAvhU}jq#&sY zL2Kr|tCVn|v-@w-fZ-QG^$9nZBpaF+Pg!?G=X^fn9s}T1VVi_;b`Je3B3abyKuDM0 zKp!#QgDyXR)-Rd*fn-Bp-Ab9>KFg&1?u7+gOW6ROKB%u&%NXWHQ+rY*e6Mebh3!K> z$Aw23t=_8BY3xg_>tBA92H7X*R9RDOFst%GUm*i&IX3et8{|}n>-SaGXAd@Cy~T;8nGk|K1}ugRpvoWiUWleI66Vah?os2N29viQp3KVbU2r@+Q+ZGN$%-~{1v`=-veD>t z=U8*XDG`+iXg!Sub!~$a1q#m#l}(YSdS~L0*?_bDgo*7J8qO!6th~XSWocSBnX>EK z)vE^hu*;qsX@rr;o{RG(&0VR$?lSWAjnMBS==HobwLWv#j~W@o0bp>AZzJl-$CZyN z7NBH+B=y51t>!43y*1hD?i1BRk-1Op?;9+*2?l94+TD7n9#m#9l(%iDy_%mN@;D7M z3GsUXUAk4^D-Z2%d?E~i6eEhVJ zkQB7|2ef!QdjEr4OQI<-$~PKel}`El=V?{3z%1>+ z^tCopGOITm&6+-0cvEnyK9oAEaFlpt`x$|M@-2qJT9M3~;)1NJuQWU2Iw9@@o;$J4 zdvPypcpqOV`I}?@JTwOarr>3|m<_)-Bj}(Y3AKA*{~y!udt>2aS>P*sO0`?2p>2({ zGe~fm_$CG?$0zMyt?c#9Exry{yw=u%OfQix@o0Y^8~}?D$GIRM?_+PTt7nxWMx zDrO&Jc^ny*?kCzp=f`B)JBhNAOK7!s&?H;UXJ-Lg#195iwu0o8P;u_MQ}W|9^e_C< zCnJuZLztQE943(dgq?+Oxp=JGJ*_*Pj4X3zbz;fdPJf%MEwWtZRZm*Efr50Y*p9N(|*3YBF(w|fHPC59I?eAUPNyAF#?8$XfUy~7m`)Vq#mtd zTIFU<)nj!Fb@%5PHsJKo9K@pTH7WHaA@vT3^IMwF`&+f-3$<_4CZZ;Gs^{h=Xs~_7 z2S3N+ADcNBL!yhlwm!PI7ZAs=mWa)VUpUVNA};+d^EF(HiSJ0pjqF(vy0l$-@T9*1 z6&ZIke(OT7AfGaa=&xmQ3RG(}FNt?2(C)TE#wc0BpQS*M`0DkcKs-yxo&?MJVw^1xL?)(QI3;UzD$@krWBM zo|R3y3=SRK5bYeeD3ee!evwd)UY3nch)jxirWtxmAj*f=lYfyk;eJusVs#&N&C7D^L)d5DWGC8&KFK2&=YoEemZM^#{N{n1J(Li&kWVZ}c~6LP%Cwv+lIQ zt;8U*(fUC7KI4HbXzA@JJ1JtRN-4Oe(z%&KxY>?MYj+#K-KjO}Z{Ysv+%DJgaoMZP ze#9e*meVpgwPaLYC*FRiT@XI!6Ib9(9}8-Xz1aV@ZuBOz>!v!s?GvuE!8-=J5W{gZ zVVb3_DI!aRkRe<*=T7z){v>X{o!6aP=xSZzTW`+#^G75oU3=(%MS)HJqvB?`Lt4FT zQoI0=f80}*Ybas?ao|&e{-BItqBpS|# z9JcQ%N;>>}r}2fZllWh=cm+kg^iTOGt1ZUo9{$y@ruKLy+i!tec}K1?zQoD9MtjK# z!GtWIN&5PGQ3zd~miKkB*sr@)X@1=2wIU>c=k>n&yZn&Xnh`pQ9>XZaladJJDLvCr zrug33RxW|tH7D=Fgu7wsU&&@+(${XzY0?TR=>+Sx(k*JH)TSk3ng0NK#v&eBgUS;- zJ^6MGwd6iVB5SR?gS~RqZB`%b@p&yH=GIpDczZ`a9tu3*&yU&MW5qS*C&9EaK8;cNtieBZaKrV5TIQfaRn_yPOh<1(?D zS0{>*l?G7rx^P>6)x?o@C@LBLkxV4(F+kctFR4Croo~kAgXI_vn|ih6LwH zA0GrRQt>q6F>tsdh;&zbGjFqZq@?3}fjR>F1(J#${V8C~oD)M$Ro|)f_ON>>(ysuF z!ESZv0cBL|{>o%`SxQAiYBKvCKlL^*QVuf+i?NQ7E%UoERa!T+lb+W0jT=%T&Z0>C0 zoUqN^ebk!NQ5mE!dSAx=7;3b8Vu%quaxJvPFWWq;OtIdQdnSnj4PR!#9^ro)&pw+i zeP-dlr#Q^|#&WdM!ybeUv`KvUwZ)p1Y9d3ccV~eB=MrJJ!=B_`e)Up4W42}3eHR_)efdLF}vnr4Eo!vP#ak4 zf@0X?vKA{$jg{?eRz%UhVn1s+qYYN;8+xYo9xz7)+mf@IgBPe zrf-nJJoyv9;;fyXYCp@nl^oFxNslF9#fXmg6Wb`>}_w$j;U;Ix_kJ~K8 zaxW3iGR-yZ;eNSWP^1$)1hld*&6*gQZ`0elCCUmhBcO*35pv)X zT4Q*rL)x2aXVAP|kW-%w(o->)r?&U7D4HNo&U+XTendL>;rdN{E-y?Y@4cyKPi`;F zDXn1yag%&oz25*J9Go0SGrHtsy&n#ZMt#vTltS{-X1I#gJ^_?-7n zez)rteZU;S1UQV1@jOr*_(d+gka^~>tG?fZ3!FF=hXP+;T}lCa9|P|Xuo~KhVL>nX z(TBFMP_$(DRS_?jnO=xf1?d%5{VEV=sa0^V>`!Lt%^z;uDB-;?g~2^V9r<2cP#0Qx zILRBh<{@++zh83*<7x7p#3WmDUyEq3RAb+~@K40|y93UIRs0!o*`cc}u@V7jy_BZ& zlpTWtuV%1+1&s+d@=1oj$DM|BHB+qoDo{Qo@9hQt>FgqCA8sWud30rjFjzbC(dmat z&uPfJB=F^faB%OGJhL>z!UI42dPO98mW=-!U z2Q`oU+TfXqY~IZY#89oXc$^{@2Yx%~$saOfDaTPz=V$Mx%IgfR$E>Cpw|>%&=V3bYrhT_5#0>^Ia9!|Z{Pvd zUNZq`lV5&n9^^YCv-7)1MnR0XI;!u$k){&oZ#l3UM0sZlHcLA^4G8Tc14-4W{uT_5 zA_c6+lk|kIw$y2X=L*VhjI7!UdhR|14(kHO2r~-JHZZrplV;xSau8ertaRgxlc*;r zj>Af_?Kh?U{T;j(Vk&x@{G*VjBczu3t(M_{zBwSfB& z`$apj6r?2PvMIL5=?m3&=>ODr(KZ6ec*vi1Pr=H+G`(1Z{0+*MMG{52QS}q=q@9@c~RPD#%tPaB}&~lm^<#!H8Of8 z#d@{<_C84z8Yb!R%97F=4zdbhU=Tb43sFP501w`ch!AsmKP>uCPvoiBi=TAUpi}#F zK_5aLtBGQheuHvj#f}E{R3dP`m{auJS2lFM!^b9_wm8_v3qjEjvq~kqSv-8_M`A~z7cv>> z-e+u|XSx0XQQW(!1o${{aM!@ftETtyT2g3ROAmQ8s&JccWDM4z30=rS3BZ^yg(n%e z0NN!QFlH~jT@AUVA`4g`r%l;Im_}Oje4WzsLLuZU>Q|w2QKwASL8xTvjUBCxFGY#^ zYS9|rcfISj%1pMWJg){ELl2Z~%*w5v^y)`#ZCM5je@#x87ya!(tdDUlD;Z&av69T? zy)vk1A5qN^sgNgxh7Vn<0-JPZJaHfNAXTDI(m2EiX1fQK7qcQgH;65m7pwW~6G1(U z;_6d}f8BrN`k{v$XAyFf#w&22E+*fQ(mXrKJw^NV*s|DR$XX9T{s_E)7Eox!LQgA-vpE3&n#Baw!P zNF>u&t$xTN!lk@WHSnTXO`HrP)z^KLaMJ)7i~p*#7}jphQq-}4RlOqgVRkO;zcV6l zLK#B9&CM5ys8?n2ZQo$sS53SH&xXIbvDTktz&2jJ8c;19k>K1KHKVd`@nGp*AJ&~@ zoPAHm($N3Z-riZ>8e?T`M|D^4{iEaj%$zT)vynI1s5bvD8)rqBp|U5;?@8leo+K+tZd8G3|rP&T;!`l=)y%_*3Aa{oMEl9^bL+8UPNzo3(E@S?&dy}EAe6U(C|c; z5jotyF45`(GNQErlGPoOxdk0R+tOu61C9;TdaGR>$7zHKz3+@tvmGaDYw?<;G535d zZseTAPrWp^Uqc@kRzs(}Wn6<#tOIV|6HNXqnkS0ruuvZYdO0*@Nyi*U6-@?b%N4k9 zYU@Yc48(#$7AWC@i;vt}w$G3AtM(WDOa*=W!toHJC) zr4;0c;aX=57tPY|X3gw9HQb-$i)~Ky>NgLeb=oXf+No>yM<--y9pw7+56rvVAPpVr zxK6mfn78z8DqKCBy8t%wIp!1Oa!ey5c!>1fUATt#q+(bsEc>WK(bHJu$@uNdj6 zwa*v=rI|?Y|EqE^-kGDnLzzdnTmdf1-ZeEn`t1>ovNw+(b0>+%*3pcQ(gX{apyE+j|`KiBsDH}3sSW0gXCC!xKC$m(*D>yj5yoKqmJY=D-R z1H;lPLdaJ8a;*-%i8DoxK@We&ZvXC&RYFAW_trmmSbH^*JRJHNU&Kz*`coKJ=%;$q zQ_@ynRc7anH0}mc2y+UZ_8rslT$qusmzHfSSZYp7x4PhN;89kYxWx%Z|s zu|J^00xUNABdf=muVFZkSlyoJ<8LZSzV7nLq5UIdNuYKcre1od>sI^J(G({92IoDz z|FiJ|KWadUk*N9%AQTpsd#Y&U@1S2c#1;M)O|1CGsWjDRSD5uU^ZMw7SU^OHkUO(e zX6JO|wuN$p&@@S?=kXqd)2HPN))$T4mj%^Efx3n2Q=kj3@n=%lvY=4?K|)olM1%8( zXBG`Uxm~ujv%#&2V=g(TSv}@k8m^_3^R}VpO-_9G%RgAF-ZDzo|3p*ZzqZJN&Ni@h z!8M5mQG|nIIBsbgiO)nI!5-o&|M}Ms&C}15XouF0bYB+yYxNar$MsrIe|!KWR2X1D zK9-t&M`xRWN^?83$Wchmb&h*9C|XnIXu(Zhna9{Z5-GVbOqCC$7Qrsv~ z*tSR{y*S4;w>pXDU453lePXVhtgv2g(6ga;0b&RV8;y2MQ?1eE-0H3C$v4cE4_k9) zSG33yj{ZyAvCf;SMe%6MtFKcFe$xwP_1j%C?hNnpX#P#O66IFyFU#0bL;PCJ=1h!< zaPEQ6^UuK`7lJtj1!};im;g^R^?^ZgwW2T9H(!IbTKQ>uNdJQaPwBN1-9VAqUO84? zy;|MTZZlSz?#md44@+*HKzCF$xlyIyy&)vHIxdA}twjH9&B7WAaPPOce3k)=O;Q_{ zeZ)=cAJxHFR+=>-^4JI|YT4S?Kl&eibZ{M~K|zhxzGg+E0-hJe2V`#VcbN2#M%I=3 zjosq40UJ=fPP=PKV`93z z%7Ev7?pu|m=;-9DnJ%Npchdt2Pl`4i@G1gK-6Zho$zX_=G9aWszjPWg-G8-m$Fi3C ziprwY7k;VwNFS2$1l{hSfe2z1W+TR4c3vy|`hc7n>RBX#SKJ$=Ss@Z6l1qVtEQjt? zS%g~H-CMgkoh#JWKO*p~Ts=AZe87A)aG@pzT?WwMAwnajl`l zsb5PyPIWHG#weeTV3^j(Qf1OcX6Aslx;FD0N|{<&(7?=!QZ>I){G~FLsHp)0RR6J^6%p4pAOLl7$Rw{)}S$6;Q0E za;5##!x5%ck3@z#Y{9S}%=0lW5vn1-`WNsjMUCRuQD3RY0ONHGSc z%kkPTVujA`_g#-a?6Ko^IpNIfXCJ~Fth8%H(d{BL!C8|Ixv+1qq;5D{Zo&cfSrk2iZ;lK4(SKowVW3d`c;>4*5LaegTy28@ZoX!OzrErj;{bik7IUSHFJ={2d1vvh2H`bs(wy0qx zZtRDE{fOymcgwYJ87s>YISJ~k%Nb*>!l&!sZE;`-%ZPj{UBrHe4OKVI5mO_Res`+f zpeH^}jgXgut|_FzE51Kv<7ZTNOlli-5H6{w_zpNAbg4Y!hXp?lxj(E^ojP46gdhz= zoW!PdI}YeRIn)(HY}$Hf1O2Z(G0G|+;w$rR1}KBqs~;#n99Mh{x8*)Vf4CSo`!?@% zv`gZ3f83J4^YrmT_3K;nd?mfh+%Lwqsl+bUjJ9)=-Ml`+eJoIC9XX?nLr4g@EwUj}-&;-wQ^Zv9f-F zSM@@BqV4A5)oz5%Mz`2|fpN4EYoDa$97k5@rl6n0(?P? zQG%O$y7MQ-9)=Y4y|s85gY3_Xe#C&>lga9jZT9>N+2yn2(n*{4vX1x|JWMFY{50+? z?Mf43`{kM634e(CfbGF}RV}mdVWRr`%ir@Jw+@!CQqWguc-|oA*w5y3M}v_UIPe;Q=6nTE?OY5m!Js@0;{Q^E zdJ6KMr_&19jy9w$0a|L~jt0p&a9o9=)@m!Y^7$+^LwBl2D^M}KwiYMK$zGw+1$9;lMmLcnG_d=G0Y__uk>5u&Mn@ImEs+X5>8WQ)cP;X15z?4OY z&LI18pX;v)=@8H}Jv1oBe&&+b4;|sFYEBNF-c!!ra|t$7dG)ZJ z*>Q!0sm$M*V(x4?QR%>8Aa!^k{M<*Gt>I+B7V--ay|tmg3Qu$$@faODtQl0?t7BV} zzIAAm?B#G$Z(79qm$_YuH4dcR_F4II8Kb~>1zzrY!dA!8Yveu0R?#-TmoTmwvs$Gq z_%be5A1MOT+WxCy1VS~6Pu0-8C+I2$TT|=@UH5QrJk9Ile!D8YY`svpHOZWm$?kfp zsM^1xSuZM-Q(_$)3#08GT44E{H0bJjb_+P5$&XO{wAO)_Had@C7~~A`9z_;; z={S}>Q+4vhS!8F(Bj|@WWG_a2ToRccIG~!%#QAQV?)?-Ou^k!C-DUN#Ju3=o$FwVI%Bh$| zYnsfBGMU@wBULgH{^4_lQ;WMVCeC~l5Tq)GwOvQvIAQ(9n0?ycEFp=G{HmA{pt^&s zENbbf?!4A-AavWU>`%@Bwch_z!t@$e>z=n0nuSrXMaIOT4zha0hL4y;$zjXJQ@tuy z$X9kfz7Rtw)qL-@o~JB33)62BvGVNAMVZUoyd2D4_;b8$9ZP#uf?Xzh5daO`JPaNk zRfd^j$*6C?&WP zB^d@42f(B`1BR15sjADG*Q1+Ca}SX1a+26CK1+yU#g!{T3J{&kL2v|t7uJ%fRv0DL zK(>Bf1D3(~6&F8Yh& z+N@*49m#dMy^rU?71KMZT;;7?W#C*$O4@`vWZRE>4v>IY0&WI<*53JO^@gf4ZH|7L%;89>y%c`uLnnJUqGq^Y^aZGFZ{%V#q6FjYb$f@yZQo%;p-3q|V922 zyi7};{Ml>rxMCj8DqM*4q( zxEdLgA|XGIX59jX&q0y5?ZnRh!pbza$I;?>`CyzX`2yvQ?Q|SxlJ(1&n6h82gv!f4 zsD_G3aFKcbbqp3H09@u0Qe%GDDXU5>~BXu zL}*^wn7bYIy!sB)hbVLVPH> zrr#|>hZmdD>|my_-!~P?{r>x7f!h=Ft%eHAe{)uel;Lp7P{0FB&RSTVn?8OlFtD)X^ndUfEr zq2eh$j{Z{){T?ha+iQLE{lvDUd#391M_Sa2+OC!%abXBtFfRaB+l4h}n}reZ$h9E* zu$^c=+}aK9cFze92XdcH9M0**^pzSzZSq508MZ$0YX^wu`G}s!?-9wghG%ZbrlCM- za-9CA&3a@7O^p*kDw>8c6&Ma1!)a%FUu(`QAYLU@4g1%x+9Dkdx9!yj-)Hwpg#gVR zBGxGq8}ULs)4H=ebNcPxewSoOl8vc*DRt|9*-1DofX^3z!#rS}KR=dLb zLa_Y#sC)Rq(NAYuSsV$S_Pw`*VOJ5kysZhov|L`B073ILHm%mn z$YD|gQM_n?43C17KRsys4)Q0`MQy1f5s$(YzZrpLVh4f#H0(FkO5Dg8*)VL^P9q)YKo^MT|uD{3N|b_lSVp$zKL{WHo=17~(@6iE81uggvlA0ZSr;O(6F;5Yfa0 zvEq%KNv>Aqg$4ABb&=BK$d}R0A*!`!6k76BVXMXKbFUQf)tD<~YTsLayB2t+gXWv% z&G~t*wq6gtyyv3N_BVY$tM(4!1PgEo`e8gKwr>+>Q)guD8JPMjn~^RjjLI*fPI41< z+0ENeP{pq(7-csXtM;{kG4lu1FxNrB>OFw`p4+zQ z%g@R~aAFAt0rlGjR;JzrrWM#2^=b9MX$Ni}{|N_YTxWvD)o4TFv1>o;-RR^vw$lBU zNKcc43G_h6@#S{>Xu!;-gj(mmkqcW1kE?L`WY4}v|3q*w@K!GG1KeM2`LPG%CZ&FP za{5Bbg8s>!p&8HE8#&SF-f_pzWwoeU0*{#3xsZ3oIbLVaR{1ZA!C$q0ZYd zu^mAYNWkz9=GSVd-{6L@3eaK*qFq<>c=LQnJqeKgoT}&ZsbWEL+*IbmYJMZO5GbB~ z{f8G#eXfCwzgFKrXw_b!Zlj02Iru2Z$iC}EwQ7fOaEbeDZg!fY`W9|*FWuVPI>S+f z6Uwcl7!TJ~eGWHs=l|KK>bb_^uQMg^&KOWNWxslm9@86FsC(Og_jv%v4W|!I4;-Ol z6aR#}fLWZ^XJJ<`0Ar&UVnzdtD-vf5_p|pyRWt_j>JD9siSZ_V6V?)A4-Z+^`{eL0 zV4LC+G>|O@yUJpLk=xoVqE?C0LP4|<TI&~~ zZeMbL%B2vyxmCFLNJQ=(%`Z4TqhR7YW~{zijTIJiMsl`bZ@CGD+9G;~atQ>9l@Y3T zxExrw(!2^aTcjMk!B%?~Q{Hdo@O*eZCm}g3@RNFri_z**d~?U$i3;N(az%RjJ@Qt- z$6Q`TCw!#V@yCH_gZ5iy*{8Bf7V*j-rcq!}{^2`^IDe#f?dAm%9s|#}E?QIbU+26r zW%i39Hr*9>)0|zxPizpg;ws|x~V*H&ZasADH)pwTNhWbtI_Mxx{tV$5n{{4Q5Z=K3g`-RQG zA5J@iG${APv(f^_YnjUlV>swC&}%9%Dhausszl(;H}t6bGA?5dY73Sc1YV{Wo+lut z96Yizt%YsJo`th@mj9k0Z(N^z zzrL~hz*ZrI{L+^_bVuf$}a6b43VRf|4vZvO*{)-h+kV zI;_lQ`zF3DdL>9NmGWuo$uUxUli?(R$+8@3;aOl?kHeZ+6927XH~Jy8r#wd_^5H_7 zPnf2U4*QS3UgBFDH8WuLZs^M-sq1l-p|h{JIh;9n!3ut=U4$`0L3s{OtELTq>gWpp zRi*8N3B2XI9g=aznqd_l;qE@R%`rFkd~`riQavp`S69^ljnjYx0O%Z;^2HhNvhno& zh}zu%0{$StpACLgIuntA5GVB_}fqnbFt`v^Va%)GtGxy z-TAntD_VHVYxUQ}0?avuc?UKE*$J@?e{sBiU&loOg*#f6476D3hb(c{W^&jHZk%|n z#O#pf??ACHX90+947)liQY_3u$4>A){*8G@Eo%x{F5Uy1L$2E@F2J|bCOx78kLEui>^9VgouCo^2Yu;PLQ05bfrCp%lvabXwV9Mg zhlh25BP%sd-?(`%UoFG?d|1FBTXvfsCobw|_@N5s%*nW+Z02$u1w9*wN|NYf8yGE1 zRvTcB;kzrV)d1henK8?gwd@$Reb}Sy2pEzR30RfY;8@{RF-q^hOokPzI%hIQ!gu-5 z3voJ{7&5}>zJZ%b814?`cBhmDsQ3*9BVn~44hQqlW(RrZ512*$z~{FPegAeu^e7>w z^NC3_^4qm{f0a z#;v>tv`^LJ=XD)htJO3gmDLlJo1*I%`7b$%m0oYPVoOtY`1T}HhCEVyn&VYbma3~O zHtcVre!BdyJzd3~l$*H0D=PoO^Vl}Sa>xZZNd!YWXY4IFX(i{PAxSo45aR_kOH$e5 zTRK%q*jS2kv?J_V0rycHaMi<`skL>(O# zi?tE&t_M`s>(tSwf!VIYU9SiYudk{KFLL47x@}3y(%-pUU)BW)v9CMP4y)EU=Vs-w z(}zcGucC!AYkv@?eQ~eWH}zWw1)B{m)oaVCV5T_wkv%6OR9|HapPw>7zZ-@__LIUW#1RHQ~lK}CsxbV5`V zj-ntUO-iI0rAj9xBq|3`T0lTVAQ2Ji1c>w!kzS)xLJ!gc1PCp?{rEiB_5JsG12cQ> zYwkU3_Fikv^cScNq|&-+xpiSaZ1_UJ4Mg^hg8mzJ*IlY!9w3p>xAA{mE5`vOoa_~UzIGlA?CT3LY(%$8#NmUh7B-`wY zdqh2g+ASUM%`Q?L&08{(4^q;XHy9XPotBl%jYoDRQNUQ3kqE#jW959>M+QFt0PZZd@e%N_c=z6}43SZj6JOL*s_%7r1h zKMzc=*zM^Va6?@qF2;YG7{^@@u@BW&a;}ZH?8YJ|_W7K(gRW%plk;o`plB(_F(v)G zJ{b{reII3nyrd~~&7mJpk68&X>5hsN?(?UGuyMJ6whvv+FxvWK?miP~p}1h0c-%j; zE!4Q80wIwj?}C;cUsPT90H4+I*t~;sBNM;o@Za50Oo^6&yFo(Sn|toizG7JFQ)RFR znN@i@nLy6u>f?G>M`AU=9pt`(>=b;01cFq{RJWqH|PZ_l*jpKed!X&qRPBrJ_o)aRv zFDosDIX&vxD@Ne$Y0+5?W)KdJ1m7*En$sEu$wFzQkOH}d;_~k;yx8yi{Z_g4m4$tU z#}hk0NmrGM9yv;8$?}lKa>sSvV zZ9D#=^mwxDb~{n<)pG1ID20ZM^{JfCZ1)+UR)l*l@N~g^f zFAbfnKX?7RIn?;WR$fC^DeJq=H#hl2ky5o-KBD>W@_GwrmM3Jpi1kI{QZ2XllxFDQ zUE}#^$Z2V|O~wgk!kLeRRU@A`C4C>ASj5D|WU6~J4 zn;GM}`$$Nysk7;{=KCLU?KdU5t8k~@+5~=;X}7Dd&91CpfP%+T!`9EM(=7$^W!bi% z5pw_hlo>r1;M0{^Zb@-|IvT=0i>s2Z_NHfTO}m1rj|_%%kdMN)eU*5h@%$j)1(mt=I<%{|~<_hparc5~mD=^rr^;Ulzz7UsFMniZJk7+HjW z;yv~S*h_eF{i$0wT+j-CFlr=k>kJaw$iL{+ifVY(_rqq`2UPns5)vd>1b*fo^#e*A z8#oaB-3K1`?Zm;C{LlmU*EE**S?n*222k9jVe~|vqK)F{jYeKA7U>8)xRC4$dF1v_ zX6jT5D%obb9z%bPGPBe_T>`b4jH_Q9XL-4=TCit#3`cUqu?$vgTIZM0P2FYR$oKb0 zoQ?fm7_Xf@wsaZk+=kQ6)N05{b&i+Gi+q7jjtYJd32*u$1?^7vVGTz**X5hZ+O51v z=sZcSDg&M5W@lVUw{CnW7VK6YgBfd64R|!*=-XL8b_+S~qJ5^u!X`H4XNgmmSc+A1 z<@*oUPNo}fJ07`~RPAC9X|iszQ_?ST8L4segXy$Pd}!EHSgC3^4;QS~dL)BauQ^?T z?^QGN>1w>ElF7M#{#HI`NX&Th(r5bN<{SBxT!N2LxZN$DsKZDOm5|LAZVb_oY`i}~ zu+HRs`W64-By>CP&f`z@5a=~!h=IedCu${T-4)OqUwonFbJ2>b=P$9VX^Ojt^fp?r z1y|aA8VtY9bd%xUhxSMTTU5(-dabwjFC1L%*P5FQ-{Z%unwb;S*TH)YJD*h*EJ>czFUo6BujVLT8DMP zvI8Wh*VSb~gz^jp$(oC)`cFX_Go}31$)w5is?{l+gq<3QQ5kU;yj~qaQE);eMlc#Y zXqxCktK}7RL}1N@nr_(OUk!N6KHHUa;M`2m_`K;;-27Jk9GghlT%8_t+8N2}UO zJ8J9hhHh13OT{S9!#GZ$c#Lx2_^0;Popc8r)M_wxS<*3}g?&svxOVE8t|x#U-Dgwa zY&-9%*y0_T;5pi|dO(HdCLz#s+}h=DW^f#F#i3<0nr--}3kqqho{=2@J-@T0cGxGU zY=YvzD0^{O5H}b>1KHCFjI&Trs&?}eKvSo$9v4xryvuVIb-aCBC;U9BizIWx*t#azW+^lhE3CpVoeSSIEOSa~ z8MN;@q>q;@rut>!*%i$bw(Rq2%~HJk;}t2PUzV0{zO`N_HLP4woQpbUM#i-Oojqh0 z#UBd}>ds%DOZm_+b!V?ausTKUK$c|924`!6nB{Aq&#`evxFUW2d2v8zIxaK}&4%)?MdAM~trV9(3uMot*iEQlSag&qide zNfp9xl<4Vu5DHx#13Sdv$1BDqGRM>I=;ml_4!KY=ginF2u0u)-U)S_!QVFdkh_FwE zmg$Z0J03y{TlR7hfsa7Pkes4Cj z{dFEOLUS}qz#j23q1A`>L-rUI|&MFkm zSS|vmW3`Xpds?Q78nI=1nUlO~amq<_Z-HD=#?&?%#7nW;3`ukvz&{an@JaKT^Idbi zoFyJakLlk{)vtj~AjsqU=jAeX^W7STR0n_8k5>8wXP(6M-d=O$6_sfEmuoGpW-dHv zswmMu3O=Ld_HV<=-zN=(R!;wa5lISGe70r$f^pjowvCaB0j1;&qA*knB*~;1qqrB5 zYRmT4FI#0QoCl8u7ZXktI7VgmvL6sR}k%W`ENH{@A#~Z0jG(&ytdtBC^&^Bo=G2|C>xJ zBYkonR$TYCXuLUFIczh}*n!Csg&>AulMwww{JOD0B5uoRV-hC4B;gnr9j#_SJ(F#5C^-ahYv!!fj7R~zX5*urpyzG|mw6oV+`LDE7m)YO;qkDLI#|~UtIkGdvf7d~*Pz!NFT4<OT;`eeUrElGTPuF7bC$aib#U|N(8@siv-5VM~+td7e!nPy|fv@p= zB)A0r$CdE}^W516EhxTh6cMr~RXlm<{opo*DU2v*a0KiDl*=s?lm9;WRe%Kd&~U@E zjadiDBO|W&&!kFloy7NfrH=Em2Y1LFcbH>LyiJCPaL&y0P1x^EE3k{lk1S+_u@~)^!R~03 zKRsflU%^hC)burRus~-yNMcXPb7$QWcEOU=UTEap#pWYBay5q!#G&=IOej{gRq?C` zYZa0PD3YF@iP>@mjSU$~nHWxZ=sx(NU@Yj+30We_^&!=8k3^3)2p7~FE?=&el?&=d z+;6}HbgMUDbGzyX)thRUmF2To_gA2({w=!0UBB33*RJY?O`k6!bxAJKbCH4j#rWfQI>1Y&^3^7o3ugIlJ!yWW|~?e z(=6O(&3OP%z?04Ct>!jURwtnxB(%GCdm1F9G&ISl_Rsur(BD#J_-}GCP?ZmYxwL9P|eX3K||lq3uTv3&XIM%|#79mG>RNFonfDdJW6psQuQ4)l`?(I(*b* zvE>{|9S+m;$ac2icW}yf-hth|pzf2IV4e|!KEHIGvh|+^QCOtQ)J9E}q?YN1V}wL< zgaCj@n{uzj+(2WRw-MVst$36JO}GaEmY8hI9sWTfmq_0J9W8PFFsku%jIoYNj${X! zu$3XcJM4GOVdVc~;8T&vX z>80bmci*IFT|nd)X(=f<`>mrYLBX#HgPjfT7Z*w-SMq!=^Ls&_B(bm_CqxK2%Q;ZF z#jk*tf#`V1*!Jlwqx?`pty$NOH_)Z@^RdoPw^SuIMb?pl>S|BZ%^e0mDVx&s3@V?3 zi;`&VvH!;fpkN~&z{{*QSw&NKLNPdGn4z=KgP9@@ec<-sqt2ep3jNoJVG&(Nb<=P} zE@%`6lhS8z^7^K3@gvsLWT4qJZAJVwPIUjfEQ5vu%bc@$h(&tHT6(Mt<%}rmH<-i* zJKe(XBmewneIu=_LFO8(b)KjA?Umcf$kiPAtC59M8~$uCTxQ;L8;6 zS{&S&XvE0)-P8HoK_58t6F2snJXpj3Mp(OsYO`1^81O!lWkHuCt4Ej9kIvGzYdh6^Seoww3Y z6=&{u^#9pDE>O44cGC?nwIn+6PVd0kGKwHaN~7f>{^Z2mE*CrT%$KQTMRqTnbJh}o z)gnKlq!x4knobW0Y!;vDxl(a?`dt~$YcN8SH?nBXD=LcuDJem)t=tR#g9aeymo3~S z+C=g(l4OtP%EQJtuK-Qb=SPReGnt>B4sTrVlN6EL{Y~~(qMUj^RS`e1REt2)o!Ob0 zn4z4~sT2csg;#IcBbUB;JQS+bE@~~j$K?~ezIoWK^~Td}{KuWDyj9A#8ws_8BTJ8I zI^`_A_B1+-07k5ZG`8<~3BimNBYrMzJT&i+371%96Nbb8=uz)A`*}Cbhp$BKJX)_Sl2k8eMN+>?hnh@>}i6hmCEf3c+f z%AtSIAyb1gh6KE6XvgP?7U$YJD4NN$v5Qm_`Z<4)0=q^*NNvWuEkd|uuVsla+nt= z_RxinVGx6%<#u{w5#HS=23yH%6H#G`tPKrr8!|}-YxS%390%{RkcqUh(ak?Vs*ww) zH!C!TpkRT>c6X^h0&qT=Q}>Mq9a5!aTX8punVnVJAGZ88=TM{Za_^`=I)9cRZ(Zh? zxOfE=4#j2KZ<&E8#tVCRDNU5z3mbXXAq}{xRrB1v_i~o1BF}P~y`SWM8WMOL${e9K zGY{mX9`Q0mIL8E4pJ^)7g&J#*Jidj9+#?LgVMlwZ)n8Gws)H$##k`WWH7lO?EpV2O z9(H$7J?OU219}_V}*9b2N>< zy1tgRNrhECeXVrQVa@onq3t98+GujLtSxs*md)Oxhs1g;yHBujh^iu z<8VUP=p^=3pJ2C)qBg_DLz{#I?rtnZu-53mbo<-u{#&L8ss(!oVdM^TQl{hljf>a8 zLy@K9#E@D;rj#UwRep+kSw2UHw(!UwzD&>X^HvFv;CG`TLu&O>X2V{Kb?nZTe zzN>}(j-aku26cf6YHD~>ta0F_+uxagUng34FGja)xF7NV#jg6ZwyG7p9i7Ip&N#5- zz_}@$jK|5E=foRn*otRT{#x8cD^*EJH+{-4dD1OYq>~iV9xL%}?cB38;`nTIISUfl zI4~RZm0DcT8S&Weh#k@kx9wl|5>2$I4mE=x>odZ_o``bsDq`+qA9?A9@ZAO{N*K7i z4T@G`K>cMp!}QgOvxhE8qKlbIhW0Ch5Y*#5yMW%dXT7+Vas}J6Ut;617O%4H1{H}B zXU>>a1U;jd%P?QA?B{*CB=}omD{7G}HS#H{3-xG0u#MWBPKInlf!0byyBv;f#Rwx~@ zb7b?p>YU!W`WwGm=jLdTqf6hE4>YM6@mr-uX0uD>J{x*kB116~x9sMB8e9U5r((^Fd@kff zevw3TFd=(x96Po1;zmCK92q(Wx_4BaG2|R#gsY#-XOIM+$m>T?N7~veo`$)GbuP1U z5j7Kuf^Wuy5#|3I*A8c6=V^g>il2PYGO-*_C!e2i@%e078GDcO;nUJ$^&!91beU0Sp8~zjcre3D1T+{^ z>hvNMDLxI@*xBN1@B@IC5djy)N^I0jlzC7Aw3z3{Uj*=f^UmnqW1YwlynuE(?@a zm&@|lLvInAH%-|Mv4p+|L5aF15bw8Fa2-g>p!Xj_|8y~%#vekrZPZ=f+blZ6fx|@@ zOZdP_>}qRXOO_(W`az{31|18HSuMGbxT$X~T)qSx%^gCSIb@pbCP&Qy{sBa6D?(La z;XkW#S!t4Qle56;i!j_J!GyavYp|gN8wpy^&8r7upF8@j>zuR=6{OAx1NJ^ zOp)vZaUQQy^#SAfJ~`f&^2&kDhydj%i=WT^wcR%|gcnQTqsIf*RX?=@D#a`Q0lO(e zKhkEt*~HJzyZ<^7w#l%MknjfY@NvRF1R)Q_YZQ751d$IJH^_ZdgW@i^;;PccHL_q* z$lt*UI#9?JVQ-F03U1U7VwqD4MLqbp%=U=1;oDp*?i!i{p{5c}$b2}=rQfy9`l}VI|4tW$4TtcKc@NjKEHOe^VjPMLG}b%Rc*(B5+sI0E!IJBlM>Jf9x$luvG9ZbR)KMah-nB~p=D)c&tnnPRY74x4}H@q zje4C|@1hkgP8qg;PUEW^a_jog7(^=4p~y<= z@RAp~sTxj752&R+BO*Z^U9yk(`)3WLBL|{FmPa3ZYSm=UC-xVB5rQt%4j3sY5N-;a zr)Xq8SGcnS6y^y_T^I}YA%Er{cdIva`AgW3bV~l}GH1{)17^Ol(L}OZH-20Kat8nYBMw`hi^|yp zJ8hxNC_+H!&fud=zj+T@J5{G42RY-L&1j9s(DANZ6&a5b((C7Lvp(x2-Vf^W%c6vN zS?v71r~6tc!gUT~g3iICKRzU_pPk5xd;Oc)9n2p1b7c8Z0WO0G9=%=EXEXui(?7i= zJs*3;>|Qcz?6htW`d~U*!pTh=x38(65>kcRgy~Vcpzud|@!7lFz)>$e==Apd{JK&p z2IDcZ^u~~De)&PLyQE|>w5>C0tU;n-8DtDG5uk+w-pC50J-9ZlOM(q?X38wJV@Vey z8}QXTxUDC&#w<22C{xVG*hre4>a=Nr7@%w@2+_|->+oPh2!$3n>V`ZQ&j;pvX$89j z0*;CuZ}iVOA`iGKY~OLYtMp)()3QT%B6Wvwlw?N^!w5o>;i?s13B#}7^W!aG(`Bp_ zr)*9s)!o2R&oeQvg_VL;ktYSlHR*1WSflHs#y+zU_gFBjk+)d_jPnX)PBYQ-4zPRm zsWdyn6P~1ST8Kc&=36*4zCGx*8%u0LgeBa%@?O08V{v~ zPbUwC!e?5+)acqhcDno8$RTQ)8lXEsVpL#HypOOpyE^uqy_d;%yhcNJzhNNY0p5@_ z2U1O#y~Qo@=9H%GoS5I%S}aFCs-bo%O%-Fc{O4AHTt1C$m;JH;j2tAq5o~c`ZMs}k&k`rsS0>cur*vnl~ciR zhZkP(H*WuI!30@3dPf2YYw`UtZ43TQYc^XyqhH65482+8Z(TN2Yw`5n4$UlC=QjnL z_T%^&J5Zj@E=f2?7`s}(iY%UA?I?wJ8@+dAyjLfdj~IfuRn-$eL+H(zT7KRo-U4L% zTI>&oc9M21ReWZIdBc>C2+B$K?jJg2tTghNkE6pQlr}X;!2k9!^qWIs1Xh930$SexUqEPF$s+$MCaq)1WZYlCVgrN&!ree& zL40?emSZ9Zo25XbNdh7ITV(@|Bjx2!lCbn5)%#_c`1ADyU2$-!Sc6iTXlY}JiYp) z(N|orrA9hAw)l&Cz4gkMV=p+j56zX|HK1XK<&3=}nF2m0XfS9)pXqXk(qRo3GF;li zB1w7!^2; z&C0<{!}|kf3qztNS#HOUpan*5=n#yrlVh7`;6-b_(U6m|Nr2(hwI4AP7!T^FTKbrp zdJtNUzdN)b))(Mx1Z|wZoo3L7u$Ab>C0!A#b#`31vC}@WwTt4~CK%XVu0c8?f2D+= z?Jy-v@^F%0AKMdJ78Bd>SNw#Rd{P&&0}2s39x;AF>e8XXx(fL5bFlz^&cNh`U~EYS zxskF8bKx;qv@Ni`RHpT%AMUPtj-BWUDoGS>ew<5$>N%bwO-)}zL!asXIatu|xa<>%Ct_n{hf-8iGAxWVmWww#bp$;4Y z3u2JtmPRtdj*Cvj`80g7m7|@*(nZ3%Ndsk3c{fydQK^h+WNSay2-=M6Xk4`m(1MC* zS*6ZTbd#%+;HX8X^6;RPtB38xIHe3%BG zOs_i+==2|n4!pdxr|CYnVTgMy-yO$qwHO1#gkqL9)T*WIJL-or7hVi@oOZ9l+~xyh zeoX?!MX3+MZ0grs)kr;QMna~#O<312fJeQ`b%%!?~|YZ(u{ zBBXl%pm{*MQ#KBx7cjqqgIl~zcDYA0M8axZw~MSbzDLcygY{H?HFj{^QHGa{1qn|8 zBjSY*eId`*urLJ05!DP^{iiV1+54AzX3Vt9HZ771)sdXy{~Az(?7kmJg#AJ2FodH` zmfCjO@9FiAndSKWuHvtrDD#|$LY)T4T6s4(l|x?L3`0@T5+Q;K;cO7^0MG~ukkohl z6X<=VG)KA^7{p9rS4|x;CaqPd=+w*|mF0c#8BwWW$aQqCQN9TCpDs5qRO#smmb)@3 zzEqWrCP{k56`9hg{f(vZVS@vIf=|D@bW#|XDIFK-nq88@(!QYaZ_ST&9hGU_8Xwn| z!S(9$O-~MHtZ!v*OX>Sy7YnY6wzxVYil%Rv&Od;SMqc4B2}=DTZpOT28s{MGF8APw z;J_2%)NDC~HM?}E=<%0^t|(#?h5Bv!HZLiwfu*wkz7CL!^fD*@jtQ!*b?cdT2KPFROfAdt-D|Q`IeR zTix3o5@S)?fxhw8nkXQKg`eaOrzF{V{V!#R^meC4sm6z#o)QtOKdljWT((nh(*qZ$ z=p1J#{XX;;^e;5nT_mv8i~5<|aPAF%W%i5geLFDA_1@&K_SxDmVs^Iwc3<=#+n3k( zw>t3qx3|cND!sEClRC7>E~q-^rP1;YgT6?<8p=hc;YXT1g))1gZcAT7!vN4TQgKot z4ODj@M#*KJ#^&gbl$fxKCw1xX_N;&=?|}^auaWNWMRoxmxJqWDE z)ZEqa?Bo~t3+OFhS$LE_4HwVc${&X(^A3L06aUYbFS6wVWxS z_%ercM+h9Wjs%wOdQFpNf0+g*H>IM8Ce4o9Jm*S>`qrdL%#6coY~)sk(EU7j2m#o2 zWhF(hor6Xc51xD>60YmRIb)|eH^s1Lro0Xz{OKDVm;c-1dnMWav%P!)Rovr+>zX-c z($XpJZTKPK^Z2@C2iC>x``&0UKKX-#>b$ZQ)9mYSkoHI+Z@+m?tobe9% zKCFFQBdja~*jmvIoxAE#_pIF1IQe1{p0GrzGFkuICA~U+HlK6M9SGqr4xw%UR`v8x zlnxrQdqM(pSv_{`+_ep%jry1OiM4aj^(YC#t!%}Gb9SzI-oJw?^J_lKU}X9J+VD!k ze}hmj-q6?DCCQU1QM1j!eG9jPpqhi+_cQ+E=b3n=8bqmb7b-k;X+IQt3Dsk@3Ep-JSH-%{A7i3;XCt}}z7z>p+FwAmBeg#L z@23Yy;%yW!4G*gBaN=LBO(7x!*Cq>DJXnXs_Nupwi5=;!-TaG$Yj;joQ2)_w|1(yX z?AzL~D?jy-Xo=!^XDn)RQp^a+WLs&m#NO^dpQ<%p+;I2IZLjDm%MJZ;AfKY_iAkbpm3Kg$?^{_w z_j|u3@~8=vUwX4;%}5vSCl+=^cQlUMBlto2QRCLbk*(XDx-BR)tbTPFKFR;--;RO8 z=Y~#IKv*lWD@Has@hd_cU`PhhnD9_uPI~7D5SGJMR`+n$UA!M^PyQ{u)Rx^;4_W~+ zWNpevtDZWA{W$8)pHV?pJX9TXdj#%xwsQ-dd~LH>F|YYrQqiYK0dBCN3yE*@#qOez z4$Js#o?byj5=;Ms_K(}w{=r5KCM0zDnx56KEZF|@qzJDPRXX9m0hjR0@`t5>Y6E=m z&owq3ShEjwWfRMm6dI~%(IB^|g4?AtdQ0RtejCS2RNjPiP<4h1a56O&%+(A6w~9AT zf7NL0qM^U>=fT(y^yWSF&jG1f3BF^ga_5kBj|eaBDfPt!sK!d^j6rwl?FB*1{gijy zWLaQ&y4u?)ZC+h-kEFLoQnefM=g62ndhC{|uUJx53L|OWJYoDVJGS(ok@24@k8`FO z`YXb@6wcd-)Szdr4vgeo*BAP$4@?q1ia0ByH!`vveDfij-&&Bc<%qvT@;Gm_^@#-$ z`2~}r%~K40aEkL7Iaj!DKEd-|vNE2O317US@8bfzFO;|Z1146i)&J0-U(vt73mmM7 zy^nDYtujHLs?=T1-bFDTM*Nq|BLWuIWPb`nq!yF+Zqo@ebqW&R9n#)me&zMO#*x>@ z@at?diGd5d$z*F%h-p^YWUM#K2V#UvRDNHPcwg@4u8-1~$CQX=&+qIW@|#>=dc@{Y z;%Wvxp~Pk1K&<;cm-T)8R!Q{@z$h(ZmP3e)U^lAKw9qf6n~qtN{xh!x))8Z6 zLTH4cf{yEdpGfoVU@8;aBo-(no4>wXltnD&)aIG_WM|f z2hHz;qALMJGm>yjKIlTd&b{Bzwro6p^=bPu%si5%gEC2C{06O{aMJTl-u3z$+GVkN zz(V;|_XWr%qPV*?w-vOIiPl+di!p88 za?g9jIQfnWp)PH>&U;Bms z;{q_2Le|`6gj+^)A=4!rQwkk@q}A&hD^9TS7`sL0M``q=Lr)IX*qlp-mA8x$BpGus zU(0&PB$iauiE;-lRc$lmngiv|}%`)N-8WWXF_7XGY zpa_y4)Fm^jkRbb_9wD{dbfe|#$HeM!i?RYj4Sx9cXlH&-GNg) z5zbw<-tfbk0?j){p_Cm$j@x-O7QSc+ez73@iCn)rqTTr49z3vxv3H*n7 z`qLqPI-64SPDAFGyW28dk2IM(d-!I%S0Pvp43i#EBL|hJ%JSVXMP?w9w7=+tBq`-> ztRQfalZ_8K!dH!8q!sAJPYipoR`7H+eF?r4N10zk5nr|R*>V59ifIz6p%%=jk&}qV zwJ~(l-a9n+ExDYJ2w|SPa>OMW?>z9rBj)L#-BYzIYt{bn3E@`!auMrx@VT3kfnuk@ zC+bQU#d7!OPUdaYV3a>yUB_nP%0$_U;eDNtjhKjUf4=A`rRHsYpezUAM>%Da z2WRX4JpZW`sn=>b=H+uny3$>XS0gT{lrqSe*W~bN{K&x3Iezu6dVU zG`EOr%SU_FMBkfK42tvhInx!CBw~^JCw}4rr4n>w+XT@DsM?$KQ)Z1i8G(M|JC<9YA+&l zuB~baMuK)RB_FxUd+I+;TE=g68W5M=`b-(YzLR?^V8XsP{w)Y>`oR^h4uwr^W|v^S zWqx_SyLc85dwnUR{-C84^iQ{Ibk3$!Rll7X!fK6SgoCvW+@5H$TQ3G>Weogl+jZxd zq?@HY_N?BUnK#ocwf@;-65f`Jfi65u#K2NI5XrqQ?5(D{a-+!{TXz|Rl5}OaLFJ26 zU_hpV9X)wV9@-=sq@2)|$i3HnM0gvYMJDnG--?LY{{jI+7=XwV^xmo*UG z|4$eW$%aetk0H6!*uo}5-1bdvi+q8-k=@S39ibR=yUJnn+i$fU2hifD zo%5lpvVjiTja7t+uCr#-kPSgCp|TG<@vp zr`!>mVOukoU<={q;Jc7yILL%qWo4Z2$9Pu@Dyw&>S=;h_nXP7;S<5>$sm@0^JKqAm zA&vgAowca!)H6`4Kfst6(9Tb-V)VQb9*L<0F4Ja_Wo8N1EC_17EkTU9Kn; zwp;}h7RIohuEJ{MMO|T%bLaQ}{AMLG1Ij9iRK7yf!p@@$waq+G22Yc-V##yabZ|<} z=$s0uRLxtt61*qh@T&~7FwG1ZG?Qh{w|wu^>!~M_%DI>J_7)8^pQd-uFE`5Bbb$gL z_4ZLH5mcM@zc&Ib5qG}gSD_mkZ4|*VGA7`exJDTASjhmi#e#!c@29$aWXCC4WAc_{ z0v)Mdy?IO4J54sIvaYXk7pFrU+9J~U!o8oU(L7YDc`s)wa-OytA~b(=@cJVX`?4kY z7x_wjy#Q~nx3QNmfE$+={5uwe@3h~JGl^`UV(&qV(#$2*@E+(u+0Fz4N3xsDH9Z-a zj&(SR9eTF?ky6I_NW(zFI3c=5l#kZ9=A+SWorljZ?SDYpJ^C+f=!WFg;|jz}sUF&y zYN6%5VlO9M$uBK;CZOn;o9dNO1-pA%yi~|)=PTXuAEq4jq(l53^{uNXl~RY!sYoF7 z>=;L$KF8Ice%}sTt^wD%kYrq|Oa8Eba_u%1AC;5C1o( ze0s`#Iv9$rjseL!hyEz@-s`z^NgYunN=fUs-8#?av$%Ug88gYhYLZ9!EpBm3i( zZRJo=BYa{ybk6M>*cei&cY9?y9y}*Eri%2y^#?uUX@_*WhdgsLgP};pp+_#gi`fUk;wa=Nve|IAzP=X~Q+NyylM)J ziva|~8Kc1)jZMQ=?q6Ky#YT>r%~jfqqK@IWXM=*%RNHFaK-V&U0jr0`{%L!{tj=PB zSj4dMlv*-Bob)9yJui=fqic~5hG z?>x?ml)C@=!cDQ)^@*IrCdqlxQ`Z~9Lk57@-j;lz1;5Bd{9 ztE7-PFaShW1c5q?I*;*49~ZjaNWm1s)!Par{nhId-LS0kpQMxANtk>R%e?HX%kFKB`P7w|FK)z@aL z#SB%hpV>m|QO0>)b!q)}=IWa(@-jQ$3iMOQ4$LpoglHp1ehyW58l>4b2HyWb!gqt1 zAZ^)+?oA!~Z4K*b-XJn6&C2iU?AUQr{TC2eBdF!e5>qmG1-1Av=rD6v34R_(|1Req zur}2PI*YyUmptH9xdHzO&dL~Eqzaqf2-3h?fK?g(?c-F9*mJL| zn@_W47PDSTonRzGEbsM+hdwhtlNwpw^_aC96P9@=BitMSm`RY$QdOJp4nc@V*c^Qe zfasU6{AF7A`RWguZR7WeZwi>R*C2;j-{O~nPMr8c#qTI)7rUe#{X>NXuE3 zmDF!V zt+A}bmve$gWo7KeP!Lmvj83ij+p1m35N3T$*XZ}Qe{&QDICB+UvST3G6!!sgwEdvK51`saNC$U6sMx!mw>phKNQmO z$3D$FQ*z7G!amElVuSIu?(8A2VRifVplyMjdUoRo&z!glSAnU>>?Z6CxGa_N?r|25 zD0a+x2SQA2J%cUwOs~?SAMoZ#XV-~65O69N}C(*61>jQcno zoqN?YiC*?1OrZ07@IcV!1Z%|-Fe@jIy3$!6;8sEpu zk}l6zE7u<|G*-5I4wgS9OL86#>T?r;$!`_Z4U1OQKp6Rh4H#{~Y*lco2|{t{>_4Mb z`Y(nxbQl{_5pPeuJ-C)T^nqT#?g>gGe}fP!B`thrQ$rA@3dAM>j`xThOqNweB*ZSA ztCK9B4OlYus*cbdeQGFJgB=D$-w7OnX=lFo7SE)`iDd5mbwqNdaGi7)RGSnb_YUe*Xb@^5Xe?yw3AH&N&a}-V^x{(So+)K9dqZE#Z=g*Jd_s z@_iNr+}Yhs$U3_WC|>MAI1$RRI}lqfjpy6}UCkBSR@X)IbvWcd)V3UV_h}~W7iIVT zwmP1wGs$0%d0~IxkGF?qfFjGFM!z^7BK9w_AAb}aZ8rpGXxPcQG(tur2FtY8yaueH zAk@&}1-joZ6Y2AtOF(9W(!T11Ca7207cTHEIF%sHo1jT~E%9#*{smJ=^_>pqJqLD3{s) zpHEr$Rl38S}BbF;Axv+bz-W$BP|bA@cZLQR*q4RmxF?y%sQBF7e*inpGK zlq!-t#aNNH8VX5vajp^w_gnkkxXc!adZG}>562^8rXp_Aq^e34p&R8=_fz!Wb64OM+1BGi9?q z%(P1?9~bkjvF*(x8P1|Hwo2AGC!9+0l8UCcvZr9s?H}@r;Fv zqc=~WtrNO~;A&lBL8-OllXvsIWB{+jV!ZteYoE*OIDB}Fn&d4@Ku-Z4>rDF~+qt}o zd%8$^T*wX6UB@{3!rxvaw%AR;C2*Mxc(!l;=kK6P>|DkRGnbXWoZ=pDJoR?z<%-$r zxyu%9)|RkTW{>N9jxtGF)nfUeH(PavJE@XXPb@XRLnf;0FCfS)$ELvfxs5?iNGn)d z$=OdCi4@XP_JBN4?RNW=Rer6ef$^}X>E5#fn}CE*g1FqKNB`KG3)NQd9(x3cU8*Pt zfS{IiCBRL&aHb~PB1D`BZd8c)^Kwse%K-(Aq6JeDeOo=#ge^-C=Ht*#e6#-0g^S^L-1cT}qU+T3)~s2gOXCfmv< z{+T$+VOWnMmFRi`5|b9eW^wj<0}G~nTj8a8%so*#sUxBHW->0P_P<-qD7w4$+|Qx9 z&$`kBxftQeecoAMr}J>rrrL~fN4Xa_B^5cEdy*w3(j&?D(nL+Tz&K$!Elp+hk!D_b zIP`_m-Hu4%)VO5-Q&mtghS}4a23lh0$Z^VSP$|}{qD`;6d+(xIT@Bb0I<}BBSv~F^ zxBkvKv-dl&HGjAHM|DR|oDw&x?rr`}C)v=KI227j^c*>-TwyXvNS17DXSobEcz3Nn z0$uk3@0K;Suf4~5Y1;&BCd7SD^4h}dXU&bdv@}{a%KZ(9)z3jUVjP>OP(u@l@@FpX zq0=MTjXaOm@!97wUS1|)j2c{pmLkBx>9%0UZ$9w1^sR3BP~q#q0wp>3Kme)aPJzA* zXNB@2JXW6&iN}R~8btqq=+x!8(1M4i`kkr8jJ(zB`pJPZL7(s0`(1AOY-M6PKlSLo zUR!uVOOq`+kbsKvI{)&u#++Q4Hn^o!H-92eIL~P>#>(JaR{1&2=hd^aAu8GL@!TQc z2xqvI#~%z(;RZ?b(y=Jx1x0nT!yE@(h z(>HWxFCIziM^gelU9*Nfu48@+vZtmiJdP{Rn6bKqiJkkNOikJ;nONjlh4$L>c*IV3 z@|Zw_KuZ*ATev{+z@UuDUeJPQjo+pHLEYgP5103rq*!{->xF}M9idY@>FO+LeN~_Q z)VgG#Cns&I*bxicT2@i__S~}yqC%DgpHXubI#Q)ayEC zI4>#_o;7GcFAWraziMn8yiqU*=pXQ@eH4Mdo-8$dJX-J71?NlK2yzY__v(WA+`oNP z=Z8A-)YwBh3NfhoPNP#aeSa-wmokmmXqB*f@u1V0oNvs*DtZfg_6^(7Y(H6!)}7k$ z>e?fhX1_hL%vRfb30#P)lL(VldpWo(9GEYOS(M1#u;9Q<@YXg;_N^G%X+(%{Mqrl7 zH>5Bl^w!XA)x2Slv-@ZFkJ?Wf3N3fb6jgmyeIM~v6%uPw*Gi$v<5ASBj7ne_3BM%1 zN1b_P+n?@y2m4qHZteM&{7ia`O#WW-^N5cbjt_LIwwiX$A=A?roTeWwBkaxOd+E)2 zdk+aspesfrs^N?%N!`0C2Cy3vWG74?h%0Hik>^b6hn?{Bw+}Z!mHwil(H353 ztCRQ==*vcjYB=|Ut&&hz6S4%pm}N0efv`1N>$|#C4<@q{t|-taj|O`=;Uv$s2dCb) z?G!e`dJUI{(}FhJ|0$0c4E571|?>K?c( zVbFMNU1?KjX-uHs4KYE4c$)rBT~9LZS}B|4x*9QN>sbwjs<_i4{`T0;r~Eu4-AGD7 zjtOSN?^n}VSaF5MuV~Y*pps<082X?LIAz_=A67xShPo2p;@#1iksy5uZn*b7CyCxE z(|B4q7u4Tc?+>=HfxhP7>$ztg72kc&WG2C{ z({&^k{+Ru6GSFow>jUw(msVLSuFaf0{Y&bnJzImRQOa%_!7nLJRp3|8CU{S>`{-aS zr%hvJn;)f5hqAn;{4VPc%$Tn{5036fX`8ki#`?!!t(hQs<-3HhlaOSZi&x~NaUkFMsnC0QQfBk} zA8k+Te%?~;Gc@KLcnOO4zWc7bV-)L^4($K@qK^9K7%kZIONYkp^WBBtzqjVi%cK>2 zXJDty&ieZ&YkQmR9wOhGHQucb)A!pw>eDHv`nr67MvYhx<;mzkReJ=zAbo!KH(~hS z7(U&9-b31W^ADe&2A%T@p-2Tb`j)hl zGn|(I!(bh1oD?JCx_ZRTXnGl-|7S5v(Oxc>)>U@3#zSSdspGnpmlit z$6H5Pjw_8z=!$@nCC9oY5VDMCH>>RF3d^M=-|~5S#==u~H&U|GwXt}uvhs8OiaZIZ zzP1^cO`wPT5((;rs3v0z$q$Or`P^j>5^Xv(SoLqS14E_vusJ&^;t}Dz;J|z*;He>1nK7sU2dIH zb?ln+8Li_=Z%pK53*;tRQx0XaCM*&it2JNEo<3PiJS1%4Kw}wd;=9>V{r1jpt$xDb zr}lc2$C5Q|p{I-d-W<#hjFn?I_>kksABr^BM#tfuG2ce;yt4_bT*X2=%!ADNDM24y zu97pL{VKt#ChfK|{(!Q0^Z0=F9XI(aM!S9l<~pLdj838W~ahBw-Vmo8V6&d8+mayAoW!OyUq zhJw1z#YHY)MChh(r2iB?vo6tTy-W}Cc+&lz7ynfN;fMa1KJtAl{lAKc{TsPKiN_}X zIT>w4z-jgT*~5dozw&2O z!q3QF2sX20sVlmMhxj+pt6TS9qG>B?*j-*W=z6`a=^SKbr?h8&(Z>0|xlY93KgEv? z^hl~3YNf%e4h2SI9>5YHXsBA!pVko?g;@DkvN2Nq42Zc-&WLaH(cdTlBjxl07V7F@ z@NVPDMmV|`uvrB{O>cW^8NbK6PAdhJEwL(rv%1IiP!U-r?NNb4163qT=Yg#YZ1eO-;0!>t@|m2w)e#*Az0j^piZHL;q0h*&}fwA27H6|BL`X=hp$Ryt-GB zuNU(Eg-)KqHaKKFdzD@Mp zfTUe*hSv@M3$}%xU3n&q3HX?igkRT-EGq9Oy{WP?+YXcq**5pt9z9gwQ3KZS?EmPD zrnq>SxCS;|2jLwB)3w@D_DR+QzR`^(a~}SZ#XWD4_fs^ZPU*%v z)$i6+AvL1v-9 zTdkL`{Z76sK`QHoxBn;4dr$66mE~%ct{0Gn;c&{f{YD11$u@CH?&aGb$?Z{{|DL#{ zTq`+pE&eT;wv)T%en@(3ooa~18$FCS@p7>7Do^2A?w^9M8E3`W1l$BC%^W%styOki zKDz+J_$T(ch^uqw%ejzhHo?DrTr+d!KRSXj`uqG+XscVSA`b`q)Ana?=d!1$n^wekNFVshn>V=ixGAu8Ewc*TX zCzTsPpC3q5qzhYKgUTgW6nO+i$Oif9z81Nu6hC(&ZJ2={);6L68>QG|pdO{#26+mF zUYA7o;$QEmNL8W2OZ2#Vgx%CoDT*7Kk~1?Ue0F8pT1%KhHTv%FMgahE+04AONaHKc z#&Y{5&yn0%T{6`-gAIf8>k)b^BB=*($Vxf87coa@N+# zihdLCzrRXwvD^_GlM<;?hP`cTh-{xzN@wX%&&GEj@rZp#)p2qSHd%;)N@&%ncjwl4Jw%jnXIpr5EswpT>iWpz z?01Zlu%XSbqK2E!p_SgdGj?S^8@XiuznS52YHY9TlgB(tL?bVhK4_}_7s4#w)3(G{ z$zJNd%0DqC6*YKt%RH>*Y^`q7hnIYjdWSXzvNj3%(p&|c+EAos3Cq{K+|fKzdxqc` zkY%*N$JFf*Z0~8E_&Q=XAd63ZaO{IiFNKqpv*1C-N6G<}9;9UL*Fw?@FvjQWF6f;7 zzU*l1*NNr?;mZc92bAlceUiSk@6wu3{aiu3I=-8Bx7xW#z16~x)if%_dzJXb2a*q8 zjJc|LT#2>L>|RXZZ$eg4Efez<+cLmi|DlgWB`vseNDlE=vTv4ZJAQdFren9xqL4TesoNd0HC^BMfx7E6s$OaWS>njm;`EGlMj8A+-}2r8r()Y%&KPw#_#-rkJc7sBb( zZ>82+9@8@RT?Q=Kz^as1`&?|r`tN*Bj6|c1mXqGHwoo)cpe(5kZ|N?+Hs8>ZM=o4a zMVtzoJFNEmPXAHWy3+^eL+aRegg;hz2gil>`+BMd&r;!Up{S{6+Ikv>*sn&FZ z5*0kEhbCitRj_!B@bZg>(M5Zdtr!HA&=up!%Gb{O@hV`-LACLPqh@(UEB4Td|91W4 zy4HKN{ME1f6w=2FLB7^;Cg@F(j-R&bKdx9T2eZueDJuX-&G<%6_Vzcc^41qf2D^bf z%Kp=%bD^o@4~Tv|Pi^G{dfKDcXjCF>&u5EwVi}V#5c0@A3D6DDDw6NcxTbGc!|ayV zG99~u8~?0??t{fv-uL~K8?>1BBR7p%eEq~ljkc?rk%7w(ot^kM76l8Hgrm)7aUrG< zVe=1>Q^#W4{5XiY5S7h~ORc%C2I4k>ohL5~MSS03ht1o;XMCG(DE$7>+(Qb48OCnj z@G!l#xwD9lI-;7b!8&*o-D);_DpnavHV#XGZ}jt9gacC@TpA5$N>>fDHUM=#0s8Cs z)j8n}{iEd87x09S{9P=E23+&Rq;@Y#pm#A|-iR*btdqHH5PJI4%4fFKrO4N<$qnwY zS26?5t5w%HS^@Qnx_~EecM0qLk^m|Bey=SR;_WG3t3 z;={gIk2v|`llZvpKi80q$<-=-;J29bMe=tI;d%>~_kfx9#({?E-jt-l!+8G@TOf0E zVXA;|0rGvMaU%-hPSzr+M36Og6oO@@WEvfA2THEif2}o{9pR?H1ce=;V zRQ3}+5L3o{_o=d{HZf@LGp6^_H#9SW#e#{G0|O3l*n5S-FuSx_^;?I z(JpZZ0s}7oR`4&Uh-7rb{-9P?&5zGUGe;#SJ$r|ZYY;AG#1@Ms-|5*HLmJ+hXwj}T zULKqlbF~iqL9+FG;Op2D%qARDw|(C&wfh?n#KbHVOeTsvfq&nB9hI0x**>mOr5Je5 z&uvX8yh>5;Xx#YNN9WRdB1%;z`xPV(_{Bn!VWD% z7v<18XX;sPxkBPDB3~P!k};J+IZpefhQ)8pCnzMTieFzNg3uHFsxjEq+f`X=F5%&^ zd?*YjvK)|ywjRHn-e=dZ%}L$f06)aHgt&JA0Z`{|c757t1@U8PJn5 z_TKPs)4=pg5W`d~DqhwbWTkG6THb{OgqB#Uh z)#2tB4>3DH2ra2HpG$BiRQm%IdWhao8uUbgCYiZrEN`;lr2NI#D<})Lnd_&O(gpJ9 zyaw>{Ul6YFgm8sXdWJh8Zdt26WQBqdde}tkf|IU;KnF9Z8J0!wU_{Zw z+g#HUMQqwHFzEo@DBo|*H4VL$NA-IYpYwHhSVZV5{HVNoov8#S2T zNd`0Vp2rN`yI0r;Snnw|4wnKd~_(0*^<~F3!4&nIch3 zW_mvm%Y_(CO7|iFB7mCUkH=qJTWE$?blPoe6IHjW6^PG?I-_ZbJ81cW)S88-nwGj} zGk4zXv8*&cFUeW~mIbQ1M_^53GG-zzPM$)RX*)`pp zs&#MbyidDMf$1X?^l#upr=sLoQ4KKpzR#4W`OGt!w3_{$jO8)m{l9ChGh#b?{Y`j- z;1Zx^+e)$eT-B|3n&+hD$hQQN9&)58i&<2qI(qY=->I;H2=VKG8##Jn&ELl6Hz{UBI zN1Q@6r9Il;X-8~0c{UrKE0y08llY2c-`>u;g^uC>#y%v<_IOa8Wf^%l$%&+P`Ow(P zurLeh>{K%yq!24|?w2Ef*Ph=!&5wb0ldH#lY|M00ro32PdR&K*?~;Ii4d_*e1sWr> zAT><4=%HrDJVl~Ir7!R1K0b_@y}hLak@)YnH%)HtJf|szY9{K&z=px?ZXEHPl>oNB z*t-n!x@LBLjB2sl89wgvTs&)K%iV^~9!Cq?$T6uQAB{q`cpc7Gt54wLg1CMoApb7d zZsAdR2}v?{HfNr~qEJ}EuyVP35;_(h&%=KVkuX5|nU!x8_ zlq$N?CjmhH!>*FN`~3~>vsLYzO2?HJ}5^49XCfhI9|G;7;0=YMoZNz-*Lsa z;9{RosbZOQ7}0Gj?-G^76<96x0-V$$p7zmwCT+>j^%FXJ95Av6{O^CDmNrtZ38>bI z(anARe~_vMU%&e43HHL--?}c*LY=^zs8@j1Y31|mjj=Jj2HNQ<>)Nx(3XQES{!O;W?&ipk=^ve!c9anDSPn#FS4d+9x+SI8S{o7e2h=gSLB zw?@HVkDLn{5sg1jKPQ;CLE#}KSA^%t0jL#f!22`hmt+vR0Rdl$tB2kr);)!ohbbA( zN=~)UHGm;D%IXr}VCfmnK+`=a9$}s{p@yN|;K+~+ZFCkD-Eqsu^}6rR`(~E3l_}6Y zqT|#8)^J-FHY-xVQK0jc{86>N!PK!+vfGtJ8QG^dQ|0fZxD8^k}B2r zRblrMc;T^2t-e}rt*N2$&pclxl%HoXY%VIh3@8M>6J^0=DT;Cdmc+BxA$sHYpNi{L zn&g~-=>x=bq|F!lqX@OzIL~@p!&U47DhLtZii*LIMLa6R7qk+nR=1bmd2<{S9>ZUH z@ViDSjmaEzNH=WRyVVS(t^jubOzDjW>L!i}shB*|{ridJ)6Tp4OPJo7KKjq0GE=cG z{(FcWG%*`qs&2kr-2a(hO_d99lSY!B!(;hhdf-W^`D^68=qXe!PzzqJ(U!AS1=f?; zEZ!}#QjjH6`0VkLjXwz_MJ>blL}n6yUH(&iA!zR3-Sd00>FI^p{@nWn4i5AvYMH+iU)=RGY%YLianKYuS<{L$RMlABc$^^j_T&yumY zBo{9UYkvbuxMn|I4Y(g8pmhlOGiSdGs<6ohJex%fZaVohfuoFah0Y~vdO)^ZLd{TH z2|=tzVM0kB8F|_LverS6%DtA>XYlaxN6?q8@FnJXj%s?u{u!U)(}C{ee?mmyZYu z6IkYaH66q>p4``6-YaLutYX+=ibJ5>gc;eq4mo4rXS)hvHlWgeNvQMxxI4h-+1v0n zTP?zzmgS1lxTRh1xaHbbmUIBU(nEJe6Vx5lWNy^JZAkisVL5aRG4D=vjzj>a!9-KU@v`%MsBd~K=Q_&Ts$aG+Mwp9cy)Ow}bM|ly z{-BgaGPwP2WpDd!z02m!xoIMW+~f);Ur_$CW}u=V^h^kK-@D2UOMn~Dy>aX+s%vCk z)m>m5rg`jyHKr>DH=kAOKB#$_ofj_epKdus3@#2_O?|jE6G+paJRfpp*!|Gt`{BmC z-VIA_n~hK*`Z+lzJaFEPZ)2`jGd~r;+#t^&zmBPs(o{Z;v55Lo6p@J}KG59||6npk zXC~AtDbQa!^|dar@Ji}fy#NQ{QbHeqeEZ>%i5!}YEx4m$dxflk#g3XG4H~;Lx)nk0 z;aYQd#bu)V@uvj7Pgg4U&yEUC(L;jHiqM`rE$Jx-vcz2`gZ>qdFS|mvgDS2Ire|MF z3EDwfmOv)L9kFHmAl?K=@zh(7D(1WZdxhPfV$H#u`8C45PM-{IkvO4qdtCE=zu_%e z)BC0YKO+yPh00THG>TUi;SyjMXCEJHBKTy+mg!Sx3rNn}-!Hk5{j?+2*3M*h`8v&z zQLL7Njl~~t#%4-Zt<-Jw9#!1E&ij!#?o_aKKX$QTat3{BDC=HJ3WN~@sV&}5^I-$` z^*N1#O)F6D)b20#yz5|#sf_vg_o0kER&Nn-@(&+~`=b(l} z-OW*{3?HF~xi3k-E#LQFJtuOYm`|4*;V9X+PRx>eh5!d$R^0vSmQheH5YgK0+5arm zwkGhm_Dcp&>pojkB~~?6HGM@F)O~y2HM*f|8uaafd;h*zXb$mIeV02ay?#41Z@zGTgg8jYIGNDzVkcr`)SPZeI!jd&^#Fc1NK9>X28Me-P zIlSP(T5IH)3orJgrv8f6Bk+eLo&8`^nA!5QD;Y^I7r?S}LiQ6X#G8BWOn^?8wOY5o zS8r=7<=TeGyZAR|V1B8rIOc9gV}vv#i>^n3Y1y&$#4qk$gr7k^xg<SBX((w^ z{oPN>jrLwp6#k*UT8*EVxEVw3$%^Z+^BHs{YkVQV!Xf+=V>t$~I&?>S_Fk!{35N*L zOw1&14B(G7#uNFRt`ZI1x-EpDiI)J<%=Gd&5pV8vKkAfC>;(cwP;cgcgV|L#A|lch zE4jbe*|hSnSK&=osMn7OoG?G;hq@gbKkW=1ZuuVMOyFIdTiH!>dK#8&iTw`2adS32 zSo;PNom%?q5#9t`x!9DWVkn+n$8K4{(`i>~or)2@+diO4IZZ^NvMrUto4rLi~hRZt3WrkeUe7L*tNy8h?vAv(htt`nhiY|Zbafp;Bx9_0j zd&wy5&vk0RNO3vBWUh%B*}8x6`~J(OL*~QtZy(Rar+qPWlABzN;iPL;Qq(MW->ERH zQPi(T+(^^S_y_#N*Yuw@ReCu$cUx-4KAe9iHFMmvH`-2hy_VCODFo5K7hR3$K}CkFyLY{nVn z@ss3EuLWa9?c}@cz_I)(EuS?PJLEs^4sFBW=9f&CkZ>QpF5xQ)tJ-1rsSyVRps-1u zT(Z6ZHmQVUrZPV`hHW%qRCao;$Rp*kI<#4dg>X+({s{^y1Awjr*MezV1`t~~G3Hx`Bw4cPw_ z7WyP2zx^Q`2C}ICl;NWzsVicUkcCIszn3A$3`(wOi!pZS5uu>tuTmWof*NA5oRPB#QTxH!))Qkb)>aPIj&;+#x(@OHUfhzf*3Ecyh2*`+8 z6Y3ub64(VFA-vfWXxG2BC*S`VSvq}T^Yy=X536)ltUb_V|1E#QxbdndLp3r>VPmh- z!=qCzzb8FJoVSy`YnZ8^v4)#XG1$~DFR6AnEnWb*4wtdzsWNJ{Vllld;p-Jjb@Ur7 zk#R*Uq1*gW<_cM_48Q&!@Hk|%KP-B^?FCCjt3+l@(z^_v7PC1zQ|8snm&vV}+eCKl(B5#9*_^rWnu3jbIC|K$Sg z$$NQ{hi3S<3GxNR`;+YHqRrz+jO|EG3k53`>w{{ zXXRYfb5iZS04X@`m5skZi(Y|YgDa3dqJXS2B1&oc>qA2Po!ZF{#47Y7<>9@l5T!Lw zeVTGuJ|tNQl_8U!3boUTqpzv)gSw)#TiZTa-Q=eyy|-B(u6E=Gb^M#7%PPez z`+|^a#J%zDz#G*VVlQwL8XjD-3gNK`XZ0zeVP0O+MR2XbM?`@PaKG`8-8+d4Bko0Z z1--G`51_%_fpET%5N@}19E;{$#pDbFP&@J?0-l-JkGP(^*_51@S~Gi3c7zO+*z}Id z0qG4Vkn4pKR@4HP;hI}(@^-Ll3)l7dgdxdO4SU$*{mYdLQ__x*s4eeOlaCgfxlK{iwuBpR$@s zhtz&)4YHE+ywSGn_QG#y@mY_tZ?Y)_s*N2{B6kFbpoGeuUTS3@j&g7ZdT{I9s%NdY z-S=>Hn}>87pWamT_1KHMumPgHOKo%Bbm_?}k}am5z`%90!)G2A%DOiEOdYv~jWA}M z@OU#!QS4a>nyf~Q46SdShb-b;qY5{3DJsPY`uiXy9Laq1C`6c$^P73^<}GEdfjUS1 z1OwhbCAC@f=6#JwrtYf|L*JFr+qgZC`p*E~X4@R5fzyu}U)?Iys*v~C?~UPJox-D| zx!Ag#?N54nNRZx}J^q3vHbDP+@UNEpEJEWpdZTrY19Pwtad3O;ol=$0ygihabAPaE zqs$xX_226If%EHHV9$Fb;?_U~TrL1QCpjWJVAyS} zt7>&m4j-tM^_qbA0L9g0pS@pH6BiM6w35AMTwR5Kc+BT_DZ=iVIn*pTpX1=uwHx$)`A~mCTSl zH$#!)X`3{}tCX-Ey#K=q4B;n+K88%E86|7A>4x4%xydI_eRfL_nrsg5wv(Z?-$c97 zfnnoZ)|E9GD6gou$a~)*>+^F@_Puz!!Oct1t^PprNxp#sSi>-@4}=EqXU zVMF~2%mhbd)ok1El$^30ti*B4{P?lu@i7g*t4IHF>GS(Qg_ehBtrUV>q{Tw^bhynl zKzhg7uX7p!xEia|*f|BTA<;eRJnM7xit)^a+4+T>FSy|^gnV;b9kX#jf{$+E~EWLYJ62{yS+!R zD>aYs&c~^rPm(XDidqsMBhMl?{(;1zBP!LKl2>-*g6>I}hG7Gj$ltx<;5`LlBS>xD z9^TSEkgWVQ2p!@*6Wy@I*za54t_>ELt36AqG+{;nlQ(%_yE>pM( z7Q!|4u;x9{9t6ISO_i|!Aip0gq?-6Rwfi1Voi8f0W69O^Bfi8_^yQnq2JU5uKj@=H;%OLm3~ z4-Jcw8l4ffJx$l1Fuv=#1ey(7P*xp=4o&~H{Y$1vdPv^`T%m0B-F|_G3Q{ID@~9FL z+=yQr&w4GAM7?i?&Kc^9Vdmq*WVY38AJW5iJDDvhzE1<;K`|hg0mZCy$~%J)p~GeA znDX5JK!3ZqqQOM*E|AsY=`Rh9E1uWfs8Pt|G!F6vi>-qBa^A6xzrsQbT^Jv{)Mq)F z9L0p#^kDa@<^OoHOM>sm`ioGR#pti{M{exg8NHghJ6<4IZ{Xze0U0rz0WKQ;h3qIuJL)-dI9SZBk|6Yr29?k2y6a5-!zd`gp2$%!^YD=j~mEwZgl$(_k6 z|IR4UKyQ3te&$^<3$v7aGg5m+;@ucLaA`^q@$A-8#`bYHmm4Ws@~o#RS`~{g?Y`%9 z_VPf0$4WnMVxOI!DnI7@eync(&rg*Tf71N*6ONQk13U_CnreF<^u^aR{uHN4o8&Ky z1t`kcJvue_iIA#y%Y9rrbF5jy`B!Qf-DG3d*z4;m9Q97Drv@WD_lIc+iiSu ze6cJAZ)k6{{}GeiJ9*blT{sGKFIhI7U*x^lx2Ar#=ViAaEay;?{lyR5ar%3>manz$ z^iWkxKJ6s`y=xXN6S!31RhJYuJLvglbzBF`nkVs>i0IS=*r-0HVqIGvS>S%4R7!n4 z@Y*0dvY`Q>^_LIF-(`xJoKeoa<5t3&EJrL|sr7uxk5OwkJn_qnlHvDYbyNyI7aj6O z&E>nrKt4`Mu&fdGW1L#!fWUK~bHKF9&zxSeRf+$uI_dsNj+>b`1}O1(>KZ0mQChlEX;c7F&9iU`t?mOI~BB}$N70dzfIn1 z!!Ir7g=4dRdGDM&cLobO_ZrdBv0db?%WrK%H@=ZH+~-!dfpv{z2aDtKyG4-CEnPEF zE1kAmZs4azbShK5e+d?L$2#oTy3;VN-_bjF6Bo65XTcH1uz_9z%e8~bcaK&t$x6HQ zhy!Uu@|+e!y@Ya$cq(y0_oq*(QP%60kWdBwG5%j1!w!DY88cnJ;xi*!GH(18ro29Tn znc3<~S{WXx^y2$2gE=IxDXg&%37!+@grmWGbE4D{rHwn`SqW6zm{T$em97x?ooOBx z&@TeAT^HN`Bvl<*O_$1T0Tvtlc_6k92Olu%=onS1Ki9K(=&oC1Xwa--_CL>Y_#5|< zQL=9$Utc_sGPDsPplzNmG|phJJ=@6w$%TnQ)iEY$aiJ*#gOHeW5eBP=_b zDr3u0_*J6f>>&f3DEUgJ9~ItVJn7Z2y^tWsAsGB_ZL>cTJh|0Bn?k*we@#SQR1<*w zaLFaIw!BjQhi;mkC1bN#wQWHivnH2`C2U#-HN8CoUjA#p z4m5Lp7VWk}uxpCno9cQQra!U3g1A@2G~2?T0Y(8&5(e!DuY{d(9=b}Oe@b?g$u1QR zNP)@gYr+_wc%cVdaJa_t3nb05;g>|iS&=zu8ErR@SfIGn5K*_Ln{EWz?G@Uh1lXW8 zZtnMiT~%lNkA^r-LY2NvvrjIDG@43>;=dC9J6$uwf}3yAvWD^UQqiIfv9y9MSg60- zsJ?2r=}2nmf$-tGgRS;;+sGI1+i|0+ zg_{i9TQ56XYWe|Lm~WkpXbCx#c5|iS#%_ODYT}#wDS=@Y$U3sEQRd3F?U}YFllZWG zkA^Bm*};sqcdK5`BVf7m!)q1zir^_Z>?Eh`vFz?j|M>!~R`#bP%@#dIp*Q#fSUf!W z(ClBAKxQH4w%Q^R9&LBVi`6Q~m2t%?6&9-W`-bQ3*dEG(339DY)rcI|xn`?1T>HlN z%pk(s?}P{(?2%v!u}uVZi?090MB!Z--4jNT9Wh+XXL<1v!JukjZ{?_4scL1`Y9k|q z?Ww=_xf?lh5fXGNTcv4Qb%&6RgYNHRp{E4TM7W}7h1cMq5COE*_}hGv=xz3&%YBA| zPMum|x9&Zb6g2-IVuaM>G=VVI(FZ^n7i_G4A6b{6BxV{-0`%m`TnOlkgx!Gy&APjx zBO~pq_U_^1oT#rYPW(4;u>MC-mz0gAYe-`L!&B$?97UwJ^+v0@m90=@D0**Jj(x~r zG$(K%h-xei9Y|}H-+x6mgeqm;6wgfn&wbu(9^m=e$H5?=gadJ;ete ze?t4TS$i6i*e75W_4^G@tMx7jd6?l$Y~!9D!qAAMO<&Q9-RlgUxBVfzCI4+ds4;<= ztM|2vJ-r~rLMuwk!yerE{=Eig3&vx@PBiu)Nu(-Xp4@9RW}v`1v-WU-WTTJ1Z>wLm z1`OMU4oNf00T8*V^RU!ejQJ-`x)$JZ$$fITuekS?TFy#ht}xE;`xf8+YNk0FFDf_9 zTMx1zPnWM5VzLkU%Cospp=)_OT;t98Si#RFK&e%w-o!A1aPJYj07v)0o1MY!R+ZUyVg~N_vr2}DJ4}3WBZ`*M>5706j_+UdN<(Pu9y*=a+qDF%u=yCqMnInm4$fPM8Pqbl-hv<9VGM(* zan#Z_W=(Uod+0HX=;+CT%6RW3e~yeT#5~Jt7Q58wN!G663x3lDvlRzn&B3n-JGW9knQ?AlY$M6 zgqGDE{kiO0V>->-U~Wucljp*f^OLlTdm9Uf=?v$4w=f~wZ??-9j=0wV;@8Pv5 z@YMe36eE`VX)}FXgTNXVhFVa6OkOs+o(pf)huFjxTbC@UZQ|l*6ZFsM4CVeGP1hOK zWY%@ZL1jh+1{tLj6@^g*M5IGdQP2@VEEFjLLU9N!gceAMh*G49D7^?MpmdNDO6Y_h zDJG%!1W2fXkdXG}{qg-yStD#@6o~=NY9_2pMei5 z)o5KJT}Zvsy99m_oktV(4X0-w9^Lz;S{&3dtC?qd!8gs4b?}I0Fu{?w0H!SJ@3o5Cb5S!(-OadCqgkAW+%WsmMc4P+pQCm8S$e*c^O9kZu6ojc!WF z{o+&kVY z-6QxTy8b_-x5Lv$J9h6-B4#^rAHVhWjUV017pv zHlZZX3nKhY3^cRXsN^EJi^D>OBUG7j1<@O4jI=hSGQ7F|DAJdWy9f2dmqi(%!A;!! zK13hD*Yni02@lpETrp?Z618=8QlKE9HdL;P+Ir zWQ+n<*Qc>-E*I<{njYK^#m7u)nI$6MiHDOK%TtqN#&1(u`o^##Se)AcfV?Ry3J16H zO|*uBfYz17%jT{NLScHDBQ5}honKmB>k1M4%q|wae5%Dj2I%q}#EDyDntr+NzhzPk z??2Fs0y%|IaZRU!AiotDP5X0p&^u{#&sii+g7QNc*n5niU_K@ki1VTi{o~r}NR(#_ z&7pOw$a};e$w@93&#kc0XzOX9sj9B-(1jm)!&4R@V_A)$ovW&QzK~3Pl)3!KWTnBj z5uKOc2NvZ)u#eFXPd^tR112X7z%-94tCpwcEj~3tCnq1M9_$*i3al2ch~)o>aFD@i z`hLpmEJ|Db=(f#P_@7Eyh%h6R_;$`Nsm|q?fWj`Zc4V?alED5?_=26LqRm9nlEL8) zsWu5PTd6`H{LI;7)i|Iw;gF?=N=wi zJj6UPbE4baR8m({HLGxCAxbiJ0UkFI6$z-oShacS!>O6Z%JiBjj~VPF?{Idv`z$o} zsn6;0q1y+qekDwF@LMW%%B1;5f3eG;WJ1a0i^45ye}}*kU9E|xiSWtmsvku0KNoFH z>0fw)xq%Kks#5!+E*fr{MKu}}aPUJO>)!rbvOM}arjL4E=n1t)rzJ$lKy7XJRlLNN zFyunj+=+9cM0eRkndtJg_!C!fG(D}R>-YVpXum(0G5?D-_FGpd%(>+>_aCj56m7=1 zn4!u1!>~_g4dAx=hzII2d9nJs=dA#-536KJe_aI-j|pW%;xzz$ukXoJ&>2>jbo&gG zvLtCA0%mw8RYiJM?5>|{AcrvTsY(~F^zO$<$;8inEaVLM_P=!KLA;NE9l+je`YVRV z#AWJF-22#)qP*EZ6&AYBv*a{ul#XNNnf{J?Ur-tzD=EpL)gJz0NJIcwMUIS4Ggb1J0IauRi2Lu0wH!oU2<%1csO4?E+Hf2}JKPmgChKjxtmYy5 zW8@Xor)WPF$X`aP*O#}pQJbiZe0&RjOhVn2^XW9B)?7{>5?j8U%zC<&k#nJbe;uMK zuBWEQGiQyr@E6;CjLjmKPdTq{*A>dQ zh`VV^eB7)BI?#0z$YU7s%n8a4v~o!Iw{!>hB_()7-pi7eKW4j^5Y?&GnY;@oe#^?M zSItM&sD4U%hx5$IoUFzwut&WeuDh6cS^Ki-od14c0M;#5sX4f<2(E%b+kPL-N$b%Yc>FZt>ofNi!#&EJP4Ou z2jF%kv4t|BE-+-hCVo?mA7nm2IeWxS%FHLMc>Nn5O^emrbIfs-;6MV2LCsptKGhBg z=PtOh_J*!%0eK#t|C@gPm1n2^ZYqa4{j2e95r+SD_)9{EOzw=Y!1kxDY^nW<1Ut~+dtifV zGQAZSZ-fb1VYBt+4*9FwH>s|Y`oSkn%-0jX(Y zd`jafR+@$wVcfeJR_*s7_wU-};iNH^$J%03-I!k|LVLmIdv!^)?HL5s z80Gf`Uc(!X;9T_z0$_N-+LcY~1nnS^y9tjY6^b(}2NDjXIacJ;=u^nJN6U6$R$+ZF z@@|0SzMg9*`7b0l`LpH@`4VW}&%6<@r5CZ_9f<#gmgHTD+?%O;WMZeU!`-tJLbx_% zwRhY8Ps~Q~*Q20-2k*pxh7#@K`#fH4DxZl?ayIklJHWg;-SsK~>TP>XRnQjJdER&D z-pux1r@&K&I`ECS#eJ+(O`jUaMGgGGta}tZm0q>ffQ|V??)8uuokfXx&&)m}y4rtA zwhuVnJtaIMe;{t3V1IErd~C}SU`7*K-sW+Q7#(-Lq#=GXl40gvH$L#a+m=3?|Eix9 z1@tHENbD_#?)E)y_H#3p{@-Nko4X@K|W)wrML&=+ECwSC+DyHXua*x$?3de zj!=H^ef~`X9Vs{MxKM2|CRf<2(WB2&$&*rG)u|p~f__7@M4@6Q+Iq_+y&QE13TT?P zq8WXnP2FHHqAbMJ-1?wKF_S-oz-whr zLgY(>A2McJd2tGj70GFN7=VsPXhQgw!JE0RLw?d#AhbFyPZKDQTu}~Be7Rl6a|4Je z+%N#R-Zh2ILMR*@1|zZg#1r&5kz#bh{lGnZclf3H)Yn}X&rz;aFDIBw17dY~{u4T; zrzd_AlZ-{3yQ;|g^Vc{3l)F19hi?hlC!}6 zHYd581r@UDdUO%L+5T$<)gd;ccrq48?R*;VEsmgslwZ+PWN9@9>1@^E)iqDjPKc1x zgf6ASM7NBwHT@QSBy<3}t;ook@ zN--l?WgT-}!8`8RoIxCKb%gWzz(wK{Vdm({dUawgb4{~rjFLlhgiNXz%LNnv(rrK^ zdL`gkL5klh+uwv}n<~lUhaFexz5~7cq?R*%;uvT}=Q<|L5?6=0Y~>8hhXoTkZR$tWAZC}k{5Nnp zOS6Lh4niD!5m8(s*Z+-iZ6u|*^Eyq-uzBW3l#0HSXzBmY0(h|{w2`i4>DX*-{GI?t zxr(EI z#-$e2tLnc`tLYyuxBkf0@ER4J*b|&%{)+o9vGGrMj$JJC)H=`G-a0&feuYt@N*-Yj zFoV($KOsBd!zy|228Fj(I%b%g!76A)Ro84GuND20kgCv!Ltia~NiQjisIM(NL-`IX z=vAYP>8V=DHv$fztgsddCKolzJmed+^YU7?!y5L#kA!jNWuJfh{%lECJ=QY%(yh+w z<)2-&H+Zyq0a{o6e1=Kuu?Ocb96PhI=B?m-+Ui6BXj8n@PWQJTFI>S33ScR9XN(M$S4%cL6t z-YdG*-xC&Yx!g(>n+N*Zd3Oce1LYbk9==(=AgIXyTi$xEz;4y@xuA}B+no;#wDzcb z?;IR|d$E5JME~fUn@m$@6Ws#JjiC~1bV^gic(;gPwdu^$mZ-BcJH-mDi_1aCIdp>b zU(;(}%OkX@al^-qSkJee59V*O1~GaI!D(yY+c~bx0jMv6#W(I++?Tbs%3DLy!MG6uYu8c967c)mu9bQ`)yrM z?cnl5v&fl{xdxTZW>Ie+E)xVKXI4vp4>>CU9hPO-Ly5I3f3*I%hYCDBCbQuiD(|l* zc@p$>oV(ekn8#ZBhjzK85=~kT%UP#K=A)b+>s+op^Ay@Gz5HP=j><9GF>8_HJr-#4 zU(k^BQ9u1C}%V%tqA`f--Dg2=2Ei30p>djTfjV|3II;H8t~9 zyAt&A`1(DuX>s?M{SYDS8#$I@ln3E^@NJc-_k2X||_!UXCbxBV;sMs}emWQqeZ0kLi-n-W4Vy z9S#{vCvzfOH!gvVqtp+B$-4ej&1ZV<4`I2ux=Q4w?5Xg@O#kzg%GRTQBrN#`+R*8R zvt^8H@E&iRuC}fV|4qu!tAbOx4HDU_dsT4Ihd7D3Y{5mR_8N!-Ke}i16J~ZGYw)vZ z!@3~wr$@JGB9iN5>gOVGO(Lglu;hSR8qQ9w*6OLu6%{<-wI^@n9oQ~`zE@7PG0B7@ zll}Y(GTE7@pES^Q5!Ep%En!LN>2n};AW<*DZ7)C@tzR`uFR+efO7BcnG-)?~0LK=G zI_1w*Yi1i>j&A*S*sXPhE9N^>ez3nNf&QkmYL*VpawDM!rX7*c^JH{CV{T1Jtw8(W z-bBLu5BQ`y>r0iPnpFDXv8ASbm{d^JV$hg8u1}+8tMGVo{fy#`cg`Url4hz#NiSzk2|`eT0M{XDdckplRFAFLln`bAV73*!rzLure&UX zR6&au+T*pb--5e)(xKMn4*-phdp{0j`N>TLA6+uQ3bVJi9klH>`-1(+!ZTIJUEb3O zY&r4+BY`(8#;8JlCvh*v4yfw5l#0m9gaY83FjNMaZQy9q#{XUU7|+q}+@KY=PPOE6 zZ(n539D6Ev&u`ql95me4t7`T{dsII|gHJ>L#DcfJ1jP`r@i{i^&g7b-Y^G`!sUhG@ z+>`)e1(Fa~lJiX<5zK;mquN;C+kyrsVY%u{r7#r_WzO}Tr2ylVzD|XIODbcT@HCp zR;XIdKaH3JU^8D#ed55HVq64sy@05XgcX&>s^9+}`CCbgXwiDX%3&Ga5yd)OU*^symLO5stmWREd%-F&W+KCBXPebo5 zBPE`y0?yb+t?577Ds071q9I7jQs8aGjC-pHYeMzLkOy_>mr4JVV5F6Z8h8}V6rf}) zSE7$n0)y@vIK8J?9w~Wd1|MH$Qc#|*Bl-tE6e_3ZR9nOinQ%wfT&kcmrPd*^fRfjC z*bp83*zfH2I}chF)X-T?#Co*F$UIYtnaC_Hja z5R32jpgb{NNt}6|75=+#e{AKkhZUj_C%?ScM(S_9zwLg+MkVms8DDrzn^^05{IMn~ zQH>EzK6QtF-Kj>c)<)P*A457iX0S^) z)xNHn$Bi$?HjY-0LdBXBJJVn-Js#(%f3f;Xs}22B>4C0B@mG zQe+L4)*qTgHt=0DUN<^47CoiCLGUW$$8+#ACn#LPi>R!Dw|+hli2dDV8OuS7l{Mug z*{$fFW*?S$j>kJ(ZU#1Fkz*ms_(v1CcgaxALks!1B@>7Y$o(I(KS(?EXWd;A?cN?$ z?bfIKNxO49dYLNJ6Jp4Y3AE;Mn2FMfYs{ruLpt2OBHYvaHc<71v!F~ZieNF{w^pLH zqhGdY?a20lEhTH3G&pB};@&V{@m|qjw5>^K86D!I55pr$R1i)QW_{O>Fr){Rejz@H zd0JoEh}Cljz!8+Sx=*_(?%e#OKEAf~THrj!0cQ3gOG+mFtVD>1E%_QGKbP|}W`-ag zcs+p#o>}+EkNQ>bP=9lz%b=NSPY?>vP9lHi9WqnhtXsI7gNf+|s+-H-=#xo|V%U>| zqHHV2FTFZ;L#b0ac^OXyziUt5Gx1g}cZLZA(?T#5{5Hewho2cjSur;-n>9pdIHgD; zE?K}8(bphF5KSbzYlIdmG1|O=kgxi~>N*Wm$~;zAu=~vcKO9wQk$q90_1O_2XZ|JF z8_BO&yvKP&?p$-5e@QKwl!q$7Ffy0Nb=6NpcHS5ECdoqdj%dFJueIk52tyb-xPAfu zcihJW@slZ*rw#N)>Qq8&9qRa+0?~}Iv(tUon@(${_^(`4txu4WlQG^d8g^3xdh&j; z)w0o4V)WODa2=)vxJTO2tRs0<6{Jk z%yUu*8BZEC@AF|<+jFmlPgrU{aj3&hq+uUtsai1cj}{+0 z(*3!z2fPN%ZZ!FsAiX>RYZ+KXeoBz34%&3zDx!Jz*-mzgfcH<#B!YLo8EDV1O%wf# zk_>8wCcCgivbP0c9{Hwr#mmr*w>S`}*6PhD_}xswWTTXF)#Y7!L!gQL1b*n=^g3)B zk8g^>&@-DG_I`7$il;4rpw)oFtt5}X=w8|U#i2lSbqMrK(i;ipy^ye6(#bL`O-h=) z{I~4P!xi@L+R#^WfNCKACS)zsi=rJIH1FK%R^5}~1>*$BX{P>!+PR7A$K$s7?xPtl zFMTrAbllYZ@0U&H&HSl)wD#O6X!0IZ%-i(#&Y*#=yJROTL-W&U9kWyV^VF6zLRe42 z8|)`@R3M&Vd+0Xq$PB&{OiXPoJpa@j@m((WQ%d_Wz7G+M@ub4@5z+!jR5Ofq#v2U` zM(T`ceOE(TwRYzCK)yv*|I?^Ar#nOq%!uqN)(SK&_gu zk^Q@P@;8C-fl9_TDO&}R70#-{?hTK&BO9Ho%>`I#`a=tUM=gncvpl36yq9}>*;<~% zX@#tw&-LD><#BV8DcwGe^;Li3G)9;;PuSO>{Fm7f#_r0>GTQ0BTKxj${B(KLW165_ z*K&6GZy`P43$rIec3N)J)ub#r0Xml2_S??#0a%fLI> zO%=xJ(U%rS$+{vuSqxLHZD405Y1S8N$g->;x26kjiCMrtBLcF|LhzBpgXW}W z*P<3(r4>5=t3f*edeXco%ulty<-kK;a_35Yr$XQWpClItW$63Mg7+Q)W5h*lv}Z%P z_wlAvm3*f8#$NcxxR)y$u#EIxVrN>9N%v2LYj1WlU5Jkl)t zq|tE((hEVnKPFgRZ}0zc??N%$H@E7)8^n$+9eE6|I@ZtxA4b)KQF{WNdU%0G;aJi< zXQ!>w|8`*|wR877pv`cEHMAV_RCml{?s%VMW#Ha^7+=#e1;KH)1)w0Mf`5mw4l0Ai?8!h*`A7j&%JyaK8#Yi(C;=FBV=6ScVaJ zTWyW0(zEX%W!O!Ial_KS?_JKte?JtpKXBCD=A@xv%6Lbah~Bx?+ARZZ4m?4(a1e2G zB@yKs`REZTz3fERYw;nV2r%`)U3Xt_CNd{!;GP~cnbVP5CV{H&4NZ(p^pBF=josoW zgZIs;B^--9>HscNgFmPwzW1;n%L-6VdsuS@1YJ2AW7Oy#&+9He7ni`}9 z66PEZY(iq8)&|iIxW-Ri#$=HCPD>mX449O(_J|9fYY6G+wULccn=Z6YqX$tef`;c3Gr3GOy?bN6>W{&%IqCxld0o@j-xpViW=u00YXQroA03rU{nDpfu z{v)G3%8DIYD51c}VLuk__0UD%huNDix)cisCZ+Sh0NYjHyQl*hREU*6*G{P`KfSE@ zjF88`+e2QrSaye9;>74<50gI!fNmGv*EFYBEQ+f zrs=OWTlPNm*#sK8+{pN7m@AoH3=Db)bGe z;h^(G#!m(D+O) zm0ZqPY-^hi)|aw0{c}HM_c>-pqPq3^k!otNKwc)VbB)$7{ za3d*4;12&YkJelAQ7LUl072AkzeDdfMa&_E*GWYLpN9Hy*IIcvYn}uSuNEF^A9;<$4=M1;pTu9HHPl*cI{RY|n0|vvn%f1CuHPfA7xR`$O=)wM z2b)maA*ajX9rvkL`tRxjJUAyDsLeo(kX7&S*!N#CzS1R z{Mcs2afwmp@6t5jN3UGI^ZK0^BDOMct(^PreZoD-{wm56_P%45#VbS&St*-Mx8&ni z(}K0c*QckuQp@Vf6ASTA9LdQa_fxbwemzP=?f6xHL`$^w!4X57KToyDWywAfAj=){ zQB<0okQph-M0q|VEQ^o{l*p4y8~ir(zL2iz|LbU4_g!O`YBlK}Zbw7!3Agp1uA6oi zY|GYLD%)=#?gRj8xb4+Y-O{c2M6DRfnV(oF6!W=_}mwwy#otb(%$jTPJ z33768jM2B8nsMgUJU3-@zw99pQM}b|eRRV<@e$ap)tLT2;AdLuXcCF)nX@shFB95m zz`sj+pLCEosEZ5nuADPHiy~A~im0CRF^;Tn2I6|SStCDHv^G~RYvR6(8#3My{IyaS z61?*}YNf3=V!kA2smmMb^~v|Ht~Pm8Egv@1{YA437mJ2U=S}=oxI2klVRd>yGa%lj zkP`e@!^m_VQxay1DcC-nv|<%->S4L&*4{e$ym@c0-jbNnncC&drAiW~#t8=Jp<5#{_5_4alnPW&AR2YuI=QTmS2MTQ_LtkD?bT zp(l%zFmvh`adX$z=Jed@-fvRMtM`FTx&sY%aW*%sBT-AKp;9g<1pRftpTLsg-zJ`+mt7?4FOvm<;|7-dKRimSr$z2e&Ayx z+S)rDnt%lceQC;Ix#xlo$Mh+Kkr_gHVW$(~7%>6}mFaB-yuB7BQB#h?Bx0?;U5VS~ z@4_ZjyJZ_Lg_}eaJ>(jJ_$R{ZDC$P`q#g5ps7EDC?qGp)A$v@1Wt>#IWu;=a%^z&b zhtT&UMcLhRHkJIen|0s%2szi;To-ZRd)rW+Xpr?53j5m za5tjQG!SFcmwINyAD#1ZsePx!J`wCJs*~xDmoSsuQy^j)iFm;XUp@5q&icECWIl} zVma^aTVahgR{Nk2So~AoMIH@SL1usD;SQ!Bv(!2g6gEtjDdZunPzg`1O=oXOx35+- zybfhRU(s2TgZvwI2I#dJ9KMXB13@IrD06oIy;BaX(|#9Q>uf$VF==IH3#NxJBOE`X z;jlqL0<%`WIi^!>=7T^Z6}sdAQGxm=b{h9kS+miM7xH$AGf@tqVT zI+fGe7UWKLK$!tnXKAZ(D6#j6%`g|f#VbipuH3qZR~Si^+towydmZd0yOG~=cWc0s zlk(FGjpUO`hM>ax8)wq*rBE2zSZ^afZo(h+ID6o0;r)#`yMo6ZLC~RO88=f0y4OBA zPM~WQ+tXWZDQK{EeM1iut-jd^V0YLug-5#F{|+V&OFk8q*$$^Hhqe84wSGTVWk=(Q z!b4V>`kCU5iQ1k=KBPvCaO(Bf5zsJBs^=ZPz;hj|P1nwmeMJVdnKBqvqb~^@OB>n= zN!Z3WH(|BBv5XL>S^pjw#WnAr;v<8}28mUS{lZhzL$z=(QM33yjfUhp_{`j3J+zHo#R-qMud%N~=66|wEY z+*#JjPu4|H=UQmlm}wbha{P#{!m8Ywm5>&~@$Z^L&}3&I>GybkfL+--QOB+=u*RbA zKa!-}$^ z0X${WFQ@UcYC*nJY`sLI++C(YQednQIz)_KtG{#SKaOJ@Ne1zWI=m&pa|`a^HF{{_ zUQeneL|~VsU1*o`^XlF6ik2T4Vke+7Q5_Y;^yPaM1eFXpBQAF}!sdBuouob&YFNcD ze4dycvW+r1*@%7q>AfQKP&U2+-C&dlhnV?Ip|=s*N!3L(63**u>wsx*rhS7W>uug#VbS|P&2L8W zdq)n#AYfMBq;=)J)63z@C85^M#@ycUIHJ!Sf)Z;4Bnx#l&(j&_d>U(a-%jy5G-bz4 zCnkqH`T{XeFdHg+f@&+fg7d7lkqlHhn&No0y8+lt`;IztDoIG({mfOP!XGF^>0;|K zbNBWgE6W!&k8n$!+J#`^M&8JS9uU)}n71pWE!fH;FZCq z1CN?sm>Pt&5M^{`>!JC)bOC~;3;M| zp9B0OTh_A-3XPsVqaLdB)dxwhNQ9+syY}eq5Ll z2_A16)NI)CX^IM*mwX7?XslX?AJgjXUOXy$o;?fjDWz+Kle)e5noJ|Qu2t!Y1Z=Km z>Xb(Ia~M<=Kes!QT?AY(d)gE-!u=Vl5jNMx4oQ=ntpw3jzxOLYt6-^N{ux}Dl82i}eMJ%s1;DEu6> z9k?H8rdsi!OJ1Q)LShu$kc*xXxu`T7{|GnqU|@3P^ly6cwTVNO?>z__a=iN;!dk1Z z?rt&4vu1;;B<_9^Js8wbkn|dn#_3)301rs@r$r1B>X|Wj{W>h{zkwKv(>|~ViUb4h zf4ry$By>CN4GWu?6bo`Gi~M}uy&}DkuSS^$gK`(Y(9Jwj!HKQexF%zjAw8_`Y|Eyv zQKPonQH{ZLtsIfix-V{veStbN{&!^W#_p>uF}QRK$pz$gVCyRAlQ?~EAJd91kUT}+vo!uHS#J^>q;ZKf|)7v%weN#jO~&mxQ~Nm<;{p7qh=A%3QN0lX$RJXeH+$7 zI`)`^?5iY93G>dJm+wQhl^}Z707au-6%$y;Z~wFC^Z%F!EnP6j7I^%7h}w}3Yu^0B z$X$Hyrb({U^C(RjvZ%jbfWh3l(Z3v!?klCmU7L;D|33>*(3lIqqs1KZz3XfE^q$bD zB#r5v+!E)#Vw(c_vq=T0)5549KC6nGyJl3beBDduB!4txXn$}nUWhYgVW8UZ_*Sh! zXnfPQ)($RR3;o+Nb{}pfqbgV=8J!-3gF~i!N?mT91I07MdHe%|%a2)kYeDUN#2l9u za-UCXfnWH}tstM6KGzJs9bL^H6b00Kv@mp>JLsQL)1*{UVBLn$Gf)xTtF7h-L*e8% znV#izSQ7b|2R)%z(;!Z@#R+5@;9u^KVB?1=An2R85|@BB+iAw7;JV=OBmPB1Xr3M6 zdocKIN63+!$W{+ZUXd+agD#tEC;5Wk%<@2}U^B3(tp0kw#;a zT`jFxIb=X>c+}xB+3OdZZ+ZIpn?pV>tpbunCTAkLGUA*`L5h0xQ+U>oqO{FBc^{vkGwm&`v#l2WK*Edo%wgYuGj}>1ye&N@JA_M3`EJ?K z@dE0s!#J<)Y>ZvmFO%IkBU8|fzc+DIdcEBZkE7-Dp|bQ=1xg4h#INl`lWu1m{neh06% z$$9;U&jOJeRlbuEeg?LpTh&EtA5ZK803yxzo6)Pl?@;R>Z;ryd#G&!q3}=u*1zZ z+wGW`3$XLdE4fN$^;?alNf$9OZ^?ZC|Bc8x&5c2qA8{`kBia9+cJ$4Dl$%r{m68m2N%eUgh}O5{)XkYU+a&Q;=Kxert;ADa7xSFOi-sqMs%e@& zIA+3{T)0?*K#kDS-tzn2DLKn)O4qI|%Qs=dWtnEr6wlw9nv-*UsYRF8qpAZq>Fl#g zPb}UM*i9-2mswQx*M!Ya=8W7!lMK2>WtO}Sv38UoE_6flluz0tNAEW88OtE-!D!H+ zwug4h=3rRcdD-cOHcnNs4&u>9KB?P1?2Lp~Ov8rLlBlknof1>`m_`cQlN=QwdIZHk)sfz9gRQ>w0!_# z1YLty=wLn_v6lC&_&KRd|&pt;Z0Ckm&Ad)X1Ak3u&|}Z3y-z5kvnSm+=)|~ z&$(U}p0c2dEb`-U1y6pDs0L>0$e@m4vA-{(vDal`zyBC4C|AJ2;#)_6%d0|kZ#4uJ zZ*0`dcOk7`rbzx&V~dL%=6$IXRYmw=UvihnL(39?lY&{p9cQ#&gwNC-yuT-5NK!=Y z^Wn~Lqbcv5_#~;T>K_r3b75ebYm7p`3oSf6-;;e+!-dbF^SwQQzVj_dmGiCeqjg@u zh(s2%plb#L4`V^(=`)>R=Wj3KbZksj!*@;r7fYA=_2P6CMAx1I25zq<`17}sKp57L zK@;%&!SveaNzadTH~fm2MN5U+<5hZ{asI#RdL84dvD`+ymV$)rSpWP0r&9Bl;T5Z+ z(T(r;%XtHT9wmouqT78?QFmJNC@;}(^L7M%Goz_#v9)5w>vgi~i3gJ`#toSU#LjeS zH?7HfCa*ePSM?eW%CjDFoOc+{)~CuOLH4s9?oKPh-)2D*vsc0Tm4h`aG7ct&`U<>h zejDsq8a}7ocKD{^zDv9z9a}eAj9pFpK^K_QP26OBo1QG1Iwe&bi*ZTNj9Z>z<%M*J z&aXCH|EH)ubTU?-IxjXHS0d#8nEN#PWC(e}tcie21Ei5_B$_OV!T1wy*Y-z&9o->h z(mU~BpMiQqeJE*ge=J-xpzTLieEVwX+fsrF3T=K(X)HRax?!cZ>Xe9`K;$-9!F1;b zD()WA9hcokKpb&6Qz3vp0w)cob#|VxR)4vtT|IHx4P~Utx3WD?k{=Z zjFzEBcX}YDx_q1$^liR}2BZKQ7iGYxe~r#oI_g7D29}M*71Ta!7OAXVYEFEzwO6}fIjlY84UOEy6N+}4s_0k)wPD zY!?et`c4Nw|KNZOjFO(BONCBTB9UJAMTJ>v3*1AU8^t{ibZPY|N&gOUO1N0--jY5p z;KrkN$8+kvP4b=NP5K`+m2}ATGFY|LZ+F!W>j}EA?$vuGh9#ouFT$12by)5$@^l2> zI92K_`56nMB02qSJ;rA7!~HRUW|~cClx5Y&`Tknnnf`oIRW632Z9-)i#8)YzRZnKI`QvXd}pjar+{HiX3k5lo`Bdy>9lMgM>!8l z@9BJ1Rl~qwU%S^3o0*g*AP5nS9UA0SfywUQo$I`DdX*uK@j*#0zNPdps_)gaAP#5d zxS6JV_s-e0jO_kNe+M2)ASY)3C8MXCBr9lo)~?@d#u+UA5QjhU@R#{yq(ynDSS?g% zUtQB0Sc~_R2a1mKD!DR;WuannFdB8gjbO6}9~5k>{nuc(iyWY}8kX;$jtHxeph>~M zkk;O69s%r-$s4p9x@-!^lZ(pMP}(hJu1*0wXLW7gD~I>CX2?|GWNR@u9oKk;hrAH2 z1TsGy)pTn~W>h>l7roc5mZ&D2MR2}^YsPcFru(m&f$qBJA*rjGgVWL!_~$9TutW>G z1$(JiUEicGGI8=Rc#8gR+;SXXy5%QQ-v6vVAZ=_U<7zJLW4%B7FM4{GdI9SL>bzX#D!td+JY+L9Y`k) z_SHp8jPun-AsCWfOwj>V91c=8<`T z1Rq<(or2fIIc1A=sx-#z8tfa9$5a3>$QM1^py}{9ZgS&ycfF)fpBYI^^1W+;V4LZlU)0GZ+5fxroB89bLXY=TNsfMU z&nEArBB{CFa(v0oW~Z*Rcoy{&XkRkgQpKub zqD^gbAill#zHoob#%ZKi%#bMNaGPF1(G}bU4G9%*SRjN0&1J7P?_Yx&rg1D%J`fIA ziP_3{KMGSKd-TML1dDk=p}EK^(I~k62b|{86|*hggr6g5oBv^8Gb)~t_2WA+*OZkcaL9x zO22r$I-}!bQe490Nt_4ujrhbhn$IH zz0qbf|EZBue$Y_8UqmJjB5PB$lKjOq0f;FNtk3Rok=O)Dr0AUHxq#4N?@Q*$UJu4~ z%(&t=xs=E`M(+2+8y?8S;jlIe#iwpZ^}0S>jMJTQ=3^ZGlM--I`0o>E+7ZJk zfH13UnB}v@cPee|t22jgqAX9yf92HB>yJ)_uDvR*mhQFCF`w6%N3cK3fOlH$u}WH> zl-Si)H{SW~MH&KH#TFUj2Li8-1cTS}6@+8v+r@)ynisu6)2yD)80sW^2q7n_47E_# zPYvxqjJvjT@^Im;giZ;6^!^a`X!CFS0HsfmwZ`X~2T&WRgK8sUR-1za?&|?Rlxg#5 zv8d{gqy^XPWviU`lNH7JQ8$u^wYvwE?3p=r&qwLPtDiionA~ULO@imfyYOSuK}oNJ zW5ZZhXR{awx^cHe;PZMS$^q-{;LcKa@uiS zNwlHjAfd$Ju14^4QNJAM1dtKjqg}3i*wMx1B>5&8K@;j#jyo?1U6gs3<0n2G#y=gM47R3;1`7+^Qe93!?1i%gGaTD9%Y zsArj%M}&1!F+_3T4CvP#C)Y>F8d71ea=jVQkK9`77qPtz<->(;r4jo@iMqzJgW3~r z=e-Pp1}r@YykGh8gH&h8kwO$4X_)ECgv5${=15yjKOn}r10sSdfFy6_Rh1K=>NxFGph8S4dKXXSi}p}nl= z>B-}+v@S#6d-b^;2Yofa8fVTg4r^R*-D&BrcpBd7=g&6@H;?C^yzMxLa-UF^mxuHk&k)v9ySjZ7z+njzOi?=!1XS68M9N<_5k0*R<2ydV5?FHctn%QYX#^?m*Zizp00|r7;82B<%7%ZTs-&Q2Md03ZdBvi=k-U6E$a!$ z+5$GY2p@k(%t=aGBZ(wDz|;p#s! z{2=|5H8~cwA(^9MCzVTfOiygd_+SK|_+?#fezfyp!9DGB!|Lmu-IIK_*HKzTg8E)Z_5IrT{Q!>n+$I@YnqP;4*UJ^#5DEbj=WQ`Rv6BC+4b3<_ zqt5tk1JghgY(%c=%pVh1g{=jwyjFs}tX%=zkvMvjd!(WCy*COF;YO{;2?UojA4f(l z8WC?AIWEQhlRt;={-FF!?6IEtT0OU@QIhbLG+<8phiwflP@lwjzC~;av!q#zs|qHu zbz2e(e=Q(I%=J8QqMG<4YOf~u25dO0Ne12vmX+q<*`rangQawq+4{om0)O;wIr6-{ z_MZ)^{+r11C{FU^FPD?}C$LKV7g1dat-T==lq2kn(V?0lGjdixe!RJXWeTSDHk93d zc{=WPCEJkG2n+7xsOpgwai+;$vXtHJ{CZ3@y<^w!bormSo6JRbcNKPN*1LRU8SROO z#eTYR*5=f(*PA6Gd-1D_%6h`Y6BR|;y(1?Pz05L>DWlFS zH9EI{Qz?%)aMSo1YN(vn3|d}9rUi>h)}0=f3fVp(Rl5JH=1uLRySQ2E%~e1Lr=#eh z4Nk$7;y(!5a;ggKoG8%#hH10V<_d|VuF4J;L0{Eou*R7FE4Wz-A96l&HfN92yHPK+ zN*xi1N*0VNMCjy;(E$RO_npF~VFi#jlLuI{ahfk?0DNMqw_8?gGY;+znTyRBQ7hl z*RrJMRY09eH^OL*`M3c6UuJLgxAEUePfVBE@m;V+ME>kMF_nE}r)|HKw1O=6qn&2Q z^NrZaEKI0>^1eBmJiz~2;|4{MmXB3LKCJ1+obRvFBll(+z`n2azjs}ibFPTZ z*vmGWza4chYQ9_%cCF~lS!l9-zl&(1SGP7%1io~Ahc}V|cy=W{+i9)UbD-elt>5sv%QaiF z;f009hgffoLf$tayRW-b&2~4nN4Kg`OMT7jAHz=(mFeUAHOl2;%*)uBsZ5E3$=1%z z&veY0k6Vm*BZ8^zX9RwGkY~Fc=jky6R!=^8q~X2OiPzhx+wcmK{K=W{*9f^D_Z(IWKa&}A>6VyxKjVF!Q^md$Nq^6|Qf-IManSC2izzwBJE4g7 zOmitUXzYtbnuPr8+nWOU@;cFW>!`1?&|N&}cL)o07{k&7?DyQZwYrLtI`@k7US|&Z zAD3RwE+OG}KJa~COnw^lsR1xst$4C5{f@W-XMoOvhN`b;zM1wJL|)UQ)#YxG&gfof-oNBJ-^~1Zuz))t)~y<-b*TcEIbU-~ z242+}P7~xZ!yw9^w@z`MTWe5HTN@w(s?G<_&v==P9khadkuRAu8aE3a$fOiIeSc7} z@Mp|B<|~mJ=_ZOYZp6{xf&Z@e9n{=;WTI;(F{y0a&R}d9)A^P;1Wjpzv{ zvNd2$r>mH?J%UH1+&OoS{^tS9ZflcgHTvGz=@RtI4ZW5%v8bM5o#VQfMY}3WZTH1M z`X@Xnf3_${GUS8{4cbhR4nU$;a5I4c!_1^Iz`*n^V(er2PD@4&ykxr9ZqIM*Q*hnC zETKxb`?ZA=nK9o|Cs`3=w^ce&hW+-@-E6y-KjV5%N0q>?)!>pRn0+#r(MMn$lnUrn zharEa)i|$9dq$Z)U5Yr)A6_w9yWD8t2M8^16&SRazTJ!ciUZsJyGfmM!+rjx(SH=X zFR6x{Xu2TTwD^JAEfQv0-e~wkFXA{>AvGu?YYt{`;^>G-mNAI3^0d}JO>=O4j_B1p zI@=TEmD-y_`a8sK-$gv8_x{8MU5#(Y)&>@?%Q5}m!yb>tlw01}IRvXXym}z7gFCij z9Exs35ofl36u4b$7X0vFuSN!MUJf5DUQh@b(~*tR1aJ0n6PopW`D=Q(QacNTuN_I$dwE3E&)csnILdZPUNU#I4}Mk}343#f&qN4pDdPhO^6&Qf`wq zjT_w_9)&$>hxU||u_4K0WKxCTRu6dj_6 z-zo1TYu|JEiql_MsnF%lhb?VM+~YZIkG7H_JE@fII{II6Ol$f(&UNWt?FsKu4t+kAM8smVuD}Ni!(8 zze**5ICK;jOpnfbX;LdotV;!l{F#!uEd@P+*>Tnk`CvU)CRJuYU7e>bJwuKS~${)IVw=r?sc5U;mo?yUsf zLs9JXyT@nsr^|EHT3#aBB?z~fb|q*PIJ(CRA9V;KS2J>=;k3tfe&D29^h?eduAD0D z4;5|d*Mys>jpECk{e`COc6K;eME$}w!52P$+3by6M2a<1+-9w$J9!XE6H1!__dr;? zsVBj2lU6b?E(U5aE!=yAg0i^&+05O)a^Jw_E24L04C>$5dXAYS2n|}v-9;&|3@w81 zKom{z)$-#=Y+tP(G(*&!YFc&S&~A82*$jDGIx0mtaZQBrX5 zmz+Bf_IxQ>`oZ^80`XiG>H8Nr`Jm&(L)Y`qukHO&tTrKc<$~ww;5Qx-jQRHuj1wk& zy_?}HJ~iz8df>-2ICj=ZKi;S6##sZQ-Hn?L)gdScL!BSV%IO|oZ`I|lMGQJnUKAa$ zrFMth)~(kF^HWmXgZsYkpeP&G;l?TwGGU!eqG2ne*5jtClmzxTb|KsI_l2?Rn6{a| zDBVExsBri^R34OP;5p-qXg6<-grxlhd|Qt4&vCLbzjV%_Pct`3U-0E|<(mEYeuuIp zue1J_ME&WM4NQ>5F$-v_@9s%*LUGg!{kblp!K(lKi=>GFUP>!5w~#|mdPx0i{+0He zF%xhJZW#g(w`t3@W%nq8ms~2eO^83&_ymb+h>eLZ?U9N4F0^_iHb1XbDz{=NidiJP zJnU!Tu~^gf2gE@7pRxJR;VW0yvNhK`k#i~ISBre(8jzpHnmvXrDmLEGVg(h5lQzBC zB;x&P!0lSetW9)NvcogsCu~5;Q8fI*MX%7Ad?bwdRZ|MhhLvXG;Qug(b4pIYDX{k3 zu$!OJXQpif%Z)YRmfRZuAv@PV)u#{t4-3Gd1*>`f0i|Wy^qr72!(Gvp_Ac^^keo2v znw@N+$_x8TDY7Bh zmnu&Y)~8>RN|pNt-9*~l(axQ)1BVP{|s5rraJw}#H^ z`uHpGWBm^HTZAfBRwBxY`v)bNs;`2eB)>jGbI_CEcY5wnZ=Uhay{JIYetMr^qwtRJxZHTaQm)ZFt-O1|7RNh)+sT^ z4m;g4XP-vnA9L8l?W^Qi#-vt$ZlsCq4wnS;Mb0h70P zP+v}sg$1RSPP}pX=n$UT{2;t+0n6Vv-^FP==C$Yr_OJrV4ZVm4^;A2S`G@5i`Zldv z3caS;bG)Ep!8HDw!rvD>eDB>rWysK0VmuF(aFq`2#U1mTZbmgyR3}`!RH01*b?%Fk3k7H`TmqnbWxxc0Tpj;p}kSrV5ocb2@q% zzuW&TLiy-WX4^qIDY}S|>0JzTuPaP7n}5A9m)W8P#$>0d2|`T}@#4Cb&g;h~&VWsu z7x&F}N0OR>IBCo6(?~a+-)3;O{ts=vKoO8n_{aI&Vj#bsj#;KP#S0euAyD^R5hH32 zNsq75sX0pOv!xnfIpe@rAG!qhz}{k!UVYi_e|@6@y`q|*LieoEEHQ$MjP2%+r2Da$ zjKG|U)|u)#3H6`EXsRhQqA0&9oY7$~V1MQv&{(LDi{w9;s?uA0+1lwHOp59LpF_Rb z(bvQsJHz|*E}j7D2RQOKO0^%~ZXAd#;S}J$D4OrQW!nk*7(vI82ht}JTGvLR7rd@h znO0Y`Vq##aN24I0{SMfIdjGAc#_6&hqlFgTgd0(fFH%osOP`5KRM{Ab>H9;}h*kpj zEZ0FlJKSveIgoUqBCS2)he~SXOKt*)1@fgw_egR*w7!4dmrvru*PjKFMf*GTb`mIi z_G#3~xHSEH=Zks`#QSV1w&G#I4X?rn9ocG8a}(=d#tgfE7&O>UHM3`@2!Ut8tJqmXOWJ z<-$4~d5trWjw427vS@u-jjl;Y8C|hJQ8(lh;gITOiI?|Za9@M^kMS~1NT#r$1=EdZ zgJTh4jU9WyZ9=YlZCzKzd|oBWn!r|NLqOeGQiSvoXS(cAkFG%6zJ*h2@@aj?3X&u- z(J$0LeTQVu6)rzw-O{-^^{GN9l3uL5BbTv%L{_ILHz=$o{NMcC3ATd5e%m|pmuT01 z{d)ZlJ;mze(jvi!26>HZf#Ob;gIRU5ihLe#4M;p-^E*Ib0jpdZ)S)`?n)a6rR@Yf? zgzft>D)sIr>h+dipC#p2mFL5B{RjSo`Fq2eliwWwow$&Rec0Vyi12Ij=<3ssh!1oE z!BwqN3;C2t_DLgG2wy{P?^S{(yA8$(o?sf2mkWQPPrl4%&Eum%ONAPoG~=(tGM_GN z?QOS97y2+QN6!=?HmlNV7tpB9-l5K(fvW^DIH$s3XL@AKgVqG?6VZGkA}dqx35>`C z59yXu<(XT*IHp)OjHzt=Xy$hd1>cZjVyYx9S(!f3vTdKXk<#e9NTCBdu$SE%+C*L^ zWMX+TB);7))!xE1&0Kyjf8+$m#WcV*^c%)FFp^+ZH$wmDU-qahjs_y+igXh;LWuUc z$J-(Dq?bLZ0TU z2HF)sKS$ zl+c~wrYf@_R#n#Js$q;2>zRt$cmw7ucp3Yeazt*(-MVKMnRz?U_yp6Q$LNE&(|szw zZ9WXKwBsaQp&F;05#qtthwbP&?U{)jMxivhT&I~fKf~S{f5s>mt2|`Ru|&n!3Q0&c zf-m+R+SJ}Eds_?tC$hNNz&AR{&WaSV#h;6${k?yKeWhJ`GHSi+<}w<-AI80RY}qv% z8ycZ^PVla8P#cf8AYtR-rE`+#HfL%!ayZFE^)c z%*ZA`vTN?HFUCd8oeg?Pk8j0hi_Rnv8AqfMv}P_wNUB^wy}n|+>OlZzvm=R+DSL}- z?ZIPJ-DITZ&YQ5}?SWbnatsfVCKO*7TQT7diZ_0OP1TPSu%00Pp7x^|NAaA)jU@vI zwbjwZX%X*Wp{}czJVKLB#e3x+#6_~&9I=sKDmYK5B4`vT!Kc4k-!D4BP zzQ`x~xr3hb)HgkCC;t_w8E@!?7Tu!|jMA*5HKYWIHuw;CgDw9JP zl`>?EYv9lCPcFlg54+an_FNwPQfERKi1kF%jac~jCJ&)N&0|v4dAcHjyYxNYX9{f6 zmp$G^QWsxFrbYD@aOf^}&3xk@&rZ)=G+!~ zw3y&mn|fH?iO}Jmd?+?H^MGBxwCMeuC6Aasehvr?fLYzmp+i-*6v3bU?WoUA_N4rw zJd&?KZWrhuEL!|sway$z7R9Ggh4r-iwg0*`Zi^$qjDRZrm;2rM7p9kj-w5eCfz8|X z4#hQkFjmB9w&$q+R-^A-znWvAR^1GfJ=_N9i%6z(M}RVN&A@AH-~XE1wfc2p@R2Zd z+I9;4W=0j++u4r|gC$mWe93*o8;Bi|!u`bdC>?!1kaiu=lNjfgQZitjN|E!7R{H+(bX+l; zl1O6c3;S@_Q!~e&AhLZ zRs*pD^HCi9<{-aZY`8_>2rK}?AlC%GNz^f4P}2vIy0hTK`KV!}$E2(>Gm6Fw3+Rq4 zhUBgl`ah{hoUHp;*9J_@aP*=U^4M@ewgZOcGVP;De z@k{QuME5etKrdy*4MljpL8g);!vA!nftMhg#w((DHL9Sf>37LGQ=f0cPQzpGQsQL| zYITILQDVISROz6mi)jT>6MB5{?=fs8iQKBe3yi0ab8jW0&Od1t)dl0vLtW#RL~=@O z?mX=6X^DP;M+N92{rltC#!6ZcTaQN4(`Ri*&Q%^N@4l<~Hji9`4AL;P=v2~&gL0m2 z+^sP9yfakS_7&n(qrXry=q@Mz2r7o?>yDa1y-B**AgMg*oF8}Lk47bYqS5?eST3;G zwtKhUw>#$HYm>QS0snyg9r#KtPZ0a7O0CY;*j{PYPY)M{NzDgcB_9mK%fo2{duD$A zQ$e)R{mk1vy7#g)Z-D-A>|}mk$A4pW5g5J@AAA776H@r_Y@etF`{`W@-dSOO<^2U} za<}8?ir6PWvByqmJI6YM{0XPq`yZzZIV@#jla3%@AwoiJ#A$I+_-%hZ0rN7lZe6sS zojhW=j$3o{TT(_9%h?CgNx=SNpoW+=A$Tu+yM_eex)=DSS~KWG6oH7$jT+3zjjHp} zq0#B7#ONj13bJ(e-Z#D&ADp|)H)lWE%z;Pf7*L6flWcR=*I{gJ(uxmpB&iVg$@?P2 zQLXgYPR#W}^r?4HGbLTr$kvm{(Qi+-|!XSl^Ezi4AvoIG#snKJlB@^*bnX2r}%pdg| zCCQLX8LW%`WZU(;=SfSfq%X+fx3ZBtj8!8{xRKsG;`>$OP(is1l1H6LAPi`g!hq`Pt$OMs-`{i4WH9hB#5(n&D5e$(|?tHv6}- zH<`-u)={ekUOoeog89dXCARh6l{sCxAM~%HCdp+!7^nD|gX9%4Q+KZLekRx2bQAA^Xc3H`V1O>)byx#*m68 zx5FUKYzhh3>5h4eTh|ILU!UQZVb)O>)lDuWP^dv_sNM*gStIzR;VU80EN8U2&)z+L zvM9ttunarFTk057AWz0D&}k{*j%W|=JT}7JT%avpQpjuh$(>=$R_#)zs%+$Z%0G@3 zxm*Y|#j3FY7wAPY#cN-leoMq9a74n%uVUdV&K%2nMl|Y9M~HtU{3lf+jGq0JIO2ds z{`M$nB%dK4eD|2QLXyPJ`zrZbAPG!W3%0IXpuvQDv!M*APRn*77fa{U$?I~(I@7^z z@YPoc^Bo%Ww2ObJ^={Nf(poZIh}s86igz={K2x9P8$FpQ9W;!)MhvkSgvkm4#hXVv z3uX_)Li~Jdw%<(rq7(y-#yn`|!AEg})b9RSr8>R7zRAU7j8bXFx16}F{%6ifHe;7# z=HaE!HF#}l_wAZFrM&$n@?-wR$laUj21$n`L5W5iAAEJ^U?e~O#hG|d6mBFhlyi5crHw}8O1|b8;DfGiehQzmnU~)SX9023 zED2_Jb7yv0UX`VB!|Atrk(MaN{wKX+$N4u^k)~sprPGVjEsqjn^EK6TkZXbknxaII z9?658O`xsCJ!++eK~JiCTFLOnowQ_#!azqYS){sG0A47lF_({DGYkD%{M8_&wB?R; zU3bxLCh_bb1IPD(e6PIaySpkxX}d&c5x=xxMEZBNSx9Ja(^? zGRX;l8H*_1ADPb2w{UgNSbSsX(wnkgW$TaS&_1hwJg;#=&P=0pNW=Lr^-SMh)ZB`o zSiiI?L9Pkjw$v8$G{S(&KpZPa)+Qif{NT7XP)d=!cMf%^Jd1mg&Oxl#kFux!(o3{i89--EKLi=hbH?4 zmF18f%GQ_Yh>JPe-3d_|t4_M!a(AGX5M+u^(1_d4%`!?p|7$QQ_F>8%coGop%3$kY zEkT@TLXg5WYsUp|@d}9aQEi1xhRCHTO|Q0>@+OK~!6#dq_iOPrN~zzkkRIhr&q~^q zs8jlzI>a@@RprP;7$7aRfj^j=^17cG@vg14&n!T=kHV5|28+m>2>kP;q(FvJVjyI< z{@tjT&3+CEp-Ex~Nu0TDYf^L}ui1l8Q)Yav?9#grpdGivvWsUe5^l4q3KeyohqL?# zSzY-ROX&aKaE4`C^?aq)hs>`tMXqCYjGt#aE$=0o(#+(bE_4i4Y27;^Lrt(2LPp-x z8u^=nYX-LAio`O#d{*z`e|KeIG!q@e2mxN~j21yX1|{1E{I574WTC(?S0Ccx-p1#z z+nKFL#V3|!`N1zZ%zpTK&t2`ATf&az$OdVr6}4Sz1^-RC9A@ zsqWzVD~Sf=biDGy12w++WL3B@m1`cdsnO;np#!Lw?~_Xrn(lL!;!eytjh$hf z6KIL^@6KMS$b%{KkO$m*_pxV6ThqG&=1&dG;e9O;XP6dKuK?b%m;`Sa5p#pybeF>M z*NY)B3N?>QqeMXK%#X&s%fDbjnQ@6DqPiWTsOMq}D#+Z0tT^#%M#CgvnU&ha)B{JI zCss5DHk%()1chv9MsAG5`VZ+X6U6EV_OB*$O?5)5pwxQehaAl7?dqhn0m<(0Plp!t| zo_CwH-kA88W?nntzs%PawD%~XKSx5=AJKi!&|A!CL4UJYj@bRk1o8KV!Td07rD#m; z-LOQ!G%HmRt+=LZ0UJ=S6RM*L!XYZeSm%cK`X*oM5`iD#)I>x3WJ`T#Q$i4OSh6J~1s}L*k4s{p#w+-QZA282B(R*0#$S9?jUZXpBEYg=32)q8%_z0Yvm&b5ss% z$YUY)4-6=Brouv^^$#uxmpfCYuwG-jG|yh)OH@#`Vm6WhG~2DFMyLjb045}m)Dt32 z+bIuslY&d!z@z*YbEs-r%}Z-S`Q~5^3qO9*=;iPD%0&7V0dpEguVMuaQo&Elj8wO?XSYe?^Hay2CpN(e`#K3hm zDVXgJpb<5^=dl6P#iQjam;+S3K%Af?3LdObL{6G0L`DuUtM!_3jc!(MaAnl`^NqH_ z_nGVp6M=HushAKNPo_NL61dx>AFjL&9{a1RFJ7)iLmbk@j0ZRP${IcP;MGpCt@3vM zf=DA&xlGfalr@G1SGZ$=cflv@7V@^#b{m6zB9oe4>S+?WyX9<`jdMaZi$q%?g_Y_| zXf{h#3+!Tq;H1_Mn(S4y>Kog(yu-Ue`Lo_-LKUYt#6v(ZGykmVkWc_Ks5Do~wzvHN zL#|cVsre_c!2KOp49+7GgH{YyU8-|`Vo3Qhy~1|rQqskLUU$Zw=~a@5eL5_GM35Q( z`@UQUf|GyM7Oz;>?JmhQOC2RPKd|(8U|keimDBJG)|C)Vx~kjfDKP_)R@h3(op>lG zkMEkQGx9$1CW?IZok7(rw+TlNno)k7t}sH@vtl%p(K7kp?;5`b&h&Zpr|M*AHs(>J zg0;g2{et0|$LrIwCsZHyP>tuneo_I{NA1_AXEmvXirhK}$ZT$OtvhiUlSpE!qk6i&ePeN75e?s^uPKYBYV!TC)>R>ShH zsn5rsL1z|p0dbwueZw2}KJlC48k*wM-8b_}M zr9s7Nm6B-#VwmM^_9Os9yv&e5onDT9XXYnn?AHYyMTFeP-+{(cJ7|=d}#rxX3mv6_M zUHX~DcRui?HMS8x@K2kRVIrusNwoW_&B70{!WBXb867`ym=G};b8oZ1xbujVUpzKK zvscL;F`sbEXbFmJ+Yty4_cqo{iyGc*<{5@r@iMNH8uV(EgeXma$$3PiJNM9vB9s3h`5!VTuy~)0$&YToQ<$ETYY{&VhtnUhiHn}gAiR*YxmpH*c`QIZx zB|Yp?X|&8wjCycE@TUG%%Jk2@uLi`4Fg!4_#03IxNHqOE6*df&BN_~<=$sG!ee8?; znuZXloi1IYsA)XGm(cC`8}h|$88IEt_=6t^<;it2?lW zdtH-}RRYTp$&x$8<|HUKEB0CHzC}4dRwC#f zv|h&Sfxds9?dyz`Q|oGW4cpl56X7TC_NLW6%lZClQYr0%w0@^;S8lEpp<6z(&3Qku z<)ScPqThmtEX9c%=Pr{~lovB1M7W+UeMJmKorV1>WrN`SKE=kN6TiCbQ+guD4bY%VD|pNnGxeVlCPr{ zp1e=?dHjrXj-)05x?Ryr!m-4*>j#$=ncrW49{=q5c3(?9lm92EI(v{y#lvs9;^ zgkmBy`qS={?Voc?@pSi@OEah9b^{Spr!896cLAZismF=bYLBmDp8_s>v|ZwjpT-(v zE;RNUXg%_n(RmLinD@yrlN?`*nvS$fJMhe}1m#--cGwY+V(ZUfuN0d-5ANbKO<(N$ zkB5?yCVdnN7ONWS4QY(TX)|Fhs4cg9+C*ymCl?N*bV$W~lv*~t;b+H7wFq%Xdq-=A zgOtL9fafB4@o5pW*SC~D&z(E-2q54-fsA+rC&!_>4cEsf zL)r`(L*Dd>rvB@yO?8%lACo*&trRoB?2zEiO{2!COEJPnl#05yl|@rLM1ljXd+>%w z^=mNxvqfOw&fbTmPE_Pm7N&E^#KLV{cI5NeLE;4u!(oPw9e@YixmX>Xc z>4*2-G1gBL4yGmI17r5UD6618{caLndWIM-PR}Tm`P{CQJt?MG3BBXQV_GrXMlF?(Yw!@n^j3h@U_Y?OY3?M2>v;m^>y#)^-@Y`&m z%sgjB#y6DjW-_35qm^zJ{D`RLEbMljyj2?fCAj#H){7@y*BkqY>-$&LAN;DnA0#J1 zZ4j~ZJm#jhaNb_-cm=!I*8TAbI4-{J=lS}A7zU3G>;OV7KI!dN4DgG5Whq zwFSyRbuNsMvG5wxP(7(D&ZAe?s^wHIOB`N7=GQg;0on&eH$xf^IWEAfXygd`*@&gBBSk&}+ws6uz=bzRnn?+ypy+r@taMBAk%ZtT zNXb~g0~xK$1%$`^$5)JpFJ?x6F_m|xVkD)5CXdlIq!R>*ox+GlJEZNMq?> z1}NB0vbAVCMQeAyJj-KJSg@Mue`{o9ol=y)a8&sdeN~#JuFu-Ua$@L5}bTp0}i+UrEZ=`8WwrEg!&7 zo+=o($M4^_UfRu$4$>lMA*@$$LI~hOq_1^@J+$|>-HNAU&qy;TeKu^iZ6nJ=Jbb%I zrJp6^GfdoR1!ntWJO|Av!FbKmuS*Y=HRR_Afai3e$G(xX zs)Ey6R%QI7rXk*1WMWBBZY?wX>5|ppRs)FU-s`|Je~UtZe{imvu--Y+fsO&Un*Sb5 zqmv8ul{djpUA>m6Whk88&#v;+&+u&@p~lN`_m$|N=}XzmMHC$sZ?7)|_uqrW4sc+goIPfpivjZP{P)9$_C`?;6+x^u;xHeDo@;tl!C5fLIzL+fcWoy6 zn`ym-O^tJy$W7IEn57i?!mJ*%N+nh3Aq(gIUvPeuZDm zeg{yycF@v;6E?(O?Z=;q>nTiQcim-4FeZbQME@h+Y>VNWFWXAY02Zj_8v(5jP4%mX zsZY-AP1X-MiR_w^uC|;nOq;UU^iiAdS^KmO3qrZKV^$oji%ojGxhqU_Mr)9+O!Fr@i7pwsq={=aux?d>T0ZRjxST1y zv&s%s*rqG`$nX6f{l;W1WMcCSHJv{e=TgnNV{<511lRf7m|Ssq_sWe2vKa24>dLOL z^{%Vy?J~M63Bt(=Rn#rgKY04JC@Ren*TceN6eG(#u7OzdPiVgCwd@7h`SWZS4{hq% z2{T4R1qIhn#$k^B{Uh?(_SpiD|0(?ys5L5dCi(sl@;S3%zp}L*zK;IO3fZ<2^;jsd zJ>)Nh*F3CKA$)T^-5)sKRZ+fP19wVH(y7Xj6BTz)>y&+2fL3&2AIwxh*EtxQ;2I<2 zTNxgclEi^vN7iD1CaK+^m_;es} zHe>Rl1J3|ALe$~D`xWyxrY>{xHVe-f#K?o63{xYIAA>w25ild4b`MsafGV~s83f_1 zrjc5}j$12o6&~{emZ1!!y(`~;%=s)ui~DECU^!d+i-ynCDf8WLhnyK%yQSI_b}hZ1 z-6J*>`~;SI;PTj~2nzp(&4~BrTX){_N}UrTxlM$RDVKf&5-b7ZyfPKsa!Z=YTcH?_ z@q`MjSjkm|->%ZKIRwovI`h^MBM7%^wi9|EhmPhqpvQE^g1=8b*hM{pl;*wrj0pOW zHZ??*o?_N!#%QY775g$?)oZf8(+0K69{J6Ku&Fa+e94p_XK-jRyi3nFwXrf*o&;Ka zbYzZF1;I5kl{#w%kD)a@>(NEWG%AVvf^a@(I#VVz`Xp|vO*jnOK&ePKmOHIyqw|#X z$YEG9!`Q1q&$_mSjHotfNZN7H&0t7p?hfh&hSr&j({BJsg68ok%(iIoXOy~#2vW@Eu~k94HFD%(PeVNc_*! z1fzIUef2<_xWoRr@Y#{Qaar2o@KQJ?vDUK&3A8j!1No+_qi3hHb8_uOAV)mNp4V&` zOHnoMe&4HTikOX6u=^gIlrQjvUBfptE{7^>ru+GxjM5Ev7d%uq&sb>mQrzFz^R*h2 zxX+LQjk2O$!vTYLXs#!w(})8Pr0%E3%a-mRN|RpwGiN{CQx@6;w+j1T+YRIAu1n{N z;86Glr|wob5{F(!O}Z)qernQdef!nkYY$p{)UBwOG{edSfmUA9J3s@YWTzKWa_MH zce(YL;`9=7rX(f+XEC*Tup%ctFvr*J#cYQ;H_V3dAOiMW}U!keUT{e@9TC7J}=($2KgM@XzpqrO{wuby&Y$BFJkd26t)zr zkLP8Bx&&FSNs5rJr(14ScU#1EYKvOFr-gJNLb7AV1QIO@F|%nZ&{X_9>i!-k$aZSu z%p9tm0b}vJ2OXpFit2<;g$2YU5YB7ADLsTm|3knRa#Cx1?So)M z=Ws|I#+{*kETKvk*KmM*f}?sQr^7Zcw+ z-R2<4S%nlS)a`%c-GWZGJ=oj#S^LE0ullW?<)(uz+>*)GQAtg`iz{_iJupH&vu^PhG;;V$LseHp z?}Fb9?RZW~9gq$VOx;acN#8h3e^Pt|akjhjc!bo>b9b~BVI2`*Zo5+1-WZ7Q#wI^Wp+hfgfSU=t8V772%?9)ZJd zp!@dToN6ihc8)Fq*_FRMwImfO;{5mub^rbgUr<&5McsECd???l67duf)Lib$d}6W} zzM82!BUlDdgq8^}DFxrov`*(*@2Ki>qLOKDP|i+QG0kyuNt=VI6>6~W^r2aQRO}|r zos%-xcy6(L3KaE~IBx8jd7IU$eunfedfVT)Oh~~-;9e+Ksm)!?laKsdQy8bp_I@EU zL3Hz5Jy(!bDO?|SN7gRofe(JA#6NnBbIX~gB_6da>=c#MnGn}mP$pli@npeV=**zD zVaGmxqGB1$-^u>d=HGyy&wfZC%*Uv&qhnR4IkMjK3bj>r>oEN2kK<%|gSkA+LpZlB!byvrRpC{eosp+?s(SgWDt2jC{3 z9Y&N5J0h$gQ+2z}l*jU0plCKJGp|1*BDCD^Zpy>l&O4e`Zq;eIt6Ibwl?{LkaMS35 zB_SJGa)}BDh8fY&5oqoo-djFLO|5;5rDg)F0Y%#hm!0S~{nEZi-L+s+U<+5QLk2d>S`Ta&&vI5O&QbTh z7AMZGe>It}ta0285B4Ai`vmNY8ud)BuJ-KN`M6?H(&y{Bl`VIFm@S=d`>d(*u3m$J*~>X7-LmJ{u59Hp)Na-=s8MsO`x*VaTUg+J z@8$*`Sn9`FnL-zyD9TG(&h0dGhIc(OxUSH;AAdNY@3^nZE#|AiTGF{F{|vFXtb*@V zLt$c~PGSY)C%C;gM9f<5b=EB(!0UQS=R`4ipnLiqVQZ%k1+~m~7)ANz?P7j!jeG$6 zF27_L|V-6nk=a5H>3;dEd~qk;pJqwqK&;*@9kxM4J!u(6$*tFzeizj z_YY#0GS7@?`kTbO#T?rMKJ!WxR$;}kUdWwN{8It6DsIIDn?N61v-y(cvsvSj`y4fG z;*j<N| z#Q3kHR?Ne?|c|dX#V)vYh5QuwJM9Qf{G^yKI(ope5D^BJeHItXab&gh4wOn zIb8|+pQM

p1FB@dEQJdP1BHsc}Dd+mm&o>Mn2b!RgvC3GnNVVZ@(w7? zodEY!DnTXd=je5;l2uYuksf7lS{KLQFR5l_7wbR!3KSyV@@-*xG!L_lss~~6*n5oq zYDiW_QR3|&#R8xIN7HwOHI;U4kHf2sqC`Xlq(nu*N>w_^I4F#RfXXN!O$-pF_Xuf& zNKr~e1f;7dh;%S?5|I*WBGN()5FnI5sOic6`40Z`eXy^+*R!7cTI((Z4dp6}^st~* zwxPX~fKLoW+8BeBlzPG*-xJg{56^zp)Pz%1BUcLMF55H~UQFJvU-v<I! zw62#WU08rX3%5;$y&kexy!mjKQ|crNc{6WHG&3@z6z(&h2`d?SBkvJ*wOrgUC%XBKp1CFmxZatVe5(9PzAuLY8|%+$XdX)M zfgz%;4e6Je4uer?i|{G6a2I&F)QauqOXvnZzcS$p*^w?4L30}p-b&0#3TS3j$zlUt z$Pzz1E=hOG=mdGu2}ac?<*PC3D3H$>g7>lp%aMmdQb^HTn|qnx!u5`EpqKEb`HAXW z!Ot)&h{Du^Ei4|Zh!hSGcgM9S=4CE7lAJB)eM4PV+Zr^t`Y3TtE58H)ZhALYw)pe2 zc>Ri3`3k=mwYQ0CmaxMb7$x3v!@^s%#qLw2CUJufug#wv=X-DaqZdGTh5txP^}eNi zmn16>Wb?6!Exh*d_95DcV;;V{nEU~#AuZK>C{iy!Ti3~mwHhnY!^Y?Fmj-+SxJ&E! zB1of>g#mZq{J$oge8uDjxi8Bv^adEsp^%H92ZM4-%Wb|EGT&ONouZPst_5tnPS}Rw z?@Cc~c43o6@>@M{`eEk>%`%oVD+)Qd`Bu+Zu6e*RvED~<=Vi<0o1gRV4aer5xM5q6 z0v2|mTFWlDRY6_`qen?@35lirlyRi^RG4T!exRgoIo*j4K8mr>PJTjr zw*+6?e775aq{F58t^ZuQLpQyYk~Oe)^2CPrt1IN=ZBAIu7Es}|8x)2QVayma0ZG^0 zTR^^B<2ct#1Z=LkVehhujF-k`O`80(TI!Bw^?9{7-w>Xyr{E2Qbzgy-C)m{oR%`gSa2JH$ylC2RMzi%P zf1YHKJ398=ZvM%oOF2(e54c^4CJ5{V8DCbfX^(X-t{iq3$(eXr^{z&Zml1A<}z)&qZqF6*s zabzWYzB>?SRKdTS7@YAxKrNuKEud11Yadw~2ep_mDHcbjj#{@n5Uy%HR|48U_;e7) zGs>4ffu#*5Mxco zf9PEe?(=_rjt|(WEGAyC-x|bd++ey-c&OAQJ$KyrSNW?N!+z^7J3*F6&9%T;!rUR7 zE;(M8NLk+hX8C*IXwv@8~6+5Z7ti1u}PJV+S-VgyOa zMc3F6mB>G{DFIySdNejD44d0HiTh)#qfNbbwE)ORFG5{*B~u*~*VKGLIteYoB}M}c zL&K+_Yxey<$(eAM`ie_Tpb^X-rXH%{@3%^}7aWb)Yh+49kSmn^ex5+SYZO~^a>2&l zZ1E+&{)*W$Be9Bm7yFd)N%dm@VWYvXWd_{$>Mn;m`pz(4+sAqZ)h1CJJlXY1)MM3? z*XMSl=D_i|&Tiqx9y^eQ9j*&{*t{+%?-8Rae9FI=FrT(K&vJlkZ25uFyvX_Us>W=Y zD)o$kMFW&CqG?_5xy$o)_5Uu;{1rFTuF3b71vlCUTYTiZPwTgmmUIlSt7r4^4@AS6 zT=OEsTbjxmjk1tsXM8r9O+`Oe_0b1rePZ_0g1s8SdrSU$rt)@u8*IkH~aItQKwO-M;K9KdvO(`O4mds#fH0 z?%fg5%Y9?cx-e{>VWt#D*;zD$tP_ae4@xsDAyLMHU8p#}Ri!FQV7vxEBRL4$PZiA5 z#`EXs?1#CmPfD6ZpqHJ8a?)aRYJ6U}UO;zS4ks~)t88!Jdi#1dH%_K_xAZ2LIy0+@ zK#@qg?f(W1N~ZerlN@$$FH*l?ej*Pwbv_OGHml@n`|>c-vu=BCGutha!r+03U*j~9 z`YY3kW(zB-v#1f07Q3f#2BA26%hy3#le2dp$n3^FG3tGU5_RoeL#oR&lMQCasjwHn zrQ$*|bc}${(oqWvx@dOR!L~d9J}r7ohlL$rIp=&n!}sczk+9)q@5 z?Kh6;2bYIW)^_y~UgN74`^#87#ahL+l&#)9_)ObghnohZ!ExtAp3bwfhuP3p-N$Nx z{u{=Zn2`_q;}57`np2%rHYFI>-jI@8gz8?}Y0$dit!&Y(vQg*8-rzcU;BggIHUsNx zKI%Cf-oIvw#mk2)XRj?2C@|JT;r@+!OYhmEhvx_9q#*G{$Y%bN#Wt;q(hu{u8`^4D zizw??mTgV8w=K(;z(0}`GHV$5K*p3rMK$Tkd`;($lfr6LT5t}sBHZOaL|;(wta1A% zWWV1~+0d=oH%*3Xp}A*l%Y&1k!B19|AOyjT02?{R`2#if1n_Rl)-s*mwa#tp_%HL> z%exk>_M%rupjPGECZBS`t-VXHxUqkck<(%KKm(*)^LozRsu5JOtglg)bGI%fMb8K< z9D+cqHO4pt&t#DE@ij^i%wK@#XX3idOPe%%hZJ9le z`)>_&KDmD5R7-_V?!PWlJ-*^Ogl;%eI#_SLVlcuCX3{H&~spRbnsB@$vyiulPTdu#I?F zxm&(gQ4UIo@AtTD8-3V^c@WY8T{`6>Y(fR63NDrq;K-Ynijha2!ASg)AMMgRhj%34(rEk}z5f5t1t9wk@lIjQd-t;CmG{g?L}@O*ft`(&o_pDUKNi(Y z1pmE7x86Y>OPF|F_^`V@x`_VgfhooOax3Yc?0Gb;e}YQ$~a6<{?+8x5+#IK&l>wOs=`Qp$DazaFTihn(QQ$KsFD2`D zC!E&NXMpRUSg+;Oh0n_@c!kclDSm%zjUkkq5~;)ZetO<5X$}gooukR%tvz~x*vjbtchLvR$tzk_KPQP3P-)>lV!1*_W=VOEYAyyf%RgRg_ zK-A^G%CE4+>K@KnN0VXy`^gsKi|!e$#h9n*O}Si8r!|oe2Hh#j-kmWKc^=6uoz-G$S~XVzi&D0(yKS@gR7;|oj97-x zt-52soZ<=J5;H7qrnq1qNZ1-2Jpk8bRNci(!3RPPyfe1XqCA+un$ zdQ@M|qZ;PfbZP*x6nz;? zqGr77(W+N4Gng7g6TOmdbJP_iq?D6|E~S8k6fHZEbrKD*cH)+nZB>)N_s(5el;LV1 z5QaKvvSm=c@*9-Y|C$o5cZy=AyhHrk=?Mdz8?2p3|Jt5Bd6|rXqVT!`yMoTG3!|5& z>{3O8gSoD}Sj98Z+S;Vc9$>-N1?qhK;2%aPOTc;R5LN*tw z{V2X^E$y5ltgy|e=OwhhzUa6bm0FY1!1xv?~)?M&nH)Q zKjWu1LD96~?cI7{!D{Y1G3k{Ok-6Muy8TR0EME@Te)XE(We0S$+|C&Ww?;GEyX9IgHtUT_I%H;*Mt*Kh`bc^IUj*$l9@JNYjVi20G5XNkX(qav`9J! zCgXNg8w20yA8--rdthQiLZ{ff9MNdqpB$&rxQ=_yt2ySVvxCwiI3hWpy zz{MJhilCp=;t&G8cG_kGNE}I&=@6bB6kqq zzil7cwfyYjs@2w-_}|XOhmuqai&1^J8wtiP@oG*viP+2&OE!7q8j^%RGe?;k`t-%* zM0ADd7W_hy!fWVm@l?Kevl{@)S1pU?&XMJk6Y<;|>FCzgs)i(=(f^ZuP%6G^Ton&b zs=DrhZ{AAwD-*g|EqLaCs{FvZ94q{;mz$oAbRaf68oY7T|r2(A7*% z;@tcRfT8nburChwnq{+2q!NIz{C`XZdwxWQKOe^AKdlH2&5sDupRx=m2dn^V<~wiY zo*ysm_oGPgLs5Iu2Z3g`ae41TT<%cj{G8gPE>(+Gw3$YbvY*@h?;*BQ60+Mp32Qx2 zpL8l)yNWP@&u3H%4tQriO&Z&j$*kZ?_vG&`ecOcb! zHC-X8e`Nb5AnS9P{&%^ne}eRjy$QOl8Xl z+?A}a635rjSDaAA{adUzYCW+LfDF8YTm#HUH)ipPl8KLcsK({<^Fu2(PbLTA-bg-< zz9g(HoOZAk;}0;SZlK)~2KehOEQ}^gcG;_6t^2au=wMw@0Hio74fvqhOxnTJ7+pKb zNgO8K+U+w(InDg$Mo5n=D#yE`^QiZ*i6N#XSq6@E8fZGQYr-(-HCs|Cn#|4vSM@Pg zEUwX+eA)1 z?9p#<>yWZtbGcR3I94ycA<}h|^Q>uE zucfRpi35Al7P08JuGk4i_`HJnc|e<$urK8Hq)bszDsLC5Z5qm*c^rq|*6019 z*=;)>MrZ@;uNy{V%P1ST#Mu@8lfm!8$@HZn_H27#)ZJCJ?URTLy19b&m>Knz z*9{x{GlmWlP<;?Z_D^fKHcqCV(sEVj)oHNB33M=~_HtOHGtemB+ z<5RZk@>bVzaHkx4gJmdMx_eaSP>S}e0?zAwTot%#{{bob(r|>_tMQXz%Fhm553EsP zHZU)=>MgrViDrKpZGTC9fpbj9CtVC7Ew`^?MyZZ5IK5nOY=i z(8W_AbWw0w#6ZKM11EE}z5;+NO;VO3b90ssIS6 z4y38!?as#vt;K5F@{IsZu+GY*nh$X!SZ%Zr|BD)0j{qf_8Y4Vlfpb(jBIAvu#jwds zV!GWWv0Ho@H25lHcW;tgCNTjfd#rJH!N#r!XxIg{IXBekC%}F(N#6op)6LshOPem+ zMinKlibQUpf%CTyh3Z6}DSJl0tl4(AoGp|Xh8ISw!nzAv94$tbe4o<%mYsdw0k$1( z{Uguwxam2Aju_y)P-oHDY3ck(L~_LsHNI-^3n?h|dhE4=H6m|XE03%8)~ZeXgP)Eh zE`f-zS}U!r&p(*k=O{nt=WJXugk^tcPkMw0~lEMXilN-wXL*ph8wu`L$x7?Z|#ccqfIeU!B>s_o81J z{PAsLd8Y;7owyF@dV7*MQm`3-Q(9H)x1M!&mnS6CqxBf-Yu^>&!&tcLl-Z7?ElZWR zQDMW}=RGMJ0|WITO&EOCzTLR?4suh*y4+rA+cEu?ZkfK0J-EsuetHhxsF&whO%zxt*pb(U!Ss7> z-W9_5r0Ps$qgS#kz z!sn5P@8v4sr&B&;Gp8mlrQsF6<>E8tFIAa;!hS3%*SRA4>^dWIOVy@u? znA(6?#Ea5)%vfRqqkTKW;X8E1p3%gKQLAr@-MKp{dsj99Ngowf=F6Bk{zVY0meV+qM>X3`1D?&{G)tn2 z2z>DKqMl*rnjIaqirKMUX@m3+Q*HIjZLv>-* z>K=RkDPW&eQrce<+nyfGK+QXjgXheleo;o9RmtC3^dVsP=#}^D%$g<>GHT@d^i#E& z5DLZXKRCn$?eG`W119~OuZhF&?{;Gj530q>6v=6Gf8{S5O;2+0T}Q3fGh8+e<_>|+ zN!l<1B`mu9yMbAFv572Fm$f1DQTgud6fjche{*hA>(j$pf8>P>1 z!t3su)6(AGDQ6B;NQ@NSq041ZCXSDp=abr=Vz}|lno$&5IbhJxddf0qlL8ws>9Li_xRZQ zqWJ9{*mO3Cu=#`o#|l%YWO1UlmkX%mw#o^WoqNlB!f}3oZpT$p#2X)EqA@(LqQQQN zQ9hi?1o{zoBYlPCohp6^AwKf$r6O_00PPU~Lg?lMQmB8_GOGv)JD4Nno)erDnt4QL zt|Ky+VPs%G2uQ?kr8$_XZf6tXjNe9vw!9vE#<~G&>b^CMTU&MIMMp;*2J?=JCR5zh z+1J~ml9~Bp<~ms~e`2aN{xG97%yj**QEE!Qpi(c?vsBN_)+8*pOfS~{@sH$np6TN= z?2#1FFOhTL3)~?4H~CU-DDSljQ|>|QXQa1}PF?S;N`Pqb8jmC139hG3ijN%w{{-)l zx?t(`>671I1~zqDQcvagyG^ibGQmXchq0(~?+L%JV%5V4hZcd>+DG%!_9uMik=kn4 z*p|*GK}YxGA2VV2Y7;?2A_lcoMl((UU1@L(LMpS`6m!lOos=-ZK4e3MygxJsx%>$TD=Z8Tzz<}!6$CxL=7|g4a@{@4UFqBE z!Yo{6J)EG_%!Qt&IVaLS?tRUzYdnV$L$P^yrM-jwwcJSV8^bRzPY&9Uw8sXyXo5)k ze#KI*la{@tBC1~c`umLtL%)yUVxld^C%r7|7AP8Ou;7= zLF;OyX8i($dl(!9e24x`G26yE8-ROxZ>n%Jd$l_bO=eSdm?tiwv^D9Y^`7OX4}(Cf za&Tm*mL&*P9-=rUZfBvShP3H z5}l8A*EBA4t3QYJ##Z|1ekD4AG zl$rgLma*b!SZ^VMPF|Wb=lw2)Oq{f@9Wl#KxU&Ay-FYhNV|0?jT9q;3>4w?Fw`&f* z9%MrKSc%MS2m~@zxO(uw;Mkr>oS3N8Fx0aB4SHj57)S4;H<_#<=ycwH-y{s=)L|wf;v*9tu0D)!Tyj=KbYmCwJ&NP5FzyC~=QR|$ z>c(-0m2X%Urf+qkF1iM;bUFJqsbWeP zKNxQ4nGE~geUNENqQSPo?(H1~cz0{qPXLGFvdUj&_b#W%r&Ay7L8br5eiCJ~Rl8^gA2%!7m2fkph1zkIuN{=0r=<5_UG~RMpBj zUDH_ZjyCIbU9uqLiN-$vmG{-_P0gb2b~YX+_#g|)d-8|(De`OgMCCBO4{i)Q^az3b zX`jHid|zM>Bw^O=CQ=b73_c5wGtPEV(@O^A&oamGns;gY4aW znj6+S1?=tD+0pJT{l{TQv62U7qIEwC*wm}ESJ0MiB3@On3ILr zwH&u0N6w3GYV@G01ACNg3E4u3K|e-U+qUmTQpBl+dk}-jhqgO82Q;us%!Ly2W5|x# zy$|9FOt?*sfz6mfKB#wBdKsU&glW%b?|~urt|EyLKmy>TA{^8UE8{Y+bdfPR;*y@E|> zB1S55O3+JJ#0Elk#+LM2)77m^MB$>b&*>Gd`QoUR4A{zN{*~44&;jCGF}B#WnmzS_ zVkV%V-TnbC*bWN}AXP|K+bA1YL4e7$c}&o}Ftk4ye%H1$l`c`)xbBILLGTlmtn#VH8P$Jg&;g)szMDWM!Ln?4) z!Dz^DT-SAyIq0#cb1p-IX=CD)WBKQ*-mc!GtrvxEOuetToB}8D{R2*et{N-_=n}Qd zH0Z5uYuIQ~T-*}sdWZSH-hU7lgXRpf9tPKRMJ;%w#q|uM$|1j|@8oYcxQ8n7Ku~zz zq+{|hVPr$w-f3w`bz9j?I(w9&83%hdsJFds#Rj)mt zf!_#ruhgJt=E(o)VMmcTs)$c0muyOJ=$-G?ci51DU&pK@Tp4W{P~A_pSbR62ZKP?X zyRH0kAyFhB_`B6vEoK^6xE$X6t(=}OK~ekBc2oPu`` zFo*7pzVFSL{MYW)pyxxamEQR=DR4A)!;e{@Cy)T+dyF@cqL;SBqg66^e^6Pk=s)|* z?M`8NhH^ym6}Dn(hiUh55;ab~o__i&%l=9(3LtK`vexsEi}`NVpnC#rQ zGArc9k&Y+4ha*)C`28m4&Agv2<6`2ZvFp^W(QQ{D-nPCd!*|{inj5j@DU=^bWnt+V z{N`UQV6o`|Cu4r+9%qI8DdU8GJ(S{sO(&nVQkg~Kr;D;%Y(bWZ-q;viOP?%gpvnIm zmN$y=`Yw*yxq9_D;zZN)bAPh^g+HX7^bgciC7$HOiGm>4?8cOx;wk?Ay3$T(R(oQ2xR%ouX}`wA;uOGGXqp25all?f^)zc=H_R8=I35QH~2+iF@c$2CHDfJi>g< z*6T{Gg9BgEuw^dm=EAq2Dx;h+2(eNAh(U{n*=br*G7f1NI!;_ifc;T^sG?H({^%vE z3Rw<8OdM4Gh?v@mQTsklC2B>!Moe)##_6zLNy!$6x}5Plio>Hux`?T_?b7mZ+z(A~ z?_;SKl+Kvsf1p*b*;4wzjflL1Hom1T|AewKtuYsi2-2VduGXJ{17nshyvzuCA3Ia; zjE@hkSE#LJv;_|~@U*6V!h3I%4cL#FXyLL0M5wDRxC`=*=IhWF+`MDP!<}BrH6_+i zDrsi!jIK_{(a-rZh>al4CdSoV?Hh+yY-n1#zL~8<8n`}|@ECf+pB+tO|+Qf~54HInTUXLK2!Rw76L&hVb z^A(z=X9HBbi+gRu40|sUy@5CLWRyE+6)PlaHN-YVyWTD^tDcELN|1fQdGCm<+5F~D zJckA8OYj&dG1C#|aM<(|)`||HwAqeSN_!b$`KRg^VRu{h)~`oVIpn zP`42~z%kr^2?KN9u^GPKe#_KYmvq9%0>6e_rm;ncL3spLtdYS6F1Q#k{lLyTw`+Hp zP~U3}PRAQTL{~BR8%menx9Um zMeN!au;Oo7)R&mteyjy~!J$sD|LuMy?)y-&rkts)WIkFr(eyV!R95}iaS4B^;XgNz zY0ieNTRQ0O3Ot13S|HYfrX}o(BsI5c0?Zf#Bd2|^5t9Uiuh`cG`K1+^aHcc3*2!e%G<*!=#`TFkHG$uX`+Ss%pi#JN%HJMAZ;<*v*|zpa0B1W+Y@h z(Wi0ZppK*P#c}VyU>^{TteAxMaa}Eu7^nk57(y2i04X->%M&u8Ytw=aTSUOK-O;UN zTvl;p`gpuq149>kuGipsvzN-4k?w%~7_n=tiz14O;+tiPfo&+S!#|`V$bPwN>X!9t zX8#zXfw+u$1YHnl_9KziC5Sl!uVejhvNbI-RY2m!y3JlC7f1rT*@PBC8{^rfJmMJ2 zZlfaSFm1oDqCo;!xj}_%P9{3`S9E`ErpOz|bf7}=wmG6%+tqB{A?00-oPPX2M?!4( zG<3h@cdhH2_e9sptO=@o4K`I$q7hB;Vm&iWVg2I76^^e5oMHdNHeLcuD3~#E0Z)r$ zzSF5?pF&&M){;6Hw0QmX-?pV|33-$-KM#}<)cHbohW+t_eB(mt@T%oVKdHYg1uK+e zpTikO7zI*D4R|wIAQ#XXX26Y2Iiusk)O&ci0VLnPSbchQbIcf~W8|R-ClXG$m7A2w zzZ=hQFM<3*1nP!J>{(_)1}i2$6#s%WWTKDSu7qNu<4$Y5yb%1R`6EJYx5TK6Kelwx z#z<|X^R@nw0zp(sCT$G&*xs=!+Dxbfg}`4pp~9UzUQWDr@XDc*g~+v!1=lhgf|@X@ zgjb-@uKNp0zV|?v4zFY9uKSfO&U6KR?{w^xYjE7$PgpD$*ip_NPXO5moL#gZ`Vc+&C~(|vO{ zv-?GkV9|8dh#>j2DD=1iL}3^d9NuX}52*b=GEG`RlRy8J{MwYk7_n0NkFCi+zsfw)tB5t^&OnZTeVeAd!|Wkf{c!)BP1r=>MsM#O z-*C|djgj+9R;tu&Qs$+OtdNbYsdrl5Uv^I5U)g#%=#3NlT3G}t{POK~!%jl?&2jZu zW0GpYQ705M+Nr)ua!3sX03wAUXbln-McuaC>QeJuzH^<|wK0*DA;&;=(CJ(-3;pbkppI`!G?1XE zGmK%Hu`SgROF&~>LtXQisFi21iMxUfT~bE3E@#s)d*hLAYR>YO9T4r;3K9HO9;zY02kb?! zJvF2D=uOZWI{6~+vAeusXU_LoPN1 zjkxe88J2T@re}G!s5T6Zh-!XaC|$Ih+eSNP`}eByu^pe+ui5u2<$RsgjteMBDAvE7 zk-st%m!jvEkimGt??~SmzndGTBaRugihBb&{s>RQ1_6^ObjuUgnW&LL` z^%K%GpkMS?F3)gu;hVmVmH3Q^1sXv5^T$)%{@~RoSmv265*jBA>T1N9ZRz(_*nV2< z?JXJf{E_IM7*VrtfUoEe8<8Gpf_h4w>0k9o7OiA*BCyyscVhoT9rQKLf1PTe?Y{&| zmcGlQsaMC9$b+`jkzS{bLN`1J!wqbXE%AVnPZ|wRbSelB3z7pmoLHv=2t#7ie4Y0s z1$m3D^lLAqb@jKhDI0N@eN=`eC%>328pjgQ9ww09m~yo1CJsK+svem*A2x$~nEH%9 ztKG@c7i}J+_Nj|2M}rP%c2s56$kX*Hkv4~CIX{7(BnoIRxmI`NpV8vY<8T<7Ej}+r zqGm5Fh7B!_SaLeX3H(d}+SMdI!viod=&1`H6xdGyizUSC-1tqtSZtY;g!oJ+{1Ahg z-3BT)b2(XLWtTP<)TmP{;_({85vcJM-rQl1CjZqX_GDMwY|F>nuTr(4ceiO1L1 zYjh3F-1LGEC|(5LxIVq4CzL$kJ0Fj3n|BDqn$*=-x&-~3IPvVcWQ{BwF=lRvuHBoR z7pk6~>kW0*^4&EZjiLD-wc>wOXnJ=DRKIdpM#rS~l~0R2chHSLL^UMIqsB19mW$7J z@46XSR=o%f3|43B%FjrTmDfbRlOy-J z1wVW?n@f71V=weni>SJ``=_NfsP%b|5Ld{bg^{w=D`WmkrOsjo_dx5*uHd#vOw?YwkN z9Dit(K%o4CRmELlvq2%PMu^+ied=^NfK#F1&ile^-`N9J- zC?lMcS?sCwwPDQAHR`4uOc38_<@U;m5#|~`O!@#65TD!Ds~Cn%H)^;oi8JD!Xf*t` zcrK7LrglO6IwZ5k^4^_vZiEUly0kYwN8YpiJ~j&`;afUYgstBQsNKoff9r5q`j(S5X{XyQiFp zsGJ>X5zoBr)rz=Cd?Qud{fb_=j{n-)t^;!{mnE(|>{IUzaHMpn=JtmVjOt|sxw%ND zn7ByNqM3;}{;w3%l!8nR?Z-Z@H6X&bDZ{0OJ~=*jHz=)+jBY>KaJ5Nkg8EgVn*Cir zf8r#uINBOdnSO2Vn0w#y#fR=L2rY53LC1akPrT_+M*F{E zH-viXzWo>~siF+7*b(2%O@3EaSnLx#P#-;7vbu+URHyh(h+H#c?_*DoXKfXGlSR5+ zHjU=6)iJwl5MT!1)XTSCU2dKEpWMI-EUzec3-&_2wN}F+&d^GIZMHYzF?(PYdBgvk zUyzOX0C+=NAghulX;8r1ji7ES$XfN=5seJomhIP`9By;gPDioQz@y8elsGd;uWHcM zqIu76(C#CKxbQqlyd&fJYH4>zBzAfc)!tZ@$Toc-wJ z7*Ex!2XCB32v)m<(dR#TqzdJm32_XCu`;7I#dMS+lf}W+r(x&|jFI$o+{ns>tC@4-Ezb4+7q< zpY;)h)xrs;MGRwA(tLG}bMv*?w28c!M7M$H{N%v9N%Xz+tQ&oFs z?W(h4x+@@C3qD_>o}2De+p`~G$!V2O2vpSA+swj(+&xZ-kzikC3O4_P8Fdsk`q!YZSIY)SPr>k2Ug|ebH>gyxUa0v z*9YdGscE0d=pAi>4iU)q;e}?}mqqbqu!X)txAQPmdvIwv_xxdhTYfa2uVdzvApXqP zX-H#wg9N>LLcK#Lc2GGKKQq=rbq?MTkvj}&L^4mL$7lwPbv4g(I`mjt%z`y}3IgRYi4UyY!5l7CnU(_8rP_zTvnR_d_qp7dSB)k&<&qX(P@@i;?hd$EH zS3&>7mQrKnh)tf~c#8--)(4iZ_~%khHT_1iztic*_sTuU(P zypL&BbCI-^Lze8#lutK@I^!NzF`%>iL+h8OLpY=^9Q6pSx8BsVPS5zTL}oo=TH4H!FCfd?6_ zZW~5{jxAFn1NOo@S>bERv|YZ@4wiVUkd+j4g1B^W_486g^XN*>Al_noivDlX3 z=|qHvuCuoi(HW@@FA<5?ygwS+_O*0^b!6b%rh*XSFWK$L4OWBIVL2tpcXfp~;I=py z(n|Pib6c)CWMQTxbjqK!R2vgQ@(r8i$B7LvGhY}kvO`(D%6usB-%+%3^UWkl=-mo@ zKIbsUdgyESA4EsW=loqCAJP5XUfxe^Hik9*(&W^3pFtm~vz(wT6?WPI?KTpPw&nTEm&q_J_OB(G+i@=<;NvFwZOoj>p7-HQ?b+m(-5i4nc6g-6-=5Yp!ZtJx9`IQ(YQa`3wtqosGsf9`hxC7)5OAG`*Q;_03EfFF3k`KazM-3f zQPxO|7sSiyDTNFdxr3&jURIo{GlB}cPeK!84k~?ZLn%}c#kjboh5*&65b~iH^S{0Q zs7T25?hWt3b8B{f z!eJlEY2{P{i()fh|6o7;o5`k)E)yBXB>P+yK5g4RqREhDPKdF@58_X=buDuoSztbN zRaUha=9DT+t}f4oX4Ev28!f#?sNaGg^!K;{naRP0?6l~o z(?Ks(52awNjTQPTU|&%DqCRXcEUD#x0FC*!waz0*zdP^HbJGaKGM8o_ z-P9J^!qN>X*~{fZYB{L6^&oFfSr`F9|5sA{c04F?{=67*<8FVSd}cZDG95V~mp$h{ z*_&!Rrmv6Fx*%uKtsaip6*#Kb`DwD@Dn}pp%Q8l*PvsL<`3$G0sO0cQ@pr^i)xG0zC|&`5Dz8+tdh!g*eWL>5+^mokw%ow2PGGm4 z*IGEZ!l$hCA!fijqD7ZXbTU&K&nXvf{D@{&5!%8b8bvjWL2Z!|bCIB6SQOZ5Hc%Y5a?dN%IwpJlaNW!POxUw4$=eG;HzH}1b!c<{jfntC5r_r#8}K+CWD@hXs+!;Pu; zzt4y<>XC${r-GVemf)8io&@loI(ntiS;U?Wl9W z@abn^y%CPCUZC^{&>F5JP?xZt*G6In=;9;e9Z`hVQN-vutW?AkoAnWm*<+}Mk0Kjy z&V`XrH%p`Uln!?3^GdrtvVOavofMFvdV|hx>rB-4K=$Jh+esNh#gehVc*vS>;x`z50Bts-N)e_5>Qshel&MorG93SSK+l|c6>dj_9XbZB^YMT zv{rXwL<+Pi0dKq2&|2B?06Q_w`)TJcbEB8*;+f3-h*Us|oe@W1KCH~WKOw5Gh-Z3< zT-H>aS>YE!v8deB$tzbbMnDDcJYrXBat zVu84EDeqN-MRVbU7jVo=+JiHnO*Uw=gK=cf-fPDQB_hphl` z&Fa^Un?QakF)76^) z7>;uw074vpY!yymrjgP1-cC`bT+UV#~H zPyMeC>5xUSuLL(UAvIl-_+ED>W#B>Evx)Y(7XTFVX3N7?Cf<@2X{dYv+_^0LRy`N2 z;g+L{8m-^H%GOC7QV@}%e3C(~w)++5Fz(XD_QnDhSt0GWg{`$aS5+@h3Mub=Iz4?& zpZaYlD~$Ynz2m^4Y4thA5VbBs7Br^>p48I7!qSi+A@;DR*X2nH`p6S-Z0O@N?0md!)xJW{MV>JS=hR zl4fMa`tz%R9H<82Xjabu_DFgUuZY^jls=?>V(m>wvz|#Jc-Ty6P?ihNIY26OZZasY z{`UOWEyEmvbOD40W4@q!D=;hH_FQwlm_KoHp}@4ae0u3!a6L?2`C#M(8zhyQhPp|JjDrrjSvyF>@1{%;DGZSp#a;eUXwig5_0twHGhIfB+64o_?~T7R-Ii z%Uxms!o*`UM5|VWwYzHFmD-jN7e%Nzp=j-QF8`+>_Iwgzagx|q%43A_!Y)dkdyO?U zb)5Z}sTjHQ?T#Q@D<`jhun+SMDbH36TuUGvc*WepdT zW(Tb%Np~%j3MHuT$CWaR42?1|L~Y1CKrU0ft)l0eqSB)M(uJ5sW4|_S_n4dESjd&t z2-e(N0TZc|PRf1~)DsQW#m5VR%*r*NApHN;=;mkjST5W`c;4f9*WZ}xpRkoh=Ge+o zbEMjx{1?mMxR5SB`(!h2jbcE5&IB>|x8;QK%u{-%7Cwk&Cg}m1{jk+Juc2(e^njs$ zBxX4R?ULOqAuFg^qCR$Poc{k8r#%E+M|rDzd;?*7U}OW6N`riJGRc7jM-`{ zR4xGIB94eTrwPR-bBQ{Ypj{M5qq;m9m^~zBUozPfQWv~&gIA5Uy7813Pki9#KS|x+ zNZpy2OR}7;e3KJ*EliPJ!-&y&-39PhOYyvDVe7wc%DU+jTD%7M<0I_K5M(UpkZ~l5 zVmiuk+ylS&rN=wsnI}yy2l^0nlMGUsRF69ZNOonU#uFp@xxeNs(8v5)*xprH4w!{&A_gz~gnJsl9TCp@ay;`r@*C ziTK$2v9xUdQ3|Z`s~*$~ZL?lZ>lP%&0x=p66R zoSq3=64?Q@Y}bCfM}mcF#;-|!aAy8~5)9r22krx-_B@O zV}5m9RWl?c?ijr;0#ID^0$RR|AdxQ`?)8p()&=NTbQP+(&MbZu_MM14)RauqbTcxP z*zG#{F!Mu(;&qGXc4Cwo%?h36& zt6FzSEdBS(>Flj!IjvOXjH#+J)ihxtwMRUcCWYY-zE!c;HNm^B+X?|M;IgS$&~EDp zE0S z%CN$vWehzv6$YD#30e1I(C1QtMO6!c*R|&W7eSNx)f#Hg zb}f~+PmLxfklS#Po@;KlD?vJt&UK}YK_wv~|7e@1|6+UndbJ-oI50*fF6O?U>V9R9 zHC}|-_O_We1j3P@tFQ5m9j47ndFG1M*fbY-RwVRk%_k;cIMNj3>@no{LvJG)=iwawn-4o4{WVNn+2fpex8p}9Hwqs-B@M{iX0hwkT1g&j47{vd0*#}qGwQJ?xG)~FzhRfy(pIcByK98Rre zl`x^EIlJN(S<*d5A+^zsuVq31P{k=VAT}k7ZnODJ5}e=BtnYMQENiY~)X>h~xshz$ z{k1Prmj_vUxBw8qIWwpE$;E>K&?|I<6L4oCwR_Zp85O;xu{i)b5~Yc%Y5A8udvvYq}GQ=bsRQQxC| z;D8v7xOBWIPxtP^)ko*yrTl-!4?p3@Gd`AY9BduJnppJ*QlwWSCZ&2 z6{V30d!=mw|1onXV)A;#azxBZVJpFWE5go64*;CqRs}rKaFnkR(M;dT+HvD!llNGX ztG-vI_V{_jai}+5+(RLA>j@5~v`q-vK`nC&%{{U~Vw+b(>A$#>G7(2x?7lFg&E_MM zftgcfz?O=o4aYspnTLxB--Eo?fk$CJ!wWVdGiIK=r#0;y>F&|8_}RpiF*Wsn;xKU@O$Lxnj(ru89>DpU`@5$-cE z1IvD|K!#w>*^ciq{$HOA+HMlK#VLow& zx5UXyo=|=EYooQ>wy$;CyYWksZ+ddVpJ``(N9?T}Ppl%J&>O=z^%>lYd*Ax%E)L_+ zI)7d+ytT6{XRXKJqIiv|xElafl^Xa_cD;DrfgaW*K>aNQiX2+%H0T=B3EteEW0_@@ zSJ!}--$W>FsJ7}%*E)}UTzSiY1KzPb zcvM~^l(^QNOS$W!s%Rk`apZ%HZr$t{sJqYHvd@)yP9!v{?@R_Trew&G^xyKRyp1`b z1*GYrpQ6W+FymC9Xtjct^vZn?H<1qH+$+I6;?HH!@N_O$${=Jbp>DpX{yf$L9i|Lz zXSgbE+!In2)+8N%-|Q>nDw0vRQHp>kGVAPvKR8I+zo@OPbpEyvwuHPVh9@+ylPKOc z`nuqFQ>f9ER{TiLrI-y;I!l+^GKFwU($&YGW0x1ConCkqCxoqhuMo`1O-tJ|@|#_7 z+eWndH4@&X>$dw=j60Vfx#}Z*`T!xMubB4+_yz-m(=fRlp+hH&9>eIM;^^~D@-u0=yOU^9HoyT zo5_x&WqsduyPLA#mu2b!TfZl<9s551jkIZi|LW=5>@;GPQ{TwgxAyK_G&~SY#Byj3*_u% z-IZA9adK`1-{e;}CG#9TDUF9qSTuC=!ort|2JDXpd=mDir3Xw^=7dKlMm6V6=KMe4 zHgZS7+Ue2Hiefh-ym`jpiJ7yFwA&0b`zXGqD*)btquTQqkP}C0LJO~Cc?B3%4(1gA zUi40e@gAIP!+IC*2Ie_DApwPLmYrsl6Ar87g~>y{|Ax73#x%H5+?-@ijr(ql?NTIA z-ygQjEhjZ*W>w#}>nK8n)l+wJJ=_=L&xPQecU1Q4$xrR-!i>E7t4h5l7baHUWRM;H zL&fpiL>25l!yeU-?X$0DoY>OlhEKH|M28?R`o6vcG`0X;Q8U%Pk~QJS0Wup{w>Vk` zI1cp)XUY;k{KswouL#^@`g@?Zz&u}`-{XhAJdyAIhK}pYU?3ml;E|jo*v~}ieJPV4 zwevV@UQtt)d)@TO_1cC{&j?Dsa{+SU##Dy@>5zW{>txua0x(M1;fJZnY}=A0>gO+)%%d&&yorF@+qEeaXs zOBQ!vDJ#wo5j_a>0Bq3nttW-{;jAR`1Gv$TT)LL(?&o2WBUgz{#r;6Fa67O zrz$>&b;pvCHqqVSw4}3-)X>Ry4;iJ1g<)ls{#97?a*?D`@E@C<`SG{%fr|=3om52K zVI{{>>Uw_voAE$FftiaVXNfL88W+TR(+TbMJ4EXk__NDdenl>l;@o#7`)!~77Q)FF z`Q1VJIh#sbStbEjLkvdsDN6!Ip>CMT^LvF_T0xwCd3LqeKJ7boJp}X*D0ML7vI4)v z7@Cuo)$1RJg8vniZKi8bu>PXesKH{ao$>CR4fDwun*d}1LCa5=JDkJ9(t3Swjig3g z4jn|w7(IQEc&J~_qtl6pfl7hAc^AWI_~E3s?{U*cNsnh9yvl1pf>Yc~i?yXiO#1Hs zx!bC9uc4WZ(YqV=17MuPK0Z`MyINHPf3-HZ+W{}cg^*v^jT*ll7Y#6yUJT_Ai5vvqGFF{mTNnbS+SuV3bDdUKOhjxfz#Bd z6=b3QkM8X#+Wn&r%eAi;m>+N{8Ie{A*0C62^7dfZ9C3eaE$xyajMWh;G7-Z4Raal9 zwrv*pvG2!|waNur=;nI!+UMXtlhN2R17N8tz~LQTV~uQWp!-30{fAJ{CF)>wF;r`# zZc$u{XRqqQ)rgUY@tVBzS^v)HdGWB9u;JjZkRm0Ge#sJgVNbb@$L+<^{dLbn3<=pN zGhw=v&(hr(e(u79qZcorWlx_`>8lxC*2bLS@>gq9ro{4KGj zUb!|F&=EL|99X$eEw4@ndYak}sI}X$k#|H*`uuom!JYvP#cR<>rkGczF^^DR@H}nF zO6BX;+QU?pXlM$xbl*;WAvLS(;4Uih6gL-0k37d#TZJz`2n$B=QHZ6KsUui3Stl)r z)gBRlga1TX%lL(($_4j)S$F0j?JM=e#xL#@K0?9BBgVw1k_M8MX@h>mp^{L@9d*1O zH=g0{N7+Lxqsne9;0|~lwQq&RfNw$j1zp^@$IUI{R~bY-E?aLGiHejK4QRiisiZ!? zsapY1b8!(@uoz=RtC70v6(_0%?hyPXPc6(<;Vo8EJTJeVkYz)sMl}frPKGvRQf%gp z^qN-WU&hp8AK2*jQ|L%i!~@DVjjV$SUs>{o5u*3-YlA*%BS^@YSUKFGLQ=ubcDNjm zXU=p3j@}8NY$?yFvm(0}-9e3)WNm@bdfOhJ6DE5M$XoCf#=ufHBG>7T1*ULttJqnIEC00JC4v!r`4Xge@t zM6(H4+Q};$B+gH)1YWn;FxR8hr|67Xb~-fjv|Vk)RF-fS7)lp~Xy^N+RxF6Nu~ z!hiL>-#xYV{~>Bw|J8BaJ1ly>zSWn~&=&=kf0takz@&LsI{VET2Hc)*_l8ei+G$WDEmXO8D^%W`iVlfxb zEU)0^w-^_Fv79_Dy&S7EVf|}*3u`)fgWh{nH6|muy$uzee+aK%#V=Fa8PeExcjw8` z6H3PQ{RRibg9Bi!>RSCT)3^)Jk^R?v)}r+0;C(Vq{GyMZg!J^Tfu!vy#!x7+pjN7} z_xpY-F5W2aQfBXqEDr<5+|Zs7XQttI=<@UE3_{~?@fVYMtuk}q`*AU{ML;NMb*G9nqjnE|0=f^Z9VZRX2gJG;m!|vEY&yh4Fv7k}LJ-dG^ z82m`y2@2!SkHHnG7O~^<79=;%RZM}_tp1s9-<)Fu46>_>yl1CjErq&0MN?u6dc(=p zpQir1420<`KDcpjl%BTV{CdzXX5?g6h~rt2Gk;s{+QRSo8Sgkeomf^`72PKf?Rgry zQZ%ddnJ&&aYg%4-b2-K*%pb{>2PfcHKVL|YmDqpP?Am+qs&>#^u=}P3r8=wU8ZoV^ z>zHy3`Ed-j!LuMZ!8kLsQA)VlE7={yo4isd3ABPLx}yW2W>Rb^&){aJw?x}Dnz?fKGF zHIOs@03C6Z$`%w#${Yv^norEWoF+ z!xjT777$@djIc@n=HZjSaasakN14hZ<9&I;xM}8smf|rdf1~9Xpft%$GrNH2Y$p$> z^Hrg0Z`;HbA7mGlHB-;Eg4BZA(|r?wD?c4~mLCINLO(qb`qeYIbkoPnbkD0CTrzM+ zQE54cNOL87fJRE@eYFSdIxlO=PAI6%-+*l5{gYaw6g}{Z24O3(eRSZX(a~WgkiVk8 z1abts#)FGO`rvp@a!pQ%htPLQg!nzMIY?P};W@Mndc%d6rx9r(|88bc^|+RHJBZ&+ z*TN8srCZQ_-ttETkF~SgN_sbCK%delDh29x)k!ZdTn)tnzv{g?llo2cSNxa$me*{l z??C_c`sB{`r#p63HKuEZfu$nO)VibpU98c+w!);uZJHQWx%7uY}x*&{-?vdfAVs z&TU<}VRH$}_7iM?U=z{SfU!38k$ZE<+&n5Wp)XB?W~0T1Ram8kJ4;@o{zl=bG-YAA z8gv*_*5(3|AZlDrk&gDtj)u5UF*^xI>pIA68~97&-}v-6m}iHmMqhlV(nb-W+A+`z zzy{$Z{iu-&d24xL%UsG+jW>{B*MCr@;X``d4uP77vF%Bum1n8lk2^{Y-Fxxya(`7k zf1}z?60%bFm54xI505C4sZQ+AtC-7VKiDiwge<;g57m=GmhLm-TV@U!VBRQTDDMwX z;QJScY)H@XPf(Pgk^9-?W2xo6JB6jQ6ZQwMwCA)x{&4;J`nct|8YCg+llhD*Dbpov zGc>M%^O8%!A~>^ zHq#iae`h4OP1EU5HiA0W;N@3)MK`6i<0{@-CO?mj@m`mNsVZXi_))X_O3)TU^9h{B znjG|z63#UfE~?*UO@BE#oWbLF0HmQv1;%Npr#0k-Lg9UIkWDr!*?HQ3*rhM*j3kc>p|Rtl z`w7m2-3q}aC3;*L{^7`&fQmkQ-^+WqiAB|^&$(2+U3UXU>yGvDb04 zL2K0BSq;&3p}rD`)!SXOh+$N8n`tr+KtSPt%9d30XCCY1VX`;@Rp2jwtQZ0eJW=RDvDz?or`PXc^# z%ZCDZ42oBuAnL0UW@=B=xevRp-9tN=Lb2=ep_fARS%2RO-1uL=0{Gw8$qUs}dwRp* z^WZ)}Y)lmjNPiiF%L~C{GW>q0GcX%@cHPttA%C@Nd0~yMI;bTgoi9!4AmSA?tafGX zv)y?1yr_nigC)DOFl{Q?~}-H$#h-UM)XFRMtlqOZKA@IEUCL#!YjRYVl>m43;mIG|}M z=sx`4t`Q&X*3&m-(WwUGlP|(N=ZE%WnkY%I!?iSb#v5U=2JY+m_PE~42xG3V2`E80 z9U1xD=$y)cnU1rKl0%0+A$`GsVK(h)5#zx(WjJQj{kB2jo=e-UcxJ;S=Xd66IO5P` z;kA#}kT_G^hzxgK%=fIUsHr06uRV${%p!{(W}v#hteKzr2Q-xXp+9HgK55qjG{(;l zN^k}%8BFQS1QyV%&^z0W^InlbFWq|;)6OsaruZ>sj2udo0!q}?j{YL9^N-ySs;*Iw zr>9fbesN)-6GtbI*MW@{&5v@5?OnFWSDx_(-wZ9#E_YtCfKep7O4;UYZ4DI5yf1JC z{*;m02{aw&!jm}nhrxkIj@9uthaYrAI7$hF)3bJZ#-05cmy{OV7qQ*0nU^$E&nLq=ApafLsV67t!(z1j z{5{zj-o8$^^6|c=kYIiknNSa(vK{G=ahBs=QsJ$WUQqD+CcpFEyK_XR8en2mO``W} z2Yb2L({9IijbT-G=BXKVm1{?PMj`SuonQQ-vE7$)e#V&YB$F>x(55j#Q&z}1+yXJ* zySZ0a6U}%9b`tR_cRHE<9evfrQ*qIZ;JF&>kso@x!z+Jk81*-Y9GRWQy(XDa&NDC+exC_d zP^D4*8{)niX)8oa;Jp8WuZnbeAu|Pht=7Bsf3}gNXzwHv6z%`Cnf=R<{j{mK#_3;A zf=rg9u#JSzZ0+Qjy~DMXK?AtP_I)`AFHa|J*tq)vtteO+s-1MGd4jiXBT7ZXr#w^_ zpN08ecE%gNnx>H~jHlSvaQ4Trt#0Po!F&+JnzYWE?ZUH|88+! z2Ak)dPcIHXC!ksx#S>g58|>sd?=Mz`sAB` zloS6Lx-2T?=;_woe)_f7!>PB{CE? zv1JNd5rX>Gnkz*63@TGHG@_N8if;{!ceKlF?hdj@$bF{l5pkabQT%#Q;L&+4a41T9 zS?-v?{Mu4tcUIR!iCZx&Gtcy}a~@Z_rqwO_X~0GpguvfwEB?#edVA;Z$_7y9mC%&} zg~|hwE(kn)gi`x6V%AYW72JX8ETvi4MZMSfNn0p&m=Q=<=o_E&Y_|>gZ^&3;E@y!+EfkN{o={-meWPtpClR zHuIM5dgMbdkv#s5gSfhBZVj+7o^+q|kZl+`M*2c3aeuiPG+JC9?l4=8FK%3ITAQ-Y z;@BrtpV9fw{17S_PW}{MxOuE{umsj6=lsg;NAwuMqw5YZ=gC4l3A1`jKMn+6egWQ7 z&L%1Ob+gRG_C{ig-j5dabP{@G>s%H@&#A1uzFI^@Ga&ER4{ujjqh%VW+2$fP-nJI zDJ@%abM{B<3T-%T5Pw~C42>5jPkc6f6nhnO&E6v=FeiRtR`G`B-6BoZNR2=H zTmxFJxg}ZJ#h+?Tzd+V6DJMyjbX*{4WypFDo}xp3X}i3@XUCkqIKellB8Ve@((6`6 z`kS{TC}6js;NabqY08;9@uH_UY6|^m+YJ;`L*@S z@-M@^EPBv3YLJbNE(GrIBlDUxp6AsmzB?IMZg5^~uuXP!wm8=gmyv!Fjfa?H-1v0Vg=G zAco1!CfQh=?AoA%XR-A672}`_X`IkHCAUo}EWJO1HR#tfw7dIq_c|#7(1*H?dVGPj zwQwG6Yz$Z)b-WYL9I0ikc;aZ@g!p+Cp=PJ8J!3ieeYpmEvf7W**cG+F^Qaj>!JeSN z|8W6gTUH+0wJ!%y4r43>qVhh7Jn?~?dsLcxmxlJYs#aYMG734jR%v5wLJFePrcDOXpRb`1z307r_xQVy9KE_ zx_9KmDuM_XA)53NQvte8I+J}>YHJ)KU>hMXOmUUZ*n4h;Mgqojc&qRA1MPsfYrFq) zZsGQ2jHp)WehG8J=67T~_mXgSfWmW%`8VH!pf&eMTimWNrvr&WpUv(*yn2DN5R>8} zb_-DFV}chKf$RQV65HoFXH?*os0IGgT`bi2tI`myCT#t(5yy{>xyJA#OH3T}h6tCi zFtj%_S;Yz>z4Y;S@suyWgVl65{cocdpTZ?uz+zvBX3WhBhjXwf$CPN=R0LDn9^Pa! zdR3`Zao7ZZU9#gp{?njm2j%G6!LSdq;(^{?|>oU%vD*8St_d-g~=Y#a5?zXuz&ReO0pxAOL|^Cy2b&zv)_zY zFMt?`YXNJF9Abh^ML7dC#;%GOi~mI_<$X}rrVq1&8N<4^gpn*WFyT&7)5@xSfoZY~ zG}rw=PMR>6{0z)1LB&vn$jK~}} zgBCfLUFG~+)kv@>ty8TbpBt+KV@-Ygt_&OoKrIm-K6^?5%J_AsUsgBW;-xU=f*$Vx z|27`aqr5p1)LuKT_Br_G2RtuKm0If=a@gbPCS~ZAS8G3}xvhV&QCy!f@XT(RM6C$s z@5eUHB8)?4p-5qy?hw&p@9m!oeqXN!-#|jOa0;(CrCy0!W_()>qn}NE3U~H_&7W;W z{!u8Qm0Y)a-K3hXc=2hA!7EQkvVY3nzuy^)983=j(93x_`#+esvobf)7O< zw)@)^8T1z!c3wGBH8@n9OO7p7dZ|#A(_LGU$Y;PrLnH2HNZ|b0xHCm+;!WYu0Mf9*psi@v-b8j>2jRB z7Nwn}04aqR6V3=b-MB{KYd-UTU6^?S>$pxS4Ctpo*TWtmGT1%xg zzFLkJ?!?5@(Wjr(J($5UfEW_|1s|NQ@ z>nwK#svPwy^(JiNNz$D5p)Ynnc!Ny}K%HQ7)8uEycfL3SShbLQAy@C5ifm}rSpOqM z7HN{*>pLAP$wl!it_8c zBUgL!e(RzzW>#fsd#Yf$7&sJlGDP+Oh)y=_En23bmG=OsKjI7;4i z_>RZKvYX&0fV+JA$k0|*v9c`1I;;#>6CG^STGOKe(~T)m4QTd%`JeuoQ0w@D(C)&) zDkG1l93F)A9Mfz6ySZ&3!^OM0`P(%4P6+@aVBPwjl?h@#rjCg8VHN56242>5k5p)_ z%LUBWR7_%rk-h)w(qj1!(Nyg1rdcYeKeP^EvC(D0xfbD0mo}|1C`Wbwu2_AWK z0~KD-{K1(!vX&aXyE@`@=`c|Y<0{VVRlPd>s4IeY8wD>?(Afwn<4l5_m%Wq;rEf?k zqrJ3J$tyAoKMh6~+9RZEhw~i18^O(68;&x<=k&e0mAtB@)5QW_LAovrI=xF2U~cDL z;dkE7U5z;GpI(fO>u)yzc&@7|bUkP(m2bRLbgst51o68(>JF)KO@O}AP#-rh9oTi= zCRRYRxxZ<>>_leccOE#i_!aRhuG&PmwbXE>pHPCOVB>%z-jcH) zI%t4t4NV{0Zw{Fmpno&996K)@oL|Cn2o^m0c@ezEX`SXS!GGuE7O=1!*GaB{?mTX# zjT>TLEt9gdMmKLkPLiO!Tqbds;0KOwgpIF$+xlp27ma{Gc2k(n2dj+yF<)<%6=fAq z7g@hB(#~C;vT|k66?~0&_UvW~kM;XtXPY&Cl@*$QAhbD_$SCrWE*%a|!Yx`?f!g+< zesg|E_oK-XQy`cHyYil&ANVN2F{rv@?MZ6ry6n7XwouA>{K~_&!F#T*%PS5b)JNGnRd*{KNQkEt)!IrQ zPGRgkv^BiKfBjPcjBd^On&em4^092buCWZ;d$FmGXz#`NM~&$!+$nw4`Icy<_XO<#C zOhWh*N{!F3w`5(H&sq|+Gsn#CR!Z=ym_+dGxq_#!1S)X0o~XAR)UGpjUieo82NjQA zAKPiFSR+(UgQ2E!onE0a0l*I}qq2J!!@iOFj<lHCt0yNZywMe_T;qGu}tJ z7X*mLssA<*s<8@?!-Nx$$i5Q#8d8#=RF`lOxs=t`y37F*8(kyz8*7hfQBP#Bc40*B z^%?H|jb*7Lwpl?3&~NnBbYJ;)bfKL-0I}TVSH5>3MA^$)_GmPEX_;tH6qtvib+Yx0NFo+|o})_39G^g=$qJjJu1R6L60drp5U?sPI{ ztkKGN#2#PsfqWu`5xLeb1AMXkB!0EJ!#k|30-zZKpEbC_dUWZ6cyLA?PHcbgan8tX z-*IwR!IBmIB4i31Wq-M8e4_Jib8#NI$H&>aQfvwj}+Cmxtfi{W!CCq)7E1C6gwhU@K~VJf`P4g|*+J zkGeF~h?D|;EZJ%B+B~znO>Z0H+8~26Av&hItgO&uOJ+~Z25WWrB-H$)e&vt2c0kMh!`O^880VFnru(+=?pjBn@>$l8ve4|^#sKr+B ze5tQasQGA0jqmuLxVt0nu4w>9Ex5>R!vpwE5Xl?{yYN!K{h3Rq+s!(5Usqse!%U+9l_=x9h_}RKRs;df+V7Ew~$Ngf63*B?7SM-4D-x=G)4JT?z0Up$m90qrWEQOI^C%)1pdMa~fYk|Cm<)EpZjq}dS; z;RNm76_VWF#?TM$dasrYD%Mb5uP8wkmIK!ESj=AXHvS*gmkUpa69+jTi!>7@z{RTK9>y z@_5rn=-~1-Nkp3^@AUCrR#kq$Mu72PYLKCwS?lXQ?E1N1-P@%DqgAXDR^5tVT#jHtBV&aSjiIcx}u1l37(NIgH=c*OF>jtz{nk zsVv930lRq+GGK#xb1MGI3%eT1;+No}654(7;+gmk_wloQ!3h@{USP>CGYqnp>7*6< zH>wJ$8#rI$*h~eZ6)nus>cmElKV_6ciFG06;j6O1FnCvk zGt_WPZ_Gg6ttROxN`o(4DYQQ+rM~ZggnKwcNiW+$X2C+wc{&knby^{xI4EYvwCY$v z7Mz3R#rWN5Dz&w$PZ6!Zag7y4oLWJD%wfNc&H}BXboz*ocH982UPb7q9__4B28wGh zwuc_h;52>XcDO)>TB_8QZvd?->A1h5Ki1I76oYh#7J&3v^E?q(-GC90_ z8~3m9V111BA9bqt|Ni8vMIyevVy~m?^W&=W30YemvW=}njHj6*;))NfF+p#2+G0Hv z=~S?(GirYsBRbk_!BE#9faQf+iSuj#c6G89V@G_zINZO^{@3;QHbTEEUKE)4(W8pD z-wT`W=GuZum8o;B)H+zG^E4^5nslWG<4M5MA*e4NnA?<6s>jS6YBKL5DUQlo1x)3r z_l^W_2Z)P|2`s;E`RHw;?*G8fW0GEtD-u&;z?>do9S5MUp+!kdvP|~G)1m8O3q;q& z6zntimsx(_By>Dul%*}51gEw)Lf1HunOKBGx*jiOey81_4pL1DBoXDP<3yP+#4y}} zLbbrZ&0ZBP)2)r%UwG^sWMX0~>231bP`PvYR5P(sVyFSxM42m~#?E((P{Mjyr(zN| zG}JcmYBLsK{|C1F4~V8Q!`b-pzMrZ8yOi>X&%z^=)I{v6V?E5%-_Uc!`idex8T1_W zJ#YX7+~V$x9Byb|dwBZ#t3IzGzy082N&1!j@>g-Aa+(&Ph1kVq`N08l9nE^D#QFJ7 zO~wqR<&iok-pgnj?-@*f4>uP&P9hcWovUw$!UabI%!T@@62KdL@OYRlPGV_-)d;S& zHoWyk3f$A-Ed|LNS8Mi$EH`?-lh_&PiY{kOdkR%+jIvubC&pQxNZqO{qj`SSD3 zDf1kJmPe~zX!~(>W8mR3&)`@?Z0S}~1%vxB!>b%sn!jrwc69*sk)w<6P*^Mi+sL%8 z`&mN$zVe5YcAZxSHAioPrN+8vIAPpW(|bNMeupU&1q(t|cyT4Sazb)JXgeUw0`27X zlRRfwH2!l7@ip&IsUp^03bCl$;`JzNqOYD56|#Cx+pjDmQ=a&MyT76VK}YfdpOZvn z^*fWG<7|Uzy1`Lc4(my}Q&C)87-z7VR2MQh1pN21`qM#0Rc#Zmwi|ndE7SIX=!Lq< z>4woKu-IrN%pErTG{mV*<~BpT)9irBv+dBSus!s__vQ@=czRh})OBXr zR@+ms=mibk<6@_=1cL?M{rDlvSIi|Bay$^#GRmo))*ArZLlyPja5*Kr+G*}!P*uD> z@Y8MR&L3nhKX~zO>$~wS1ab+&g$19h0b6KMK2?_p>NeGngV$VypRuK+*^ju}5q4%_ z#*C#dP^@VLEfpX((Z?7`NKsR%F9Di zs{cKC+wrseGg2~H3MHU(H~_CltqrXw+@CtWE=u{Y0{`Ox!>_;quzp&bMy% zy;uF|og5$Qav8NZG<+YB#3luajl8SRT@c}A4%Y7O|D)+Uqnb*;uYZms%nSmfsB|*w zC^m@no{SxOpMnObrkq#k6Md=U~HA+cDq?dq5Cqx87Cm_R7Wyb{F?!=2+YToaCV8I>mq0N;AA+=ANBtqzghD5);@Qe563P#L~8~%v>~k->FUUdJsAKnCeI}OY7p%-cvgd` z^jBU?hQpJj+{Ro#<8&9G^0+E?tz8W}1W&HeOhi;M(+V1e41&=J$G(3Pg3QP2Xpv8#YK1^SNzI6YUo-DDvUwjPvx}Yhb3vvUU5Yf&$wSTJ-k9*dSJW^`G3p#gD?% zMu<9#GYnNfW~dJ4g;y_H$@tDNp7f4-JAF>Yp}UQfr|BK+dvr>rH|zY`D}$=>FWNs# z7ac=8T<$JONs*~#n9?G3L+voZ&0%fnwksIpP>re@)1Tmwq(XeGY659?a)5bxcESH( zxj9v*rFZT0!26dkg2qlPe2LkG%~a}u8|+Jl(FS9EO=LZU6tXA6^Hs6Dc7lo-Y|Sht zNxiwHHYyS4m&Is>jvIJ>%e|$QslEfhbhSRI2{#)@lbUA~GS|5RPNVWtY)u>|f~brwx_ny(e;s^>w?m-IAlMEf`SH@it-;BruDz#INo zN_Ar!{p^?dUePK~xyd=;w=vs7y2&U#WJC8^GbU|$``L9t3JAdAi?_kiXvpOawqy{` z4piGqcO&ZR#;AN z0fwheYJv#Cebw`7|6Us&2v0#+4DPHBOvFO z9TB9q_u9JVZDu(e#gaxiQVK?7ksJ83^RcJs8g!eP+zIJOR%trRYBg;V%po)Fvb|g$ zUl+80*7=r)qBrxt&i;9!JEm4Tx$ok#@v-V{8(Vbjh^F8$k1;&3mvR#4&kFCPwE$3u z=7gIoKPY<-pg1g+*B(ai7}L&UxiBU1?o%|G5^)N=){FdWHgSgSUM};++pJ9&xlluY z4qo920nA*lYt`th=3_~2^vrhS_2I~`r%S^nD|amW6meN^OrM%QzP+yoPPaO868L=# zFk-V(|H$w)=70Wqq-i;2!9T5Av~AR3|2w7Ix4Sp-;0|y2_p#SNu2BL-zUSW5>c^>J z(y^=<;Y{6%28GH98#?8;;3roucxtzDp?#P?y*Mp+K{nCWIa|K-yC~7m&<5T)^>M4} zh5td*u}O6JTN?F6W2S8cdhV|lYF*$LubY|+q6W?@xC%Vx=izW8@O;vS5H&(WXQ3ZK+` z&q~Vo{EHddU6@0TU8a{d6F+PBbK6b{+X{OtIBy_ud7-cu1)}xA#16=-^1QdRABJ)_ z;gD#DlF^01}-;8)c8FO0a=Uk%TFU3+03_gw-i z9a)tAvC{Q%T-Rt4Qa`VCgOQuup#-+kXI$t!(>!?~xSzN@v-UOebel^lhI?T13wAP% z1b%Nn-nW$Z=;OEUI|fo|E}b01WaRdj)7!cJ!&5t-ZmJ6|y;?OV{Zz0$1G^gY?YEr9 zToseXlYEeUcr1={<6!g(YwuWWv&Q(mBK)Emat33CcZ~{ft7R49JK{%b)#V;w)u9JV2NOuqQh zQcID^?{P`vn$BIUpPvNp+>e%Q&-7M)GS4bVlG?V2zlwKlgXr(rXE*whsj{F?%SmVt zu6(v|&hyH($o(+KuD#2ZPetnswQgW-myjKcdvtkvNAwCAk{s5oQ2W`_@Vf`}?^0xK zC>J~BoTFVAzoq!JVWW$7wONV+*Iu-kJJ>5y?fX)oVto>~q|7uxHD2}KqP{TpgXzJO zV*i{PM4p6XwGTB%O!HC&n5DxgjC)E3>@G9>+8k&7C}rXb@-Fl?YNd(usM7EQ^-p~D zDa|&@tP0Ql&YmRXx44zWIFT=H>F*-bdKx4*`Xl<3cs`{(q)jV)^dX$;hZrAoG`R94{RY4`< zUT>}n&|<+Mv+DHh1?$dhF_RC?h0%+7lq8vW-ku7jzF!mBtrdMQ?!x1vg=ihG@fB%{ z3Rklf%HtE8ON#JuShnc(336o)-UQU0(=gPoYnF!7IpW#5wXhi`>nTVLNz&WyJ|6T< z-^4+|vid6LUw&#yy7K{-yxPH;cs7bSdmG~4=f>-cVI%MlB*^6JkATF)U>^QUV0 zAx-m-#L!^qqq2EvG$1%hS%S;Dmq*C1tNyHr1Shb?zq=#rmo8}rR;8TTcPi~_VvM1x zY-adL_YC~^%VSRKBXzvcmUhB*e3gPKhZBiAvBfownpyr~RW2%T`h4GRG(H6V2tIYj zr-cxG7*Dz3I)8zF!sy`RkBGqS+^)CJ>TFHU=oWafpO=eo8(v+zV=oF1Ic)PbB0|T+ zlmN(TYToLXivy&>)GBl5^#J9TkTIYgcsF+nf#Ye*I+3*~NxF1S*HaH?^bytK}ykYUbvhkfe zm-f8B)nk;wzB*SE{<*BFt#~@+K%6McL;nY4rG0v*S;yzqQAI-PC2gH!?p1A?u%zQ5 z(b}fKnu`Y?&3DOrk!*wSy5M}BI?ThAMo&d_S?o9;t37)XZ#d_HR*_+1-rE|&ekm=N zHooL8zJXcHwJf_JctuG*rYP*TGkS%Fi%vfOA_Db*V=6rw zK|z%=J@O|H;dk5`NPp@sZXlJo|CSYf7_cL9-qj?l47N>LubTP%%{o>`>O@}9=RUQ` zQ2>Uf-5HG*aIodatmw?uH0^eTxMhd-u$*@%NLTW6EKcV7bhXr z^p00m;%Xaowm8GC%gAQq$0HEqazL%%lyGb=mdcaBB?fdMjuwd}^aRAtt&MKVux{9x znDsUs!6k~O(l0I#`mgS|Pc}#mJ%LvJ?>EE1N`s!^@#w*@8LvWI+yUo?oj}m*Q*(d( z3G+{Z>*+_F5h($gMGixyO#hAekZWb<{MNs=Sw0Z)JLNn0u6$)|`<3*9IIq;|fuYJn zGNvku&6PG59FAiNORuFv6CrK?zZgc)BR;6!R>w3}-)P-fGL&~6yB^{( zHvg`^DWbyx4Q0(2;>&=%T)ku>?QL7$9xkHK{M+AB%bbzumzSIi0q4E&WVM{CAd>NG zRfmwPdyD_6c?L5(jp>q;RBWgoH5es4?2iLYcHoKTlVC^G+7Op~;X}5A(FWUcFMzuv zHbV!aON|X{!KrKDqXzCx*^>aE`tHj*N?0o5Zh#sYCU#0G>W7KNBYd$V-yazednj!| z6dQCU`)`8}Jz=R@;jGK${i(8VPK%>Z``!~kCsCu;t*Iu)FL*NM7Zvi@j~aU{iAyd5 z*x8G!;ceLW#cv1F3gP}vA)eYHZ^qpLob%jK*l9!LoAiah{Fp?2xw4p+SC-pOen;GK z6pj^M)G+=l5OGU=^;Mq%eR!%^u0fT|h<*d6h}p0zD)Twr{dLj+H$%=%?i@UVk;OEcvq3R~0s*7700PPplxB!E0!5 zpva8SV7Jm5<>r4MGiWW@krGNv88Zlbbb&~FqEscgB1)vaf zUjB6i7L1sxu_H|xHT!2V&mg&`t7Q=TO5<#RUCxxjMb(a^2JRZ}HZbr+!B5?Ut=-bxD$TsmyMnl&aZ`ZRm@vU}M`F$i^ojY6JK zu}V7tq-tG4L37)Iy0GQOsax!Dm?xYPi&-}JENH^ z+=`w=5xK2s5^Bm7STdIa{`U*&O^eucMmvizTOw1`bMQRqLz+0`ny=*JR{$VvEG%oJ zYl4R|8s&n3PV^553vxK%%)nLZn8S=}W7L}RZS6!l8`U5n2Q-ba+Zu0DaYKAC(mI@u zT2CbL(Ar(u)-MfdT=r^voRbFY)pW`8-6g$R=j>SaPIcZBi3nn_i+w-3EaC)iXVg$nzI{1z{7- z&>t1d1H{6+v#89N;_{zVOKz(37)4EaBv9mIde6}*v|2!8wo(#R3^}ISEgtdN2<0$l z9yKu^eNyM8LfDv=kWA6>#_?ZeuYuMON%q5j7Glks{ni^19*YJNJw0MqXf*GK-JdNR z`Vs3`TD`CuO%N9YZ;d_h&7r~EpfEGm*tx*Bt5_Y7ZV@+-P4v9HfqS@XGv~L(5XXmw z$1vvhX^CGFy#7$0a#>Xs&h4&*wmO4NuaZT7%q{RFs7sD8^B>82D-RFxQ8g|2ueT); z6tz0p=5Do``-J@I%Y0YUh3!$TIS$%tQ)2XA&9DRhk;stVuazOA&rIgyzZGCWS z=91n!-(XcvQS`i$Zy6@`@s-;_uY{j(>FfX$w>``_1o;}-iO|iJ%dr=hdv}+2hn9%z zb)B9hGQ6L}i2n8xLE*|zH6V8-CzVf36_@gf>_$GlJ#k%gvBRA z#Z#KeHYjzn@1OpV3>@E&iUN;lzhgaGUHP6!aN=eXe_|Y*xisuY!PD2C|4NX+vNR!` zZ;f3d4#TD|iA~LcV|++#KWPZc6qHybU|BxfHx<>-G!A0%TOs#Li{?kdETgOSP#4_O zDR6Y)yt3~!LBcyVGAm$*f*>dMKHHmfDs~khxyJo^n6ug<-7%BRn+Gk#?d2o#DtGqkUs|S+;~MmT#l8R7$DBiveA0L-V_cY+Z?^j~L6jq|SZV-9XF=BLl_oVa@*FfVq9@(!wsVW= zRYSfRHZ=BT)+|DZF%%Gf*Z{>N_ffyS04#j%J%{_D!615Vm@KJCu=x@_zmpR@Auj3{ zFiyV4;Y!_XO`hR<$ZuucyOmX+J~V?oRC;_h1Gh3i)$5tV^7QOR*3|R(bts|j`_d1T7b9cFV?(B0LRaMV~7Q#v(GP`h)1tJA`} zw@I&_75fHFX%u<|$xCVi27&1bV&t$#_um(Tkwgb>;YYq0pJCMeYv}PB@D)?PpTmyY zxKiyB=I*#~VCB3QtYaO&EnbS<0BFA0K#`WBBfEuU9)^(sUe5`Uo^O_Dq9xmX6R=@s zH5XPz-c#>W{w4yqYJbuUCNz0miCLYU@feisyv>kS`Aude?bJj42;KLC!~Y1a+~iI$ zQgv^8avbkJ9U{5;svE)=WZW0z4{pb)0I^@yI}3N!oDx0`VB+eSM{)N*4fp7Sz5VIR zxMu@Cr;g=$e3fn5^(})7nmk=IzCx+RcaX~RAG{Ap)%-ixD0la60_vec=l8}>)UTqu zFGbrwzjim3pVfKNnSCcb-9FCKsD#5(c>rKEm^~QU2d*5BZy-I@jy|4+mxnK;wG41Z zyo8^TD+A1VT8pFlf}R>;9(~4~5i|?#O7+)H+qjJT6Ec1n#R}qm0*1=ItP$xMG0}jc zDSZTG*%|dPXKAXUaM_(&L>MNyEzyN@3`lvz2B18o30rnH03X)$1hiZyng$=Rpg90D zL40yk0ZKH0*m>h{DJ$mHggEj(rmqC8{dHx+We+9(VCHU{k;|Up7XbBuhJI7xc1G&n zl+vIzrr}1kI$|bZ0l13eya$d(=@QBeDmC&9b<#C%VOhs{Hb(*jzuic_aFGYpz6#h8>LgaP!x*ArG%)!UJex(_6J z7i%Pd50F5|o*!6A>Hno)cp$Pz!lF3zZ7WyBV<(@gn=ka%|BwsxhWh+Qc$1IvmO+f_ z;c~50f1c#tfL6XaEvLkJ`bA?^(W9;$2=lg|E5R_kl_Z1QsTZ?Bv#I$V&*%6DLE{g? zE(?#pFvh?&!5b-Q%!1C;x%rF)elbwVGj`!xa`1S3Fxe;P8LnksdK7*T?C)o|4q!aP z7@NvBm6?Hx_VEu}ELxQFmLBWHtgJLD_>eRtM5hDc4T)#H<=E>b2c}rS&T$$l%1rb_ zz8J+}M2E9#j!0^LN|bApy(@}!+`t<6a6RP^kfJ@dC81Veri-~-+v3t0(W~gDCrH6? zls!bmk|+TXHdv&noL?X@`k*j&F&;lLj@6GCqhqAG7AWk80y$#+szXSGN1zv@P|?m$ zJj4xK_o`bl8dr(qqP{l_BZ)iNutcQXI`5C3=QomC4gE6SXZz zvO*j;_N|{N*lt69x1KL4>p#nM?u5V4(1}McT8p3L>xX>%OX{KIq?M)wp?+r*Ay*u> z9j<6K#5US=S$OqbNIhzh@@GfZl-0=t0QL3v(hqo9y|k9$$iHR0cwWf{3-V$U5^=K5 zw46K$jVVX&fSbmpQH!1050Z01-qSrpR#FBapEHf;;tG+LkUj70fES*F^JoF1Wjn9Y zkX6{;=MglNP%Em&`s=CM*j2hT*B?RCQ;?2pxs4>%9VctVQ$KT#rRj=#puxLC_C0#q zqfTmY$>}p?y8**H1@HaTfD0^G-l88U){IvMli$AgIhA^8rqWIcjSM&9%P=`=JG*H8~!+h^o$vrsmp2qawQhd;F-UkTPPG};|w#c z7ZVOnQkB5>8!vr7<{9Yjxt6;#y@6AyjXb2Fble7_MZ6n)AZxs@GaGZ~w2h|#dSyp8 zEdooa?6?MgWF2@Z4*cD9q1C15PL*|Y7Xe+B6ZeXxkq0nsM6O)Yqv&|8EotZgRugub zPlx4Hp>G2NW;^3GZu$63JB8<-mNq(Tas|FU)p&?C5-~ z2Kz)m=u|K%L8P}rBdXtZStz>l=cVn}u6T@mT~h38^^zpmYwse+*sdB=WbekX4}d$g zIxkHuMs93k$elPd0?(OZXEXz+h4)fe+`SI`Mpm$phww$tg{Pz;G@2>RYmJY@b0#sc zA5?OV7faE_7T4_SvT{2MVFlj)_CkZeTwh%V9?M!7_8qrO>GN(_%LHa@& zmfh)CngJwJj^9=dSF6fGcCXUeG1KzmnvBz>He)F&H;o>Syl;8&qx7Cc<{D(d2;`2& zh%xx(jT0*Ux8#e;Z~v*XURbE9{v~X%zPEmqecH!S;6FuM1g7}nM!psKlx70 zVJ2JNj$qwdrRWp274i86#lzhg!7E%Z&9KzJ*gz$X5G=j54)fdex!=?-(^m`l`5}!4 z?sbO$h|RC{Z(39kks25Lj_s#6E9V%3cTc3_p4V1I>HLd38(A~)kvRH5&u62!e=TpGxd5whshX(Hp#9@;x(gXsDgcroiw@l-XP9R$lv*0&vvJwTL{HPg6hv52i{=m__)aN%v}*Sal&UD|wi*V2 zH{f;R6SXfIbLRgt0#Q{Xr%lueOY7Svl`g3EeKj12u!LTSIs!-+j`Gie8jau!a%3)a zE}D7)INZPmM8PcNP~)R)I--IfHrir&n-Vpu@y0;%{1T02O28X~*NB^IH6`!L$cJU8 z`C<_|W#zb8)cw0L|GVYa@=9wyX3&{7A6xM6|18c(AFA!?bOBmQn|}Ys!meJCQ$a%u zJ6~1ZopNdo-c@J;9t_J%eu`RT+iLO(4iQvbpmk2+uKHEyW$%eDpaWAGOU=n>Eopt2 z#pwH_vq4kL4yd=I)5Ep6SBgfohA=6gxI=b_+Z+)ezN0LND`YkD~a@HOyjm!R8{s#D_d`pZ<h#xk(uFU`FPcpO zSrUi1@q>7D4GvdtAh9gbeA}4jKT1E``LE)H@RO%)R`HMnRn@(yql9{6{Wf3;IQn@s z341Ycv~K4$aWIE{vu4XbUldQ}S@wJ(=XzqGcqi&vm<_jYW4WPW046pPj#7fE_qdH; z5t1#^Apg}*c}f$D+!4%BH~>Y--ff9T4t$_F;7zw0S1q=LBt{Z>GaJMP@)x)?#4zoh z#<0!=ahkH0xRC&kETp1Ve4>ubNG`+*54Ef`Z*1VgQ!&}GR&?n(n~?B&2lJKnRcCxN zNT-s{xKJpMT2EiqA%^WT;wf{BJVc*FSGg&P>jkR;Yvy#CBxhaIFC|OSba?WMLe%%% zrdsorcFV|(k4dS!clJ$Isl$(>7sgXGX(d^^o0Vlef0?VzT?-2%gpoBHQ|=m>)E?_i z_)}9proH2-Zz$Y4`0htM$kqruVg=@&-M_!-y|wKjX==Njs`o+jK&Tr+?8_UaV;t2dx?zXR4El`wuQFRJqn{B2zRWu3s7Y7!msZenkSFl7C{n8W`#}a^M;YL1 zCI{)-?(~Q_X_WTD_?w|?`u@B{eulFqIf6&dDgu07PvvD0qoi)i=8+TO79#0Uq6(0M5B=fcZ=9JWe6i zsjp1~dHXGXH@{ZG5U38zU}IlFr20kQQ$Wr-wp-O%sjf`Xf|ZLc8RU~i{j-`E*vYm- z#S9$H;6|ceE1KMav*zA`HeUf$u}2yIVnfE9B(A6;C(_{+~RJ3 zT)Zd25#q@nRh1ht49BjhF$3p=Q|qQK;2swM=SHLcrVg)>6={ff2)m|jaLlCY*;C*{ zGQOS>RUENW7vbnhV!T>79LKu?1`Y(FinLjGFT0v8>SakNE6`bsLk2w&pC6Q|)|An! zD?2@*mkMgjj+zTv{p6fM=0)CT&{a3Er#w5*AwL z#t24+S)s#RBa{VS8$)D(3VgywebZ+PiMJL9KS6gb0myeKf6kZ;Xmnn3uI}v(Ic#QP z5hN~hAA+?yRbW$xD&`p>yzd>1-y`ay0f;<`2Vb^R_)Rv-G<|YSDGQAVEu@P(Qnc|% zyZDOHoryx+mdWIc5p5n%ZQBf(l`d$Lx9!y6^gpnhs_`O<`AABOUzz?I``eUwNnt2f zctYjcq}4g2sAI_mtHtUX+l;?fFUnoj-081~k@I>t;r(12*c{tyRkG)#{cJ^LL-8=~ zu2kCiP>1%}n8PQJfG{cAg`q!HxyiK3PzfPE-F{=4=Wi`UPari@Qtri%gHOY2Ph& zcbjG-IO&h30-$9(!HdI{M||>(A>1!?^9sM5mU2=)i?hFTw^C&`e6OMeEysA>+oDh4 zkbyWXb0nxg?8gmSeL3O<6#VD-Yyt5To2Ms%p=v-QMVomr7k~D>uBNaZjKt;+_({!n z=;D}u$jgp<8Ps`kkw&BqY`)mM6YSQ$CDd`4S{k=E{d?hiywdygQs()mt)(Y>BUcrD9402e=4qI0?3`-?6QMQEu6c)nj6Zh{Al&Hjyg)Jsau<%!U)-(VJ7m~L( zD?ej0(Xkz`-c&$oSthMU;2WyC%O~YRYu!X!U}E!-Ca{{?iXr*v?)fQ6m?HpRr9&bY zA+jpctYf{nT^XQC7K)JQ_U!KoLmU35}yR>o5FL-J>cQ?_(e;=`<->nX$t8wubR;f5aO}Jg> zR$(}P0J!msW>_GzD6FR+q|r7%r1Cdw9Ccn=o;ca&D$PqXK74XLv?4m`THjSWBMHiX zxNZHa{LcLT5@e;N3*skmT{pdQ%O|tLiLC^hKf2=fuc5i72#Xnx=GzmuOc!p&qAh+=r$jVh%N(%EH~bzSc3~H!_wuIE!Y#$240+*B`eSeDUuDF@ zHy(eS7rXqxjbNsN-mr7Qo)*YsF;GKd|4I&g1x?T2)=Ua|i?*7O0x53vEJYmg)3^+# zGL_5Nukji31Tp_=n5PPxTjB+*Zs?WwI@EjBLXMOSLkrTQ+y9X03d&-@#lW>%UF;=r z*@#$qq_T4^5ScX;``5a-4G`JS*oK%*0A2AhqiMr)s0Ul*?Fpk!Uig9pW!_;nAtHnV zKTrLfy+RCsk40>X2sTPCy-N_P*V!isT3xfMm461ljvByug0_83H>Y^HI^V$|&n3p87a~R82YixhbyN)R z3~sBkx~m(!b*1n)RY=Tg;S&Cf{6X(04?HWKA)Izxe+H(ZRo=DiC@k3wV6CRQ%G!O8 z|B?^ssvg?NJf==A^eXC00J&k1*)cT@Y=la5WP=*z1~;`B!Fx!#;J;6!;U)Oi(u$J( z*b9%H{n}v*L%l0s20~NI(>kmVYB>|v^cK3B-3W{+-Xremlumd&W8`I_yk>7H>%gy)Mf&PG|n%V2CmAF)ed=9iE)*4G@-nYhR}?KYJz|e+XXqpo!}a% zBs*g9_H=TEIfTSYYOJ!Z!(d3;_#iF zZo=@A3vvb=0%tSpjH*gyB@X4y$k}a>GH8f9Z^!0XF=EK|l}T1q|MgSL^0P{~BG8ty z;$;_?l{+RiV?*PLtFDV3$qIyYI++V^!aBrA_7gI%+~H%{g{={ zb_|$4DMk&il==7;ys-KhRHL5m(&u@jb+@4j0LFkPM!r3_N#1Ow}yC3HOPU)IP+ z^cWviPn*oFA|pfC;)736857(3IuB&OpWc&dE2jDZeLD2_v#J^STwiqLDd zbfD>;?u@GK>Cj;#z&M)JV~MZx5xow>GkaH3M2ox0Ne8D+7amU889?%0c!}AlXg{B+ zsbWI**L|a-eRV0m zm->Y%V)OgpT9aYJ{x8x|C;SzMoCHh9`XBe?f-~2vNZUL2YX8zfUp{HmGR03hO3<+b z`v)NJBgfHnbIxf6Ztii1tPyDDL{O#dT8#Q@(P1AAeD_Ul)(DCIIwT)j*@vyV5w3^C zYESp63-DpNO+*prX4*`}*n_SxXSQpaQAJy>p+mxGKzu=-z;``!^TSNWncVY|Y zf$jHM?fdhwn*psA=<>1XOJG5}+h@R7e!JuD)w*TJi*ygxwf0Pt#p!6*rbVZw$eHh& zbf~FJC`3ji6vlSsc1ES;Pi|riB^iO2#de}|e zmT=x8m|ZU}N7+!IIG|(U{7}r5vh3waOftO+=l5B}1-I=gpQbsBg@rN&k2Z-%wc)cZ4P)3tU@fk5)VjthIwhq0FC>pk}%;U_BK`;2cV z6=MvHnJ=`F-5o1uT>L+Ue@p>9EDu5#i~g|pJc)|&lf~XzmR-IYZL!=1A*)WzCm5`I zmvYbEE`L>KchaF{`Lj=3`QB_{|65v^_Q6_Y5+L^D_KFF)dZnnMeWgVvI4(hsIoPnB zsBTI>i@p^4YvJ|`?Q&qv@&bPMs`1?tTl&;aK>r_L|DleO7T>@|1HZ>sn<10gHAM!? z9#u8{v(U;S>#C&s@ba+fUKO>p8}Lz;AA1sW3pGDWC!D<^c+g7H>p4G_ZJx6Jv{H;V znLp2T8mw#Pj;*!^D2u)wYN--NhFPGl`i(>mk)CL{ZPs)D%xkr;m{hxtOHj z<{dMcQEMj+UN7tG=al66EZ}!uqDaC+br@rCJZfnpr=pq1`hCvD6JbpUfcN`HvWg`Q z-i?ldEL#+FS5*+oeOK3RiYRJV*Qf3o2v)q)KrZJzuuaFNaKd9~34+VVLe8gme`u;0FeBR8o&v(3 zk(o73PGB7+Ct&2T(K>8y!5Uhj7GU zp)n&=Ii_8HJNy(!)KYg=IQdI4d0PU7)BoQL8st^&QnJ*%}l z)guSOx3_R61RBAYkeI_sJvM#5qH!h+ESWz_=C|FGu&V1e0|#f%Bc&n?ywQr2>(Kke zU-@&yOw`SWMBdLZC19iZ*Aph3+lirFiZf2~byHt<2h$Xtp$=8Ap}g^bQ2IGA4%!bc zcpub!@#dVQ#u@TytHHFEM)i7U+#a3KfuxDC6z{@>5+st_=tM-azH2a2Ae zpR0j*D}ST#Q^%vqk_m+iCDWt_XzlkAUfw&#iD}Wlnq6!o-g_^K0j4?p3E;2L#_A74 zc1s&-V_;qj;Kw#WnJQ1;vQ)?hl$nj17D3MxVZdNc8=VXtm)s+V{aST;GYBen^ThPx z>t|xfCVSssJC$K5RU^9Fc~X8k&HWTp)}O*(JSDBqGe7y%r(zLMaVRz_8&+@djo{Sm zNIUXj)!B1M-b9IQU&w2H9hTX@J*9~_E5&2}ve@zqknxMOh4+t`c7K?^i{P#KEyM42 z=1g{8CXRNZ!Sw2f0Iid>7>gf%J%jo2^B+}@2+cWFdNJZNQeO^{t2#8)i+ankfq%MV zwCCEJiwM zvDuRxL@Ib>$F3lhWF-~?X5E)$H6pLikQgblcVtF(M&xx$kb1Lbo{`)j(WCiRB5Evr zVyQ0H>kwtOtIGRL!-Tsz3Acnb%`6-%>F%g1dbId3M6jV6+;57CCNq$u=aB@`Hu$R_ zZ`cpYPNDfuK~u&-&7C3ZY_K{W&9scqikLyhz|X<@M7Ywe(im~ihsown>cMWWbYWf? zc&gXSpUY~sYsq@4TmzzbS&!{X!X=K$7k9I^5<#n#u~FkG=E*rSM`R}Y?Z^=?cD-MB zM7T2+t^5VUfmQUB#tvoPdWcC;8W7a{>OQEwBs8G@uuX^jY}e-3d^K5WVpr$-rw=y$ zeJ)I+BA=a7LsN~8+*XlgJk+v73Vgo2z2c6 zG}09>v4(G_U4*_0t5=oK6m^nDv*D0(?q%Y`xwHu1@~oOak#RG-C@f#xwd*XXb|5}( z%F3?aM9Z%+b{#n>g* z-}~PSxjCQvOjf+sPRBh+aSC>yUIQJO_2<$bQInxV=VeK*)s$z39T4 zxVdA~;fWbK4NbtN=kKB|(Q1_`CZ>lhJ-qe<=~m`XZG^>kgCi450VAEaea_T;2f~Y% ze^Ajywe&L#w^3JXbO9*F2)NV3hhTSDW#sX9{71NRmEScnTVA=h+nY_nsVX zTq#X0DalPCpvw}-GnFu7kN~gP$}-@n4ej8$CgH&E#~~zIp7OyJOJ8-uR&1uvojggbJZD1b)G| z3vx|YME&Q%ChD?b#cgGi91~CY>V^T78iZK+Fx-KeUN$iIC(;@L zq4^p#;^r}NIH$dQj@L z^pCnprxv7Kb{&bQ9(3wXdC!q)cd7a+1!K=L-$rLztbbX6@YPgzy$4{X zw|8WvZu!K!Y=p||M??^AV*DlNdfBP36@)E?a><-+zt3gv46_>9#vu_ngkD!*EnWsV zxC3BgjCV$;AQ+h$TflCPau{soxV`pYy??;qf8y%(Eq(6*ZjW{jC{20#$wIt-yv%xR+kedl097YtPZ^XKc_~G=2)g z9ca?r>sX?+=+?R6cI#bi3vreG#r( zRdFCpwAi?9*&_M(hS@Db0i5&J&z6zP!b!%X5L;*)2kV3`Z2VR)*L?Oss9_KPkJQ0e zQC34qVGO?}aVh>}q@4pOl=4p6f}7}Rh7D9eo!F;3)qCa9-&wGoFRRQlSN*#x=b1ko zj$9O6**)GSZIuy|<`muXXP=%ZIpTi%NIUBD>I+$sp7tx{$RSya>T7`QR9z`WbB^O; zu#$vjs*7Cn7@umh>t@6TPhf`gtj( z%-wH6y+b$St>w9J%;Or(F9WX9izD}wq(C}fO?x!(WYv} z`9HnqI$tt-vQsgJZoS*NO1Ul^mDtvQ)l&9d@b;C}1+hI@38X%y%$j|Q>(6Q=(^1}x(Oj*^j{fz;ptS4lyxH4=6>F0oAN7Xq{Jn9NTTeUki zCK3loBiOfp&?eE8%@0_1D#wO7jGkMLUY0>Yk;4>$lR2Lu=ap94PUZOq?%c9~e^=!o zhxRI%DHAs}PL_GOM1-%yPGKbTH#&e(EM~n$<-)k*j2r^LYWmq#;Q3bZPL7X{7Em?$dgnPbzMUUPjnBrTOMzhI@&PRmJo@!fk-s3#8B>aOCd8l_dgbcS@Kle z176;+cJ?e2J2O1GHDN)Z&omX5{y&<&GpdQS{d-+jS)?tZ(uv9fvQk8(ldy`2N)u24 zY0^t5LIe^@SVcjk1O%ypCTWJZw6guI27~5_7nHO*6-3x}P76m}_iZ5*wZ|M;NbLA?7sv&?nm?3eYGlOZetN4J02wkoC$zjb$ z=S8fRONAUIN&}xfWv$ArxO{Du#26~9#rg4H9;$Fv=WI<@2nt4Nhi|&{QF{S6>%#pWsh{J?nQ;^^@dRX*$*%VImgL4nKRyb{0%z%Wj;-wuOYPwS<^k zJJooGt*O6j2RG0Xu#mceAV( zOp8b=zO}D(uJSzw#;;$wTNsuwe^{}^l8>seWqet{(BsyvPOkZM$FF@i>NeK6&YKoA z9=@5v%D%ewvv%%x2ZR-v~rh4tQ;=&I|s}$PChqv_-G(M6sntizVy87%N0|7gcuI z73TdF?+7;(+2jtYD&v2fC)NDIfMS@!EK?D`8C<4N(vGgR^UcT+Xb+BP66`PVu{|2v9}4@vF9xsW;kJ+`p-O`4#~C(yyZdm91EPn6zz7 zisVnu5UDu6u_xvj?adlh(Ft~Rn>+^_=bh-KD%Dx*ohVccXs;+}O>#FD0ur52=|-Rr z1lNeE-~>^tbdgWu;iIOxHkhC3&x6C{Ds)O?C(Oeil5;e=9cl7Tly})ybnEVCbI)Dl znr7?k%2Z!C9ZVQal=mcUzd%3Jqj2wkPaQHMoN=sKj4Q+0ZEu^C>ZH{asR~bAD{YMR zgrYWxW8}@~z;$nj+St8=fd;m@_G->}0sNE?eZ7r1)L?3D&!I=3^v|35;q|O3-fL|U zTytwku?*vu7kSWC7<{iPo;2VTLEHDlwugjKRrmUkP9{;b)xQ13y`&ZiR1L0tbEVDa z@YOruWjmFcqjE1|QK)~DTN^9b3DVNTZSyh5`AKfM+=qZF2u~#0&RW z$HxNfdRnE+7BqCSClX6dAn6^sGnjv=j=N;|hhak#F6;bonIRF7)(_1k>e^)SM z6=1KITYE4tzQ+x(*XE8?*<6sMFgyU8+Ry3Fw2e-;R2_0TEWp#`&r`AD{KHPVHB|h^ z=a%C^0zpwe!}lG{VlH?#VmVi?;uoW8B!HLAO5OM9i7ELeZ3WMX*Jg7B>= z$t4+|)N16*X>h_;fi_f>A0csMiTKEGvRcFx}M`BUl(H17uQ6-Y!96fmL#ZY^lKfBVdM&ib9a0Q z?YH2E3aq**;Ir=Qs{2*@ftD2@)CZZi|CBO6DX)&ZhDl3LSCBaU`+&YF;)LT6AS2Dd zZwy6+&()q%=f~-kmgre%!P@!J(JI_b_uA8n#%>ks5DsffY_8a^qKX%rRkk<~Y97Vh z0-pvkyP}5!8FmX#TrRXyc;QSN6?6w&#gZ`4)cv)34Jm{=*FJL+d}}{Uf!0nsryEeC3oKprw9XqfT_D~@5tQ_1o<2pQrut=>B9?{8J z6h=VbVP0gI+1;p7%V|KL`a7u+Xf|v~#%_G^xByyhA$ESDS zLfOZL`}+kU+q=eZo&Kg4K2^C4TogIUQ&=rh(O~8G8C$K)#{Z*o<=|iLlG~$J{Jc>k z<-f%3rsFbRBo-`R64NUH^&r}oIMypqqWsRzD^L6%7r=2_VqA zL4-ff;3%a6m%|53tQ#0VGQ_$HwUq{z#!Z)D#+wjou~T`o2D01{>00lLZS~`7;<(tj z5Sz;etFpm&FdG+8TE^Q)ztXkgSu&dEvEPrX)c4~(55<~1%J7wew{$eR{RwfTk38HSo?_$>k*LTr!i z|DiQFyqf0xggffyLc3t84i`}o`}N*)CFrSHv7V6Q`Qe|c_~P6PXtuXTKv<{Wc+P^T z(^FJ1^(mixF|GxFI!m6*$3tv?e0VTOy8N>izQf-IPt-0dFC1ycQI@!;=sCyasS zuH}czH*Vf4zu+_~2;X$mdnUR2roP!b6}O?bq9i(D1~$Zh@?bsV?JQ;KhObn18(_V^ z2OkU}_0F5&jI7=Q1C=M`$RkIiS~u!9)2k-3aXx&_+m{TcHNip}wugg@D+tL}#BF74 zTkj2cxm998@47K|{N_7A>jebO583vGOoWBNiv3A$8pFk!J_+u^&)BOXXT?OY{5 zOJLulcxdU=gbY>I(^ukom@?E5J@L89mER}#5ndg&by%6&gpsLJ2_BTJ)t}Admpb?q zyqh_rR;`ha?(0p}`=M`3m@v)pu_N0AISZz$fw!RD0C>Do-Fq7ddjjWED#s<`@@tAS zW3fEWHi|3g;rOu+!}zZ)UNCAXim@Y<;(plmSb|-2HlE8 z1nc#}jIBIJ#+VATa70QIGKDv!UiOQX*M3_=O|;eAcSi zbWdUBk-?!M_V__})9#y=A|*i(*fP%eDsOd585Bl-qVEJiHUi zt$dzEv{MWBbc@s1WJQcjo_C@nMu*hRUhYCVmMb!c^)@>0`yUX;Jj1%?rXw%LZ$tw> zN?np zZRZ-&;8_jIgFUVGV7N^Sy~1bNgg~@{2cn0yeAWa6{x0wY4X63N#t2gXd=g9w@dTL> zHS)-c4DABR+9L__(B3WQ58vTyOjmoy1zFaG0h`byG1dL1fSa0tLdSSIf^fE6dnj-m zE^W6uLbaZ5Je-^rcVvPw6D8dN6zfBa5-?P0YAnLvNKr{@L(CkoY4?g)h^NzrZGE@F zf%;_}KE(P15wTZlI_r0bit5PZxv3lEwy^o%qc}omn%p`^Dmk}vI8(R`i+V-bPYT`2 zQ?6fI0p5x9g&egMdje&Z6+(nyo%M5;^rZQ5UM%ZD+gse(%?Ww`9D%5N5k4Ln>7F3> z<5$1zwnKb7RTp3?O@+UfE-*RHS0v)m5z8BHbnya15eCsEj!Kl&+OsN%bB~_rOTwX-&`8NP}WSs_)$_qe; zT~1sRDd4#@rm2#h28medqWat3_&qMt$wSn`*)!(MInfZ&%U5}7jiWVWlHIz6dd(zx zZqy^r)~DhgnE4ughNdP{kgh+|eR+~0<;H3|e=?50w3Ev>TUweI*Q9=;kVx!u?Anj* z&F9-cHj7&pLOqr&j!WP;92!gIIo6EKw~`L~>9azJ)85k(%RofK*+CD$@i7;IznZSP zE*7lazI?P$O_C7Or1iE%i(1_1{c<%|eFYrsDKh*|OZ=9JvFAms))+4u!7_7IvCMm? zQPGgKp|M`D>3bU2%6?k47WybprEGK`QlLMgtrT!C<%;8#T+!HjQ;Eeh;%-evu7d^! zhCejg%AnflTsMbbUNv18DBn1SldZedrEkR{zvndv3Kehsos+4O#SHnN?-HV&iW1AZSz1OM+6hp)2L9Ob2XqVpm8kzkM=!FKt5#OA!f*~^JwsY3? zDef*e$liMsJEp0ck${@1?(RHpjJ|Uv^F*W)gwY zr(Z+sA~Gfb1iyRHQZ8z_ZsU~`YmJZcs&W$9**om~zKVfHb9~9rQqiQ*Y9E%raINnu z>;i&7nLDmG0k|i2Q_pgfrwUF|4XT?C-`6HADyiM~`_wdk*gLyzKwV#Gn3VpeZt6gN z!LGQaJ7PencBRFWT7JI7N>wO09(32q$F8cxP4DT2Ae0C#M|yz36$@!Ut8`F@edMt^ znzi~k;owXcv*~K0*pU1RQq8&HO2w$)*2p5~dI1&cNTD3Ng2Z`E07BbMEo?`sVscK= zH(WoFN?Z5D_I=bouKQ)^_a1_gI}ZMjF9Ul9gW?T$?(i>@fZOY{QV;u2c+l@XW7`_G zL2V~23?6ryjH($FQNUJ1x2ei6Lv7^9SjtPmmr}LEj@`h9F7eR@#Dy1MeSRwQ5N2MN zy59D@?yuEbAiyhq%a_CE6hNqwQu+^xAR)hr9hm{=6s{FPC|@Wwi!o}ifeX)et;h%xf(&Fc zag#;PQpzB^8ZtN3@}9WM*GMV>PyDy)t^F6d_gq5^uEX5RM~xeVTvbPu?j!^*DiicN^6hNrW%048 z9G3P04~y>`6hUwd1xFY?D8UN1*KD`(?Yx~isW@cKHKiVEfJCaSC+rC)m1+&xV~18bY7L%=XnAfb z1l@MsQJI)_tMuJrUp!BJoLZT@ejsovO+@JQA}y19D(?8|VEpMX93S|buxen`rMeG$ ze>9bEbb(0v~lxbT%S1XV$V+gBe83~#ZmaS z!>n5Z{s(_g&nF`{!Vj6Tx!?!rp;gU*aU=gvtZ=gd0)oGfa16e$ngpTx)C-7xQakUo z>m35WwD0GK1r`VUFQ(W4hD8ZZ}P@6Uv0koM~-D#el@jf*|c8rH2K?wMjD3a4M_-vIOvlT}z> zA;?2A6-DP?`Q0Day!T;f?Dk4YSkkQSU-afYef->gM$%*DZSr+v7~6l(j2E0dw3_Od zx977sugh{U@l@Z5w8ZtD&cRYn#^E0cZOC=N@u}yqXaS~!*7>ryMbqW{+T)Y^6UvZ3 zZymWLygjOWDWn{Hb|ml}-+pENL|Ne0!6fUI@e2>$FrQB6m-X-CHC&Us?$3&l>$bPxI#Tq-gfZJLyIm})@q?K)B?c?eM!dEoU)tk}O_!)m zD>#C?A{4brU54~E^4iym9d;5A^(hD!)J-E*_Fx669Va~4&>++U!JIzM8R4-$=ZLPI5mRsUUhRf|$edoS`iY=L*6GYl z=Em;N4I9=R8UcF=u%p+I-}R)d4!hK6i}_AQK;mnYxlTzCG>O=j__u3gDl(p{YOAC# zw;^`~x6^u1HyBI$pc>mMR&;gfjwE?Dd4DnTIRzgzy^&myeMPXBT$^I&y70(1v!o(Y z4gh(!%9tv{OkUo)8k=BEd1sT($v{;uPTWf62gVkdbojvPVBd;qh*@Txk+hz?l-2R1 z%1hXmH*zkny|paaX!TsM5di_1)12RZ8qVDz-9DjKxhc5<{7EBGPXiAB3c5sliswqf z)^z30+mJ~JQp%I?;j{fs4p;1rgtW@@wU&CKMX6^}l^&Z*d}@}sg9qY_WlS4vPXZplpw`5k0O<{bl_*u&lD+;7?J7f>u8BS()T7ek$0i(YIjSNtN7}J6OL~C1cOO(FG7o!feSmg%=+zKiXp1NcEaF9cH{RTv+_?lm13Jx! zTU^NAIxYnsAFdnqw`>GY9(>|vd@TscM-q0*`tnJqvtC>Hpw_X=;^GnE z#q@l?BdJ>v3)qG1T60Q<;Sl01yDy_VnWQZzVnpiPi$*;)77)w(>$p~e`89m|*Q2fU z)c@3aZ|u~>2-~ysltCAL-{O#x;zxsygSPL+@O)pB)jmV>Aw7cpOdi!f_G_zxuS zINc*>1XA$3iydH?-koVIPyFljBel8%*?OXXu?qh*p%^Kl1v(5*n4es7v7gCW7jT!u9Sn^ZY6ma$WOl9z}f_Z-g z#7vv2gyJz8KFn0SPl};y9ZvW@Bff=a8k6LT>&@E&>@>G}0&Xi4mh;RbW=(gZyM1x3 z^Ol&Y_v$kbneYlZPCX`{|o5dZM>+GifzGsB5k_WC?RPM&c1Z zc!+%mG}E?Zc5;>w3Ew2-Q}pr%cB1-?W^d3Pok5gM^hAui_wk*Xg0a{&A>yBH)`(#5EE|R$7j0hj!DxO%0Ju1s;w*e z&Z-Q#h8jifKiuMpjaOa2btn; z@GG~2|2%YezRhj*&(7N)h z>ztlVOXM0j2rE@gbUggY-p(=arD&q%jCD&Ln-TVAaq+M#@602w3^bnuQlCzj3CXly z&E5ST?qJ~Kc~3_e>ak?fJH0X!!r)+du|y?eA4+&blBC^%|41Fw_>t&!n9zWbE70=o z$0P(7d>K>MZ7o1j12+PtCO&NZGGsu7EJ1zOe(Sfr`CF1P5T}S~cK(PqssEWhg)IBF zbE3tkAO`^KU9j#L)MJYN=uwq^F)^TagbmuE4j#>D-B0Kux?L5f*7_DXPvXeFy7*ea zzKv$L^scR>atKM&Jw5fmFog+XE z(%h$`d828r#TYG@lRNSyjJY?^+iOChAG)_E_TdSrvg*UURU3X)lCuA z#V6-|@c?Z)UU@30Wg$wLOuR`FUKAmXQ)I@gv|b^JI*do)U!LzV`zmO5Rg7wsbAa3N zieJ`A7S^X`tY&?HIuq+7a=I1iwVvQBIG36SKDMP+ZtQm1IgUAePrhZ^ni# zT<$5{p52!5X@Dm}xgvKvsGHIiwXtJ13cAjlRO0 zEuH#Z)A!RJY9q1!MaAZw&KB4~JP${Vc#_H`5s=jjq7@bYSG%T4Qd~3 zYX5ELfK%qvq$bcQveLHyzreQ7(p;DiO1JH6t9*-Q3i(v$-k}IR*|V9>{Ac!{4oMGF z&5{;_+_iVBg{=39kwthb?ljj5GR9us@iK5TrqxP$T#4GPZcaWB$D9Rz5{0GDIMyj^J9q1+&6k}sp%&*|&=vjQdrm0^6N%N&I)|Sf zr(ZC2Vb8DKLUyguenTE;KhXB{eb0q0daB~3G_43MHFcJt66j}%1r=WUTU9Os+5mal zGwNVDQS$g(@R)Q~2*uNV^ef7toeh)L?Wf7+>bF{r<#wy*J=7w@obEYt<%IRTTc~c? zz^@CwGS?4HGpl>e`$2R(Q$3{dWca-M1;Js8%k8`~j@vNbpS5@PtDOfA#Ma!je`z~* z6%WPJjKsRbG$c2_nhmRu3xP-KL`}KDnV~IO!MRmhQQ5rx>5Xq9YC9Xfi$DJ(vezg% z4p5+spbi1hZ1i;z-#}^VlS`?X7dc3CF^yhfJU4IPy#l6*~H~#Et zVrKDY&*RU%he6NpRrC>dk(2*`W} z|DfI`(whrZz+Bq7=t?}ce?5-bKKuhC<~U^7AsiXrvPq*JW0_#ME%(?hr*2)z;96F< zu8ni&^j~m7`&&h<>gMTdPFnyz@e)p)%xz#jlHRN!Vo$wUyLne(y+eRa%+6L}Z~|ae z=X?3|z#aOqof$Y)JD>+%le#hCW;!hdzH28q%gp=YhTgSX`FWCLcefz)1{^WDta#!E z?p%6@KMl=GoqBlsfh>@r!ff6dhBQ@pRe-p`%>n~y*iq6c&J z+t6KyiN0=L?b|F;s8-HCc;C599hP{Iobz3#zQ4?l!gX&vbN*vckn<_?`QJ_%)eYNd z*T))k$yAsy`_5%kRu)}Vi*};hTQjogM2FX4AGC2ThL3q++M;}n7KbKKN1fHr#BX)8IUr}(&E^K6(D(EU1G0SK3 z@ss}ely~@yiMAmrN`G@KU?lP6MMis86jOO^ zguo>hY46x3)o1&ml>zz*>I+l{3qao#)mG!2f2uiWEK?zRy#i##dM_AgAw8l0P>%ST zykE#D;D5o7Xm|*)$k=I~mQh))9Rm?N;a`CVmuM*~XW-#uwuC?neP&Qd+|1g4RFCN6 zY*51Ha|^ZE{{7Q-0jf|y!n^wUY$1tdFroA_5ql2=5)El#?-L~C}t~s=}6c*)cbdCZxHp7(pUud(YHtOo_sem?~OA{kRZI1+=v z>QCx{N3U{emRMROf3N&O*lG$>T{8)`8?=AMaVZx6LSHQaKZnFb+HV)$qBm|w^x%&} z-)YUfe+g%tBATQ_7QaRish3V{QY%TDLczZ{44j9r-x0L zvCXWCgPbaD;lo~F%Wz*_xQ_@Mulu(k-YS)4JQ`Tt5{gW>08rBQP}^nu^9`g%`{OSm zwi<_zyH+C^d+%Nr+_6KibbEPfG5%@sx;a|=g@FumKn>>9JN>sf*95Ck57pH~r|-3y zXfM>soTQBT4*(+z_G0w)LR*?&N`;(chNuq{RW_fq=f9^fakXGtOJx`~_@IAP3-W3W zpEDKK(qy`IPM}+*>d=MhcfP+omcMtZe5&cT1$| z2{n=!zV-iCe03nuTcx}$Y9~rs6U%40`kL^covL$$_aRy%|At4duDIYoqLwo0TbB$g zGc)ug^H)ESD+knPi6<`C11-|IHAo!xUkt_+sA7lEccur4u2n0(*`w9{Z7eZ(_Ir0w z(U`~B!w?e?gGvkYZ9+B}%{)Q;6_7sOqs>v~oLxbJ-Vf0FWD0%r@vZe47xcTat+FjK zszc<%FAY{n!k0@58Um_U!&?+oCgha@q2bAUED3ChE49AOe?vmuwDm1Y$6JXwIo09V ze!_|se5|1VvcX*zX(96iUU`^31m~pv}YW$n%AU1rt_R;3AkAZ-}b9C;yYaQ4rx{5)D(oc zA`?t6viD?*>QPN?mux0{;Y(m*ey6H_@}9XE*YwC%(9m4Bs0L>OrBl8bJZGDw>xZW9 zo%w_DRoT1NZc7ZihO=6?2Bv+9?Eg)K{>ROQ{gk1xThtp>h=)5+Ej9MNMfSyFG<&RZ zQ~66$E@FePP|;gQcqmUJA86`z@0V6V-!{(>=|h%=`6D>|zR7k1pNePF$3!N~Tv*Tx z9dgcT+9M;hE%85YEplZMbo1aNifE?NLkY6@Zg=}q+8#4dFBR6m2Sra*6zmdq-O2nn zD`T=013a?N{vQ{B3>%%8)+TBuAa&Aq&f=E()Z&G*9tepbRJ1MjH4yHA`dD<&`vonL_-F$yWMU)}Aa z{44I}X+1jib^Ov$KL>yJ`8=(y!FpAuD_(2*6*`m9Tp$OG7XYW;X3VxX*YU+y%;&0a zWHvjI%;uenA>c*tCOUSDU9ywuK~4yErrq&llIeF1k^GV2lFkV_%08gS4S@QJ24(@z zy%X|3D~Is+<22=vh^r10;1I6|drAuMyOnNK@TbT)eQN?Pw~r;z^i7Sezj1n~RWh6) zY6r{9@U+wh&{_JLOfI0QC!**6=Z(@Ae4fn8JC8pM{GyGz*%n+PUb0W-)%nwe=#``K zM)?iJn;L=y`2A+Gxb;(Cz%F%9&*irYf8dcBm890+1LaEk4|85hD7ZmxyDzfm+G*K@u(B^K->F;`_+SJ&Xm*f2evGTEclqPk@T{$E{d|29ZG5MOl zuzoONP~vd@RnO(M_}ot+pjq6oNtDyZ%*L>bZVr_D5_P+EqGl|&bB|A8&0!xy)9-y# z;i-*1)iOW4fPI!)S5vj8HLtqgcbvSYKfHRM$pDIokABMj>$mgft(n*d&w2Ysjl26S zGa|<1#vQ)LhBel{iKM3eK++`Kp{hU4oZ~gr`-U|lxy7qo^U7>5P=4nF+Xv`?Rk7!* zxaSAc8%)i@cvjJ ztiXY!zzI*fZG9DGyO2r9wAzCq}i`Fe{liqkyl0G}3(*m|2gD+~f)ACwwp2Zb)8m`E zF1pg8je?Jy1a_k6$BTL$aKI~OuS0eCv366q^-$hi!UFMIQs;@kx%R@-R1>+uKAA*N z$fVmZ#beLtXM_4K&9!GF8>$O=Te<-gG3x1^+9Uva&6_Bgy)9}qat2=7shpkP zt}cJg!^J{!p{S-L&};?(X${9{+m0XP&;AQ{7RFK;Mto|)(ZE@H)tJglLlEua{&x|u zv`Z!^C^VtU?65w&XIigbzbBp)JXRMu269JlXAMsoya7h{1b2QQRDW56&a(;~9_ydG zjFqWxG&*sdd77G|nS1$#bJDKT2GYVQWmuu2iFQIg1z=4VQuKJ|VV-M#jaIvuM>le? z(%sHss)8#203(cZNiQF_#21cvKwOB(e;sPyS|E-}SH4 zep~g7U&k$dq;A$Xj5;Za->CJi#9D&JBSmCJW}JoVSN$DS@Whc)p2?ImhvDY>F7X-3 z^gv8F;w+$R`+Gyy5l`%_rNkxeQGDKHb5+%6ev-jjGj~kIQ)SdiI6P@GTY_n!1CLH^`|oCA|esp{{@mY;;dYr0^}#AzXymKl#(+5 zJ~!TgGhIOB0=q9)F6vw#Sd+Tk^-fgg+=}I5ZKtRbp!cfy&;dtWr*p+D z1Dm6nHx*H6V_Dh-20s&?@*mg~W}2?P$>N@nmbh^=SEU+I``=>F3z(WjxyGQncdsl& zoR}gK>)^Mbb6r;hSMkRZ*S~`$C2@@U#!7)LT*1-fH!;~mS`r54Rpmzp?U7~^)};?S z(wE!1CqIQNPK07&tg79HzYMa!nlH-m_C#q$ej~xG#|93g=1&(361~RljI1@-1-tob)u3Nf?d zVHTuUD(Ipb;gzm&#uXjCktMsgn*FNb^6HqU7i%)MPx5t|C&B_YCY6!2C z*w07hs(VY1R}9V44~i!>BV_s1Iia2Bqbkb~&T-HusOp7h9p#`~`f}6r&gk%&+x1TM z75bM5i26%Wy@Cf0%KdsnIq-k8d-h|Ie<&s+7;f#29;#(zP?7e-y;VwHB`9IS%Vov)NHw z$X(u=QeV*AZvQNB9ndqRKD;6EL}GMu$P;1d{j|p6(dQzsi3-lH^H!3*xgn;~m!|R2 z?03IgO_aCM_0-@xVdc@c3cWs%^@H_zy@~_|-<6pUcw8Qy z=P*Hvji7$y--*tA0Ia{?WEz+?bXK_ihE+wFO*wnyLSzc;%4{orMV0?ZR%w8 z9^R77i97;}`2|`nqBl;b;$! zy)A=kZ(^KiXpEA}Ly)@uuQj|k_a6*($*UP7eJ|f4oACuOL;py#X&VYTGEpcCk%$9}z*K7^C`1vou|4MN_VtA1@J z*1Zr&@ZYNPxM<@t6b&!6Lt0JKAC)@W3m&@|nWonRrbyy|Kd*(j$PLkTXgm`BQ4E_` zTMI&i4TAmI<*v7ayUH`w@EHf8vWurwNd_X44NJdWq!+8V!0TL8svipt;hu-0R_Wo{ z3tb4(qE2&jRPYF zTv9XdA0&f{6XhH~rvSV&)CZ)K+rrVZPCENCks$VjzVRXxhOLc;)I#+EnYjO@>jf)+D4 z2fo?AmLYI(2qzuN+k}(&PeBy67Y9U*b(^mLwdo07x>43w?gzbYm+G)|TP6a4PB? zop8oeH`}$R&AFRrp1a0>Geb%O+rMr;3wV16z9x49c|;Fy36r-URRGcuJ&~W=?+SRC zf5*yBH#F%nf<*)auQ_>}9|8YzQ98&KoRD4VSeVhd4%VRvwuI>#%;%docuvSc#3IK0 z?P=r)!ABn!y@6%N=XOM>G2EfD+tb_L@-Bcq)B%g8_|WrNV+B6zu5SvJPvF)>p^`ay z*euU;xIF`7!+EuN-RoQ~=XMJGZF9Nb_{*cDA)D_;w&tgq)Rb96f{H}cUl2*}%DNwn zp{+M#!Lf07GETGv`9mE9UZBqh^mzt~atCW2*4h*F#xx(~6G-RHwBhauzSNvugs5^6hEAG{k6qjx*KFH2kdQ^@f9GqwLSok2s^w zR;B2mlBgA(10V0)koqTc1^Tx^ULo(#&{fX~f;R=>OARTe2SO1>CYQ})T5OD~#NYua zS5g;A-4?y|RuLKeK+fJ>fBWokp>Kv%;C9Rv z1HDJCW*6Wqboe)eIVHllCXzQtz%YTFZmTw{dhl=Qne1Y1!lAs*qVQkv|($Nb|Hs(D#_xuW}DJqVOFoUaxd!ny~T$qBkobD+(gk>XRVvd@vdiG zb$Zlb0pl;VrPepk-{c#u9;_23(xte#;MlnpjuH6w~z(?SYP zE3F&1zb9I?pNfOcB;5y_{QV84YrT724WtX^D?_zo1y0B1DMvOoyq&4^Gkf22IShc_ z8j2w4DFpI5bYXyb+AV%BFE0_UKP&x!(J(vWIl*Qhu|mzmpWcs}U|r$i?^DX*CQc2h zHyNVtcr)h+1`6qz>IM9~hM2(8BC`cC5F&fjEAa zj-9{&wMnH{X*BBRptb_J()%&(vyOO8cl9_15KI-dw0CzrN4#8SXgXVr(?ojFuaQin zt6!v_syr&WEG4Yxi@X^l>C=&^yC!MYER;c;`ORrxgmCNRryma7p|#8v{)f5sen!OK zQn&{vK7e}AvRY*GVNlk8XAV3RKLB(Rw@5H7@kem75ed=MUC~}Qe}se^Gcj=Xz%h!2 zvkR1pXtV3!#z9%hsCms+BRs6Heamu(tsRiW`Zr*}&gjfHYZWh1CF#<4@%m%eh4-H$ z%_{3+G#;w|*{>aCQ_M$s+a$H*h+*)CWtp^cyh>vJ6g)sKjwIv0?6_S+X_&~}MpK&WIh(h-O*C{^ALxA811%M35tU0*7-5>Q%oEQXWFB^t5!?*SnJV=5}jzzBs zbmTBh(nxYa)6F4Cfvoy+>)`3|9FOa4kf@750p&cf-zp}gLk}yspR3>7)t2hg7kn2v z+K%~6Dqy@~5<#X^%aP`$4E$D(C0=&h%OMjC58kWvzBUTK-|9F!*x#?ze4A2xXD)PGC+5@BXG zyj~emsCRJd`HSacK{ozJFFn(_`oqK17oVX2wkqi~w(Wlv+Iq!q8W|T{G|yoj25z|`j3^&u!6O}27FRD!a;DZ zlvKg4HY2;w`x`LZgkfp-A18*oj-Z4pPmhGn=}2LTF?~D5)QVQ4=3=yXc*P;@6yfQn zr4qPJu`2HaCHY*E?Ut^-WQ(6q$5=!+ELPcFg`;`l!jV z+As4XaF}wGrP^3bv4epJE$VWO(!b$<-69pobT1*mrK zYTiu1BW$VDqd8M7Pxd`uR=t89k!F7S*ikRU(NT}?7||ZCm-vZosT#X=vz2w+uHfar z%$0#6UUPOSw=5kr$jiYsc4u0dQlVc0juYz#PNt9Z%?k=6eq>OrhZWY=@gT|jya_@HSLB8d(2*K zmb8$z=9S_J{1f-}SENS-(fw=tX#D0=r;3fQgCzu%+E>P_kwZXx#sf#6D-UO z1gYQD{H1d%FFt)rc0E~IyKK6>U}!!@rS@6R0!9Mq5?XV)F^@{|lJvLPnpNF}|1x)Y z0IQiZ3|4SjOt$T3Vp0!yGLrB1GX48q1_LWxE&Xq6MD<^d5TB;zE2M+}WO~qI=Z%!( zwnm=#X!Ly|4K7-Cb<4c2v=E|UO{`D6+_JtU-{%hoM%!DfEQAbX{|y{hKJI=-k13zO zn_DrCwnEu#2M=3cyAk?qc%a3e?pPf3q1Pu#$Y}tw&Sjp;2Kv!R&#tQ4OdtQxM^k;~ zXLf5K@eOq$StA7>de)+jrVDO>{k%hm(aAJ&jW*wxxw)0_quf$!LI$l9DwsABO#Tbr zy62Io2q~3f;`VCc?$O?$~zUc338$ZBt6WQMrp zU76-_TIIy%Tb3vkxF5os|U1p5=uq+GM^H^%8k$~b)wA5(T- zZkl_vwXy4{KdT&OB2!*(sCs8cCc~&rK2)3+yChg?%o%p{RR=`W?K|{O=vf+R+B21g z{5XAe(I0A)Uf0r6e;J*UtFUVcQDAgRCFW66PKmNGUY*BN6*GV$2q5_o=_h8y76vhy za2x{7ex)@h_H2|bNFKGnyQ0k6@K$L+9mk7$)+$xRN4J@y0bxzEEO(#G7( z{nY|`nXh;IE|J*?_4iZqba11!!!lB5mlnaAIdgJJU|1k;;dXWsKgP;o`i0V#=lP(n zy(15tF@1=;y6;lXBx~h_c7ep3uH0FyRmH7olYMT}wY!2bQe6dM4?`!S?ai|v`}9Bb zdI}q54(N)RciF8%u4PIhB+m91NmCD$eF>|ck|JBqHobdVM~QYF%J;OD5uLx#oxvF#+RK;tW_F)A zfD=siGoJ%c@ulFGmvkUrQqlE z0CwIUNG#tG*Rb*!<$83siY1g!Icn1Gf&VW;u&YuCq)Sv+(54=l7 zMg@wo#P1dFv`Fq*g(J2s_x6~Agpo4oIB_wTg&dr(wk`g;*CpG*(@yY9zOg{J7q}L& zZ7Xz2VE&)~qIT=$z0b2dUo1?oEpyIU^OItsKauS-ojzFBloX;}F^F7!U*xqsK%NwN zOYI8mSISxmJjuskN|ElBA7Rs51mB^xkDNydQlpX*3$##amLKnpfX~#7u|l)R2eK>4 z6qc86PZi)Gt2QDT-KWq7X(LjxLBp(qwk+!zL`OlF_F}emrDBfFpy3j{oZjyI*foGv zspQQ=9lME}<_l4l<)LjQhkQW8<2>o`l)mi={#o7N6>6ah<{c|`u-$@I|z97z(^SSYd zTIt=xF+r~wW?|x{WT_BK#g_$_N)rxQ2Xnp}y|#2dZ+$f#6PalT4tgODyJUta>Qz5?j8fNsfwOZySgX6d-t2*n&>u? z(N!~R`DHq0+AX)>5!f2H=-2{v0IRiK(-Qi_;wygfuj39fgi81-F(GYZM!bHP0A+|&a=TVoZq6;)IadFJb!xvUSS!B5lHnIF zmr^L}0IdDSARms*kd92Au0GR`6KTCF`F-|AUH@)9M3V!u9z;B;UrHE3bvFEXNIJw7 zE|9{*?ewE3JtK5%eYl7t;RBm0O1%L3F{$dXT5@1UoVvSlgK{2;+yUMs-6X!o{`l(h zSQgOD3w(PlG6MXGJJi}Q27jWcGABNhDg7vSX5MTxTQA{bD%)%w$*z6X*sTN@?a zdLxwOby%j}xM=pQBjno>Z1orlkvh$aIT(MAL3O25a{j*;V3G38(^BqEwmC;{npqUJ zx+x=lyK_(h?pfMgdTP<4NH8!PIAW@Dq*{^_Sm!Vnh@E)-=8mu*i_L5Q)?wG_LdXZ& zM-m{n!O@iS$IUB^t zJy#|pPPKpI(lLR+FrnaInoZ?$`^)(i)^g@5o;z1S4&ONq5YaOG!t0^I~DaB!q{7c)#Fav_rB@s z6m8N(4me+(I8M05Yp8Z8ER_|u-O(#<`{5^D&d-U~*h#NJieiAjjuz}5*qs@^hW~ij zdAdh=2$`n(fr@%j8Pfzun{vuh-VqBv@gcqSwjP9s${y53R! zV2N=$(S#YOF;)F`HI~QxuBZ;1wanDOROCPF2)pD33w_ycPR)BZg}$)pQ0Pj(%tPSH z^~WGXTp)*;3*MW>IX9S`;+ru!zUCvqFtNQM}tS7D5hK9-XJM6l(;`45~=hX*W1He9CU8SNi* ztoBVVpz?v#(pB7(gX|~umHi&)uotU>ms2pWqdPKe=VV|eBD9Md)B?k`XXQhoe0%?O zo)|04m^4SGQzHa=cBM?vzokB_eRVMY&qSHH%sCEwCg@%LXb}}=u z(z65FZ6mdWJNUp=#T~h9uv+4mB=CQ-js<1IeL60lM^X>pEBZ{!&rX~L`7g7cJwj9I zeEtV42oqW^pylq!S*PUMEd1mpsu{N^Vc?8<%Q8MWvhcVuBG}g(-3gzu<#24m@!Rf}8)F<~T}QytyO;q%qDS+vTk`w1R!CfA zlXl}CM#ymdd^bA?UV`Bk+L=i{dY7$y&1m#IU}j9!NMOuIYAdT6j&1!z%n_3B`K$PH$~!uVk(}V3_~nZ%b`;sua3P^CdC>y?)p?mkd;dmxY$Zug zY2*8FaOsDiF@edIEvZxt@9urH*oaMG>55_CYDgcHboIDpGv*e6@Abl6an}`A0hNIX zp7oIrc`jdwhIb5to_^~9eIkoukc0tte0`Ep-lyR=E$IT#gpFui4&%XbXbmbY^B;6w0yQHp(AG4)ab0b)RzAA1pg*UN46+U z4*?G=#Isaduz}PeHr&TbH!%ZvM6LisM^77Qs+Na;NjE#4W|)-|D*^Mr z4E|1T(_E(hCRaJmMyT_pbM{8BGdm z?NqY7HNa&KijZ4&KUF7gtzTX&SCYI0eg~U*wrLIGjd6VCA*PWY$T~IgTcICt26ctIR+!|AYJm00Y%e46OVVOFmwT7Y7TURkgAP4o& zoTQtQNa2y-dxDeo-u9EYWa3F(nb&yrAEdG~$Jq^d9U@O>h&>9K>Hi1BR@r64sKTI1 z<-hcPc@QygLlbOI<>)R<-6e?AqzT{UYyVEWiSdO31+(qd3H)2RH@7(szw@y$rIRKO-_rs zrl^K%yI`7B{-f+j{1x~lX|#VJe)_xkR!lvIRyU(kn5&A_>Ep)f;z9xu7<_sysEW9ksIu^(sJDI)NLm;o-2 z2QZ>r8m6IF22#@IG2>XRhhW&wT)SZPdie1u;$&p~y50y|ANpkXYv^WX(7N8MnClSc zlM@rmeoci^@gj9kF%6SsjOx+ATYrsM5vOW7+A445Vhfc|8k@uwSSy_{z# z{JPExbp_E_i2*_sX+@eE-{b~fo5sF#*~`$pR*3cD9_+Gs-BWn-=ai4qf_*TsxPAz0 zjH`JVuI}osFR&MM%&aDt�>#h1$GTE(q!!JqP$Jg z5ZX0t+h?C$_#LC!(hHXpDKeP6SoQg^2l^9G=%ngAsh$}EL6kcRkXGJjATv5 zO;EV!OTYTkEb_!m`2HiDrPHa-5;8@auKu4O3KT9Xd0=IMQHF4j$mQ-OuJQDQzq)?> zg|h;BHiI1l%#6}|Oqw^!lB(h;?9IOO;X>I5*Q@UYU-t3T+n&vMs%AF&4B$M+CjH(X z+3~aASN{tC_sbEFyvB_xnxFYet>jON1WLU&-)%hV^#Kb(1?oP+XrXcyde&QoN%|Ef z6!vPLr|>h<2g@mtF`X!hPLmAvd)c;+($wZlI8}ao^p&%pz!kF=7k*m407MQjEdOsZ z18m`{GiO<4V5Riy!8|8c75XZEU^>tWl@dyFd zDndUGAf+?>ZTdaffoHR zqAALk38L}ciQYU?qxzh8DOzeO>}H6R#aPWCccT%bRx2dji!mtV>`mFGkvpuADL5DM zJ?oM88@?_l+$>Ls1S-$fuF5u*vhD_n{-3j3-e5WTOYI1!r9MTSMMA!NJI|Xh@bB=R z#stN5E4IG9?hV|iK4Ge+{x!5~DlhHIQO9dZQ|vn1Brr4kwBqzXS>?3bBYEc=SVjC@Fp zf-FE(J7#00^M zxzqB>N&-Q5xG(C$9QlvB{{3`G_nb!cZ{7UXx26QGY#R}IF8i+Q0g#>Z;39N>apgJ9 zlv?)o6E_Jb4t5RHQ&inacFp2Z%>p<5ocn=D)7$mcC}J1JXP_fW(|>vSE5qWhu++?h zuqn1lrQ0^!r)4U5O(n2}2kj}B%l~GwUhk}pE9%lznG^z$%C-@A3p?uzj|g)9N&cNy zxY{am1wA*h01t=SZ z{U4^XP-dsgg|85?s84{R8)(L}4mRWK*%Uf-Z<9hkm{q4T%4BW`Kfm>$o1(K|j_tZu zYfmGzNnN66m)vMa6lFz+mAy9%ZF-lnAITJGt&B4(yF?Md=9k>g8z^B*|#Vp@9rNym06hW_$xliHqq#yci(`}#^5>KF1 za@8$N1ES(~MY;1}JQ8W_DAa@ZOaZ%ex0p5snE+JRPkBa)Mypd@t(sVa_lil6nh*a% zdVyC`n)t!7F#qc}{A02lBvX&FwKX2hefIVa$82DIp9*K?h{8Lu+0QyN?))kQmJ{07 z`SYX7=X`;4cZa6U_7pAv)+PYB$&x|=pI;p7m3F_GN(EiTxO_E#8p1sOB=5X{{Yh33 z^Lu>L-*y0TIkpF0=DN^e=8afyIGMu5tdYXy?uV1jHHp*_mRJyX)QCtqm-3ov;z6P{ zl=Z}+aG4L4r^T{f3Gs2Q`>n?|Y4%FB1J-Z%Pdcij;cNI&q`>XodV9(w|pOOJ+G_K1#s?Bf7Te)T45&KGtGOFCm2QE^gPTo z{Kp|IEX`0C9kIG>H+k@_)KYq1Cp;}ECzgGK96l!Y7?YQp$~r8&uaZFk3$&FhQHJJ9 zvpHVySOZd)xdU z1I?xD#vG<@b4Xg}3QcCRi>bdgn{NovNIg<1k^1*ozbe?L5^ADw65tm&VYEYk8{SDO zY1rOr(^tEKm&()o(GrAFvzl=Xj{)O*I1fcRmd}^7ww~!_g*~A$Wvh&Sp1ZUqcJ2to zi^wA=)GFkqd-V12RW*+4c{H{T3BWy`2et}e{BzU8Y5I^^gNMUm(2X3_twd$<>G@8LD8a8i9ST3F<$1VA|oOPUAvnL}G7&}#I&6H`J&@ku&UH*H|$`y-U9#{Mt9K+y?@Q#i+o zama0rtDFyIf6PQ(4x)$o!l&V!FfK+=a(VT{vYG^mUQDCQD7ZaELKebU0tQ8BZ&wD> z-;xW?LuxXgYkqPy$)Rx&k3vhgxzLAn{i)(bv2fr{;>O4?H&4X^GZ9bw@b5u#U}&#MkwC4r zgHzkQuo~Pz>HX|tnDq4G_8&E9$83S5aiY8RX>Y;A!r`5rK zNw;udP*@BQ;fTQDKiP1(DvwCT&-;WZQ)CoPo91m2Z5{!)JhQ)ER%Oy$br__bf1hJy#}SClkx8H$ZGNVzN!)|3;-DCvJh|opRUsG zgH*41C@Zfm|Nm${eO~j4tf9WSDXN2Cy5Sw^Lka%+YOC_6_nE9y#8CRkX|br#0Q~`k zz*LA^o+WtiGFC7UD>zIt3Y$|PD_c32LFR($B*z8sFwbi&<2-D98au)s5m4dBKqXof z$^XE9zlCc91bT*hAX$2LZkroXJlRw8jFwjoR!9>EE#CPUWIFsYn(j)wT4=?M$fZ za8qDCfSd2_pS94kR{Q>shD~!}C-J=F9DKZCGFSR-e(x3hYd!Z-(z=>|im({A@87jS zkSdQ>-TU;^QIaNpQkvnBK>o`ksg?QA5}!;du=&h>EYQe9O`56--OC&l4E&r4tbNwv z%{eabegL3wpj&ZCbTJ= zP_)X=y`)?Sa_C(yCk^oWj6t2@{KBT!Wvsv{-PM4a4VLZ7xA-Wa5uFGF#;g8EaE5a9 z(QYwbY|vsK9hB@@*A{Lo)$ZP2<=3F;m?|rg{sxF$xlXI`Sw-Hi<&NGu%T~bcc$FXQ zXVYXO2BwkMbDbu=?^Os=xer{y> zvj!T!L*C14r1e94pmC7AuTK}mvC#@mW9^8!dBV%V;Tf7;*RXlZvew}#ER~gc?K!85 zS`kMuH+Tz~BL2I+o6t|a%<2`awx1SgA)`R1K|pMyfiyc#=UVg1J?fH3Pw3VGtIAl< zNeT;j1oRaa5Qvb!IiNE9LY0fCJD)G(qnb}!yJqh0j1^7Z&H_qL-6qgUa- zyf!DcK>`Aub%))p^5IXFg#outg6*W3d1Q;-R3VzNQV?whZHHJ=`Iuk7Eyrk8D4~J> z_K2y{blGPO+F_^@fpX!0q1AwcH;=jF{Y35hn<2NU=Ml(wRd<$2$j66EYT?XK|wZ)&7WIC!wyL($gxI%NPd|gG+_*y%m>T4 zFk`_6ybZ(C^1XjrND%#Xr+cCAx3@56UA)I`8Y+PO9Mf_q=x}dhTz)nzAfOW_nRW@2 zH{^jod?s%wdHXPSdSI8OBsE!l%MJmnz)$3j^Z@PC<*LI=Yx88>OG39lkti*}c5Q*O z@qJ7XLhF4Dm0uI;oT?#NzZY!S_F)aZj<;`!C`XAS+g~qJ=QZI2X@N!q4g2<$t4tFg zD@XdXuz>kSU&j124pY=}HlyL;dS;>Qt<0_QU%~lYDWce>H&`zO%RVEcVLXhpoQMdt zd9D`PU`YK24Jb1}^cPsd?;~meZzs*&qbM(PTa(O7)5ZY!ft~J*9Gjk!isUj= z_}91@-W89VdL24p@8VVS0T-36cg9PJFsjhc<>r!Z-XtXqY{XgQolO;q<)XjaMQptI z+AIB~Fz%A@Iq`J?4JY`j*-Qe_#v>mkOS3H7WnA;!kf_sZzPmlj;9+lDj*`$woi@M( z$8VB3_UB#Z4d(2DxxX<#w<%iTfkztyW7^U)DxTWgl%%-A*D%7kk&=kF{h_w>1N6|B zYvBDJ@sI;m^f+NVIE_G$bG0&Kpej;j7n0mO2@|q2JyEC9o&wQvW(bC;*gs&It>?j9 zKTY6{koyh+E{5*GwbpfUmw0NQDak?*(@~(lAMk;{gpvN7Bxv73$=4U>K`(iJ}$jW<$>~P6K z>bQ(KONyt2CS%C~Z+W#W0~F^(1X}+I$J-dcTQxiNKaEi?0#f=|```4S z7zm}~hKF8uFBmf>_c(uP<+3~7^K$SxDGusO@i^?eB4Yl@Yjx^Wn(*gXrcoJI#OX?c zq&_~iacFbHmiUud=6^JkSUBdFPk68eCUZLP33k@ zp0}0TX1QP;4E1GpfZIqLrcVgU7Fgrj!ftX=>!=^TJLil5+se`zBQdp79P5pRoc)YZ zu1B7OSI@yr7=JJ0xcQpFxR85ovu}V>6Rr64;)!L~E4$N$w_cEjhU?xo@A~rOM!uvI z-?ogdz1MUykk4}K`l5Kdp8qS@M?-{j$-Wxb_EZU;&zZ#K60`O!9$(VOl$5^HPXDIF zGKoI=zvPOS!hpbs0q*96RQ12AP6&kXHS6}^C=~PYFFIv=_j&7zW}M4PgKHrCXOndTr1dmwm(Wv73HiFN^8F@Whmts&xO;w5 z;FwIYM%=YO!!}bww_C<>OsBN^3$X2^tOZobTKn;IvoxjOaJGTA`Bq`>Z^$T=;(sW0+2ua(9APy2slCdvPO2+^+v$r=>7ahSs+QB-9wTH# zStK!16`AyA|6h)iifKX5TFzfSlk8k$2Yh+oihxU3>pSNy^ zxUFz1T{_|F$Q9Dgbn?FNy_$o$Wqo;uTe@uNL>|hK?O+r2x4~t>5uy{R;doCTyR`47 zsi|?-dkxBdG_K_O2v;Gnt!a(#{m29V1%F_Gn8b<>NCwWaYytUE&+Q6!mt(fOdQSf2 z4A_4ic>mJ2h+Jivpv=6s#aV}JjZ^fdW#qQbn9j^QYqaVenhiAIid=R`1px~r-sb7W zV@yLA59Wz#Gzzaa{h;_EOZJik&eCvUX){UVwL;ppF>zmP4-_Z9;L`hIU5+jvSL8_6<}6TeeQqmd^e~WfUd`ty)IN zEYL)QhNJU1aeTunIev=hqwa*6)j6JK7M=)y(8j58F@)xx7E*pdZD~4hJlC zLuX_Y#U(87s2Axx(fs?}OHb4r*c9otTN$NbMQ3|fi`7Mk4f>74@~Qz=!aGTQj)}`-5zEpxC}QE~?(3-{@~cF@?n=iP zyW7y7Tqj+RHy4M^Mr>b+J_Nqo|j30vaecXX!hT+}0EKEL@a z`?ft$y8ZXa3Q1QXJ`(91azcRhMW-4K><}m_MZK+O5e>gjakp@vrrP~^hdB<1EA2{k zlyHq}WIfALkRWo+6_*7s1T<%buwhY@f0q1CZnCiWO$2gouz1k>+5J}lHZzPp^P8r3 zhzA36%x^8{RgykzbCbGC0O{K`&jf~b#m*Aj>8q9^E^9I7+n?r@=_;S#=ToI%x;{Kv z1)nct?x#QD>^->l{c}_OJg{>1F&qmV&0b7$T652ab=DN}9jvhNAL4E&?EZFxJ<-ERqlQ`&@ zSeP<`D|+OWM$wm8yT2wp!QNu2pe|(lc&7UH4SzX`Y4a+7ZI&7qv}hiNNOulRe#Q6Y zZ@6804Hn3~^&K2boLpZRnCGSrI9-u?0g&)+0UX`=bT~P^z5A|iHS8}-Or%B0O(2%-3LAc zM^K;mA(5;^6F}wjfLeiXDh!&{@!l_&k=E|eJ=tT8UJ?6wk?c2u(5kP^wfLHYN2>QM zoTXQM#*SQXq(#Ive6ieAjY9@UhaZ2WHH<}g#1CpUC{F#16X22zWn$Vt$F;v$Ny<4V z=`8M^$uuZtTKk45U#2X`N0K%wV)zIs+`I{T$3YAJhR%nzMCm1tBgRmTTVBf`K)EL@ z<0j>T`nuUJ(_-;2k*yuxI|xZ9TT6TceqyOzrNS$$4cDl%ANdbD!ic9*JMVa|nYdt% zmW!1F5P8R5504;d<+9NEhk90ry+C^vnCEM(lNiKQ5J-I4$gIqUho51C{877-uSWhN z-}aL?5wb4?OO+r`M|0rbv@qMHOogIurN5k4+tkwzw+^SazHM~@bv^#bkvzg@j-j++ z_A~Z-Be@S_eV{*W&r$}nX|a!TNr?a2m~T)Jy;g z)7Ulh%JA*`Adk4^rKzxqkrwF1M&I2RqW|ZmOUjj`>~+OY;a$2z-7GKs*B$*GX3rCp&H?XXioU;wMhAb zytwmiT*EbJ_D_O9Lr*)A)j{9p5FvWRm#Q2vn>+_tZ08cgRrDb9CftdY!ZmbKl($YQ zZo5tzQ}3gznaIAmT)%$FV+QZmP>DK`0j|kpA$}w~3*CjOnB5T?O;AL-|altxQie@`&}g z>$O$5*FY&u-4m)b5QH;0dWBWe@EY+ix%K?*tfeBp2`JZTv-@YOgh`YM z9TsCrBXdO%V%TiOYQsWx$|JVTuwmnt;TUh&!_-!8Npq&K*zS9@+RSUuLeVA}x~K!j79P1S z!NuqNkYN81Mq`kjk}p+rxP^T!WPJ4R?c!vSDIg8eecLPAz4z!8v17h1Et~qOw}*+< zyqZ2ZR<1P3imO~=yZ5*@i<(TQN2n&hYNrBTXRXXQj1Em;D;TPKJ)*J2=fzz~;;U690Kt=;?h13N~MyEo`hi9Ng*(;i(Op zDjp*yXSdsyy&`kNj4uDc`o*qirzVL@VzaQmrwCY7uBK` zFE5dDz#}wu{GX7LH&gVTT;H`EFrE||{>#;@%xc>fZ)FA>DPL+mq|YdISAn%F7X=G! ztBM=mSsFwb2&Qx(`UO9FEzTa@6Ii;HP}@cCQ3tsF)lpe(x={TjZKPxFf)T2~!G3Mw zCTc&R&E2pxD#0k{9(c+HbtPbCz+yg6>4+Q~;B!^wRnR}e>WmgchVvu;HExvfHusYg zt68gCE4O?0`!{A&eY z^4kxMtVKx$$_H)bp5zL)_rhEPhXU+j z3H$q|7PP>qimP{OpkAJzloz{?aM~fK^GJ6h#M4~I6n!B(Ah#V&1XA1IS)$cDXvokq z0i~R8^QTq?-esop+{ZQVlBQNSn$Kh~`+9{Who@L*mB(cw^tqfFjbWm8j=0nCKr)jz6 z_VM5|hU5-iII*2=+Vtbe49Y%G@J_|Djx#-kn+yI+U|ISz%&;h)S$3$s+x`paCyOsc z-r9~Jw`X`CyWp9qdq}F8-Dl%$mh$-?sV4 zyU}}q%Visjba}g6=iBZLYqE{D;^?1S!BjaCjxy`D#y((HzjXOvR{i<{Q!5+?lxXBZ zzr&~dRiv7E2Pc+XnO@-w)8^S%L;qK-jnGW`O?FMxz?)E!;11Ckj)L`@#lIBkFh#?l!Ducv{hOYV0;R?u&{xtQuDZj&ZL4Gzt3k4=9uA zA7EP_F40C|2>iyr;uSp`&W=m$br|sS@9r^wo|vkbx(%^&p(?5YBLFmW?+`8QbR*)$ zT{&z*@s%x`|MYB?J`9U@)spK@+fmLT9Jg5(e4n5}3;<1f1Wza?uYJJ)m1lfxrpcnO zzQ*t670*ABkO1{pe=q}W`HDrMCCnv{EvaGh+rwl-%8RzM1hpOCqeiDO=)qO1tVR=x z`azv4VG>O2N_IcCk*3Ev45rOHdEz!$8}WC8t`-?QK#Ra=asIu2ignUXN`OR1XF^=h z1gql9>Asa8pnfuAGm z@@q8H$Y^1Y+l!CQ?I~J~D_LA?H^5;<+tf`Y{eI9AJ*WoDQb zMp_vyU}MhS!sDT($`?~P{K9;w#~DTlnQyRMjG3=k8W8gFiR=8QJTk41;H)^q)gY|w zy3BQvGO#+FUh~ES2jKLuY>=qCy`$+5cz3Kmxi~k+AN$_9JbMFh7&tnnfc&{MU~E0- zLOMS(Y`!76>jwyW+WHYdC^dQ$)7~-jro<;x?bN@o>A1ByWcgPquOe@wUz;16NgQL7 zW-16DMFL(BK6>)m`6?|{5>ZtxYIO0Y`VY-ERa+|l1C-=j^JVi!eRXkm>BBtMH~2QD z@F95cscvK7v96kGnzOPst(~LH-v-)x`onYnr0LP-Y&!od!s?U^hSzc-p#G81yhw=( zXK&L|F*!e0ibH~gUHB#G9Xj@R1^5gp*cd#OvCy!)c(wUD7gCb=(!cC)E+~ORL#QZo z&q*h@z7+hRYmg+&G8sefh$cUd{Vg}5DEwg^=*?cLPVt%f@Z7lg@phlw@FjI-fCU$v zo+zjdNBfs5Y7A%`43HiTfRDu*=|pG8ML**Xz`cb5g>sPIampwc`S*MyC8#5vdmAe_ z8D;F=qYc`p*RKIk7V+Y zVsV67#1H<*_BT`rGPEkic-J4adx>LaTPpJwGJIUMkY#%PTB0rdQ=RiX>EnmlCZvlc z+N&zxSw~TnnDuGLW9A{B`A)LHyxpi=2;pfps| zJ^(nV7nowUdr0!V3t2H2!OkY``q=56)ZxwMA71?*Is%>G8u2DF{Kk=T$^oh!;y5!< zYbA3H+=8ifsX$;Cn0buDEVPX`G@&;^Z1R9fCXFpyu^#&(c%8_fp;JJUPnkV8M}be@ zaIMdPq1x9bx(jQYSX?&#GAw!P_pC&ELfbtBTj1*tc3{Q<94AXrlyfKOVwPj!PjA=Y zlX6jcuT>baS&+g--9{(OcGDMlvXg^t_R$`Ul-T#H4P`HI$6*SZD%5jKt?d;KBmoeuS27FdQv%=Z zWHk2;pqfiLCV^h%29VxcVUbM7ZFSQkO=ftiumN+Ve84 z5oUV`oELS_b!mcPA^bgjr}A)3#x0|8@c11Ym`t$fYQx{y6EJzXRr=ou{WM$`>!0&# zCbE8|I5;f|Ht!QyyopESN#$?TyEWDOXE(eOwIJ(zyFuYQ>HZUBbgG^Agl02mRoA2!F_&7 z-nNnKyCp-{;s_3UV2V=ouEWGc)sJo8itifEtpHt{E^RzV`KaIi$U91CF+r zXR+?;4zrw*`YGQYsRq}K_Y2lC_-s&~GI;}T)1;O)k8@tNfNU^83Yfr*DY5zb^VNR^ z?{j9e9Gcj32~$xU!(;V5 z9}?Rh%uTmFR*aww?!!K*2E9ldQoA!Rp)9Om6G*Jt?I|(rC#NICt@S1Q91$l4C5ePeIE?UY@pH!_}u!b+al$G+Ba@RXLI4IzB zA*yM_@1MZqMFH)g@@{~AdAJPy4#{~J+E#?RcoJFdy{Qg5FvaIuf)Chs4WnW@C%qI} zt(1NynEnpW;x+?TWx$lzLB?$&P+^j=>lT2ZoOo7kBdBC1SaJcY$$7$9f0OL{Z)N8t z1?mCPzSkX9o08@~Y^>Z2?9N)%`i}5Mly0azEF=*)zN-8(-WrbK2P9`fMGX_EuH=2zU?@PP~kW@uJYV1C?OBx=YSLbN>#lrErge8&127ASNb^W^h zZ2_eAlxN3k~oZ;Z=%)XN&pt!~Ro+~us6zw86k{9J#|$Wi&naVJq% z(e=0pH2%hNhW@Q52krk76&LIhmd4^s^ous&@6Yg9h+EU`JDDDa`NrTqq1U25#HlR0 zJ`X(YK$dR*rARFTq7qo5+Ef$QrSFQ<_LaJ%HnSS7&l)=Df3x!CDIu(?gH0mj-iA>@ z(03T>Khg&YUoz$3dns1a{*}Kt(Tuas&k&0&NMu;&Y{TYn#Jn+fmA+dU!u6-15%BdDn3pTLax8Wwrbs{cz}{p z%$%8KrVZ!_q<>FSi&tfTj|kKnEbF~Z(Mq7F)N~xp>7l3Q3VJGs@lCvpLObRg z;Y*(s?(XjaFQSy!rU&kKp+O=;P0YFC0hOX$mUvjIQ5k!pq@%xcjsIpP%T0w6k=-w5 z_sal&?mFSiQ2<^Fb%>td2;7xY3vkjGIR1)~IR5hJ7sB?`*KO919JH2vY}h9PP=5eb z4SmJ1OP<)J*s<_UIS(>xOlcnGWd=c3f6NTKE`EbZPc~_)H*(eqs(e{dyk9Bn{YMhB zMrBr$lGCAShYjzkt-}K=KHSwnO8t(^1X9m;uHW9d8AtY)dTr-!AXV();A??upFp;f zqs`Y>r=WU1wkPp?955z!7MH1(paZSIgz)c$liB#uh8d~jl$yTvtY_iB_A_#VXqSVQ ze_e&vHQLMpU)cA8aXYDIqus1z?ZKACfo~1ai57iD#^K5_2 z_*$rW<74e#SBXqn;jIjfKyHr#;$KxhztSHX0bO0Sk>O>)c$@!2(|1KR zm9>ArGmbD00xBa#AQ5puhbFxzqo|00sEBkTL_nm5&`D8Iij;szkrt7vl+Zf?1QL4a zp|?OHgdRdk2z>cpd>4DIv(C9VYn}C+y`S>OZ9CXG(f1t^E;F(c7UP;LJQ?ROw;v72Qrqeh43*8M?yat8K=z`vY6O%4M>>E)(s0%p z8)*sra}xSdjlJKsqOrRYDPwOCPXWQEzk?~*>AP{QeT)|pJtO_P=hrh6PF(x0Txd)K zXPrIf(~pNr+DnRQCUq6*3A!f|&iQX2dD@(ORAUDkrl`&5@RHKW0LCTWC-ablF|Yl zBBsr>twBj_4cuu=OVN{yD2E(haUWbq%O?;mXe$fcGnS&KBptQ`*{pWOJRtY!tBfKZ zJZG}QX1+FNFWoQpY&DLX$L!&Yq8wii{)S=wzTPoF!u09?P?}kow`_!PGVKY?|5I8{ zA|;$zZmsj{pHOIpO!;?=N!5~wdj%k1X!CCIEkmz++EB$I-k2V3+5IpI>(OnZUc$WI9Wn!>T!%UZMt`nj2vNOyD3t>W$jmBTM~XYz+` z27mw^-lh$DWe4&+^?QeB_8)9LNuj@4#8O};Zu^ACjLJnuo|RmLC7$p$^ttTr+bWHo zNn#l23#H+^JjPjh-g3Uf9868`thKuzGTZn~8a_X&GgYq_pi(e#c1BFKyBvY#Esn7T zR4!>@5;6T(L^goYMRqsnJmiup1yMQRe;p=npdM*M(0A23gUD$Tnfb`IBk@n0Co?_R6o25t5J1%!dLa52YgHUSR!QL<%nYxUA0x7*4w75OrUXF2*27^ zyf_YN0cbk-T*Di47wlaXmRqu6ZswC|r&%7Tx(4@1xbA*#3~ps$OalI4DLPK12mpPUaxA39yImz1;$vtymv0L?z} zmOI=$Uw194zq~r~k>U`hk^@Mqs{mZr2N-5oZGizhdQ7vw>wN~<(tJXih)$T_T1 zvoHH+!s*m;;}c6dYvq&UtIR$`VeQb6Oy38I8Pqsuaie$tW2~Xc!>}-LNSe~bH92-% z1mfovff%}OaL9ka)It4=PBz8gtYRG3!_#IAMax`%rHmD{5`Bm0Q&Xbrk3%!jr(|>& z-^sl?*B?3H^+_HAla+4U2;MYzFUa8Bp4t-vIAG2|3Zqv3(5GBBVhOU`yI2)wM-V>_ zZWVhYv$}Yz7dowB+GUY0^ZqG2-E1w0D+cR3CR61HfKK~dZSor%`lEd@H$a2H>WpAM zE-Sf)kM5nYC1=LhS2ynA27+T7ojKpyD?H&HW-Kvq@7TTqaQ8)1$0Pa$==azmDUGr! z&#Vi}gmzzA--eFj&q`%`yU|&yB-<`Rf>@G32?r5{BS3w%uN0@W1Z>AM|D=m?ocN0c zYP6c9yqBIO?&bAgJKammYc@+c8WGMIqUlUaq^j=x=)TMl=x)lFtf-?aPHG+SReW8{ zS%lu~`i)e1x?N+rGN)g#jBm7WOd0;Q*~r$5te~4 z<3i~b>RWDBaJ79=LWQZn$cnmz(^;mf8z88kJa~Wh+OtbLid^(j5NA-gVy=IsNC}{fcf4 zFT#rLgS2+lf|9fxR_ldimw(vtlVVg4sTpT#`;uAye2|M0db4M%?Z*Xxj~GP@hNpMF zANSi_*S4fW-diXGqgUDeA|CMxc!Qhh@#3q3%lb3rEi+jY7W)_K1Og@EL-Y!QI)|KM z^r+$I>OK0;S=Vlt?b;1R2)2R?kn0zV&r;t6?tFy$?({%)$Qu6cT1_u92YqhY*Dk}3 z4n5JILpSvF%gvt}4DjDhvCt!W_n=43#3;AeVgQC8IPkE8eX z2Xh6SoAtcGZ#0!Z?k;5{1WLE4mY2Ag--_^`tXK@T)<Fsw~ zQgR!nwdfg)>`P~CsB&J1=_e#TrvaoH0rGq$XuGE6o#$J2GUwo_SNr-TgVH|}yYp>D zuv7+LoejJ$u1&jC{Zs01$QA2xWKy}x*SWHc@N-WmQC*aTA^bX>2nbDW4it@`_WS~ zr$4w(?5$g}r9dk35hESqi@uuKcsto&l0W3dMe@V+BC6Z#GrAG!*! z=0to_arM{-JT1ID)`Fd#Q0A>gl$h0WIPFVe2ov`WOoWP-5Xq|W>V2+)?xg5)(l1}T z8SHn4yP&*&q?cHx=(LKCR0`%%S8}z`CDy3(rGVFbq4PkGDLEvw(E>=-fBx=VX4G4Q zm9(P>A#g9W*9NiL)oD8zXV4SrVH2R%R<>VdAsJlif07~X$~xOz9u~W+X17`ZM`htt ziuI(78?urI#HN!d|BX0IHXXkz6x?}bCRTPHKtE%o`*3Pnnbk(573<^(?%N58o3Tp= z;tIBKnS%zW|1su#0r`qCg7r-Y@t<8hlqv;xR8h}K2$8A{a$UL!M~#OJ_q(HL?SChH zTCh-3@Y9xIjp^)F#*vY$N}O^dUrD zVX4uCe&|Fwk&tHB!nCl~t}|*X4;4}4C>l|MnNKGF(;tg+}bniS)az}^Ri z^LGm;f8e9Ibc(0*=Od1zjKvSjuoE}H5vEwb=8C#9+~{$%80B;?pJ2zeDQZu zuMbK4CXc&oowVTb+c2-TLrWFC-$&Gb z>d0jh_3#!_(OE|*EZAnwf-Rg#H*ur>9R__Ml!&MrClGwI!JDqH>_p_;a)#kw6+6mi zy0Wk4Pcg1`A-@LfOtHZ*4z9I@s${RP9I*Q1+)a<7SO8L21H>(Ak}e~mA7PVg=Wfe& zsDg|`vl8}i&Ns|Yx*pbVtUAdug!zzh4E!Q$Xje#OSX1UqY-pa^Y%|*k zm7apVL5fN(8lGBiV!(bT?(jcf)Z6&@@~sl|PKBA>XrudnsY>&Jt^B;9{WkGu_&vwI6Ere{$N8veb*_^eu_U_-RaE^^0R{JsQb-VtP!Lzo$mEL4K)(<<+D>M*l z`eyfZ=2@MIWfmfXavT^NXm@1nmi`W%?wMq4h?S!p&3975Vi*bOCpXA;`#)k7^{#UG zci>q;wO`ecn7uKOg7HH`=XuB}J0zj##j3a;qgJ)jOInLMwmE1#HNY6}UZG z;;m575$d0r7rYt2x7;Nj%D60fQ&ap~q&LiGh-nS3n+lYiI%_?j>!f%-Wx1(Ge|WGe zvYbVEi(}Ed8&L_uHh_dqTUHwL+xr_3sSjGV+_oLQZ5aF9R-H z1$bMu^VWVNBAM3~arci1B-N|_4>YiM%PcJ`PK2jNZ*F%qk!h)-l>bfnwLP~d|C4#rAe+DF7%Vfv(_&(lF>~L2 z6*ty|J-VJzQc~NlC(d{V&~TlH4DMD?zf4?)_4+3Z;l@meGjikI@UoeS+T*c#Cs)*v z#%BNZd}~$Tzbah6`HkO`lOZTx5le|Slv!T7{EG4ox|dC{`=x6;@wEi9tT^G%H$Pg= zFjaoWn{gR5@Fys@(Ly*-@>BGE89Tk$u%pj>i01>0`TH5@4%l9~B!rlVD3lglzCgV* zPkSgq;tz;a$2sBvtvdPMBGWcXGv9a>@a*ugy%)VGYvrx7@rTfVlSxtPcjs(uA!a3E zxQh&?iVsu6%f7gT-e`r2eSQl-Hw*;>#|K8I*f-*KbCnK$n_KMAykDD&T-be)m3+ou za-^pBF$1;L9`tCKr}{q#5!KR(T-aZD+>7EEoMk_B*Hp=7f2iInnpd1wL|JUst>n(Y z__B=9!|EH@hs@d+>mHk5XZr~lciR1|F$Jd0@dlL~ccTZ}(@LR7h zL17t`&Z&AU?wjw8D$16%H zHkP9S4xH?d0aAgx8lv5H2`8Li2vAyBw*u)VL9Mzy zEl9s`rLM{p#@pSxsCLA!zDRLv{9RBYCgKX@BR#eA@ys=QL4i9i7-=uB2v|bt@5J2F z%N{+4qQ{+*-fJh;gU7yI82`n&pN=0JuEMi;R41M-p78+OZ@Uezsb1xvmszy5=UqUy zNT}FRc!QPg^a1nXc-0Hg!n5z*_rw<_b-1!k*OG~Y5?q4IZNHJ>sB+U@g7e5QY;ye{ zR*k2FhE%#g>e`foxTU>Wzn2@frnyf9Bpin9uzIF*J(lKuBLfpKgub254!lIuP&kV{ zck^R*gS=pR3iB->__sj6wkK^;e~JG-6GB~2z&A9j3|2vSu0YQmBSFyLa1=2XIuQ*Ds{bcjD$yxbk4W*UK{r zlU{&~+&Z{49$)?n8vJ$N3Nx2BTk(23ax{}7AQ$wAI@K4~?jf{E=;egEq|7dJN?>Nd(QJfREpWV2>OP+_= zpN9|%OxA3&QTJ-d4*LzeVjhzgLE9Pg2&?44Q|shFO1#!ZmMD=*&5Rw(Id#>)t2O;9 zLfoMv&+M#itZDkSb9O8iex;yXl;ktmq?PX%k<~^1rI3#^@`@0-v{tnx_~a2yU<%Q8 z$1^3MS!mrY(Kx~_xXesjFD_CXdaI_>w(;m}uKBVsRZ*vQx` z*{de#GCsoNa6_{Adi&)*I#9hM8_++d%39WTJB~+JvC)exL;f8@rwaTc;Dzrw^?h>f z)S>$y^%2Jugk$FKH4rE`peDGfPO0 z_9P)JTKOU+T#FJC^qPwSNoGpK!L)#fp^)uec$fBa|HNkkWJ5uuZz%55e#ZeTHo(Jk zh%9^*Zy8r2AvWT4{n)Tx)5ird7t%}bFL!A$V876`tBQ?h{bMqe}U~n48=Ei}eB+3~5-P?bVRgEN1F?b&gfC-w8LZ=7ysG zsrytzUtKXKeYT}XrKt8~aJv5Gv8$$`=r0*}$w+3y9JT2F+L_Uu`;tO{@ z^XO7^RDA+iTN#7!*t0{LCes_^*qs~tz-7Vn9mMRHbz?*g229Wqe59Xe=P|z(n~_s%`;-;7bkKKV z0`rmqxc}kMP~)SCE(ypHwPr!#x+oz=cjd*k`wMLEVn`4dQS@W_$vAM~(let#+a zN;>^hc|EE)3;Dpw+Me7(NNoaaG%;_c$$D*4n3<}8VfSmr>E(j%Ka|g-!HPv6b`*L$ zcl+vIN%Xmw$_VTnXE@nF1}s1ARWhamm6P|6jaQ5P+bPhX+>wUu*3eTu@~s*;qDBFw z+An!wd)=C~`z1$0mL$$pet{|Yci~IrYZ}&E9ARR&`_mlYlRc6ZLKlLHY#)^8#CD$} zd3m91w5|1~Nt6{W9q-+;{S4z}pJM4fkI3%<*8E(RPzv0BEa2Lx%x(awJC+jZNx8`P zDTEN_@ukXQyUBU&6-oKJxN?K*Msjw3Skl40WZ?ceq=F)ILe=V2oq-*49hW5~9gqr1 z{*H)}(1B)2dgXdHDa+L?y&^dJHn6DDsy^#@frh+1zrPCg=(?9z%in-NY}`DT5#{_+ z#gZx>{M#wj-7HUCCXSW)m-hNylfEZtg)Dr)9S!;5N6CBZiQ{|}&1qX1ds*(MjBm>a z_ACu=IlGa;-NU8m{YxBGv60eu>$zEVpGQTEpoxd#NbaLgw`j_@o@dtf($s-aTeSgB z@2xkU!DU$bMXoOL`38wZ=z|R*)$#jqb+{F7P8*vN4ky!Hua+k_!?Qkp@H~y*WlRhT zs&j4~E;Lm0V{<$jw}tf!{Yk7UCw?`=$i{D&#eIY2_sSj%(a7cf_--*&ly|U$aHWTS z|CPXjpvP+@YqSjrMmnjaew45l8vRTCPh~hNz$17XHI$WI+E;pGz8JK}KYaK{6Iysy zvn||xq3p4EF}iD(t>AGQTe`C(;4nRt=wdG#rZPEA0Ci{_H=Gy=*PMopVjCUO23lrj z47x}i=jy(rt)kyxJ57R|@s0z;b}RomMQp9|u6CU2DSis~3uv7nTc#km57%cbG*J$* z%_r(gz5Mm@mDCl=vuY_>b0yovH`e^w~bsaSj!BBrkEc@S`S8|}<(F4Z_*PNw` zFMX+j_Ha2?fjqw?li4QGR};L|GzjL)cL~OEK_N z!V2mRC*!|}Gpo%I-I+}{$4KOH;zm~ewEjK@1ehlD(Zh&K+4)8sJpldE_!rh+pCSgG z;exrOTvC=jgsFXC$pyvZZsB)+n7hUN6(IHerxdeU`M}hJ6k`^d2(|Zr+OwTKo$Omk z-J<@OmcFmvM^{2yD%x{C%CAky<%#X2Z^Y6dig~LCy)P&S&QFNb-08kqMJ@y5M(-iG zpp@BV-<=HmUYNDCJXKT-_Bz|tJ|osqNGO_;VEmAgI})tr*i047t*)VXB;-0pz1T?r zmd|1PVh(P<_v060CrdyB3Gpo7)QWH8MQ;E4!pQCOK8a$jIs7`#X~JH42NWo7-T1jh)NF3J825{ekHN&@Llm<$V3h(HLT-yP1mN0-&U=LF#P*G4$U9lIfAd}DT}j; zXaW_=j!Q7*7{n`LF}ENq4K;Kq4&Bk|_&2)i4~g}HgL1)QNFJ&X^4r#dP*IvEC}QSu z`@;-hAW#)5tB5A!Dr)9v&l!n>e=$lm3Ep65H!tZ?96ZO^?!+LKKU%Pr19_WC=vW7u80RBfU z$Qr!Uxb!SW5W!N#(^3xq-noS`LWrl=yEL@UuMN3YqCf&i|HnHR>|Wh(RZue0~g)pW?m ze*jfg?iA)!!LxMX|IM@#r$3Y*C`C_;9m&E8;BG#xy>5@u7RLK=NnZT^cOY4$l4?Zm zc{fh(J?`=0(-KfaS*FR_7m$^FZVhmRYk-Mw30vo=u*{t7c~$ngFXTh}w&SH?*jC_7 zN&Wc820x^|WOHUW%#m0gpSatafweq-L5FG6=+%EpTmp(%GR1&gy+W<5kGOpYo#Bk+v@o1Hqu3w#uEN=0VOijR_~Kj^?S7VbZCmT^zwxz`sPb*OgX28J@vEC`27#&UTsOG@bN*l^e={iU z&52G6(K@^!D5LiF_6<3X^0P2WLW~>gmOre3J*bILSEPC9IlufvC(HgVjTjM z2*HNX!J3TdB9RSvqt<>s&#`X{zJZo^GUGq2w|eCZ`4*KdP5r%i@ULB-+M^P~pKTSM zJ(4ODep=QA_axEri~E|n?o{cJ3k!>tq5G~Dq+^M#z(4laRW&>^21+68)AgH^X0I{` z3`J(>dH=Xn#jGM__Xh$)1GvgfZ5AQuHBDL96?BbBD;}}yl1@?t!CN!ZG1|;=gpu+! zV8<>h{0!%D&Zx!;!D>im-aW>2Rm*yA-Mus%E|$OOgd9~`Zw5a&SSJ}xf5v>M{_4pd z#TZSGVm_qh&QMT3`^EpbTPaF|Ee#IK``sl*$UN)!EFmdiT8?*&kUyUAfqZ-Ui3{X0 zHr4n^#sQk63Gs=YGru_PNaVD!Eo{hELMzc%zEof1p?|Bm<=ui)BYv|x`AV+beTsI) z`od6(E_UA3JI#r!AadBR9{i5-G0Ngl`S~&Ev-e?w!|_)fN~>w3Y;7l}@HGi|p9#)* z2$XY-2AUF7-FMPo?-T8#ZX4OL1T_G|f`*OWz4gHA6$wuT06S^>83`E71XFutU9Ub* zJ*bxs*Puhuk2TUEqp-V-yUp9|faD_I-nIK#QJKVLy96K{gQB{f{nD~@75IyDC8DW| zSgcttCUU7oC_*rbH?yq=c4iBIjyVDh)5utAI=Z;qln*DKrMDUU`fmhKPyKXmh(@GL z?x$pYc30BBN&X=aGNR}L3=nz^FJaZWj#NT^x%+5sE#;O+E*{ne4Ym=hxpdNQ^KzyA zhE@?M@k`T9$$*aQnws9ouIvYfS>>RP?3W-*FC8iIl;&%EQwI+jFAucMj`QNuUy_T7 z&R(8Jg3W5xM%ZIH7k0 zXBL2LPww9-qgcsxE>EQ)e_q*P1(w?@q>A`Sj)1cjCL)j`!T0B_puaq#PX-8`kvp$? zGwNMBYRJL|VsvBi=r2q6O6}yh#Q%o&9rvd!Y`A+isJ7vaWP_`z1^5eM%tvP68YD_$3;aPN7DTP;Y|4Qr$HeF^eCO<1_!=t(vCl~wm<;yY}Lkd0sub{(L8(!Q}9|4M({tUTK3oc zsoG(AqRcx%g{MJ(N{z=&)M%uXXv_4{KnnJiHO9@S`N;O*l!wHs&|KV!tx5}%tTJ;_ zBme6#vu81`HuL>}=9qs+`5L3VoT!J$INdVA>U6+iPBHV}A0empMZ&aaPINoXOYdVB z{#V&PsVyNyVx{7%EfwDeuGtEcU)+jNO(<6c%=;*&8?U8~N0+k-yU4j=mewOUu;;dJ-zZv9?j*pj#2mmTBc?)Y_AtbzGgxa=dZJ z@4U9sz7PE-SyIHBo3*{ax1i;{Hoajlh{^&^0@AZW9p5C0&sBK*(+p|?JtW^I#X&tq ziB3}>=wm8epiz(4&Nfne;#k$b(Z_6C4|c0#>Y}CdbK1*+Q2~EhZ}%KK6G=5!%sEhD zFt_1-Q}*z({b?Gu8M9oidZT|X@mKIlb(N^=@YWajV|T0PeC_ofir*>hmJ_&x zQR(H~(JQG9t2&e1(;VhaE%%$*sgd{4f3D+heb5qDkK3TgUbM5FI*J1nZ<~w#GB>L) zmYaIYdrqIWZTng)W0hnTWOq=>clbU0mp8lh*OwK%R4g{kYG&uYQ+h{*XqI4Eq#!DlN|J$L5dN&q4!U?e7Z(H1?qL4;PMhEb?)%Uo_@#-qL0EjhA4t zlEJwR8Sogljjl80Nzp6qqFHjB-(8t7^*?9a=H7fkdrs1()BHOs_hT%=jU?I)IHIJb zY0z=8Anc6nr}b%k z!}Hrnu~#Tls(Oozfx-m5G}*{&`Q>#+ZdJ7rf|2$qeJG6g^{v6Zw9U&a?z?{ljjpi2 zb5i%L&XZJkRA)T(@67M2%=A$C%ETf*fx0K)0u6fMlGDd^wXp)CR^VCHVxwv0)$g1i zx?fc+Re2u;uiw(x|51rrc7C};4luDPKs-D6-soE2Ea{>5TxG!Bv&_1&4BLdBobY+% z3(cwrZir1k==J>CjTDn#zqhn};-de#(jJnC>CBgen^1qXYiX1&{_y{*;JI5~U5lJD z=gR3D2!1oxJqd$t@zc%@ceEt98fx*AqZ~KGo!?4oUgS)Dg$=cxEuXBzI)3J_%KA5A_RnoKLL~h&e24eqw=!-gJ zi-*1Dlksg6)-~i8FHW~gV}~YD8Cos3J>O6&VNSU+uL3x${jB4yXSn}8DNK+0#8Xj0 zOlc?74V!opuD`hYf}4&daX~H4UbAH9LMFf1>rnIXsT)JM!FLK9&6u%Tyc8o0tSse; zJsk71KF=&bCZMaeovhth$>@cX{G!-_i{hX9N$sFR@y5G`Si~G%$d*cVPE|!DNtZXx zO*2Ok_1B2OrnrZ*+U|LaO~x>4;HFn$7%$@oXr;Kn7eJ2iuxDtl27i`!;ap zG0yiiK~YZ6ydH9oswWUTJv*lEhq&eNm%!%_3U$>3@zQ#e_mf6=hGQiW%RmV8CN~nK{?J* zs`1&OH=FODkEqCqqRhsfzhJp#Vz1+_3$;fEZ(d46ft#D6b@CvELg#CjkVcR`f@9mO}@qYA#M&K|ZWd0~`pWhSl#`5=RjZQ?q zDb#lu?0>h{&z7{D$CsH;51&gK$4soimNb992y5Cdd5RMMdw$!0etmC7o%b*ZpH|Qt zyW=~lPJg1W#joBX%t@90hrU8Q{BmX+c9hyMlm&N@@Kw|4EVny@Dh^D5bP4Y786u}J zt7-gdC~&b`4D2UbdfzA$KI2((47hr*9orbl(R9Z}mmi}X73$H{ag;R$${7-_+DPd& zl(n;kUT4*;Xo!xW_Hym++pdvK?n<&zish1~8=sBCFRzPX7y$A>4v-*Lv-Z8{C&OgJ z1F50Vt~r5C9*#L&-zV^uej4sGGe%Q-RVG;JOXJUPZ*B0}oMunp{=`^$wv?8_)*XEj15qJbu==#K? zw|_s@v-dORl|s+b7n_v+V6@MccZf9yrmx*NvTi1nUS|{5y2W7&(at0lbhp6wg}7By zJIJ**ybilCH){z_{?)E7<|}W-__(vggp}YTW5GN+`QXn4#li!2sZdZDME%57RCb;G zuT>qm)-K347?6K|tn~Efag6s6B9GqErSaV$N$)RYrOpnETV(u<1IO&7o0N#m6`$sd z?#{ojp1)=xe%h}*Htij7+Z%5|#n-#F+`CMRI;Xd{vte?)d{zU-9@YI>E9@qM_x}(? z6^AU_UC(aU)ML}JB8YTBtp4w)!{^^Io=7o_4&g%;vX7CTgJhCEc<*Yr9GYs!Foeqx z8yRNDE(LLXbwjve%|Fxy=_}-~{LL-*dchD8BwM+NQDnpk3 zI1e^!o)Z35Sb(i|1u8Rwx1}Op(T>u!_NJTG-xo`Qt`+eL_Wo#Ve^(yssa#kv(4A;= zMqJ2>ORRa|)^NI7Ca5qXZcAGyJw!7|FTZjVxWQdHu~(d=#9ywSSzl^73x?;RBDeH5 zuX^l?9@X6_9ZKpPpj^Z;EuW4h2k_|9qRX9b@xZHs9~)+jLkxjTV>k~$`DV4u*x@a1 z*7Vb`{*YN2vNdAQxTi0=*jZe#9}l6un%AboS?^{+oVR}c+;MI)mh|MvoTL+vVKwSs zX2ie}kp|}pP5_4nt?hdX@E8vd7p3R&PRw%w z6PPqzaAYHV6pVu5@{SEmksPPZ74r3cQz!4>ax;Nq7$`rp=bh*v+&(g4y5{6z2)(7G zKEj`gs*5-n1r>-olUqp2qd(abu!=|b^!}=gHwY|YzmubwW4qp^?gK6_$yqjH5G7V- zOBroU((%*vo@%B3!)L_`lv~~%N|gV+E~<7sZF#5f3RBQvc26~iW;i`H6IgDqUI8dX z(ln2ubc$+vG zsJH(EKJqV_zy!6By%%@?_fD|a{X8at9bUeBYp06@@6ZJ9Bmz4+Z~qBIKnC~SSCTsZ zv{Du!+!i=2LzQhEHurJA6Dss??9DsaY8Z1n*#CHL8RHFm=Uyy{d^b1VGyWxHyxq9t zr{;v6$+&jx#?ldYvO5$`r)z1&6(+L(r^9)%Wnx_0S zf6yoT{{Xw*eZB`wjy5Dz+pDQaiMXMEV&Ki<5WP#ZG1sG@FW64s)Q&4D(aAYmPL7IE ztF$hojq|9gK+)H=*PQG<*wR83ux^;O_EuS+`-Gh7N#&P5Y{e?#xNj1`MF#fAi0rk8dyuW&#~V6NR`%3Oo)RJ- zem=4}KT?4HQtV=|*|UctVre|61v&-VCd!5 zOhszk&P+J)0p-Z@+;}sRAnm2V&s*$9D<-W~k85n;wMbK6n*N@TftLoDprXvqLZ;sF z?Z0#zr}Wgj4aYrp-_$4k3DQUz8T}g+1%&s#oYl@5Ml6=JX&j24+;&A|(^KDK%WVGr zP_0(emGfuVkwrQ<6WjSGvR(hzdEjh{X!`*9W)y|F>`Z&7r~C@E9$}t;%w} zAXa^&>QyzTu0wafsb#p~h6i%IiAji$Ydy^t3qnCKe$$wfap}BDYOSO=y$JmzajS&$ z@OUs}KYMsP+m4-WKCM(H2#jX}O;&iFciNVcyER{%{M`(vx_+d%p!Nh+F!Lyr2G>SX z!BW}8{9*Iop%ZFfHql_0@^t&^54K~&T9nmwF zi=u)XCoY256lyXHvgqH`UmL-=JCmFhn*~=&u8+mlF`4ykz#y%?MVq4UN0w-DCE&qb5TmhmuagZXzR`4PF*}=~-mEh>})e@h%012WV9Dk*KMQ!G! z81Mjg!(M+cpC!MgFMlSM-M(14cr2IezotKI&wjV3ewx|m`R{9RB0e7*QGcxwpWl** zr(*f8EB}Jh7U+b5N60jVnpN@QH>;kDypqnTmi9ktGcwFFNE9Jr_vh%&a#XT`gLwZK zErG48s2mQGsC?IBK{UUOL&pF)`J^X_ zY%xOO!$GHB$y4*1X4TzkQS_I6VXSL_fm4qCX@8>kc-pJdG|f69N5F)TyNpn5M|_|| zj+DJeKavHCn_Be?OrHqgtGR+;z0U6*#I&h|( zv~6lsz|7PZQRM<4Sb`r?7GJ>}v5*ge*ut-n>(Z zvmora+G_ja1?~Z;xaxiKooy!wD}IS6Vx+#6h7N{8`! zr~NvM$>zci7P(ZU&O4^}sSUEx>RGi?O~z9`C(rc}`=dzP5OMUiW>av|90B_yqlklj z@EO0wYy&_&!7#3mOn7;_pD5Vhs%>uaBACF`yCdQI(e7`}j)f*#_A!5o4A7DpV=cww z{vS}Odw#`j_YHD<^m)Csu>0#Jbul0oy5|@R-S`X6uYF(MH+S7x!hGvOL^TsW%T%gA zGxk~cv+DYU#DH0z|CD}6bM>QU+h^pL<6%Lu_fy8s25Wg0exT@!aA~D_w5)L8YV?g# zIFjtqvoWl}P<{&<)$dgzY%>M*jzP-ot1o`(OscEkv!rqS(eo-}W4X}%#9_ssqvfg`5J&3%TU?q<{L@qHpc z`LXl+Z*2>4w6qv$v)vmuIk(7rLaU|hngyM<>LHaC0k;gl=F!a1gwZV3A51Epz4|hc zQ=8~N6!vPiKAk|-X#SVe-*QUcc`lwm6_Aq$Y!^9 zS5MSO%n!b`zlkl6Mv4HfJ_@bt@iL`=q<=F?}DhMQ@;mTTAKo+V^Crho0r_r^=M}tql>${pV0|GQKuu@&u*oAv~ZZr!qc-$~s!*uSZ zM}K1AL&oRnJm)p8{E7?8h8rJJdD@WA15*aW_6Me`ZiumJ9wl)|lEc~!Wmjq#2J4Mw zzV{pZon9Sj2*HTl5`P2nNTICNJ)HTNp%&iD>t6~EtlVAm{HU$+ymwUpow`T*&MT?F zDT^M3zR)ZwGb(mx>jyi3p|yxjT~~j1ILn+5Jg!p2b=tV%rG(4pBdVG_TK=q5qlv8q zHn^W-1FAjK5Q$Z$=v&KA-hZL*>R-^3qN(=TBAYzp3U(q5zKj*sc9R=^B7Pp3c=+Mc znT(w~UNM657)uSq^HVI?m>oy`ta!95+ene8@#yC?)1gEE&&E3~sy!`-4UdA5@no)z z*`@PXMvHE9KtI!)q1bS;fncJ7z3P&uT|hq$CJ094Rrl7_Qn7(R6Nl>t@cS?C^%in5 z^hRFx!Fd`nZegJ!PNEKZm8>)rR|obQ$2v$Z-TO;JZFmXbl*-m!{SF*y`Fr}fC3Lqo zUIB25{NvK0rqf5sc|e?KjA2x5t{boYXaVw6*l#zWyqYTqxrNw%u5u`)v|D+J+Z`Jo zAmWQKk~u)61XimiI05LN^b#OlEyo4TWyjqo?*$HnkhoIUfpqALrAp1il-n2aYk#v{ zQ6;GS(|47;kM*eju+_3+G0{LzAG`6t)%!$NRV4*todYb8vOOD7*4^H%l8-zyEEsXd z=vmZv{b}T!Pz7{KQS4RF)QVx>?WUaIXW`QhpWfcrtA2&~oWC&~0o;Cfe3};;aooZk zBUHma5`bG|9nNk21?$Xo zW93(;w|iNPnzd*TOHSY!S@AOw|BY55$6aTe7QHq=ksz&G4xC_H?xr>JA>#+3;&=_3 zS#-2#1)L^cafbSM;J0&ZgnT?Q16n@6#{ZjHJzv;227MN5UWXZoL08Y5^wKI=*LQyO zTlCa^65Jc3{=4YRddXi=|6Z4hXew>kT2mj^TggcxANpBkDD~t#Fk}nujf z3DjBt79z5GMS!oAZ${9zK>zDOR|8xVyDz9Np@I{`Kil_cdXzPTibi;n4Of7G&<7_w z4D6@VLqg&;C1Fj82OCJhfy)du0b)kM7`rkx@EYMQA9qqx*mOSG<%xp1hsV`_4wg1} z9|iI~MKAeja{WNV=KgloOItWlYvuKJHH5I9e2S=sq1z1O0tQ$XjA~F>yRJe|#D|Ft z+JvKa>8N#j)7H8^F(3P~&dUTi+B#*~9wA7Je%T?9Gy5m>*K|HOSACGVjfnaXytlI{ zG#6E&RaLINFfZlriaVEH8aym)J%O@%-Y+ibS-onDoQufxOtqXxMO>!x$Xr_gdH{RA z*DM`o8jsW>e-a9_+HvHS>_LI{(fj zmdI;BIwh_<+WB7ZmHP2{JA43rW4GGAHX=2~-pB@($R6nNQ=$xDYih3ZpZ z%|~g+!F31TLb$hJ!=_I|_g~)}Yl`3gN0{1%^Q6A@HNlkZh!T5R6~_M`O-c~y?A;vy-vs8*?nMxtsR6=DLlARf{jD5&5V_yb? zvCfz=8}sx1!To!5Du*R!e!^nYdZ7gk$jL%i{v2sz69=kSv! z*nL&s?&w*I8(K!Mh-^ES9{Y9#IH604-{gjB(OkI>ga_LbU!~|^PMnRaJ}Y!g#l@K` z8d*ENwS1ezZJtW2h}#s(7>+Qun9(ffmdaup z`*=%}ar~CvL}y{M@iBr~6=|jf97=Us{luS1o-W}7xefg8{FyzQ8P?{P87l$U8;8bf z1MwaZ$JAUqJSb~$e4S-$BeC-iYj>W0VQf*G9FuH#b;RS-)eWVm#eyd$nK4qu4@T#| z*G9tvf0zp#PzZmxUH!^YiRxxzci)C@*3JcEjj$oixOnauJ0M&nr9a<6s`gvLPn>xP5iw^aRgeCk@qpaNYkQr;(gCaKT?I&gl1O%*7 zmtss#Fx0nSdU2}O<25meXp()PNu$fpstcLz&!qL_IDP{$8M1z7tF-HbsZOk==&cR{ za8x0DgtTks{DG8o3B<~S<(40b$|=*oI;j@JxkfaQXP=HI&9Iw@P6YzCW@?Jpmbq{l zWbU~Qa4Zl$3m#B>O&0)feqSB^qqVr-c+3`StT===qNOYmL0Oz9%AIX@ovN)?E-oIa z-B@q zU_OL@v(WWvUhw9*g3py6U0i;z508v9u(d9{bHuC?dVJ_i+y-^@{hUQHRA%eeN2ilG zADFv=BVOmNxkk$c+f+puFk{(`{;e|30q{AKj!3Igt_C_E$tmH|l1L1AzJL#M@s}gkHiqua@+UzjTDLaP6Ml!^gtPstXUU&mr>=V5*w6& zAJJ@<82D*F1hT#%XU8#KXf!&X=?RV7j9@O@z*GXx(nBQK8fn6Y1ulhnq*?}b zue!zC1{XA4184lY4tvb4R@gK)ME0y%TqHDEwlAp2MBS6{Bp@4Asl;rvP5 z5^&&>4y=IP@OSu$eq_bQNzfF(>erpjbb>|GtOMuNccZn-UZ#popv@zl&Fa6u`aWMn z4^;k7pM1u%yPwff<*N(&+rVvn#G_W1t{8YeE{FbQB+cgqSW%=~7fFmhscI0k)rvFVQ?^AWAH`Fz5MBBc!^ z^qO^2-F%mGDX(!7*&K3*t#9!Tk;Z*L6r1@`fBu(tHX&l_!RK>^{yrxQZpNfFvq}Ss zrZF$5F0Iioh+a#^cd{n42 ze8aIVh}3>I^cHsO)Q8b12P}}-Ht9e@u~%ZEqnw0Wa!?n;f+B8iDL38UBB}`C>+I$u zl$Kk5BVZE_hOU%@9xPxTyeZCe&NNS~-N>N|xAfACc!O7-@OR0{J(^?--%PA-Mg^E+ zL4O%`p42Mk52D+29Vw46_l+;T=Vz+dRe)Mm?H*q06gF&WcL`>z$$`zkY$N;>;q;0w zlp{5nJ8N;ft0{?7!0(k+GO@w-L@w@90W_F`)Sndt%=50%#H3nFe9hJ~SNb0RJ3@a> zFD)1fO%*7Rb8Gji5!665{mfeDCCd0|sZp%Dg`xOPBm;GABiz+wW<7#Y!<;kQngEHp zV{)@t0oR|Rq``zwEO`lG^(%Pdg5Tu^W9~3{uk&lB+pK}SgV7`LD7$Z{rxf57_|3*8 zD+k-v*Ej{DrW`(s)bo%`{wc?2RFcnZ)?OArH$N301zDP|NR!r&{ z06=t#DYYmZ?_`UsKH;Rw}<1wU!UrVHHq_9%t3=e&CU;Sb)zXrf~ICFs5$kmC5a;=%Q+yQC?iu zv;?H56exmtb{^RJUxEVzq9&c}f5MSjm0#Hfnd0lzG_1)EU-U($WP4B#ldR#|hY;Ew;=a&CO2<#5!$74`RL0f+otc}qT zuY1-sB8>Uf z=+~qFwS}3US3{Y*a(m}hDaZEL7F0W?=^*^k1vNqax4^?vfmhD)zh7Fp40G$^$6TS% zK%C^zCCl>FF^jKW0yxxWttkx(2TLzu?g{KDit)#k}Q}K_@ z89;Y)wOPE#pno`G(&Y!nG!%P9Ub(CR*1Rl8?m~p$!N)vE$B;CZ!i@sV-Cl$znDu9{))T=lsH>*RuUinA2Gb2 zJlmjKd*9~as0LK4m?hcFHIJYBY~laI83e2?$vZ%vsUby7>9D#if&Jx``lvA}g>&N? zk=Ip7Y0$F+58w(5|mvkt{qI(no8=ZLP4P?sGCbR!UEN(_dYg zS_*GIW$IiQTT3v7Is>adP%V6uqXqGV#6H@mg;VEE-&^ z-&TDy1_A*sAFu0~uXvpgj_fff7F+EpI9*vW;(zdzbNnMu{xEcAo*kLJ8%5|9GWcq> zYKVqQzGDA0@tdMSDl1VwlY(f_-ag+Ri=lN|-rL1cW^fmy)?7(wmRmi@IDFAE61c0w zjq4zo45NR|p!LS6bi~t%N_9S6Sx_Fm6Vh3CqIY5njT+~qlPx<59nMGbDRG{#-5uJU z%Z7KC;pKdh*{Lbu;?F+^{3k5@RG*XM{sy_(_NOulaa}m96KLA;&-BrC?~~%fthzSt<*)H|m3RE+$bD?$f9p zen3;pZlp9Il=#I=QKV(&-v}$R6glqbjY=#uT*_9LgW8N7g?U0ARXi^q<6OP-SqugK29BwF7gu)HwW)+H7~x~=~hM~l;ALPa^s)EyOR^VZ9xp<$!UEXL~k z&MO^RJ$3Dr%yU4bt5xM@MAHUe5-(Bxuc7FSQfp5QLi~2MdY-UQlM>x0aUR4q?tj?p zj|1k2Lj?P_2|A!!`Yw>k!)8OTiP?vQnWvQ{u{qI}0RxPR6Wf;4IIi&`Ts0dlf3)fy ztaZk5>KNk?*kjVaQG2KD0yr&y+RZoAN4q!Q1-gCcl7hB=M>jvp=F-6oMiv1S`hlZJGHno=Zt z)61`X;`}P;eDs?NCz(rh+w#4#wT5`tR{UT2|G+VC6yJYtv}wqIvH_Cli*mgUdbEkJ z*B~CwEB<%e7+U{I)_p1q*{4yizJGnPt>s^rxJe1_0jm5)|r_S**hn=n#+!$AQj zVa|7$eQ!MiQjxA6ya$4))4-~Lm`?lB^f*=CM^*6Tg zVLBDzRhI5mI?WGFCLx0k#JB}vxW}=v(x_>V;dH_$J5GeB%E7ar>lP3YZ zsb>+7Es(#6x9SU0?h;;qoJQ546elaEpRTEHB?Gy|z7y7AE^Nf9KO2*a*-4ZC7xG5q zI=sqY0L5;^1jSmo2kUya+YwEbF*WJE+DOW+CG6-*e@nOCzL?*i6%CcDMr)wpGOwFN zYd7z$Gva&nYUCQ{5WWtx2 z!HS(kpHyuNPlZ10bB$iP6rVmvD-iKc-3(IE?abTBo)$o+Wfu(pSo8HugPQ?OnX17j zjDAJ|i`U$zW8|4+J)_F-%b|`YJ_~Ze8ro3eW2y0>%Om1|U~x$DVtjs5FAPaQ*Mk@X z7dOner}p}+;+B3X&nfYME?w1h+^Kbdx2UOR=TRGMHY;aG)a1wnFHMT}Za`l%Erw); z)U{(U?gtYL&!SbPY4q6zBJbLLcDN${%;fZ=Ly9+NUnu?LC~}Ihw+%+^&-y6D8{C|d zB0&`Ix`<7Tgq{PBOSM8H1p1`&LeyHvUx9$EaduC7jtrtHO|`0xHsHoD1I)i!kA0Dy zt5l{0m3LS~J6TUjDbha2{tD$?wHG~xXmv^&-}FtRr>e=sV>kM1y@^8~rp(HN>KfM> z2Mn8UVV!Wk31v*sGg*y_xv2nxb$fKS=yC_$X!5HJ&>xux$GH~U@n|ByF%st(#~<}t zFl79NbXvU+r!|7!LqD>u_9tc|ev#keu)vNs`(o_EJr`#E8?Cw=;fI?w?paO^U3&?l z^Xe(%h#g=U{c-jSqC}A#TiaBRka#ByU^CprX$bVevtqc4Z5+wOsBGmES;hpYkC$ zu<$9ce>_^8v`TDMipJ(3+ip@SCchDAMTDib(!dFF3!g^1r>IYgM;_WSswtY>g(-Z_ zO8e1{uujAN(Nb*c1IWorw)x`%L_gbEoV&Mat!C8+s~6pp z7gq05Z#ZiADgcwE117QI>j~1z*H<3VEPDT5r$`du*w;%N6W4bA1ZI(nqYoy}B-Qjn<4G0H3IYwRw z(9G*ZCD{u-v5XZ#{A&%U#E7CtI-vAqr{YKZ0yD>=|`0;v?FBtUV8A zb?(_b(~9#x?$-`(`!UF|a&wLS*QIEawD3Pks>$Y_(zH=pg0_oL5MS^@9d&YTZz)Qg zfVHw#T>ama!-3TsWReB~l$F-mC>SY?0xR#zI2)Ww*z|&4tLHy4ytd+={Jq{SX(ZkH4UHxT zXQ&BAy5D`Z84SXyru9hj9@;|+wgSBhv)F04R(Quf<*U>V$nVSA6?)w1h!c_o9rQKp zx+@iblNVa3vlMbC{I}d6*Id-&RaDJSQ+`9|qpcsK>Wsp$CRbz6MDjPA!Gklg5zgmD z3cZL^75$d=lV56!`3Uf8oq(`tl|X1$$`4H{GlY3&7AWPhH}rJmvO1e0!1FaJO{~L_ z=+TX|_@?)$r2OW;CrO`ozf@Sm`gTq)P}UJ-&CetQ*4gdtctYl~6)j&k&`AEOMp#?`fA7x?0JF`vDcO}faW$yZW5vA{o>lqmJJK*c+H|Tg>Jeu;~x>SVDw!@&@#+z+> z${WS(u&KiVcb(GX8Li|;0?5#WY&e6lCg|PF+^n)`X-ZOav#uRsGdy_ZtYovci!UJCZE7N876Xw?IQUIV{H2~<%AL1Y|aU-{4It-5%c0n@~PmW1c z(1%2_9ABC>+FNh;V2+)wX->CNg$1*+Nq)<+hBc2emYryx;lQ~l^ByRJ`wb8Zl*KL^ z(Qs1$(!4U)1Eg|nFkwg8vDJ(6{WyM6RV zZmIp}(0<;V06Q=L%1oo=-!<01)yX5fT@_xXwo5yvEJquBRJc7Ata>Sh!xsEf%ad{O z{C$mgHMKduXwjg2!}D&3@_##`(u3mv89v{yznVL`A9Ew@kU*-2?hW0!oKP>Lr!KzC zLuT>}m0H0YK9$h@0HT$1e@SBGhlEcVLX27IvkQtkGqT$&60n>-x)$5r*l<$Z<^(r? zk)#AOAw}#Q+SZ3AkuI_)4ZT8^W209{#+VyPyU9?3pYM=l{7VyME_9h0cw0lO1Nr~S`6X8z+C5#;3z$CW%tM^$Y>*mz6VK?4fEIheJgx2`HPDLQVS&zTZjWUS zfpMQDr(BVxB&vcBK|(J2LVb@8ju)PkcS0_eHNc(`{lhTdy_Q;tFTT!J$-h}FwH)TWaTxE{k1(FMe6& zVO(z0!(@F<-ufcx|IxgFtnoS32677)DXM-9`hz~VY~+fk)|)caY#>WmS8e)Gtm1yu zgZ&8sq>ZTLT5DH)JonNVy$6YRLsi4FJ^c@Xo6rXhiDXw?Sv^l0_Nqb;LLD9ncs~+w zMOpP@YEpj1j}O-XQPE`?5f0;fEdPUAh`8M$`Rr+~XLz4O8kxM@+-tt4O8brNttt31%r&}N))1@p;GLMp-! z83~e(b&y2e+Ws+rckSnaU<(r9Wkw>IHs2y&ks&}i%#_Mkj8&%ZaB0H}ybMOqpUIg= z3b-@ct%{|TtlR@i_uQq|=h=M|43h*7di8<80latqN1sI;?mQsiNPOKJE0CkR$oqaY zBWhV=yBkU9csukR+7*j&=(*=-*oz#Fy0VU~c6CwQ0bQ5}sg)e?V95c? z>z9#DROANMJ;IL7ukO5nH9e@;?z;2yMfJ=}l3v`z;Ap-bqSfW=*ZpjpQ=;RN+L!gY z&@r`D_ZG#;qw5TL#S{s~3*{DbJW8pqYo}H$%r*|wYXtQ`yoz#2yb}A+5xJo7<;6x^* zs-dTwVsPOERX#WcPxgYGQ=B7IR#jY%q_cG)=Jnn~ccS=*#MJAxHzH6WgIejBPK^=a z)VWA6zOz8|J+*1#sqybyFukbCdVNKsjI!8(B(jIk>#ay!a;+S{{s5G=Rr78rl^mLV zge-LGnec&Yg$DiJm3^}?ud7JV$ch{Xi|y&26oKbWT+_f^Y??iy;*LZ6&6D|h70gEM z9+IQW3eCR0efoa@DCIwk=#v)Eq;ia(24+Z~SANO?(Qgp~R7u8Vw(X`_ z^wgGN=9N4liGWdrMsaWvznna~lXZx$!=vq2~co4r8HA&AM+h zqeyzg{ImzBzR262o`KcA~)tWLoE%1$en<>$HeH(*%5yd-oz+Zn}kv^VB zW@M5lv71#~8V6`F=09pO&{;#b;Lz2pHg1z5@}_RC<}j`#6PQ*Ycrm%8*ul`L1&r(&* zMWbN7bBIHVZN;c&k4S*?t8(PR*}B4PwffG4GHT$89{-yn{kIK^72>h(8Vd;LRafu- zd{nVXQu{(N)st`N6g7AmE$<7t$lM41CnZET<6FI3u~_}g5Nwv$*#Bhin|tt+2`fPW zMJj?yTGsxlmX#xyx|;hSC*_Z)q}7cm`86FHvP4ZOy|PJswFB@eL#-$m4~_UUi7WA3 zB+hXom(A*^W>N1Z;Gg>C$7@X>+?8;#8?>gfTCt8&y?xis$#+>Lc9gM=Sy+C}K2=}C zHFuH2@tw~AzI1b}L-eRHQ_GO)CzrDRy)=jXm%6;^JOne9SBU}IkG?j$dvE+2yo~-d zQ67Xi4r+O}BPP%A)qN5;I0B&cADgT)}7)D>ulG%CtevA=>G?ZDE64z~O zjn$Fj;%5>ksBz)y0Fu?@==ND-u&3Ji*s;iPWdD;$%m#4`sZ!oTMw^}KU>?T+TqYL26tw?{pYPIM0s z0#(b^0g?U~G|$JZvUOxTOS)Y6y)+aSS2(O{m8ffEDrr1Au=X_B(Eo>{%1-wO^}R9d zzcjUM^CVF}9~T;ZD(xaX{zo?zrU9XuC7n|9z2t+83|QYGW;Yz*pF)@HvY8s?aok=v<+>Z`iu>4?cbipuZ3pr$0FTjd;UX8z7f5S?%9YfmqzbEIXHZnG= z$qzDmqJhh2@m9!uq#Q%r727nsM~>!mTV4f3?SN-Fef{$F|8oJ#wk-uSUY$bekGt-2 z#=$#zE_=vsd6^TRwnFRvRcIx|D-ZA**Xor(G1&r0^~N(~x)~z@7wa@3lDDb0E9?an z+ad1P@}S#!>zR@LK3HSvMIH0t8HJXBOzy?mJLAvn79|$z2b{~EjhxCx0@tQ-ycdB+ z;*)ovRuc6e^`T~No>;|ocQ3dKdIm(iA*pe*ndKPt+~OV3U}&=Cru2lLciYd}I-=gr zf*dyCCRFfY{n+hTPj()>s|B{cRi^<+o!mNxY|gu!_<^XC4@U~x}3KF|M zKNNd4p904(q>Wh|?<4lqtoGU>ieymDI*hJc`!%@*9S)1pv$9o#r3r+u9GI?@znOUW zNhuzj@Ns_Y!7^b3LwDOI`fZ)975~JqQUaZMCLYtddf6tDA6s3sXA`)_u}2pj6@&eN zrq;9BsP)7oKWSZD$Pg8B!@#~H?~cXdJ{W;8tVXX{B7ggwLXLdYwKFywvoyZz>r)C6 zJ(bGTGP8Q*eLIV>*SK@4bIiU&dA+*uQqK``>816%kS+zs#8)=;bhvliX3|luD|-5B zT4#_<6W?@era7XrYCTp)Rv@4MInqcs)pASfGq(F+4Uu9LY(l~<#$fQhi90-6LLyPD z7OVnXmh@`XZdH4(z~@L+%`mkL#EEaa`5c>sXPnWO>`#J~q|{wRE$~j(BXh^8wrT;j zcr%2cP??PhUC#(YdCYoR|L7T^DJxmW@Z*lhE}Ua4)M?vT=lA%k)xqfhmO}J5z#M)~!}IDGPfv3@L>BWa_5`^@ysi-MXt^^Hf>g@3_RR=0eMl8Lb<)9%YRv0aKO=&%(sNnPykO%1e+MJ&l6MF*DRAg!WPUleXYpkNgpb0-c=YWGTc(m*UaCsVrT3 zn_5d-I>HA7{kCTtlQQC6dC#GxiAAA>Uwzz;__%fybO~!%=vgMWoK|Pb{ij*<{uTNIUN$5%`|@Z8X72_@EOeeareUh#k*17;+@#y&AB z;0Ff5+>G6-_9x)Fu)o(n)Aw7hEj)CnuPv*H1ni#d%GVO-0Ky302PKWGxEpj)!RSd~uk zyS6eMr~Y>`kpFP%cj$D}-3?V7<7M5{9+=t|$rNT)3OEm#dpx6x<8ox0DdQwu@~jn28J1)gGu&7{V; z*s(HZ_Ey?Re*k7v^bsRP>ZMm!)-8jf0rX{g$?{LuZ+-*N;qmhDA*JcY48q`0hbil0 z*v_FU%upt5GLaGv%o`dRAGnKv%Hb%>ot_=j1wVC7tb$uRD?qL{I15p{6V$`9mCliT%&W$d7KHUCt?U=JyQa(X@i5 zjK3mave-&ojIri2pfCHq=XNJ%m21Lb)Sp?lQI^|ELlS>P$dUZazYli@$1}_t#Zwaog($*1Bg2{pHhyb`-$$+uJ}~-Lab4Wy z>`;AUzA$zd#ndV;uvG^fl6FV#9^{Whas?e@iN19}PukPQceuPi7Y6K6fWZfT$NY{| zOz*?S>GO-6easUWGm(wRo@vg0DZTguuvudQuG7DIHo+G|#|t(T&74|p@f-gKE0_K@ zdY#H${mK-eKABAd77d}{*|&I`=F83$Z5i?s&7~ysF|Zx}l@qIExW2&N!zpmqq#k2G zJoG3pQwzsjdV-CP{E&3?(8Ob9^!gpa>_+8cvf9MMcDSN2b0@BH5w2_^HlUE^W+vWl zq-!heOBNckxu%;t#mLRTS>Vh)jd-E?JGEp5WC-Sj1*_UHTyc2H-#}Z>KoBWwRHc0a zrP{OpD{}pK*7RQE^?gmV9gR1At?Q0*@N}DuYVG)#pCKByL;s;5!&hZ@f~xgh9mex8D;vp7}m$A zBI?#5`DKT&wydMc)aFm5Kn+xKHn{G;vI5v*E%_ZJP#oR8e!Y$vD3kw+F!Yrn$NyZ0 zw(wanf2U%o&xuJ^%3;LB4osIiV%qx#Y24qNv}SETi*bziciT7YQETT)3Mis=Wy51l zkIAdgBJ6_C(**B2mqO*Tx4Tw0>8tg$vUj?P^?UDf)uzr7Ct7XeE~#a&^q6rmI+S4v z>6Ciw(@-){l=*&afAltzN0aAW|Lrl4q8#EZZO3ngM;tCHq>b1;sD8=&cFE<&rIsdl zN4w94<-WP$#TBi0w=aCIL49a0A@Hhg6^^zxjCiwN1m*@zR|_84_6OHG2 z4CcG-m-fRZ7O!kWokkhxw@Mn_eSJdobIk;j#iG1+A$226I*Bcpku;6<#nW0H_cfWf z)3qYHGCxL%Yr34s>i>D};@FPi__zg3PVZZg{7QC(4Fxy1)*1*J=SOupnZ%GbhlVz2 zM!!Eqz=DM{0n%EUWbK#_QIkiMQR818V*W<_7&b{Px9)&l)Ei>?|7{joi+V^5${ktC z#NAY8_AM}Yo@Q-o?ITwtS*LeCb!HVvLd6oQNcuqqUvD)IIy z@^q^aO#%V*e^hhc*U&yQ;u(P34CYBu?=vY20(%?vE)8C?#{prcQJnK1j$=W&=4~>; ztNYdFd6kpl8g425$%Q5$8&ad5 z*GdML?lk@tCG)tB%G`1FrLFygr&Hh?*PuCDQ2^%h+vXR-#|d*t2W%AJ4Z6E|867)8 z3$_1Xtm%eq_rzt;S;>o{WI2%p6dcx|6`nHm*USoJH+ALhJ6+AGam33G2ToNj0A z(I-qC2mJXopL3;Zt2S~o=p92o|Bv9OwAsVkd83v@Ocv#kVEcaY1AUjcTWfQr%Tcz*AqO~OIIXZ6+b zWAMDdD8t35USsdp-jFk-O2#M{0(mGGm||p*v-)IJi>Q&;LQ%{i#i%eW*(lyZ?Hx3j znLJM%mCXK^{7qCtf zgBW0z6V_18EYg@2BAhCkF3&A$QTd)5RLUoJseP*sirBn*5$X<*6-Qs#87}?IJs`Gz zmv|ZT+%{iwCr(=oku%#^hM6qEZjL}iln)~7oF1FjOm*%?sF;$yr?%8XuAJqM>daFY zrx)7J7wMkI9|lZt@w#QLZ(Wp1_F8FbhJS^=YJqj{uU*kKcv@M$Xi#)P#4ZYw=1auP zw`N9B>bb~%m5j-e6?t9H#lyhI-*gtPkY<|Eap*4HnPT(isgXxAQ+qyA)Hbcbx;Fmr z5r1#(!~D+)vv#9eZP$pum(cjcDT5QW)(`-jj%wGD%9hp+?H(z0al6tc_-pPZsTD zbch==yy198nToYLKWO_Ns{IP?fs-E2K7KW?=FcLS)-_E3fWW}QQ2*cx29ZatK0}9W zQi|Rv+>98$IJfNGCtnOIJ`nkKKc3;;KT?FR1Y;Ky=`#^E5Lq=nD)r}s`!0q~g6Ni^ zeD5PpHcNCR>9ZeH3?)$2lu7XAKx)SivsyCxuYW-Fu@KW-uS#h1{+sTHS>jR*HiaaL@b^y~@VLAsG{q zR^_W1V<1Lh;*<}6L1=se#7+{vzYbYKT}1K_AqBEcu4;rLSviRjToDq^RdLJ_4TEqo=TjaGh zofn=SN&*9tZX1)UBO4CX=~`7kOzAo*`nze+mHtA)J4GNt=uK^K*)GS0DhhImME^X7 zdv53V;um69rZV`mXnm;CLrL1l*dlsl@^w;y`;H}{A1vILh4bos{lICrq0*>UOoBEf zROs+Ns8nyd{{$NVe)b)_zalFaQ?4-kd2j;7nNhYvkXOF;tgOu`8%^Ydh3#@N7N=3x zMVM~?yZwH4XEACvSscLOd;SlznvsVBScz{bBjDCK_C~|A7qG{#;hPE5h`q&SWze5{ zNa~AP|Mbj&Z%_AZl;qm>P{{eA&DQ~nQzrhZs840YQBsa0%|kRXzJZw-L0c;-S6S79 z>sTR+ZQT)cFo2#HAYZD(}{_iwcJ1KeFW|N5^R+%ko^s1G}lKU6~ECOa`1OL(^au zRCd6=RHP)xIO?n)R#B9VdMpv^-3=4)nXLuZVFl}9~TuXk^0x>L`~!EgPx{14k5~mrf*dQwIKM59@1R8 zcGw_0F%&nPuNk~8j57VT^)c$r^a<{f;<@ct*pAUPos{HJ!dapfV;3I074YRUDIj8&hcmFk6X%L=Vy-GcdQu$79!3ooA`L5@3dd`FHj!> znSwxQ+ZEN$Z~ID@0WK$vZpXt{6d67jQ}3WR!hc-AG%${$+k-BK0LXKynuItGzwrZ- zChCp${9d+eeKqzhbpVdA={l@#Y$1A(+9yeAZ zE~zGKfUt2|+9!%Wxgy^ySc^rUse6mPI;t>0+PJXvKzRqzH{lZjsS_WH^qK=ldX9!I zt`tq?`uj$>;ELAzM^Ue`$&(+nMKtd6m*n7jVfRssR&XgRlRDnVeHu@-ZEX8JSLdKh z5S*7&MiSrj&y?U;@Se;2U2NimB!`6Q63}90AQ?HG_l|!P0^frJUk8DeDprmxKbKqn zt=+h{n0zGyBIlC9>a}k?z#z{BqW=Zt`e!>B#7;v__e}ZpBN`Z6oKIvf>dDx$5eKNt zkFF)1tPUbwAC zl3?YG!xw+R_kze5>)mG;Pq|_%bWJW;(;D zusccj;r37MkNRSd%JT3lgAaUdWZq!`gV!T9t7+>SjfVv%I{F7DYn z&)#Kdl~Uqp$S6oz5nK=OGWG@kN-op+IT`L<~cVA^|}3E52vz~WkKZ}^e`9hgvYGZ z)Sp8X8 zif{eTw{PE!c2dfh&-d*h-4rQ{=S8JFXYUKA&Q_c~s#4lRXyd8q{mBi4glUJg(7)yJ zFnEQ)+!o~Q7j^Y)y6=?Kfyw*7{lM2f(b_T6nWC}v3L+7p8Xw0Q8af_BwiG;chQyzW zU*!Nkp%r9$pAJ!H7bYW9cvBJBuzeXzkD~9x665K1a`b(>)s3Lp4%0KkAF85py^e zw_S!;YkgG5WRm+f+zI`Q;iRUGjWI{fE>$Qi zB&6mP8r|kqwKp0q3XgA<0&cdoX=IOC%x)N*YeincEW~omtm0qVu6cS(M|4*sLpLgk zp&G`z+EX3SyverinwL#u*j%~sYwhXmmb zQv;n`S0VmBMa)EoOfe%lC0S|IU_l3&h8dPOx=}Z{UC_!$?qqD9iB@niL0v*G?sz;p z5VK-_!$qM3$i*r(*Z)s=aE(qkROV853XO)APBqzw2%kBLU$sQCw{Qs@n9ypw^>pC{ zOxqkUd^-khujS-7^_mcWP4O$^5$`%f)#pu0{wVgb_%>%M&fq4uQ>UU%3xi~b!Lh5~ z8xO-;%hKv_m!h(Ga*%~A5p`ExChGZpc4v9c>AwBuX^uuZ$n4q%Dp2EMy5(P1k_r}F z0_c?KUoBDtq$k9!PL?O6xv8i0Eis%(F1T>YI?+_c_?%lo{JA^GzQY7hjTXDpHLq|@ zHuyLA(!H^^IEXAf@@?x=eGAwLP3?;Aqpo{LH#|i%GvM8zH^rQu`hPTiXH*m07w`2V z<|;x|6p)f!3!0s<-}Akv#ilNyTj5|9#l=%I%mAe0nJ zNJ#Sdzqj6pnKiR!oey)?o-_OGU)ii0eqfHJk@hdQQT zV}^DuV`eYAHyS)dOjFy_98zwi1_muh{I*$wBYgvj9A3_6?SdZJ0f=kf7EFZ#1C<&r zi8ul29l*CNsc}t$fOOWZLX59~EdYd35~`#7EkvY)+Q&=%&DC%bw|!H!6);R{Q;=%6 zlfsQb0w;o&KXTAPrdE)~p#_Bgl_!uPUn}G8FHnh!e5;m2O9yx8rU8f=@hM`MQ@!>R z^%He<(09Ff16-##s0JZC6sDP`LA)Z5N$v7O2F1!cpgna)u0WZ53^n{L;3gk2^qs+m zeNmyg-gv^yAN^{Jt`d}_)yw138^_!?X&;c$Sb5jmR@NlX3Q?w2)POWxRZydH zjlRz6`z63DH9uhwO_9%?!k6gjuvQ1hqwDetx6*_AM!I@t$L;pN@e4Rgm?18ug)Z7= zC$R*0l0&l&rK^K;sJ#`pgZQ#V3tz6J;ViH;L@au5k z`bv>*Gw>fkXHPAw0%ObW5(F~jJ;MX_TF=RSIb^(erfREwEZ@M$nZeqcH)7XW95IFc zE9WI*hb=cq<(jU?u_rbbFF{XHchg7TT6#fb`RCMC&kG>2 z$W53HGoGsJv_%JM*(!nrbkC`I^=rb+b=NftrE$PLMsHo(C1~!>kuzRZh0&R zj4~r&px9_xU%wwgxyG&HwJ6h#^&1xiT@$2 z|8OUXLOx6+4HRsCt!9bud!prBxyB7kzM+W4l4&~J@1%cKtepCIH{23?(W z>5H%Y#W# zp+%of6ikUDCE)R8P=v=qU}uiB%#xJFP{E%j?3Zo;oquvxiI?b!|srX%y%A(_EX0urp?jFJ)SCU3v7gKNl1#J zse(QzwqlslZmO|(x}lfcv|y#Nm|FhgR~>z$6_9G6V@RG*mjjkegI=y3M+)vM{QP9+`mA3zk%gc zb=yZrk}MMk|t{rd)nMtuanxU zy#K~`{f)!agH}6A4R+!X-+1MEmN&oCb?(O@3$FxGMo8V!M{qCDl&cf5QjNB@&`50G z(B~+>7Ce9xEE{H^tU#2;RQF7M2&qYi@Z3vF5~jA!?bZUiYJAe3cei7Qj#X{PLP#I=uQ4?}kTuu|vQUm<9t#VNLni*<={wT4qZrn#U-sPNoU-Vs} zI263Rk?c=)dtcmZ90B`-UHxS!aZTP`U%fR7W*+^k9rta_^{7aaBm-HxHjek`Yo)-= z1D`SLkIY2|aTo^3q%men?4bSVYoG`&T__&fqEN7$0Rcd}i>#n#mNvqkW*OU@b$qKI{+)n;VDZ1gOE-JSKBhAxzLVVR<2AtCfT&g=?a}4KLMeA@nUdx zO(M5u>FQvwX|c?#w})})q_^k=p@Z8iM9V%eEBfM1TQ-T5Wz)xl=%?EsPzlz>emfSF0ufjrkLzWoY6KCM$GCWF;g< z;tpTI6T<9%RebnG;ASLnjuy7K3m9FFIqQA-!+@L^!|d36CbYw(b=&embP<=P7J9lk zQ9p3`;zu_X-R9I7gTQFG=DWa7=S|TDenUA>!2vyVY~KCp@tBXf^CjYv2DU{f>M&%X za&EaDJE?H1^FIjmTj+9nR&9y`$__yg-){vd=vG3&$3xL+xhnrr+*FQ!nJ*}wXdu+L z-z{SAZpm-ZSG_*4%)C4YGV}61p?Lwto$; z>GiNJ(m9jg?=;)MDR~qqtH#w%{M#2hKI7@3&bmPGmeBPmnTvs3&jK9B0blP4hqjN4 z`WW*vta;K6O;wb2nJS5exJ^pu6W|@#)f;0%AGwuwjMY?U_>i+iR3ss(Ig23pk6$)^ zC{NYX+dorE6Ol2Q8iW+iN6IQrz@EY~L`+G1pcQ{I4&;O_|Haupn69UuG86y3$4 z1I7{uFA6Vsf)EOzZqBTd`t^=1wAEXxDI!W=Xf4(;indyqVrL!kiRT;H{vN)w6mK&C zoxD~L-YoEL$GjL^WJ(>-`oqv>(+3JGZ?>#8*&2fP3fuc-!F7%*bs<7)-P|wNgBQ2Y zYNqif$I3lpPSAEQ5}f>><5N6KXPB=0lc6#{o-E-vrWySiIGDaB!E1qb5|n%T9FS+Tk$ zM<;O`NEXS^;9Oq+3Nko3;tK<@j1|45XbpAyK_%5O_>ob3;ZN(!)tBcA>6s-MsT2u* zL`Id{Wn%fHCezTiUqPTCEQ$PvPHyneiBwUHQm~q_GykhyW_^qBxG3$T}2qbMIcZ6D($0s>Ww|bl&e?msibmAj0})@|L*&0>;0#=sQzHiL9x-X}@Z+j}yNVV&EMvz?IVl}=VyTJ7B zl;SLUgh$Jfoivut?R?TA`?_TTlx2%Q(2Wzr)_lRGf7G z7BR%KVj14q%t*F0-=IhX6m8jceC{~mON~k^>fHUOV8c!a8l_)1Ha!ARR4Q^qH0o_b zg{O?7h+8L5bw|A|V)9d3F@6o;K>Omd3Up+A=RL{7^%q0vtz2rYHjRgI&;q7WBV}0S zh;d;`HN0(K^(>*^6Ohy_jUD;3h#YPXcjBa0JDBQQ( z*BzjOu#8r-K0P1e0E-oBQnwn}<@05JH>D{zCw1?KIQbk{%;c!X<7SGa78#jGrjUje z<_EowRNFht_Drhk`>`LKtcbw^5Zr8+V=^>-&uOOg@suyq1o!KZ?8MI)LTu3qL9IBK zL#MS>1?qgX)Il`t;TCl=Qie~la;ZdzafwpFeZcDkpByeNC#(R3YX zc+jOO;o115%$&lq2Q19hd*7%%6R9p^)9z1W5(5%Szt{)aL!rZM@}1Au)aEzh;@=s| z5&5IV-!v`JKg2PR2vQ^}9n{;%eE;JO3;r zH)!WnE!{^LC5DKD&g>Q?NQd!GQYpH*#FB2yGXl6ph*UlLcf~vrD zd0*A1@Yju=eGzw@Y!oTksKsOGY;e8X=tPg?DE$lO!$gMihu#69jh%VvFQ}knxeZvL zz}E4DDHD~LO>NMR>5;337D`EXwfQe1fZmQ%f^3UH`dq(_rGb(*=w7dO(wVFg(j0aZ zo!WaT%8LgQ31-x#g95n|D3b$r_}Sxn+13aT+zQDKL}<5X9Kn_vT8*L8rcla}QXB8c z+Ihk?G2{_z+u8uJ=uE2m_&KPOVgl+Puy#0bYxbsSz13@w+ncsj*pg!Z zrO2ATve*A}w}*8W+z8qR#du@L2h)W81v?g^hL!ie7QZ^D*&lSDvZ&gZnX`I_XV_@gYBwN>O}`m_4Y>@zke3)0Oq-f_*x@Uk#n|T&CeMk8o`f^_ z=un!7>FcM|8pnW2k*)f|{bL&t6;D_&Jn1cO45h^yZDdZVop6 zSo2DITUWJ6{*}|}laGbw&+Z!)kKa0I9(&D}k!@^`$#yDJ_JU{83p&L*z?9^#%MUik zfRjsBNf}_1&G-e;^#2HXRkeu`yU)j1v)ZMr&|i73D3YD?ieu^2i_%r#hMQ*OPHc28 zqSHNKJx0Xq!y>@Tc?x+=xQPwT69cEN zi`Xd%cwfjK%~{$X>Zh3bnNYV7k97MbJ(jpWLccM4PnSPaoW!NrJh*pGl~i+HmsFt| zKG>BV@rM6MD=R@SANv|-+=q>ku6vioYYe@VmOz~xq3(&bk@iWlNo@t%7NC-Jf!(CI z_PwF5cN1O5!hEP^i&54S+;$V<7ftjH!jV--YcLHGFs-y4m>f z*ejJdn&{2(JfObOhVv5Ybcsa9W6?bE{oBxo`1Jh=OiY#SYh`RknN0OHkfL>j%z=bm zwAFk=32@nArF;0@k%{nCD%Xc^Ac~3=56#qBd9YF)mvH*bP1va7-jV&(i@V|$_av*@ zWV>+qW$1id^H!-D9?IE$Ek-p~J@~ds7;Wy)U!%xQTFC4~+ z#ul>Qiq3^!!hMajILY`Vve%|Dg@ro{XuLjS_j6EilaOSrI&{DXpEEI{HD=zdSSu-u zG|=w+`{Vty`0Q?GQ@#JWfo2D=NILtPYU2uqTp`nsEFb7!3>@2-lu)}9-Vu~)x7?JT z1%7fkcXcO>R zu;mFfz9h8;wfAW4=Wkbou_`xzn+OAAVzCm;?{z?1=xa)SC#bu7>griM+)w+MM zxf14xsCO7XWnx40R=Bj^Bh#Is$7|Mg#Q*Fl^g45AfYq)O>PDBz@r`DQC|1SWjNcnA z1~P8l%T}9$eIL9A*VoeOv86uwzQPHnJc<1= znv_iHdqffT^VdpL?Yku@)6=??l$9%|j7b*d8FXB}-W)jfWmQzt#G`&x!FsXt&cj;C zmmbH?JiNRfPjqROQKZ(k^~K0Z*d>#Yq~K5m+SS>SZ=!}~58uwGcjLI&o*^jdw`MyH zo%AdZhAsl@ztE+l$Vjpf^5L$4@0RG+?=GaKE8APm@BeX9p8y;bvX_Y9pw9VVMeQyA z$s}fr!@-S?BUR1AgBVvUwC7WT23|mm-$E+nDMi7dtOj**CDHO4?_xe;_nE9`8+`4X z%OJe-A9}zi)er%LEo1BR5~oHPFuU9?W!O0K@_A*6x{tRld{*5JF#j}EGTcv&2PfuT z?t+iURd@5JLmFZC&8=M8=2+L=RsnjfN;X`lUAiE`v`DHR`8`& zRc8lHyZaxu!QxNm>+`EoO|9P4U!choVX~ZD)K&S;8h;Pn=E3C@6|Q~L|J?E~$6RyE zM>gg!QLQO7OXrFgF@gCoTkgNPF6>D>W#OZH>=#oc(z* zVq?&<>KOhdO&L|naGkvgKzSb=y+#||U&0shh`~M1p*xXQuCL!d45f*JMMbHFzwCQB zLE2E}S4o)z2nO|F)q&uXjsoy6#dqaPZKN}+yzUJ86UavkrrIy~^j$psG*wPY=*^#0 zRa$BY^UON*d_KNL8p=)#y4A3AB~;2ogd*EuGqTZ7^BYJzc16?X=(zpeL+DNp?0vFppN%mDtB$vpX=j^bQqmOP{=x*6KpWJaNhQz{3`0$#EIpLyc0N zU%li&%OrAFSHnxjY7t7ZDY9%6M0L8`6#o^~U`ACg*_qqV*j8;QW)&v^vjYx=h7wQe zEGE@4n@$J%K?8Poo&3|i6&m-OAECn$SKhy|TsN^z_pAv}4hMV14prHU?8UatziKw4 zPrQ~>4LC%(N>n)>Sm+J4C_;XybHShJ^^gseelHZbmNckyz2)!PJmekrXNF{5V!Rbv z)bL~q(2J-xeeK9k*KgWy3YOQ~{b;dBd zluFyle`y9v#Isi-1>0sZHIK|TKR#^tqvdhXc zYpF)8TS(b1;AO4|aLmL;833(Lyp?&&5;5vJC+gw5m#QHztGDmOPqyeuT)IYCs}KJv zWoQ5c8(o1sdeKOmm&1*d5R!_L1>LV2e<^ErZV-bWm5%uGopw&+4Rqkj7 zY?Cjxg>e?`7C|&ZEr#95Br^_kh2$8-UaO=!_`A|N)rsw%M$ma+cBm7E*D9heMwEpf zqXPq@%53J6hTZlwR*!HHjLnJLlh~|~yQ?91@a!IdA2u<(U7UoUI&w&w)7T)7_f>ft z``{!k+0?$>>jz}ayZ8MSJG8rYW{?HJi~$#_?L7e=D|a1%LoQvdE2)uHmC^7Ye>}`2n;2w z;r|sayVYea!qX&l^^*U;+1LRQ&(?5($oq1bxcWcx+S7Fp23H3w%GD`>#X@&+ub@-E z(Ux9hC?1t#12G71k5Vz_xF=%Dm?^rpi2dw6)Q)rsbO?HC;C2@H zqp6VmtjdlaIG!hnASh%JynDu})KLxpr&dagPP4QKG%v*+ksm{26>E&_k7eG?kO@y76!LYl(IvCxO zitjbHl*#D*>dc z!c|vXLKZgW2O|Vl+S9ml5ypsANOH{H5LbPoD*!F1ds|_Z5wA9I24fcu%Yz zn<$z61Q0IQ(#b?VYxvkkvx&X#^rqhXLYZpwEh>twg>y^vYms**1ctult;_Uhb_YA* zw;#Vvzp!h^tFqu{d4|i+1lr&l&*)%l;?QH^mUZwm77AIj5Ve)ZdwP@VvWXLZhjHhw%7m{RRoQKIuIYW*?g+O}kfdvJ6&jI+ijMan zMY@+{Ar4(P)0&*7I%(!=gLDglaL>g<*>>>j3K`9z@i#7c;S`NA^8l;0cETqjC_7=< zGEZ!c8I_sLsQTAG9Ype=V+inPFxq52BnK001M`LKsi%7O?X1_{4t44pZOYb^nV`AW z?cPU!k*fX7!D!>R6BCv6$-$c-><>vzTKQ=T6 z)mYD%6NIS5pF&@s^%9GYTznHW4)q;}z3xh+J`U4ZEJgUmgV8Q1hhY^((z8dIL^Il0 zV$8S|UhZ~_#umSO<&x~Jm0^X9cCcDMw-PCoCtyFC*@P-SE2U~4bcxHk?4sQ$N2j;S zoX{Bqku^>Y=&zy=KVho5s*+7$s^tz!)m+mvW5c_S+){h2hQ)nHCwk~C2___$gEAKw zpWDq84~zsy+%A%vTX$zZYf6;N8SXwfrdJ+aAj06atO3hVwI?r5P`)^7EBYdHS=)8z zcv;&mAJVdN%a=3>Dgi=S1GXB-8I40t;r0qOHJW2owQ?Hmde`%wU~`EWZxB8z_!L7_ zKHfb}@DloeBRyEL2%n7s%7Zx*zea-PoB{YHvoRswceXdsmse!Ikjrea(SH%U%ksT+--_w@<3GlI84%4aP~Hwc%I0?rv}eSq=sr9H4sqGk zsrV^;DfFa5kku%=Smu(Zypce7j}_^9qcqsN?clE%f}6dD9ocq)9s@)DE-dbM%Z)h_ zUwErvS0Y;cbhCJOFZN;5^TKXeo;Y+s{tX;e4dUmDfUnXKJPSh!V<)L$PWaD@h88l3 zMdvUEj>GnM@1(v6(~w>-`ZF~=+&;i0<}+b(oM~MomGL~khmy~sB&Rxc=Qrow7csDs ztd&H7OK8T*qOswOKvZ?jlve^3SntUUX&mQBjB~z>rl3)qknkWye8e zjzwA`Dzn$W5w&6>jaZAFID-lDxVBqt{Eo_7peyZDN%n-`c~&r&UxpR2uVgc z5A|N5)Jd9@OTIWEiZk#yG_w#n{wq-Rin)Je|51Wp!WCpPZd~WFuT`Y~Fb;06u5hns9s-+VSSBJSLvnS3LbUge=|k3W*h~xhZDXki1E$rbv9; z(P@Yyg{#%raorbT3T~(Dhk>Lahs&DTX`FL}j)r?o&=)9N9r6hKjIesrifEPnUVK_C@leH$~q{yo}s>zX*KX+GFbw z;{pG7KoQ`E?cAGOl$Kl!Z(=EV1*9}W+m2KLQP(_N>Oqm9y_|JxiO6==*+yppPkcWU1oq z^B$(+z4T+;=HX!|T2S$3Jssb`e4Dgp<<)W*ZK`+gCyco0rgc z@I!zTSGX0^{l>Z*6u=qnn4{3K9d{F;5Jf90k^@*F6|>0cTTk#lY;rE~0+QkZGveinS|jAu~0VX9Yq&Tra0 z^fxiv3RY-Gh?1nx36t+lwj@8SS&#=J!H-ffiG`5C(4P91A5x*U-AAiJcsfJv!dw|l zCEc>#)oXPz!aMW3{Fj|?brIy121DzvT0Ix`a~C-!W?kt@hf$y#}_`2;>DaCGvq zD>(y$O3QrL3u#L1br^<_O8qCF*1-e-;uMlt0UFKIVham`6sUodsSs==U<{kin{MT+ z`{_h>ZiQ9_U*l_ut)DbUA3UmK5IdH#pG7)hHY1frl#F8nBc7c%kEg!sbxPRRerAI_ zOBkYd?x*<=a-eP(C?_45|D|W|r3$+i*tevQ8g9y#933;u`VMZ`-KqNI>XLQ?^4CmI zMX?klN|ui&Z~9N1p^-vrFBir@t1ZaT&>eE+GR3L*sCo$2KNLzJC{N<)&r3#a&V$=( zc-7cfiQxLV(Dl|qeB*};%#(N--nEd4-J*#Y4rkE5Hr8lj(q{9wa*B9(u&1oT)V z*itJR$(CuHd(S)iLJ!Mae8zuKh96&Cu~4Y<|G5CDCsb5^70P(I0_2yG(jp~y2olR2vU-#Gjs%7Pz-`5Dua$i-$G8d=|uN( z*O@&ln!p6Mj;h$upmcnY>vr@{svpyGTIOi9^&MSumd1Yx=sbvab{3l(54=;Fv6qbr zQ`J5b6Ll4;5APlB3Kytx1pD+4(MzqA)=Z(^^+ERFGR~HfoLqc27x=lmU8C?B%!C73 zF>(1GBm=aQxdq{Fy7ys0$2ADOpFq%pq@w%%pTO{>L+J)# z2`x~JR^Yb;AypFvinpMg^?fqECJ+eu&I2wF=ZjI{-{wx_-Ao`}^|oJ?KXz#niD;nB zW+9l8;F&wKep#vROv}RH!#<)=zJ~W?YGs#>#^I}=#RoWKbH_kFmUyMfs0oL zDjZtgB4&Y2uQE1M&;EYD6ai;16VKt^C>%CSv>$N=USX`6iL+*x8`xMAwzRM>bo-%X z;Xq08?;4nFw%A)@7VaXRD`*ZTp#bpA0TSMdE1I9zvv$I_`*%083J}A?+u~M4+))B# zSJUdqRG}e7YA?yE3>aY5xc6~a9L~R=gCdcu;oq-B&|sIO?n#Ba6@^;l_MOFth@%RM zK=OgE2zPyifA_r>N_gw`Pxzh#KQQ;ngvA)LtYJwB{kcdRbPkoSZRvX=f@l{XA_-P= z#jag(Bt&8Z!c2Ahk4S@d1Y@#M(qNo?RxU8B$#Hh%VNyPxCG6t2Aoly+H0nd2Vc_v= z?-F*cf`D>c3Y<}q4j3ZicJsIomDNV!8fFD-C3o#5)p^5qqmK`u9l1wXdCgf)?bZ5f zakh*Y!*s`@bFFH%0|2^s(kjPS?cqs~9 zV~=H3|Bm9K-~x`l6EE`aw@*U%4B{=X;)immgqaYv2Bn`YvzIk&u8;dPzDP_fZ%Re@ zYqq4cp5I^#;qu&6U?Dz@{G%Nb%R@vb@$Ci4rv~;~!G|$fvphNYD;@B}D+jfy*IxXxmnp{QdGb>KT>KxBZge^7=eH0K&&vnt zk2qDuULiB%*NZX_dpzD@0sjxu&onSRNKTiIkkpQm+)zw>5fGDe0=a)HsBu@2z49L7 z9#Wi{<}JgFv6G>vmg>9s9#}ppzIFVs0}?qHzr8VL)uXOjo)oncb?C1ML7TB>(UMiH zBY^16hBx+>7H^7`3HCf?&Iv zoNgE8)zu~RpB9pIU7@bs6`-9v={4vPhvf1&W@ z4dV0JeKT|G&IYT|_lvpAD!EQBW;pkyqY$gt#fkt@bwx=$v>$HaegVCb?kS9EAD&lw%Lw1J)X@@e+ITL08v_~)$W*$b{QK3%3Ip&G==G#-}%(=D&*fIHD| zlr#8>5`KQZ^!Fm)H*5B%QGban0&MW81wWAYC4}CtOh_lFBw?X}_^RC%=;heV7nsk*__>>1;V>c+iXUd|=wu)ZjG$nhC0q#7d7Ps? z4)n$Y0?Et~RuUBxe~)N`VA3AGy3W}d79@fQW1xMzLOtf=1l8}^|MpvHh;Fue#YWi9VOOGmi9C(u z5E0=EW3`>7?rr}Ro_GH>7Mcw{S5?wJa0~PJGdbDfFvKJpxV;&cV%ovHH@przX1Qssvtt>^t1Y&eJq{%yZTUQ zW3jq%wB5<-IoPaGImmf#XOF}!d0EDcq2?Ecedla{HD$)siw{QhDHa*BXHU$d3OGk= zo>l!*vsj;{qpZoo>^ChWS8}fdd`j8@)ma|@SVec*n-|c{i4ic>REg*Wx|rH~$Uw~S zW#G(2-8)uP_U{bua+j)8X4l097Wi$g8BrJ-rDgRYDx1H??>@AQi%@v{i~M(d6rWhU zbkjqJ*{j7imtZMinW&=C)hdhO2qlmH?`i!>F6zKdArD#0DoMFu#Rv74G*PcrviUDd zB(moZ?gTrwL;v@9`)7EwTpJK3m+D&mC0V~e+7iRja!vkf68&=Xg7>9^Ma{B;sLmzR zg?wQEc-*P$y?-BT(b7&~Rju5khqusyuHHE#H`~W&<>TAnF}%F7v&im0e9)n*d64A< z!DN@6TFLd_OXgR7BvrB*!~C5prBd3U6VdsAI@?Tv?1SnH8BUIKe=wuHF`5SK61|Tq zYkD)OE2-W)g3TA=Z-}gBiYu+b*KduBRqzSjpt5d$nG;8b)_r|%Q2J0|BA$|qI~_qf?j>E0Vth-tCOjqqP)Zyjdh zl79KlVC!ZxC+^L~&p&2LLdJgZJwvf=RSK^2=(o>9D`WipP{J4%Vv^_QsBh=uFz~a& z-dSeU=vtm5MM`tGc^a{u0ZiS$riai#p7^C8FhFEy_Bc<;+ZId4%o{}fN7`0v&*XPd zGI!E?ll31l^0-Hz3S$nr?!#$yg#e}^^p-RNanuGism)3yNCY5f&X_Aua=FM zu)*JoJ0iLzSzqlY*ILZl;D72*Vew^g`zg`NBO3*7dJY*aiWU#NZ}!L|fBYpisO0+; zm}M5w5(g3v97fG;vx#H}@ci8#RAg|FL){OGyuwPmwIysv77O9PR52He+EvH5{- zAZeh>$^mgM3DV}kzW`nl17~1^qj%LCp0GOiT7PW}Rd8x{<=jq8V-o!SNUr}-J(OY$XBJpkd`}ji3zO^? za{dv1H{cq_{8vqn$kJXAp+rls1z ztS2}na8V}!+4%12+_JTv*Wc>2F9CmtFAuYa23R!nii^#yVxE<_)Esl;Z3cTVyI>?k zJWE%p7q(vL6@mQG3H?jqK~1%z-;M>f1oU||Gn(N`c&9v)p{}Rd!eM8Yv2r-+s(L!I ztgO$6rpnE_0hddiuZ6N5(AUq*LZl+BQXq65EKjtBx^T!&VCQszs~H>p(Y1`e@W`~0 zBzZ$J4!ZZ~eq^ds+f-K~sgS2Q`U!d{8w|D5WIOVzt!299AC0<33QZb0aObuuo-BlKm_fr#5A2_0#8+%f;+ss_1`N znTU;FbiTfGjaS7eavLGdG*J4m<=coS)6)uhwLJczHH{{ZYEp@er`Td|2iQU(SXs zq)jp~+0JU>hjh#WbSt>C!VY{8lh1bBq??itjBMSoNtX~uD zp77^s7hgApN*0!dra29>iH)qm9q(U&BB4_5UJlP2QX@@6pbuRJbDHibZ=rO9X!(sr z)fD36y$~%f-yT$t^xZeQ$C`(c)__h} zu}%kH=5XvxhrICRISHqm!m;sETji1wsnYPZcS15qfeX=69l}x`kjF@cQvW*@sBc`P z%XaY@a=%-{&0E2XNy4$h%O8Z~36cj!N#o~;|G8#!@>CkrPMgOV>_2!PJ=Z4)oSBJ- zY9Ex&7d3dNWmgSpOZ}>do1ZU+gK^G3MUR`}vbf_Np|K5YUA(H%n4xt(ERxliR*KR4hdRvR?R&<%6iE5FN{g@4e|BZmDjYwaQs$QX2=AIv_ta_5r zF-Y}%bZ1mGm}SpxD%G1k1PtfQ0A}A;V&1>kvxuJChb&nX95ag+65F9&=B!?;^&^)L zdLzK&ao|cda4!MKz9P6zi=97fP_qu;u+uwawud+g+9yafSU@Izay@*Do^-3e2BQRb zQx>}^*Loq(0tF#_VCJd_-BA$V(|Ww(I1@z>pCek*c?ml^)>Y}$-ia|p8H3HU>2>Pl3L{I*H6 z{Nsqho~&CUVQR=U+8_RvABQ=iSkZb{A{#zkzG8N=_GeYolpgM)crlsVzcaXeR^pZ} z9Ee+`?mfyp{7)$0-ZM#!^ia3}J%zvK!3mJLPoaOV?wD}8Ad@I>YE(6J;?Q7O+%)wc zys$onFpcth*Hp>|EH>I+h2NQzqQQi1&#bBNF@A>bQ-$eHpnPra&*xVj{FEcAT0oHv zyFc0!H{WJ3$Gp|&Jh`7l#AHSc;YPGelj~#t6@z!AQ)Du^t*e z?Lp{I{inxd_I_EV%cBx*(c=!-q*=&)_>XU<;T9|U9!?;93KM}VQWX)48e~kDWo~4> zzyxopw? zaC&wItp6g|u}OJe_5p4f0& zTw=l>6H9(KgZc#_MfHB{(3V1T-e3*38b?kXAvuwvNa1Q9<%zN5nU-n?1wer7OuKirKniymS~yX96R7ba}X)Pq88Zl zP3~OJFfr=fOjI3RzF%-0^sDliaK3&=~gQ%9N~{0;6vLSpEDdr=w6#ELZjb%ayCkO4%%A5 znUy8mGrC6`2C0anevAyni~;|6BnT6A+zD4fWU6N`erpoM7GJyJKLNADu7*g^!z+bX zyiZH^*-8X3FU<=nXGKLccUZz==}$^i)Y?PpqxP@VP4X;$AnQx5r1JT%e{xxPDtu1K zOC8zA-!xeDZVDI~`eAUKFf!1`nz04famUl|HfUgeAO)dAQ6N~Glj=v4F9ofAWSKw` zH~p)}kSzzO-QFh(`QWZ4?rQQ)!W+rYg}qX4i(-rq4WGad1vnz;Z>F6WaVpnhxLJPp zi(OYd*T;Y79Y$~EA{lf3V&3_1;a8hY`KNpJ1ouMOA z>F*OIFKja8VLU3XR(my*NXG0;0Xy!-K$tbabrZ3o#mrU;K?q!nl%+Wd)kxM%W^Rfv9|~ zca4l`6_2FEN9=KYmQ1cxu~2#Es4`26ZND8RCbiQ-0gm+6BjV-uRhAXwX8qtQ^50O~ zaL1h@#RJhKS*w+|o|68^;v&w;C(-L4s`baBa50l{sT(buaU^}1ssFa|!|+poN)MXn zg+te0saVEy9-N|z!l1`*yDI9j`2d+Rx0+K7QlCpJt~H+VWLcAp|GgJckGKtNEu;P2 zh?(6F)$|HMU6HpFLv-^!2y+fjvz73wc9H2<*R?w*v~By1dcntt$D?%RO5{gCT!V7bR%`w*d6b{YRY zem#p+-HbY=3>h0k)S;e$&Mw5|=EP%&&U(&S#)3cl^m6Czd?>iq>lz2?EtF*Tg|4#tz5EAcP`A8b<_)1#W^&b)YrhEuZVvqb_$(^i#fl>;wE%kk^!*1nwoZ12$WqGv<*|D-wR=Qru%+s(^fXu-U7;Ps@J)K=k> z*fCpz2YanP9v&X}R*t2t*~m7*3){_W=s=vYu6s%7;K^}?P970|&}#cZZ|POX-UmCt zlIf6@v9`l|Jm;9(JnLf}z^S9;mF^qk%~>b&iJn?N*03e~JZJfO&VID)^}Uuh_r8#3 z(+}AFv;V?-z;K8iscY#~^ls;6A5R;)pK0_}ad{8H-r-?I-s&1cOmjb=M?`;|#wuSz(QToZAf!1%ZW8-W7JS}C|zViL1 z|6A&oW5mz@t$nX_oUmp28@skFe~bej92?ZpiqH}Q6(yiLVn^@9`U$AR^flRNa_DhJr#J#m)4VU@$H@aiGd-;VOH z{PA{FK6*;*ePrsAbn1kmbmD2N=vtjlJk{2xOc+k5OjxPc#EC;`^28Ns>coL`#>9bi z)}+34_T;{F?&Rg^!YMs^$o$BZCGk*d=MU)8-1Da0m%6TaBrTuyrL<<=x6{U+-5N)Y zX%%PWg5y0NpYi9s2ru|`zWj~IC2}RBUXoL{Z+lq}=!Y7ib7cOv;|CIZ3;K^{gZxum zy=D^_O8u_~_L81)mUQ6Fa_xLBv%97bBwToHIImg(2BXon*GMU#szuc{88-K z#^KCsjJ#G1l=~KaN74VLBi}dL*?`Z&&vV9*<6-#?KCPWhYi9$xb-%$5=-`unoOkhk z(bGNCKd*HNyWn3s5O&dv zwPL7h>iTK-s!h3fFP;ARct(X^!avUQ-}v5{{SO~`Y>8K!`$&@v=Tr7A?yY&M`D$H= z_jr6JlXWZZcToS|-1kPu37ePg+qHSwzO-rCz9i%3ULTk3OGDTGlO86!F8_2|J?}fV z4?c{-&sR2&?Y_oa>x9p0N%H00ro^7o^B$>A1q@|F@8 zXvbolan5L(eg4L@;F3?MZ{nlGZf)nY>89=%bKH9OrJH--%xj4a#e1{wZCdt5&PT$+~Hy*lRwZ>6s>&(705{f{Hgv(Dd`)^+_T>PhUWomwBSdCvGM z*#ck7-Wy>@Vu;vA%q6~%kr8vT-EPjf&?n9dEQNn9dvE5P!v;pzt$LWo{=>fP<6=4N zH_=#U6Cdrvm!>$xUZo>y2e?RIjkVC*qzAF}kz>-%zUI|!x8o`5j`7tPRL`5K`>I^W za*tZyy*p|Ox<(f~m89o!?^t}rr=!mUN0Y60ME~a=g1_VDxr$@-9sF0Hk8S_Ai?P~v zJb_~w-E$AO|0|z34r<$d1CHa-|7*K`q|X!7SUt+~81`H60Y7qpHI3|t$jf?d*R!d2 z)|aD}(X&lGH>;|6wbSZTf+IaGZ#v;v`z&KHB~# zTM-vLBbw|8KlTwz=GO_p}_6>8uNbwW6=Nr3sy-)K~xOAK1SaG*J1Sk%{^~) zoUoy1|E>*7_oWR>-%J~N{95{E+Sv1Ex{lruNF!W%=77@rXFri{==`zCh@A6_46e}S zG+D-*oTSI3m6qJ@%@zz(9ONM;?$f=!rGuvS}~uD8_wh-I6`U4Rih_pGfN# z?@1eb%x~C>xR8F(WK>(^3--bucr->iriR;XdE6R(@jbPLx!NmrL6-Rx19Ab`9*-~9 zGNQ&sFX)t0iHZ4@@q&+Sz;@d`#DZ+Vc8tEKdKnwy=cC!G`kyc(FRgmA53*-|m7~f+ zS79&b8+ze0WS~>`DfX}fIpBjl_I2%Ys73HV)_C_9_dU_Kgbt%}&yjl*^g>o>a&N-D zNB9Oi{web{*lx-v^o8G*ueu+)B)-(w9^1mNpb;PCU+jQiN3zGUj6Jd)SfjS~Ma|cH zh&k+uKG>~kVe5$ce_!YeTY)RvD(sSe!7KTIY+!R9UULrMXXL?cYHktx3I}vS1~#E9 z#)eo+oyqf1oPLJr5(ecHdiZ8F4?Hc;f7ZeEAv%3eWyywMs4uN2 z=%Rh#3H**L=v5pLKiP*3$f^yJ$G*yhp4NMO)>Za@X)E93p*QTh?_o!5v5yV5k4yiP z?}{xj9C`o4_wdzyLab`vwQi7Kss-cs=R@FW?a6HCK*tF;E#1FsefNQMAFw613t6?nx=l7?%s5MbEzeRP@&HCX$PW)@3m9nBSjd{~ z0i)A`hx3iO=@J|@mWW%UyxA;$+D~=rm^dF1d%{=a?yhh&)HP;`Q=zs|3{s8PA!fezsPsa1M-+_ptY{DPUN-Z8Q%uwF6tI^jWoyu6y>9Wrv|{e}(t=ArlV+Z`DGndYWYt3Esv(#^yYcq&$wU@{z680VGlgEN3xZD z_5pfIKM$xc&}TMsY#1NrB`?|5m>~y*VB^sT)WVbYe#J6oHsuQ zXkThs^m~n!HB;f0%g7RZB$i>k={|hX1Uj|l;b)JAxM~}z4#Roc080$K?>xQm_X{<9} zH*~$FYmBm|bK#S{u7hcK-cM5hHQ#f-EGv7=%Q|9DY<0brvR$($`>LO?Fs@?mc0_;H zBl2Xw#;t3^THtDDufkKvc#LvvEH1Hj+lEi}a!gf^;x-w{T(%b}7D$o8wu}!=K~d|Gl%msrS3m z7snj2c`NmId@l~J@&lS2NPDjSn#Zp0FYh_^gW^m2T4PCd%JqeOV3gh;um3yUHh5x< z8lio}o%&X40I|?faz=QJR@Sx9+Fe}7Dhr!Dx^Ji%9m8Mh*9I(*$?+_6!TZ9aS5>Q^ z@qWx9!z0B*_`)w>j=Yy~3f}STqeo&C9l0JA7q7#XW`T?K^1Q-R$WVOEhW7yFTIjftA6}cB z)W$EX|4}!F6L|)%GXAA6$^%~!3m*&l@GZ;BK3}795FK6g^IfBh-b%&Q`Ey%$zLiFN zPsh%m+gkQJ-_i^FrM&4g8RG;0=pvV8y^G8aY=|zI;}Y4}^SP~^F1j2uWU#OH3SHSZ z!vvo^2JV;WgAV9yvXS?)pC*SG!5)nfU#BU4^0&a7>0yiZ)t1X6#%7=L1A89x+Bf)B z#~r$%uXpyh;w`BD8uF6QSd1JG;;AEH#5(LCw#ZxL*JDU@l|fFzj^(Dn7kiXP_t)?v z{uCFAht{vyS>$;S3^_-l2bcI1^V&Ac0z3Q2cD0vKD_N&vZoy*v7H96UQoe|{+gE+S z5_rj1U;=g>-CoVFm>c2<9U8|9YuNtP@Bc-YeKAcxdn|rfn|smyY301<{hliRqZV^* zHPsVxhC0Jo_i5B_L#|B++420c?!bfm#YnkQ-IX5ZbG^~8vFAOFItL&2QAP$wrQN#fIu+REx9~rajj~x6$`aky{;(@%O$HO=GEB4`6O_z1V>Nou_ zaV=wp8q9Rrk2qI#koO=*yj)LGOOX?rqYfMD3AkXR-FPhfzqXNU#d{L5aNLR!H26z3 zru)9u8ul1KPHA!wUA^$&=$eIZJ#gHw&So2sCZ zKilYQCu=!6!h4O_XtKk!rg`UE5A@CXx9Ao0jnJC#jTeJ)^ToC)rfQ?wYimRJD&7L) zczdwfpd)ZM$n##zMOOnauqgg|A8U-HBmCt(;KkT(ucp^)$onX^)DQ4slzpDlI`EOM zMjvS(u{f&HaTM`BR=N*IPaOxBX^O*P`PW8YJ6X%oFRuUF;b@|d7lU#0HC_y=y|y-l vui`B*j<<)rH|Pl54f4Dv^U;O>d&d6(^(&;cIgp=x00000NkvXXu0mjfu81AY literal 0 HcmV?d00001 diff --git a/noir/noir-repo/noir_stdlib/src/cmp.nr b/noir/noir-repo/noir_stdlib/src/cmp.nr index dde29d7ee87..457b2cfa167 100644 --- a/noir/noir-repo/noir_stdlib/src/cmp.nr +++ b/noir/noir-repo/noir_stdlib/src/cmp.nr @@ -314,3 +314,55 @@ impl Ord for (A, B, C, D, E) where A: Ord, B: Ord, C: Ord, D: Ord result } } + +// Compares and returns the maximum of two values. +// +// Returns the second argument if the comparison determines them to be equal. +// +// # Examples +// +// ``` +// use std::cmp; +// +// assert_eq(cmp::max(1, 2), 2); +// assert_eq(cmp::max(2, 2), 2); +// ``` +pub fn max(v1: T, v2: T) -> T where T: Ord { + if v1 > v2 { v1 } else { v2 } +} + +// Compares and returns the minimum of two values. +// +// Returns the first argument if the comparison determines them to be equal. +// +// # Examples +// +// ``` +// use std::cmp; +// +// assert_eq(cmp::min(1, 2), 1); +// assert_eq(cmp::min(2, 2), 2); +// ``` +pub fn min(v1: T, v2: T) -> T where T: Ord { + if v1 > v2 { v2 } else { v1 } +} + +mod cmp_tests { + use crate::cmp::{min, max}; + + #[test] + fn sanity_check_min() { + assert_eq(min(0 as u64, 1 as u64), 0); + assert_eq(min(0 as u64, 0 as u64), 0); + assert_eq(min(1 as u64, 1 as u64), 1); + assert_eq(min(255 as u8, 0 as u8), 0); + } + + #[test] + fn sanity_check_max() { + assert_eq(max(0 as u64, 1 as u64), 1); + assert_eq(max(0 as u64, 0 as u64), 0); + assert_eq(max(1 as u64, 1 as u64), 1); + assert_eq(max(255 as u8, 0 as u8), 255); + } +} diff --git a/noir/noir-repo/noir_stdlib/src/collections/bounded_vec.nr b/noir/noir-repo/noir_stdlib/src/collections/bounded_vec.nr index c789bc386ef..c6a3365a979 100644 --- a/noir/noir-repo/noir_stdlib/src/collections/bounded_vec.nr +++ b/noir/noir-repo/noir_stdlib/src/collections/bounded_vec.nr @@ -1,3 +1,5 @@ +use crate::cmp::Eq; + struct BoundedVec { storage: [T; MaxLen], len: u64, @@ -93,3 +95,37 @@ impl BoundedVec { ret } } + +impl Eq for BoundedVec where T: Eq { + fn eq(self, other: BoundedVec) -> bool { + // TODO: https://github.com/noir-lang/noir/issues/4837 + // + // We make the assumption that the user has used the proper interface for working with `BoundedVec`s + // rather than directly manipulating the internal fields as this can result in an inconsistent internal state. + + (self.len == other.len) & (self.storage == other.storage) + } +} + +mod bounded_vec_tests { + // TODO: Allow imports from "super" + use crate::collections::bounded_vec::BoundedVec; + + #[test] + fn empty_equality() { + let mut bounded_vec1: BoundedVec = BoundedVec::new(); + let mut bounded_vec2: BoundedVec = BoundedVec::new(); + + assert_eq(bounded_vec1, bounded_vec2); + } + + #[test] + fn inequality() { + let mut bounded_vec1: BoundedVec = BoundedVec::new(); + let mut bounded_vec2: BoundedVec = BoundedVec::new(); + bounded_vec1.push(1); + bounded_vec2.push(2); + + assert(bounded_vec1 != bounded_vec2); + } +} diff --git a/noir/noir-repo/noir_stdlib/src/convert.nr b/noir/noir-repo/noir_stdlib/src/convert.nr index 00ac0a0fd8c..d3537df3c5e 100644 --- a/noir/noir-repo/noir_stdlib/src/convert.nr +++ b/noir/noir-repo/noir_stdlib/src/convert.nr @@ -12,12 +12,12 @@ impl From for T { // docs:start:into-trait trait Into { - fn into(input: Self) -> T; + fn into(self) -> T; } impl Into for U where T: From { - fn into(input: U) -> T { - T::from(input) + fn into(self) -> T { + T::from(self) } } // docs:end:into-trait diff --git a/noir/noir-repo/noir_stdlib/src/hash.nr b/noir/noir-repo/noir_stdlib/src/hash.nr index 1a61b5e084e..26a9fa6c2c0 100644 --- a/noir/noir-repo/noir_stdlib/src/hash.nr +++ b/noir/noir-repo/noir_stdlib/src/hash.nr @@ -1,7 +1,6 @@ mod poseidon; mod mimc; mod poseidon2; -mod pedersen; use crate::default::Default; use crate::uint128::U128; @@ -12,36 +11,18 @@ pub fn sha256(input: [u8; N]) -> [u8; 32] // docs:end:sha256 {} -#[foreign(sha256)] -// docs:start:sha256_slice -pub fn sha256_slice(input: [u8]) -> [u8; 32] -// docs:end:sha256_slice -{} - #[foreign(blake2s)] // docs:start:blake2s pub fn blake2s(input: [u8; N]) -> [u8; 32] // docs:end:blake2s {} -#[foreign(blake2s)] -// docs:start:blake2s_slice -pub fn blake2s_slice(input: [u8]) -> [u8; 32] -// docs:end:blake2s_slice -{} - #[foreign(blake3)] // docs:start:blake3 pub fn blake3(input: [u8; N]) -> [u8; 32] // docs:end:blake3 {} -#[foreign(blake3)] -// docs:start:blake3_slice -pub fn blake3_slice(input: [u8]) -> [u8; 32] -// docs:end:blake3_slice -{} - // docs:start:pedersen_commitment struct PedersenPoint { x : Field, @@ -53,28 +34,14 @@ pub fn pedersen_commitment(input: [Field; N]) -> PedersenPoint { pedersen_commitment_with_separator(input, 0) } -// docs:start:pedersen_commitment_slice -pub fn pedersen_commitment_slice(input: [Field]) -> PedersenPoint { - pedersen_commitment_with_separator_slice(input, 0) -} -// docs:end:pedersen_commitment_slice - #[foreign(pedersen_commitment)] pub fn __pedersen_commitment_with_separator(input: [Field; N], separator: u32) -> [Field; 2] {} -#[foreign(pedersen_commitment)] -pub fn __pedersen_commitment_with_separator_slice(input: [Field], separator: u32) -> [Field; 2] {} - pub fn pedersen_commitment_with_separator(input: [Field; N], separator: u32) -> PedersenPoint { let values = __pedersen_commitment_with_separator(input, separator); PedersenPoint { x: values[0], y: values[1] } } -pub fn pedersen_commitment_with_separator_slice(input: [Field], separator: u32) -> PedersenPoint { - let values = __pedersen_commitment_with_separator_slice(input, separator); - PedersenPoint { x: values[0], y: values[1] } -} - // docs:start:pedersen_hash pub fn pedersen_hash(input: [Field; N]) -> Field // docs:end:pedersen_hash @@ -82,31 +49,18 @@ pub fn pedersen_hash(input: [Field; N]) -> Field pedersen_hash_with_separator(input, 0) } -// docs:start:pedersen_hash_slice -pub fn pedersen_hash_slice(input: [Field]) -> Field -// docs:end:pedersen_hash_slice -{ - pedersen_hash_with_separator_slice(input, 0) -} - #[foreign(pedersen_hash)] pub fn pedersen_hash_with_separator(input: [Field; N], separator: u32) -> Field {} -#[foreign(pedersen_hash)] -pub fn pedersen_hash_with_separator_slice(input: [Field], separator: u32) -> Field {} - pub fn hash_to_field(inputs: [Field]) -> Field { - let mut inputs_as_bytes = &[]; + let mut sum = 0; for input in inputs { - let input_bytes = input.to_le_bytes(32); - for i in 0..32 { - inputs_as_bytes = inputs_as_bytes.push_back(input_bytes[i]); - } + let input_bytes: [u8; 32] = input.to_le_bytes(32).as_array(); + sum += crate::field::bytes32_to_field(blake2s(input_bytes)); } - let hashed_input = blake2s_slice(inputs_as_bytes); - crate::field::bytes32_to_field(hashed_input) + sum } #[foreign(keccak256)] @@ -115,12 +69,6 @@ pub fn keccak256(input: [u8; N], message_size: u32) -> [u8; 32] // docs:end:keccak256 {} -#[foreign(keccak256)] -// docs:start:keccak256_slice -pub fn keccak256_slice(input: [u8], message_size: u32) -> [u8; 32] -// docs:end:keccak256_slice -{} - #[foreign(poseidon2_permutation)] pub fn poseidon2_permutation(_input: [Field; N], _state_length: u32) -> [Field; N] {} @@ -140,7 +88,7 @@ trait Hash{ trait Hasher{ fn finish(self) -> Field; - fn write(&mut self, input: [Field]); + fn write(&mut self, input: Field); } // BuildHasher is a factory trait, responsible for production of specific Hasher. @@ -170,49 +118,49 @@ where impl Hash for Field { fn hash(self, state: &mut H) where H: Hasher{ - H::write(state, &[self]); + H::write(state, self); } } impl Hash for u8 { fn hash(self, state: &mut H) where H: Hasher{ - H::write(state, &[self as Field]); + H::write(state, self as Field); } } impl Hash for u32 { fn hash(self, state: &mut H) where H: Hasher{ - H::write(state, &[self as Field]); + H::write(state, self as Field); } } impl Hash for u64 { fn hash(self, state: &mut H) where H: Hasher{ - H::write(state, &[self as Field]); + H::write(state, self as Field); } } impl Hash for i8 { fn hash(self, state: &mut H) where H: Hasher{ - H::write(state, &[self as Field]); + H::write(state, self as Field); } } impl Hash for i32 { fn hash(self, state: &mut H) where H: Hasher{ - H::write(state, &[self as Field]); + H::write(state, self as Field); } } impl Hash for i64 { fn hash(self, state: &mut H) where H: Hasher{ - H::write(state, &[self as Field]); + H::write(state, self as Field); } } impl Hash for bool { fn hash(self, state: &mut H) where H: Hasher{ - H::write(state, &[self as Field]); + H::write(state, self as Field); } } @@ -222,7 +170,8 @@ impl Hash for () { impl Hash for U128 { fn hash(self, state: &mut H) where H: Hasher{ - H::write(state, &[self.lo as Field, self.hi as Field]); + H::write(state, self.lo as Field); + H::write(state, self.hi as Field); } } diff --git a/noir/noir-repo/noir_stdlib/src/hash/mimc.nr b/noir/noir-repo/noir_stdlib/src/hash/mimc.nr index 1fb53701013..6c5502c2fbf 100644 --- a/noir/noir-repo/noir_stdlib/src/hash/mimc.nr +++ b/noir/noir-repo/noir_stdlib/src/hash/mimc.nr @@ -126,9 +126,8 @@ pub fn mimc_bn254(array: [Field; N]) -> Field { r } -struct MimcHasher{ +struct MimcHasher { _state: [Field], - _len: u64, } impl Hasher for MimcHasher { @@ -136,24 +135,22 @@ impl Hasher for MimcHasher { fn finish(self) -> Field { let exponent = 7; let mut r = 0; - for i in 0..self._len { + for i in 0..self._state.len() { let h = mimc(self._state[i], r, MIMC_BN254_CONSTANTS, exponent); r = r + self._state[i] + h; } r } - fn write(&mut self, input: [Field]){ - self._state = self._state.append(input); - self._len += input.len(); + fn write(&mut self, input: Field){ + self._state = self._state.push_back(input); } } impl Default for MimcHasher{ fn default() -> Self{ - MimcHasher{ + MimcHasher { _state: &[], - _len: 0, } } } diff --git a/noir/noir-repo/noir_stdlib/src/hash/pedersen.nr b/noir/noir-repo/noir_stdlib/src/hash/pedersen.nr deleted file mode 100644 index ad21e728945..00000000000 --- a/noir/noir-repo/noir_stdlib/src/hash/pedersen.nr +++ /dev/null @@ -1,24 +0,0 @@ -use crate::hash::{Hasher, pedersen_hash_slice}; -use crate::default::Default; - -struct PedersenHasher{ - _state: [Field] -} - -impl Hasher for PedersenHasher { - fn finish(self) -> Field { - pedersen_hash_slice(self._state) - } - - fn write(&mut self, input: [Field]){ - self._state = self._state.append(input); - } -} - -impl Default for PedersenHasher{ - fn default() -> Self{ - PedersenHasher{ - _state: &[] - } - } -} diff --git a/noir/noir-repo/noir_stdlib/src/hash/poseidon.nr b/noir/noir-repo/noir_stdlib/src/hash/poseidon.nr index 85a0802f630..742bfcaf804 100644 --- a/noir/noir-repo/noir_stdlib/src/hash/poseidon.nr +++ b/noir/noir-repo/noir_stdlib/src/hash/poseidon.nr @@ -105,66 +105,65 @@ fn apply_matrix(a: [Field; M], x: [Field; N]) -> [Field; N] { struct PoseidonHasher{ _state: [Field], - _len: u64, } impl Hasher for PoseidonHasher { #[field(bn254)] fn finish(self) -> Field { let mut result = 0; - assert(self._len < 16); - if self._len == 1 { + let len = self._state.len(); + assert(len < 16); + if len == 1 { result = bn254::hash_1([self._state[0]]); } - if self._len == 2 { + if len == 2 { result = bn254::hash_2([self._state[0],self._state[1]]); } - if self._len == 3 { + if len == 3 { result = bn254::hash_3([self._state[0],self._state[1],self._state[2]]); } - if self._len == 4 { + if len == 4 { result = bn254::hash_4([self._state[0],self._state[1],self._state[2],self._state[3]]); } - if self._len == 5 { + if len == 5 { result = bn254::hash_5([self._state[0],self._state[1],self._state[2],self._state[3],self._state[4]]); } - if self._len == 6 { + if len == 6 { result = bn254::hash_6([self._state[0],self._state[1],self._state[2],self._state[3],self._state[4], self._state[5]]); } - if self._len == 7 { + if len == 7 { result = bn254::hash_7([self._state[0],self._state[1],self._state[2],self._state[3],self._state[4], self._state[5], self._state[6]]); } - if self._len == 8 { + if len == 8 { result = bn254::hash_8([self._state[0],self._state[1],self._state[2],self._state[3],self._state[4], self._state[5], self._state[6], self._state[7]]); } - if self._len == 9 { + if len == 9 { result = bn254::hash_9([self._state[0],self._state[1],self._state[2],self._state[3],self._state[4], self._state[5], self._state[6], self._state[7], self._state[8]]); } - if self._len == 10 { + if len == 10 { result = bn254::hash_10([self._state[0],self._state[1],self._state[2],self._state[3],self._state[4], self._state[5], self._state[6], self._state[7], self._state[8], self._state[9]]); } - if self._len == 11 { + if len == 11 { result = bn254::hash_11([self._state[0],self._state[1],self._state[2],self._state[3],self._state[4], self._state[5], self._state[6], self._state[7], self._state[8], self._state[9], self._state[10]]); } - if self._len == 12 { + if len == 12 { result = bn254::hash_12([self._state[0],self._state[1],self._state[2],self._state[3],self._state[4], self._state[5], self._state[6], self._state[7], self._state[8], self._state[9], self._state[10], self._state[11]]); } - if self._len == 13 { + if len == 13 { result = bn254::hash_13([self._state[0],self._state[1],self._state[2],self._state[3],self._state[4], self._state[5], self._state[6], self._state[7], self._state[8], self._state[9], self._state[10], self._state[11], self._state[12]]); } - if self._len == 14 { + if len == 14 { result = bn254::hash_14([self._state[0],self._state[1],self._state[2],self._state[3],self._state[4], self._state[5], self._state[6], self._state[7], self._state[8], self._state[9], self._state[10], self._state[11], self._state[12], self._state[13]]); } - if self._len == 15 { + if len == 15 { result = bn254::hash_15([self._state[0],self._state[1],self._state[2],self._state[3],self._state[4], self._state[5], self._state[6], self._state[7], self._state[8], self._state[9], self._state[10], self._state[11], self._state[12], self._state[13], self._state[14]]); } result } - fn write(&mut self, input: [Field]){ - self._state = self._state.append(input); - self._len += input.len(); + fn write(&mut self, input: Field){ + self._state = self._state.push_back(input); } } @@ -172,7 +171,6 @@ impl Default for PoseidonHasher{ fn default() -> Self{ PoseidonHasher{ _state: &[], - _len: 0, } } } diff --git a/noir/noir-repo/noir_stdlib/src/hash/poseidon2.nr b/noir/noir-repo/noir_stdlib/src/hash/poseidon2.nr index 12bf373e671..e5a82a596c6 100644 --- a/noir/noir-repo/noir_stdlib/src/hash/poseidon2.nr +++ b/noir/noir-repo/noir_stdlib/src/hash/poseidon2.nr @@ -117,30 +117,27 @@ impl Poseidon2 { struct Poseidon2Hasher{ _state: [Field], - _len: u64, } impl Hasher for Poseidon2Hasher { fn finish(self) -> Field { let iv : Field = (self._state.len() as Field)*18446744073709551616; // iv = (self._state.len() << 64) let mut sponge = Poseidon2::new(iv); - for i in 0..self._len { + for i in 0..self._state.len() { sponge.absorb(self._state[i]); } sponge.squeeze() } - fn write(&mut self, input: [Field]){ - self._state = self._state.append(input); - self._len += input.len(); + fn write(&mut self, input: Field){ + self._state = self._state.push_back(input); } } -impl Default for Poseidon2Hasher{ - fn default() -> Self{ - Poseidon2Hasher{ +impl Default for Poseidon2Hasher { + fn default() -> Self { + Poseidon2Hasher { _state: &[], - _len: 0, } } } diff --git a/noir/noir-repo/noir_stdlib/src/slice.nr b/noir/noir-repo/noir_stdlib/src/slice.nr index 164b4f96cf6..ac542a960ed 100644 --- a/noir/noir-repo/noir_stdlib/src/slice.nr +++ b/noir/noir-repo/noir_stdlib/src/slice.nr @@ -43,4 +43,14 @@ impl [T] { } self } + + pub fn as_array(self) -> [T; N] { + assert(self.len() == N); + + let mut array = [crate::unsafe::zeroed(); N]; + for i in 0..N { + array[i] = self[i]; + } + array + } } diff --git a/noir/noir-repo/rust-toolchain.toml b/noir/noir-repo/rust-toolchain.toml index 0e5ac891ce9..fe2949c8458 100644 --- a/noir/noir-repo/rust-toolchain.toml +++ b/noir/noir-repo/rust-toolchain.toml @@ -1,5 +1,5 @@ [toolchain] -channel = "1.73.0" +channel = "1.74.1" components = [ "rust-src" ] targets = [ "wasm32-unknown-unknown", "wasm32-wasi", "aarch64-apple-darwin" ] profile = "default" diff --git a/noir/noir-repo/scripts/benchmark_start.sh b/noir/noir-repo/scripts/benchmark_start.sh new file mode 100755 index 00000000000..3e69b3d2c65 --- /dev/null +++ b/noir/noir-repo/scripts/benchmark_start.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +echo -1 | sudo tee /proc/sys/kernel/perf_event_paranoid diff --git a/noir/noir-repo/scripts/benchmark_stop.sh b/noir/noir-repo/scripts/benchmark_stop.sh new file mode 100755 index 00000000000..964e5291817 --- /dev/null +++ b/noir/noir-repo/scripts/benchmark_stop.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +echo 4 | sudo tee /proc/sys/kernel/perf_event_paranoid diff --git a/noir/noir-repo/test_programs/execution_failure/hashmap_load_factor/src/main.nr b/noir/noir-repo/test_programs/execution_failure/hashmap_load_factor/src/main.nr index ade43f898e1..907c3628142 100644 --- a/noir/noir-repo/test_programs/execution_failure/hashmap_load_factor/src/main.nr +++ b/noir/noir-repo/test_programs/execution_failure/hashmap_load_factor/src/main.nr @@ -1,6 +1,6 @@ use dep::std::collections::map::HashMap; use dep::std::hash::BuildHasherDefault; -use dep::std::hash::pedersen::PedersenHasher; +use dep::std::hash::poseidon2::Poseidon2Hasher; struct Entry{ key: Field, @@ -10,7 +10,7 @@ struct Entry{ global HASHMAP_CAP = 8; global HASHMAP_LEN = 6; -fn allocate_hashmap() -> HashMap> { +fn allocate_hashmap() -> HashMap> { HashMap::default() } diff --git a/noir/noir-repo/test_programs/execution_success/eddsa/src/main.nr b/noir/noir-repo/test_programs/execution_success/eddsa/src/main.nr index fd1a95ee5fb..012c8466f2f 100644 --- a/noir/noir-repo/test_programs/execution_success/eddsa/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/eddsa/src/main.nr @@ -4,7 +4,6 @@ use dep::std::ec::tecurve::affine::Point as TEPoint; use dep::std::hash; use dep::std::eddsa::{eddsa_to_pub, eddsa_poseidon_verify, eddsa_verify_with_hasher}; use dep::std::hash::poseidon2::Poseidon2Hasher; -use dep::std::hash::pedersen::PedersenHasher; fn main(msg: pub Field, _priv_key_a: Field, _priv_key_b: Field) { // Skip this test for non-bn254 backends @@ -53,8 +52,5 @@ fn main(msg: pub Field, _priv_key_a: Field, _priv_key_b: Field) { // Using a different hash should fail let mut hasher = Poseidon2Hasher::default(); assert(!eddsa_verify_with_hasher(pub_key_a.x, pub_key_a.y, s_a, r8_a.x, r8_a.y, msg, &mut hasher)); - // Using a different hash should fail - let mut hasher = PedersenHasher::default(); - assert(!eddsa_verify_with_hasher(pub_key_a.x, pub_key_a.y, s_a, r8_a.x, r8_a.y, msg, &mut hasher)); } } diff --git a/noir/noir-repo/test_programs/execution_success/fold_numeric_generic_poseidon/Nargo.toml b/noir/noir-repo/test_programs/execution_success/fold_numeric_generic_poseidon/Nargo.toml new file mode 100644 index 00000000000..8c2bc79ea8d --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/fold_numeric_generic_poseidon/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "fold_numeric_generic_poseidon" +type = "bin" +authors = [""] +compiler_version = ">=0.27.0" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/execution_success/fold_numeric_generic_poseidon/Prover.toml b/noir/noir-repo/test_programs/execution_success/fold_numeric_generic_poseidon/Prover.toml new file mode 100644 index 00000000000..00e821cf89d --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/fold_numeric_generic_poseidon/Prover.toml @@ -0,0 +1,2 @@ +enable = [true, false] +to_hash = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]] diff --git a/noir/noir-repo/test_programs/execution_success/fold_numeric_generic_poseidon/src/main.nr b/noir/noir-repo/test_programs/execution_success/fold_numeric_generic_poseidon/src/main.nr new file mode 100644 index 00000000000..f9f3e75789b --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/fold_numeric_generic_poseidon/src/main.nr @@ -0,0 +1,33 @@ +use dep::std::hash::{pedersen_hash_with_separator, poseidon2::Poseidon2}; + +global NUM_HASHES = 2; +global HASH_LENGTH = 10; + +#[fold] +pub fn poseidon_hash(inputs: [Field; N]) -> Field { + Poseidon2::hash(inputs, inputs.len()) +} + +fn main( + to_hash: [[Field; HASH_LENGTH]; NUM_HASHES], + enable: [bool; NUM_HASHES] +) -> pub [Field; NUM_HASHES + 1] { + let mut result = [0; NUM_HASHES + 1]; + for i in 0..NUM_HASHES { + let enable = enable[i]; + let to_hash = to_hash[i]; + if enable { + result[i] = poseidon_hash(to_hash); + } + } + + // We want to make sure that the foldable function with a numeric generic + // is monomorphized correctly. + let mut double_preimage = [0; 20]; + for i in 0..HASH_LENGTH * 2 { + double_preimage[i] = to_hash[0][i % HASH_LENGTH]; + } + result[NUM_HASHES] = poseidon_hash(double_preimage); + + result +} diff --git a/noir/noir-repo/test_programs/execution_success/hashmap/src/main.nr b/noir/noir-repo/test_programs/execution_success/hashmap/src/main.nr index 4d2cbd45993..76daa594a89 100644 --- a/noir/noir-repo/test_programs/execution_success/hashmap/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/hashmap/src/main.nr @@ -2,7 +2,7 @@ mod utils; use dep::std::collections::map::HashMap; use dep::std::hash::BuildHasherDefault; -use dep::std::hash::pedersen::PedersenHasher; +use dep::std::hash::poseidon2::Poseidon2Hasher; use dep::std::cmp::Eq; use utils::cut; @@ -25,7 +25,7 @@ global K_CMP = FIELD_CMP; global V_CMP = FIELD_CMP; global KV_CMP = |a: (K, V), b: (K, V)| a.0.lt(b.0); -global ALLOCATE_HASHMAP = || -> HashMap> +global ALLOCATE_HASHMAP = || -> HashMap> HashMap::default(); fn main(input: [Entry; HASHMAP_LEN]) { @@ -194,24 +194,24 @@ fn test_mut_iterators() { } // docs:start:type_alias -type MyMap = HashMap>; +type MyMap = HashMap>; // docs:end:type_alias /// Tests examples from the stdlib hashmap documentation fn doc_tests() { // docs:start:default_example - let hashmap: HashMap> = HashMap::default(); + let hashmap: HashMap> = HashMap::default(); assert(hashmap.is_empty()); // docs:end:default_example // docs:start:with_hasher_example - let my_hasher: BuildHasherDefault = Default::default(); - let hashmap: HashMap> = HashMap::with_hasher(my_hasher); + let my_hasher: BuildHasherDefault = Default::default(); + let hashmap: HashMap> = HashMap::with_hasher(my_hasher); assert(hashmap.is_empty()); // docs:end:with_hasher_example // docs:start:insert_example - let mut map: HashMap> = HashMap::default(); + let mut map: HashMap> = HashMap::default(); map.insert(12, 42); assert(map.len() == 1); // docs:end:insert_example @@ -255,7 +255,7 @@ fn doc_tests() { // docs:end:len_example // docs:start:capacity_example - let empty_map: HashMap> = HashMap::default(); + let empty_map: HashMap> = HashMap::default(); assert(empty_map.len() == 0); assert(empty_map.capacity() == 42); // docs:end:capacity_example @@ -283,8 +283,8 @@ fn doc_tests() { // docs:end:retain_example // docs:start:eq_example - let mut map1: HashMap> = HashMap::default(); - let mut map2: HashMap> = HashMap::default(); + let mut map1: HashMap> = HashMap::default(); + let mut map2: HashMap> = HashMap::default(); map1.insert(1, 2); map1.insert(3, 4); @@ -297,7 +297,7 @@ fn doc_tests() { } // docs:start:get_example -fn get_example(map: HashMap>) { +fn get_example(map: HashMap>) { let x = map.get(12); if x.is_some() { @@ -306,7 +306,7 @@ fn get_example(map: HashMap> } // docs:end:get_example -fn entries_examples(map: HashMap>) { +fn entries_examples(map: HashMap>) { // docs:start:entries_example let entries = map.entries(); @@ -344,7 +344,7 @@ fn entries_examples(map: HashMap>) { +fn iter_examples(mut map: HashMap>) { // docs:start:iter_mut_example // Add 1 to each key in the map, and double the value associated with that key. map.iter_mut(|k, v| (k + 1, v * 2)); diff --git a/noir/noir-repo/test_programs/execution_success/regression_sha256_slice/Nargo.toml b/noir/noir-repo/test_programs/execution_success/regression_sha256_slice/Nargo.toml deleted file mode 100644 index 759c3b20ba8..00000000000 --- a/noir/noir-repo/test_programs/execution_success/regression_sha256_slice/Nargo.toml +++ /dev/null @@ -1,7 +0,0 @@ -[package] -name = "regression_sha256_slice" -type = "bin" -authors = [""] -compiler_version = ">=0.26.0" - -[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/execution_success/regression_sha256_slice/Prover.toml b/noir/noir-repo/test_programs/execution_success/regression_sha256_slice/Prover.toml deleted file mode 100644 index 8a027e9eca9..00000000000 --- a/noir/noir-repo/test_programs/execution_success/regression_sha256_slice/Prover.toml +++ /dev/null @@ -1 +0,0 @@ -x = ["5", "10"] diff --git a/noir/noir-repo/test_programs/execution_success/regression_sha256_slice/src/main.nr b/noir/noir-repo/test_programs/execution_success/regression_sha256_slice/src/main.nr deleted file mode 100644 index 60b0911cf09..00000000000 --- a/noir/noir-repo/test_programs/execution_success/regression_sha256_slice/src/main.nr +++ /dev/null @@ -1,12 +0,0 @@ -use dep::std; - -fn main(x: [u8; 2]) { - let mut y = x.as_slice(); - let digest1 = std::hash::sha256_slice(y); - let mut v = y; - if x[0] != 0 { - v = y.push_back(x[0]); - } - let digest2 = std::hash::sha256_slice(v); - assert(digest1 != digest2); -} diff --git a/noir/noir-repo/tooling/backend_interface/Cargo.toml b/noir/noir-repo/tooling/backend_interface/Cargo.toml index 2d991f9ae6c..b731c138c7d 100644 --- a/noir/noir-repo/tooling/backend_interface/Cargo.toml +++ b/noir/noir-repo/tooling/backend_interface/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "backend-interface" description = "The definition of the backend CLI interface which Nargo uses for proving/verifying ACIR circuits." -version = "0.11.0" +version.workspace = true authors.workspace = true edition.workspace = true rust-version.workspace = true diff --git a/noir/noir-repo/tooling/backend_interface/src/cli/info.rs b/noir/noir-repo/tooling/backend_interface/src/cli/info.rs index 8ca3d4dd0a3..6e6603ce53e 100644 --- a/noir/noir-repo/tooling/backend_interface/src/cli/info.rs +++ b/noir/noir-repo/tooling/backend_interface/src/cli/info.rs @@ -56,7 +56,7 @@ fn info_command() -> Result<(), BackendError> { let expression_width = InfoCommand { crs_path }.run(backend.binary_path())?; - assert!(matches!(expression_width, ExpressionWidth::Bounded { width: 3 })); + assert!(matches!(expression_width, ExpressionWidth::Bounded { width: 4 })); Ok(()) } diff --git a/noir/noir-repo/tooling/bb_abstraction_leaks/build.rs b/noir/noir-repo/tooling/bb_abstraction_leaks/build.rs index 0f9770c805d..b3dfff9e94c 100644 --- a/noir/noir-repo/tooling/bb_abstraction_leaks/build.rs +++ b/noir/noir-repo/tooling/bb_abstraction_leaks/build.rs @@ -10,7 +10,7 @@ use const_format::formatcp; const USERNAME: &str = "AztecProtocol"; const REPO: &str = "aztec-packages"; -const VERSION: &str = "0.34.0"; +const VERSION: &str = "0.35.1"; const TAG: &str = formatcp!("aztec-packages-v{}", VERSION); const API_URL: &str = diff --git a/noir/noir-repo/tooling/debugger/Cargo.toml b/noir/noir-repo/tooling/debugger/Cargo.toml index 30d11db8cf3..a3bf12f5368 100644 --- a/noir/noir-repo/tooling/debugger/Cargo.toml +++ b/noir/noir-repo/tooling/debugger/Cargo.toml @@ -4,6 +4,7 @@ description = "Debugger for Noir" version.workspace = true authors.workspace = true edition.workspace = true +rust-version.workspace = true license.workspace = true [build-dependencies] diff --git a/noir/noir-repo/tooling/debugger/ignored-tests.txt b/noir/noir-repo/tooling/debugger/ignored-tests.txt index 4507aeb8545..3b63f8d5542 100644 --- a/noir/noir-repo/tooling/debugger/ignored-tests.txt +++ b/noir/noir-repo/tooling/debugger/ignored-tests.txt @@ -15,3 +15,6 @@ to_bytes_integration fold_basic fold_basic_nested_call fold_call_witness_condition +fold_after_inlined_calls +fold_numeric_generic_poseidon + diff --git a/noir/noir-repo/tooling/lsp/Cargo.toml b/noir/noir-repo/tooling/lsp/Cargo.toml index 750e85694e2..a599b096e52 100644 --- a/noir/noir-repo/tooling/lsp/Cargo.toml +++ b/noir/noir-repo/tooling/lsp/Cargo.toml @@ -3,7 +3,8 @@ name = "noir_lsp" description = "Language server for Noir" version.workspace = true authors.workspace = true -edition.workspace = true +edition.workspace = true# +rust-version.workspace = true license.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/noir/noir-repo/tooling/nargo/Cargo.toml b/noir/noir-repo/tooling/nargo/Cargo.toml index efd38a182e0..72b412ac5b9 100644 --- a/noir/noir-repo/tooling/nargo/Cargo.toml +++ b/noir/noir-repo/tooling/nargo/Cargo.toml @@ -4,13 +4,11 @@ description = "Noir's package manager" version.workspace = true authors.workspace = true edition.workspace = true +rust-version.workspace = true license.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html -[build-dependencies] -rustc_version = "0.4.0" - [dependencies] acvm.workspace = true fm.workspace = true diff --git a/noir/noir-repo/tooling/nargo/build.rs b/noir/noir-repo/tooling/nargo/build.rs deleted file mode 100644 index ab2b7579132..00000000000 --- a/noir/noir-repo/tooling/nargo/build.rs +++ /dev/null @@ -1,12 +0,0 @@ -use rustc_version::{version, Version}; - -fn check_rustc_version() { - assert!( - version().unwrap() >= Version::parse("1.73.0").unwrap(), - "The minimal supported rustc version is 1.73.0." - ); -} - -fn main() { - check_rustc_version(); -} diff --git a/noir/noir-repo/tooling/nargo_cli/Cargo.toml b/noir/noir-repo/tooling/nargo_cli/Cargo.toml index 1629ae86edb..c20be037e62 100644 --- a/noir/noir-repo/tooling/nargo_cli/Cargo.toml +++ b/noir/noir-repo/tooling/nargo_cli/Cargo.toml @@ -5,6 +5,7 @@ default-run = "nargo" version.workspace = true authors.workspace = true edition.workspace = true +rust-version.workspace = true license.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -15,7 +16,6 @@ name = "nargo" path = "src/main.rs" [build-dependencies] -rustc_version = "0.4.0" build-data.workspace = true toml.workspace = true @@ -72,13 +72,9 @@ assert_cmd = "2.0.8" assert_fs = "1.0.10" predicates = "2.1.5" fm.workspace = true -criterion = "0.5.0" +criterion.workspace = true +pprof.workspace = true paste = "1.0.14" -pprof = { version = "0.12", features = [ - "flamegraph", - "frame-pointer", - "criterion", -] } iai = "0.1.1" test-binary = "3.0.2" diff --git a/noir/noir-repo/tooling/nargo_cli/build.rs b/noir/noir-repo/tooling/nargo_cli/build.rs index bf97dfb3e96..0ed2d4c07f7 100644 --- a/noir/noir-repo/tooling/nargo_cli/build.rs +++ b/noir/noir-repo/tooling/nargo_cli/build.rs @@ -1,21 +1,11 @@ -use rustc_version::{version, Version}; use std::fs::File; use std::io::Write; use std::path::{Path, PathBuf}; use std::{env, fs}; -fn check_rustc_version() { - assert!( - version().unwrap() >= Version::parse("1.73.0").unwrap(), - "The minimal supported rustc version is 1.73.0." - ); -} - const GIT_COMMIT: &&str = &"GIT_COMMIT"; fn main() { - check_rustc_version(); - // Only use build_data if the environment variable isn't set. if std::env::var(GIT_COMMIT).is_err() { build_data::set_GIT_COMMIT(); diff --git a/noir/noir-repo/tooling/nargo_fmt/Cargo.toml b/noir/noir-repo/tooling/nargo_fmt/Cargo.toml index 374413ac9f2..05b2fdb7d52 100644 --- a/noir/noir-repo/tooling/nargo_fmt/Cargo.toml +++ b/noir/noir-repo/tooling/nargo_fmt/Cargo.toml @@ -3,6 +3,7 @@ name = "nargo_fmt" version.workspace = true authors.workspace = true edition.workspace = true +rust-version.workspace = true license.workspace = true [dependencies] diff --git a/noir/noir-repo/tooling/nargo_fmt/src/rewrite/array.rs b/noir/noir-repo/tooling/nargo_fmt/src/rewrite/array.rs index db7dc4701b7..011e775a018 100644 --- a/noir/noir-repo/tooling/nargo_fmt/src/rewrite/array.rs +++ b/noir/noir-repo/tooling/nargo_fmt/src/rewrite/array.rs @@ -1,4 +1,4 @@ -use noirc_frontend::{hir::resolution::errors::Span, token::Token, Expression}; +use noirc_frontend::{ast::Expression, hir::resolution::errors::Span, token::Token}; use crate::{ items::Item, diff --git a/noir/noir-repo/tooling/nargo_fmt/src/rewrite/expr.rs b/noir/noir-repo/tooling/nargo_fmt/src/rewrite/expr.rs index 6cf69a2309d..e4616c99aaa 100644 --- a/noir/noir-repo/tooling/nargo_fmt/src/rewrite/expr.rs +++ b/noir/noir-repo/tooling/nargo_fmt/src/rewrite/expr.rs @@ -1,7 +1,7 @@ -use noirc_frontend::{ - macros_api::Span, token::Token, ArrayLiteral, BlockExpression, Expression, ExpressionKind, - Literal, UnaryOp, +use noirc_frontend::ast::{ + ArrayLiteral, BlockExpression, Expression, ExpressionKind, Literal, UnaryOp, }; +use noirc_frontend::{macros_api::Span, token::Token}; use crate::visitor::{ expr::{format_brackets, format_parens, NewlineMode}, diff --git a/noir/noir-repo/tooling/nargo_fmt/src/rewrite/imports.rs b/noir/noir-repo/tooling/nargo_fmt/src/rewrite/imports.rs index 55eb259bcdd..564ef3fa370 100644 --- a/noir/noir-repo/tooling/nargo_fmt/src/rewrite/imports.rs +++ b/noir/noir-repo/tooling/nargo_fmt/src/rewrite/imports.rs @@ -1,4 +1,4 @@ -use noirc_frontend::{PathKind, UseTreeKind}; +use noirc_frontend::ast; use crate::{ items::Item, @@ -60,13 +60,13 @@ pub(crate) struct UseTree { } impl UseTree { - pub(crate) fn from_ast(use_tree: noirc_frontend::UseTree) -> Self { + pub(crate) fn from_ast(use_tree: ast::UseTree) -> Self { let mut result = UseTree { path: vec![] }; match use_tree.prefix.kind { - PathKind::Crate => result.path.push(UseSegment::Crate), - PathKind::Dep => result.path.push(UseSegment::Dep), - PathKind::Plain => {} + ast::PathKind::Crate => result.path.push(UseSegment::Crate), + ast::PathKind::Dep => result.path.push(UseSegment::Dep), + ast::PathKind::Plain => {} }; result.path.extend( @@ -78,13 +78,13 @@ impl UseTree { ); match use_tree.kind { - UseTreeKind::Path(name, alias) => { + ast::UseTreeKind::Path(name, alias) => { result.path.push(UseSegment::Ident( name.to_string(), alias.map(|rename| rename.to_string()), )); } - UseTreeKind::List(list) => { + ast::UseTreeKind::List(list) => { let segment = UseSegment::List(list.into_iter().map(UseTree::from_ast).collect()); result.path.push(segment); } diff --git a/noir/noir-repo/tooling/nargo_fmt/src/rewrite/infix.rs b/noir/noir-repo/tooling/nargo_fmt/src/rewrite/infix.rs index 5d2b387496a..e2555f21187 100644 --- a/noir/noir-repo/tooling/nargo_fmt/src/rewrite/infix.rs +++ b/noir/noir-repo/tooling/nargo_fmt/src/rewrite/infix.rs @@ -1,6 +1,6 @@ use std::iter::zip; -use noirc_frontend::{Expression, ExpressionKind}; +use noirc_frontend::ast::{Expression, ExpressionKind}; use crate::{ rewrite, diff --git a/noir/noir-repo/tooling/nargo_fmt/src/rewrite/parenthesized.rs b/noir/noir-repo/tooling/nargo_fmt/src/rewrite/parenthesized.rs index 3926b52cb73..93e1538b042 100644 --- a/noir/noir-repo/tooling/nargo_fmt/src/rewrite/parenthesized.rs +++ b/noir/noir-repo/tooling/nargo_fmt/src/rewrite/parenthesized.rs @@ -1,4 +1,5 @@ -use noirc_frontend::{hir::resolution::errors::Span, Expression, ExpressionKind}; +use noirc_frontend::ast::{Expression, ExpressionKind}; +use noirc_frontend::hir::resolution::errors::Span; use crate::visitor::{FmtVisitor, Shape}; diff --git a/noir/noir-repo/tooling/nargo_fmt/src/rewrite/typ.rs b/noir/noir-repo/tooling/nargo_fmt/src/rewrite/typ.rs index 980d02ee5dc..278457f82d1 100644 --- a/noir/noir-repo/tooling/nargo_fmt/src/rewrite/typ.rs +++ b/noir/noir-repo/tooling/nargo_fmt/src/rewrite/typ.rs @@ -1,4 +1,4 @@ -use noirc_frontend::{UnresolvedType, UnresolvedTypeData}; +use noirc_frontend::ast::{UnresolvedType, UnresolvedTypeData}; use crate::{ utils::span_is_empty, diff --git a/noir/noir-repo/tooling/nargo_fmt/src/utils.rs b/noir/noir-repo/tooling/nargo_fmt/src/utils.rs index 94969d45e81..2c5c3085e66 100644 --- a/noir/noir-repo/tooling/nargo_fmt/src/utils.rs +++ b/noir/noir-repo/tooling/nargo_fmt/src/utils.rs @@ -3,10 +3,10 @@ use std::borrow::Cow; use crate::items::HasItem; use crate::rewrite; use crate::visitor::{FmtVisitor, Shape}; +use noirc_frontend::ast::{Expression, Ident, Param, Visibility}; use noirc_frontend::hir::resolution::errors::Span; use noirc_frontend::lexer::Lexer; use noirc_frontend::token::Token; -use noirc_frontend::{Expression, Ident, Param, Visibility}; pub(crate) fn changed_comment_content(original: &str, new: &str) -> bool { comments(original).ne(comments(new)) diff --git a/noir/noir-repo/tooling/nargo_fmt/src/visitor/expr.rs b/noir/noir-repo/tooling/nargo_fmt/src/visitor/expr.rs index f9836adda18..18b962a7f85 100644 --- a/noir/noir-repo/tooling/nargo_fmt/src/visitor/expr.rs +++ b/noir/noir-repo/tooling/nargo_fmt/src/visitor/expr.rs @@ -1,7 +1,8 @@ -use noirc_frontend::{ - hir::resolution::errors::Span, lexer::Lexer, token::Token, BlockExpression, - ConstructorExpression, Expression, ExpressionKind, IfExpression, Statement, StatementKind, +use noirc_frontend::ast::Expression; +use noirc_frontend::ast::{ + BlockExpression, ConstructorExpression, ExpressionKind, IfExpression, Statement, StatementKind, }; +use noirc_frontend::{hir::resolution::errors::Span, lexer::Lexer, token::Token}; use super::{ExpressionType, FmtVisitor, Shape}; use crate::{ diff --git a/noir/noir-repo/tooling/nargo_fmt/src/visitor/item.rs b/noir/noir-repo/tooling/nargo_fmt/src/visitor/item.rs index 28aad3c551f..82cfefba632 100644 --- a/noir/noir-repo/tooling/nargo_fmt/src/visitor/item.rs +++ b/noir/noir-repo/tooling/nargo_fmt/src/visitor/item.rs @@ -1,10 +1,3 @@ -use noirc_frontend::{ - hir::resolution::errors::Span, - parser::{Item, ItemKind}, - token::{Keyword, Token}, - Distinctness, NoirFunction, ParsedModule, Visibility, -}; - use crate::{ rewrite::{self, UseTree}, utils::{ @@ -13,6 +6,13 @@ use crate::{ }, visitor::expr::{format_seq, NewlineMode}, }; +use noirc_frontend::ast::{Distinctness, NoirFunction, Visibility}; +use noirc_frontend::{ + hir::resolution::errors::Span, + parser::{Item, ItemKind}, + token::{Keyword, Token}, + ParsedModule, +}; use super::{ expr::Tactic::{HorizontalVertical, LimitedHorizontalVertical}, diff --git a/noir/noir-repo/tooling/nargo_fmt/src/visitor/stmt.rs b/noir/noir-repo/tooling/nargo_fmt/src/visitor/stmt.rs index ee8cc990e0e..e41827c94a1 100644 --- a/noir/noir-repo/tooling/nargo_fmt/src/visitor/stmt.rs +++ b/noir/noir-repo/tooling/nargo_fmt/src/visitor/stmt.rs @@ -1,6 +1,8 @@ use std::iter::zip; -use noirc_frontend::{ +use noirc_frontend::macros_api::Span; + +use noirc_frontend::ast::{ ConstrainKind, ConstrainStatement, ExpressionKind, ForRange, Statement, StatementKind, }; @@ -14,92 +16,94 @@ impl super::FmtVisitor<'_> { for (Statement { kind, span }, index) in zip(stmts, 1..) { let is_last = index == len; + self.visit_stmt(kind, span, is_last); + self.last_position = span.end(); + } + } - match kind { - StatementKind::Expression(expr) => self.visit_expr( - expr, - if is_last { ExpressionType::SubExpression } else { ExpressionType::Statement }, - ), - StatementKind::Semi(expr) => { - self.visit_expr(expr, ExpressionType::Statement); - self.push_str(";"); - } - StatementKind::Let(let_stmt) => { - let let_str = - self.slice(span.start()..let_stmt.expression.span.start()).trim_end(); - - let expr_str = rewrite::sub_expr(self, self.shape(), let_stmt.expression); - - self.push_rewrite(format!("{let_str} {expr_str};"), span); - } - StatementKind::Constrain(ConstrainStatement(expr, message, kind)) => { - let mut nested_shape = self.shape(); - let shape = nested_shape; - - nested_shape.indent.block_indent(self.config); - - let message = message.map_or(String::new(), |message| { - let message = rewrite::sub_expr(self, nested_shape, message); - format!(", {message}") - }); - - let (callee, args) = match kind { - ConstrainKind::Assert | ConstrainKind::Constrain => { - let assertion = rewrite::sub_expr(self, nested_shape, expr); - let args = format!("{assertion}{message}"); - - ("assert", args) - } - ConstrainKind::AssertEq => { - if let ExpressionKind::Infix(infix) = expr.kind { - let lhs = rewrite::sub_expr(self, nested_shape, infix.lhs); - let rhs = rewrite::sub_expr(self, nested_shape, infix.rhs); + fn visit_stmt(&mut self, kind: StatementKind, span: Span, is_last: bool) { + match kind { + StatementKind::Expression(expr) => self.visit_expr( + expr, + if is_last { ExpressionType::SubExpression } else { ExpressionType::Statement }, + ), + StatementKind::Semi(expr) => { + self.visit_expr(expr, ExpressionType::Statement); + self.push_str(";"); + } + StatementKind::Let(let_stmt) => { + let let_str = self.slice(span.start()..let_stmt.expression.span.start()).trim_end(); - let args = format!("{lhs}, {rhs}{message}"); + let expr_str = rewrite::sub_expr(self, self.shape(), let_stmt.expression); - ("assert_eq", args) - } else { - unreachable!() - } + self.push_rewrite(format!("{let_str} {expr_str};"), span); + } + StatementKind::Constrain(ConstrainStatement(expr, message, kind)) => { + let mut nested_shape = self.shape(); + let shape = nested_shape; + + nested_shape.indent.block_indent(self.config); + + let message = message.map_or(String::new(), |message| { + let message = rewrite::sub_expr(self, nested_shape, message); + format!(", {message}") + }); + + let (callee, args) = match kind { + ConstrainKind::Assert | ConstrainKind::Constrain => { + let assertion = rewrite::sub_expr(self, nested_shape, expr); + let args = format!("{assertion}{message}"); + + ("assert", args) + } + ConstrainKind::AssertEq => { + if let ExpressionKind::Infix(infix) = expr.kind { + let lhs = rewrite::sub_expr(self, nested_shape, infix.lhs); + let rhs = rewrite::sub_expr(self, nested_shape, infix.rhs); + + let args = format!("{lhs}, {rhs}{message}"); + + ("assert_eq", args) + } else { + unreachable!() } - }; - - let args = wrap_exprs( - "(", - ")", - args, - nested_shape, - shape, - NewlineMode::IfContainsNewLineAndWidth, - ); - let constrain = format!("{callee}{args};"); - - self.push_rewrite(constrain, span); - } - StatementKind::For(for_stmt) => { - let identifier = self.slice(for_stmt.identifier.span()); - let range = match for_stmt.range { - ForRange::Range(start, end) => format!( - "{}..{}", - rewrite::sub_expr(self, self.shape(), start), - rewrite::sub_expr(self, self.shape(), end) - ), - ForRange::Array(array) => rewrite::sub_expr(self, self.shape(), array), - }; - let block = rewrite::sub_expr(self, self.shape(), for_stmt.block); - - let result = format!("for {identifier} in {range} {block}"); - self.push_rewrite(result, span); - } - StatementKind::Assign(_) => { - self.push_rewrite(self.slice(span).to_string(), span); - } - StatementKind::Error => unreachable!(), - StatementKind::Break => self.push_rewrite("break;".into(), span), - StatementKind::Continue => self.push_rewrite("continue;".into(), span), + } + }; + + let args = wrap_exprs( + "(", + ")", + args, + nested_shape, + shape, + NewlineMode::IfContainsNewLineAndWidth, + ); + let constrain = format!("{callee}{args};"); + + self.push_rewrite(constrain, span); } - - self.last_position = span.end(); + StatementKind::For(for_stmt) => { + let identifier = self.slice(for_stmt.identifier.span()); + let range = match for_stmt.range { + ForRange::Range(start, end) => format!( + "{}..{}", + rewrite::sub_expr(self, self.shape(), start), + rewrite::sub_expr(self, self.shape(), end) + ), + ForRange::Array(array) => rewrite::sub_expr(self, self.shape(), array), + }; + let block = rewrite::sub_expr(self, self.shape(), for_stmt.block); + + let result = format!("for {identifier} in {range} {block}"); + self.push_rewrite(result, span); + } + StatementKind::Assign(_) => { + self.push_rewrite(self.slice(span).to_string(), span); + } + StatementKind::Error => unreachable!(), + StatementKind::Break => self.push_rewrite("break;".into(), span), + StatementKind::Continue => self.push_rewrite("continue;".into(), span), + StatementKind::Comptime(statement) => self.visit_stmt(*statement, span, is_last), } } } diff --git a/noir/noir-repo/tooling/nargo_toml/Cargo.toml b/noir/noir-repo/tooling/nargo_toml/Cargo.toml index c835ddd936c..574972d99e7 100644 --- a/noir/noir-repo/tooling/nargo_toml/Cargo.toml +++ b/noir/noir-repo/tooling/nargo_toml/Cargo.toml @@ -4,6 +4,7 @@ description = "Utilities for working with Nargo.toml files" version.workspace = true authors.workspace = true edition.workspace = true +rust-version.workspace = true license.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/noir/noir-repo/tooling/noir_js_backend_barretenberg/package.json b/noir/noir-repo/tooling/noir_js_backend_barretenberg/package.json index 438e91ff302..af9e47a8e63 100644 --- a/noir/noir-repo/tooling/noir_js_backend_barretenberg/package.json +++ b/noir/noir-repo/tooling/noir_js_backend_barretenberg/package.json @@ -42,7 +42,7 @@ "lint": "NODE_NO_WARNINGS=1 eslint . --ext .ts --ignore-path ./.eslintignore --max-warnings 0" }, "dependencies": { - "@aztec/bb.js": "portal:../../../../barretenberg/ts", + "@aztec/bb.js": "0.35.1", "@noir-lang/types": "workspace:*", "fflate": "^0.8.0" }, diff --git a/noir/noir-repo/tooling/noirc_abi/Cargo.toml b/noir/noir-repo/tooling/noirc_abi/Cargo.toml index b7fe1ef8084..3258ea04c40 100644 --- a/noir/noir-repo/tooling/noirc_abi/Cargo.toml +++ b/noir/noir-repo/tooling/noirc_abi/Cargo.toml @@ -3,6 +3,7 @@ name = "noirc_abi" version.workspace = true authors.workspace = true edition.workspace = true +rust-version.workspace = true license.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/noir/noir-repo/tooling/noirc_abi/src/lib.rs b/noir/noir-repo/tooling/noirc_abi/src/lib.rs index 6ad13500bdd..8ff0154d32c 100644 --- a/noir/noir-repo/tooling/noirc_abi/src/lib.rs +++ b/noir/noir-repo/tooling/noirc_abi/src/lib.rs @@ -10,7 +10,8 @@ use acvm::{ use errors::AbiError; use input_parser::InputValue; use iter_extended::{try_btree_map, try_vecmap, vecmap}; -use noirc_frontend::{hir::Context, Signedness, Type, TypeBinding, TypeVariableKind, Visibility}; +use noirc_frontend::ast::{Signedness, Visibility}; +use noirc_frontend::{hir::Context, Type, TypeBinding, TypeVariableKind}; use serde::{Deserialize, Serialize}; use std::ops::Range; use std::{collections::BTreeMap, str}; diff --git a/noir/noir-repo/yarn.lock b/noir/noir-repo/yarn.lock index b45678f5d8b..e9915882fac 100644 --- a/noir/noir-repo/yarn.lock +++ b/noir/noir-repo/yarn.lock @@ -221,18 +221,19 @@ __metadata: languageName: node linkType: hard -"@aztec/bb.js@portal:../../../../barretenberg/ts::locator=%40noir-lang%2Fbackend_barretenberg%40workspace%3Atooling%2Fnoir_js_backend_barretenberg": - version: 0.0.0-use.local - resolution: "@aztec/bb.js@portal:../../../../barretenberg/ts::locator=%40noir-lang%2Fbackend_barretenberg%40workspace%3Atooling%2Fnoir_js_backend_barretenberg" +"@aztec/bb.js@npm:0.35.1": + version: 0.35.1 + resolution: "@aztec/bb.js@npm:0.35.1" dependencies: comlink: ^4.4.1 commander: ^10.0.1 debug: ^4.3.4 tslib: ^2.4.0 bin: - bb.js: ./dest/node/main.js + bb.js: dest/node/main.js + checksum: 8e3551f059523d9494af4721a9219e2c6e63c8ed1df447a2d0daa9f8526a794758ae708bd1d9c9b1fbfb89c56dc867d9f0b87250dbabfcde23ec02dabbb5a32a languageName: node - linkType: soft + linkType: hard "@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.12.11, @babel/code-frame@npm:^7.16.0, @babel/code-frame@npm:^7.22.13, @babel/code-frame@npm:^7.23.5, @babel/code-frame@npm:^7.8.3": version: 7.23.5 @@ -4395,7 +4396,7 @@ __metadata: version: 0.0.0-use.local resolution: "@noir-lang/backend_barretenberg@workspace:tooling/noir_js_backend_barretenberg" dependencies: - "@aztec/bb.js": "portal:../../../../barretenberg/ts" + "@aztec/bb.js": 0.35.1 "@noir-lang/types": "workspace:*" "@types/node": ^20.6.2 "@types/prettier": ^3 From 100744f89b676a03990c2d29aa0b48da77be5d8d Mon Sep 17 00:00:00 2001 From: Miranda Wood Date: Tue, 23 Apr 2024 13:52:52 +0100 Subject: [PATCH 082/102] fix: args + selector in deploy.nr (#5948) Quick fix for contracts using the `deploy_contract` method after changes to the instance deployer signature (tested using e2e deploy). --- noir-projects/aztec-nr/aztec/src/deploy.nr | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/deploy.nr b/noir-projects/aztec-nr/aztec/src/deploy.nr index 53fda2bee03..9b138875d5b 100644 --- a/noir-projects/aztec-nr/aztec/src/deploy.nr +++ b/noir-projects/aztec-nr/aztec/src/deploy.nr @@ -16,7 +16,7 @@ pub fn deploy_contract(context: &mut PrivateContext, target: AztecAddress) { // Adapted from noir-contracts/contracts/contract_instance_deployer_contract/src/interface/ContractInstanceDeployer.nr // That file was autogenerated running the following command from noir-projects/noir-contracts: // ../../yarn-project/node_modules/.bin/aztec-cli codegen target/contract_instance_deployer_contract-ContractInstanceDeployer.json --nr -o ./contracts/contract_instance_deployer_contract/src/interface - let mut serialized_args = [0; 6]; + let mut serialized_args = [0; 5]; serialized_args[0] = instance.salt; serialized_args[1] = instance.contract_class_id.to_field(); serialized_args[2] = instance.initialization_hash; @@ -25,7 +25,7 @@ pub fn deploy_contract(context: &mut PrivateContext, target: AztecAddress) { let _call_result = context.call_private_function( AztecAddress::from_field(DEPLOYER_CONTRACT_ADDRESS), - FunctionSelector::from_field(0x883355ab), + FunctionSelector::from_field(0x7ebd3690), serialized_args ); } From a51663707b96914b0a300440611748ce44fbe933 Mon Sep 17 00:00:00 2001 From: Ilyas Ridhuan Date: Tue, 23 Apr 2024 14:11:52 +0100 Subject: [PATCH 083/102] feat(avm): shift relations (#5716) Please read [contributing guidelines](CONTRIBUTING.md) and remove this line. --- barretenberg/cpp/CMakeLists.txt | 1 + barretenberg/cpp/pil/avm/avm_alu.pil | 134 ++++- barretenberg/cpp/pil/avm/avm_main.pil | 26 +- .../relations/generated/avm/avm_alu.hpp | 484 ++++++++++++------ .../relations/generated/avm/avm_main.hpp | 219 ++++---- .../relations/generated/avm/declare_views.hpp | 16 + .../generated/avm/lookup_pow_2_0.hpp | 170 ++++++ .../generated/avm/lookup_pow_2_1.hpp | 170 ++++++ .../relations/generated/avm/perm_main_alu.hpp | 10 +- .../relations/generated/avm/pow_2_lookups.hpp | 170 ++++++ .../vm/avm_trace/avm_alu_trace.cpp | 253 ++++++++- .../vm/avm_trace/avm_alu_trace.hpp | 11 + .../vm/avm_trace/avm_deserialization.cpp | 2 + .../vm/avm_trace/avm_execution.cpp | 14 + .../barretenberg/vm/avm_trace/avm_helper.cpp | 122 ++--- .../barretenberg/vm/avm_trace/avm_trace.cpp | 129 ++++- .../barretenberg/vm/avm_trace/avm_trace.hpp | 6 + .../vm/generated/avm_circuit_builder.hpp | 42 +- .../barretenberg/vm/generated/avm_flavor.hpp | 150 +++++- .../barretenberg/vm/generated/avm_prover.cpp | 30 ++ .../vm/generated/avm_verifier.cpp | 24 + .../vm/tests/avm_bitwise.test.cpp | 115 ++++- 22 files changed, 1934 insertions(+), 364 deletions(-) create mode 100644 barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_pow_2_0.hpp create mode 100644 barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_pow_2_1.hpp create mode 100644 barretenberg/cpp/src/barretenberg/relations/generated/avm/pow_2_lookups.hpp diff --git a/barretenberg/cpp/CMakeLists.txt b/barretenberg/cpp/CMakeLists.txt index 6a6f3170757..f33ff1034bd 100644 --- a/barretenberg/cpp/CMakeLists.txt +++ b/barretenberg/cpp/CMakeLists.txt @@ -80,6 +80,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED TRUE) set(CMAKE_CXX_EXTENSIONS ON) if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-fbracket-depth=512) if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "14") message(WARNING "Clang <14 is not supported") endif() diff --git a/barretenberg/cpp/pil/avm/avm_alu.pil b/barretenberg/cpp/pil/avm/avm_alu.pil index cc39ef9ca7e..35771b3fb48 100644 --- a/barretenberg/cpp/pil/avm/avm_alu.pil +++ b/barretenberg/cpp/pil/avm/avm_alu.pil @@ -23,7 +23,10 @@ namespace avm_alu(256); pol commit op_lt; pol commit op_lte; pol commit cmp_sel; // Predicate if LT or LTE is set - pol commit rng_chk_sel; // Predicate representing a range check row used in LT/LTE. + pol commit rng_chk_sel; // Predicate representing a range check row. + pol commit op_shl; + pol commit op_shr; + pol commit shift_sel; // Predicate if SHR or SHR is set // Instruction tag (1: u8, 2: u16, 3: u32, 4: u64, 5: u128, 6: field) copied from Main table pol commit in_tag; @@ -61,8 +64,9 @@ namespace avm_alu(256); pol commit cf; // Compute predicate telling whether there is a row entry in the ALU table. - alu_sel = op_add + op_sub + op_mul + op_not + op_eq + op_cast + op_lt + op_lte; + alu_sel = op_add + op_sub + op_mul + op_not + op_eq + op_cast + op_lt + op_lte + op_shr + op_shl; cmp_sel = op_lt + op_lte; + shift_sel = op_shl + op_shr; // ========= Type Constraints ============================================= // TODO: Range constraints @@ -355,7 +359,7 @@ namespace avm_alu(256); // (b) IS_GT = 1 - ic = 0 // (c) res_lo = B_SUB_A_LO and res_hi = B_SUB_A_HI // (d) res_lo = y_lo - x_lo + borrow * 2**128 and res_hi = y_hi - x_hi - borrow. - // (e) Due to 128-bit range checks on res_lo, res_hi, y_lo, x_lo, y_hi, y_lo, we + // (e) Due to 128-bit range checks on res_lo, res_hi, y_lo, x_lo, y_hi, x_hi, we // have the guarantee that res_lo >= 0 && res_hi >= 0. Furthermore, borrow is // boolean and so we have two cases to consider: // (i) borrow == 0 ==> y_lo >= x_lo && y_hi >= x_hi @@ -368,7 +372,7 @@ namespace avm_alu(256); // (b) IS_GT = 1 - ic = 1 // (c) res_lo = A_SUB_B_LO and res_hi = A_SUB_B_HI // (d) res_lo = x_lo - y_lo - 1 + borrow * 2**128 and res_hi = x_hi - y_hi - borrow. - // (e) Due to 128-bit range checks on res_lo, res_hi, y_lo, x_lo, y_hi, y_lo, we + // (e) Due to 128-bit range checks on res_lo, res_hi, y_lo, x_lo, y_hi, x_hi, we // have the guarantee that res_lo >= 0 && res_hi >= 0. Furthermore, borrow is // boolean and so we have two cases to consider: // (i) borrow == 0 ==> x_lo > y_lo && x_hi >= y_hi @@ -383,7 +387,7 @@ namespace avm_alu(256); // (b) IS_GT = ic = 1 // (c) res_lo = A_SUB_B_LO and res_hi = A_SUB_B_HI, **remember we have swapped inputs** // (d) res_lo = y_lo - x_lo - 1 + borrow * 2**128 and res_hi = y_hi - x_hi - borrow. - // (e) Due to 128-bit range checks on res_lo, res_hi, y_lo, x_lo, y_hi, y_lo, we + // (e) Due to 128-bit range checks on res_lo, res_hi, y_lo, x_lo, y_hi, x_hi, we // have the guarantee that res_lo >= 0 && res_hi >= 0. Furthermore, borrow is // boolean and so we have two cases to consider: // (i) borrow == 0 ==> y_lo > x_lo && y_hi >= x_hi @@ -395,8 +399,8 @@ namespace avm_alu(256); // (a) We DO swap the operands, so a = y and b = x, // (b) IS_GT = ic = 0 // (c) res_lo = B_SUB_A_LO and res_hi = B_SUB_A_HI, **remember we have swapped inputs** - // (d) res_lo = x_lo - y_lo + borrow * 2**128 and res_hi = x_hi - y_hi - borrow. - // (e) Due to 128-bit range checks on res_lo, res_hi, y_lo, x_lo, y_hi, y_lo, we + // (d) res_lo = a_lo - y_lo + borrow * 2**128 and res_hi = a_hi - y_hi - borrow. + // (e) Due to 128-bit range checks on res_lo, res_hi, y_lo, x_lo, y_hi, x_hi, we // have the guarantee that res_lo >= 0 && res_hi >= 0. Furthermore, borrow is // boolean and so we have two cases to consider: // (i) borrow == 0 ==> x_lo >= y_lo && x_hi >= y_hi @@ -434,11 +438,13 @@ namespace avm_alu(256); cmp_rng_ctr * ((1 - rng_chk_sel) * (1 - op_eq_diff_inv) + op_eq_diff_inv) - rng_chk_sel = 0; // We perform a range check if we have some range checks remaining or we are performing a comparison op - pol RNG_CHK_OP = rng_chk_sel + cmp_sel + op_cast + op_cast_prev; + pol RNG_CHK_OP = rng_chk_sel + cmp_sel + op_cast + op_cast_prev + shift_lt_bit_len; pol commit rng_chk_lookup_selector; + // TODO: Possible optimisation here if we swap the op_shl and op_shr with shift_lt_bit_len. + // Shift_lt_bit_len is a more restrictive form therefore we can avoid performing redundant range checks when we know the result == 0. #[RNG_CHK_LOOKUP_SELECTOR] - rng_chk_lookup_selector' = cmp_sel' + rng_chk_sel' + op_add' + op_sub' + op_mul' + op_mul * u128_tag + op_cast' + op_cast_prev'; + rng_chk_lookup_selector' = cmp_sel' + rng_chk_sel' + op_add' + op_sub' + op_mul' + op_mul * u128_tag + op_cast' + op_cast_prev' + op_shl' + op_shr'; // Perform 128-bit range check on lo part #[LOWER_CMP_RNG_CHK] @@ -469,7 +475,6 @@ namespace avm_alu(256); (p_sub_b_lo' - res_lo) * rng_chk_sel'= 0; (p_sub_b_hi' - res_hi) * rng_chk_sel'= 0; - // ========= CAST Operation Constraints =============================== // We handle the input ia independently of its tag, i.e., we suppose it can take // any value between 0 and p-1. @@ -509,4 +514,111 @@ namespace avm_alu(256); // 128-bit multiplication and CAST need two rows in ALU trace. We need to ensure // that another ALU operation does not start in the second row. #[TWO_LINE_OP_NO_OVERLAP] - (op_mul * ff_tag + op_cast) * alu_sel' = 0; \ No newline at end of file + (op_mul * ff_tag + op_cast) * alu_sel' = 0; + + // ========= SHIFT LEFT/RIGHT OPERATIONS =============================== + // Given (1) an input b, within the range [0, 2**128-1], + // (2) a value s, the amount of bits to shift b by, + // (3) and a memory tag, mem_tag that supports a maximum of t bits. + // Split input b into Big Endian hi and lo limbs, (we re-use the b_hi and b_lo columns we used for the comparison operators) + // b_hi and b_lo, and the number of bits represented by the memory tag, t. + // If we are shifting by more than the bit length represented by the memory tag, the result is trivially zero + // + // === Steps when performing SHR + // (1) Prove the correct decomposition: b_hi * 2**s + b_lo = b + // (2) Range check b_hi < 2**(t-s) && b_lo < 2**s, ensure we have not overflowed the limbs during decomp + // (3) Return b_hi + // + // <--(t-s) bits --> | <-- s bits --> + // -------------------|------------------- + // | b_hi | b_lo | --> b + // --------------------------------------- + // + // === Steps when performing SHL + // (1) Prove the correct decomposition: b_hi * 2**(t-s) + b_lo = b + // (2) Range check b_hi < 2**s && b_lo < 2**(t-s) + // (3) Return b_lo * 2**s + // + // <-- s bits --> | <-- (t-s) bits --> + // ------------------|------------------- + // | b_hi | b_lo | --> b + // -------------------------------------- + + // Check that b_lo and b_hi are range checked such that: + // SHR: b_hi < 2**(t - s) && b_lo < 2**s + // SHL: b_hi < 2**s && b_lo < 2**(t - s) + + // In lieu of a variable length check, we can utilise 2 fixed range checks instead. + // Given the dynamic range check of 0 <= b_hi < 2**(t-s), where s < t + // (1) 0 <= b_hi < 2**128 + // (2) 0 <= 2**(t - s) - b_hi < 2**128 + // Note that (1) is guaranteed elsewhere through the tagged memory model, so we focus on (2) here. + + // === General Notes: + // There are probably ways to merge various relations for the SHL/SHR, but they are separate + // now while we are still figuring out. + + + // We re-use the a_lo and a_hi cols from the comparison operators for the range checks + // SHR: (1) a_lo = 2**s - b_lo, (2) a_hi = 2**(t-s) - b_hi + // === Range checks: (1) a_lo < 2**128, (2) a_hi < 2**128. + #[SHR_RANGE_0] + shift_lt_bit_len * op_shr * (a_lo - (two_pow_s - b_lo - 1)) = 0; + #[SHR_RANGE_1] + shift_lt_bit_len * op_shr * (a_hi - (two_pow_t_sub_s - b_hi - 1)) = 0; + + // SHL: (1) a_lo = 2**(t-s) - b_lo, (2) a_hi = 2**s - b_hi + // === Range checks: (1) a_lo < 2**128, (2) a_hi < 2**128. + #[SHL_RANGE_0] + shift_lt_bit_len * op_shl * (a_lo - (two_pow_t_sub_s - b_lo - 1)) = 0; + #[SHL_RANGE_1] + shift_lt_bit_len * op_shl * (a_hi - (two_pow_s - b_hi - 1)) = 0; + + // Indicate if the shift amount < MAX_BITS + pol commit shift_lt_bit_len; + shift_lt_bit_len * (1 - shift_lt_bit_len) = 0; + + // The number of bits represented by the memory tag, any shifts greater than this will result in zero. + pol MAX_BITS = u8_tag * 8 + + u16_tag * 16 + + u32_tag * 32 + + u64_tag * 64 + + u128_tag * 128; + + // The result of MAX_BITS - ib, this used as part of the range check with the main trace + pol commit t_sub_s_bits; + + // Lookups for powers of 2. + // 2**(MAX_BITS - ib), constrained as part of the range check to the main trace + pol commit two_pow_t_sub_s; + // 2 ** ib, constrained as part of the range check to the main trace + pol commit two_pow_s; + + // For our assumptions to hold, we must check that s < MAX_BITS. This can be achieved by the following relation. + // We check if s <= MAX_BITS || s >= MAX_BITS using boolean shift_lt_bit_len. + // Regardless of which side is evaluated, the value of t_sub_s_bits < 2**8 + // There is no chance of an underflow involving ib to result in a t_sub_b_bits < 2**8 ib is range checked to be < 2**8 + // The range checking of t_sub_b_bits in the range [0, 2**8) is done by the lookup for 2**t_sub_s_bits + #[SHIFT_LT_BIT_LEN] + t_sub_s_bits = shift_sel * (shift_lt_bit_len * (MAX_BITS - ib) + (1 - shift_lt_bit_len) * (ib - MAX_BITS)); + + // ========= SHIFT RIGHT OPERATIONS =============================== + // a_hi * 2**s + a_lo = a + // If ib >= MAX_BITS, we trivially skip this check since the result will be forced to 0. + #[SHR_INPUT_DECOMPOSITION] + shift_lt_bit_len * op_shr * ((b_hi * two_pow_s + b_lo) - ia) = 0; + + // Return hi limb, if ib >= MAX_BITS, the output is forced to be 0 + #[SHR_OUTPUT] + op_shr * (ic - (b_hi * shift_lt_bit_len)) = 0; + + // ========= SHIFT LEFT OPERATIONS =============================== + // a_hi * 2**(t-s) + a_lo = a + // If ib >= MAX_BITS, we trivially skip this check since the result will be forced to 0. + #[SHL_INPUT_DECOMPOSITION] + shift_lt_bit_len * op_shl * ((b_hi * two_pow_t_sub_s + b_lo) - ia) = 0; + + // Return lo limb a_lo * 2**s, if ib >= MAX_BITS, the output is forced to be 0 + #[SHL_OUTPUT] + op_shl * (ic - (b_lo * two_pow_s * shift_lt_bit_len)) = 0; + diff --git a/barretenberg/cpp/pil/avm/avm_main.pil b/barretenberg/cpp/pil/avm/avm_main.pil index f4ce7214edb..74ce4b93574 100644 --- a/barretenberg/cpp/pil/avm/avm_main.pil +++ b/barretenberg/cpp/pil/avm/avm_main.pil @@ -15,6 +15,9 @@ namespace avm_main(256); pol commit sel_rng_8; // Boolean selector for the 8-bit range check lookup pol commit sel_rng_16; // Boolean selector for the 16-bit range check lookup + //===== Lookup table powers of 2 ============================================= + pol commit table_pow_2; // Table of powers of 2 for 8-bit numbers. + //===== CONTROL FLOW ========================================================== // Program counter pol commit pc; @@ -60,6 +63,10 @@ namespace avm_main(256); pol commit sel_op_lt; // LTE pol commit sel_op_lte; + // SHL + pol commit sel_op_shl; + // SHR + pol commit sel_op_shr; // Helper selector to characterize an ALU chiplet selector pol commit alu_sel; @@ -138,6 +145,8 @@ namespace avm_main(256); sel_op_cast * (1 - sel_op_cast) = 0; sel_op_lt * (1 - sel_op_lt) = 0; sel_op_lte * (1 - sel_op_lte) = 0; + sel_op_shl * (1 - sel_op_shl) = 0; + sel_op_shr * (1 - sel_op_shr) = 0; sel_internal_call * (1 - sel_internal_call) = 0; sel_internal_return * (1 - sel_internal_return) = 0; @@ -295,7 +304,7 @@ namespace avm_main(256); //===== ALU CONSTRAINTS ===================================================== // TODO: when division is moved to the alu, we will need to add the selector in the list below. - pol ALU_R_TAG_SEL = sel_op_add + sel_op_sub + sel_op_mul + sel_op_not + sel_op_eq + sel_op_lt + sel_op_lte; + pol ALU_R_TAG_SEL = sel_op_add + sel_op_sub + sel_op_mul + sel_op_not + sel_op_eq + sel_op_lt + sel_op_lte + sel_op_shr + sel_op_shl; pol ALU_W_TAG_SEL = sel_op_cast; pol ALU_ALL_SEL = ALU_R_TAG_SEL + ALU_W_TAG_SEL; @@ -317,11 +326,11 @@ namespace avm_main(256); #[PERM_MAIN_ALU] alu_sel {clk, ia, ib, ic, sel_op_add, sel_op_sub, sel_op_mul, sel_op_eq, sel_op_not, sel_op_cast, - sel_op_lt, sel_op_lte, alu_in_tag} + sel_op_lt, sel_op_lte, sel_op_shr, sel_op_shl, alu_in_tag} is avm_alu.alu_sel {avm_alu.clk, avm_alu.ia, avm_alu.ib, avm_alu.ic, avm_alu.op_add, avm_alu.op_sub, avm_alu.op_mul, avm_alu.op_eq, avm_alu.op_not, avm_alu.op_cast, - avm_alu.op_lt, avm_alu.op_lte, avm_alu.in_tag}; + avm_alu.op_lt, avm_alu.op_lte, avm_alu.op_shr, avm_alu.op_shl, avm_alu.in_tag}; // Based on the boolean selectors, we derive the binary op id to lookup in the table; // TODO: Check if having 4 columns (op_id + 3 boolean selectors) is more optimal that just using the op_id @@ -379,6 +388,17 @@ namespace avm_main(256); #[PERM_MAIN_MEM_IND_D] ind_op_d {clk, ind_d, mem_idx_d} is avm_mem.ind_op_d {avm_mem.clk, avm_mem.addr, avm_mem.val}; + //====== Inter-table Shift Constraints (Lookups) ============================================ + // Currently only used for shift operations but can be generalised for other uses. + + // Lookup for 2**(ib) + #[LOOKUP_POW_2_0] + avm_alu.shift_sel {avm_alu.ib, avm_alu.two_pow_s} in sel_rng_8 {clk, table_pow_2}; + + // Lookup for 2**(t-ib) + #[LOOKUP_POW_2_1] + avm_alu.shift_sel {avm_alu.t_sub_s_bits , avm_alu.two_pow_t_sub_s} in sel_rng_8 {clk, table_pow_2}; + //====== Inter-table Constraints (Range Checks) ============================================ // TODO: Investigate optimising these range checks. Handling non-FF elements should require less range checks. // One can increase the granularity based on the operation and tag. In the most extreme case, diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/avm_alu.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/avm_alu.hpp index ac09315024a..95ced4b652b 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/avm_alu.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/avm_alu.hpp @@ -41,6 +41,10 @@ template struct Avm_aluRow { FF avm_alu_op_mul{}; FF avm_alu_op_mul_shift{}; FF avm_alu_op_not{}; + FF avm_alu_op_shl{}; + FF avm_alu_op_shl_shift{}; + FF avm_alu_op_shr{}; + FF avm_alu_op_shr_shift{}; FF avm_alu_op_sub{}; FF avm_alu_op_sub_shift{}; FF avm_alu_p_a_borrow{}; @@ -58,6 +62,11 @@ template struct Avm_aluRow { FF avm_alu_rng_chk_lookup_selector_shift{}; FF avm_alu_rng_chk_sel{}; FF avm_alu_rng_chk_sel_shift{}; + FF avm_alu_shift_lt_bit_len{}; + FF avm_alu_shift_sel{}; + FF avm_alu_t_sub_s_bits{}; + FF avm_alu_two_pow_s{}; + FF avm_alu_two_pow_t_sub_s{}; FF avm_alu_u128_tag{}; FF avm_alu_u16_r0{}; FF avm_alu_u16_r0_shift{}; @@ -94,104 +103,131 @@ template struct Avm_aluRow { inline std::string get_relation_label_avm_alu(int index) { switch (index) { - case 11: + case 12: return "ALU_ADD_SUB_1"; - case 12: + case 13: return "ALU_ADD_SUB_2"; - case 13: + case 14: return "ALU_MULTIPLICATION_FF"; - case 14: + case 15: return "ALU_MUL_COMMON_1"; - case 15: + case 16: return "ALU_MUL_COMMON_2"; - case 18: + case 19: return "ALU_MULTIPLICATION_OUT_U128"; - case 19: + case 20: return "ALU_FF_NOT_XOR"; - case 20: + case 21: return "ALU_OP_NOT"; - case 21: + case 22: return "ALU_RES_IS_BOOL"; - case 22: + case 23: return "ALU_OP_EQ"; - case 23: + case 24: return "INPUT_DECOMP_1"; - case 24: + case 25: return "INPUT_DECOMP_2"; - case 26: + case 27: return "SUB_LO_1"; - case 27: + case 28: return "SUB_HI_1"; - case 29: + case 30: return "SUB_LO_2"; - case 30: + case 31: return "SUB_HI_2"; - case 31: + case 32: return "RES_LO"; - case 32: + case 33: return "RES_HI"; - case 33: + case 34: return "CMP_CTR_REL_1"; - case 34: + case 35: return "CMP_CTR_REL_2"; - case 37: + case 38: return "CTR_NON_ZERO_REL"; - case 38: + case 39: return "RNG_CHK_LOOKUP_SELECTOR"; - case 39: + case 40: return "LOWER_CMP_RNG_CHK"; - case 40: + case 41: return "UPPER_CMP_RNG_CHK"; - case 41: + case 42: return "SHIFT_RELS_0"; - case 43: + case 44: return "SHIFT_RELS_1"; - case 45: + case 46: return "SHIFT_RELS_2"; - case 47: + case 48: return "SHIFT_RELS_3"; - case 49: + case 50: return "OP_CAST_PREV_LINE"; - case 50: + case 51: return "ALU_OP_CAST"; - case 51: + case 52: return "OP_CAST_RNG_CHECK_P_SUB_A_LOW"; - case 52: + case 53: return "OP_CAST_RNG_CHECK_P_SUB_A_HIGH"; - case 53: + case 54: return "TWO_LINE_OP_NO_OVERLAP"; + + case 55: + return "SHR_RANGE_0"; + + case 56: + return "SHR_RANGE_1"; + + case 57: + return "SHL_RANGE_0"; + + case 58: + return "SHL_RANGE_1"; + + case 60: + return "SHIFT_LT_BIT_LEN"; + + case 61: + return "SHR_INPUT_DECOMPOSITION"; + + case 62: + return "SHR_OUTPUT"; + + case 63: + return "SHL_INPUT_DECOMPOSITION"; + + case 64: + return "SHL_OUTPUT"; } return std::to_string(index); } @@ -200,9 +236,9 @@ template class avm_aluImpl { public: using FF = FF_; - static constexpr std::array SUBRELATION_PARTIAL_LENGTHS{ - 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 5, 5, 5, 5, 6, 6, 8, 3, 4, 4, 5, 4, 4, 3, 4, - 3, 3, 4, 3, 6, 5, 3, 3, 3, 3, 4, 3, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 2, 5, 3, 3, 4, + static constexpr std::array SUBRELATION_PARTIAL_LENGTHS{ + 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 5, 5, 5, 5, 6, 6, 8, 3, 4, 4, 5, 4, 4, 3, 4, 3, 3, 4, 3, 6, + 5, 3, 3, 3, 3, 4, 3, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 2, 5, 3, 3, 4, 4, 4, 4, 4, 3, 5, 5, 4, 5, 5, }; template @@ -217,10 +253,12 @@ template class avm_aluImpl { Avm_DECLARE_VIEWS(0); auto tmp = (avm_alu_alu_sel - - (((((((avm_alu_op_add + avm_alu_op_sub) + avm_alu_op_mul) + avm_alu_op_not) + avm_alu_op_eq) + - avm_alu_op_cast) + - avm_alu_op_lt) + - avm_alu_op_lte)); + (((((((((avm_alu_op_add + avm_alu_op_sub) + avm_alu_op_mul) + avm_alu_op_not) + avm_alu_op_eq) + + avm_alu_op_cast) + + avm_alu_op_lt) + + avm_alu_op_lte) + + avm_alu_op_shr) + + avm_alu_op_shl)); tmp *= scaling_factor; std::get<0>(evals) += tmp; } @@ -236,7 +274,7 @@ template class avm_aluImpl { { Avm_DECLARE_VIEWS(2); - auto tmp = (avm_alu_cf * (-avm_alu_cf + FF(1))); + auto tmp = (avm_alu_shift_sel - (avm_alu_op_shl + avm_alu_op_shr)); tmp *= scaling_factor; std::get<2>(evals) += tmp; } @@ -244,7 +282,7 @@ template class avm_aluImpl { { Avm_DECLARE_VIEWS(3); - auto tmp = (avm_alu_ff_tag * (-avm_alu_ff_tag + FF(1))); + auto tmp = (avm_alu_cf * (-avm_alu_cf + FF(1))); tmp *= scaling_factor; std::get<3>(evals) += tmp; } @@ -252,7 +290,7 @@ template class avm_aluImpl { { Avm_DECLARE_VIEWS(4); - auto tmp = (avm_alu_u8_tag * (-avm_alu_u8_tag + FF(1))); + auto tmp = (avm_alu_ff_tag * (-avm_alu_ff_tag + FF(1))); tmp *= scaling_factor; std::get<4>(evals) += tmp; } @@ -260,7 +298,7 @@ template class avm_aluImpl { { Avm_DECLARE_VIEWS(5); - auto tmp = (avm_alu_u16_tag * (-avm_alu_u16_tag + FF(1))); + auto tmp = (avm_alu_u8_tag * (-avm_alu_u8_tag + FF(1))); tmp *= scaling_factor; std::get<5>(evals) += tmp; } @@ -268,7 +306,7 @@ template class avm_aluImpl { { Avm_DECLARE_VIEWS(6); - auto tmp = (avm_alu_u32_tag * (-avm_alu_u32_tag + FF(1))); + auto tmp = (avm_alu_u16_tag * (-avm_alu_u16_tag + FF(1))); tmp *= scaling_factor; std::get<6>(evals) += tmp; } @@ -276,7 +314,7 @@ template class avm_aluImpl { { Avm_DECLARE_VIEWS(7); - auto tmp = (avm_alu_u64_tag * (-avm_alu_u64_tag + FF(1))); + auto tmp = (avm_alu_u32_tag * (-avm_alu_u32_tag + FF(1))); tmp *= scaling_factor; std::get<7>(evals) += tmp; } @@ -284,7 +322,7 @@ template class avm_aluImpl { { Avm_DECLARE_VIEWS(8); - auto tmp = (avm_alu_u128_tag * (-avm_alu_u128_tag + FF(1))); + auto tmp = (avm_alu_u64_tag * (-avm_alu_u64_tag + FF(1))); tmp *= scaling_factor; std::get<8>(evals) += tmp; } @@ -292,28 +330,36 @@ template class avm_aluImpl { { Avm_DECLARE_VIEWS(9); + auto tmp = (avm_alu_u128_tag * (-avm_alu_u128_tag + FF(1))); + tmp *= scaling_factor; + std::get<9>(evals) += tmp; + } + // Contribution 10 + { + Avm_DECLARE_VIEWS(10); + auto tmp = (avm_alu_alu_sel * ((((((avm_alu_ff_tag + avm_alu_u8_tag) + avm_alu_u16_tag) + avm_alu_u32_tag) + avm_alu_u64_tag) + avm_alu_u128_tag) - FF(1))); tmp *= scaling_factor; - std::get<9>(evals) += tmp; + std::get<10>(evals) += tmp; } - // Contribution 10 + // Contribution 11 { - Avm_DECLARE_VIEWS(10); + Avm_DECLARE_VIEWS(11); auto tmp = (avm_alu_in_tag - (((((avm_alu_u8_tag + (avm_alu_u16_tag * FF(2))) + (avm_alu_u32_tag * FF(3))) + (avm_alu_u64_tag * FF(4))) + (avm_alu_u128_tag * FF(5))) + (avm_alu_ff_tag * FF(6)))); tmp *= scaling_factor; - std::get<10>(evals) += tmp; + std::get<11>(evals) += tmp; } - // Contribution 11 + // Contribution 12 { - Avm_DECLARE_VIEWS(11); + Avm_DECLARE_VIEWS(12); auto tmp = (((avm_alu_op_add + avm_alu_op_sub) * ((((((((((avm_alu_u8_r0 + (avm_alu_u8_r1 * FF(256))) + (avm_alu_u16_r0 * FF(65536))) + @@ -328,11 +374,11 @@ template class avm_aluImpl { ((avm_alu_op_add - avm_alu_op_sub) * ((avm_alu_cf * FF(uint256_t{ 0UL, 0UL, 1UL, 0UL })) - avm_alu_ib))); tmp *= scaling_factor; - std::get<11>(evals) += tmp; + std::get<12>(evals) += tmp; } - // Contribution 12 + // Contribution 13 { - Avm_DECLARE_VIEWS(12); + Avm_DECLARE_VIEWS(13); auto tmp = (((avm_alu_op_add + avm_alu_op_sub) * (((((((avm_alu_u8_tag * avm_alu_u8_r0) + @@ -355,19 +401,19 @@ template class avm_aluImpl { avm_alu_ic)) + ((avm_alu_ff_tag * (avm_alu_op_add - avm_alu_op_sub)) * avm_alu_ib)); tmp *= scaling_factor; - std::get<12>(evals) += tmp; + std::get<13>(evals) += tmp; } - // Contribution 13 + // Contribution 14 { - Avm_DECLARE_VIEWS(13); + Avm_DECLARE_VIEWS(14); auto tmp = ((avm_alu_ff_tag * avm_alu_op_mul) * ((avm_alu_ia * avm_alu_ib) - avm_alu_ic)); tmp *= scaling_factor; - std::get<13>(evals) += tmp; + std::get<14>(evals) += tmp; } - // Contribution 14 + // Contribution 15 { - Avm_DECLARE_VIEWS(14); + Avm_DECLARE_VIEWS(15); auto tmp = ((((-avm_alu_ff_tag + FF(1)) - avm_alu_u128_tag) * avm_alu_op_mul) * (((((((((avm_alu_u8_r0 + (avm_alu_u8_r1 * FF(256))) + (avm_alu_u16_r0 * FF(65536))) + @@ -379,11 +425,11 @@ template class avm_aluImpl { (avm_alu_u16_r6 * FF(uint256_t{ 0UL, 281474976710656UL, 0UL, 0UL }))) - (avm_alu_ia * avm_alu_ib))); tmp *= scaling_factor; - std::get<14>(evals) += tmp; + std::get<15>(evals) += tmp; } - // Contribution 15 + // Contribution 16 { - Avm_DECLARE_VIEWS(15); + Avm_DECLARE_VIEWS(16); auto tmp = (avm_alu_op_mul * @@ -395,11 +441,11 @@ template class avm_aluImpl { (avm_alu_u16_r2 * FF(281474976710656UL))))) - (((-avm_alu_ff_tag + FF(1)) - avm_alu_u128_tag) * avm_alu_ic))); tmp *= scaling_factor; - std::get<15>(evals) += tmp; + std::get<16>(evals) += tmp; } - // Contribution 16 + // Contribution 17 { - Avm_DECLARE_VIEWS(16); + Avm_DECLARE_VIEWS(17); auto tmp = ((avm_alu_u128_tag * avm_alu_op_mul) * ((((((avm_alu_u8_r0 + (avm_alu_u8_r1 * FF(256))) + (avm_alu_u16_r0 * FF(65536))) + @@ -410,11 +456,11 @@ template class avm_aluImpl { FF(uint256_t{ 0UL, 1UL, 0UL, 0UL }))) - avm_alu_ia)); tmp *= scaling_factor; - std::get<16>(evals) += tmp; + std::get<17>(evals) += tmp; } - // Contribution 17 + // Contribution 18 { - Avm_DECLARE_VIEWS(17); + Avm_DECLARE_VIEWS(18); auto tmp = ((avm_alu_u128_tag * avm_alu_op_mul) * @@ -427,11 +473,11 @@ template class avm_aluImpl { FF(uint256_t{ 0UL, 1UL, 0UL, 0UL }))) - avm_alu_ib)); tmp *= scaling_factor; - std::get<17>(evals) += tmp; + std::get<18>(evals) += tmp; } - // Contribution 18 + // Contribution 19 { - Avm_DECLARE_VIEWS(18); + Avm_DECLARE_VIEWS(19); auto tmp = ((avm_alu_u128_tag * avm_alu_op_mul) * @@ -452,19 +498,19 @@ template class avm_aluImpl { FF(uint256_t{ 0UL, 0UL, 1UL, 0UL }))) - avm_alu_ic)); tmp *= scaling_factor; - std::get<18>(evals) += tmp; + std::get<19>(evals) += tmp; } - // Contribution 19 + // Contribution 20 { - Avm_DECLARE_VIEWS(19); + Avm_DECLARE_VIEWS(20); auto tmp = (avm_alu_op_not * avm_alu_ff_tag); tmp *= scaling_factor; - std::get<19>(evals) += tmp; + std::get<20>(evals) += tmp; } - // Contribution 20 + // Contribution 21 { - Avm_DECLARE_VIEWS(20); + Avm_DECLARE_VIEWS(21); auto tmp = (avm_alu_op_not * ((avm_alu_ia + avm_alu_ic) - ((((((avm_alu_u8_tag * FF(256)) + (avm_alu_u16_tag * FF(65536))) + @@ -473,25 +519,13 @@ template class avm_aluImpl { (avm_alu_u128_tag * FF(uint256_t{ 0UL, 0UL, 1UL, 0UL }))) - FF(1)))); tmp *= scaling_factor; - std::get<20>(evals) += tmp; - } - // Contribution 21 - { - Avm_DECLARE_VIEWS(21); - - auto tmp = ((avm_alu_cmp_sel + avm_alu_op_eq) * (avm_alu_ic * (-avm_alu_ic + FF(1)))); - tmp *= scaling_factor; std::get<21>(evals) += tmp; } // Contribution 22 { Avm_DECLARE_VIEWS(22); - auto tmp = - (avm_alu_op_eq * ((((avm_alu_ia - avm_alu_ib) * - ((avm_alu_ic * (-avm_alu_op_eq_diff_inv + FF(1))) + avm_alu_op_eq_diff_inv)) - - FF(1)) + - avm_alu_ic)); + auto tmp = ((avm_alu_cmp_sel + avm_alu_op_eq) * (avm_alu_ic * (-avm_alu_ic + FF(1)))); tmp *= scaling_factor; std::get<22>(evals) += tmp; } @@ -499,9 +533,11 @@ template class avm_aluImpl { { Avm_DECLARE_VIEWS(23); - auto tmp = (((avm_alu_op_lt * avm_alu_ib) + ((avm_alu_op_lte + avm_alu_op_cast) * avm_alu_ia)) - - ((avm_alu_a_lo + (avm_alu_a_hi * FF(uint256_t{ 0UL, 0UL, 1UL, 0UL }))) * - (avm_alu_cmp_sel + avm_alu_op_cast))); + auto tmp = + (avm_alu_op_eq * ((((avm_alu_ia - avm_alu_ib) * + ((avm_alu_ic * (-avm_alu_op_eq_diff_inv + FF(1))) + avm_alu_op_eq_diff_inv)) - + FF(1)) + + avm_alu_ic)); tmp *= scaling_factor; std::get<23>(evals) += tmp; } @@ -509,8 +545,9 @@ template class avm_aluImpl { { Avm_DECLARE_VIEWS(24); - auto tmp = (((avm_alu_op_lt * avm_alu_ia) + (avm_alu_op_lte * avm_alu_ib)) - - ((avm_alu_b_lo + (avm_alu_b_hi * FF(uint256_t{ 0UL, 0UL, 1UL, 0UL }))) * avm_alu_cmp_sel)); + auto tmp = (((avm_alu_op_lt * avm_alu_ib) + ((avm_alu_op_lte + avm_alu_op_cast) * avm_alu_ia)) - + ((avm_alu_a_lo + (avm_alu_a_hi * FF(uint256_t{ 0UL, 0UL, 1UL, 0UL }))) * + (avm_alu_cmp_sel + avm_alu_op_cast))); tmp *= scaling_factor; std::get<24>(evals) += tmp; } @@ -518,7 +555,8 @@ template class avm_aluImpl { { Avm_DECLARE_VIEWS(25); - auto tmp = (avm_alu_p_a_borrow * (-avm_alu_p_a_borrow + FF(1))); + auto tmp = (((avm_alu_op_lt * avm_alu_ia) + (avm_alu_op_lte * avm_alu_ib)) - + ((avm_alu_b_lo + (avm_alu_b_hi * FF(uint256_t{ 0UL, 0UL, 1UL, 0UL }))) * avm_alu_cmp_sel)); tmp *= scaling_factor; std::get<25>(evals) += tmp; } @@ -526,10 +564,7 @@ template class avm_aluImpl { { Avm_DECLARE_VIEWS(26); - auto tmp = ((avm_alu_p_sub_a_lo - - ((-avm_alu_a_lo + FF(uint256_t{ 4891460686036598784UL, 2896914383306846353UL, 0UL, 0UL })) + - (avm_alu_p_a_borrow * FF(uint256_t{ 0UL, 0UL, 1UL, 0UL })))) * - (avm_alu_cmp_sel + avm_alu_op_cast)); + auto tmp = (avm_alu_p_a_borrow * (-avm_alu_p_a_borrow + FF(1))); tmp *= scaling_factor; std::get<26>(evals) += tmp; } @@ -537,9 +572,9 @@ template class avm_aluImpl { { Avm_DECLARE_VIEWS(27); - auto tmp = ((avm_alu_p_sub_a_hi - - ((-avm_alu_a_hi + FF(uint256_t{ 13281191951274694749UL, 3486998266802970665UL, 0UL, 0UL })) - - avm_alu_p_a_borrow)) * + auto tmp = ((avm_alu_p_sub_a_lo - + ((-avm_alu_a_lo + FF(uint256_t{ 4891460686036598784UL, 2896914383306846353UL, 0UL, 0UL })) + + (avm_alu_p_a_borrow * FF(uint256_t{ 0UL, 0UL, 1UL, 0UL })))) * (avm_alu_cmp_sel + avm_alu_op_cast)); tmp *= scaling_factor; std::get<27>(evals) += tmp; @@ -548,7 +583,10 @@ template class avm_aluImpl { { Avm_DECLARE_VIEWS(28); - auto tmp = (avm_alu_p_b_borrow * (-avm_alu_p_b_borrow + FF(1))); + auto tmp = ((avm_alu_p_sub_a_hi - + ((-avm_alu_a_hi + FF(uint256_t{ 13281191951274694749UL, 3486998266802970665UL, 0UL, 0UL })) - + avm_alu_p_a_borrow)) * + (avm_alu_cmp_sel + avm_alu_op_cast)); tmp *= scaling_factor; std::get<28>(evals) += tmp; } @@ -556,27 +594,35 @@ template class avm_aluImpl { { Avm_DECLARE_VIEWS(29); + auto tmp = (avm_alu_p_b_borrow * (-avm_alu_p_b_borrow + FF(1))); + tmp *= scaling_factor; + std::get<29>(evals) += tmp; + } + // Contribution 30 + { + Avm_DECLARE_VIEWS(30); + auto tmp = ((avm_alu_p_sub_b_lo - ((-avm_alu_b_lo + FF(uint256_t{ 4891460686036598784UL, 2896914383306846353UL, 0UL, 0UL })) + (avm_alu_p_b_borrow * FF(uint256_t{ 0UL, 0UL, 1UL, 0UL })))) * avm_alu_cmp_sel); tmp *= scaling_factor; - std::get<29>(evals) += tmp; + std::get<30>(evals) += tmp; } - // Contribution 30 + // Contribution 31 { - Avm_DECLARE_VIEWS(30); + Avm_DECLARE_VIEWS(31); auto tmp = ((avm_alu_p_sub_b_hi - ((-avm_alu_b_hi + FF(uint256_t{ 13281191951274694749UL, 3486998266802970665UL, 0UL, 0UL })) - avm_alu_p_b_borrow)) * avm_alu_cmp_sel); tmp *= scaling_factor; - std::get<30>(evals) += tmp; + std::get<31>(evals) += tmp; } - // Contribution 31 + // Contribution 32 { - Avm_DECLARE_VIEWS(31); + Avm_DECLARE_VIEWS(32); auto tmp = ((avm_alu_res_lo - @@ -586,11 +632,11 @@ template class avm_aluImpl { (-((avm_alu_op_lt * avm_alu_ic) + ((-avm_alu_ic + FF(1)) * avm_alu_op_lte)) + FF(1))))) * avm_alu_cmp_sel); tmp *= scaling_factor; - std::get<31>(evals) += tmp; + std::get<32>(evals) += tmp; } - // Contribution 32 + // Contribution 33 { - Avm_DECLARE_VIEWS(32); + Avm_DECLARE_VIEWS(33); auto tmp = ((avm_alu_res_hi - ((((avm_alu_a_hi - avm_alu_b_hi) - avm_alu_borrow) * @@ -599,21 +645,13 @@ template class avm_aluImpl { (-((avm_alu_op_lt * avm_alu_ic) + ((-avm_alu_ic + FF(1)) * avm_alu_op_lte)) + FF(1))))) * avm_alu_cmp_sel); tmp *= scaling_factor; - std::get<32>(evals) += tmp; - } - // Contribution 33 - { - Avm_DECLARE_VIEWS(33); - - auto tmp = (((avm_alu_cmp_rng_ctr_shift - avm_alu_cmp_rng_ctr) + FF(1)) * avm_alu_cmp_rng_ctr); - tmp *= scaling_factor; std::get<33>(evals) += tmp; } // Contribution 34 { Avm_DECLARE_VIEWS(34); - auto tmp = ((avm_alu_cmp_rng_ctr_shift - FF(4)) * avm_alu_cmp_sel); + auto tmp = (((avm_alu_cmp_rng_ctr_shift - avm_alu_cmp_rng_ctr) + FF(1)) * avm_alu_cmp_rng_ctr); tmp *= scaling_factor; std::get<34>(evals) += tmp; } @@ -621,7 +659,7 @@ template class avm_aluImpl { { Avm_DECLARE_VIEWS(35); - auto tmp = (avm_alu_rng_chk_sel * (-avm_alu_rng_chk_sel + FF(1))); + auto tmp = ((avm_alu_cmp_rng_ctr_shift - FF(4)) * avm_alu_cmp_sel); tmp *= scaling_factor; std::get<35>(evals) += tmp; } @@ -629,7 +667,7 @@ template class avm_aluImpl { { Avm_DECLARE_VIEWS(36); - auto tmp = (avm_alu_rng_chk_sel * avm_alu_cmp_sel); + auto tmp = (avm_alu_rng_chk_sel * (-avm_alu_rng_chk_sel + FF(1))); tmp *= scaling_factor; std::get<36>(evals) += tmp; } @@ -637,9 +675,7 @@ template class avm_aluImpl { { Avm_DECLARE_VIEWS(37); - auto tmp = ((avm_alu_cmp_rng_ctr * (((-avm_alu_rng_chk_sel + FF(1)) * (-avm_alu_op_eq_diff_inv + FF(1))) + - avm_alu_op_eq_diff_inv)) - - avm_alu_rng_chk_sel); + auto tmp = (avm_alu_rng_chk_sel * avm_alu_cmp_sel); tmp *= scaling_factor; std::get<37>(evals) += tmp; } @@ -647,13 +683,9 @@ template class avm_aluImpl { { Avm_DECLARE_VIEWS(38); - auto tmp = (avm_alu_rng_chk_lookup_selector_shift - - (((((((avm_alu_cmp_sel_shift + avm_alu_rng_chk_sel_shift) + avm_alu_op_add_shift) + - avm_alu_op_sub_shift) + - avm_alu_op_mul_shift) + - (avm_alu_op_mul * avm_alu_u128_tag)) + - avm_alu_op_cast_shift) + - avm_alu_op_cast_prev_shift)); + auto tmp = ((avm_alu_cmp_rng_ctr * (((-avm_alu_rng_chk_sel + FF(1)) * (-avm_alu_op_eq_diff_inv + FF(1))) + + avm_alu_op_eq_diff_inv)) - + avm_alu_rng_chk_sel); tmp *= scaling_factor; std::get<38>(evals) += tmp; } @@ -661,6 +693,22 @@ template class avm_aluImpl { { Avm_DECLARE_VIEWS(39); + auto tmp = (avm_alu_rng_chk_lookup_selector_shift - + (((((((((avm_alu_cmp_sel_shift + avm_alu_rng_chk_sel_shift) + avm_alu_op_add_shift) + + avm_alu_op_sub_shift) + + avm_alu_op_mul_shift) + + (avm_alu_op_mul * avm_alu_u128_tag)) + + avm_alu_op_cast_shift) + + avm_alu_op_cast_prev_shift) + + avm_alu_op_shl_shift) + + avm_alu_op_shr_shift)); + tmp *= scaling_factor; + std::get<39>(evals) += tmp; + } + // Contribution 40 + { + Avm_DECLARE_VIEWS(40); + auto tmp = (avm_alu_a_lo - (((((((((avm_alu_u8_r0 + (avm_alu_u8_r1 * FF(256))) + (avm_alu_u16_r0 * FF(65536))) + (avm_alu_u16_r1 * FF(4294967296UL))) + @@ -669,13 +717,14 @@ template class avm_aluImpl { (avm_alu_u16_r4 * FF(uint256_t{ 0UL, 65536UL, 0UL, 0UL }))) + (avm_alu_u16_r5 * FF(uint256_t{ 0UL, 4294967296UL, 0UL, 0UL }))) + (avm_alu_u16_r6 * FF(uint256_t{ 0UL, 281474976710656UL, 0UL, 0UL }))) * - (((avm_alu_rng_chk_sel + avm_alu_cmp_sel) + avm_alu_op_cast) + avm_alu_op_cast_prev))); + ((((avm_alu_rng_chk_sel + avm_alu_cmp_sel) + avm_alu_op_cast) + avm_alu_op_cast_prev) + + avm_alu_shift_lt_bit_len))); tmp *= scaling_factor; - std::get<39>(evals) += tmp; + std::get<40>(evals) += tmp; } - // Contribution 40 + // Contribution 41 { - Avm_DECLARE_VIEWS(40); + Avm_DECLARE_VIEWS(41); auto tmp = (avm_alu_a_hi - ((((((((avm_alu_u16_r7 + (avm_alu_u16_r8 * FF(65536))) + (avm_alu_u16_r9 * FF(4294967296UL))) + @@ -684,15 +733,8 @@ template class avm_aluImpl { (avm_alu_u16_r12 * FF(uint256_t{ 0UL, 65536UL, 0UL, 0UL }))) + (avm_alu_u16_r13 * FF(uint256_t{ 0UL, 4294967296UL, 0UL, 0UL }))) + (avm_alu_u16_r14 * FF(uint256_t{ 0UL, 281474976710656UL, 0UL, 0UL }))) * - (((avm_alu_rng_chk_sel + avm_alu_cmp_sel) + avm_alu_op_cast) + avm_alu_op_cast_prev))); - tmp *= scaling_factor; - std::get<40>(evals) += tmp; - } - // Contribution 41 - { - Avm_DECLARE_VIEWS(41); - - auto tmp = ((avm_alu_a_lo_shift - avm_alu_b_lo) * avm_alu_rng_chk_sel_shift); + ((((avm_alu_rng_chk_sel + avm_alu_cmp_sel) + avm_alu_op_cast) + avm_alu_op_cast_prev) + + avm_alu_shift_lt_bit_len))); tmp *= scaling_factor; std::get<41>(evals) += tmp; } @@ -700,7 +742,7 @@ template class avm_aluImpl { { Avm_DECLARE_VIEWS(42); - auto tmp = ((avm_alu_a_hi_shift - avm_alu_b_hi) * avm_alu_rng_chk_sel_shift); + auto tmp = ((avm_alu_a_lo_shift - avm_alu_b_lo) * avm_alu_rng_chk_sel_shift); tmp *= scaling_factor; std::get<42>(evals) += tmp; } @@ -708,7 +750,7 @@ template class avm_aluImpl { { Avm_DECLARE_VIEWS(43); - auto tmp = ((avm_alu_b_lo_shift - avm_alu_p_sub_a_lo) * avm_alu_rng_chk_sel_shift); + auto tmp = ((avm_alu_a_hi_shift - avm_alu_b_hi) * avm_alu_rng_chk_sel_shift); tmp *= scaling_factor; std::get<43>(evals) += tmp; } @@ -716,7 +758,7 @@ template class avm_aluImpl { { Avm_DECLARE_VIEWS(44); - auto tmp = ((avm_alu_b_hi_shift - avm_alu_p_sub_a_hi) * avm_alu_rng_chk_sel_shift); + auto tmp = ((avm_alu_b_lo_shift - avm_alu_p_sub_a_lo) * avm_alu_rng_chk_sel_shift); tmp *= scaling_factor; std::get<44>(evals) += tmp; } @@ -724,7 +766,7 @@ template class avm_aluImpl { { Avm_DECLARE_VIEWS(45); - auto tmp = ((avm_alu_p_sub_a_lo_shift - avm_alu_p_sub_b_lo) * avm_alu_rng_chk_sel_shift); + auto tmp = ((avm_alu_b_hi_shift - avm_alu_p_sub_a_hi) * avm_alu_rng_chk_sel_shift); tmp *= scaling_factor; std::get<45>(evals) += tmp; } @@ -732,7 +774,7 @@ template class avm_aluImpl { { Avm_DECLARE_VIEWS(46); - auto tmp = ((avm_alu_p_sub_a_hi_shift - avm_alu_p_sub_b_hi) * avm_alu_rng_chk_sel_shift); + auto tmp = ((avm_alu_p_sub_a_lo_shift - avm_alu_p_sub_b_lo) * avm_alu_rng_chk_sel_shift); tmp *= scaling_factor; std::get<46>(evals) += tmp; } @@ -740,7 +782,7 @@ template class avm_aluImpl { { Avm_DECLARE_VIEWS(47); - auto tmp = ((avm_alu_p_sub_b_lo_shift - avm_alu_res_lo) * avm_alu_rng_chk_sel_shift); + auto tmp = ((avm_alu_p_sub_a_hi_shift - avm_alu_p_sub_b_hi) * avm_alu_rng_chk_sel_shift); tmp *= scaling_factor; std::get<47>(evals) += tmp; } @@ -748,7 +790,7 @@ template class avm_aluImpl { { Avm_DECLARE_VIEWS(48); - auto tmp = ((avm_alu_p_sub_b_hi_shift - avm_alu_res_hi) * avm_alu_rng_chk_sel_shift); + auto tmp = ((avm_alu_p_sub_b_lo_shift - avm_alu_res_lo) * avm_alu_rng_chk_sel_shift); tmp *= scaling_factor; std::get<48>(evals) += tmp; } @@ -756,7 +798,7 @@ template class avm_aluImpl { { Avm_DECLARE_VIEWS(49); - auto tmp = (avm_alu_op_cast_prev_shift - avm_alu_op_cast); + auto tmp = ((avm_alu_p_sub_b_hi_shift - avm_alu_res_hi) * avm_alu_rng_chk_sel_shift); tmp *= scaling_factor; std::get<49>(evals) += tmp; } @@ -764,6 +806,14 @@ template class avm_aluImpl { { Avm_DECLARE_VIEWS(50); + auto tmp = (avm_alu_op_cast_prev_shift - avm_alu_op_cast); + tmp *= scaling_factor; + std::get<50>(evals) += tmp; + } + // Contribution 51 + { + Avm_DECLARE_VIEWS(51); + auto tmp = (avm_alu_op_cast * (((((((avm_alu_u8_tag * avm_alu_u8_r0) + @@ -784,21 +834,13 @@ template class avm_aluImpl { (avm_alu_ff_tag * avm_alu_ia)) - avm_alu_ic)); tmp *= scaling_factor; - std::get<50>(evals) += tmp; - } - // Contribution 51 - { - Avm_DECLARE_VIEWS(51); - - auto tmp = (avm_alu_op_cast * (avm_alu_a_lo_shift - avm_alu_p_sub_a_lo)); - tmp *= scaling_factor; std::get<51>(evals) += tmp; } // Contribution 52 { Avm_DECLARE_VIEWS(52); - auto tmp = (avm_alu_op_cast * (avm_alu_a_hi_shift - avm_alu_p_sub_a_hi)); + auto tmp = (avm_alu_op_cast * (avm_alu_a_lo_shift - avm_alu_p_sub_a_lo)); tmp *= scaling_factor; std::get<52>(evals) += tmp; } @@ -806,10 +848,116 @@ template class avm_aluImpl { { Avm_DECLARE_VIEWS(53); - auto tmp = (((avm_alu_op_mul * avm_alu_ff_tag) + avm_alu_op_cast) * avm_alu_alu_sel_shift); + auto tmp = (avm_alu_op_cast * (avm_alu_a_hi_shift - avm_alu_p_sub_a_hi)); tmp *= scaling_factor; std::get<53>(evals) += tmp; } + // Contribution 54 + { + Avm_DECLARE_VIEWS(54); + + auto tmp = (((avm_alu_op_mul * avm_alu_ff_tag) + avm_alu_op_cast) * avm_alu_alu_sel_shift); + tmp *= scaling_factor; + std::get<54>(evals) += tmp; + } + // Contribution 55 + { + Avm_DECLARE_VIEWS(55); + + auto tmp = ((avm_alu_shift_lt_bit_len * avm_alu_op_shr) * + (avm_alu_a_lo - ((avm_alu_two_pow_s - avm_alu_b_lo) - FF(1)))); + tmp *= scaling_factor; + std::get<55>(evals) += tmp; + } + // Contribution 56 + { + Avm_DECLARE_VIEWS(56); + + auto tmp = ((avm_alu_shift_lt_bit_len * avm_alu_op_shr) * + (avm_alu_a_hi - ((avm_alu_two_pow_t_sub_s - avm_alu_b_hi) - FF(1)))); + tmp *= scaling_factor; + std::get<56>(evals) += tmp; + } + // Contribution 57 + { + Avm_DECLARE_VIEWS(57); + + auto tmp = ((avm_alu_shift_lt_bit_len * avm_alu_op_shl) * + (avm_alu_a_lo - ((avm_alu_two_pow_t_sub_s - avm_alu_b_lo) - FF(1)))); + tmp *= scaling_factor; + std::get<57>(evals) += tmp; + } + // Contribution 58 + { + Avm_DECLARE_VIEWS(58); + + auto tmp = ((avm_alu_shift_lt_bit_len * avm_alu_op_shl) * + (avm_alu_a_hi - ((avm_alu_two_pow_s - avm_alu_b_hi) - FF(1)))); + tmp *= scaling_factor; + std::get<58>(evals) += tmp; + } + // Contribution 59 + { + Avm_DECLARE_VIEWS(59); + + auto tmp = (avm_alu_shift_lt_bit_len * (-avm_alu_shift_lt_bit_len + FF(1))); + tmp *= scaling_factor; + std::get<59>(evals) += tmp; + } + // Contribution 60 + { + Avm_DECLARE_VIEWS(60); + + auto tmp = (avm_alu_t_sub_s_bits - + (avm_alu_shift_sel * + ((avm_alu_shift_lt_bit_len * + ((((((avm_alu_u8_tag * FF(8)) + (avm_alu_u16_tag * FF(16))) + (avm_alu_u32_tag * FF(32))) + + (avm_alu_u64_tag * FF(64))) + + (avm_alu_u128_tag * FF(128))) - + avm_alu_ib)) + + ((-avm_alu_shift_lt_bit_len + FF(1)) * + (avm_alu_ib - + (((((avm_alu_u8_tag * FF(8)) + (avm_alu_u16_tag * FF(16))) + (avm_alu_u32_tag * FF(32))) + + (avm_alu_u64_tag * FF(64))) + + (avm_alu_u128_tag * FF(128)))))))); + tmp *= scaling_factor; + std::get<60>(evals) += tmp; + } + // Contribution 61 + { + Avm_DECLARE_VIEWS(61); + + auto tmp = ((avm_alu_shift_lt_bit_len * avm_alu_op_shr) * + (((avm_alu_b_hi * avm_alu_two_pow_s) + avm_alu_b_lo) - avm_alu_ia)); + tmp *= scaling_factor; + std::get<61>(evals) += tmp; + } + // Contribution 62 + { + Avm_DECLARE_VIEWS(62); + + auto tmp = (avm_alu_op_shr * (avm_alu_ic - (avm_alu_b_hi * avm_alu_shift_lt_bit_len))); + tmp *= scaling_factor; + std::get<62>(evals) += tmp; + } + // Contribution 63 + { + Avm_DECLARE_VIEWS(63); + + auto tmp = ((avm_alu_shift_lt_bit_len * avm_alu_op_shl) * + (((avm_alu_b_hi * avm_alu_two_pow_t_sub_s) + avm_alu_b_lo) - avm_alu_ia)); + tmp *= scaling_factor; + std::get<63>(evals) += tmp; + } + // Contribution 64 + { + Avm_DECLARE_VIEWS(64); + + auto tmp = + (avm_alu_op_shl * (avm_alu_ic - ((avm_alu_b_lo * avm_alu_two_pow_s) * avm_alu_shift_lt_bit_len))); + tmp *= scaling_factor; + std::get<64>(evals) += tmp; + } } }; diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/avm_main.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/avm_main.hpp index b9c4dfd14df..93ab5869174 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/avm_main.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/avm_main.hpp @@ -56,6 +56,8 @@ template struct Avm_mainRow { FF avm_main_sel_op_mul{}; FF avm_main_sel_op_not{}; FF avm_main_sel_op_or{}; + FF avm_main_sel_op_shl{}; + FF avm_main_sel_op_shr{}; FF avm_main_sel_op_sub{}; FF avm_main_sel_op_xor{}; FF avm_main_tag_err{}; @@ -65,52 +67,52 @@ template struct Avm_mainRow { inline std::string get_relation_label_avm_main(int index) { switch (index) { - case 33: + case 35: return "OUTPUT_U8"; - case 34: + case 36: return "SUBOP_DIVISION_FF"; - case 35: + case 37: return "SUBOP_DIVISION_ZERO_ERR1"; - case 36: + case 38: return "SUBOP_DIVISION_ZERO_ERR2"; - case 37: + case 39: return "SUBOP_ERROR_RELEVANT_OP"; - case 39: + case 41: return "RETURN_POINTER_INCREMENT"; - case 45: + case 47: return "RETURN_POINTER_DECREMENT"; - case 50: + case 52: return "PC_INCREMENT"; - case 51: + case 53: return "INTERNAL_RETURN_POINTER_CONSISTENCY"; - case 52: + case 54: return "CMOV_CONDITION_RES_1"; - case 53: + case 55: return "CMOV_CONDITION_RES_2"; - case 56: + case 58: return "MOV_SAME_VALUE_A"; - case 57: + case 59: return "MOV_SAME_VALUE_B"; - case 58: + case 60: return "MOV_MAIN_SAME_TAG"; - case 62: + case 64: return "BIN_SEL_1"; - case 63: + case 65: return "BIN_SEL_2"; } return std::to_string(index); @@ -120,9 +122,9 @@ template class avm_mainImpl { public: using FF = FF_; - static constexpr std::array SUBRELATION_PARTIAL_LENGTHS{ - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 5, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 3, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, + static constexpr std::array SUBRELATION_PARTIAL_LENGTHS{ + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 5, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 3, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, }; template @@ -232,7 +234,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(12); - auto tmp = (avm_main_sel_internal_call * (-avm_main_sel_internal_call + FF(1))); + auto tmp = (avm_main_sel_op_shl * (-avm_main_sel_op_shl + FF(1))); tmp *= scaling_factor; std::get<12>(evals) += tmp; } @@ -240,7 +242,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(13); - auto tmp = (avm_main_sel_internal_return * (-avm_main_sel_internal_return + FF(1))); + auto tmp = (avm_main_sel_op_shr * (-avm_main_sel_op_shr + FF(1))); tmp *= scaling_factor; std::get<13>(evals) += tmp; } @@ -248,7 +250,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(14); - auto tmp = (avm_main_sel_jump * (-avm_main_sel_jump + FF(1))); + auto tmp = (avm_main_sel_internal_call * (-avm_main_sel_internal_call + FF(1))); tmp *= scaling_factor; std::get<14>(evals) += tmp; } @@ -256,7 +258,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(15); - auto tmp = (avm_main_sel_halt * (-avm_main_sel_halt + FF(1))); + auto tmp = (avm_main_sel_internal_return * (-avm_main_sel_internal_return + FF(1))); tmp *= scaling_factor; std::get<15>(evals) += tmp; } @@ -264,7 +266,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(16); - auto tmp = (avm_main_sel_mov * (-avm_main_sel_mov + FF(1))); + auto tmp = (avm_main_sel_jump * (-avm_main_sel_jump + FF(1))); tmp *= scaling_factor; std::get<16>(evals) += tmp; } @@ -272,7 +274,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(17); - auto tmp = (avm_main_sel_cmov * (-avm_main_sel_cmov + FF(1))); + auto tmp = (avm_main_sel_halt * (-avm_main_sel_halt + FF(1))); tmp *= scaling_factor; std::get<17>(evals) += tmp; } @@ -280,7 +282,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(18); - auto tmp = (avm_main_op_err * (-avm_main_op_err + FF(1))); + auto tmp = (avm_main_sel_mov * (-avm_main_sel_mov + FF(1))); tmp *= scaling_factor; std::get<18>(evals) += tmp; } @@ -288,7 +290,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(19); - auto tmp = (avm_main_tag_err * (-avm_main_tag_err + FF(1))); + auto tmp = (avm_main_sel_cmov * (-avm_main_sel_cmov + FF(1))); tmp *= scaling_factor; std::get<19>(evals) += tmp; } @@ -296,7 +298,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(20); - auto tmp = (avm_main_id_zero * (-avm_main_id_zero + FF(1))); + auto tmp = (avm_main_op_err * (-avm_main_op_err + FF(1))); tmp *= scaling_factor; std::get<20>(evals) += tmp; } @@ -304,7 +306,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(21); - auto tmp = (avm_main_mem_op_a * (-avm_main_mem_op_a + FF(1))); + auto tmp = (avm_main_tag_err * (-avm_main_tag_err + FF(1))); tmp *= scaling_factor; std::get<21>(evals) += tmp; } @@ -312,7 +314,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(22); - auto tmp = (avm_main_mem_op_b * (-avm_main_mem_op_b + FF(1))); + auto tmp = (avm_main_id_zero * (-avm_main_id_zero + FF(1))); tmp *= scaling_factor; std::get<22>(evals) += tmp; } @@ -320,7 +322,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(23); - auto tmp = (avm_main_mem_op_c * (-avm_main_mem_op_c + FF(1))); + auto tmp = (avm_main_mem_op_a * (-avm_main_mem_op_a + FF(1))); tmp *= scaling_factor; std::get<23>(evals) += tmp; } @@ -328,7 +330,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(24); - auto tmp = (avm_main_mem_op_d * (-avm_main_mem_op_d + FF(1))); + auto tmp = (avm_main_mem_op_b * (-avm_main_mem_op_b + FF(1))); tmp *= scaling_factor; std::get<24>(evals) += tmp; } @@ -336,7 +338,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(25); - auto tmp = (avm_main_rwa * (-avm_main_rwa + FF(1))); + auto tmp = (avm_main_mem_op_c * (-avm_main_mem_op_c + FF(1))); tmp *= scaling_factor; std::get<25>(evals) += tmp; } @@ -344,7 +346,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(26); - auto tmp = (avm_main_rwb * (-avm_main_rwb + FF(1))); + auto tmp = (avm_main_mem_op_d * (-avm_main_mem_op_d + FF(1))); tmp *= scaling_factor; std::get<26>(evals) += tmp; } @@ -352,7 +354,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(27); - auto tmp = (avm_main_rwc * (-avm_main_rwc + FF(1))); + auto tmp = (avm_main_rwa * (-avm_main_rwa + FF(1))); tmp *= scaling_factor; std::get<27>(evals) += tmp; } @@ -360,7 +362,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(28); - auto tmp = (avm_main_rwd * (-avm_main_rwd + FF(1))); + auto tmp = (avm_main_rwb * (-avm_main_rwb + FF(1))); tmp *= scaling_factor; std::get<28>(evals) += tmp; } @@ -368,7 +370,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(29); - auto tmp = (avm_main_ind_op_a * (-avm_main_ind_op_a + FF(1))); + auto tmp = (avm_main_rwc * (-avm_main_rwc + FF(1))); tmp *= scaling_factor; std::get<29>(evals) += tmp; } @@ -376,7 +378,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(30); - auto tmp = (avm_main_ind_op_b * (-avm_main_ind_op_b + FF(1))); + auto tmp = (avm_main_rwd * (-avm_main_rwd + FF(1))); tmp *= scaling_factor; std::get<30>(evals) += tmp; } @@ -384,7 +386,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(31); - auto tmp = (avm_main_ind_op_c * (-avm_main_ind_op_c + FF(1))); + auto tmp = (avm_main_ind_op_a * (-avm_main_ind_op_a + FF(1))); tmp *= scaling_factor; std::get<31>(evals) += tmp; } @@ -392,7 +394,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(32); - auto tmp = (avm_main_ind_op_d * (-avm_main_ind_op_d + FF(1))); + auto tmp = (avm_main_ind_op_b * (-avm_main_ind_op_b + FF(1))); tmp *= scaling_factor; std::get<32>(evals) += tmp; } @@ -400,8 +402,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(33); - auto tmp = - (((avm_main_sel_op_eq + avm_main_sel_op_lte) + avm_main_sel_op_lt) * (avm_main_w_in_tag - FF(1))); + auto tmp = (avm_main_ind_op_c * (-avm_main_ind_op_c + FF(1))); tmp *= scaling_factor; std::get<33>(evals) += tmp; } @@ -409,8 +410,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(34); - auto tmp = - ((avm_main_sel_op_div * (-avm_main_op_err + FF(1))) * ((avm_main_ic * avm_main_ib) - avm_main_ia)); + auto tmp = (avm_main_ind_op_d * (-avm_main_ind_op_d + FF(1))); tmp *= scaling_factor; std::get<34>(evals) += tmp; } @@ -418,7 +418,8 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(35); - auto tmp = (avm_main_sel_op_div * (((avm_main_ib * avm_main_inv) - FF(1)) + avm_main_op_err)); + auto tmp = + (((avm_main_sel_op_eq + avm_main_sel_op_lte) + avm_main_sel_op_lt) * (avm_main_w_in_tag - FF(1))); tmp *= scaling_factor; std::get<35>(evals) += tmp; } @@ -426,7 +427,8 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(36); - auto tmp = ((avm_main_sel_op_div * avm_main_op_err) * (-avm_main_inv + FF(1))); + auto tmp = + ((avm_main_sel_op_div * (-avm_main_op_err + FF(1))) * ((avm_main_ic * avm_main_ib) - avm_main_ia)); tmp *= scaling_factor; std::get<36>(evals) += tmp; } @@ -434,7 +436,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(37); - auto tmp = (avm_main_op_err * (avm_main_sel_op_div - FF(1))); + auto tmp = (avm_main_sel_op_div * (((avm_main_ib * avm_main_inv) - FF(1)) + avm_main_op_err)); tmp *= scaling_factor; std::get<37>(evals) += tmp; } @@ -442,7 +444,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(38); - auto tmp = (avm_main_sel_jump * (avm_main_pc_shift - avm_main_ia)); + auto tmp = ((avm_main_sel_op_div * avm_main_op_err) * (-avm_main_inv + FF(1))); tmp *= scaling_factor; std::get<38>(evals) += tmp; } @@ -450,8 +452,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(39); - auto tmp = (avm_main_sel_internal_call * - (avm_main_internal_return_ptr_shift - (avm_main_internal_return_ptr + FF(1)))); + auto tmp = (avm_main_op_err * (avm_main_sel_op_div - FF(1))); tmp *= scaling_factor; std::get<39>(evals) += tmp; } @@ -459,7 +460,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(40); - auto tmp = (avm_main_sel_internal_call * (avm_main_internal_return_ptr - avm_main_mem_idx_b)); + auto tmp = (avm_main_sel_jump * (avm_main_pc_shift - avm_main_ia)); tmp *= scaling_factor; std::get<40>(evals) += tmp; } @@ -467,7 +468,8 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(41); - auto tmp = (avm_main_sel_internal_call * (avm_main_pc_shift - avm_main_ia)); + auto tmp = (avm_main_sel_internal_call * + (avm_main_internal_return_ptr_shift - (avm_main_internal_return_ptr + FF(1)))); tmp *= scaling_factor; std::get<41>(evals) += tmp; } @@ -475,7 +477,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(42); - auto tmp = (avm_main_sel_internal_call * ((avm_main_pc + FF(1)) - avm_main_ib)); + auto tmp = (avm_main_sel_internal_call * (avm_main_internal_return_ptr - avm_main_mem_idx_b)); tmp *= scaling_factor; std::get<42>(evals) += tmp; } @@ -483,7 +485,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(43); - auto tmp = (avm_main_sel_internal_call * (avm_main_rwb - FF(1))); + auto tmp = (avm_main_sel_internal_call * (avm_main_pc_shift - avm_main_ia)); tmp *= scaling_factor; std::get<43>(evals) += tmp; } @@ -491,7 +493,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(44); - auto tmp = (avm_main_sel_internal_call * (avm_main_mem_op_b - FF(1))); + auto tmp = (avm_main_sel_internal_call * ((avm_main_pc + FF(1)) - avm_main_ib)); tmp *= scaling_factor; std::get<44>(evals) += tmp; } @@ -499,8 +501,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(45); - auto tmp = (avm_main_sel_internal_return * - (avm_main_internal_return_ptr_shift - (avm_main_internal_return_ptr - FF(1)))); + auto tmp = (avm_main_sel_internal_call * (avm_main_rwb - FF(1))); tmp *= scaling_factor; std::get<45>(evals) += tmp; } @@ -508,7 +509,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(46); - auto tmp = (avm_main_sel_internal_return * ((avm_main_internal_return_ptr - FF(1)) - avm_main_mem_idx_a)); + auto tmp = (avm_main_sel_internal_call * (avm_main_mem_op_b - FF(1))); tmp *= scaling_factor; std::get<46>(evals) += tmp; } @@ -516,7 +517,8 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(47); - auto tmp = (avm_main_sel_internal_return * (avm_main_pc_shift - avm_main_ia)); + auto tmp = (avm_main_sel_internal_return * + (avm_main_internal_return_ptr_shift - (avm_main_internal_return_ptr - FF(1)))); tmp *= scaling_factor; std::get<47>(evals) += tmp; } @@ -524,7 +526,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(48); - auto tmp = (avm_main_sel_internal_return * avm_main_rwa); + auto tmp = (avm_main_sel_internal_return * ((avm_main_internal_return_ptr - FF(1)) - avm_main_mem_idx_a)); tmp *= scaling_factor; std::get<48>(evals) += tmp; } @@ -532,7 +534,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(49); - auto tmp = (avm_main_sel_internal_return * (avm_main_mem_op_a - FF(1))); + auto tmp = (avm_main_sel_internal_return * (avm_main_pc_shift - avm_main_ia)); tmp *= scaling_factor; std::get<49>(evals) += tmp; } @@ -540,16 +542,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(50); - auto tmp = - ((((-avm_main_first + FF(1)) * (-avm_main_sel_halt + FF(1))) * - (((((((((avm_main_sel_op_add + avm_main_sel_op_sub) + avm_main_sel_op_div) + avm_main_sel_op_mul) + - avm_main_sel_op_not) + - avm_main_sel_op_eq) + - avm_main_sel_op_and) + - avm_main_sel_op_or) + - avm_main_sel_op_xor) + - avm_main_sel_op_cast)) * - (avm_main_pc_shift - (avm_main_pc + FF(1)))); + auto tmp = (avm_main_sel_internal_return * avm_main_rwa); tmp *= scaling_factor; std::get<50>(evals) += tmp; } @@ -557,10 +550,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(51); - auto tmp = ((-(((avm_main_first + avm_main_sel_internal_call) + avm_main_sel_internal_return) + - avm_main_sel_halt) + - FF(1)) * - (avm_main_internal_return_ptr_shift - avm_main_internal_return_ptr)); + auto tmp = (avm_main_sel_internal_return * (avm_main_mem_op_a - FF(1))); tmp *= scaling_factor; std::get<51>(evals) += tmp; } @@ -568,7 +558,16 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(52); - auto tmp = (avm_main_sel_cmov * (((avm_main_id * avm_main_inv) - FF(1)) + avm_main_id_zero)); + auto tmp = + ((((-avm_main_first + FF(1)) * (-avm_main_sel_halt + FF(1))) * + (((((((((avm_main_sel_op_add + avm_main_sel_op_sub) + avm_main_sel_op_div) + avm_main_sel_op_mul) + + avm_main_sel_op_not) + + avm_main_sel_op_eq) + + avm_main_sel_op_and) + + avm_main_sel_op_or) + + avm_main_sel_op_xor) + + avm_main_sel_op_cast)) * + (avm_main_pc_shift - (avm_main_pc + FF(1)))); tmp *= scaling_factor; std::get<52>(evals) += tmp; } @@ -576,7 +575,10 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(53); - auto tmp = ((avm_main_sel_cmov * avm_main_id_zero) * (-avm_main_inv + FF(1))); + auto tmp = ((-(((avm_main_first + avm_main_sel_internal_call) + avm_main_sel_internal_return) + + avm_main_sel_halt) + + FF(1)) * + (avm_main_internal_return_ptr_shift - avm_main_internal_return_ptr)); tmp *= scaling_factor; std::get<53>(evals) += tmp; } @@ -584,7 +586,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(54); - auto tmp = (avm_main_sel_mov_a - (avm_main_sel_mov + (avm_main_sel_cmov * (-avm_main_id_zero + FF(1))))); + auto tmp = (avm_main_sel_cmov * (((avm_main_id * avm_main_inv) - FF(1)) + avm_main_id_zero)); tmp *= scaling_factor; std::get<54>(evals) += tmp; } @@ -592,7 +594,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(55); - auto tmp = (avm_main_sel_mov_b - (avm_main_sel_cmov * avm_main_id_zero)); + auto tmp = ((avm_main_sel_cmov * avm_main_id_zero) * (-avm_main_inv + FF(1))); tmp *= scaling_factor; std::get<55>(evals) += tmp; } @@ -600,7 +602,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(56); - auto tmp = (avm_main_sel_mov_a * (avm_main_ia - avm_main_ic)); + auto tmp = (avm_main_sel_mov_a - (avm_main_sel_mov + (avm_main_sel_cmov * (-avm_main_id_zero + FF(1))))); tmp *= scaling_factor; std::get<56>(evals) += tmp; } @@ -608,7 +610,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(57); - auto tmp = (avm_main_sel_mov_b * (avm_main_ib - avm_main_ic)); + auto tmp = (avm_main_sel_mov_b - (avm_main_sel_cmov * avm_main_id_zero)); tmp *= scaling_factor; std::get<57>(evals) += tmp; } @@ -616,7 +618,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(58); - auto tmp = ((avm_main_sel_mov + avm_main_sel_cmov) * (avm_main_r_in_tag - avm_main_w_in_tag)); + auto tmp = (avm_main_sel_mov_a * (avm_main_ia - avm_main_ic)); tmp *= scaling_factor; std::get<58>(evals) += tmp; } @@ -624,14 +626,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(59); - auto tmp = - (avm_main_alu_sel - - ((((((((avm_main_sel_op_add + avm_main_sel_op_sub) + avm_main_sel_op_mul) + avm_main_sel_op_not) + - avm_main_sel_op_eq) + - avm_main_sel_op_lt) + - avm_main_sel_op_lte) + - avm_main_sel_op_cast) * - (-avm_main_tag_err + FF(1)))); + auto tmp = (avm_main_sel_mov_b * (avm_main_ib - avm_main_ic)); tmp *= scaling_factor; std::get<59>(evals) += tmp; } @@ -639,11 +634,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(60); - auto tmp = (((((((avm_main_sel_op_add + avm_main_sel_op_sub) + avm_main_sel_op_mul) + avm_main_sel_op_not) + - avm_main_sel_op_eq) + - avm_main_sel_op_lt) + - avm_main_sel_op_lte) * - (avm_main_alu_in_tag - avm_main_r_in_tag)); + auto tmp = ((avm_main_sel_mov + avm_main_sel_cmov) * (avm_main_r_in_tag - avm_main_w_in_tag)); tmp *= scaling_factor; std::get<60>(evals) += tmp; } @@ -651,7 +642,16 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(61); - auto tmp = (avm_main_sel_op_cast * (avm_main_alu_in_tag - avm_main_w_in_tag)); + auto tmp = + (avm_main_alu_sel - + ((((((((((avm_main_sel_op_add + avm_main_sel_op_sub) + avm_main_sel_op_mul) + avm_main_sel_op_not) + + avm_main_sel_op_eq) + + avm_main_sel_op_lt) + + avm_main_sel_op_lte) + + avm_main_sel_op_shr) + + avm_main_sel_op_shl) + + avm_main_sel_op_cast) * + (-avm_main_tag_err + FF(1)))); tmp *= scaling_factor; std::get<61>(evals) += tmp; } @@ -659,7 +659,14 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(62); - auto tmp = (avm_main_bin_op_id - (avm_main_sel_op_or + (avm_main_sel_op_xor * FF(2)))); + auto tmp = + (((((((((avm_main_sel_op_add + avm_main_sel_op_sub) + avm_main_sel_op_mul) + avm_main_sel_op_not) + + avm_main_sel_op_eq) + + avm_main_sel_op_lt) + + avm_main_sel_op_lte) + + avm_main_sel_op_shr) + + avm_main_sel_op_shl) * + (avm_main_alu_in_tag - avm_main_r_in_tag)); tmp *= scaling_factor; std::get<62>(evals) += tmp; } @@ -667,10 +674,26 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(63); - auto tmp = (avm_main_bin_sel - ((avm_main_sel_op_and + avm_main_sel_op_or) + avm_main_sel_op_xor)); + auto tmp = (avm_main_sel_op_cast * (avm_main_alu_in_tag - avm_main_w_in_tag)); tmp *= scaling_factor; std::get<63>(evals) += tmp; } + // Contribution 64 + { + Avm_DECLARE_VIEWS(64); + + auto tmp = (avm_main_bin_op_id - (avm_main_sel_op_or + (avm_main_sel_op_xor * FF(2)))); + tmp *= scaling_factor; + std::get<64>(evals) += tmp; + } + // Contribution 65 + { + Avm_DECLARE_VIEWS(65); + + auto tmp = (avm_main_bin_sel - ((avm_main_sel_op_and + avm_main_sel_op_or) + avm_main_sel_op_xor)); + tmp *= scaling_factor; + std::get<65>(evals) += tmp; + } } }; diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/declare_views.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/declare_views.hpp index e427a1bf7be..43acfc68dd1 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/declare_views.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/declare_views.hpp @@ -29,6 +29,8 @@ [[maybe_unused]] auto avm_alu_op_lte = View(new_term.avm_alu_op_lte); \ [[maybe_unused]] auto avm_alu_op_mul = View(new_term.avm_alu_op_mul); \ [[maybe_unused]] auto avm_alu_op_not = View(new_term.avm_alu_op_not); \ + [[maybe_unused]] auto avm_alu_op_shl = View(new_term.avm_alu_op_shl); \ + [[maybe_unused]] auto avm_alu_op_shr = View(new_term.avm_alu_op_shr); \ [[maybe_unused]] auto avm_alu_op_sub = View(new_term.avm_alu_op_sub); \ [[maybe_unused]] auto avm_alu_p_a_borrow = View(new_term.avm_alu_p_a_borrow); \ [[maybe_unused]] auto avm_alu_p_b_borrow = View(new_term.avm_alu_p_b_borrow); \ @@ -40,6 +42,11 @@ [[maybe_unused]] auto avm_alu_res_lo = View(new_term.avm_alu_res_lo); \ [[maybe_unused]] auto avm_alu_rng_chk_lookup_selector = View(new_term.avm_alu_rng_chk_lookup_selector); \ [[maybe_unused]] auto avm_alu_rng_chk_sel = View(new_term.avm_alu_rng_chk_sel); \ + [[maybe_unused]] auto avm_alu_shift_lt_bit_len = View(new_term.avm_alu_shift_lt_bit_len); \ + [[maybe_unused]] auto avm_alu_shift_sel = View(new_term.avm_alu_shift_sel); \ + [[maybe_unused]] auto avm_alu_t_sub_s_bits = View(new_term.avm_alu_t_sub_s_bits); \ + [[maybe_unused]] auto avm_alu_two_pow_s = View(new_term.avm_alu_two_pow_s); \ + [[maybe_unused]] auto avm_alu_two_pow_t_sub_s = View(new_term.avm_alu_two_pow_t_sub_s); \ [[maybe_unused]] auto avm_alu_u128_tag = View(new_term.avm_alu_u128_tag); \ [[maybe_unused]] auto avm_alu_u16_r0 = View(new_term.avm_alu_u16_r0); \ [[maybe_unused]] auto avm_alu_u16_r1 = View(new_term.avm_alu_u16_r1); \ @@ -135,10 +142,13 @@ [[maybe_unused]] auto avm_main_sel_op_mul = View(new_term.avm_main_sel_op_mul); \ [[maybe_unused]] auto avm_main_sel_op_not = View(new_term.avm_main_sel_op_not); \ [[maybe_unused]] auto avm_main_sel_op_or = View(new_term.avm_main_sel_op_or); \ + [[maybe_unused]] auto avm_main_sel_op_shl = View(new_term.avm_main_sel_op_shl); \ + [[maybe_unused]] auto avm_main_sel_op_shr = View(new_term.avm_main_sel_op_shr); \ [[maybe_unused]] auto avm_main_sel_op_sub = View(new_term.avm_main_sel_op_sub); \ [[maybe_unused]] auto avm_main_sel_op_xor = View(new_term.avm_main_sel_op_xor); \ [[maybe_unused]] auto avm_main_sel_rng_16 = View(new_term.avm_main_sel_rng_16); \ [[maybe_unused]] auto avm_main_sel_rng_8 = View(new_term.avm_main_sel_rng_8); \ + [[maybe_unused]] auto avm_main_table_pow_2 = View(new_term.avm_main_table_pow_2); \ [[maybe_unused]] auto avm_main_tag_err = View(new_term.avm_main_tag_err); \ [[maybe_unused]] auto avm_main_w_in_tag = View(new_term.avm_main_w_in_tag); \ [[maybe_unused]] auto avm_mem_addr = View(new_term.avm_mem_addr); \ @@ -179,6 +189,8 @@ [[maybe_unused]] auto lookup_byte_operations = View(new_term.lookup_byte_operations); \ [[maybe_unused]] auto incl_main_tag_err = View(new_term.incl_main_tag_err); \ [[maybe_unused]] auto incl_mem_tag_err = View(new_term.incl_mem_tag_err); \ + [[maybe_unused]] auto lookup_pow_2_0 = View(new_term.lookup_pow_2_0); \ + [[maybe_unused]] auto lookup_pow_2_1 = View(new_term.lookup_pow_2_1); \ [[maybe_unused]] auto lookup_u8_0 = View(new_term.lookup_u8_0); \ [[maybe_unused]] auto lookup_u8_1 = View(new_term.lookup_u8_1); \ [[maybe_unused]] auto lookup_u16_0 = View(new_term.lookup_u16_0); \ @@ -200,6 +212,8 @@ [[maybe_unused]] auto lookup_byte_operations_counts = View(new_term.lookup_byte_operations_counts); \ [[maybe_unused]] auto incl_main_tag_err_counts = View(new_term.incl_main_tag_err_counts); \ [[maybe_unused]] auto incl_mem_tag_err_counts = View(new_term.incl_mem_tag_err_counts); \ + [[maybe_unused]] auto lookup_pow_2_0_counts = View(new_term.lookup_pow_2_0_counts); \ + [[maybe_unused]] auto lookup_pow_2_1_counts = View(new_term.lookup_pow_2_1_counts); \ [[maybe_unused]] auto lookup_u8_0_counts = View(new_term.lookup_u8_0_counts); \ [[maybe_unused]] auto lookup_u8_1_counts = View(new_term.lookup_u8_1_counts); \ [[maybe_unused]] auto lookup_u16_0_counts = View(new_term.lookup_u16_0_counts); \ @@ -228,6 +242,8 @@ [[maybe_unused]] auto avm_alu_op_cast_prev_shift = View(new_term.avm_alu_op_cast_prev_shift); \ [[maybe_unused]] auto avm_alu_op_cast_shift = View(new_term.avm_alu_op_cast_shift); \ [[maybe_unused]] auto avm_alu_op_mul_shift = View(new_term.avm_alu_op_mul_shift); \ + [[maybe_unused]] auto avm_alu_op_shl_shift = View(new_term.avm_alu_op_shl_shift); \ + [[maybe_unused]] auto avm_alu_op_shr_shift = View(new_term.avm_alu_op_shr_shift); \ [[maybe_unused]] auto avm_alu_op_sub_shift = View(new_term.avm_alu_op_sub_shift); \ [[maybe_unused]] auto avm_alu_p_sub_a_hi_shift = View(new_term.avm_alu_p_sub_a_hi_shift); \ [[maybe_unused]] auto avm_alu_p_sub_a_lo_shift = View(new_term.avm_alu_p_sub_a_lo_shift); \ diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_pow_2_0.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_pow_2_0.hpp new file mode 100644 index 00000000000..a4629615a75 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_pow_2_0.hpp @@ -0,0 +1,170 @@ + + +#pragma once + +#include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" + +#include +#include + +namespace bb { + +/** + * @brief This class contains an example of how to set LookupSettings classes used by the + * GenericLookupRelationImpl class to specify a scaled lookup + * + * @details To create your own lookup: + * 1) Create a copy of this class and rename it + * 2) Update all the values with the ones needed for your lookup + * 3) Update "DECLARE_LOOKUP_IMPLEMENTATIONS_FOR_ALL_SETTINGS" and "DEFINE_LOOKUP_IMPLEMENTATIONS_FOR_ALL_SETTINGS" to + * include the new settings + * 4) Add the relation with the chosen settings to Relations in the flavor (for example,"` + * using Relations = std::tuple>;)` + * + */ +class lookup_pow_2_0_lookup_settings { + public: + /** + * @brief The number of read terms (how many lookups we perform) in each row + * + */ + static constexpr size_t READ_TERMS = 1; + /** + * @brief The number of write terms (how many additions to the lookup table we make) in each row + * + */ + static constexpr size_t WRITE_TERMS = 1; + + /** + * @brief The type of READ_TERM used for each read index (basic and scaled) + * + */ + static constexpr size_t READ_TERM_TYPES[READ_TERMS] = { 0 }; + + /** + * @brief They type of WRITE_TERM used for each write index + * + */ + static constexpr size_t WRITE_TERM_TYPES[WRITE_TERMS] = { 0 }; + + /** + * @brief How many values represent a single lookup object. This value is used by the automatic read term + * implementation in the relation in case the lookup is a basic or scaled tuple and in the write term if it's a + * basic tuple + * + */ + static constexpr size_t LOOKUP_TUPLE_SIZE = 2; + + /** + * @brief The polynomial degree of the relation telling us if the inverse polynomial value needs to be computed + * + */ + static constexpr size_t INVERSE_EXISTS_POLYNOMIAL_DEGREE = 4; + + /** + * @brief The degree of the read term if implemented arbitrarily. This value is not used by basic and scaled read + * terms, but will cause compilation error if not defined + * + */ + static constexpr size_t READ_TERM_DEGREE = 0; + + /** + * @brief The degree of the write term if implemented arbitrarily. This value is not used by the basic write + * term, but will cause compilation error if not defined + * + */ + + static constexpr size_t WRITE_TERM_DEGREE = 0; + + /** + * @brief If this method returns true on a row of values, then the inverse polynomial exists at this index. + * Otherwise the value needs to be set to zero. + * + * @details If this is true then the lookup takes place in this row + * + */ + + template static inline auto inverse_polynomial_is_computed_at_row(const AllEntities& in) + { + return (in.avm_alu_shift_sel == 1 || in.avm_main_sel_rng_8 == 1); + } + + /** + * @brief Subprocedure for computing the value deciding if the inverse polynomial value needs to be checked in this + * row + * + * @tparam Accumulator Type specified by the lookup relation + * @tparam AllEntities Values/Univariates of all entities row + * @param in Value/Univariate of all entities at row/edge + * @return Accumulator + */ + + template + static inline auto compute_inverse_exists(const AllEntities& in) + { + using View = typename Accumulator::View; + const auto is_operation = View(in.avm_alu_shift_sel); + const auto is_table_entry = View(in.avm_main_sel_rng_8); + return (is_operation + is_table_entry - is_operation * is_table_entry); + } + + /** + * @brief Get all the entities for the lookup when need to update them + * + * @details The generic structure of this tuple is described in ./generic_lookup_relation.hpp . The following is + description for the current case: + The entities are returned as a tuple of references in the following order (this is for ): + * - The entity/polynomial used to store the product of the inverse values + * - The entity/polynomial that specifies how many times the lookup table entry at this row has been looked up + * - READ_TERMS entities/polynomials that enable individual lookup operations + * - The entity/polynomial that enables adding an entry to the lookup table in this row + * - LOOKUP_TUPLE_SIZE entities/polynomials representing the basic tuple being looked up as the first read term + * - LOOKUP_TUPLE_SIZE entities/polynomials representing the previous accumulators in the second read term + (scaled tuple) + * - LOOKUP_TUPLE_SIZE entities/polynomials representing the shifts in the second read term (scaled tuple) + * - LOOKUP_TUPLE_SIZE entities/polynomials representing the current accumulators in the second read term + (scaled tuple) + * - LOOKUP_TUPLE_SIZE entities/polynomials representing basic tuples added to the table + * + * @return All the entities needed for the lookup + */ + + template static inline auto get_const_entities(const AllEntities& in) + { + + return std::forward_as_tuple(in.lookup_pow_2_0, + in.lookup_pow_2_0_counts, + in.avm_alu_shift_sel, + in.avm_main_sel_rng_8, + in.avm_alu_ib, + in.avm_alu_two_pow_s, + in.avm_main_clk, + in.avm_main_table_pow_2); + } + + /** + * @brief Get all the entities for the lookup when we only need to read them + * @details Same as in get_const_entities, but nonconst + * + * @return All the entities needed for the lookup + */ + + template static inline auto get_nonconst_entities(AllEntities& in) + { + + return std::forward_as_tuple(in.lookup_pow_2_0, + in.lookup_pow_2_0_counts, + in.avm_alu_shift_sel, + in.avm_main_sel_rng_8, + in.avm_alu_ib, + in.avm_alu_two_pow_s, + in.avm_main_clk, + in.avm_main_table_pow_2); + } +}; + +template using lookup_pow_2_0_relation = GenericLookupRelation; +template using lookup_pow_2_0 = GenericLookup; + +} // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_pow_2_1.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_pow_2_1.hpp new file mode 100644 index 00000000000..e1e7284056e --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_pow_2_1.hpp @@ -0,0 +1,170 @@ + + +#pragma once + +#include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" + +#include +#include + +namespace bb { + +/** + * @brief This class contains an example of how to set LookupSettings classes used by the + * GenericLookupRelationImpl class to specify a scaled lookup + * + * @details To create your own lookup: + * 1) Create a copy of this class and rename it + * 2) Update all the values with the ones needed for your lookup + * 3) Update "DECLARE_LOOKUP_IMPLEMENTATIONS_FOR_ALL_SETTINGS" and "DEFINE_LOOKUP_IMPLEMENTATIONS_FOR_ALL_SETTINGS" to + * include the new settings + * 4) Add the relation with the chosen settings to Relations in the flavor (for example,"` + * using Relations = std::tuple>;)` + * + */ +class lookup_pow_2_1_lookup_settings { + public: + /** + * @brief The number of read terms (how many lookups we perform) in each row + * + */ + static constexpr size_t READ_TERMS = 1; + /** + * @brief The number of write terms (how many additions to the lookup table we make) in each row + * + */ + static constexpr size_t WRITE_TERMS = 1; + + /** + * @brief The type of READ_TERM used for each read index (basic and scaled) + * + */ + static constexpr size_t READ_TERM_TYPES[READ_TERMS] = { 0 }; + + /** + * @brief They type of WRITE_TERM used for each write index + * + */ + static constexpr size_t WRITE_TERM_TYPES[WRITE_TERMS] = { 0 }; + + /** + * @brief How many values represent a single lookup object. This value is used by the automatic read term + * implementation in the relation in case the lookup is a basic or scaled tuple and in the write term if it's a + * basic tuple + * + */ + static constexpr size_t LOOKUP_TUPLE_SIZE = 2; + + /** + * @brief The polynomial degree of the relation telling us if the inverse polynomial value needs to be computed + * + */ + static constexpr size_t INVERSE_EXISTS_POLYNOMIAL_DEGREE = 4; + + /** + * @brief The degree of the read term if implemented arbitrarily. This value is not used by basic and scaled read + * terms, but will cause compilation error if not defined + * + */ + static constexpr size_t READ_TERM_DEGREE = 0; + + /** + * @brief The degree of the write term if implemented arbitrarily. This value is not used by the basic write + * term, but will cause compilation error if not defined + * + */ + + static constexpr size_t WRITE_TERM_DEGREE = 0; + + /** + * @brief If this method returns true on a row of values, then the inverse polynomial exists at this index. + * Otherwise the value needs to be set to zero. + * + * @details If this is true then the lookup takes place in this row + * + */ + + template static inline auto inverse_polynomial_is_computed_at_row(const AllEntities& in) + { + return (in.avm_alu_shift_sel == 1 || in.avm_main_sel_rng_8 == 1); + } + + /** + * @brief Subprocedure for computing the value deciding if the inverse polynomial value needs to be checked in this + * row + * + * @tparam Accumulator Type specified by the lookup relation + * @tparam AllEntities Values/Univariates of all entities row + * @param in Value/Univariate of all entities at row/edge + * @return Accumulator + */ + + template + static inline auto compute_inverse_exists(const AllEntities& in) + { + using View = typename Accumulator::View; + const auto is_operation = View(in.avm_alu_shift_sel); + const auto is_table_entry = View(in.avm_main_sel_rng_8); + return (is_operation + is_table_entry - is_operation * is_table_entry); + } + + /** + * @brief Get all the entities for the lookup when need to update them + * + * @details The generic structure of this tuple is described in ./generic_lookup_relation.hpp . The following is + description for the current case: + The entities are returned as a tuple of references in the following order (this is for ): + * - The entity/polynomial used to store the product of the inverse values + * - The entity/polynomial that specifies how many times the lookup table entry at this row has been looked up + * - READ_TERMS entities/polynomials that enable individual lookup operations + * - The entity/polynomial that enables adding an entry to the lookup table in this row + * - LOOKUP_TUPLE_SIZE entities/polynomials representing the basic tuple being looked up as the first read term + * - LOOKUP_TUPLE_SIZE entities/polynomials representing the previous accumulators in the second read term + (scaled tuple) + * - LOOKUP_TUPLE_SIZE entities/polynomials representing the shifts in the second read term (scaled tuple) + * - LOOKUP_TUPLE_SIZE entities/polynomials representing the current accumulators in the second read term + (scaled tuple) + * - LOOKUP_TUPLE_SIZE entities/polynomials representing basic tuples added to the table + * + * @return All the entities needed for the lookup + */ + + template static inline auto get_const_entities(const AllEntities& in) + { + + return std::forward_as_tuple(in.lookup_pow_2_1, + in.lookup_pow_2_1_counts, + in.avm_alu_shift_sel, + in.avm_main_sel_rng_8, + in.avm_alu_t_sub_s_bits, + in.avm_alu_two_pow_t_sub_s, + in.avm_main_clk, + in.avm_main_table_pow_2); + } + + /** + * @brief Get all the entities for the lookup when we only need to read them + * @details Same as in get_const_entities, but nonconst + * + * @return All the entities needed for the lookup + */ + + template static inline auto get_nonconst_entities(AllEntities& in) + { + + return std::forward_as_tuple(in.lookup_pow_2_1, + in.lookup_pow_2_1_counts, + in.avm_alu_shift_sel, + in.avm_main_sel_rng_8, + in.avm_alu_t_sub_s_bits, + in.avm_alu_two_pow_t_sub_s, + in.avm_main_clk, + in.avm_main_table_pow_2); + } +}; + +template using lookup_pow_2_1_relation = GenericLookupRelation; +template using lookup_pow_2_1 = GenericLookup; + +} // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_alu.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_alu.hpp index d79a11acf7c..69ec55c1d2c 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_alu.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_alu.hpp @@ -12,7 +12,7 @@ namespace bb { class perm_main_alu_permutation_settings { public: // This constant defines how many columns are bundled together to form each set. - constexpr static size_t COLUMNS_PER_SET = 13; + constexpr static size_t COLUMNS_PER_SET = 15; /** * @brief If this method returns true on a row of values, then the inverse polynomial at this index. Otherwise the @@ -62,6 +62,8 @@ class perm_main_alu_permutation_settings { in.avm_main_sel_op_cast, in.avm_main_sel_op_lt, in.avm_main_sel_op_lte, + in.avm_main_sel_op_shr, + in.avm_main_sel_op_shl, in.avm_main_alu_in_tag, in.avm_alu_clk, in.avm_alu_ia, @@ -75,6 +77,8 @@ class perm_main_alu_permutation_settings { in.avm_alu_op_cast, in.avm_alu_op_lt, in.avm_alu_op_lte, + in.avm_alu_op_shr, + in.avm_alu_op_shl, in.avm_alu_in_tag); } @@ -114,6 +118,8 @@ class perm_main_alu_permutation_settings { in.avm_main_sel_op_cast, in.avm_main_sel_op_lt, in.avm_main_sel_op_lte, + in.avm_main_sel_op_shr, + in.avm_main_sel_op_shl, in.avm_main_alu_in_tag, in.avm_alu_clk, in.avm_alu_ia, @@ -127,6 +133,8 @@ class perm_main_alu_permutation_settings { in.avm_alu_op_cast, in.avm_alu_op_lt, in.avm_alu_op_lte, + in.avm_alu_op_shr, + in.avm_alu_op_shl, in.avm_alu_in_tag); } }; diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/pow_2_lookups.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/pow_2_lookups.hpp new file mode 100644 index 00000000000..b66844e7d06 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/pow_2_lookups.hpp @@ -0,0 +1,170 @@ + + +#pragma once + +#include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" + +#include +#include + +namespace bb { + +/** + * @brief This class contains an example of how to set LookupSettings classes used by the + * GenericLookupRelationImpl class to specify a scaled lookup + * + * @details To create your own lookup: + * 1) Create a copy of this class and rename it + * 2) Update all the values with the ones needed for your lookup + * 3) Update "DECLARE_LOOKUP_IMPLEMENTATIONS_FOR_ALL_SETTINGS" and "DEFINE_LOOKUP_IMPLEMENTATIONS_FOR_ALL_SETTINGS" to + * include the new settings + * 4) Add the relation with the chosen settings to Relations in the flavor (for example,"` + * using Relations = std::tuple>;)` + * + */ +class pow_2_lookups_lookup_settings { + public: + /** + * @brief The number of read terms (how many lookups we perform) in each row + * + */ + static constexpr size_t READ_TERMS = 1; + /** + * @brief The number of write terms (how many additions to the lookup table we make) in each row + * + */ + static constexpr size_t WRITE_TERMS = 1; + + /** + * @brief The type of READ_TERM used for each read index (basic and scaled) + * + */ + static constexpr size_t READ_TERM_TYPES[READ_TERMS] = { 0 }; + + /** + * @brief They type of WRITE_TERM used for each write index + * + */ + static constexpr size_t WRITE_TERM_TYPES[WRITE_TERMS] = { 0 }; + + /** + * @brief How many values represent a single lookup object. This value is used by the automatic read term + * implementation in the relation in case the lookup is a basic or scaled tuple and in the write term if it's a + * basic tuple + * + */ + static constexpr size_t LOOKUP_TUPLE_SIZE = 2; + + /** + * @brief The polynomial degree of the relation telling us if the inverse polynomial value needs to be computed + * + */ + static constexpr size_t INVERSE_EXISTS_POLYNOMIAL_DEGREE = 4; + + /** + * @brief The degree of the read term if implemented arbitrarily. This value is not used by basic and scaled read + * terms, but will cause compilation error if not defined + * + */ + static constexpr size_t READ_TERM_DEGREE = 0; + + /** + * @brief The degree of the write term if implemented arbitrarily. This value is not used by the basic write + * term, but will cause compilation error if not defined + * + */ + + static constexpr size_t WRITE_TERM_DEGREE = 0; + + /** + * @brief If this method returns true on a row of values, then the inverse polynomial exists at this index. + * Otherwise the value needs to be set to zero. + * + * @details If this is true then the lookup takes place in this row + * + */ + + template static inline auto inverse_polynomial_is_computed_at_row(const AllEntities& in) + { + return (in.avm_alu_pow_2_sel == 1 || in.avm_main_sel_rng_8 == 1); + } + + /** + * @brief Subprocedure for computing the value deciding if the inverse polynomial value needs to be checked in this + * row + * + * @tparam Accumulator Type specified by the lookup relation + * @tparam AllEntities Values/Univariates of all entities row + * @param in Value/Univariate of all entities at row/edge + * @return Accumulator + */ + + template + static inline auto compute_inverse_exists(const AllEntities& in) + { + using View = typename Accumulator::View; + const auto is_operation = View(in.avm_alu_pow_2_sel); + const auto is_table_entry = View(in.avm_main_sel_rng_8); + return (is_operation + is_table_entry - is_operation * is_table_entry); + } + + /** + * @brief Get all the entities for the lookup when need to update them + * + * @details The generic structure of this tuple is described in ./generic_lookup_relation.hpp . The following is + description for the current case: + The entities are returned as a tuple of references in the following order (this is for ): + * - The entity/polynomial used to store the product of the inverse values + * - The entity/polynomial that specifies how many times the lookup table entry at this row has been looked up + * - READ_TERMS entities/polynomials that enable individual lookup operations + * - The entity/polynomial that enables adding an entry to the lookup table in this row + * - LOOKUP_TUPLE_SIZE entities/polynomials representing the basic tuple being looked up as the first read term + * - LOOKUP_TUPLE_SIZE entities/polynomials representing the previous accumulators in the second read term + (scaled tuple) + * - LOOKUP_TUPLE_SIZE entities/polynomials representing the shifts in the second read term (scaled tuple) + * - LOOKUP_TUPLE_SIZE entities/polynomials representing the current accumulators in the second read term + (scaled tuple) + * - LOOKUP_TUPLE_SIZE entities/polynomials representing basic tuples added to the table + * + * @return All the entities needed for the lookup + */ + + template static inline auto get_const_entities(const AllEntities& in) + { + + return std::forward_as_tuple(in.pow_2_lookups, + in.pow_2_lookups_counts, + in.avm_alu_pow_2_sel, + in.avm_main_sel_rng_8, + in.avm_alu_ib, + in.avm_alu_two_pow_b, + in.avm_main_clk, + in.avm_main_table_pow_2); + } + + /** + * @brief Get all the entities for the lookup when we only need to read them + * @details Same as in get_const_entities, but nonconst + * + * @return All the entities needed for the lookup + */ + + template static inline auto get_nonconst_entities(AllEntities& in) + { + + return std::forward_as_tuple(in.pow_2_lookups, + in.pow_2_lookups_counts, + in.avm_alu_pow_2_sel, + in.avm_main_sel_rng_8, + in.avm_alu_ib, + in.avm_alu_two_pow_b, + in.avm_main_clk, + in.avm_main_table_pow_2); + } +}; + +template using pow_2_lookups_relation = GenericLookupRelation; +template using pow_2_lookups = GenericLookup; + +} // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_alu_trace.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_alu_trace.cpp index 9935a74b840..d7bea240603 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_alu_trace.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_alu_trace.cpp @@ -41,6 +41,18 @@ bool AvmAluTraceBuilder::is_range_check_required() const return range_checked_required; } +/** + * @brief Helper function that returns a boolean if this entry is an alu operation. + * This is helpful to filter out range check rows or the second row in the 128-bit multiply. + * + * @return A boolean telling whether range check is required. + */ +bool AvmAluTraceBuilder::is_alu_row_enabled(AvmAluTraceBuilder::AluTraceEntry const& r) +{ + return (r.alu_op_add || r.alu_op_sub || r.alu_op_mul || r.alu_op_eq || r.alu_op_not || r.alu_op_lt || + r.alu_op_lte || r.alu_op_shr || r.alu_op_shl || r.alu_op_cast); +} + /** * @brief Build Alu trace and compute the result of an addition of type defined by in_tag. * Besides the addition calculation, for the types u8, u16, u32, u64, and u128, we @@ -501,15 +513,15 @@ std::vector AvmAluTraceBuilder::cmp_range_che } /** - * Helper function to decompose a uint256_t into upper 128-bit and lower 128-bit tuple. + * Helper function to decompose a uint256_t into a b-lower bits and (256-b) upper bits * The outputs are cast to uint256_t so they are easier to use in checks */ -std::tuple decompose(uint256_t const& a) +std::tuple decompose(uint256_t const& a, uint8_t const b) { - uint256_t upper_bitmask = (uint256_t(1) << uint256_t(128)) - 1; + uint256_t upper_bitmask = (uint256_t(1) << uint256_t(b)) - 1; uint256_t a_lo = a & upper_bitmask; - uint256_t a_hi = a >> 128; + uint256_t a_hi = a >> b; return std::make_tuple(a_lo, a_hi); } @@ -518,8 +530,8 @@ std::tuple decompose(uint256_t const& a) std::tuple gt_witness(uint256_t const& a, uint256_t const& b) { uint256_t two_pow_128 = uint256_t(1) << uint256_t(128); - auto [a_lo, a_hi] = decompose(a); - auto [b_lo, b_hi] = decompose(b); + auto [a_lo, a_hi] = decompose(a, 128); + auto [b_lo, b_hi] = decompose(b, 128); bool borrow = a_lo <= b_lo; auto borrow_u256 = uint256_t(static_cast(borrow)); uint256_t r_lo = a_lo - b_lo - 1 + borrow_u256 * two_pow_128; @@ -533,8 +545,8 @@ std::tuple gt_witness(uint256_t const& a, uint256_t std::tuple gt_or_lte_witness(uint256_t const& a, uint256_t const& b) { uint256_t two_pow_128 = uint256_t(1) << uint256_t(128); - auto [a_lo, a_hi] = decompose(a); - auto [b_lo, b_hi] = decompose(b); + auto [a_lo, a_hi] = decompose(a, 128); + auto [b_lo, b_hi] = decompose(b, 128); bool isGT = a > b; if (isGT) { return gt_witness(a, b); @@ -566,9 +578,9 @@ FF AvmAluTraceBuilder::op_lt(FF const& a, FF const& b, AvmMemoryTag in_tag, uint // Note: This is counter-intuitive, to show that a < b we actually show that b > a // The subtlety is here that the circuit is designed as a GT(x,y) circuit, therefore we swap the inputs a & b // Get the decomposition of b - auto [a_lo, a_hi] = decompose(b); + auto [a_lo, a_hi] = decompose(b, 128); // Get the decomposition of a - auto [b_lo, b_hi] = decompose(a); + auto [b_lo, b_hi] = decompose(a, 128); // Get the decomposition of p - a and p - b **remember that we swap the inputs** // Note that a valid witness here is ONLY that p > a and p > b auto [p_sub_a_lo, p_sub_a_hi, p_a_borrow] = gt_witness(FF::modulus, b); @@ -620,9 +632,9 @@ FF AvmAluTraceBuilder::op_lte(FF const& a, FF const& b, AvmMemoryTag in_tag, uin bool c = uint256_t(a) <= uint256_t(b); // Get the decomposition of a - auto [a_lo, a_hi] = decompose(a); + auto [a_lo, a_hi] = decompose(a, 128); // Get the decomposition of b - auto [b_lo, b_hi] = decompose(b); + auto [b_lo, b_hi] = decompose(b, 128); // Get the decomposition of p - a and p - b // Note that a valid witness here is that p > a and p > b auto [p_sub_a_lo, p_sub_a_hi, p_a_borrow] = gt_witness(FF::modulus, a); @@ -694,7 +706,7 @@ FF AvmAluTraceBuilder::op_cast(FF const& a, AvmMemoryTag in_tag, uint32_t clk) } // Get the decomposition of a - auto [a_lo, a_hi] = decompose(uint256_t(a)); + auto [a_lo, a_hi] = decompose(uint256_t(a), 128); // Decomposition of p-a auto [p_sub_a_lo, p_sub_a_hi, p_a_borrow] = gt_witness(FF::modulus, uint256_t(a)); auto [u8_r0, u8_r1, u16_reg] = to_alu_slice_registers(uint256_t(a)); @@ -731,4 +743,219 @@ FF AvmAluTraceBuilder::op_cast(FF const& a, AvmMemoryTag in_tag, uint32_t clk) return c; } +// Returns the number of bits associated with a given memory tag +uint8_t mem_tag_bits(AvmMemoryTag in_tag) +{ + switch (in_tag) { + case AvmMemoryTag::U8: + return 8; + case AvmMemoryTag::U16: + return 16; + case AvmMemoryTag::U32: + return 32; + case AvmMemoryTag::U64: + return 64; + case AvmMemoryTag::U128: + return 128; + case AvmMemoryTag::FF: + return 254; + case AvmMemoryTag::U0: + return 0; + } + return 0; +} + +/** + * @brief Build Alu trace and compute the result of a SHR operation on two operands of type defined by in_tag. + * + * @param a Left operand of the SHR + * @param b Right operand of the SHR + * @param clk Clock referring to the operation in the main trace. + * @param in_tag Instruction tag defining the number of bits for the SHR. + * + * @return FF The boolean result of SHR casted to a finite field element + */ +FF AvmAluTraceBuilder::op_shr(FF const& a, FF const& b, AvmMemoryTag in_tag, uint32_t clk) +{ + // Perform the shift operation over 256-bit integers + uint256_t a_u256{ a }; + // Check that the shifted amount is an 8-bit integer + ASSERT(uint256_t(b) < 256); + + uint8_t b_u8 = static_cast(uint256_t(b)); + uint256_t c_u256 = a_u256 >> b_u8; + + uint8_t num_bits = mem_tag_bits(in_tag); + u8_pow_2_counters[0][b_u8]++; + + // If we are shifting more than the number of bits, the result is trivially 0 + if (b_u8 >= num_bits) { + u8_pow_2_counters[1][b_u8 - num_bits]++; + // Even though the registers are trivially zero, we call this function to increment the lookup counters + [[maybe_unused]] auto [alu_u8_r0, alu_u8_r1, alu_u16_reg] = AvmAluTraceBuilder::to_alu_slice_registers(0); + alu_trace.push_back(AvmAluTraceBuilder::AluTraceEntry{ + .alu_clk = clk, + .alu_op_shr = true, + .alu_ff_tag = in_tag == AvmMemoryTag::FF, + .alu_u8_tag = in_tag == AvmMemoryTag::U8, + .alu_u16_tag = in_tag == AvmMemoryTag::U16, + .alu_u32_tag = in_tag == AvmMemoryTag::U32, + .alu_u64_tag = in_tag == AvmMemoryTag::U64, + .alu_u128_tag = in_tag == AvmMemoryTag::U128, + .alu_ia = a, + .alu_ib = FF(b_u8), + .alu_ic = 0, + .hi_lo_limbs = { 0, 0, 0, 0 }, + .mem_tag_bits = num_bits, + .mem_tag_sub_shift = static_cast(b_u8 - num_bits), + .shift_lt_bit_len = false, + }); + return 0; + } + // We decompose the input into two limbs partitioned at the b-th bit, we use x_lo and x_hi + // to avoid any confusion with the a_lo and a_hi that form part of the range check + auto [x_lo, x_hi] = decompose(a, b_u8); + // We can modify the dynamic range check by performing an additional static one + // rng_chk_lo = 2^b - x_lo - 1 && rng_chk_hi = 2^(num_bits - b) - x_hi - 1 + uint256_t rng_chk_lo = (uint256_t(1) << b_u8) - x_lo - 1; + uint256_t rng_chk_hi = (uint256_t(1) << (num_bits - b_u8)) - x_hi - 1; + + // Each hi and lo limb is range checked over 128bits + uint256_t limb = rng_chk_lo + (rng_chk_hi << uint256_t(128)); + // Load the range check values into the ALU registers + auto [alu_u8_r0, alu_u8_r1, alu_u16_reg] = AvmAluTraceBuilder::to_alu_slice_registers(limb); + + // Add counters for the pow of two lookups + u8_pow_2_counters[1][num_bits - b_u8]++; + + alu_trace.push_back(AvmAluTraceBuilder::AluTraceEntry{ + .alu_clk = clk, + .alu_op_shr = true, + .alu_u8_tag = in_tag == AvmMemoryTag::U8, + .alu_u16_tag = in_tag == AvmMemoryTag::U16, + .alu_u32_tag = in_tag == AvmMemoryTag::U32, + .alu_u64_tag = in_tag == AvmMemoryTag::U64, + .alu_u128_tag = in_tag == AvmMemoryTag::U128, + .alu_ia = a, + .alu_ib = b, + // Could be replaced with x_hi but nice to have 2 ways of calculating the result + .alu_ic = FF(c_u256), + .alu_u8_r0 = alu_u8_r0, + .alu_u8_r1 = alu_u8_r1, + .alu_u16_reg = alu_u16_reg, + .hi_lo_limbs{ rng_chk_lo, rng_chk_hi, x_lo, x_hi }, + .mem_tag_bits = num_bits, + .mem_tag_sub_shift = static_cast(num_bits - b_u8), + .shift_lt_bit_len = true, + + }); + return c_u256; +} + +/** + * @brief Build Alu trace and compute the result of a SHL operation on two operands of type defined by in_tag. + * + * @param a Left operand of the SHL + * @param b Right operand of the SHL + * @param clk Clock referring to the operation in the main trace. + * @param in_tag Instruction tag defining the number of bits for the SHL. + * + * @return FF The boolean result of SHL casted to a finite field element + */ +FF AvmAluTraceBuilder::op_shl(FF const& a, FF const& b, AvmMemoryTag in_tag, uint32_t clk) +{ + // Perform the shift operation over 256-bit integers + uint256_t a_u256{ a }; + // Check that the shift amount is an 8-bit integer + ASSERT(uint256_t(b) < 256); + uint8_t b_u8 = static_cast(uint256_t(b)); + + uint256_t c_u256 = a_u256 << b_u8; + + uint8_t num_bits = mem_tag_bits(in_tag); + u8_pow_2_counters[0][b_u8]++; + // If we are shifting more than the number of bits, the result is trivially 0 + if (b_u8 >= num_bits) { + u8_pow_2_counters[1][b_u8 - num_bits]++; + // Even though the registers are trivially zero, we call this function to increment the lookup counters + [[maybe_unused]] auto [alu_u8_r0, alu_u8_r1, alu_u16_reg] = AvmAluTraceBuilder::to_alu_slice_registers(0); + alu_trace.push_back(AvmAluTraceBuilder::AluTraceEntry{ + .alu_clk = clk, + .alu_op_shl = true, + .alu_ff_tag = in_tag == AvmMemoryTag::FF, + .alu_u8_tag = in_tag == AvmMemoryTag::U8, + .alu_u16_tag = in_tag == AvmMemoryTag::U16, + .alu_u32_tag = in_tag == AvmMemoryTag::U32, + .alu_u64_tag = in_tag == AvmMemoryTag::U64, + .alu_u128_tag = in_tag == AvmMemoryTag::U128, + .alu_ia = a, + .alu_ib = FF(b_u8), + .alu_ic = 0, + .hi_lo_limbs = { 0, 0, 0, 0 }, + .mem_tag_bits = num_bits, + .mem_tag_sub_shift = static_cast(b_u8 - num_bits), + .shift_lt_bit_len = false, + }); + return 0; + } + // We decompose the input into two limbs partitioned at the b-th bit, we use x_lo and x_hi + // to avoid any confusion with the a_lo and a_hi that form part of the range check + auto [x_lo, x_hi] = decompose(a, num_bits - b_u8); + + u8_pow_2_counters[1][num_bits - b_u8]++; + // We can modify the dynamic range check by performing an additional static one + // rng_chk_lo = 2^(num_bits - b) - x_lo - 1 && rng_chk_hi = 2^b - x_hi - 1 + uint256_t rng_chk_lo = uint256_t(uint256_t(1) << (num_bits - b_u8)) - x_lo - 1; + uint256_t rng_chk_hi = uint256_t(uint256_t(1) << b_u8) - x_hi - 1; + + // Each hi and lo limb is range checked over 128bits + uint256_t limb = rng_chk_lo + (rng_chk_hi << 128); + // Load the range check values into the ALU registers + auto [alu_u8_r0, alu_u8_r1, alu_u16_reg] = AvmAluTraceBuilder::to_alu_slice_registers(limb); + + FF c = 0; + switch (in_tag) { + case AvmMemoryTag::U8: + c = FF{ uint8_t(c_u256) }; + break; + case AvmMemoryTag::U16: + c = FF{ uint16_t(c_u256) }; + break; + case AvmMemoryTag::U32: + c = FF{ uint32_t(c_u256) }; + break; + case AvmMemoryTag::U64: + c = FF{ uint64_t(c_u256) }; + break; + case AvmMemoryTag::U128: + c = FF{ uint256_t::from_uint128(uint128_t(c_u256)) }; + break; + // Unsupported instruction tags + case AvmMemoryTag::U0: + case AvmMemoryTag::FF: + return 0; + } + + alu_trace.push_back(AvmAluTraceBuilder::AluTraceEntry{ + .alu_clk = clk, + .alu_op_shl = true, + .alu_ff_tag = in_tag == AvmMemoryTag::FF, + .alu_u8_tag = in_tag == AvmMemoryTag::U8, + .alu_u16_tag = in_tag == AvmMemoryTag::U16, + .alu_u32_tag = in_tag == AvmMemoryTag::U32, + .alu_u64_tag = in_tag == AvmMemoryTag::U64, + .alu_u128_tag = in_tag == AvmMemoryTag::U128, + .alu_ia = a, + .alu_ib = b, + .alu_ic = c, + .alu_u8_r0 = alu_u8_r0, + .alu_u8_r1 = alu_u8_r1, + .alu_u16_reg = alu_u16_reg, + .hi_lo_limbs{ rng_chk_lo, rng_chk_hi, x_lo, x_hi }, + .mem_tag_bits = num_bits, + .mem_tag_sub_shift = static_cast(num_bits - b_u8), + .shift_lt_bit_len = true, + }); + return c; +} } // namespace bb::avm_trace diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_alu_trace.hpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_alu_trace.hpp index 7920aabd28e..e01e8e53b4b 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_alu_trace.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_alu_trace.hpp @@ -19,6 +19,8 @@ class AvmAluTraceBuilder { bool alu_op_lte = false; bool alu_op_cast = false; bool alu_op_cast_prev = false; + bool alu_op_shr = false; + bool alu_op_shl = false; bool alu_ff_tag = false; bool alu_u8_tag = false; @@ -48,9 +50,15 @@ class AvmAluTraceBuilder { bool p_b_borrow = false; uint8_t cmp_rng_ctr = 0; bool rng_chk_sel = false; + + // Shift Operations + uint8_t mem_tag_bits = 0; + uint8_t mem_tag_sub_shift = 0; + bool shift_lt_bit_len = true; }; std::array, 2> u8_range_chk_counters; + std::array, 2> u8_pow_2_counters; std::array, 15> u16_range_chk_counters; AvmAluTraceBuilder(); @@ -65,8 +73,11 @@ class AvmAluTraceBuilder { FF op_lt(FF const& a, FF const& b, AvmMemoryTag in_tag, uint32_t clk); FF op_lte(FF const& a, FF const& b, AvmMemoryTag in_tag, uint32_t clk); FF op_cast(FF const& a, AvmMemoryTag in_tag, uint32_t clk); + FF op_shr(FF const& a, FF const& b, AvmMemoryTag in_tag, uint32_t clk); + FF op_shl(FF const& a, FF const& b, AvmMemoryTag in_tag, uint32_t clk); bool is_range_check_required() const; + static bool is_alu_row_enabled(AvmAluTraceBuilder::AluTraceEntry const& r); private: std::vector alu_trace; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_deserialization.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_deserialization.cpp index 9b9c4bd7b3e..bce4188712d 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_deserialization.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_deserialization.cpp @@ -35,6 +35,8 @@ const std::unordered_map> OPCODE_WIRE_FORMAT = { OpCode::AND, three_operand_format }, { OpCode::OR, three_operand_format }, { OpCode::XOR, three_operand_format }, + { OpCode::SHR, three_operand_format }, + { OpCode::SHL, three_operand_format }, // Compute - Type Conversions { OpCode::CAST, { OperandType::INDIRECT, OperandType::TAG, OperandType::UINT32, OperandType::UINT32 } }, // Execution Environment - Calldata diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp index e25d9ad1807..85c5ed9ebea 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp @@ -180,6 +180,20 @@ std::vector Execution::gen_trace(std::vector const& instructio std::get(inst.operands.at(4)), std::get(inst.operands.at(1))); break; + case OpCode::SHR: + trace_builder.op_shr(std::get(inst.operands.at(0)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + std::get(inst.operands.at(4)), + std::get(inst.operands.at(1))); + break; + case OpCode::SHL: + trace_builder.op_shl(std::get(inst.operands.at(0)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + std::get(inst.operands.at(4)), + std::get(inst.operands.at(1))); + break; // Compute - Type Conversions case OpCode::CAST: trace_builder.op_cast(std::get(inst.operands.at(0)), diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_helper.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_helper.cpp index 71bc1b292ae..08691c39e83 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_helper.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_helper.cpp @@ -11,77 +11,79 @@ namespace bb::avm_trace { */ void log_avm_trace(std::vector const& trace, size_t beg, size_t end, bool enable_selectors) { - info("Built circuit with ", trace.size(), " rows"); + { + info("Built circuit with ", trace.size(), " rows"); - for (size_t i = beg; i < end; i++) { - info("====================================================================================="); - info("== ROW ", i); - info("====================================================================================="); + for (size_t i = beg; i < end; i++) { + info("====================================================================================="); + info("== ROW ", i); + info("====================================================================================="); - info("=======MEMORY TRACE=================================================================="); - info("m_addr: ", trace.at(i).avm_mem_addr); - info("m_clk: ", trace.at(i).avm_mem_clk); - info("m_sub_clk: ", trace.at(i).avm_mem_sub_clk); - info("m_val: ", trace.at(i).avm_mem_val); - info("m_rw: ", trace.at(i).avm_mem_rw); - info("m_tag: ", trace.at(i).avm_mem_tag); - info("r_in_tag: ", trace.at(i).avm_mem_r_in_tag); - info("w_in_tag: ", trace.at(i).avm_mem_w_in_tag); - info("m_tag_err: ", trace.at(i).avm_mem_tag_err); - info("m_one_min_inv: ", trace.at(i).avm_mem_one_min_inv); + info("=======MEMORY TRACE=================================================================="); + info("m_addr: ", trace.at(i).avm_mem_addr); + info("m_clk: ", trace.at(i).avm_mem_clk); + info("m_sub_clk: ", trace.at(i).avm_mem_sub_clk); + info("m_val: ", trace.at(i).avm_mem_val); + info("m_rw: ", trace.at(i).avm_mem_rw); + info("m_tag: ", trace.at(i).avm_mem_tag); + info("r_in_tag: ", trace.at(i).avm_mem_r_in_tag); + info("w_in_tag: ", trace.at(i).avm_mem_w_in_tag); + info("m_tag_err: ", trace.at(i).avm_mem_tag_err); + info("m_one_min_inv: ", trace.at(i).avm_mem_one_min_inv); - info("m_lastAccess: ", trace.at(i).avm_mem_lastAccess); - info("m_last: ", trace.at(i).avm_mem_last); - info("m_val_shift: ", trace.at(i).avm_mem_val_shift); + info("m_lastAccess: ", trace.at(i).avm_mem_lastAccess); + info("m_last: ", trace.at(i).avm_mem_last); + info("m_val_shift: ", trace.at(i).avm_mem_val_shift); - info("=======CONTROL_FLOW==================================================================="); - info("pc: ", trace.at(i).avm_main_pc); - info("internal_call: ", trace.at(i).avm_main_sel_internal_call); - info("internal_return: ", trace.at(i).avm_main_sel_internal_return); - info("internal_return_ptr:", trace.at(i).avm_main_internal_return_ptr); + info("=======CONTROL_FLOW==================================================================="); + info("pc: ", trace.at(i).avm_main_pc); + info("internal_call: ", trace.at(i).avm_main_sel_internal_call); + info("internal_return: ", trace.at(i).avm_main_sel_internal_return); + info("internal_return_ptr:", trace.at(i).avm_main_internal_return_ptr); - info("=======ALU TRACE====================================================================="); - info("alu_clk ", trace.at(i).avm_alu_clk); - info("alu_ia ", trace.at(i).avm_alu_ia); - info("alu_ib ", trace.at(i).avm_alu_ib); - info("alu_ic ", trace.at(i).avm_alu_ic); + info("=======ALU TRACE====================================================================="); + info("alu_clk ", trace.at(i).avm_alu_clk); + info("alu_ia ", trace.at(i).avm_alu_ia); + info("alu_ib ", trace.at(i).avm_alu_ib); + info("alu_ic ", trace.at(i).avm_alu_ic); - info("=======MAIN TRACE===================================================================="); - info("clk: ", trace.at(i).avm_main_clk); - info("ia: ", trace.at(i).avm_main_ia); - info("ib: ", trace.at(i).avm_main_ib); - info("ic: ", trace.at(i).avm_main_ic); - info("r_in_tag ", trace.at(i).avm_main_r_in_tag); - info("w_in_tag ", trace.at(i).avm_main_w_in_tag); - info("tag_err ", trace.at(i).avm_main_tag_err); - info("first: ", trace.at(i).avm_main_first); - info("last: ", trace.at(i).avm_main_last); + info("=======MAIN TRACE===================================================================="); + info("clk: ", trace.at(i).avm_main_clk); + info("ia: ", trace.at(i).avm_main_ia); + info("ib: ", trace.at(i).avm_main_ib); + info("ic: ", trace.at(i).avm_main_ic); + info("r_in_tag ", trace.at(i).avm_main_r_in_tag); + info("w_in_tag ", trace.at(i).avm_main_w_in_tag); + info("tag_err ", trace.at(i).avm_main_tag_err); + info("first: ", trace.at(i).avm_main_first); + info("last: ", trace.at(i).avm_main_last); - info("=======MEM_OP_A======================================================================"); - info("mem_op_a: ", trace.at(i).avm_main_mem_op_a); - info("mem_idx_a: ", trace.at(i).avm_main_mem_idx_a); - info("rwa: ", trace.at(i).avm_main_rwa); + info("=======MEM_OP_A======================================================================"); + info("mem_op_a: ", trace.at(i).avm_main_mem_op_a); + info("mem_idx_a: ", trace.at(i).avm_main_mem_idx_a); + info("rwa: ", trace.at(i).avm_main_rwa); - info("=======MEM_OP_B======================================================================"); - info("mem_op_b: ", trace.at(i).avm_main_mem_op_b); - info("mem_idx_b: ", trace.at(i).avm_main_mem_idx_b); - info("rwb: ", trace.at(i).avm_main_rwb); + info("=======MEM_OP_B======================================================================"); + info("mem_op_b: ", trace.at(i).avm_main_mem_op_b); + info("mem_idx_b: ", trace.at(i).avm_main_mem_idx_b); + info("rwb: ", trace.at(i).avm_main_rwb); - info("=======MEM_OP_C======================================================================"); - info("mem_op_c: ", trace.at(i).avm_main_mem_op_c); - info("mem_idx_c: ", trace.at(i).avm_main_mem_idx_c); - info("rwc: ", trace.at(i).avm_main_rwc); + info("=======MEM_OP_C======================================================================"); + info("mem_op_c: ", trace.at(i).avm_main_mem_op_c); + info("mem_idx_c: ", trace.at(i).avm_main_mem_idx_c); + info("rwc: ", trace.at(i).avm_main_rwc); - if (enable_selectors) { - info("=======SELECTORS======================================================================"); - info("sel_op_add: ", trace.at(i).avm_main_sel_op_add); - info("sel_op_sub: ", trace.at(i).avm_main_sel_op_sub); - info("sel_op_mul: ", trace.at(i).avm_main_sel_op_mul); - info("sel_op_eq: ", trace.at(i).avm_main_sel_op_eq); - info("sel_op_not: ", trace.at(i).avm_main_sel_op_not); - info("sel_op_sel_alu: ", trace.at(i).avm_main_alu_sel); + if (enable_selectors) { + info("=======SELECTORS======================================================================"); + info("sel_op_add: ", trace.at(i).avm_main_sel_op_add); + info("sel_op_sub: ", trace.at(i).avm_main_sel_op_sub); + info("sel_op_mul: ", trace.at(i).avm_main_sel_op_mul); + info("sel_op_eq: ", trace.at(i).avm_main_sel_op_eq); + info("sel_op_not: ", trace.at(i).avm_main_sel_op_not); + info("sel_op_sel_alu: ", trace.at(i).avm_main_alu_sel); + } + info("\n"); } - info("\n"); } } diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp index 9a449eb43e8..8b92cfbeddc 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp @@ -735,6 +735,109 @@ void AvmTraceBuilder::op_lte( }); } +void AvmTraceBuilder::op_shr( + uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, AvmMemoryTag in_tag) +{ + + auto clk = static_cast(main_trace.size()); + + auto const res = resolve_ind_three(clk, indirect, a_offset, b_offset, dst_offset); + bool tag_match = res.tag_match; + + // Reading from memory and loading into ia resp. ib. + auto read_a = + mem_trace_builder.read_and_load_from_memory(clk, IntermRegister::IA, res.direct_a_offset, in_tag, in_tag); + auto read_b = + mem_trace_builder.read_and_load_from_memory(clk, IntermRegister::IB, res.direct_b_offset, in_tag, in_tag); + tag_match = read_a.tag_match && read_b.tag_match; + + FF a = tag_match ? read_a.val : FF(0); + FF b = tag_match ? read_b.val : FF(0); + + FF c = tag_match ? alu_trace_builder.op_shr(a, b, in_tag, clk) : FF(0); + + // Write into memory value c from intermediate register ic. + mem_trace_builder.write_into_memory(clk, IntermRegister::IC, res.direct_c_offset, c, in_tag, in_tag); + + main_trace.push_back(Row{ + .avm_main_clk = clk, + .avm_main_alu_in_tag = FF(static_cast(in_tag)), + .avm_main_ia = a, + .avm_main_ib = b, + .avm_main_ic = c, + .avm_main_ind_a = res.indirect_flag_a ? FF(a_offset) : FF(0), + .avm_main_ind_b = res.indirect_flag_b ? FF(b_offset) : FF(0), + .avm_main_ind_c = res.indirect_flag_c ? FF(dst_offset) : FF(0), + .avm_main_ind_op_a = FF(static_cast(res.indirect_flag_a)), + .avm_main_ind_op_b = FF(static_cast(res.indirect_flag_b)), + .avm_main_ind_op_c = FF(static_cast(res.indirect_flag_c)), + .avm_main_internal_return_ptr = FF(internal_return_ptr), + .avm_main_mem_idx_a = FF(res.direct_a_offset), + .avm_main_mem_idx_b = FF(res.direct_b_offset), + .avm_main_mem_idx_c = FF(res.direct_c_offset), + .avm_main_mem_op_a = FF(1), + .avm_main_mem_op_b = FF(1), + .avm_main_mem_op_c = FF(1), + .avm_main_pc = FF(pc++), + .avm_main_r_in_tag = FF(static_cast(in_tag)), + .avm_main_rwc = FF(1), + .avm_main_sel_op_shr = FF(1), + .avm_main_tag_err = FF(static_cast(!tag_match)), + .avm_main_w_in_tag = FF(static_cast(in_tag)), + }); +} + +void AvmTraceBuilder::op_shl( + uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, AvmMemoryTag in_tag) +{ + + auto clk = static_cast(main_trace.size()); + + auto const res = resolve_ind_three(clk, indirect, a_offset, b_offset, dst_offset); + bool tag_match = res.tag_match; + + // Reading from memory and loading into ia resp. ib. + auto read_a = + mem_trace_builder.read_and_load_from_memory(clk, IntermRegister::IA, res.direct_a_offset, in_tag, in_tag); + auto read_b = + mem_trace_builder.read_and_load_from_memory(clk, IntermRegister::IB, res.direct_b_offset, in_tag, in_tag); + tag_match = read_a.tag_match && read_b.tag_match; + + FF a = tag_match ? read_a.val : FF(0); + FF b = tag_match ? read_b.val : FF(0); + + FF c = tag_match ? alu_trace_builder.op_shl(a, b, in_tag, clk) : FF(0); + + // Write into memory value c from intermediate register ic. + mem_trace_builder.write_into_memory(clk, IntermRegister::IC, res.direct_c_offset, c, in_tag, in_tag); + + main_trace.push_back(Row{ + .avm_main_clk = clk, + .avm_main_alu_in_tag = FF(static_cast(in_tag)), + .avm_main_ia = a, + .avm_main_ib = b, + .avm_main_ic = c, + .avm_main_ind_a = res.indirect_flag_a ? FF(a_offset) : FF(0), + .avm_main_ind_b = res.indirect_flag_b ? FF(b_offset) : FF(0), + .avm_main_ind_c = res.indirect_flag_c ? FF(dst_offset) : FF(0), + .avm_main_ind_op_a = FF(static_cast(res.indirect_flag_a)), + .avm_main_ind_op_b = FF(static_cast(res.indirect_flag_b)), + .avm_main_ind_op_c = FF(static_cast(res.indirect_flag_c)), + .avm_main_internal_return_ptr = FF(internal_return_ptr), + .avm_main_mem_idx_a = FF(res.direct_a_offset), + .avm_main_mem_idx_b = FF(res.direct_b_offset), + .avm_main_mem_idx_c = FF(res.direct_c_offset), + .avm_main_mem_op_a = FF(1), + .avm_main_mem_op_b = FF(1), + .avm_main_mem_op_c = FF(1), + .avm_main_pc = FF(pc++), + .avm_main_r_in_tag = FF(static_cast(in_tag)), + .avm_main_rwc = FF(1), + .avm_main_sel_op_shl = FF(1), + .avm_main_tag_err = FF(static_cast(!tag_match)), + .avm_main_w_in_tag = FF(static_cast(in_tag)), + }); +} // TODO: Ensure that the bytecode validation and/or deserialization is // enforcing that val complies to the tag. /** @@ -1519,6 +1622,8 @@ std::vector AvmTraceBuilder::finalize() dest.avm_alu_op_cast_prev = FF(static_cast(src.alu_op_cast_prev)); dest.avm_alu_cmp_sel = FF(static_cast(src.alu_op_lt) + static_cast(src.alu_op_lte)); dest.avm_alu_rng_chk_sel = FF(static_cast(src.rng_chk_sel)); + dest.avm_alu_op_shr = FF(static_cast(src.alu_op_shr)); + dest.avm_alu_op_shl = FF(static_cast(src.alu_op_shl)); dest.avm_alu_ff_tag = FF(static_cast(src.alu_ff_tag)); dest.avm_alu_u8_tag = FF(static_cast(src.alu_u8_tag)); @@ -1560,9 +1665,7 @@ std::vector AvmTraceBuilder::finalize() // Not all rows in ALU are enabled with a selector. For instance, // multiplication over u128 is taking two lines. - if (dest.avm_alu_op_add == FF(1) || dest.avm_alu_op_sub == FF(1) || dest.avm_alu_op_mul == FF(1) || - dest.avm_alu_op_eq == FF(1) || dest.avm_alu_op_not == FF(1) || dest.avm_alu_op_lt == FF(1) || - dest.avm_alu_op_lte == FF(1) || dest.avm_alu_op_cast == FF(1)) { + if (AvmAluTraceBuilder::is_alu_row_enabled(src)) { dest.avm_alu_alu_sel = FF(1); } @@ -1607,14 +1710,27 @@ std::vector AvmTraceBuilder::finalize() if (dest.avm_alu_op_mul == FF(1) && dest.avm_alu_u128_tag) { main_trace.at(i + 1).avm_alu_rng_chk_lookup_selector = FF(1); } + if (src.alu_op_shr || src.alu_op_shl) { + dest.avm_alu_a_lo = FF(src.hi_lo_limbs[0]); + dest.avm_alu_a_hi = FF(src.hi_lo_limbs[1]); + dest.avm_alu_b_lo = FF(src.hi_lo_limbs[2]); + dest.avm_alu_b_hi = FF(src.hi_lo_limbs[3]); + dest.avm_alu_shift_sel = FF(1); + dest.avm_alu_shift_lt_bit_len = FF(static_cast(src.shift_lt_bit_len)); + dest.avm_alu_t_sub_s_bits = FF(src.mem_tag_sub_shift); + dest.avm_alu_two_pow_s = FF(uint256_t(1) << dest.avm_alu_ib); + dest.avm_alu_two_pow_t_sub_s = FF(uint256_t(1) << uint256_t(dest.avm_alu_t_sub_s_bits)); + dest.avm_alu_rng_chk_lookup_selector = FF(1); + } } for (size_t i = 0; i < main_trace_size; i++) { auto& r = main_trace.at(i); if ((r.avm_main_sel_op_add == FF(1) || r.avm_main_sel_op_sub == FF(1) || r.avm_main_sel_op_mul == FF(1) || - r.avm_main_sel_op_eq == FF(1) || r.avm_main_sel_op_not == FF(1) || r.avm_main_sel_op_lt || - r.avm_main_sel_op_lte || r.avm_main_sel_op_cast == FF(1)) && + r.avm_main_sel_op_eq == FF(1) || r.avm_main_sel_op_not == FF(1) || r.avm_main_sel_op_lt == FF(1) || + r.avm_main_sel_op_lte == FF(1) || r.avm_main_sel_op_cast == FF(1) || r.avm_main_sel_op_shr == FF(1) || + r.avm_main_sel_op_shl == FF(1)) && r.avm_main_tag_err == FF(0)) { r.avm_main_alu_sel = FF(1); } @@ -1622,7 +1738,10 @@ std::vector AvmTraceBuilder::finalize() if (i <= UINT8_MAX) { r.lookup_u8_0_counts = alu_trace_builder.u8_range_chk_counters[0][static_cast(i)]; r.lookup_u8_1_counts = alu_trace_builder.u8_range_chk_counters[1][static_cast(i)]; + r.lookup_pow_2_0_counts = alu_trace_builder.u8_pow_2_counters[0][static_cast(i)]; + r.lookup_pow_2_1_counts = alu_trace_builder.u8_pow_2_counters[1][static_cast(i)]; r.avm_main_sel_rng_8 = FF(1); + r.avm_main_table_pow_2 = uint256_t(1) << uint256_t(i); } if (i <= UINT16_MAX) { diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.hpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.hpp index 71b1aabe368..059d2fdd6c9 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.hpp @@ -62,6 +62,12 @@ class AvmTraceBuilder { // Less Than or Equal to with direct or indirect memory access. void op_lte(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, AvmMemoryTag in_tag); + // Shift Right with direct or indirect memory access. + void op_shr(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, AvmMemoryTag in_tag); + + // Shift Left with direct or indirect memory access. + void op_shl(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, AvmMemoryTag in_tag); + // Set a constant from bytecode with direct or indirect memory access. void op_set(uint8_t indirect, uint128_t val, uint32_t dst_offset, AvmMemoryTag in_tag); diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.hpp index 4bfaa9fa499..d43ce2b914b 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.hpp @@ -19,6 +19,8 @@ #include "barretenberg/relations/generated/avm/incl_mem_tag_err.hpp" #include "barretenberg/relations/generated/avm/lookup_byte_lengths.hpp" #include "barretenberg/relations/generated/avm/lookup_byte_operations.hpp" +#include "barretenberg/relations/generated/avm/lookup_pow_2_0.hpp" +#include "barretenberg/relations/generated/avm/lookup_pow_2_1.hpp" #include "barretenberg/relations/generated/avm/lookup_u16_0.hpp" #include "barretenberg/relations/generated/avm/lookup_u16_1.hpp" #include "barretenberg/relations/generated/avm/lookup_u16_10.hpp" @@ -78,6 +80,8 @@ template struct AvmFullRow { FF avm_alu_op_lte{}; FF avm_alu_op_mul{}; FF avm_alu_op_not{}; + FF avm_alu_op_shl{}; + FF avm_alu_op_shr{}; FF avm_alu_op_sub{}; FF avm_alu_p_a_borrow{}; FF avm_alu_p_b_borrow{}; @@ -89,6 +93,11 @@ template struct AvmFullRow { FF avm_alu_res_lo{}; FF avm_alu_rng_chk_lookup_selector{}; FF avm_alu_rng_chk_sel{}; + FF avm_alu_shift_lt_bit_len{}; + FF avm_alu_shift_sel{}; + FF avm_alu_t_sub_s_bits{}; + FF avm_alu_two_pow_s{}; + FF avm_alu_two_pow_t_sub_s{}; FF avm_alu_u128_tag{}; FF avm_alu_u16_r0{}; FF avm_alu_u16_r1{}; @@ -184,10 +193,13 @@ template struct AvmFullRow { FF avm_main_sel_op_mul{}; FF avm_main_sel_op_not{}; FF avm_main_sel_op_or{}; + FF avm_main_sel_op_shl{}; + FF avm_main_sel_op_shr{}; FF avm_main_sel_op_sub{}; FF avm_main_sel_op_xor{}; FF avm_main_sel_rng_16{}; FF avm_main_sel_rng_8{}; + FF avm_main_table_pow_2{}; FF avm_main_tag_err{}; FF avm_main_w_in_tag{}; FF avm_mem_addr{}; @@ -228,6 +240,8 @@ template struct AvmFullRow { FF lookup_byte_operations{}; FF incl_main_tag_err{}; FF incl_mem_tag_err{}; + FF lookup_pow_2_0{}; + FF lookup_pow_2_1{}; FF lookup_u8_0{}; FF lookup_u8_1{}; FF lookup_u16_0{}; @@ -249,6 +263,8 @@ template struct AvmFullRow { FF lookup_byte_operations_counts{}; FF incl_main_tag_err_counts{}; FF incl_mem_tag_err_counts{}; + FF lookup_pow_2_0_counts{}; + FF lookup_pow_2_1_counts{}; FF lookup_u8_0_counts{}; FF lookup_u8_1_counts{}; FF lookup_u16_0_counts{}; @@ -277,6 +293,8 @@ template struct AvmFullRow { FF avm_alu_op_cast_prev_shift{}; FF avm_alu_op_cast_shift{}; FF avm_alu_op_mul_shift{}; + FF avm_alu_op_shl_shift{}; + FF avm_alu_op_shr_shift{}; FF avm_alu_op_sub_shift{}; FF avm_alu_p_sub_a_hi_shift{}; FF avm_alu_p_sub_a_lo_shift{}; @@ -316,8 +334,8 @@ class AvmCircuitBuilder { using Polynomial = Flavor::Polynomial; using ProverPolynomials = Flavor::ProverPolynomials; - static constexpr size_t num_fixed_columns = 253; - static constexpr size_t num_polys = 215; + static constexpr size_t num_fixed_columns = 269; + static constexpr size_t num_polys = 229; std::vector rows; void set_trace(std::vector&& trace) { rows = std::move(trace); } @@ -360,6 +378,8 @@ class AvmCircuitBuilder { polys.avm_alu_op_lte[i] = rows[i].avm_alu_op_lte; polys.avm_alu_op_mul[i] = rows[i].avm_alu_op_mul; polys.avm_alu_op_not[i] = rows[i].avm_alu_op_not; + polys.avm_alu_op_shl[i] = rows[i].avm_alu_op_shl; + polys.avm_alu_op_shr[i] = rows[i].avm_alu_op_shr; polys.avm_alu_op_sub[i] = rows[i].avm_alu_op_sub; polys.avm_alu_p_a_borrow[i] = rows[i].avm_alu_p_a_borrow; polys.avm_alu_p_b_borrow[i] = rows[i].avm_alu_p_b_borrow; @@ -371,6 +391,11 @@ class AvmCircuitBuilder { polys.avm_alu_res_lo[i] = rows[i].avm_alu_res_lo; polys.avm_alu_rng_chk_lookup_selector[i] = rows[i].avm_alu_rng_chk_lookup_selector; polys.avm_alu_rng_chk_sel[i] = rows[i].avm_alu_rng_chk_sel; + polys.avm_alu_shift_lt_bit_len[i] = rows[i].avm_alu_shift_lt_bit_len; + polys.avm_alu_shift_sel[i] = rows[i].avm_alu_shift_sel; + polys.avm_alu_t_sub_s_bits[i] = rows[i].avm_alu_t_sub_s_bits; + polys.avm_alu_two_pow_s[i] = rows[i].avm_alu_two_pow_s; + polys.avm_alu_two_pow_t_sub_s[i] = rows[i].avm_alu_two_pow_t_sub_s; polys.avm_alu_u128_tag[i] = rows[i].avm_alu_u128_tag; polys.avm_alu_u16_r0[i] = rows[i].avm_alu_u16_r0; polys.avm_alu_u16_r1[i] = rows[i].avm_alu_u16_r1; @@ -466,10 +491,13 @@ class AvmCircuitBuilder { polys.avm_main_sel_op_mul[i] = rows[i].avm_main_sel_op_mul; polys.avm_main_sel_op_not[i] = rows[i].avm_main_sel_op_not; polys.avm_main_sel_op_or[i] = rows[i].avm_main_sel_op_or; + polys.avm_main_sel_op_shl[i] = rows[i].avm_main_sel_op_shl; + polys.avm_main_sel_op_shr[i] = rows[i].avm_main_sel_op_shr; polys.avm_main_sel_op_sub[i] = rows[i].avm_main_sel_op_sub; polys.avm_main_sel_op_xor[i] = rows[i].avm_main_sel_op_xor; polys.avm_main_sel_rng_16[i] = rows[i].avm_main_sel_rng_16; polys.avm_main_sel_rng_8[i] = rows[i].avm_main_sel_rng_8; + polys.avm_main_table_pow_2[i] = rows[i].avm_main_table_pow_2; polys.avm_main_tag_err[i] = rows[i].avm_main_tag_err; polys.avm_main_w_in_tag[i] = rows[i].avm_main_w_in_tag; polys.avm_mem_addr[i] = rows[i].avm_mem_addr; @@ -500,6 +528,8 @@ class AvmCircuitBuilder { polys.lookup_byte_operations_counts[i] = rows[i].lookup_byte_operations_counts; polys.incl_main_tag_err_counts[i] = rows[i].incl_main_tag_err_counts; polys.incl_mem_tag_err_counts[i] = rows[i].incl_mem_tag_err_counts; + polys.lookup_pow_2_0_counts[i] = rows[i].lookup_pow_2_0_counts; + polys.lookup_pow_2_1_counts[i] = rows[i].lookup_pow_2_1_counts; polys.lookup_u8_0_counts[i] = rows[i].lookup_u8_0_counts; polys.lookup_u8_1_counts[i] = rows[i].lookup_u8_1_counts; polys.lookup_u16_0_counts[i] = rows[i].lookup_u16_0_counts; @@ -530,6 +560,8 @@ class AvmCircuitBuilder { polys.avm_alu_op_cast_prev_shift = Polynomial(polys.avm_alu_op_cast_prev.shifted()); polys.avm_alu_op_cast_shift = Polynomial(polys.avm_alu_op_cast.shifted()); polys.avm_alu_op_mul_shift = Polynomial(polys.avm_alu_op_mul.shifted()); + polys.avm_alu_op_shl_shift = Polynomial(polys.avm_alu_op_shl.shifted()); + polys.avm_alu_op_shr_shift = Polynomial(polys.avm_alu_op_shr.shifted()); polys.avm_alu_op_sub_shift = Polynomial(polys.avm_alu_op_sub.shifted()); polys.avm_alu_p_sub_a_hi_shift = Polynomial(polys.avm_alu_p_sub_a_hi.shifted()); polys.avm_alu_p_sub_a_lo_shift = Polynomial(polys.avm_alu_p_sub_a_lo.shifted()); @@ -688,6 +720,12 @@ class AvmCircuitBuilder { if (!evaluate_logderivative.template operator()>("INCL_MEM_TAG_ERR")) { return false; } + if (!evaluate_logderivative.template operator()>("LOOKUP_POW_2_0")) { + return false; + } + if (!evaluate_logderivative.template operator()>("LOOKUP_POW_2_1")) { + return false; + } if (!evaluate_logderivative.template operator()>("LOOKUP_U8_0")) { return false; } diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp index bcdaabdbd6c..bad383523e2 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp @@ -21,6 +21,8 @@ #include "barretenberg/relations/generated/avm/incl_mem_tag_err.hpp" #include "barretenberg/relations/generated/avm/lookup_byte_lengths.hpp" #include "barretenberg/relations/generated/avm/lookup_byte_operations.hpp" +#include "barretenberg/relations/generated/avm/lookup_pow_2_0.hpp" +#include "barretenberg/relations/generated/avm/lookup_pow_2_1.hpp" #include "barretenberg/relations/generated/avm/lookup_u16_0.hpp" #include "barretenberg/relations/generated/avm/lookup_u16_1.hpp" #include "barretenberg/relations/generated/avm/lookup_u16_10.hpp" @@ -69,11 +71,11 @@ class AvmFlavor { using RelationSeparator = FF; static constexpr size_t NUM_PRECOMPUTED_ENTITIES = 2; - static constexpr size_t NUM_WITNESS_ENTITIES = 213; + static constexpr size_t NUM_WITNESS_ENTITIES = 227; static constexpr size_t NUM_WIRES = NUM_WITNESS_ENTITIES + NUM_PRECOMPUTED_ENTITIES; // We have two copies of the witness entities, so we subtract the number of fixed ones (they have no shift), one for // the unshifted and one for the shifted - static constexpr size_t NUM_ALL_ENTITIES = 253; + static constexpr size_t NUM_ALL_ENTITIES = 269; using GrandProductRelations = std::tuple, perm_main_bin_relation, @@ -89,6 +91,8 @@ class AvmFlavor { lookup_byte_operations_relation, incl_main_tag_err_relation, incl_mem_tag_err_relation, + lookup_pow_2_0_relation, + lookup_pow_2_1_relation, lookup_u8_0_relation, lookup_u8_1_relation, lookup_u16_0_relation, @@ -125,6 +129,8 @@ class AvmFlavor { lookup_byte_operations_relation, incl_main_tag_err_relation, incl_mem_tag_err_relation, + lookup_pow_2_0_relation, + lookup_pow_2_1_relation, lookup_u8_0_relation, lookup_u8_1_relation, lookup_u16_0_relation, @@ -200,6 +206,8 @@ class AvmFlavor { avm_alu_op_lte, avm_alu_op_mul, avm_alu_op_not, + avm_alu_op_shl, + avm_alu_op_shr, avm_alu_op_sub, avm_alu_p_a_borrow, avm_alu_p_b_borrow, @@ -211,6 +219,11 @@ class AvmFlavor { avm_alu_res_lo, avm_alu_rng_chk_lookup_selector, avm_alu_rng_chk_sel, + avm_alu_shift_lt_bit_len, + avm_alu_shift_sel, + avm_alu_t_sub_s_bits, + avm_alu_two_pow_s, + avm_alu_two_pow_t_sub_s, avm_alu_u128_tag, avm_alu_u16_r0, avm_alu_u16_r1, @@ -306,10 +319,13 @@ class AvmFlavor { avm_main_sel_op_mul, avm_main_sel_op_not, avm_main_sel_op_or, + avm_main_sel_op_shl, + avm_main_sel_op_shr, avm_main_sel_op_sub, avm_main_sel_op_xor, avm_main_sel_rng_16, avm_main_sel_rng_8, + avm_main_table_pow_2, avm_main_tag_err, avm_main_w_in_tag, avm_mem_addr, @@ -350,6 +366,8 @@ class AvmFlavor { lookup_byte_operations, incl_main_tag_err, incl_mem_tag_err, + lookup_pow_2_0, + lookup_pow_2_1, lookup_u8_0, lookup_u8_1, lookup_u16_0, @@ -371,6 +389,8 @@ class AvmFlavor { lookup_byte_operations_counts, incl_main_tag_err_counts, incl_mem_tag_err_counts, + lookup_pow_2_0_counts, + lookup_pow_2_1_counts, lookup_u8_0_counts, lookup_u8_1_counts, lookup_u16_0_counts, @@ -416,6 +436,8 @@ class AvmFlavor { avm_alu_op_lte, avm_alu_op_mul, avm_alu_op_not, + avm_alu_op_shl, + avm_alu_op_shr, avm_alu_op_sub, avm_alu_p_a_borrow, avm_alu_p_b_borrow, @@ -427,6 +449,11 @@ class AvmFlavor { avm_alu_res_lo, avm_alu_rng_chk_lookup_selector, avm_alu_rng_chk_sel, + avm_alu_shift_lt_bit_len, + avm_alu_shift_sel, + avm_alu_t_sub_s_bits, + avm_alu_two_pow_s, + avm_alu_two_pow_t_sub_s, avm_alu_u128_tag, avm_alu_u16_r0, avm_alu_u16_r1, @@ -522,10 +549,13 @@ class AvmFlavor { avm_main_sel_op_mul, avm_main_sel_op_not, avm_main_sel_op_or, + avm_main_sel_op_shl, + avm_main_sel_op_shr, avm_main_sel_op_sub, avm_main_sel_op_xor, avm_main_sel_rng_16, avm_main_sel_rng_8, + avm_main_table_pow_2, avm_main_tag_err, avm_main_w_in_tag, avm_mem_addr, @@ -566,6 +596,8 @@ class AvmFlavor { lookup_byte_operations, incl_main_tag_err, incl_mem_tag_err, + lookup_pow_2_0, + lookup_pow_2_1, lookup_u8_0, lookup_u8_1, lookup_u16_0, @@ -587,6 +619,8 @@ class AvmFlavor { lookup_byte_operations_counts, incl_main_tag_err_counts, incl_mem_tag_err_counts, + lookup_pow_2_0_counts, + lookup_pow_2_1_counts, lookup_u8_0_counts, lookup_u8_1_counts, lookup_u16_0_counts, @@ -637,6 +671,8 @@ class AvmFlavor { avm_alu_op_lte, avm_alu_op_mul, avm_alu_op_not, + avm_alu_op_shl, + avm_alu_op_shr, avm_alu_op_sub, avm_alu_p_a_borrow, avm_alu_p_b_borrow, @@ -648,6 +684,11 @@ class AvmFlavor { avm_alu_res_lo, avm_alu_rng_chk_lookup_selector, avm_alu_rng_chk_sel, + avm_alu_shift_lt_bit_len, + avm_alu_shift_sel, + avm_alu_t_sub_s_bits, + avm_alu_two_pow_s, + avm_alu_two_pow_t_sub_s, avm_alu_u128_tag, avm_alu_u16_r0, avm_alu_u16_r1, @@ -743,10 +784,13 @@ class AvmFlavor { avm_main_sel_op_mul, avm_main_sel_op_not, avm_main_sel_op_or, + avm_main_sel_op_shl, + avm_main_sel_op_shr, avm_main_sel_op_sub, avm_main_sel_op_xor, avm_main_sel_rng_16, avm_main_sel_rng_8, + avm_main_table_pow_2, avm_main_tag_err, avm_main_w_in_tag, avm_mem_addr, @@ -787,6 +831,8 @@ class AvmFlavor { lookup_byte_operations, incl_main_tag_err, incl_mem_tag_err, + lookup_pow_2_0, + lookup_pow_2_1, lookup_u8_0, lookup_u8_1, lookup_u16_0, @@ -808,6 +854,8 @@ class AvmFlavor { lookup_byte_operations_counts, incl_main_tag_err_counts, incl_mem_tag_err_counts, + lookup_pow_2_0_counts, + lookup_pow_2_1_counts, lookup_u8_0_counts, lookup_u8_1_counts, lookup_u16_0_counts, @@ -836,6 +884,8 @@ class AvmFlavor { avm_alu_op_cast_prev_shift, avm_alu_op_cast_shift, avm_alu_op_mul_shift, + avm_alu_op_shl_shift, + avm_alu_op_shr_shift, avm_alu_op_sub_shift, avm_alu_p_sub_a_hi_shift, avm_alu_p_sub_a_lo_shift, @@ -893,6 +943,8 @@ class AvmFlavor { avm_alu_op_lte, avm_alu_op_mul, avm_alu_op_not, + avm_alu_op_shl, + avm_alu_op_shr, avm_alu_op_sub, avm_alu_p_a_borrow, avm_alu_p_b_borrow, @@ -904,6 +956,11 @@ class AvmFlavor { avm_alu_res_lo, avm_alu_rng_chk_lookup_selector, avm_alu_rng_chk_sel, + avm_alu_shift_lt_bit_len, + avm_alu_shift_sel, + avm_alu_t_sub_s_bits, + avm_alu_two_pow_s, + avm_alu_two_pow_t_sub_s, avm_alu_u128_tag, avm_alu_u16_r0, avm_alu_u16_r1, @@ -999,10 +1056,13 @@ class AvmFlavor { avm_main_sel_op_mul, avm_main_sel_op_not, avm_main_sel_op_or, + avm_main_sel_op_shl, + avm_main_sel_op_shr, avm_main_sel_op_sub, avm_main_sel_op_xor, avm_main_sel_rng_16, avm_main_sel_rng_8, + avm_main_table_pow_2, avm_main_tag_err, avm_main_w_in_tag, avm_mem_addr, @@ -1043,6 +1103,8 @@ class AvmFlavor { lookup_byte_operations, incl_main_tag_err, incl_mem_tag_err, + lookup_pow_2_0, + lookup_pow_2_1, lookup_u8_0, lookup_u8_1, lookup_u16_0, @@ -1064,6 +1126,8 @@ class AvmFlavor { lookup_byte_operations_counts, incl_main_tag_err_counts, incl_mem_tag_err_counts, + lookup_pow_2_0_counts, + lookup_pow_2_1_counts, lookup_u8_0_counts, lookup_u8_1_counts, lookup_u16_0_counts, @@ -1092,6 +1156,8 @@ class AvmFlavor { avm_alu_op_cast_prev_shift, avm_alu_op_cast_shift, avm_alu_op_mul_shift, + avm_alu_op_shl_shift, + avm_alu_op_shr_shift, avm_alu_op_sub_shift, avm_alu_p_sub_a_hi_shift, avm_alu_p_sub_a_lo_shift, @@ -1149,6 +1215,8 @@ class AvmFlavor { avm_alu_op_lte, avm_alu_op_mul, avm_alu_op_not, + avm_alu_op_shl, + avm_alu_op_shr, avm_alu_op_sub, avm_alu_p_a_borrow, avm_alu_p_b_borrow, @@ -1160,6 +1228,11 @@ class AvmFlavor { avm_alu_res_lo, avm_alu_rng_chk_lookup_selector, avm_alu_rng_chk_sel, + avm_alu_shift_lt_bit_len, + avm_alu_shift_sel, + avm_alu_t_sub_s_bits, + avm_alu_two_pow_s, + avm_alu_two_pow_t_sub_s, avm_alu_u128_tag, avm_alu_u16_r0, avm_alu_u16_r1, @@ -1255,10 +1328,13 @@ class AvmFlavor { avm_main_sel_op_mul, avm_main_sel_op_not, avm_main_sel_op_or, + avm_main_sel_op_shl, + avm_main_sel_op_shr, avm_main_sel_op_sub, avm_main_sel_op_xor, avm_main_sel_rng_16, avm_main_sel_rng_8, + avm_main_table_pow_2, avm_main_tag_err, avm_main_w_in_tag, avm_mem_addr, @@ -1299,6 +1375,8 @@ class AvmFlavor { lookup_byte_operations, incl_main_tag_err, incl_mem_tag_err, + lookup_pow_2_0, + lookup_pow_2_1, lookup_u8_0, lookup_u8_1, lookup_u16_0, @@ -1320,6 +1398,8 @@ class AvmFlavor { lookup_byte_operations_counts, incl_main_tag_err_counts, incl_mem_tag_err_counts, + lookup_pow_2_0_counts, + lookup_pow_2_1_counts, lookup_u8_0_counts, lookup_u8_1_counts, lookup_u16_0_counts, @@ -1351,6 +1431,8 @@ class AvmFlavor { avm_alu_op_cast_prev, avm_alu_op_cast, avm_alu_op_mul, + avm_alu_op_shl, + avm_alu_op_shr, avm_alu_op_sub, avm_alu_p_sub_a_hi, avm_alu_p_sub_a_lo, @@ -1392,6 +1474,8 @@ class AvmFlavor { avm_alu_op_cast_prev_shift, avm_alu_op_cast_shift, avm_alu_op_mul_shift, + avm_alu_op_shl_shift, + avm_alu_op_shr_shift, avm_alu_op_sub_shift, avm_alu_p_sub_a_hi_shift, avm_alu_p_sub_a_lo_shift, @@ -1442,6 +1526,8 @@ class AvmFlavor { avm_alu_op_cast_prev, avm_alu_op_cast, avm_alu_op_mul, + avm_alu_op_shl, + avm_alu_op_shr, avm_alu_op_sub, avm_alu_p_sub_a_hi, avm_alu_p_sub_a_lo, @@ -1503,6 +1589,10 @@ class AvmFlavor { prover_polynomials, relation_parameters, this->circuit_size); bb::compute_logderivative_inverse>( prover_polynomials, relation_parameters, this->circuit_size); + bb::compute_logderivative_inverse>( + prover_polynomials, relation_parameters, this->circuit_size); + bb::compute_logderivative_inverse>( + prover_polynomials, relation_parameters, this->circuit_size); bb::compute_logderivative_inverse>( prover_polynomials, relation_parameters, this->circuit_size); bb::compute_logderivative_inverse>( @@ -1656,6 +1746,8 @@ class AvmFlavor { Base::avm_alu_op_lte = "AVM_ALU_OP_LTE"; Base::avm_alu_op_mul = "AVM_ALU_OP_MUL"; Base::avm_alu_op_not = "AVM_ALU_OP_NOT"; + Base::avm_alu_op_shl = "AVM_ALU_OP_SHL"; + Base::avm_alu_op_shr = "AVM_ALU_OP_SHR"; Base::avm_alu_op_sub = "AVM_ALU_OP_SUB"; Base::avm_alu_p_a_borrow = "AVM_ALU_P_A_BORROW"; Base::avm_alu_p_b_borrow = "AVM_ALU_P_B_BORROW"; @@ -1667,6 +1759,11 @@ class AvmFlavor { Base::avm_alu_res_lo = "AVM_ALU_RES_LO"; Base::avm_alu_rng_chk_lookup_selector = "AVM_ALU_RNG_CHK_LOOKUP_SELECTOR"; Base::avm_alu_rng_chk_sel = "AVM_ALU_RNG_CHK_SEL"; + Base::avm_alu_shift_lt_bit_len = "AVM_ALU_SHIFT_LT_BIT_LEN"; + Base::avm_alu_shift_sel = "AVM_ALU_SHIFT_SEL"; + Base::avm_alu_t_sub_s_bits = "AVM_ALU_T_SUB_S_BITS"; + Base::avm_alu_two_pow_s = "AVM_ALU_TWO_POW_S"; + Base::avm_alu_two_pow_t_sub_s = "AVM_ALU_TWO_POW_T_SUB_S"; Base::avm_alu_u128_tag = "AVM_ALU_U128_TAG"; Base::avm_alu_u16_r0 = "AVM_ALU_U16_R0"; Base::avm_alu_u16_r1 = "AVM_ALU_U16_R1"; @@ -1762,10 +1859,13 @@ class AvmFlavor { Base::avm_main_sel_op_mul = "AVM_MAIN_SEL_OP_MUL"; Base::avm_main_sel_op_not = "AVM_MAIN_SEL_OP_NOT"; Base::avm_main_sel_op_or = "AVM_MAIN_SEL_OP_OR"; + Base::avm_main_sel_op_shl = "AVM_MAIN_SEL_OP_SHL"; + Base::avm_main_sel_op_shr = "AVM_MAIN_SEL_OP_SHR"; Base::avm_main_sel_op_sub = "AVM_MAIN_SEL_OP_SUB"; Base::avm_main_sel_op_xor = "AVM_MAIN_SEL_OP_XOR"; Base::avm_main_sel_rng_16 = "AVM_MAIN_SEL_RNG_16"; Base::avm_main_sel_rng_8 = "AVM_MAIN_SEL_RNG_8"; + Base::avm_main_table_pow_2 = "AVM_MAIN_TABLE_POW_2"; Base::avm_main_tag_err = "AVM_MAIN_TAG_ERR"; Base::avm_main_w_in_tag = "AVM_MAIN_W_IN_TAG"; Base::avm_mem_addr = "AVM_MEM_ADDR"; @@ -1806,6 +1906,8 @@ class AvmFlavor { Base::lookup_byte_operations = "LOOKUP_BYTE_OPERATIONS"; Base::incl_main_tag_err = "INCL_MAIN_TAG_ERR"; Base::incl_mem_tag_err = "INCL_MEM_TAG_ERR"; + Base::lookup_pow_2_0 = "LOOKUP_POW_2_0"; + Base::lookup_pow_2_1 = "LOOKUP_POW_2_1"; Base::lookup_u8_0 = "LOOKUP_U8_0"; Base::lookup_u8_1 = "LOOKUP_U8_1"; Base::lookup_u16_0 = "LOOKUP_U16_0"; @@ -1827,6 +1929,8 @@ class AvmFlavor { Base::lookup_byte_operations_counts = "LOOKUP_BYTE_OPERATIONS_COUNTS"; Base::incl_main_tag_err_counts = "INCL_MAIN_TAG_ERR_COUNTS"; Base::incl_mem_tag_err_counts = "INCL_MEM_TAG_ERR_COUNTS"; + Base::lookup_pow_2_0_counts = "LOOKUP_POW_2_0_COUNTS"; + Base::lookup_pow_2_1_counts = "LOOKUP_POW_2_1_COUNTS"; Base::lookup_u8_0_counts = "LOOKUP_U8_0_COUNTS"; Base::lookup_u8_1_counts = "LOOKUP_U8_1_COUNTS"; Base::lookup_u16_0_counts = "LOOKUP_U16_0_COUNTS"; @@ -1888,6 +1992,8 @@ class AvmFlavor { Commitment avm_alu_op_lte; Commitment avm_alu_op_mul; Commitment avm_alu_op_not; + Commitment avm_alu_op_shl; + Commitment avm_alu_op_shr; Commitment avm_alu_op_sub; Commitment avm_alu_p_a_borrow; Commitment avm_alu_p_b_borrow; @@ -1899,6 +2005,11 @@ class AvmFlavor { Commitment avm_alu_res_lo; Commitment avm_alu_rng_chk_lookup_selector; Commitment avm_alu_rng_chk_sel; + Commitment avm_alu_shift_lt_bit_len; + Commitment avm_alu_shift_sel; + Commitment avm_alu_t_sub_s_bits; + Commitment avm_alu_two_pow_s; + Commitment avm_alu_two_pow_t_sub_s; Commitment avm_alu_u128_tag; Commitment avm_alu_u16_r0; Commitment avm_alu_u16_r1; @@ -1994,10 +2105,13 @@ class AvmFlavor { Commitment avm_main_sel_op_mul; Commitment avm_main_sel_op_not; Commitment avm_main_sel_op_or; + Commitment avm_main_sel_op_shl; + Commitment avm_main_sel_op_shr; Commitment avm_main_sel_op_sub; Commitment avm_main_sel_op_xor; Commitment avm_main_sel_rng_16; Commitment avm_main_sel_rng_8; + Commitment avm_main_table_pow_2; Commitment avm_main_tag_err; Commitment avm_main_w_in_tag; Commitment avm_mem_addr; @@ -2038,6 +2152,8 @@ class AvmFlavor { Commitment lookup_byte_operations; Commitment incl_main_tag_err; Commitment incl_mem_tag_err; + Commitment lookup_pow_2_0; + Commitment lookup_pow_2_1; Commitment lookup_u8_0; Commitment lookup_u8_1; Commitment lookup_u16_0; @@ -2059,6 +2175,8 @@ class AvmFlavor { Commitment lookup_byte_operations_counts; Commitment incl_main_tag_err_counts; Commitment incl_mem_tag_err_counts; + Commitment lookup_pow_2_0_counts; + Commitment lookup_pow_2_1_counts; Commitment lookup_u8_0_counts; Commitment lookup_u8_1_counts; Commitment lookup_u16_0_counts; @@ -2120,6 +2238,8 @@ class AvmFlavor { avm_alu_op_lte = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_alu_op_mul = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_alu_op_not = deserialize_from_buffer(Transcript::proof_data, num_frs_read); + avm_alu_op_shl = deserialize_from_buffer(Transcript::proof_data, num_frs_read); + avm_alu_op_shr = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_alu_op_sub = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_alu_p_a_borrow = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_alu_p_b_borrow = deserialize_from_buffer(Transcript::proof_data, num_frs_read); @@ -2131,6 +2251,11 @@ class AvmFlavor { avm_alu_res_lo = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_alu_rng_chk_lookup_selector = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_alu_rng_chk_sel = deserialize_from_buffer(Transcript::proof_data, num_frs_read); + avm_alu_shift_lt_bit_len = deserialize_from_buffer(Transcript::proof_data, num_frs_read); + avm_alu_shift_sel = deserialize_from_buffer(Transcript::proof_data, num_frs_read); + avm_alu_t_sub_s_bits = deserialize_from_buffer(Transcript::proof_data, num_frs_read); + avm_alu_two_pow_s = deserialize_from_buffer(Transcript::proof_data, num_frs_read); + avm_alu_two_pow_t_sub_s = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_alu_u128_tag = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_alu_u16_r0 = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_alu_u16_r1 = deserialize_from_buffer(Transcript::proof_data, num_frs_read); @@ -2227,10 +2352,13 @@ class AvmFlavor { avm_main_sel_op_mul = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_main_sel_op_not = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_main_sel_op_or = deserialize_from_buffer(Transcript::proof_data, num_frs_read); + avm_main_sel_op_shl = deserialize_from_buffer(Transcript::proof_data, num_frs_read); + avm_main_sel_op_shr = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_main_sel_op_sub = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_main_sel_op_xor = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_main_sel_rng_16 = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_main_sel_rng_8 = deserialize_from_buffer(Transcript::proof_data, num_frs_read); + avm_main_table_pow_2 = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_main_tag_err = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_main_w_in_tag = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_mem_addr = deserialize_from_buffer(Transcript::proof_data, num_frs_read); @@ -2271,6 +2399,8 @@ class AvmFlavor { lookup_byte_operations = deserialize_from_buffer(Transcript::proof_data, num_frs_read); incl_main_tag_err = deserialize_from_buffer(Transcript::proof_data, num_frs_read); incl_mem_tag_err = deserialize_from_buffer(Transcript::proof_data, num_frs_read); + lookup_pow_2_0 = deserialize_from_buffer(Transcript::proof_data, num_frs_read); + lookup_pow_2_1 = deserialize_from_buffer(Transcript::proof_data, num_frs_read); lookup_u8_0 = deserialize_from_buffer(Transcript::proof_data, num_frs_read); lookup_u8_1 = deserialize_from_buffer(Transcript::proof_data, num_frs_read); lookup_u16_0 = deserialize_from_buffer(Transcript::proof_data, num_frs_read); @@ -2292,6 +2422,8 @@ class AvmFlavor { lookup_byte_operations_counts = deserialize_from_buffer(Transcript::proof_data, num_frs_read); incl_main_tag_err_counts = deserialize_from_buffer(Transcript::proof_data, num_frs_read); incl_mem_tag_err_counts = deserialize_from_buffer(Transcript::proof_data, num_frs_read); + lookup_pow_2_0_counts = deserialize_from_buffer(Transcript::proof_data, num_frs_read); + lookup_pow_2_1_counts = deserialize_from_buffer(Transcript::proof_data, num_frs_read); lookup_u8_0_counts = deserialize_from_buffer(Transcript::proof_data, num_frs_read); lookup_u8_1_counts = deserialize_from_buffer(Transcript::proof_data, num_frs_read); lookup_u16_0_counts = deserialize_from_buffer(Transcript::proof_data, num_frs_read); @@ -2357,6 +2489,8 @@ class AvmFlavor { serialize_to_buffer(avm_alu_op_lte, Transcript::proof_data); serialize_to_buffer(avm_alu_op_mul, Transcript::proof_data); serialize_to_buffer(avm_alu_op_not, Transcript::proof_data); + serialize_to_buffer(avm_alu_op_shl, Transcript::proof_data); + serialize_to_buffer(avm_alu_op_shr, Transcript::proof_data); serialize_to_buffer(avm_alu_op_sub, Transcript::proof_data); serialize_to_buffer(avm_alu_p_a_borrow, Transcript::proof_data); serialize_to_buffer(avm_alu_p_b_borrow, Transcript::proof_data); @@ -2368,6 +2502,11 @@ class AvmFlavor { serialize_to_buffer(avm_alu_res_lo, Transcript::proof_data); serialize_to_buffer(avm_alu_rng_chk_lookup_selector, Transcript::proof_data); serialize_to_buffer(avm_alu_rng_chk_sel, Transcript::proof_data); + serialize_to_buffer(avm_alu_shift_lt_bit_len, Transcript::proof_data); + serialize_to_buffer(avm_alu_shift_sel, Transcript::proof_data); + serialize_to_buffer(avm_alu_t_sub_s_bits, Transcript::proof_data); + serialize_to_buffer(avm_alu_two_pow_s, Transcript::proof_data); + serialize_to_buffer(avm_alu_two_pow_t_sub_s, Transcript::proof_data); serialize_to_buffer(avm_alu_u128_tag, Transcript::proof_data); serialize_to_buffer(avm_alu_u16_r0, Transcript::proof_data); serialize_to_buffer(avm_alu_u16_r1, Transcript::proof_data); @@ -2463,10 +2602,13 @@ class AvmFlavor { serialize_to_buffer(avm_main_sel_op_mul, Transcript::proof_data); serialize_to_buffer(avm_main_sel_op_not, Transcript::proof_data); serialize_to_buffer(avm_main_sel_op_or, Transcript::proof_data); + serialize_to_buffer(avm_main_sel_op_shl, Transcript::proof_data); + serialize_to_buffer(avm_main_sel_op_shr, Transcript::proof_data); serialize_to_buffer(avm_main_sel_op_sub, Transcript::proof_data); serialize_to_buffer(avm_main_sel_op_xor, Transcript::proof_data); serialize_to_buffer(avm_main_sel_rng_16, Transcript::proof_data); serialize_to_buffer(avm_main_sel_rng_8, Transcript::proof_data); + serialize_to_buffer(avm_main_table_pow_2, Transcript::proof_data); serialize_to_buffer(avm_main_tag_err, Transcript::proof_data); serialize_to_buffer(avm_main_w_in_tag, Transcript::proof_data); serialize_to_buffer(avm_mem_addr, Transcript::proof_data); @@ -2507,6 +2649,8 @@ class AvmFlavor { serialize_to_buffer(lookup_byte_operations, Transcript::proof_data); serialize_to_buffer(incl_main_tag_err, Transcript::proof_data); serialize_to_buffer(incl_mem_tag_err, Transcript::proof_data); + serialize_to_buffer(lookup_pow_2_0, Transcript::proof_data); + serialize_to_buffer(lookup_pow_2_1, Transcript::proof_data); serialize_to_buffer(lookup_u8_0, Transcript::proof_data); serialize_to_buffer(lookup_u8_1, Transcript::proof_data); serialize_to_buffer(lookup_u16_0, Transcript::proof_data); @@ -2528,6 +2672,8 @@ class AvmFlavor { serialize_to_buffer(lookup_byte_operations_counts, Transcript::proof_data); serialize_to_buffer(incl_main_tag_err_counts, Transcript::proof_data); serialize_to_buffer(incl_mem_tag_err_counts, Transcript::proof_data); + serialize_to_buffer(lookup_pow_2_0_counts, Transcript::proof_data); + serialize_to_buffer(lookup_pow_2_1_counts, Transcript::proof_data); serialize_to_buffer(lookup_u8_0_counts, Transcript::proof_data); serialize_to_buffer(lookup_u8_1_counts, Transcript::proof_data); serialize_to_buffer(lookup_u16_0_counts, Transcript::proof_data); diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp index d5b48dee516..9343f80ba62 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp @@ -84,6 +84,8 @@ void AvmProver::execute_wire_commitments_round() witness_commitments.avm_alu_op_lte = commitment_key->commit(key->avm_alu_op_lte); witness_commitments.avm_alu_op_mul = commitment_key->commit(key->avm_alu_op_mul); witness_commitments.avm_alu_op_not = commitment_key->commit(key->avm_alu_op_not); + witness_commitments.avm_alu_op_shl = commitment_key->commit(key->avm_alu_op_shl); + witness_commitments.avm_alu_op_shr = commitment_key->commit(key->avm_alu_op_shr); witness_commitments.avm_alu_op_sub = commitment_key->commit(key->avm_alu_op_sub); witness_commitments.avm_alu_p_a_borrow = commitment_key->commit(key->avm_alu_p_a_borrow); witness_commitments.avm_alu_p_b_borrow = commitment_key->commit(key->avm_alu_p_b_borrow); @@ -95,6 +97,11 @@ void AvmProver::execute_wire_commitments_round() witness_commitments.avm_alu_res_lo = commitment_key->commit(key->avm_alu_res_lo); witness_commitments.avm_alu_rng_chk_lookup_selector = commitment_key->commit(key->avm_alu_rng_chk_lookup_selector); witness_commitments.avm_alu_rng_chk_sel = commitment_key->commit(key->avm_alu_rng_chk_sel); + witness_commitments.avm_alu_shift_lt_bit_len = commitment_key->commit(key->avm_alu_shift_lt_bit_len); + witness_commitments.avm_alu_shift_sel = commitment_key->commit(key->avm_alu_shift_sel); + witness_commitments.avm_alu_t_sub_s_bits = commitment_key->commit(key->avm_alu_t_sub_s_bits); + witness_commitments.avm_alu_two_pow_s = commitment_key->commit(key->avm_alu_two_pow_s); + witness_commitments.avm_alu_two_pow_t_sub_s = commitment_key->commit(key->avm_alu_two_pow_t_sub_s); witness_commitments.avm_alu_u128_tag = commitment_key->commit(key->avm_alu_u128_tag); witness_commitments.avm_alu_u16_r0 = commitment_key->commit(key->avm_alu_u16_r0); witness_commitments.avm_alu_u16_r1 = commitment_key->commit(key->avm_alu_u16_r1); @@ -191,10 +198,13 @@ void AvmProver::execute_wire_commitments_round() witness_commitments.avm_main_sel_op_mul = commitment_key->commit(key->avm_main_sel_op_mul); witness_commitments.avm_main_sel_op_not = commitment_key->commit(key->avm_main_sel_op_not); witness_commitments.avm_main_sel_op_or = commitment_key->commit(key->avm_main_sel_op_or); + witness_commitments.avm_main_sel_op_shl = commitment_key->commit(key->avm_main_sel_op_shl); + witness_commitments.avm_main_sel_op_shr = commitment_key->commit(key->avm_main_sel_op_shr); witness_commitments.avm_main_sel_op_sub = commitment_key->commit(key->avm_main_sel_op_sub); witness_commitments.avm_main_sel_op_xor = commitment_key->commit(key->avm_main_sel_op_xor); witness_commitments.avm_main_sel_rng_16 = commitment_key->commit(key->avm_main_sel_rng_16); witness_commitments.avm_main_sel_rng_8 = commitment_key->commit(key->avm_main_sel_rng_8); + witness_commitments.avm_main_table_pow_2 = commitment_key->commit(key->avm_main_table_pow_2); witness_commitments.avm_main_tag_err = commitment_key->commit(key->avm_main_tag_err); witness_commitments.avm_main_w_in_tag = commitment_key->commit(key->avm_main_w_in_tag); witness_commitments.avm_mem_addr = commitment_key->commit(key->avm_mem_addr); @@ -225,6 +235,8 @@ void AvmProver::execute_wire_commitments_round() witness_commitments.lookup_byte_operations_counts = commitment_key->commit(key->lookup_byte_operations_counts); witness_commitments.incl_main_tag_err_counts = commitment_key->commit(key->incl_main_tag_err_counts); witness_commitments.incl_mem_tag_err_counts = commitment_key->commit(key->incl_mem_tag_err_counts); + witness_commitments.lookup_pow_2_0_counts = commitment_key->commit(key->lookup_pow_2_0_counts); + witness_commitments.lookup_pow_2_1_counts = commitment_key->commit(key->lookup_pow_2_1_counts); witness_commitments.lookup_u8_0_counts = commitment_key->commit(key->lookup_u8_0_counts); witness_commitments.lookup_u8_1_counts = commitment_key->commit(key->lookup_u8_1_counts); witness_commitments.lookup_u16_0_counts = commitment_key->commit(key->lookup_u16_0_counts); @@ -269,6 +281,8 @@ void AvmProver::execute_wire_commitments_round() transcript->send_to_verifier(commitment_labels.avm_alu_op_lte, witness_commitments.avm_alu_op_lte); transcript->send_to_verifier(commitment_labels.avm_alu_op_mul, witness_commitments.avm_alu_op_mul); transcript->send_to_verifier(commitment_labels.avm_alu_op_not, witness_commitments.avm_alu_op_not); + transcript->send_to_verifier(commitment_labels.avm_alu_op_shl, witness_commitments.avm_alu_op_shl); + transcript->send_to_verifier(commitment_labels.avm_alu_op_shr, witness_commitments.avm_alu_op_shr); transcript->send_to_verifier(commitment_labels.avm_alu_op_sub, witness_commitments.avm_alu_op_sub); transcript->send_to_verifier(commitment_labels.avm_alu_p_a_borrow, witness_commitments.avm_alu_p_a_borrow); transcript->send_to_verifier(commitment_labels.avm_alu_p_b_borrow, witness_commitments.avm_alu_p_b_borrow); @@ -281,6 +295,13 @@ void AvmProver::execute_wire_commitments_round() transcript->send_to_verifier(commitment_labels.avm_alu_rng_chk_lookup_selector, witness_commitments.avm_alu_rng_chk_lookup_selector); transcript->send_to_verifier(commitment_labels.avm_alu_rng_chk_sel, witness_commitments.avm_alu_rng_chk_sel); + transcript->send_to_verifier(commitment_labels.avm_alu_shift_lt_bit_len, + witness_commitments.avm_alu_shift_lt_bit_len); + transcript->send_to_verifier(commitment_labels.avm_alu_shift_sel, witness_commitments.avm_alu_shift_sel); + transcript->send_to_verifier(commitment_labels.avm_alu_t_sub_s_bits, witness_commitments.avm_alu_t_sub_s_bits); + transcript->send_to_verifier(commitment_labels.avm_alu_two_pow_s, witness_commitments.avm_alu_two_pow_s); + transcript->send_to_verifier(commitment_labels.avm_alu_two_pow_t_sub_s, + witness_commitments.avm_alu_two_pow_t_sub_s); transcript->send_to_verifier(commitment_labels.avm_alu_u128_tag, witness_commitments.avm_alu_u128_tag); transcript->send_to_verifier(commitment_labels.avm_alu_u16_r0, witness_commitments.avm_alu_u16_r0); transcript->send_to_verifier(commitment_labels.avm_alu_u16_r1, witness_commitments.avm_alu_u16_r1); @@ -387,10 +408,13 @@ void AvmProver::execute_wire_commitments_round() transcript->send_to_verifier(commitment_labels.avm_main_sel_op_mul, witness_commitments.avm_main_sel_op_mul); transcript->send_to_verifier(commitment_labels.avm_main_sel_op_not, witness_commitments.avm_main_sel_op_not); transcript->send_to_verifier(commitment_labels.avm_main_sel_op_or, witness_commitments.avm_main_sel_op_or); + transcript->send_to_verifier(commitment_labels.avm_main_sel_op_shl, witness_commitments.avm_main_sel_op_shl); + transcript->send_to_verifier(commitment_labels.avm_main_sel_op_shr, witness_commitments.avm_main_sel_op_shr); transcript->send_to_verifier(commitment_labels.avm_main_sel_op_sub, witness_commitments.avm_main_sel_op_sub); transcript->send_to_verifier(commitment_labels.avm_main_sel_op_xor, witness_commitments.avm_main_sel_op_xor); transcript->send_to_verifier(commitment_labels.avm_main_sel_rng_16, witness_commitments.avm_main_sel_rng_16); transcript->send_to_verifier(commitment_labels.avm_main_sel_rng_8, witness_commitments.avm_main_sel_rng_8); + transcript->send_to_verifier(commitment_labels.avm_main_table_pow_2, witness_commitments.avm_main_table_pow_2); transcript->send_to_verifier(commitment_labels.avm_main_tag_err, witness_commitments.avm_main_tag_err); transcript->send_to_verifier(commitment_labels.avm_main_w_in_tag, witness_commitments.avm_main_w_in_tag); transcript->send_to_verifier(commitment_labels.avm_mem_addr, witness_commitments.avm_mem_addr); @@ -425,6 +449,8 @@ void AvmProver::execute_wire_commitments_round() witness_commitments.incl_main_tag_err_counts); transcript->send_to_verifier(commitment_labels.incl_mem_tag_err_counts, witness_commitments.incl_mem_tag_err_counts); + transcript->send_to_verifier(commitment_labels.lookup_pow_2_0_counts, witness_commitments.lookup_pow_2_0_counts); + transcript->send_to_verifier(commitment_labels.lookup_pow_2_1_counts, witness_commitments.lookup_pow_2_1_counts); transcript->send_to_verifier(commitment_labels.lookup_u8_0_counts, witness_commitments.lookup_u8_0_counts); transcript->send_to_verifier(commitment_labels.lookup_u8_1_counts, witness_commitments.lookup_u8_1_counts); transcript->send_to_verifier(commitment_labels.lookup_u16_0_counts, witness_commitments.lookup_u16_0_counts); @@ -468,6 +494,8 @@ void AvmProver::execute_log_derivative_inverse_round() witness_commitments.lookup_byte_operations = commitment_key->commit(key->lookup_byte_operations); witness_commitments.incl_main_tag_err = commitment_key->commit(key->incl_main_tag_err); witness_commitments.incl_mem_tag_err = commitment_key->commit(key->incl_mem_tag_err); + witness_commitments.lookup_pow_2_0 = commitment_key->commit(key->lookup_pow_2_0); + witness_commitments.lookup_pow_2_1 = commitment_key->commit(key->lookup_pow_2_1); witness_commitments.lookup_u8_0 = commitment_key->commit(key->lookup_u8_0); witness_commitments.lookup_u8_1 = commitment_key->commit(key->lookup_u8_1); witness_commitments.lookup_u16_0 = commitment_key->commit(key->lookup_u16_0); @@ -501,6 +529,8 @@ void AvmProver::execute_log_derivative_inverse_round() transcript->send_to_verifier(commitment_labels.lookup_byte_operations, witness_commitments.lookup_byte_operations); transcript->send_to_verifier(commitment_labels.incl_main_tag_err, witness_commitments.incl_main_tag_err); transcript->send_to_verifier(commitment_labels.incl_mem_tag_err, witness_commitments.incl_mem_tag_err); + transcript->send_to_verifier(commitment_labels.lookup_pow_2_0, witness_commitments.lookup_pow_2_0); + transcript->send_to_verifier(commitment_labels.lookup_pow_2_1, witness_commitments.lookup_pow_2_1); transcript->send_to_verifier(commitment_labels.lookup_u8_0, witness_commitments.lookup_u8_0); transcript->send_to_verifier(commitment_labels.lookup_u8_1, witness_commitments.lookup_u8_1); transcript->send_to_verifier(commitment_labels.lookup_u16_0, witness_commitments.lookup_u16_0); diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp index a7b418bab60..5edd090d1e6 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp @@ -82,6 +82,8 @@ bool AvmVerifier::verify_proof(const HonkProof& proof) commitments.avm_alu_op_lte = transcript->template receive_from_prover(commitment_labels.avm_alu_op_lte); commitments.avm_alu_op_mul = transcript->template receive_from_prover(commitment_labels.avm_alu_op_mul); commitments.avm_alu_op_not = transcript->template receive_from_prover(commitment_labels.avm_alu_op_not); + commitments.avm_alu_op_shl = transcript->template receive_from_prover(commitment_labels.avm_alu_op_shl); + commitments.avm_alu_op_shr = transcript->template receive_from_prover(commitment_labels.avm_alu_op_shr); commitments.avm_alu_op_sub = transcript->template receive_from_prover(commitment_labels.avm_alu_op_sub); commitments.avm_alu_p_a_borrow = transcript->template receive_from_prover(commitment_labels.avm_alu_p_a_borrow); @@ -101,6 +103,16 @@ bool AvmVerifier::verify_proof(const HonkProof& proof) transcript->template receive_from_prover(commitment_labels.avm_alu_rng_chk_lookup_selector); commitments.avm_alu_rng_chk_sel = transcript->template receive_from_prover(commitment_labels.avm_alu_rng_chk_sel); + commitments.avm_alu_shift_lt_bit_len = + transcript->template receive_from_prover(commitment_labels.avm_alu_shift_lt_bit_len); + commitments.avm_alu_shift_sel = + transcript->template receive_from_prover(commitment_labels.avm_alu_shift_sel); + commitments.avm_alu_t_sub_s_bits = + transcript->template receive_from_prover(commitment_labels.avm_alu_t_sub_s_bits); + commitments.avm_alu_two_pow_s = + transcript->template receive_from_prover(commitment_labels.avm_alu_two_pow_s); + commitments.avm_alu_two_pow_t_sub_s = + transcript->template receive_from_prover(commitment_labels.avm_alu_two_pow_t_sub_s); commitments.avm_alu_u128_tag = transcript->template receive_from_prover(commitment_labels.avm_alu_u128_tag); commitments.avm_alu_u16_r0 = transcript->template receive_from_prover(commitment_labels.avm_alu_u16_r0); @@ -262,6 +274,10 @@ bool AvmVerifier::verify_proof(const HonkProof& proof) transcript->template receive_from_prover(commitment_labels.avm_main_sel_op_not); commitments.avm_main_sel_op_or = transcript->template receive_from_prover(commitment_labels.avm_main_sel_op_or); + commitments.avm_main_sel_op_shl = + transcript->template receive_from_prover(commitment_labels.avm_main_sel_op_shl); + commitments.avm_main_sel_op_shr = + transcript->template receive_from_prover(commitment_labels.avm_main_sel_op_shr); commitments.avm_main_sel_op_sub = transcript->template receive_from_prover(commitment_labels.avm_main_sel_op_sub); commitments.avm_main_sel_op_xor = @@ -270,6 +286,8 @@ bool AvmVerifier::verify_proof(const HonkProof& proof) transcript->template receive_from_prover(commitment_labels.avm_main_sel_rng_16); commitments.avm_main_sel_rng_8 = transcript->template receive_from_prover(commitment_labels.avm_main_sel_rng_8); + commitments.avm_main_table_pow_2 = + transcript->template receive_from_prover(commitment_labels.avm_main_table_pow_2); commitments.avm_main_tag_err = transcript->template receive_from_prover(commitment_labels.avm_main_tag_err); commitments.avm_main_w_in_tag = @@ -320,6 +338,10 @@ bool AvmVerifier::verify_proof(const HonkProof& proof) transcript->template receive_from_prover(commitment_labels.incl_main_tag_err_counts); commitments.incl_mem_tag_err_counts = transcript->template receive_from_prover(commitment_labels.incl_mem_tag_err_counts); + commitments.lookup_pow_2_0_counts = + transcript->template receive_from_prover(commitment_labels.lookup_pow_2_0_counts); + commitments.lookup_pow_2_1_counts = + transcript->template receive_from_prover(commitment_labels.lookup_pow_2_1_counts); commitments.lookup_u8_0_counts = transcript->template receive_from_prover(commitment_labels.lookup_u8_0_counts); commitments.lookup_u8_1_counts = @@ -386,6 +408,8 @@ bool AvmVerifier::verify_proof(const HonkProof& proof) transcript->template receive_from_prover(commitment_labels.incl_main_tag_err); commitments.incl_mem_tag_err = transcript->template receive_from_prover(commitment_labels.incl_mem_tag_err); + commitments.lookup_pow_2_0 = transcript->template receive_from_prover(commitment_labels.lookup_pow_2_0); + commitments.lookup_pow_2_1 = transcript->template receive_from_prover(commitment_labels.lookup_pow_2_1); commitments.lookup_u8_0 = transcript->template receive_from_prover(commitment_labels.lookup_u8_0); commitments.lookup_u8_1 = transcript->template receive_from_prover(commitment_labels.lookup_u8_1); commitments.lookup_u16_0 = transcript->template receive_from_prover(commitment_labels.lookup_u16_0); diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_bitwise.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_bitwise.test.cpp index ce4e07e8f2c..16789ac3dc6 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_bitwise.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_bitwise.test.cpp @@ -1,5 +1,6 @@ #include "avm_common.test.hpp" #include "barretenberg/numeric/uint128/uint128.hpp" +#include "barretenberg/vm/avm_trace/avm_common.hpp" #include "barretenberg/vm/tests/helpers.test.hpp" #include "gtest/gtest.h" #include @@ -85,6 +86,52 @@ void common_validate_op_not(std::vector const& trace, } } +void common_validate_shift_op(std::vector const& trace, + FF const& a, + FF const& b, + FF const& c, + FF const& addr_a, + FF const& addr_b, + FF const& addr_c, + avm_trace::AvmMemoryTag const tag, + bool shr) +{ + auto row = + shr ? std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_shr == FF(1); }) + : std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_shl == FF(1); }); + ASSERT_TRUE(row != trace.end()); + FF clk = row->avm_main_clk; + auto alu_row = std::ranges::find_if(trace.begin(), trace.end(), [clk](Row r) { return r.avm_alu_clk == clk; }); + ASSERT_TRUE(alu_row != trace.end()); + + // Check that the correct result is stored at the expected memory location. + EXPECT_EQ(row->avm_main_ic, c); + EXPECT_EQ(row->avm_main_mem_idx_c, addr_c); + EXPECT_EQ(row->avm_main_mem_op_c, FF(1)); + EXPECT_EQ(row->avm_main_rwc, FF(1)); + + // Check that ia register is correctly set with memory load operations. + EXPECT_EQ(row->avm_main_ia, a); + EXPECT_EQ(row->avm_main_mem_idx_a, addr_a); + EXPECT_EQ(row->avm_main_mem_op_a, FF(1)); + EXPECT_EQ(row->avm_main_rwa, FF(0)); + + // Check that ia register is correctly set with memory load operations. + EXPECT_EQ(row->avm_main_ib, b); + EXPECT_EQ(row->avm_main_mem_idx_b, addr_b); + EXPECT_EQ(row->avm_main_mem_op_b, FF(1)); + EXPECT_EQ(row->avm_main_rwb, FF(0)); + + // Check the instruction tags + EXPECT_EQ(row->avm_main_r_in_tag, FF(static_cast(tag))); + EXPECT_EQ(row->avm_main_w_in_tag, FF(static_cast(tag))); + + // Check that start row is the same as what is copied into the main trace + EXPECT_EQ(alu_row->avm_alu_ia, a); + EXPECT_EQ(alu_row->avm_alu_ib, b); + EXPECT_EQ(alu_row->avm_alu_ic, c); +} + void common_validate_bit_op(std::vector const& trace, uint8_t op_id, FF const& a, @@ -318,6 +365,21 @@ std::vector> positive_op_xor_test_values = { (uint128_t{ 0x1006021301080000 } << 64) + uint128_t{ 0x000000000000001080876844827 }, (uint128_t{ 0xa906021301080001 } << 64) + uint128_t{ 0x0001080876844827 } } } }; +std::vector> positive_op_shr_test_values = { + { { 20, 3, 2 }, + { 5323, 255, 0 }, + { 36148, 13, 4 }, + { 0x7bff744e3cdf79LLU, 64, 0 }, + { (uint128_t{ 0x1006021301080000 } << 64) + uint128_t{ 0x000000000000001080876844827 }, 123, 2 } } +}; +std::vector> positive_op_shl_test_values = { + { { 20, 8, 0 }, + { 5323, 10, 11264 }, + { 13793, 255, 0 }, + { 239, 50, 269090077735387136 }, + { 9, 127, (uint128_t{ 0x4800000000000000LLU } << 68) } } +}; + std::vector gen_three_op_params(std::vector> operands, std::vector mem_tags) { @@ -332,6 +394,8 @@ class AvmBitwiseTestsNot : public AvmBitwiseTests, public testing::WithParamInte class AvmBitwiseTestsAnd : public AvmBitwiseTests, public testing::WithParamInterface {}; class AvmBitwiseTestsOr : public AvmBitwiseTests, public testing::WithParamInterface {}; class AvmBitwiseTestsXor : public AvmBitwiseTests, public testing::WithParamInterface {}; +class AvmBitwiseTestsShr : public AvmBitwiseTests, public testing::WithParamInterface {}; +class AvmBitwiseTestsShl : public AvmBitwiseTests, public testing::WithParamInterface {}; /****************************************************************************** * @@ -375,7 +439,6 @@ TEST_P(AvmBitwiseTestsAnd, AllAndTest) FF ff_a = FF(uint256_t::from_uint128(a)); FF ff_b = FF(uint256_t::from_uint128(b)); FF ff_output = FF(uint256_t::from_uint128(output)); - // EXPECT_EQ(1, 2) << "a ^ b " << (a ^ b) << '\n'; common_validate_bit_op(trace, 0, ff_a, ff_b, ff_output, FF(0), FF(1), FF(2), mem_tag); validate_trace(std::move(trace)); } @@ -426,6 +489,56 @@ INSTANTIATE_TEST_SUITE_P(AvmBitwiseTests, AvmBitwiseTestsXor, testing::ValuesIn(gen_three_op_params(positive_op_xor_test_values, mem_tags))); +TEST_P(AvmBitwiseTestsShr, AllShrTest) +{ + const auto [operands, mem_tag] = GetParam(); + const auto [a, b, output] = operands; + trace_builder.op_set(0, a, 0, mem_tag); + trace_builder.op_set(0, b, 1, mem_tag); + trace_builder.op_shr(0, 0, 1, 2, mem_tag); + trace_builder.return_op(0, 2, 1); + auto trace = trace_builder.finalize(); + common_validate_shift_op(trace, + uint256_t::from_uint128(a), + uint256_t::from_uint128(b), + uint256_t::from_uint128(output), + FF(0), + FF(1), + FF(2), + mem_tag, + true); + validate_trace(std::move(trace)); +} + +INSTANTIATE_TEST_SUITE_P(AvmBitwiseTests, + AvmBitwiseTestsShr, + testing::ValuesIn(gen_three_op_params(positive_op_shr_test_values, mem_tags))); + +TEST_P(AvmBitwiseTestsShl, AllShlTest) +{ + const auto [operands, mem_tag] = GetParam(); + const auto [a, b, output] = operands; + trace_builder.op_set(0, a, 0, mem_tag); + trace_builder.op_set(0, b, 1, mem_tag); + trace_builder.op_shl(0, 0, 1, 2, mem_tag); + trace_builder.return_op(0, 2, 1); + auto trace = trace_builder.finalize(); + + common_validate_shift_op(trace, + uint256_t::from_uint128(a), + uint256_t::from_uint128(b), + uint256_t::from_uint128(output), + FF(0), + FF(1), + FF(2), + mem_tag, + false); + validate_trace(std::move(trace)); +} + +INSTANTIATE_TEST_SUITE_P(AvmBitwiseTests, + AvmBitwiseTestsShl, + testing::ValuesIn(gen_three_op_params(positive_op_shl_test_values, mem_tags))); /****************************************************************************** * * NEGATIVE TESTS - Finite Field Type From 8a5ece7548a86d099ac6a166f04882624b8d95fd Mon Sep 17 00:00:00 2001 From: Ilyas Ridhuan Date: Tue, 23 Apr 2024 14:14:58 +0100 Subject: [PATCH 084/102] feat(avm): negative tests (#5919) Please read [contributing guidelines](CONTRIBUTING.md) and remove this line. --- .../vm/tests/avm_bitwise.test.cpp | 111 ++++++++++++++++++ .../barretenberg/vm/tests/helpers.test.cpp | 38 ++++++ .../barretenberg/vm/tests/helpers.test.hpp | 1 + 3 files changed, 150 insertions(+) diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_bitwise.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_bitwise.test.cpp index 16789ac3dc6..379908b06c5 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_bitwise.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_bitwise.test.cpp @@ -216,6 +216,66 @@ enum BIT_FAILURES { IncorrectBinSelector, }; +enum SHIFT_FAILURES { + IncorrectShiftPastBitLength, // Incorrect Setting shift_lt_bit_len + IncorrectInputDecomposition, + ShiftOutputIncorrect, +}; + +std::tuple, std::string> gen_mutated_trace_shift(std::vector trace, + std::function&& select_row, + FF const& c_mutated, + SHIFT_FAILURES fail_mode, + bool shr = true) +{ + auto main_trace_row = std::ranges::find_if(trace.begin(), trace.end(), select_row); + auto main_clk = main_trace_row->avm_main_clk; + // The corresponding row in the alu trace as well as the row where start = 1 + auto alu_row = + std::ranges::find_if(trace.begin(), trace.end(), [main_clk](Row r) { return r.avm_alu_clk == main_clk; }); + + std::string failure; + switch (fail_mode) { + case IncorrectShiftPastBitLength: + alu_row->avm_alu_shift_lt_bit_len = FF(0); + update_slice_registers(*alu_row, uint256_t{ 0 }); + alu_row->avm_alu_a_lo = FF(0); + alu_row->avm_alu_a_hi = FF(0); + failure = "SHIFT_LT_BIT_LEN"; + return std::make_tuple(trace, failure); + case IncorrectInputDecomposition: { + // Subtrace one from b_lo and update b_lo + uint256_t b_lo = alu_row->avm_alu_b_lo - 1; + uint256_t b_hi = alu_row->avm_alu_b_hi; + alu_row->avm_alu_b_lo = b_lo; + + // Update the range checks involving b_lo and b_hi so we dont throw an error about the range checks + if (shr) { + uint256_t a_lo = (uint256_t(1) << alu_row->avm_alu_ib) - b_lo - 1; + uint256_t a_hi = (uint256_t(1) << (32 - uint8_t(alu_row->avm_alu_ib))) - b_hi - 1; + alu_row->avm_alu_a_lo = a_lo & ((uint256_t(1) << 128) - 1); + alu_row->avm_alu_a_hi = a_hi; + // Update slice registers + update_slice_registers(*alu_row, a_lo + (a_hi << 128)); + failure = "SHR_INPUT_DECOMPOSITION"; + return std::make_tuple(trace, failure); + } + uint256_t a_lo = (uint256_t(1) << (32 - uint8_t(alu_row->avm_alu_ib))) - b_lo - 1; + uint256_t a_hi = (uint256_t(1) << alu_row->avm_alu_ib) - b_hi - 1; + alu_row->avm_alu_a_lo = a_lo & ((uint256_t(1) << 128) - 1); + alu_row->avm_alu_a_hi = a_hi; + // Update slice registers + update_slice_registers(*alu_row, a_lo + (a_hi << 128)); + failure = "SHL_INPUT_DECOMPOSITION"; + return std::make_tuple(trace, failure); + } + case ShiftOutputIncorrect: + alu_row->avm_alu_ic = c_mutated; + failure = shr ? "SHR_OUTPUT" : "SHL_OUTPUT"; + return std::make_tuple(trace, failure); + } + return std::make_tuple(trace, failure); +} std::vector gen_mutated_trace_bit(std::vector trace, std::function&& select_row, FF const& c_mutated, @@ -554,6 +614,10 @@ class AvmBitwiseNegativeTestsOr : public AvmBitwiseTests, public testing::WithParamInterface> {}; class AvmBitwiseNegativeTestsXor : public AvmBitwiseTests, public testing::WithParamInterface> {}; +class AvmBitwiseNegativeTestsShr : public AvmBitwiseTests, + public testing::WithParamInterface> {}; +class AvmBitwiseNegativeTestsShl : public AvmBitwiseTests, + public testing::WithParamInterface> {}; class AvmBitwiseNegativeTestsFF : public AvmBitwiseTests {}; class AvmBitwiseNegativeTestsU8 : public AvmBitwiseTests {}; class AvmBitwiseNegativeTestsU16 : public AvmBitwiseTests {}; @@ -570,12 +634,17 @@ std::vector> bit_failures = { { "OP_ID_REL", BIT_FAILURES::InconsistentOpId }, { "BIN_SEL_CTR_REL", BIT_FAILURES::IncorrectBinSelector }, }; +std::vector shift_failures = { SHIFT_FAILURES::IncorrectShiftPastBitLength, + SHIFT_FAILURES::IncorrectInputDecomposition, + SHIFT_FAILURES::ShiftOutputIncorrect }; // For the negative test the output is set to be incorrect so that we can test the byte lookups. // Picking "simple" inputs such as zero also makes it easier when check the byte length lookups as we dont // need to worry about copying the accmulated a & b registers into the main trace. std::vector neg_test_and = { { { 0, 0, 1 }, AvmMemoryTag::U32 } }; std::vector neg_test_or = { { { 0, 0, 1 }, AvmMemoryTag::U32 } }; std::vector neg_test_xor = { { { 0, 0, 1 }, AvmMemoryTag::U32 } }; + +std::vector neg_test_shr = { { { 7, 2, 0 }, AvmMemoryTag::U32 } }; /****************************************************************************** * Negative Tests - FF ******************************************************************************/ @@ -641,6 +710,48 @@ INSTANTIATE_TEST_SUITE_P(AvmBitwiseNegativeTests, AvmBitwiseNegativeTestsXor, testing::Combine(testing::ValuesIn(bit_failures), testing::ValuesIn(neg_test_xor))); +TEST_P(AvmBitwiseNegativeTestsShr, AllNegativeTests) +{ + const auto [failure, params] = GetParam(); + const auto [operands, mem_tag] = params; + const auto [a, b, output] = operands; + auto trace_builder = avm_trace::AvmTraceBuilder(); + trace_builder.op_set(0, uint128_t{ a }, 0, mem_tag); + trace_builder.op_set(0, uint128_t{ b }, 1, mem_tag); + trace_builder.op_shr(0, 0, 1, 2, mem_tag); + trace_builder.halt(); + auto trace = trace_builder.finalize(); + std::function&& select_row = [](Row r) { return r.avm_main_sel_op_shr == FF(1); }; + + auto [mutated_trace, str] = gen_mutated_trace_shift( + std::move(trace), std::move(select_row), FF(uint256_t::from_uint128(output)), failure, true); + EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(mutated_trace)), str); +} +INSTANTIATE_TEST_SUITE_P(AvmBitwiseNegativeTests, + AvmBitwiseNegativeTestsShr, + testing::Combine(testing::ValuesIn(shift_failures), testing::ValuesIn(neg_test_shr))); + +TEST_P(AvmBitwiseNegativeTestsShl, AllNegativeTests) +{ + const auto [failure, params] = GetParam(); + const auto [operands, mem_tag] = params; + const auto [a, b, output] = operands; + auto trace_builder = avm_trace::AvmTraceBuilder(); + trace_builder.op_set(0, uint128_t{ a }, 0, mem_tag); + trace_builder.op_set(0, uint128_t{ b }, 1, mem_tag); + trace_builder.op_shl(0, 0, 1, 2, mem_tag); + trace_builder.halt(); + auto trace = trace_builder.finalize(); + std::function&& select_row = [](Row r) { return r.avm_main_sel_op_shl == FF(1); }; + + auto [mutated_trace, str] = gen_mutated_trace_shift( + std::move(trace), std::move(select_row), FF(uint256_t::from_uint128(output)), failure, false); + EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(mutated_trace)), str); +} +INSTANTIATE_TEST_SUITE_P(AvmBitwiseNegativeTests, + AvmBitwiseNegativeTestsShl, + testing::Combine(testing::ValuesIn(shift_failures), testing::ValuesIn(neg_test_shr))); + TEST_F(AvmBitwiseNegativeTestsFF, UndefinedOverFF) { auto trace_builder = avm_trace::AvmTraceBuilder(); diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.cpp index c91374202df..290b15585a0 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.cpp @@ -78,6 +78,44 @@ void mutate_ic_in_trace(std::vector& trace, std::function&& sele mem_row->avm_mem_val = newValue; }; +// TODO: Should be a cleaner way to do this +void update_slice_registers(Row& row, uint256_t a) +{ + row.avm_alu_u8_r0 = static_cast(a); + a >>= 8; + row.avm_alu_u8_r1 = static_cast(a); + a >>= 8; + row.avm_alu_u16_r0 = static_cast(a); + a >>= 16; + row.avm_alu_u16_r1 = static_cast(a); + a >>= 16; + row.avm_alu_u16_r2 = static_cast(a); + a >>= 16; + row.avm_alu_u16_r3 = static_cast(a); + a >>= 16; + row.avm_alu_u16_r4 = static_cast(a); + a >>= 16; + row.avm_alu_u16_r5 = static_cast(a); + a >>= 16; + row.avm_alu_u16_r6 = static_cast(a); + a >>= 16; + row.avm_alu_u16_r7 = static_cast(a); + a >>= 16; + row.avm_alu_u16_r8 = static_cast(a); + a >>= 16; + row.avm_alu_u16_r9 = static_cast(a); + a >>= 16; + row.avm_alu_u16_r10 = static_cast(a); + a >>= 16; + row.avm_alu_u16_r11 = static_cast(a); + a >>= 16; + row.avm_alu_u16_r12 = static_cast(a); + a >>= 16; + row.avm_alu_u16_r13 = static_cast(a); + a >>= 16; + row.avm_alu_u16_r14 = static_cast(a); +} + // TODO: There has to be a better way to do. // This is a helper function to clear the range check counters associated with the alu register decomposition of // "previous_value" so we don't trigger a trivial range_check count error diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.hpp b/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.hpp index b1f4df3924a..fd1f862404d 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.hpp @@ -29,5 +29,6 @@ void mutate_ic_in_trace(std::vector& trace, FF const& newValue, bool alu = false); void clear_range_check_counters(std::vector& trace, uint256_t previous_value); +void update_slice_registers(Row& row, uint256_t a); } // namespace tests_avm From 185e57d51e8bbf6194628ce62db3dd44f11634a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Bene=C5=A1?= Date: Tue, 23 Apr 2024 16:32:55 +0200 Subject: [PATCH 085/102] refactor: renaming `noir-compiler` as `builder` (#5951) --- README.md | 8 -- boxes/Dockerfile | 2 +- boxes/Earthfile | 2 +- boxes/boxes/react/package.json | 2 +- boxes/boxes/vanilla/package.json | 2 +- boxes/contract-only/package.json | 2 +- .../how_to_compile_contract.md | 2 +- yarn-project/.earthlyignore | 22 ++--- yarn-project/.gitignore | 22 ++--- yarn-project/aztec/package.json | 2 +- yarn-project/aztec/tsconfig.json | 2 +- .../{noir-compiler => builder}/.eslintrc.cjs | 0 .../.prettierignore | 0 .../{noir-compiler => builder}/README.md | 8 +- .../aztec-builder-dest} | 0 .../{noir-compiler => builder}/package.json | 4 +- .../{noir-compiler => builder}/src/cli.ts | 2 +- .../src/cli/codegen.ts | 0 .../src/cli/update/common.ts | 0 .../src/cli/update/github.ts | 0 .../src/cli/update/noir.ts | 0 .../src/cli/update/npm.ts | 0 .../src/cli/update/update.ts | 0 .../src/cli/update/utils.ts | 0 .../src/contract-interface-gen/typescript.ts | 0 .../src/fixtures/test_contract/Nargo.toml | 0 .../src/fixtures/test_contract/src/main.nr | 0 .../src/fixtures/test_lib.zip | Bin .../src/fixtures/test_lib/Nargo.toml | 0 .../src/fixtures/test_lib/src/lib.nr | 0 .../src/fixtures/test_lib/src/module.nr | 0 .../src/fixtures/test_lib/src/module/foo.nr | 0 .../{noir-compiler => builder}/src/index.ts | 0 .../src/mocked_keys.ts | 0 .../{noir-compiler => builder}/src/utils.ts | 0 .../{noir-compiler => builder}/tsconfig.json | 0 yarn-project/deploy_npm.sh | 2 +- .../end-to-end/src/e2e_slow_tree.test.ts | 2 +- yarn-project/noir-contracts.js/package.json | 2 +- .../scripts/generate-types.sh | 2 +- yarn-project/noir-contracts.js/tsconfig.json | 2 +- .../noir-protocol-circuits-types/package.json | 2 +- .../tsconfig.json | 2 +- yarn-project/package.json | 2 +- yarn-project/pxe/package.json | 2 +- yarn-project/pxe/tsconfig.json | 2 +- yarn-project/tsconfig.json | 2 +- yarn-project/typedoc.json | 2 +- yarn-project/yarn.lock | 80 +++++++++--------- 49 files changed, 90 insertions(+), 96 deletions(-) rename yarn-project/{noir-compiler => builder}/.eslintrc.cjs (100%) rename yarn-project/{noir-compiler => builder}/.prettierignore (100%) rename yarn-project/{noir-compiler => builder}/README.md (61%) rename yarn-project/{noir-compiler/aztec-compile-dest => builder/aztec-builder-dest} (100%) rename yarn-project/{noir-compiler => builder}/package.json (96%) rename yarn-project/{noir-compiler => builder}/src/cli.ts (98%) rename yarn-project/{noir-compiler => builder}/src/cli/codegen.ts (100%) rename yarn-project/{noir-compiler => builder}/src/cli/update/common.ts (100%) rename yarn-project/{noir-compiler => builder}/src/cli/update/github.ts (100%) rename yarn-project/{noir-compiler => builder}/src/cli/update/noir.ts (100%) rename yarn-project/{noir-compiler => builder}/src/cli/update/npm.ts (100%) rename yarn-project/{noir-compiler => builder}/src/cli/update/update.ts (100%) rename yarn-project/{noir-compiler => builder}/src/cli/update/utils.ts (100%) rename yarn-project/{noir-compiler => builder}/src/contract-interface-gen/typescript.ts (100%) rename yarn-project/{noir-compiler => builder}/src/fixtures/test_contract/Nargo.toml (100%) rename yarn-project/{noir-compiler => builder}/src/fixtures/test_contract/src/main.nr (100%) rename yarn-project/{noir-compiler => builder}/src/fixtures/test_lib.zip (100%) rename yarn-project/{noir-compiler => builder}/src/fixtures/test_lib/Nargo.toml (100%) rename yarn-project/{noir-compiler => builder}/src/fixtures/test_lib/src/lib.nr (100%) rename yarn-project/{noir-compiler => builder}/src/fixtures/test_lib/src/module.nr (100%) rename yarn-project/{noir-compiler => builder}/src/fixtures/test_lib/src/module/foo.nr (100%) rename yarn-project/{noir-compiler => builder}/src/index.ts (100%) rename yarn-project/{noir-compiler => builder}/src/mocked_keys.ts (100%) rename yarn-project/{noir-compiler => builder}/src/utils.ts (100%) rename yarn-project/{noir-compiler => builder}/tsconfig.json (100%) diff --git a/README.md b/README.md index 38e03d97604..82fa8dff1ea 100644 --- a/README.md +++ b/README.md @@ -27,14 +27,6 @@ Alternatively, to just hack on Noir contracts and Typescript, run `./bootstrap.s To build Typescript code, make sure to have [`nvm`](https://github.com/nvm-sh/nvm) (node version manager) installed. -To build noir code, make sure that you are using the version from `yarn-project/noir-compiler/src/noir-version.json`. - -Install nargo by running - -``` -noirup -v TAG_FROM_THE_FILE -``` - ## Continuous Integration This repository uses CircleCI for continuous integration. Build steps are managed using [`build-system`](https://github.com/AztecProtocol/build-system). Small packages are built and tested as part of a docker build operation, while larger ones and end-to-end tests spin up a large AWS spot instance. Each successful build step creates a new docker image that gets tagged with the package name and commit. diff --git a/boxes/Dockerfile b/boxes/Dockerfile index 5809c3a2b5b..6ca01d2f468 100644 --- a/boxes/Dockerfile +++ b/boxes/Dockerfile @@ -13,7 +13,7 @@ COPY --from=noir-projects /usr/src/noir-projects/noir-protocol-circuits/crates/t WORKDIR /usr/src/boxes COPY . . ENV AZTEC_NARGO=/usr/src/noir/noir-repo/target/release/nargo -ENV AZTEC_COMPILE=/usr/src/yarn-project/noir-compiler/aztec-compile-dest +ENV AZTEC_BUILDER=/usr/src/yarn-project/builder/aztec-builder-dest RUN yarn RUN npx -y playwright@1.42 install --with-deps ENTRYPOINT ["/bin/sh", "-c"] diff --git a/boxes/Earthfile b/boxes/Earthfile index 77999a36a41..d790d1b0da5 100644 --- a/boxes/Earthfile +++ b/boxes/Earthfile @@ -12,7 +12,7 @@ build: WORKDIR /usr/src/boxes COPY . . ENV AZTEC_NARGO=/usr/src/noir/noir-repo/target/release/nargo - ENV AZTEC_COMPILE=/usr/src/yarn-project/noir-compiler/aztec-compile-dest + ENV AZTEC_BUILDER=/usr/src/yarn-project/builder/aztec-builder-dest RUN yarn && yarn build RUN npx -y playwright@1.42 install --with-deps ENTRYPOINT ["/bin/sh", "-c"] diff --git a/boxes/boxes/react/package.json b/boxes/boxes/react/package.json index 31619d2ea24..8d121e38a9d 100644 --- a/boxes/boxes/react/package.json +++ b/boxes/boxes/react/package.json @@ -7,7 +7,7 @@ "main": "./dist/index.js", "scripts": { "compile": "cd src/contracts && ${AZTEC_NARGO:-aztec-nargo} compile", - "codegen": "${AZTEC_COMPILE:-aztec-compile} codegen src/contracts/target -o artifacts", + "codegen": "${AZTEC_BUILDER:-aztec-builder} codegen src/contracts/target -o artifacts", "clean": "rm -rf ./dist .tsbuildinfo ./artifacts ./src/contracts/target", "prep": "yarn clean && yarn compile && yarn codegen", "dev": "yarn prep && webpack serve --mode development", diff --git a/boxes/boxes/vanilla/package.json b/boxes/boxes/vanilla/package.json index 92b3ebc7cd2..f2d6ee850ee 100644 --- a/boxes/boxes/vanilla/package.json +++ b/boxes/boxes/vanilla/package.json @@ -6,7 +6,7 @@ "type": "module", "scripts": { "compile": "cd src/contracts && ${AZTEC_NARGO:-aztec-nargo} compile", - "codegen": "${AZTEC_COMPILE:-aztec-compile} codegen src/contracts/target -o artifacts", + "codegen": "${AZTEC_BUILDER:-aztec-builder} codegen src/contracts/target -o artifacts", "clean": "rm -rf ./dest .tsbuildinfo ./artifacts ./src/contracts/target", "prep": "yarn clean && yarn compile && yarn codegen && tsc -b", "dev": "yarn prep && webpack serve --mode development", diff --git a/boxes/contract-only/package.json b/boxes/contract-only/package.json index 13edb7678fd..493f35979f9 100644 --- a/boxes/contract-only/package.json +++ b/boxes/contract-only/package.json @@ -6,7 +6,7 @@ "type": "module", "scripts": { "compile": "cd src && ${AZTEC_NARGO:-aztec-nargo} compile", - "codegen": "${AZTEC_COMPILE:-aztec-compile} codegen target -o artifacts", + "codegen": "${AZTEC_BUILDER:-aztec-builder} codegen target -o artifacts", "clean": "rm -rf ./dest .tsbuildinfo ./artifacts ./target", "prep": "yarn clean && yarn compile && yarn codegen && tsc -b", "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules $(yarn bin jest) --runInBand", diff --git a/docs/docs/developers/contracts/compiling_contracts/how_to_compile_contract.md b/docs/docs/developers/contracts/compiling_contracts/how_to_compile_contract.md index 6f047087f03..c1fdb70014c 100644 --- a/docs/docs/developers/contracts/compiling_contracts/how_to_compile_contract.md +++ b/docs/docs/developers/contracts/compiling_contracts/how_to_compile_contract.md @@ -22,7 +22,7 @@ This will output a JSON [artifact](./artifacts.md) for each contract in the proj :::note This command looks for `Nargo.toml` files by ascending up the parent directories, and will compile the top-most Nargo.toml file it finds. -Eg: if you are in `/hobbies/cool-game/contracts/easter-egg/`, and both `cool-game` and `easter-egg` contain a Nargo.toml file, then `aztec-compile` will be performed on `cool-game/Nargo.toml` and compile the project(s) specified within it. Eg +Eg: if you are in `/hobbies/cool-game/contracts/easter-egg/`, and both `cool-game` and `easter-egg` contain a Nargo.toml file, then `aztec-nargo compile` will be performed on `cool-game/Nargo.toml` and compile the project(s) specified within it. Eg ``` [workspace] members = [ diff --git a/yarn-project/.earthlyignore b/yarn-project/.earthlyignore index 0ca688aac6e..90a25913737 100644 --- a/yarn-project/.earthlyignore +++ b/yarn-project/.earthlyignore @@ -53,17 +53,17 @@ end-to-end/src/web/main.js end-to-end/src/web/main.js.LICENSE.txt entry-points/src/artifacts l1-contracts/generated -noir-compiler/target/ -noir-compiler/proofs/ -noir-compiler/Prover.toml -noir-compiler/Verifier.toml -noir-compiler/noir-protocol-circuits-types/.gitignore wow -noir-compiler/proofs/ -noir-compiler/Prover.toml -noir-compiler/Verifier.toml -noir-compiler/src/target -noir-compiler/src/crs -noir-compiler/src/types +builder/target/ +builder/proofs/ +builder/Prover.toml +builder/Verifier.toml +builder/noir-protocol-circuits-types/.gitignore wow +builder/proofs/ +builder/Prover.toml +builder/Verifier.toml +builder/src/target +builder/src/crs +builder/src/types protocol-contracts/src/artifacts scripts/tmp noir-contracts.js/src diff --git a/yarn-project/.gitignore b/yarn-project/.gitignore index db7a81c9d62..7c86855f16a 100644 --- a/yarn-project/.gitignore +++ b/yarn-project/.gitignore @@ -27,17 +27,17 @@ end-to-end/src/web/main.js.LICENSE.txt entry-points/src/artifacts l1-artifacts/generated l1-contracts/generated -noir-compiler/target/ -noir-compiler/proofs/ -noir-compiler/Prover.toml -noir-compiler/Verifier.toml -noir-compiler/noir-protocol-circuits-types/.gitignore wow -noir-compiler/proofs/ -noir-compiler/Prover.toml -noir-compiler/Verifier.toml -noir-compiler/src/target -noir-compiler/src/crs -noir-compiler/src/types +builder/target/ +builder/proofs/ +builder/Prover.toml +builder/Verifier.toml +builder/noir-protocol-circuits-types/.gitignore wow +builder/proofs/ +builder/Prover.toml +builder/Verifier.toml +builder/src/target +builder/src/crs +builder/src/types noir-protocol-circuits-types/src/types/ protocol-contracts/src/artifacts scripts/tmp diff --git a/yarn-project/aztec/package.json b/yarn-project/aztec/package.json index 923d86a2938..5d3874c5a85 100644 --- a/yarn-project/aztec/package.json +++ b/yarn-project/aztec/package.json @@ -31,6 +31,7 @@ "@aztec/archiver": "workspace:^", "@aztec/aztec-node": "workspace:^", "@aztec/aztec.js": "workspace:^", + "@aztec/builder": "workspace:^", "@aztec/circuit-types": "workspace:^", "@aztec/circuits.js": "workspace:^", "@aztec/entrypoints": "workspace:^", @@ -38,7 +39,6 @@ "@aztec/foundation": "workspace:^", "@aztec/kv-store": "workspace:^", "@aztec/l1-artifacts": "workspace:^", - "@aztec/noir-compiler": "workspace:^", "@aztec/noir-contracts.js": "workspace:^", "@aztec/p2p": "workspace:^", "@aztec/protocol-contracts": "workspace:^", diff --git a/yarn-project/aztec/tsconfig.json b/yarn-project/aztec/tsconfig.json index cb1f515a166..ff9caf3d51b 100644 --- a/yarn-project/aztec/tsconfig.json +++ b/yarn-project/aztec/tsconfig.json @@ -40,7 +40,7 @@ "path": "../l1-artifacts" }, { - "path": "../noir-compiler" + "path": "../builder" }, { "path": "../noir-contracts.js" diff --git a/yarn-project/noir-compiler/.eslintrc.cjs b/yarn-project/builder/.eslintrc.cjs similarity index 100% rename from yarn-project/noir-compiler/.eslintrc.cjs rename to yarn-project/builder/.eslintrc.cjs diff --git a/yarn-project/noir-compiler/.prettierignore b/yarn-project/builder/.prettierignore similarity index 100% rename from yarn-project/noir-compiler/.prettierignore rename to yarn-project/builder/.prettierignore diff --git a/yarn-project/noir-compiler/README.md b/yarn-project/builder/README.md similarity index 61% rename from yarn-project/noir-compiler/README.md rename to yarn-project/builder/README.md index ade6f9bfa0c..3b2a1729676 100644 --- a/yarn-project/noir-compiler/README.md +++ b/yarn-project/builder/README.md @@ -1,13 +1,15 @@ # Aztec.nr compiler -The Aztec.nr compiler compiles Aztec.nr contracts using nargo and outputs Aztec formatted contract ABIs. The compiler can also generate typescript classes for each contract, as well as Aztec.nr interfaces for calling external functions. +The Aztec.nr compiler compiles Aztec.nr contracts using nargo and outputs Aztec formatted contract ABIs. +The compiler can also generate typescript classes for each contract, as well as Aztec.nr interfaces for calling external functions. +It can also be used to update aztec project dependencies. ## Installation To install the package, run: ```bash -yarn add @aztec/noir-compiler +yarn add @aztec/builder ``` ## Usage @@ -15,7 +17,7 @@ yarn add @aztec/noir-compiler To run the compiler as a CLI tool, first install the package and then run: ```bash -yarn aztec-compile compile --help +yarn aztec-builder compile --help ``` You can also run the compiler from the [main Aztec CLI](../cli/README.md), which includes several other features for interacting with the Aztec Network: diff --git a/yarn-project/noir-compiler/aztec-compile-dest b/yarn-project/builder/aztec-builder-dest similarity index 100% rename from yarn-project/noir-compiler/aztec-compile-dest rename to yarn-project/builder/aztec-builder-dest diff --git a/yarn-project/noir-compiler/package.json b/yarn-project/builder/package.json similarity index 96% rename from yarn-project/noir-compiler/package.json rename to yarn-project/builder/package.json index c35f9e851d5..5f87dd34488 100644 --- a/yarn-project/noir-compiler/package.json +++ b/yarn-project/builder/package.json @@ -1,5 +1,5 @@ { - "name": "@aztec/noir-compiler", + "name": "@aztec/builder", "version": "0.1.0", "type": "module", "exports": { @@ -14,7 +14,7 @@ "tsconfig": "./tsconfig.json" }, "bin": { - "aztec-compile": "dest/cli.js" + "aztec-builder": "dest/cli.js" }, "scripts": { "build": "yarn clean && tsc -b", diff --git a/yarn-project/noir-compiler/src/cli.ts b/yarn-project/builder/src/cli.ts similarity index 98% rename from yarn-project/noir-compiler/src/cli.ts rename to yarn-project/builder/src/cli.ts index 931512a63d5..a8d2faf4d6a 100644 --- a/yarn-project/noir-compiler/src/cli.ts +++ b/yarn-project/builder/src/cli.ts @@ -25,7 +25,7 @@ const main = async () => { .default(`http://${LOCALHOST}:8080`) .makeOptionMandatory(true); - program.name('aztec-compile'); + program.name('aztec-builder'); program .command('codegen') .argument('', 'Path to the Noir ABI or project dir.') diff --git a/yarn-project/noir-compiler/src/cli/codegen.ts b/yarn-project/builder/src/cli/codegen.ts similarity index 100% rename from yarn-project/noir-compiler/src/cli/codegen.ts rename to yarn-project/builder/src/cli/codegen.ts diff --git a/yarn-project/noir-compiler/src/cli/update/common.ts b/yarn-project/builder/src/cli/update/common.ts similarity index 100% rename from yarn-project/noir-compiler/src/cli/update/common.ts rename to yarn-project/builder/src/cli/update/common.ts diff --git a/yarn-project/noir-compiler/src/cli/update/github.ts b/yarn-project/builder/src/cli/update/github.ts similarity index 100% rename from yarn-project/noir-compiler/src/cli/update/github.ts rename to yarn-project/builder/src/cli/update/github.ts diff --git a/yarn-project/noir-compiler/src/cli/update/noir.ts b/yarn-project/builder/src/cli/update/noir.ts similarity index 100% rename from yarn-project/noir-compiler/src/cli/update/noir.ts rename to yarn-project/builder/src/cli/update/noir.ts diff --git a/yarn-project/noir-compiler/src/cli/update/npm.ts b/yarn-project/builder/src/cli/update/npm.ts similarity index 100% rename from yarn-project/noir-compiler/src/cli/update/npm.ts rename to yarn-project/builder/src/cli/update/npm.ts diff --git a/yarn-project/noir-compiler/src/cli/update/update.ts b/yarn-project/builder/src/cli/update/update.ts similarity index 100% rename from yarn-project/noir-compiler/src/cli/update/update.ts rename to yarn-project/builder/src/cli/update/update.ts diff --git a/yarn-project/noir-compiler/src/cli/update/utils.ts b/yarn-project/builder/src/cli/update/utils.ts similarity index 100% rename from yarn-project/noir-compiler/src/cli/update/utils.ts rename to yarn-project/builder/src/cli/update/utils.ts diff --git a/yarn-project/noir-compiler/src/contract-interface-gen/typescript.ts b/yarn-project/builder/src/contract-interface-gen/typescript.ts similarity index 100% rename from yarn-project/noir-compiler/src/contract-interface-gen/typescript.ts rename to yarn-project/builder/src/contract-interface-gen/typescript.ts diff --git a/yarn-project/noir-compiler/src/fixtures/test_contract/Nargo.toml b/yarn-project/builder/src/fixtures/test_contract/Nargo.toml similarity index 100% rename from yarn-project/noir-compiler/src/fixtures/test_contract/Nargo.toml rename to yarn-project/builder/src/fixtures/test_contract/Nargo.toml diff --git a/yarn-project/noir-compiler/src/fixtures/test_contract/src/main.nr b/yarn-project/builder/src/fixtures/test_contract/src/main.nr similarity index 100% rename from yarn-project/noir-compiler/src/fixtures/test_contract/src/main.nr rename to yarn-project/builder/src/fixtures/test_contract/src/main.nr diff --git a/yarn-project/noir-compiler/src/fixtures/test_lib.zip b/yarn-project/builder/src/fixtures/test_lib.zip similarity index 100% rename from yarn-project/noir-compiler/src/fixtures/test_lib.zip rename to yarn-project/builder/src/fixtures/test_lib.zip diff --git a/yarn-project/noir-compiler/src/fixtures/test_lib/Nargo.toml b/yarn-project/builder/src/fixtures/test_lib/Nargo.toml similarity index 100% rename from yarn-project/noir-compiler/src/fixtures/test_lib/Nargo.toml rename to yarn-project/builder/src/fixtures/test_lib/Nargo.toml diff --git a/yarn-project/noir-compiler/src/fixtures/test_lib/src/lib.nr b/yarn-project/builder/src/fixtures/test_lib/src/lib.nr similarity index 100% rename from yarn-project/noir-compiler/src/fixtures/test_lib/src/lib.nr rename to yarn-project/builder/src/fixtures/test_lib/src/lib.nr diff --git a/yarn-project/noir-compiler/src/fixtures/test_lib/src/module.nr b/yarn-project/builder/src/fixtures/test_lib/src/module.nr similarity index 100% rename from yarn-project/noir-compiler/src/fixtures/test_lib/src/module.nr rename to yarn-project/builder/src/fixtures/test_lib/src/module.nr diff --git a/yarn-project/noir-compiler/src/fixtures/test_lib/src/module/foo.nr b/yarn-project/builder/src/fixtures/test_lib/src/module/foo.nr similarity index 100% rename from yarn-project/noir-compiler/src/fixtures/test_lib/src/module/foo.nr rename to yarn-project/builder/src/fixtures/test_lib/src/module/foo.nr diff --git a/yarn-project/noir-compiler/src/index.ts b/yarn-project/builder/src/index.ts similarity index 100% rename from yarn-project/noir-compiler/src/index.ts rename to yarn-project/builder/src/index.ts diff --git a/yarn-project/noir-compiler/src/mocked_keys.ts b/yarn-project/builder/src/mocked_keys.ts similarity index 100% rename from yarn-project/noir-compiler/src/mocked_keys.ts rename to yarn-project/builder/src/mocked_keys.ts diff --git a/yarn-project/noir-compiler/src/utils.ts b/yarn-project/builder/src/utils.ts similarity index 100% rename from yarn-project/noir-compiler/src/utils.ts rename to yarn-project/builder/src/utils.ts diff --git a/yarn-project/noir-compiler/tsconfig.json b/yarn-project/builder/tsconfig.json similarity index 100% rename from yarn-project/noir-compiler/tsconfig.json rename to yarn-project/builder/tsconfig.json diff --git a/yarn-project/deploy_npm.sh b/yarn-project/deploy_npm.sh index 3a08cec3846..b64c347f168 100755 --- a/yarn-project/deploy_npm.sh +++ b/yarn-project/deploy_npm.sh @@ -90,7 +90,7 @@ deploy_package entrypoints deploy_package accounts deploy_package l1-artifacts deploy_package ethereum -deploy_package noir-compiler +deploy_package builder deploy_package noir-contracts.js deploy_package kv-store deploy_package merkle-tree diff --git a/yarn-project/end-to-end/src/e2e_slow_tree.test.ts b/yarn-project/end-to-end/src/e2e_slow_tree.test.ts index b1f583e9e54..e853e125f65 100644 --- a/yarn-project/end-to-end/src/e2e_slow_tree.test.ts +++ b/yarn-project/end-to-end/src/e2e_slow_tree.test.ts @@ -6,7 +6,7 @@ import { SlowTreeContract } from '@aztec/noir-contracts.js/SlowTree'; import { setup } from './fixtures/utils.js'; -describe('e2e_slow_tree', () => { +describe.skip('e2e_slow_tree', () => { let logger: DebugLogger; let wallet: Wallet; let teardown: () => Promise; diff --git a/yarn-project/noir-contracts.js/package.json b/yarn-project/noir-contracts.js/package.json index 5d3d3fc7f6c..811ab20a72b 100644 --- a/yarn-project/noir-contracts.js/package.json +++ b/yarn-project/noir-contracts.js/package.json @@ -41,7 +41,7 @@ "tslib": "^2.4.0" }, "devDependencies": { - "@aztec/noir-compiler": "workspace:^", + "@aztec/builder": "workspace:^", "@jest/globals": "^29.5.0", "@types/jest": "^29.5.0", "jest": "^29.5.0", diff --git a/yarn-project/noir-contracts.js/scripts/generate-types.sh b/yarn-project/noir-contracts.js/scripts/generate-types.sh index 6e98b09125b..f7355440508 100755 --- a/yarn-project/noir-contracts.js/scripts/generate-types.sh +++ b/yarn-project/noir-contracts.js/scripts/generate-types.sh @@ -28,7 +28,7 @@ for ABI in $(find ../../noir-projects/noir-contracts/target -maxdepth 1 -type f done # Generate types for the contracts -node --no-warnings ../noir-compiler/dest/cli.js codegen -o $OUT_DIR artifacts +node --no-warnings ../builder/dest/cli.js codegen -o $OUT_DIR artifacts # Append exports for each generated TypeScript file to index.ts find "$OUT_DIR" -maxdepth 1 -type f -name '*.ts' ! -name 'index.ts' | while read -r TS_FILE; do diff --git a/yarn-project/noir-contracts.js/tsconfig.json b/yarn-project/noir-contracts.js/tsconfig.json index 52f76611325..caf5e40c801 100644 --- a/yarn-project/noir-contracts.js/tsconfig.json +++ b/yarn-project/noir-contracts.js/tsconfig.json @@ -10,7 +10,7 @@ "path": "../aztec.js" }, { - "path": "../noir-compiler" + "path": "../builder" } ], "include": [ diff --git a/yarn-project/noir-protocol-circuits-types/package.json b/yarn-project/noir-protocol-circuits-types/package.json index 49c2f916be8..01acd5cc549 100644 --- a/yarn-project/noir-protocol-circuits-types/package.json +++ b/yarn-project/noir-protocol-circuits-types/package.json @@ -37,9 +37,9 @@ } }, "dependencies": { + "@aztec/builder": "workspace:^", "@aztec/circuits.js": "workspace:^", "@aztec/foundation": "workspace:^", - "@aztec/noir-compiler": "workspace:^", "@aztec/types": "workspace:^", "@noir-lang/acvm_js": "portal:../../noir/packages/acvm_js", "@noir-lang/noirc_abi": "portal:../../noir/packages/noirc_abi", diff --git a/yarn-project/noir-protocol-circuits-types/tsconfig.json b/yarn-project/noir-protocol-circuits-types/tsconfig.json index a2e4cd63239..b932dd11a80 100644 --- a/yarn-project/noir-protocol-circuits-types/tsconfig.json +++ b/yarn-project/noir-protocol-circuits-types/tsconfig.json @@ -13,7 +13,7 @@ "path": "../foundation" }, { - "path": "../noir-compiler" + "path": "../builder" }, { "path": "../types" diff --git a/yarn-project/package.json b/yarn-project/package.json index 78df3f10602..7df2db0bf2e 100644 --- a/yarn-project/package.json +++ b/yarn-project/package.json @@ -39,7 +39,7 @@ "kv-store", "l1-artifacts", "merkle-tree", - "noir-compiler", + "builder", "noir-contracts.js", "noir-protocol-circuits-types", "p2p", diff --git a/yarn-project/pxe/package.json b/yarn-project/pxe/package.json index 563ac0c866f..03c104943be 100644 --- a/yarn-project/pxe/package.json +++ b/yarn-project/pxe/package.json @@ -40,13 +40,13 @@ ] }, "dependencies": { + "@aztec/builder": "workspace:^", "@aztec/circuit-types": "workspace:^", "@aztec/circuits.js": "workspace:^", "@aztec/ethereum": "workspace:^", "@aztec/foundation": "workspace:^", "@aztec/key-store": "workspace:^", "@aztec/kv-store": "workspace:^", - "@aztec/noir-compiler": "workspace:^", "@aztec/noir-protocol-circuits-types": "workspace:^", "@aztec/protocol-contracts": "workspace:^", "@aztec/simulator": "workspace:^", diff --git a/yarn-project/pxe/tsconfig.json b/yarn-project/pxe/tsconfig.json index 32d3eb3dda6..e32a4d6aa27 100644 --- a/yarn-project/pxe/tsconfig.json +++ b/yarn-project/pxe/tsconfig.json @@ -25,7 +25,7 @@ "path": "../kv-store" }, { - "path": "../noir-compiler" + "path": "../builder" }, { "path": "../noir-protocol-circuits-types" diff --git a/yarn-project/tsconfig.json b/yarn-project/tsconfig.json index 3fde67b857e..9cd760e9a18 100644 --- a/yarn-project/tsconfig.json +++ b/yarn-project/tsconfig.json @@ -35,7 +35,7 @@ { "path": "l1-artifacts/tsconfig.json" }, { "path": "merkle-tree/tsconfig.json" }, { "path": "noir-contracts.js/tsconfig.json" }, - { "path": "noir-compiler/tsconfig.json" }, + { "path": "builder/tsconfig.json" }, { "path": "noir-protocol-circuits-types/tsconfig.json" }, { "path": "p2p/tsconfig.json" }, { "path": "p2p-bootstrap/tsconfig.json" }, diff --git a/yarn-project/typedoc.json b/yarn-project/typedoc.json index fa3d9891894..90edf2de43f 100644 --- a/yarn-project/typedoc.json +++ b/yarn-project/typedoc.json @@ -11,7 +11,7 @@ "aztec.js", "key-store", "noir-contracts.js", - "noir-compiler", + "builder", "p2p", "prover-client", "aztec-node", diff --git a/yarn-project/yarn.lock b/yarn-project/yarn.lock index 01b7cd8f4e7..12ef01aca7c 100644 --- a/yarn-project/yarn.lock +++ b/yarn-project/yarn.lock @@ -196,6 +196,7 @@ __metadata: "@aztec/archiver": "workspace:^" "@aztec/aztec-node": "workspace:^" "@aztec/aztec.js": "workspace:^" + "@aztec/builder": "workspace:^" "@aztec/circuit-types": "workspace:^" "@aztec/circuits.js": "workspace:^" "@aztec/entrypoints": "workspace:^" @@ -203,7 +204,6 @@ __metadata: "@aztec/foundation": "workspace:^" "@aztec/kv-store": "workspace:^" "@aztec/l1-artifacts": "workspace:^" - "@aztec/noir-compiler": "workspace:^" "@aztec/noir-contracts.js": "workspace:^" "@aztec/p2p": "workspace:^" "@aztec/protocol-contracts": "workspace:^" @@ -239,6 +239,42 @@ __metadata: languageName: node linkType: soft +"@aztec/builder@workspace:^, @aztec/builder@workspace:builder": + version: 0.0.0-use.local + resolution: "@aztec/builder@workspace:builder" + dependencies: + "@aztec/circuits.js": "workspace:^" + "@aztec/foundation": "workspace:^" + "@aztec/types": "workspace:^" + "@iarna/toml": ^2.2.5 + "@jest/globals": ^29.5.0 + "@types/fs-extra": ^11.0.1 + "@types/jest": ^29.5.0 + "@types/lodash.camelcase": ^4.3.7 + "@types/lodash.capitalize": ^4.2.7 + "@types/lodash.uniqby": ^4.7.9 + "@types/node": ^18.7.23 + "@types/pako": ^2.0.0 + "@types/semver": ^7.5.4 + base64-js: ^1.5.1 + commander: ^9.0.0 + fs-extra: ^11.1.1 + jest: ^29.5.0 + lodash.camelcase: ^4.3.0 + lodash.capitalize: ^4.2.1 + lodash.uniqby: ^4.7.0 + memfs: ^4.6.0 + pako: ^2.1.0 + semver: ^7.5.4 + ts-node: ^10.9.1 + tslib: ^2.4.0 + typescript: ^5.0.4 + unzipit: ^1.4.3 + bin: + aztec-builder: dest/cli.js + languageName: unknown + linkType: soft + "@aztec/circuit-types@workspace:^, @aztec/circuit-types@workspace:circuit-types": version: 0.0.0-use.local resolution: "@aztec/circuit-types@workspace:circuit-types" @@ -525,48 +561,12 @@ __metadata: languageName: unknown linkType: soft -"@aztec/noir-compiler@workspace:^, @aztec/noir-compiler@workspace:noir-compiler": - version: 0.0.0-use.local - resolution: "@aztec/noir-compiler@workspace:noir-compiler" - dependencies: - "@aztec/circuits.js": "workspace:^" - "@aztec/foundation": "workspace:^" - "@aztec/types": "workspace:^" - "@iarna/toml": ^2.2.5 - "@jest/globals": ^29.5.0 - "@types/fs-extra": ^11.0.1 - "@types/jest": ^29.5.0 - "@types/lodash.camelcase": ^4.3.7 - "@types/lodash.capitalize": ^4.2.7 - "@types/lodash.uniqby": ^4.7.9 - "@types/node": ^18.7.23 - "@types/pako": ^2.0.0 - "@types/semver": ^7.5.4 - base64-js: ^1.5.1 - commander: ^9.0.0 - fs-extra: ^11.1.1 - jest: ^29.5.0 - lodash.camelcase: ^4.3.0 - lodash.capitalize: ^4.2.1 - lodash.uniqby: ^4.7.0 - memfs: ^4.6.0 - pako: ^2.1.0 - semver: ^7.5.4 - ts-node: ^10.9.1 - tslib: ^2.4.0 - typescript: ^5.0.4 - unzipit: ^1.4.3 - bin: - aztec-compile: dest/cli.js - languageName: unknown - linkType: soft - "@aztec/noir-contracts.js@workspace:^, @aztec/noir-contracts.js@workspace:noir-contracts.js": version: 0.0.0-use.local resolution: "@aztec/noir-contracts.js@workspace:noir-contracts.js" dependencies: "@aztec/aztec.js": "workspace:^" - "@aztec/noir-compiler": "workspace:^" + "@aztec/builder": "workspace:^" "@jest/globals": ^29.5.0 "@types/jest": ^29.5.0 jest: ^29.5.0 @@ -580,12 +580,12 @@ __metadata: version: 0.0.0-use.local resolution: "@aztec/noir-protocol-circuits-types@workspace:noir-protocol-circuits-types" dependencies: + "@aztec/builder": "workspace:^" "@aztec/circuit-types": "workspace:^" "@aztec/circuits.js": "workspace:^" "@aztec/foundation": "workspace:^" "@aztec/kv-store": "workspace:^" "@aztec/merkle-tree": "workspace:^" - "@aztec/noir-compiler": "workspace:^" "@aztec/types": "workspace:^" "@jest/globals": ^29.5.0 "@noir-lang/acvm_js": "portal:../../noir/packages/acvm_js" @@ -711,13 +711,13 @@ __metadata: version: 0.0.0-use.local resolution: "@aztec/pxe@workspace:pxe" dependencies: + "@aztec/builder": "workspace:^" "@aztec/circuit-types": "workspace:^" "@aztec/circuits.js": "workspace:^" "@aztec/ethereum": "workspace:^" "@aztec/foundation": "workspace:^" "@aztec/key-store": "workspace:^" "@aztec/kv-store": "workspace:^" - "@aztec/noir-compiler": "workspace:^" "@aztec/noir-contracts.js": "workspace:^" "@aztec/noir-protocol-circuits-types": "workspace:^" "@aztec/protocol-contracts": "workspace:^" From ae502199b84999418d461ed5d0d6fca0c60494c5 Mon Sep 17 00:00:00 2001 From: Ilyas Ridhuan Date: Tue, 23 Apr 2024 15:49:47 +0100 Subject: [PATCH 086/102] fix(avm): comments and assert (#5956) Please read [contributing guidelines](CONTRIBUTING.md) and remove this line. --- .../barretenberg/vm/avm_trace/avm_alu_trace.cpp | 17 +++++++++++------ .../barretenberg/vm/tests/avm_bitwise.test.cpp | 2 +- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_alu_trace.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_alu_trace.cpp index d7bea240603..497d4143f44 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_alu_trace.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_alu_trace.cpp @@ -781,6 +781,7 @@ FF AvmAluTraceBuilder::op_shr(FF const& a, FF const& b, AvmMemoryTag in_tag, uin uint256_t a_u256{ a }; // Check that the shifted amount is an 8-bit integer ASSERT(uint256_t(b) < 256); + ASSERT(in_tag != AvmMemoryTag::U0 || in_tag != AvmMemoryTag::FF); uint8_t b_u8 = static_cast(uint256_t(b)); uint256_t c_u256 = a_u256 >> b_u8; @@ -792,6 +793,7 @@ FF AvmAluTraceBuilder::op_shr(FF const& a, FF const& b, AvmMemoryTag in_tag, uin if (b_u8 >= num_bits) { u8_pow_2_counters[1][b_u8 - num_bits]++; // Even though the registers are trivially zero, we call this function to increment the lookup counters + // Future workaround would be to decouple the range_check toggle and the counter from this function [[maybe_unused]] auto [alu_u8_r0, alu_u8_r1, alu_u16_reg] = AvmAluTraceBuilder::to_alu_slice_registers(0); alu_trace.push_back(AvmAluTraceBuilder::AluTraceEntry{ .alu_clk = clk, @@ -803,7 +805,7 @@ FF AvmAluTraceBuilder::op_shr(FF const& a, FF const& b, AvmMemoryTag in_tag, uin .alu_u64_tag = in_tag == AvmMemoryTag::U64, .alu_u128_tag = in_tag == AvmMemoryTag::U128, .alu_ia = a, - .alu_ib = FF(b_u8), + .alu_ib = b, .alu_ic = 0, .hi_lo_limbs = { 0, 0, 0, 0 }, .mem_tag_bits = num_bits, @@ -820,7 +822,7 @@ FF AvmAluTraceBuilder::op_shr(FF const& a, FF const& b, AvmMemoryTag in_tag, uin uint256_t rng_chk_lo = (uint256_t(1) << b_u8) - x_lo - 1; uint256_t rng_chk_hi = (uint256_t(1) << (num_bits - b_u8)) - x_hi - 1; - // Each hi and lo limb is range checked over 128bits + // Each hi and lo limb is range checked over 128 bits uint256_t limb = rng_chk_lo + (rng_chk_hi << uint256_t(128)); // Load the range check values into the ALU registers auto [alu_u8_r0, alu_u8_r1, alu_u16_reg] = AvmAluTraceBuilder::to_alu_slice_registers(limb); @@ -868,6 +870,8 @@ FF AvmAluTraceBuilder::op_shl(FF const& a, FF const& b, AvmMemoryTag in_tag, uin uint256_t a_u256{ a }; // Check that the shift amount is an 8-bit integer ASSERT(uint256_t(b) < 256); + ASSERT(in_tag != AvmMemoryTag::U0 || in_tag != AvmMemoryTag::FF); + uint8_t b_u8 = static_cast(uint256_t(b)); uint256_t c_u256 = a_u256 << b_u8; @@ -878,6 +882,7 @@ FF AvmAluTraceBuilder::op_shl(FF const& a, FF const& b, AvmMemoryTag in_tag, uin if (b_u8 >= num_bits) { u8_pow_2_counters[1][b_u8 - num_bits]++; // Even though the registers are trivially zero, we call this function to increment the lookup counters + // Future workaround would be to decouple the range_check toggle and the counter from this function [[maybe_unused]] auto [alu_u8_r0, alu_u8_r1, alu_u16_reg] = AvmAluTraceBuilder::to_alu_slice_registers(0); alu_trace.push_back(AvmAluTraceBuilder::AluTraceEntry{ .alu_clk = clk, @@ -889,7 +894,7 @@ FF AvmAluTraceBuilder::op_shl(FF const& a, FF const& b, AvmMemoryTag in_tag, uin .alu_u64_tag = in_tag == AvmMemoryTag::U64, .alu_u128_tag = in_tag == AvmMemoryTag::U128, .alu_ia = a, - .alu_ib = FF(b_u8), + .alu_ib = b, .alu_ic = 0, .hi_lo_limbs = { 0, 0, 0, 0 }, .mem_tag_bits = num_bits, @@ -908,7 +913,7 @@ FF AvmAluTraceBuilder::op_shl(FF const& a, FF const& b, AvmMemoryTag in_tag, uin uint256_t rng_chk_lo = uint256_t(uint256_t(1) << (num_bits - b_u8)) - x_lo - 1; uint256_t rng_chk_hi = uint256_t(uint256_t(1) << b_u8) - x_hi - 1; - // Each hi and lo limb is range checked over 128bits + // Each hi and lo limb is range checked over 128 bits uint256_t limb = rng_chk_lo + (rng_chk_hi << 128); // Load the range check values into the ALU registers auto [alu_u8_r0, alu_u8_r1, alu_u16_reg] = AvmAluTraceBuilder::to_alu_slice_registers(limb); @@ -930,10 +935,10 @@ FF AvmAluTraceBuilder::op_shl(FF const& a, FF const& b, AvmMemoryTag in_tag, uin case AvmMemoryTag::U128: c = FF{ uint256_t::from_uint128(uint128_t(c_u256)) }; break; - // Unsupported instruction tags + // Unsupported instruction tags, asserted earlier in function case AvmMemoryTag::U0: case AvmMemoryTag::FF: - return 0; + __builtin_unreachable(); } alu_trace.push_back(AvmAluTraceBuilder::AluTraceEntry{ diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_bitwise.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_bitwise.test.cpp index 379908b06c5..71b8babbfd5 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_bitwise.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_bitwise.test.cpp @@ -116,7 +116,7 @@ void common_validate_shift_op(std::vector const& trace, EXPECT_EQ(row->avm_main_mem_op_a, FF(1)); EXPECT_EQ(row->avm_main_rwa, FF(0)); - // Check that ia register is correctly set with memory load operations. + // Check that ib register is correctly set with memory load operations. EXPECT_EQ(row->avm_main_ib, b); EXPECT_EQ(row->avm_main_mem_idx_b, addr_b); EXPECT_EQ(row->avm_main_mem_op_b, FF(1)); From 52a1631b59297ce062eda14a10e99e552f7fa706 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Tue, 23 Apr 2024 12:16:56 -0300 Subject: [PATCH 087/102] feat!: remove slow updates tree (#5954) With #5885 merged, we are no longer using the slow updates tree and can fully delete it. Docs have already been removed by #5884. --- .../writing_contracts/oracles/pop_capsule.md | 6 +- .../sandbox/references/sandbox-reference.md | 1 - docs/docs/misc/migration_notes.md | 22 ++ noir-projects/aztec-nr/Nargo.toml | 1 - .../aztec-nr/slow-updates-tree/Nargo.toml | 8 - .../aztec-nr/slow-updates-tree/src/leaf.nr | 20 -- .../aztec-nr/slow-updates-tree/src/lib.nr | 8 - .../slow-updates-tree/src/slow_map.nr | 188 ------------------ .../src/slow_update_proof.nr | 52 ----- noir-projects/noir-contracts/Nargo.toml | 1 - .../src/capsule.nr | 3 +- .../src/main.nr | 4 + .../contracts/slow_tree_contract/Nargo.toml | 9 - .../slow_tree_contract/src/capsule.nr | 10 - .../contracts/slow_tree_contract/src/main.nr | 142 ------------- .../contracts/slow_tree_contract/src/types.nr | 33 --- .../token_blacklist_contract/Nargo.toml | 3 +- .../end-to-end/src/e2e_slow_tree.test.ts | 153 -------------- 18 files changed, 32 insertions(+), 632 deletions(-) delete mode 100644 noir-projects/aztec-nr/slow-updates-tree/Nargo.toml delete mode 100644 noir-projects/aztec-nr/slow-updates-tree/src/leaf.nr delete mode 100644 noir-projects/aztec-nr/slow-updates-tree/src/lib.nr delete mode 100644 noir-projects/aztec-nr/slow-updates-tree/src/slow_map.nr delete mode 100644 noir-projects/aztec-nr/slow-updates-tree/src/slow_update_proof.nr delete mode 100644 noir-projects/noir-contracts/contracts/slow_tree_contract/Nargo.toml delete mode 100644 noir-projects/noir-contracts/contracts/slow_tree_contract/src/capsule.nr delete mode 100644 noir-projects/noir-contracts/contracts/slow_tree_contract/src/main.nr delete mode 100644 noir-projects/noir-contracts/contracts/slow_tree_contract/src/types.nr delete mode 100644 yarn-project/end-to-end/src/e2e_slow_tree.test.ts diff --git a/docs/docs/developers/contracts/writing_contracts/oracles/pop_capsule.md b/docs/docs/developers/contracts/writing_contracts/oracles/pop_capsule.md index a364be5d881..6c150b7ec71 100644 --- a/docs/docs/developers/contracts/writing_contracts/oracles/pop_capsule.md +++ b/docs/docs/developers/contracts/writing_contracts/oracles/pop_capsule.md @@ -12,16 +12,16 @@ On this page you will learn how to use the `popCapsule` oracle. To see what othe In a new file on the same level as your `main.nr`, implement an unconstrained function that calls the pop_capsule oracle: -#include_code pop_capsule noir-projects/noir-contracts/contracts/slow_tree_contract/src/capsule.nr rust +#include_code pop_capsule noir-projects/noir-contracts/contracts/contract_class_registerer_contract/src/capsule.nr rust ### 2. Import this into your smart contract If it lies in the same directory as your smart contract, you can import it like this: -#include_code import_pop_capsule noir-projects/noir-contracts/contracts/slow_tree_contract/src/main.nr rust +#include_code import_pop_capsule noir-projects/noir-contracts/contracts/contract_class_registerer_contract/src/main.nr rust ### 3. Use it as any other oracle Now it becomes a regular oracle you can call like this: -#include_code pop_capsule noir-projects/noir-contracts/contracts/slow_tree_contract/src/main.nr rust +#include_code pop_capsule noir-projects/noir-contracts/contracts/contract_class_registerer_contract/src/main.nr rust diff --git a/docs/docs/developers/sandbox/references/sandbox-reference.md b/docs/docs/developers/sandbox/references/sandbox-reference.md index 8ce365cdf2a..512ef3e31af 100644 --- a/docs/docs/developers/sandbox/references/sandbox-reference.md +++ b/docs/docs/developers/sandbox/references/sandbox-reference.md @@ -197,7 +197,6 @@ PriceFeedContractArtifact SchnorrAccountContractArtifact SchnorrHardcodedAccountContractArtifact SchnorrSingleKeyAccountContractArtifact -SlowTreeContractArtifact StatefulTestContractArtifact TestContractArtifact TokenBlacklistContractArtifact diff --git a/docs/docs/misc/migration_notes.md b/docs/docs/misc/migration_notes.md index 731f78a774e..ed02683b00b 100644 --- a/docs/docs/misc/migration_notes.md +++ b/docs/docs/misc/migration_notes.md @@ -8,6 +8,28 @@ Aztec is in full-speed development. Literally every version breaks compatibility ## 0.36.0 +## `SlowUpdatesTree` replaced for `SharedMutable` + +The old `SlowUpdatesTree` contract and libraries have been removed from the codebase, use the new `SharedMutable` library instead. This will require that you add a global variable specifying a delay in blocks for updates, and replace the slow updates tree state variable with `SharedMutable` variables. + +```diff ++ global CHANGE_ROLES_DELAY_BLOCKS = 5; + +struct Storage { +- slow_update: SharedImmutable, ++ roles: Map>, +} +``` + +Reading from `SharedMutable` is much simpler, all that's required is to call `get_current_value_in_public` or `get_current_value_in_private`, depending on the domain. + +```diff +- let caller_roles = UserFlags::new(U128::from_integer(slow.read_at_pub(context.msg_sender().to_field()).call(&mut context))); ++ let caller_roles = storage.roles.at(context.msg_sender()).get_current_value_in_public(); +``` + +Finally, you can remove all capsule usage on the client code or tests, since those are no longer required when working with `SharedMutable`. + ## [Aztec.nr & js] Portal addresses Deployments have been modified. No longer are portal addresses treated as a special class, being immutably set on creation of a contract. They are no longer passed in differently compared to the other variables and instead should be implemented using usual storage by those who require it. One should use the storage that matches the usecase - likely shared storage to support private and public. diff --git a/noir-projects/aztec-nr/Nargo.toml b/noir-projects/aztec-nr/Nargo.toml index 94e4674f336..e3d50c4968d 100644 --- a/noir-projects/aztec-nr/Nargo.toml +++ b/noir-projects/aztec-nr/Nargo.toml @@ -6,7 +6,6 @@ members = [ "compressed-string", "easy-private-state", "field-note", - "slow-updates-tree", "value-note", "tests", ] diff --git a/noir-projects/aztec-nr/slow-updates-tree/Nargo.toml b/noir-projects/aztec-nr/slow-updates-tree/Nargo.toml deleted file mode 100644 index 9460f7c31cf..00000000000 --- a/noir-projects/aztec-nr/slow-updates-tree/Nargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[package] -name = "slow_updates_tree" -authors = ["aztec-labs"] -compiler_version = ">=0.18.0" -type = "lib" - -[dependencies] -aztec = { path = "../aztec" } \ No newline at end of file diff --git a/noir-projects/aztec-nr/slow-updates-tree/src/leaf.nr b/noir-projects/aztec-nr/slow-updates-tree/src/leaf.nr deleted file mode 100644 index e5cda208efb..00000000000 --- a/noir-projects/aztec-nr/slow-updates-tree/src/leaf.nr +++ /dev/null @@ -1,20 +0,0 @@ -use dep::aztec::protocol_types::traits::{Serialize, Deserialize}; - -// A leaf in the tree. -struct Leaf { - next_change: Field, - before: Field, - after: Field, -} - -impl Serialize<3> for Leaf { - fn serialize(leaf: Leaf) -> [Field; 3] { - [leaf.next_change, leaf.before, leaf.after] - } -} - -impl Deserialize<3> for Leaf { - fn deserialize(serialized: [Field; 3]) -> Leaf { - Leaf { next_change: serialized[0], before: serialized[1], after: serialized[2] } - } -} diff --git a/noir-projects/aztec-nr/slow-updates-tree/src/lib.nr b/noir-projects/aztec-nr/slow-updates-tree/src/lib.nr deleted file mode 100644 index b57ed505243..00000000000 --- a/noir-projects/aztec-nr/slow-updates-tree/src/lib.nr +++ /dev/null @@ -1,8 +0,0 @@ -mod leaf; -mod slow_map; -mod slow_update_proof; - -use crate::leaf::Leaf; -use crate::slow_map::SlowMap; -use crate::slow_update_proof::{deserialize_slow_update_proof, SlowUpdateProof}; -use dep::std::merkle::compute_merkle_root; diff --git a/noir-projects/aztec-nr/slow-updates-tree/src/slow_map.nr b/noir-projects/aztec-nr/slow-updates-tree/src/slow_map.nr deleted file mode 100644 index ddfaf6bfa03..00000000000 --- a/noir-projects/aztec-nr/slow-updates-tree/src/slow_map.nr +++ /dev/null @@ -1,188 +0,0 @@ -use crate::{leaf::Leaf, slow_update_proof::SlowUpdateProof}; -use dep::aztec::{ - context::Context, oracle::storage::{storage_read, storage_write}, - protocol_types::traits::{Serialize, Deserialize} -}; -use dep::std::hash::pedersen_hash; -use dep::std::merkle::compute_merkle_root; - -// The epoch length is just a random number for now. -global EPOCH_LENGTH: u64 = 100; - -fn compute_next_change(time: Field) -> Field { - ((time as u64 / EPOCH_LENGTH + 1) * EPOCH_LENGTH) as Field -} - -// TODO(#4760): Rename slow updates to shared mutable and ideally move the impl to state-vars in aztec-nr. -// The simple slow map which stores a sparse tree -struct SlowMap { - context: Context, - storage_slot: Field -} - -impl SlowMap { - pub fn new(context: Context, storage_slot: Field) -> Self { - assert(storage_slot != 0, "Storage slot 0 not allowed. Storage slots must start from 1."); - Self { context, storage_slot } - } - - pub fn read_root(self: Self) -> Leaf { - let fields = storage_read(self.storage_slot); - Leaf::deserialize(fields) - } - - // Beware that the initial root could include much state that is not shown by the public storage! - pub fn initialize(self: Self, initial_root: Field) { - let mut root_object = self.read_root(); - assert(root_object.next_change == 0, "cannot initialize twice"); - root_object = Leaf { - next_change: 0xffffffffffffffffffffffffffffff, - before: initial_root, - after: initial_root, - }; - let fields = root_object.serialize(); - storage_write(self.storage_slot, fields); - } - - // Reads the "CURRENT" value of the root - pub fn current_root(self: Self) -> Field { - let time = self.context.public.unwrap().timestamp(); - let root_object = self.read_root(); - if time <= root_object.next_change as u64 { - root_object.before - } else { - root_object.after - } - } - - // docs:start:read_leaf_at - pub fn read_leaf_at(self: Self, key: Field) -> Leaf { - let derived_storage_slot = pedersen_hash([self.storage_slot, key]); - let fields = storage_read(derived_storage_slot); - Leaf::deserialize(fields) - } - // docs:end:read_leaf_at - - // docs:start:read_at - // Reads the "CURRENT" value of the leaf - pub fn read_at(self: Self, key: Field) -> Field { - let time = self.context.public.unwrap().timestamp(); - let leaf = self.read_leaf_at(key); - if time <= leaf.next_change as u64 { - leaf.before - } else { - leaf.after - } - } - // docs:end:read_at - - // Will update values in the "AFTER" tree - // - updates the leaf and root to follow current values, moving from after to before if - // needed. - // - checks that the provided merkle paths match state values - // - update the leaf and compute the net root - // Should only be used when updates from public are desired, since the hashing will be - // costly since done by sequencer. - pub fn update_at(self: Self, p: SlowUpdateProof) { - // The calling function should ensure that the index is within the tree. - // This must be done separately to ensure we are not constraining too tight here. - - let time = self.context.public.unwrap().timestamp(); - let next_change = compute_next_change(time as Field); - - let mut root = self.read_root(); - let mut leaf = self.read_leaf_at(p.index); - - // Move leaf if needed - if time > leaf.next_change as u64 { - leaf.before = leaf.after; - } - - // Move root if needed - if time > root.next_change as u64 { - root.before = root.after; - } - - // Ensures that when before is active, it is not altered by this update - assert( - root.before == compute_merkle_root(leaf.before, p.index, p.before.sibling_path), "Before root don't match" - ); - - // Ensures that the provided sibling path is valid for the CURRENT "after" tree. - // Without this check, someone could provide a sibling path for a different tree - // and update the entire "after" tree at once, causing it to be out of sync with leaf storage. - assert( - root.after == compute_merkle_root(leaf.after, p.index, p.after.sibling_path), "After root don't match" - ); - - // Update the leaf - leaf.after = p.new_value; - leaf.next_change = next_change; - - // Update the after root - root.after = compute_merkle_root(leaf.after, p.index, p.after.sibling_path); - root.next_change = next_change; - - self.update_unsafe(p.index, leaf, root); - } - - // A variation of `update_at` that skips the merkle-membership checks. - // To be used by a contract which has already checked the merkle-membership. - // This allows us to check the merkle-memberships in private and then update - // in public, limiting the cost of the update. - pub fn update_unsafe_at(self: Self, index: Field, leaf_value: Field, new_root: Field) { - // User must ensure that the checks from update_at is performed for safety - let time = self.context.public.unwrap().timestamp(); - let next_change = compute_next_change(time as Field); - - let mut root = self.read_root(); - let mut leaf = self.read_leaf_at(index); - - // Move leaf if needed - if time > leaf.next_change as u64 { - leaf.before = leaf.after; - } - - // Move root if needed - if time > root.next_change as u64 { - root.before = root.after; - } - - // Update the leaf - leaf.after = leaf_value; - leaf.next_change = next_change; - - // Update the root - root.after = new_root; - root.next_change = next_change; - - self.update_unsafe(index, leaf, root); - } - - // Updates the value in the in storage with no checks. - fn update_unsafe(self: Self, index: Field, leaf: Leaf, root: Leaf) { - let derived_storage_slot = pedersen_hash([self.storage_slot, index]); - let fields = leaf.serialize(); - storage_write(derived_storage_slot, fields); - - let fields = root.serialize(); - storage_write(self.storage_slot, fields); - } -} - -/*pub fn compute_merkle_root(leaf: Field, index: Field, hash_path: [Field; N]) -> Field { - let n = hash_path.len(); - let index_bits = index.to_le_bits(n as u32); - let mut current = leaf; - for i in 0..n { - let path_bit = index_bits[i] as bool; - let (hash_left, hash_right) = if path_bit { - (hash_path[i], current) - } else { - (current, hash_path[i]) - }; - current = pedersen_hash([hash_left, hash_right]); - }; - current -} -*/ diff --git a/noir-projects/aztec-nr/slow-updates-tree/src/slow_update_proof.nr b/noir-projects/aztec-nr/slow-updates-tree/src/slow_update_proof.nr deleted file mode 100644 index 6f1b1d79a0f..00000000000 --- a/noir-projects/aztec-nr/slow-updates-tree/src/slow_update_proof.nr +++ /dev/null @@ -1,52 +0,0 @@ -// Subset of the MembershipProof that is needed for the slow update. -struct SlowUpdateInner { - value: Field, // Value only really used for the private flow though :thinking: - sibling_path: [Field; N], -} - -// The slow update proof. Containing two merkle paths -// One for the before and one for the after trees. -// M = 2 * N + 4 -struct SlowUpdateProof { - index: Field, - new_value: Field, - before: SlowUpdateInner, - after: SlowUpdateInner, -} - -pub fn deserialize_slow_update_proof(serialized: [Field; M]) -> SlowUpdateProof { - SlowUpdateProof::deserialize(serialized) -} - -impl SlowUpdateProof { - pub fn serialize(self: Self) -> [Field; M] { - let mut serialized = [0; M]; - serialized[0] = self.index; - serialized[1] = self.new_value; - serialized[2] = self.before.value; - serialized[3 + N] = self.after.value; - - for i in 0..N { - serialized[3 + i] = self.before.sibling_path[i]; - serialized[4 + N + i] = self.after.sibling_path[i]; - } - serialized - } - - pub fn deserialize(serialized: [Field; M]) -> Self { - let mut before_sibling_path = [0; N]; - let mut after_sibling_path = [0; N]; - - for i in 0..N { - before_sibling_path[i] = serialized[3 + i]; - after_sibling_path[i] = serialized[4 + N + i]; - } - - Self { - index: serialized[0], - new_value: serialized[1], - before: SlowUpdateInner { value: serialized[2], sibling_path: before_sibling_path }, - after: SlowUpdateInner { value: serialized[3 + N], sibling_path: after_sibling_path } - } - } -} diff --git a/noir-projects/noir-contracts/Nargo.toml b/noir-projects/noir-contracts/Nargo.toml index b3d1c57c752..38a37c0083b 100644 --- a/noir-projects/noir-contracts/Nargo.toml +++ b/noir-projects/noir-contracts/Nargo.toml @@ -33,7 +33,6 @@ members = [ "contracts/schnorr_account_contract", "contracts/schnorr_hardcoded_account_contract", "contracts/schnorr_single_key_account_contract", - "contracts/slow_tree_contract", "contracts/stateful_test_contract", "contracts/test_contract", "contracts/token_contract", diff --git a/noir-projects/noir-contracts/contracts/contract_class_registerer_contract/src/capsule.nr b/noir-projects/noir-contracts/contracts/contract_class_registerer_contract/src/capsule.nr index d77649e6b28..8ce37646e61 100644 --- a/noir-projects/noir-contracts/contracts/contract_class_registerer_contract/src/capsule.nr +++ b/noir-projects/noir-contracts/contracts/contract_class_registerer_contract/src/capsule.nr @@ -1,6 +1,6 @@ -// Copied from noir-contracts/contracts/slow_tree_contract/src/capsule.nr // We should extract this to a shared lib in aztec-nr once we settle on a design for capsules +// docs:start:pop_capsule #[oracle(popCapsule)] fn pop_capsule_oracle() -> [Field; N] {} @@ -8,3 +8,4 @@ fn pop_capsule_oracle() -> [Field; N] {} unconstrained pub fn pop_capsule() -> [Field; N] { pop_capsule_oracle() } +// docs:end:pop_capsule \ No newline at end of file diff --git a/noir-projects/noir-contracts/contracts/contract_class_registerer_contract/src/main.nr b/noir-projects/noir-contracts/contracts/contract_class_registerer_contract/src/main.nr index 9857b3e6f3e..8cb01885ccd 100644 --- a/noir-projects/noir-contracts/contracts/contract_class_registerer_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/contract_class_registerer_contract/src/main.nr @@ -18,14 +18,18 @@ contract ContractClassRegisterer { unconstrained_function_broadcasted::{ClassUnconstrainedFunctionBroadcasted, UnconstrainedFunction} }; + // docs:start:import_pop_capsule use crate::capsule::pop_capsule; + // docs:end:import_pop_capsule #[aztec(private)] fn register(artifact_hash: Field, private_functions_root: Field, public_bytecode_commitment: Field) { // TODO: Validate public_bytecode_commitment is the correct commitment of packed_public_bytecode // TODO: Validate packed_public_bytecode is legit public bytecode + // docs:start:pop_capsule let packed_public_bytecode: [Field; MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS] = pop_capsule(); + // docs:end:pop_capsule // Compute contract class id from preimage let contract_class_id = ContractClassId::compute( diff --git a/noir-projects/noir-contracts/contracts/slow_tree_contract/Nargo.toml b/noir-projects/noir-contracts/contracts/slow_tree_contract/Nargo.toml deleted file mode 100644 index 2edcc357b5a..00000000000 --- a/noir-projects/noir-contracts/contracts/slow_tree_contract/Nargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[package] -name = "slow_tree_contract" -authors = [""] -compiler_version = ">=0.25.0" -type = "contract" - -[dependencies] -aztec = { path = "../../../aztec-nr/aztec" } -slow_updates_tree = { path = "../../../aztec-nr/slow-updates-tree" } diff --git a/noir-projects/noir-contracts/contracts/slow_tree_contract/src/capsule.nr b/noir-projects/noir-contracts/contracts/slow_tree_contract/src/capsule.nr deleted file mode 100644 index 7a00e3354f1..00000000000 --- a/noir-projects/noir-contracts/contracts/slow_tree_contract/src/capsule.nr +++ /dev/null @@ -1,10 +0,0 @@ -// docs:start:pop_capsule -#[oracle(popCapsule)] -fn pop_capsule_oracle() -> [Field; N] {} - -// A capsule is a "blob" of data that is passed to the contract through an oracle. -unconstrained pub fn pop_capsule() -> [Field; N] { - pop_capsule_oracle() -} -// docs:end:pop_capsule - diff --git a/noir-projects/noir-contracts/contracts/slow_tree_contract/src/main.nr b/noir-projects/noir-contracts/contracts/slow_tree_contract/src/main.nr deleted file mode 100644 index f71c2ff62c5..00000000000 --- a/noir-projects/noir-contracts/contracts/slow_tree_contract/src/main.nr +++ /dev/null @@ -1,142 +0,0 @@ -mod capsule; -mod types; - -// This contract allow us to "read" public storage in private through a delayed tree. -// More documentation need to be outlined for this properly, but there is some in -// https://github.com/AztecProtocol/aztec-packages/issues/1291 -// This is made as a separate contract for one thing mainly. Making it simpler to use. -// TODO(#4760): Rename slow updates to shared mutable and ideally move the impl to state-vars in aztec-nr. -contract SlowTree { - use dep::aztec::prelude::{ - AztecAddress, FunctionSelector, NoteHeader, NoteInterface, NoteViewerOptions, PrivateContext, - Map, PublicMutable, PrivateSet - }; - - use dep::aztec::{context::{PublicContext, Context}, protocol_types::type_serialization::FIELD_SERIALIZED_LEN}; - use dep::slow_updates_tree::{SlowMap, Leaf, SlowUpdateProof, compute_merkle_root, deserialize_slow_update_proof}; - - // docs:start:import_pop_capsule - use crate::capsule::pop_capsule; - // docs:end:import_pop_capsule - use crate::types::{MembershipProof, deserialize_membership_proof}; - - // docs:start:constants_and_storage - global TREE_HEIGHT: u64 = 254; - global MEMBERSHIP_SIZE: Field = 256; // TREE_HEIGHT + 2 - global UPDATE_SIZE: Field = 512; // TREE_HEIGHT * 2 + 4 - - global EMPTY_ROOT: Field = 5785871043333994658400733180052743689641713274194136017445890613179954325976; - - #[aztec(storage)] - struct Storage { - trees: Map>, - } - // docs:end:constants_and_storage - - // docs:start:initialize - #[aztec(public)] - fn initialize() { - storage.trees.at(context.msg_sender().to_field()).initialize(EMPTY_ROOT); - } - // docs:end:initialize - // docs:start:read_at_pub - #[aztec(public)] - fn read_at_pub(key: Field) -> Field { - storage.trees.at(context.msg_sender().to_field()).read_at(key) - } - // docs:end:read_at_pub - #[aztec(public)] - fn read_leaf_at_pub(key: Field) -> Leaf { - storage.trees.at(context.msg_sender().to_field()).read_leaf_at(key) - } - // docs:start:read_at_private - #[aztec(private)] - fn read_at(index: Field) -> Field { - // docs:start:pop_capsule - let fields = pop_capsule(); - // docs:end:pop_capsule - let p: MembershipProof = deserialize_membership_proof(fields); - assert(index == p.index, "Index does not match expected"); - - let expected_root = compute_merkle_root(p.value, p.index, p.sibling_path); - let selector = FunctionSelector::from_signature("_assert_current_root(Field,Field)"); - context.call_public_function( - context.this_address(), - selector, - [context.msg_sender().to_field(), expected_root] - ); - - p.value - } - // docs:end:read_at_private - // docs:start:assert_current_root - #[aztec(public)] - #[aztec(internal)] - fn _assert_current_root(caller: Field, expected: Field) { - let root = storage.trees.at(caller).current_root(); - assert(root == expected, "Root does not match expected"); - } - // docs:end:assert_current_root - - // docs:start:update_at_pub - #[aztec(public)] - fn update_at_public(p: SlowUpdateProof) { - storage.trees.at(context.msg_sender().to_field()).update_at(p); - } - // docs:end:update_at_pub - // docs:start:update_at_private - #[aztec(private)] - fn update_at_private(index: Field, new_value: Field) { - let fields = pop_capsule(); - let p: SlowUpdateProof = deserialize_slow_update_proof(fields); - assert(index == p.index, "Index does not match expected"); - assert(new_value == p.new_value, "New value does not match expected"); - - // We compute the root before. - let before_root = compute_merkle_root(p.before.value, p.index, p.before.sibling_path); - let after_root = compute_merkle_root(p.after.value, p.index, p.after.sibling_path); - let new_after_root = compute_merkle_root(p.new_value, p.index, p.after.sibling_path); - - let selector = FunctionSelector::from_signature("_update(Field,Field,Field,Field,Field,Field)"); - context.call_public_function( - context.this_address(), - selector, - [ - context.msg_sender().to_field(), - p.index, - p.new_value, - before_root, - after_root, - new_after_root - ] - ); - } - // docs:end:update_at_private - // docs:start:_update - #[aztec(public)] - #[aztec(internal)] - fn _update( - caller: Field, - index: Field, - new_value: Field, - before: Field, - after: Field, - new_root: Field - ) { - let current_root = storage.trees.at(caller).current_root(); - let after_root = storage.trees.at(caller).read_root().after; - - assert(current_root == before, "Before root does not match expected"); - assert(after_root == after, "After root does not match expected"); - - storage.trees.at(caller).update_unsafe_at(index, new_value, new_root); - } - // docs:end:_update - unconstrained fn un_read_leaf_at(address: AztecAddress, key: Field) -> pub Leaf { - storage.trees.at(address.to_field()).read_leaf_at(key) - } - - unconstrained fn un_read_root(address: AztecAddress) -> pub Leaf { - storage.trees.at(address.to_field()).read_root() - } -} diff --git a/noir-projects/noir-contracts/contracts/slow_tree_contract/src/types.nr b/noir-projects/noir-contracts/contracts/slow_tree_contract/src/types.nr deleted file mode 100644 index 58b934e7aa7..00000000000 --- a/noir-projects/noir-contracts/contracts/slow_tree_contract/src/types.nr +++ /dev/null @@ -1,33 +0,0 @@ -// docs:start:membership_proof -// A single inclusion proof. -// M = N + 2 -struct MembershipProof { - index: Field, - value: Field, - sibling_path: [Field; N], -} -// docs:end:membership_proof - -fn deserialize_membership_proof(serialized: [Field; M]) -> MembershipProof { - let mut sibling_path = [0; N]; - for i in 0..N { - sibling_path[i] = serialized[2 + i]; - } - MembershipProof { index: serialized[0], value: serialized[1], sibling_path } -} - -impl MembershipProof { - fn serialize(self: Self) -> [Field; M] { - let mut serialized = [0; M]; - serialized[0] = self.index; - serialized[1] = self.value; - for i in 0..N { - serialized[2 + i] = self.sibling_path[i]; - } - serialized - } - - fn deserialize(serialized: [Field; M]) -> Self { - deserialize_membership_proof(serialized) - } -} diff --git a/noir-projects/noir-contracts/contracts/token_blacklist_contract/Nargo.toml b/noir-projects/noir-contracts/contracts/token_blacklist_contract/Nargo.toml index 54bc420b804..ee4f8aa622b 100644 --- a/noir-projects/noir-contracts/contracts/token_blacklist_contract/Nargo.toml +++ b/noir-projects/noir-contracts/contracts/token_blacklist_contract/Nargo.toml @@ -7,5 +7,4 @@ type = "contract" [dependencies] aztec = { path = "../../../aztec-nr/aztec" } field_note = { path = "../../../aztec-nr/field-note" } -authwit = { path = "../../../aztec-nr/authwit" } -slow_tree = { path = "../slow_tree_contract" } \ No newline at end of file +authwit = { path = "../../../aztec-nr/authwit" } \ No newline at end of file diff --git a/yarn-project/end-to-end/src/e2e_slow_tree.test.ts b/yarn-project/end-to-end/src/e2e_slow_tree.test.ts deleted file mode 100644 index e853e125f65..00000000000 --- a/yarn-project/end-to-end/src/e2e_slow_tree.test.ts +++ /dev/null @@ -1,153 +0,0 @@ -/* eslint-disable camelcase */ -import { type CheatCodes, type DebugLogger, Fr, type Wallet } from '@aztec/aztec.js'; -import { openTmpStore } from '@aztec/kv-store/utils'; -import { Pedersen, SparseTree, newTree } from '@aztec/merkle-tree'; -import { SlowTreeContract } from '@aztec/noir-contracts.js/SlowTree'; - -import { setup } from './fixtures/utils.js'; - -describe.skip('e2e_slow_tree', () => { - let logger: DebugLogger; - let wallet: Wallet; - let teardown: () => Promise; - - let contract: SlowTreeContract; - let cheatCodes: CheatCodes; - - beforeAll(async () => { - ({ teardown, logger, wallet, cheatCodes } = await setup()); - contract = await SlowTreeContract.deploy(wallet).send().deployed(); - }, 100_000); - - afterAll(() => teardown()); - - it('Messing around with noir slow tree', async () => { - const depth = 254; - const slowUpdateTreeSimulator = await newTree(SparseTree, openTmpStore(), new Pedersen(), 'test', Fr, depth); - const getMembershipProof = async (index: bigint, includeUncommitted: boolean) => { - return { - index, - value: slowUpdateTreeSimulator.getLeafValue(index, includeUncommitted)!, - // eslint-disable-next-line camelcase - sibling_path: (await slowUpdateTreeSimulator.getSiblingPath(index, includeUncommitted)).toFields(), - }; - }; - - const getMembershipCapsule = (proof: { index: bigint; value: Fr; sibling_path: Fr[] }) => { - return [new Fr(proof.index), proof.value, ...proof.sibling_path]; - }; - - const getUpdateProof = async (newValue: bigint, index: bigint) => { - const beforeProof = await getMembershipProof(index, false); - const afterProof = await getMembershipProof(index, true); - - return { - index, - // eslint-disable-next-line camelcase - new_value: newValue, - // eslint-disable-next-line camelcase - before: { value: beforeProof.value, sibling_path: beforeProof.sibling_path }, - // eslint-disable-next-line camelcase - after: { value: afterProof.value, sibling_path: afterProof.sibling_path }, - }; - }; - - const getUpdateCapsule = (proof: { - index: bigint; - new_value: bigint; - before: { value: Fr; sibling_path: Fr[] }; - after: { value: Fr; sibling_path: Fr[] }; - }) => { - return [ - new Fr(proof.index), - new Fr(proof.new_value), - proof.before.value, - ...proof.before.sibling_path, - proof.after.value, - ...proof.after.sibling_path, - ]; - }; - - const status = async ( - key: bigint, - _root: { before: bigint; after: bigint; next_change: bigint }, - _leaf: { before: bigint; after: bigint; next_change: bigint }, - ) => { - const root = await contract.methods.un_read_root(owner).simulate(); - const leaf = await contract.methods.un_read_leaf_at(owner, key).simulate(); - expect(root).toEqual(_root); - expect(leaf).toEqual(_leaf); - }; - - const owner = wallet.getCompleteAddress().address; - const key = owner.toBigInt(); - - await contract.methods.initialize().send().wait(); - - const computeNextChange = (ts: bigint) => (ts / 100n + 1n) * 100n; - - let _root = { - before: Fr.fromBuffer(slowUpdateTreeSimulator.getRoot(true)).toBigInt(), - after: Fr.fromBuffer(slowUpdateTreeSimulator.getRoot(true)).toBigInt(), - next_change: 2n ** 120n - 1n, - }; - let _leaf = { before: 0n, after: 0n, next_change: 0n }; - await status(key, _root, _leaf); - await wallet.addCapsule(getMembershipCapsule(await getMembershipProof(key, true))); - await contract.methods.read_at(key).send().wait(); - - logger.info(`Updating tree[${key}] to 1 from public`); - const t1 = computeNextChange(BigInt(await cheatCodes.eth.timestamp())); - await contract.methods - .update_at_public(await getUpdateProof(1n, key)) - .send() - .wait(); - await slowUpdateTreeSimulator.updateLeaf(new Fr(1), key); - - // Update below. - _root = { - ..._root, - after: Fr.fromBuffer(slowUpdateTreeSimulator.getRoot(true)).toBigInt(), - next_change: t1, - }; - _leaf = { ..._leaf, after: 1n, next_change: t1 }; - await status(key, _root, _leaf); - - const zeroProof = await getMembershipProof(key, false); - logger.info(`"Reads" tree[${zeroProof.index}] from the tree, equal to ${zeroProof.value}`); - await wallet.addCapsule(getMembershipCapsule({ ...zeroProof, value: new Fr(0) })); - await contract.methods.read_at(key).send().wait(); - - // Progress time to beyond the update and thereby commit it to the tree. - await cheatCodes.aztec.warp((await cheatCodes.eth.timestamp()) + 1000); - await slowUpdateTreeSimulator.commit(); - logger.info('--- Progressing time to after the update ---'); - await status(key, _root, _leaf); - - logger.info( - `Tries to "read" tree[${zeroProof.index}] from the tree, but is rejected as value is not ${zeroProof.value}`, - ); - await wallet.addCapsule(getMembershipCapsule({ ...zeroProof, value: new Fr(0) })); - await expect(contract.methods.read_at(key).prove()).rejects.toThrow( - /Assertion failed: Root does not match expected/, - ); - - logger.info(`"Reads" tree[${key}], expect to be 1`); - await wallet.addCapsule(getMembershipCapsule({ ...zeroProof, value: new Fr(1) })); - await contract.methods.read_at(key).send().wait(); - - logger.info(`Updating tree[${key}] to 4 from private`); - const t2 = computeNextChange(BigInt(await cheatCodes.eth.timestamp())); - await wallet.addCapsule(getUpdateCapsule(await getUpdateProof(4n, key))); - await contract.methods.update_at_private(key, 4n).send().wait(); - await slowUpdateTreeSimulator.updateLeaf(new Fr(4), key); - _root = { - before: Fr.fromBuffer(slowUpdateTreeSimulator.getRoot(false)).toBigInt(), - after: Fr.fromBuffer(slowUpdateTreeSimulator.getRoot(true)).toBigInt(), - next_change: t2, - }; - _leaf = { before: 1n, after: 4n, next_change: t2 }; - - await status(key, _root, _leaf); - }, 200_000); -}); From fed5b6dd1ee310fc90404a3e5ec9eb02ad7dbc10 Mon Sep 17 00:00:00 2001 From: Jean M <132435771+jeanmon@users.noreply.github.com> Date: Tue, 23 Apr 2024 17:39:15 +0200 Subject: [PATCH 088/102] feat(avm): avm circuit FDIV opcode (#5958) Resolves #5953 --- barretenberg/cpp/pil/avm/avm_main.pil | 50 ++-- .../relations/generated/avm/avm_main.hpp | 248 ++++++++++-------- .../relations/generated/avm/declare_views.hpp | 1 + .../relations/generated/avm/perm_main_alu.hpp | 6 +- .../vm/avm_trace/avm_deserialization.cpp | 1 + .../vm/avm_trace/avm_execution.cpp | 11 +- .../barretenberg/vm/avm_trace/avm_trace.cpp | 24 +- .../barretenberg/vm/avm_trace/avm_trace.hpp | 4 +- .../vm/generated/avm_circuit_builder.hpp | 6 +- .../barretenberg/vm/generated/avm_flavor.hpp | 13 +- .../barretenberg/vm/generated/avm_prover.cpp | 2 + .../vm/generated/avm_verifier.cpp | 2 + .../vm/tests/avm_arithmetic.test.cpp | 135 ++++++---- .../vm/tests/avm_execution.test.cpp | 13 +- .../barretenberg/vm/tests/avm_memory.test.cpp | 16 +- 15 files changed, 316 insertions(+), 216 deletions(-) diff --git a/barretenberg/cpp/pil/avm/avm_main.pil b/barretenberg/cpp/pil/avm/avm_main.pil index 74ce4b93574..42141360f38 100644 --- a/barretenberg/cpp/pil/avm/avm_main.pil +++ b/barretenberg/cpp/pil/avm/avm_main.pil @@ -47,6 +47,8 @@ namespace avm_main(256); pol commit sel_op_mul; // DIV pol commit sel_op_div; + // FDIV + pol commit sel_op_fdiv; // NOT pol commit sel_op_not; // EQ @@ -137,6 +139,7 @@ namespace avm_main(256); sel_op_sub * (1 - sel_op_sub) = 0; sel_op_mul * (1 - sel_op_mul) = 0; sel_op_div * (1 - sel_op_div) = 0; + sel_op_fdiv * (1 - sel_op_fdiv) = 0; sel_op_not * (1 - sel_op_not) = 0; sel_op_eq * (1 - sel_op_eq) = 0; sel_op_and * (1 - sel_op_and) = 0; @@ -188,39 +191,48 @@ namespace avm_main(256); #[OUTPUT_U8] (sel_op_eq + sel_op_lte + sel_op_lt) * (w_in_tag - 1) = 0; + //====== FDIV OPCODE CONSTRAINTS ============================================ // Relation for division over the finite field // If tag_err == 1 in a division, then ib == 0 and op_err == 1. - #[SUBOP_DIVISION_FF] - sel_op_div * (1 - op_err) * (ic * ib - ia) = 0; + #[SUBOP_FDIV] + sel_op_fdiv * (1 - op_err) * (ic * ib - ia) = 0; - // When sel_op_div == 1, we want ib == 0 <==> op_err == 1 + // When sel_op_fdiv == 1, we want ib == 0 <==> op_err == 1 // This can be achieved with the 2 following relations. // inv is an extra witness to show that we can invert ib, i.e., inv = ib^(-1) // If ib == 0, we have to set inv = 1 to satisfy the second relation, // because op_err == 1 from the first relation. - #[SUBOP_DIVISION_ZERO_ERR1] - sel_op_div * (ib * inv - 1 + op_err) = 0; - #[SUBOP_DIVISION_ZERO_ERR2] - sel_op_div * op_err * (1 - inv) = 0; + #[SUBOP_FDIV_ZERO_ERR1] + sel_op_fdiv * (ib * inv - 1 + op_err) = 0; + #[SUBOP_FDIV_ZERO_ERR2] + sel_op_fdiv * op_err * (1 - inv) = 0; + + // Enforcement that instruction tags are FF (tag constant 6). + // TODO: These 2 conditions might be removed and enforced through + // the bytecode decomposition instead. + #[SUBOP_FDIV_R_IN_TAG_FF] + sel_op_fdiv * (r_in_tag - 6) = 0; + #[SUBOP_FDIV_W_IN_TAG_FF] + sel_op_fdiv * (w_in_tag - 6) = 0; // op_err cannot be maliciously activated for a non-relevant - // operation selector, i.e., op_err == 1 ==> sel_op_div || sel_op_XXX || ... - // op_err * (sel_op_div + sel_op_XXX + ... - 1) == 0 + // operation selector, i.e., op_err == 1 ==> sel_op_fdiv || sel_op_XXX || ... + // op_err * (sel_op_fdiv + sel_op_XXX + ... - 1) == 0 // Note that the above is even a stronger constraint, as it shows // that exactly one sel_op_XXX must be true. // At this time, we have only division producing an error. #[SUBOP_ERROR_RELEVANT_OP] - op_err * (sel_op_div - 1) = 0; + op_err * (sel_op_fdiv - 1) = 0; // TODO: constraint that we stop execution at the first error (tag_err or op_err) // An error can only happen at the last sub-operation row. // OPEN/POTENTIAL OPTIMIZATION: Dedicated error per relevant operation? - // For the division, we could lower the degree from 4 to 3 - // (sel_op_div - op_div_err) * (ic * ib - ia) = 0; + // For the finite field division, we could lower the degree from 4 to 3 + // (sel_op_fdiv - op_fdiv_err) * (ic * ib - ia) = 0; // Same for the relations related to the error activation: - // (ib * inv - 1 + op_div_err) = 0 && op_err * (1 - inv) = 0 - // This works in combination with op_div_err * (sel_op_div - 1) = 0; + // (ib * inv - 1 + op_fdiv_err) = 0 && op_err * (1 - inv) = 0 + // This works in combination with op_fdiv_err * (sel_op_fdiv - 1) = 0; // Drawback is the need to paralllelize the latter. //===== CONTROL FLOW ======================================================= @@ -257,7 +269,7 @@ namespace avm_main(256); //===== CONTROL_FLOW_CONSISTENCY ============================================ pol INTERNAL_CALL_STACK_SELECTORS = (first + sel_internal_call + sel_internal_return + sel_halt); - pol OPCODE_SELECTORS = (sel_op_add + sel_op_sub + sel_op_div + sel_op_mul + sel_op_not + pol OPCODE_SELECTORS = (sel_op_add + sel_op_sub + sel_op_div + sel_op_fdiv + sel_op_mul + sel_op_not + sel_op_eq + sel_op_and + sel_op_or + sel_op_xor + sel_op_cast); // Program counter must increment if not jumping or returning @@ -303,8 +315,8 @@ namespace avm_main(256); (sel_mov + sel_cmov) * (r_in_tag - w_in_tag) = 0; //===== ALU CONSTRAINTS ===================================================== - // TODO: when division is moved to the alu, we will need to add the selector in the list below. - pol ALU_R_TAG_SEL = sel_op_add + sel_op_sub + sel_op_mul + sel_op_not + sel_op_eq + sel_op_lt + sel_op_lte + sel_op_shr + sel_op_shl; + pol ALU_R_TAG_SEL = sel_op_add + sel_op_sub + sel_op_mul + sel_op_div + sel_op_not + sel_op_eq + + sel_op_lt + sel_op_lte + sel_op_shr + sel_op_shl; pol ALU_W_TAG_SEL = sel_op_cast; pol ALU_ALL_SEL = ALU_R_TAG_SEL + ALU_W_TAG_SEL; @@ -325,11 +337,11 @@ namespace avm_main(256); #[PERM_MAIN_ALU] alu_sel {clk, ia, ib, ic, sel_op_add, sel_op_sub, - sel_op_mul, sel_op_eq, sel_op_not, sel_op_cast, + sel_op_mul, sel_op_div, sel_op_eq, sel_op_not, sel_op_cast, sel_op_lt, sel_op_lte, sel_op_shr, sel_op_shl, alu_in_tag} is avm_alu.alu_sel {avm_alu.clk, avm_alu.ia, avm_alu.ib, avm_alu.ic, avm_alu.op_add, avm_alu.op_sub, - avm_alu.op_mul, avm_alu.op_eq, avm_alu.op_not, avm_alu.op_cast, + avm_alu.op_mul, avm_alu.op_div, avm_alu.op_eq, avm_alu.op_not, avm_alu.op_cast, avm_alu.op_lt, avm_alu.op_lte, avm_alu.op_shr, avm_alu.op_shl, avm_alu.in_tag}; // Based on the boolean selectors, we derive the binary op id to lookup in the table; diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/avm_main.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/avm_main.hpp index 93ab5869174..681210ee41d 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/avm_main.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/avm_main.hpp @@ -51,6 +51,7 @@ template struct Avm_mainRow { FF avm_main_sel_op_cast{}; FF avm_main_sel_op_div{}; FF avm_main_sel_op_eq{}; + FF avm_main_sel_op_fdiv{}; FF avm_main_sel_op_lt{}; FF avm_main_sel_op_lte{}; FF avm_main_sel_op_mul{}; @@ -67,52 +68,58 @@ template struct Avm_mainRow { inline std::string get_relation_label_avm_main(int index) { switch (index) { - case 35: - return "OUTPUT_U8"; - case 36: - return "SUBOP_DIVISION_FF"; + return "OUTPUT_U8"; case 37: - return "SUBOP_DIVISION_ZERO_ERR1"; + return "SUBOP_FDIV"; case 38: - return "SUBOP_DIVISION_ZERO_ERR2"; + return "SUBOP_FDIV_ZERO_ERR1"; case 39: - return "SUBOP_ERROR_RELEVANT_OP"; + return "SUBOP_FDIV_ZERO_ERR2"; + + case 40: + return "SUBOP_FDIV_R_IN_TAG_FF"; case 41: + return "SUBOP_FDIV_W_IN_TAG_FF"; + + case 42: + return "SUBOP_ERROR_RELEVANT_OP"; + + case 44: return "RETURN_POINTER_INCREMENT"; - case 47: + case 50: return "RETURN_POINTER_DECREMENT"; - case 52: + case 55: return "PC_INCREMENT"; - case 53: + case 56: return "INTERNAL_RETURN_POINTER_CONSISTENCY"; - case 54: + case 57: return "CMOV_CONDITION_RES_1"; - case 55: + case 58: return "CMOV_CONDITION_RES_2"; - case 58: + case 61: return "MOV_SAME_VALUE_A"; - case 59: + case 62: return "MOV_SAME_VALUE_B"; - case 60: + case 63: return "MOV_MAIN_SAME_TAG"; - case 64: + case 67: return "BIN_SEL_1"; - case 65: + case 68: return "BIN_SEL_2"; } return std::to_string(index); @@ -122,9 +129,9 @@ template class avm_mainImpl { public: using FF = FF_; - static constexpr std::array SUBRELATION_PARTIAL_LENGTHS{ - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 5, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 3, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, + static constexpr std::array SUBRELATION_PARTIAL_LENGTHS{ + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 5, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 3, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, }; template @@ -170,7 +177,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(4); - auto tmp = (avm_main_sel_op_not * (-avm_main_sel_op_not + FF(1))); + auto tmp = (avm_main_sel_op_fdiv * (-avm_main_sel_op_fdiv + FF(1))); tmp *= scaling_factor; std::get<4>(evals) += tmp; } @@ -178,7 +185,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(5); - auto tmp = (avm_main_sel_op_eq * (-avm_main_sel_op_eq + FF(1))); + auto tmp = (avm_main_sel_op_not * (-avm_main_sel_op_not + FF(1))); tmp *= scaling_factor; std::get<5>(evals) += tmp; } @@ -186,7 +193,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(6); - auto tmp = (avm_main_sel_op_and * (-avm_main_sel_op_and + FF(1))); + auto tmp = (avm_main_sel_op_eq * (-avm_main_sel_op_eq + FF(1))); tmp *= scaling_factor; std::get<6>(evals) += tmp; } @@ -194,7 +201,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(7); - auto tmp = (avm_main_sel_op_or * (-avm_main_sel_op_or + FF(1))); + auto tmp = (avm_main_sel_op_and * (-avm_main_sel_op_and + FF(1))); tmp *= scaling_factor; std::get<7>(evals) += tmp; } @@ -202,7 +209,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(8); - auto tmp = (avm_main_sel_op_xor * (-avm_main_sel_op_xor + FF(1))); + auto tmp = (avm_main_sel_op_or * (-avm_main_sel_op_or + FF(1))); tmp *= scaling_factor; std::get<8>(evals) += tmp; } @@ -210,7 +217,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(9); - auto tmp = (avm_main_sel_op_cast * (-avm_main_sel_op_cast + FF(1))); + auto tmp = (avm_main_sel_op_xor * (-avm_main_sel_op_xor + FF(1))); tmp *= scaling_factor; std::get<9>(evals) += tmp; } @@ -218,7 +225,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(10); - auto tmp = (avm_main_sel_op_lt * (-avm_main_sel_op_lt + FF(1))); + auto tmp = (avm_main_sel_op_cast * (-avm_main_sel_op_cast + FF(1))); tmp *= scaling_factor; std::get<10>(evals) += tmp; } @@ -226,7 +233,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(11); - auto tmp = (avm_main_sel_op_lte * (-avm_main_sel_op_lte + FF(1))); + auto tmp = (avm_main_sel_op_lt * (-avm_main_sel_op_lt + FF(1))); tmp *= scaling_factor; std::get<11>(evals) += tmp; } @@ -234,7 +241,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(12); - auto tmp = (avm_main_sel_op_shl * (-avm_main_sel_op_shl + FF(1))); + auto tmp = (avm_main_sel_op_lte * (-avm_main_sel_op_lte + FF(1))); tmp *= scaling_factor; std::get<12>(evals) += tmp; } @@ -242,7 +249,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(13); - auto tmp = (avm_main_sel_op_shr * (-avm_main_sel_op_shr + FF(1))); + auto tmp = (avm_main_sel_op_shl * (-avm_main_sel_op_shl + FF(1))); tmp *= scaling_factor; std::get<13>(evals) += tmp; } @@ -250,7 +257,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(14); - auto tmp = (avm_main_sel_internal_call * (-avm_main_sel_internal_call + FF(1))); + auto tmp = (avm_main_sel_op_shr * (-avm_main_sel_op_shr + FF(1))); tmp *= scaling_factor; std::get<14>(evals) += tmp; } @@ -258,7 +265,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(15); - auto tmp = (avm_main_sel_internal_return * (-avm_main_sel_internal_return + FF(1))); + auto tmp = (avm_main_sel_internal_call * (-avm_main_sel_internal_call + FF(1))); tmp *= scaling_factor; std::get<15>(evals) += tmp; } @@ -266,7 +273,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(16); - auto tmp = (avm_main_sel_jump * (-avm_main_sel_jump + FF(1))); + auto tmp = (avm_main_sel_internal_return * (-avm_main_sel_internal_return + FF(1))); tmp *= scaling_factor; std::get<16>(evals) += tmp; } @@ -274,7 +281,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(17); - auto tmp = (avm_main_sel_halt * (-avm_main_sel_halt + FF(1))); + auto tmp = (avm_main_sel_jump * (-avm_main_sel_jump + FF(1))); tmp *= scaling_factor; std::get<17>(evals) += tmp; } @@ -282,7 +289,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(18); - auto tmp = (avm_main_sel_mov * (-avm_main_sel_mov + FF(1))); + auto tmp = (avm_main_sel_halt * (-avm_main_sel_halt + FF(1))); tmp *= scaling_factor; std::get<18>(evals) += tmp; } @@ -290,7 +297,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(19); - auto tmp = (avm_main_sel_cmov * (-avm_main_sel_cmov + FF(1))); + auto tmp = (avm_main_sel_mov * (-avm_main_sel_mov + FF(1))); tmp *= scaling_factor; std::get<19>(evals) += tmp; } @@ -298,7 +305,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(20); - auto tmp = (avm_main_op_err * (-avm_main_op_err + FF(1))); + auto tmp = (avm_main_sel_cmov * (-avm_main_sel_cmov + FF(1))); tmp *= scaling_factor; std::get<20>(evals) += tmp; } @@ -306,7 +313,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(21); - auto tmp = (avm_main_tag_err * (-avm_main_tag_err + FF(1))); + auto tmp = (avm_main_op_err * (-avm_main_op_err + FF(1))); tmp *= scaling_factor; std::get<21>(evals) += tmp; } @@ -314,7 +321,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(22); - auto tmp = (avm_main_id_zero * (-avm_main_id_zero + FF(1))); + auto tmp = (avm_main_tag_err * (-avm_main_tag_err + FF(1))); tmp *= scaling_factor; std::get<22>(evals) += tmp; } @@ -322,7 +329,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(23); - auto tmp = (avm_main_mem_op_a * (-avm_main_mem_op_a + FF(1))); + auto tmp = (avm_main_id_zero * (-avm_main_id_zero + FF(1))); tmp *= scaling_factor; std::get<23>(evals) += tmp; } @@ -330,7 +337,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(24); - auto tmp = (avm_main_mem_op_b * (-avm_main_mem_op_b + FF(1))); + auto tmp = (avm_main_mem_op_a * (-avm_main_mem_op_a + FF(1))); tmp *= scaling_factor; std::get<24>(evals) += tmp; } @@ -338,7 +345,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(25); - auto tmp = (avm_main_mem_op_c * (-avm_main_mem_op_c + FF(1))); + auto tmp = (avm_main_mem_op_b * (-avm_main_mem_op_b + FF(1))); tmp *= scaling_factor; std::get<25>(evals) += tmp; } @@ -346,7 +353,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(26); - auto tmp = (avm_main_mem_op_d * (-avm_main_mem_op_d + FF(1))); + auto tmp = (avm_main_mem_op_c * (-avm_main_mem_op_c + FF(1))); tmp *= scaling_factor; std::get<26>(evals) += tmp; } @@ -354,7 +361,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(27); - auto tmp = (avm_main_rwa * (-avm_main_rwa + FF(1))); + auto tmp = (avm_main_mem_op_d * (-avm_main_mem_op_d + FF(1))); tmp *= scaling_factor; std::get<27>(evals) += tmp; } @@ -362,7 +369,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(28); - auto tmp = (avm_main_rwb * (-avm_main_rwb + FF(1))); + auto tmp = (avm_main_rwa * (-avm_main_rwa + FF(1))); tmp *= scaling_factor; std::get<28>(evals) += tmp; } @@ -370,7 +377,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(29); - auto tmp = (avm_main_rwc * (-avm_main_rwc + FF(1))); + auto tmp = (avm_main_rwb * (-avm_main_rwb + FF(1))); tmp *= scaling_factor; std::get<29>(evals) += tmp; } @@ -378,7 +385,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(30); - auto tmp = (avm_main_rwd * (-avm_main_rwd + FF(1))); + auto tmp = (avm_main_rwc * (-avm_main_rwc + FF(1))); tmp *= scaling_factor; std::get<30>(evals) += tmp; } @@ -386,7 +393,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(31); - auto tmp = (avm_main_ind_op_a * (-avm_main_ind_op_a + FF(1))); + auto tmp = (avm_main_rwd * (-avm_main_rwd + FF(1))); tmp *= scaling_factor; std::get<31>(evals) += tmp; } @@ -394,7 +401,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(32); - auto tmp = (avm_main_ind_op_b * (-avm_main_ind_op_b + FF(1))); + auto tmp = (avm_main_ind_op_a * (-avm_main_ind_op_a + FF(1))); tmp *= scaling_factor; std::get<32>(evals) += tmp; } @@ -402,7 +409,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(33); - auto tmp = (avm_main_ind_op_c * (-avm_main_ind_op_c + FF(1))); + auto tmp = (avm_main_ind_op_b * (-avm_main_ind_op_b + FF(1))); tmp *= scaling_factor; std::get<33>(evals) += tmp; } @@ -410,7 +417,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(34); - auto tmp = (avm_main_ind_op_d * (-avm_main_ind_op_d + FF(1))); + auto tmp = (avm_main_ind_op_c * (-avm_main_ind_op_c + FF(1))); tmp *= scaling_factor; std::get<34>(evals) += tmp; } @@ -418,8 +425,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(35); - auto tmp = - (((avm_main_sel_op_eq + avm_main_sel_op_lte) + avm_main_sel_op_lt) * (avm_main_w_in_tag - FF(1))); + auto tmp = (avm_main_ind_op_d * (-avm_main_ind_op_d + FF(1))); tmp *= scaling_factor; std::get<35>(evals) += tmp; } @@ -428,7 +434,7 @@ template class avm_mainImpl { Avm_DECLARE_VIEWS(36); auto tmp = - ((avm_main_sel_op_div * (-avm_main_op_err + FF(1))) * ((avm_main_ic * avm_main_ib) - avm_main_ia)); + (((avm_main_sel_op_eq + avm_main_sel_op_lte) + avm_main_sel_op_lt) * (avm_main_w_in_tag - FF(1))); tmp *= scaling_factor; std::get<36>(evals) += tmp; } @@ -436,7 +442,8 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(37); - auto tmp = (avm_main_sel_op_div * (((avm_main_ib * avm_main_inv) - FF(1)) + avm_main_op_err)); + auto tmp = + ((avm_main_sel_op_fdiv * (-avm_main_op_err + FF(1))) * ((avm_main_ic * avm_main_ib) - avm_main_ia)); tmp *= scaling_factor; std::get<37>(evals) += tmp; } @@ -444,7 +451,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(38); - auto tmp = ((avm_main_sel_op_div * avm_main_op_err) * (-avm_main_inv + FF(1))); + auto tmp = (avm_main_sel_op_fdiv * (((avm_main_ib * avm_main_inv) - FF(1)) + avm_main_op_err)); tmp *= scaling_factor; std::get<38>(evals) += tmp; } @@ -452,7 +459,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(39); - auto tmp = (avm_main_op_err * (avm_main_sel_op_div - FF(1))); + auto tmp = ((avm_main_sel_op_fdiv * avm_main_op_err) * (-avm_main_inv + FF(1))); tmp *= scaling_factor; std::get<39>(evals) += tmp; } @@ -460,7 +467,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(40); - auto tmp = (avm_main_sel_jump * (avm_main_pc_shift - avm_main_ia)); + auto tmp = (avm_main_sel_op_fdiv * (avm_main_r_in_tag - FF(6))); tmp *= scaling_factor; std::get<40>(evals) += tmp; } @@ -468,8 +475,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(41); - auto tmp = (avm_main_sel_internal_call * - (avm_main_internal_return_ptr_shift - (avm_main_internal_return_ptr + FF(1)))); + auto tmp = (avm_main_sel_op_fdiv * (avm_main_w_in_tag - FF(6))); tmp *= scaling_factor; std::get<41>(evals) += tmp; } @@ -477,7 +483,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(42); - auto tmp = (avm_main_sel_internal_call * (avm_main_internal_return_ptr - avm_main_mem_idx_b)); + auto tmp = (avm_main_op_err * (avm_main_sel_op_fdiv - FF(1))); tmp *= scaling_factor; std::get<42>(evals) += tmp; } @@ -485,7 +491,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(43); - auto tmp = (avm_main_sel_internal_call * (avm_main_pc_shift - avm_main_ia)); + auto tmp = (avm_main_sel_jump * (avm_main_pc_shift - avm_main_ia)); tmp *= scaling_factor; std::get<43>(evals) += tmp; } @@ -493,7 +499,8 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(44); - auto tmp = (avm_main_sel_internal_call * ((avm_main_pc + FF(1)) - avm_main_ib)); + auto tmp = (avm_main_sel_internal_call * + (avm_main_internal_return_ptr_shift - (avm_main_internal_return_ptr + FF(1)))); tmp *= scaling_factor; std::get<44>(evals) += tmp; } @@ -501,7 +508,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(45); - auto tmp = (avm_main_sel_internal_call * (avm_main_rwb - FF(1))); + auto tmp = (avm_main_sel_internal_call * (avm_main_internal_return_ptr - avm_main_mem_idx_b)); tmp *= scaling_factor; std::get<45>(evals) += tmp; } @@ -509,7 +516,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(46); - auto tmp = (avm_main_sel_internal_call * (avm_main_mem_op_b - FF(1))); + auto tmp = (avm_main_sel_internal_call * (avm_main_pc_shift - avm_main_ia)); tmp *= scaling_factor; std::get<46>(evals) += tmp; } @@ -517,8 +524,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(47); - auto tmp = (avm_main_sel_internal_return * - (avm_main_internal_return_ptr_shift - (avm_main_internal_return_ptr - FF(1)))); + auto tmp = (avm_main_sel_internal_call * ((avm_main_pc + FF(1)) - avm_main_ib)); tmp *= scaling_factor; std::get<47>(evals) += tmp; } @@ -526,7 +532,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(48); - auto tmp = (avm_main_sel_internal_return * ((avm_main_internal_return_ptr - FF(1)) - avm_main_mem_idx_a)); + auto tmp = (avm_main_sel_internal_call * (avm_main_rwb - FF(1))); tmp *= scaling_factor; std::get<48>(evals) += tmp; } @@ -534,7 +540,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(49); - auto tmp = (avm_main_sel_internal_return * (avm_main_pc_shift - avm_main_ia)); + auto tmp = (avm_main_sel_internal_call * (avm_main_mem_op_b - FF(1))); tmp *= scaling_factor; std::get<49>(evals) += tmp; } @@ -542,7 +548,8 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(50); - auto tmp = (avm_main_sel_internal_return * avm_main_rwa); + auto tmp = (avm_main_sel_internal_return * + (avm_main_internal_return_ptr_shift - (avm_main_internal_return_ptr - FF(1)))); tmp *= scaling_factor; std::get<50>(evals) += tmp; } @@ -550,7 +557,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(51); - auto tmp = (avm_main_sel_internal_return * (avm_main_mem_op_a - FF(1))); + auto tmp = (avm_main_sel_internal_return * ((avm_main_internal_return_ptr - FF(1)) - avm_main_mem_idx_a)); tmp *= scaling_factor; std::get<51>(evals) += tmp; } @@ -558,16 +565,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(52); - auto tmp = - ((((-avm_main_first + FF(1)) * (-avm_main_sel_halt + FF(1))) * - (((((((((avm_main_sel_op_add + avm_main_sel_op_sub) + avm_main_sel_op_div) + avm_main_sel_op_mul) + - avm_main_sel_op_not) + - avm_main_sel_op_eq) + - avm_main_sel_op_and) + - avm_main_sel_op_or) + - avm_main_sel_op_xor) + - avm_main_sel_op_cast)) * - (avm_main_pc_shift - (avm_main_pc + FF(1)))); + auto tmp = (avm_main_sel_internal_return * (avm_main_pc_shift - avm_main_ia)); tmp *= scaling_factor; std::get<52>(evals) += tmp; } @@ -575,10 +573,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(53); - auto tmp = ((-(((avm_main_first + avm_main_sel_internal_call) + avm_main_sel_internal_return) + - avm_main_sel_halt) + - FF(1)) * - (avm_main_internal_return_ptr_shift - avm_main_internal_return_ptr)); + auto tmp = (avm_main_sel_internal_return * avm_main_rwa); tmp *= scaling_factor; std::get<53>(evals) += tmp; } @@ -586,7 +581,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(54); - auto tmp = (avm_main_sel_cmov * (((avm_main_id * avm_main_inv) - FF(1)) + avm_main_id_zero)); + auto tmp = (avm_main_sel_internal_return * (avm_main_mem_op_a - FF(1))); tmp *= scaling_factor; std::get<54>(evals) += tmp; } @@ -594,7 +589,17 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(55); - auto tmp = ((avm_main_sel_cmov * avm_main_id_zero) * (-avm_main_inv + FF(1))); + auto tmp = + ((((-avm_main_first + FF(1)) * (-avm_main_sel_halt + FF(1))) * + ((((((((((avm_main_sel_op_add + avm_main_sel_op_sub) + avm_main_sel_op_div) + avm_main_sel_op_fdiv) + + avm_main_sel_op_mul) + + avm_main_sel_op_not) + + avm_main_sel_op_eq) + + avm_main_sel_op_and) + + avm_main_sel_op_or) + + avm_main_sel_op_xor) + + avm_main_sel_op_cast)) * + (avm_main_pc_shift - (avm_main_pc + FF(1)))); tmp *= scaling_factor; std::get<55>(evals) += tmp; } @@ -602,7 +607,10 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(56); - auto tmp = (avm_main_sel_mov_a - (avm_main_sel_mov + (avm_main_sel_cmov * (-avm_main_id_zero + FF(1))))); + auto tmp = ((-(((avm_main_first + avm_main_sel_internal_call) + avm_main_sel_internal_return) + + avm_main_sel_halt) + + FF(1)) * + (avm_main_internal_return_ptr_shift - avm_main_internal_return_ptr)); tmp *= scaling_factor; std::get<56>(evals) += tmp; } @@ -610,7 +618,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(57); - auto tmp = (avm_main_sel_mov_b - (avm_main_sel_cmov * avm_main_id_zero)); + auto tmp = (avm_main_sel_cmov * (((avm_main_id * avm_main_inv) - FF(1)) + avm_main_id_zero)); tmp *= scaling_factor; std::get<57>(evals) += tmp; } @@ -618,7 +626,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(58); - auto tmp = (avm_main_sel_mov_a * (avm_main_ia - avm_main_ic)); + auto tmp = ((avm_main_sel_cmov * avm_main_id_zero) * (-avm_main_inv + FF(1))); tmp *= scaling_factor; std::get<58>(evals) += tmp; } @@ -626,7 +634,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(59); - auto tmp = (avm_main_sel_mov_b * (avm_main_ib - avm_main_ic)); + auto tmp = (avm_main_sel_mov_a - (avm_main_sel_mov + (avm_main_sel_cmov * (-avm_main_id_zero + FF(1))))); tmp *= scaling_factor; std::get<59>(evals) += tmp; } @@ -634,7 +642,7 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(60); - auto tmp = ((avm_main_sel_mov + avm_main_sel_cmov) * (avm_main_r_in_tag - avm_main_w_in_tag)); + auto tmp = (avm_main_sel_mov_b - (avm_main_sel_cmov * avm_main_id_zero)); tmp *= scaling_factor; std::get<60>(evals) += tmp; } @@ -642,9 +650,34 @@ template class avm_mainImpl { { Avm_DECLARE_VIEWS(61); + auto tmp = (avm_main_sel_mov_a * (avm_main_ia - avm_main_ic)); + tmp *= scaling_factor; + std::get<61>(evals) += tmp; + } + // Contribution 62 + { + Avm_DECLARE_VIEWS(62); + + auto tmp = (avm_main_sel_mov_b * (avm_main_ib - avm_main_ic)); + tmp *= scaling_factor; + std::get<62>(evals) += tmp; + } + // Contribution 63 + { + Avm_DECLARE_VIEWS(63); + + auto tmp = ((avm_main_sel_mov + avm_main_sel_cmov) * (avm_main_r_in_tag - avm_main_w_in_tag)); + tmp *= scaling_factor; + std::get<63>(evals) += tmp; + } + // Contribution 64 + { + Avm_DECLARE_VIEWS(64); + auto tmp = (avm_main_alu_sel - - ((((((((((avm_main_sel_op_add + avm_main_sel_op_sub) + avm_main_sel_op_mul) + avm_main_sel_op_not) + + (((((((((((avm_main_sel_op_add + avm_main_sel_op_sub) + avm_main_sel_op_mul) + avm_main_sel_op_div) + + avm_main_sel_op_not) + avm_main_sel_op_eq) + avm_main_sel_op_lt) + avm_main_sel_op_lte) + @@ -653,14 +686,15 @@ template class avm_mainImpl { avm_main_sel_op_cast) * (-avm_main_tag_err + FF(1)))); tmp *= scaling_factor; - std::get<61>(evals) += tmp; + std::get<64>(evals) += tmp; } - // Contribution 62 + // Contribution 65 { - Avm_DECLARE_VIEWS(62); + Avm_DECLARE_VIEWS(65); auto tmp = - (((((((((avm_main_sel_op_add + avm_main_sel_op_sub) + avm_main_sel_op_mul) + avm_main_sel_op_not) + + ((((((((((avm_main_sel_op_add + avm_main_sel_op_sub) + avm_main_sel_op_mul) + avm_main_sel_op_div) + + avm_main_sel_op_not) + avm_main_sel_op_eq) + avm_main_sel_op_lt) + avm_main_sel_op_lte) + @@ -668,31 +702,31 @@ template class avm_mainImpl { avm_main_sel_op_shl) * (avm_main_alu_in_tag - avm_main_r_in_tag)); tmp *= scaling_factor; - std::get<62>(evals) += tmp; + std::get<65>(evals) += tmp; } - // Contribution 63 + // Contribution 66 { - Avm_DECLARE_VIEWS(63); + Avm_DECLARE_VIEWS(66); auto tmp = (avm_main_sel_op_cast * (avm_main_alu_in_tag - avm_main_w_in_tag)); tmp *= scaling_factor; - std::get<63>(evals) += tmp; + std::get<66>(evals) += tmp; } - // Contribution 64 + // Contribution 67 { - Avm_DECLARE_VIEWS(64); + Avm_DECLARE_VIEWS(67); auto tmp = (avm_main_bin_op_id - (avm_main_sel_op_or + (avm_main_sel_op_xor * FF(2)))); tmp *= scaling_factor; - std::get<64>(evals) += tmp; + std::get<67>(evals) += tmp; } - // Contribution 65 + // Contribution 68 { - Avm_DECLARE_VIEWS(65); + Avm_DECLARE_VIEWS(68); auto tmp = (avm_main_bin_sel - ((avm_main_sel_op_and + avm_main_sel_op_or) + avm_main_sel_op_xor)); tmp *= scaling_factor; - std::get<65>(evals) += tmp; + std::get<68>(evals) += tmp; } } }; diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/declare_views.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/declare_views.hpp index 43acfc68dd1..9dce9599042 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/declare_views.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/declare_views.hpp @@ -137,6 +137,7 @@ [[maybe_unused]] auto avm_main_sel_op_cast = View(new_term.avm_main_sel_op_cast); \ [[maybe_unused]] auto avm_main_sel_op_div = View(new_term.avm_main_sel_op_div); \ [[maybe_unused]] auto avm_main_sel_op_eq = View(new_term.avm_main_sel_op_eq); \ + [[maybe_unused]] auto avm_main_sel_op_fdiv = View(new_term.avm_main_sel_op_fdiv); \ [[maybe_unused]] auto avm_main_sel_op_lt = View(new_term.avm_main_sel_op_lt); \ [[maybe_unused]] auto avm_main_sel_op_lte = View(new_term.avm_main_sel_op_lte); \ [[maybe_unused]] auto avm_main_sel_op_mul = View(new_term.avm_main_sel_op_mul); \ diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_alu.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_alu.hpp index 69ec55c1d2c..83506a187ff 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_alu.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_alu.hpp @@ -12,7 +12,7 @@ namespace bb { class perm_main_alu_permutation_settings { public: // This constant defines how many columns are bundled together to form each set. - constexpr static size_t COLUMNS_PER_SET = 15; + constexpr static size_t COLUMNS_PER_SET = 16; /** * @brief If this method returns true on a row of values, then the inverse polynomial at this index. Otherwise the @@ -57,6 +57,7 @@ class perm_main_alu_permutation_settings { in.avm_main_sel_op_add, in.avm_main_sel_op_sub, in.avm_main_sel_op_mul, + in.avm_main_sel_op_div, in.avm_main_sel_op_eq, in.avm_main_sel_op_not, in.avm_main_sel_op_cast, @@ -72,6 +73,7 @@ class perm_main_alu_permutation_settings { in.avm_alu_op_add, in.avm_alu_op_sub, in.avm_alu_op_mul, + in.avm_alu_op_div, in.avm_alu_op_eq, in.avm_alu_op_not, in.avm_alu_op_cast, @@ -113,6 +115,7 @@ class perm_main_alu_permutation_settings { in.avm_main_sel_op_add, in.avm_main_sel_op_sub, in.avm_main_sel_op_mul, + in.avm_main_sel_op_div, in.avm_main_sel_op_eq, in.avm_main_sel_op_not, in.avm_main_sel_op_cast, @@ -128,6 +131,7 @@ class perm_main_alu_permutation_settings { in.avm_alu_op_add, in.avm_alu_op_sub, in.avm_alu_op_mul, + in.avm_alu_op_div, in.avm_alu_op_eq, in.avm_alu_op_not, in.avm_alu_op_cast, diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_deserialization.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_deserialization.cpp index bce4188712d..5ea81593782 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_deserialization.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_deserialization.cpp @@ -26,6 +26,7 @@ const std::unordered_map> OPCODE_WIRE_FORMAT = { OpCode::SUB, three_operand_format }, { OpCode::MUL, three_operand_format }, { OpCode::DIV, three_operand_format }, + { OpCode::FDIV, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32 } }, // Compute - Comparators { OpCode::EQ, three_operand_format }, { OpCode::LT, three_operand_format }, diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp index 85c5ed9ebea..746003beb50 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp @@ -121,12 +121,11 @@ std::vector Execution::gen_trace(std::vector const& instructio std::get(inst.operands.at(4)), std::get(inst.operands.at(1))); break; - case OpCode::DIV: - trace_builder.op_div(std::get(inst.operands.at(0)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3)), - std::get(inst.operands.at(4)), - std::get(inst.operands.at(1))); + case OpCode::FDIV: + trace_builder.op_fdiv(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3))); break; // Compute - Comparators case OpCode::EQ: diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp index 8b92cfbeddc..ff7cefbe1f8 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp @@ -272,8 +272,8 @@ void AvmTraceBuilder::op_mul( }); } -/** TODO: Implement for non finite field types - * @brief Division with direct or indirect memory access. +/** + * @brief Finite field division with direct or indirect memory access. * * @param indirect A byte encoding information about indirect/direct memory access. * @param a_offset An index in memory pointing to the first operand of the division. @@ -281,8 +281,7 @@ void AvmTraceBuilder::op_mul( * @param dst_offset An index in memory pointing to the output of the division. * @param in_tag The instruction memory tag of the operands. */ -void AvmTraceBuilder::op_div( - uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, AvmMemoryTag in_tag) +void AvmTraceBuilder::op_fdiv(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset) { auto clk = static_cast(main_trace.size()); @@ -290,10 +289,10 @@ void AvmTraceBuilder::op_div( bool tag_match = res.tag_match; // Reading from memory and loading into ia resp. ib. - auto read_a = - mem_trace_builder.read_and_load_from_memory(clk, IntermRegister::IA, res.direct_a_offset, in_tag, in_tag); - auto read_b = - mem_trace_builder.read_and_load_from_memory(clk, IntermRegister::IB, res.direct_b_offset, in_tag, in_tag); + auto read_a = mem_trace_builder.read_and_load_from_memory( + clk, IntermRegister::IA, res.direct_a_offset, AvmMemoryTag::FF, AvmMemoryTag::FF); + auto read_b = mem_trace_builder.read_and_load_from_memory( + clk, IntermRegister::IB, res.direct_b_offset, AvmMemoryTag::FF, AvmMemoryTag::FF); tag_match = read_a.tag_match && read_b.tag_match; // a * b^(-1) = c @@ -315,7 +314,8 @@ void AvmTraceBuilder::op_div( } // Write into memory value c from intermediate register ic. - mem_trace_builder.write_into_memory(clk, IntermRegister::IC, res.direct_c_offset, c, in_tag, in_tag); + mem_trace_builder.write_into_memory( + clk, IntermRegister::IC, res.direct_c_offset, c, AvmMemoryTag::FF, AvmMemoryTag::FF); main_trace.push_back(Row{ .avm_main_clk = clk, @@ -338,11 +338,11 @@ void AvmTraceBuilder::op_div( .avm_main_mem_op_c = FF(1), .avm_main_op_err = tag_match ? error : FF(1), .avm_main_pc = FF(pc++), - .avm_main_r_in_tag = FF(static_cast(in_tag)), + .avm_main_r_in_tag = FF(static_cast(AvmMemoryTag::FF)), .avm_main_rwc = FF(1), - .avm_main_sel_op_div = FF(1), + .avm_main_sel_op_fdiv = FF(1), .avm_main_tag_err = FF(static_cast(!tag_match)), - .avm_main_w_in_tag = FF(static_cast(in_tag)), + .avm_main_w_in_tag = FF(static_cast(AvmMemoryTag::FF)), }); } diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.hpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.hpp index 059d2fdd6c9..d6ba959df17 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.hpp @@ -38,8 +38,8 @@ class AvmTraceBuilder { // Multiplication with direct or indirect memory access. void op_mul(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, AvmMemoryTag in_tag); - // Division with direct or indirect memory access. - void op_div(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, AvmMemoryTag in_tag); + // Finite field division with direct or indirect memory access. + void op_fdiv(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset); // Bitwise not with direct or indirect memory access. void op_not(uint8_t indirect, uint32_t a_offset, uint32_t dst_offset, AvmMemoryTag in_tag); diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.hpp index d43ce2b914b..f7e89924259 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.hpp @@ -188,6 +188,7 @@ template struct AvmFullRow { FF avm_main_sel_op_cast{}; FF avm_main_sel_op_div{}; FF avm_main_sel_op_eq{}; + FF avm_main_sel_op_fdiv{}; FF avm_main_sel_op_lt{}; FF avm_main_sel_op_lte{}; FF avm_main_sel_op_mul{}; @@ -334,8 +335,8 @@ class AvmCircuitBuilder { using Polynomial = Flavor::Polynomial; using ProverPolynomials = Flavor::ProverPolynomials; - static constexpr size_t num_fixed_columns = 269; - static constexpr size_t num_polys = 229; + static constexpr size_t num_fixed_columns = 270; + static constexpr size_t num_polys = 230; std::vector rows; void set_trace(std::vector&& trace) { rows = std::move(trace); } @@ -486,6 +487,7 @@ class AvmCircuitBuilder { polys.avm_main_sel_op_cast[i] = rows[i].avm_main_sel_op_cast; polys.avm_main_sel_op_div[i] = rows[i].avm_main_sel_op_div; polys.avm_main_sel_op_eq[i] = rows[i].avm_main_sel_op_eq; + polys.avm_main_sel_op_fdiv[i] = rows[i].avm_main_sel_op_fdiv; polys.avm_main_sel_op_lt[i] = rows[i].avm_main_sel_op_lt; polys.avm_main_sel_op_lte[i] = rows[i].avm_main_sel_op_lte; polys.avm_main_sel_op_mul[i] = rows[i].avm_main_sel_op_mul; diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp index bad383523e2..1f16a50834d 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp @@ -71,11 +71,11 @@ class AvmFlavor { using RelationSeparator = FF; static constexpr size_t NUM_PRECOMPUTED_ENTITIES = 2; - static constexpr size_t NUM_WITNESS_ENTITIES = 227; + static constexpr size_t NUM_WITNESS_ENTITIES = 228; static constexpr size_t NUM_WIRES = NUM_WITNESS_ENTITIES + NUM_PRECOMPUTED_ENTITIES; // We have two copies of the witness entities, so we subtract the number of fixed ones (they have no shift), one for // the unshifted and one for the shifted - static constexpr size_t NUM_ALL_ENTITIES = 269; + static constexpr size_t NUM_ALL_ENTITIES = 270; using GrandProductRelations = std::tuple, perm_main_bin_relation, @@ -314,6 +314,7 @@ class AvmFlavor { avm_main_sel_op_cast, avm_main_sel_op_div, avm_main_sel_op_eq, + avm_main_sel_op_fdiv, avm_main_sel_op_lt, avm_main_sel_op_lte, avm_main_sel_op_mul, @@ -544,6 +545,7 @@ class AvmFlavor { avm_main_sel_op_cast, avm_main_sel_op_div, avm_main_sel_op_eq, + avm_main_sel_op_fdiv, avm_main_sel_op_lt, avm_main_sel_op_lte, avm_main_sel_op_mul, @@ -779,6 +781,7 @@ class AvmFlavor { avm_main_sel_op_cast, avm_main_sel_op_div, avm_main_sel_op_eq, + avm_main_sel_op_fdiv, avm_main_sel_op_lt, avm_main_sel_op_lte, avm_main_sel_op_mul, @@ -1051,6 +1054,7 @@ class AvmFlavor { avm_main_sel_op_cast, avm_main_sel_op_div, avm_main_sel_op_eq, + avm_main_sel_op_fdiv, avm_main_sel_op_lt, avm_main_sel_op_lte, avm_main_sel_op_mul, @@ -1323,6 +1327,7 @@ class AvmFlavor { avm_main_sel_op_cast, avm_main_sel_op_div, avm_main_sel_op_eq, + avm_main_sel_op_fdiv, avm_main_sel_op_lt, avm_main_sel_op_lte, avm_main_sel_op_mul, @@ -1854,6 +1859,7 @@ class AvmFlavor { Base::avm_main_sel_op_cast = "AVM_MAIN_SEL_OP_CAST"; Base::avm_main_sel_op_div = "AVM_MAIN_SEL_OP_DIV"; Base::avm_main_sel_op_eq = "AVM_MAIN_SEL_OP_EQ"; + Base::avm_main_sel_op_fdiv = "AVM_MAIN_SEL_OP_FDIV"; Base::avm_main_sel_op_lt = "AVM_MAIN_SEL_OP_LT"; Base::avm_main_sel_op_lte = "AVM_MAIN_SEL_OP_LTE"; Base::avm_main_sel_op_mul = "AVM_MAIN_SEL_OP_MUL"; @@ -2100,6 +2106,7 @@ class AvmFlavor { Commitment avm_main_sel_op_cast; Commitment avm_main_sel_op_div; Commitment avm_main_sel_op_eq; + Commitment avm_main_sel_op_fdiv; Commitment avm_main_sel_op_lt; Commitment avm_main_sel_op_lte; Commitment avm_main_sel_op_mul; @@ -2347,6 +2354,7 @@ class AvmFlavor { avm_main_sel_op_cast = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_main_sel_op_div = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_main_sel_op_eq = deserialize_from_buffer(Transcript::proof_data, num_frs_read); + avm_main_sel_op_fdiv = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_main_sel_op_lt = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_main_sel_op_lte = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_main_sel_op_mul = deserialize_from_buffer(Transcript::proof_data, num_frs_read); @@ -2597,6 +2605,7 @@ class AvmFlavor { serialize_to_buffer(avm_main_sel_op_cast, Transcript::proof_data); serialize_to_buffer(avm_main_sel_op_div, Transcript::proof_data); serialize_to_buffer(avm_main_sel_op_eq, Transcript::proof_data); + serialize_to_buffer(avm_main_sel_op_fdiv, Transcript::proof_data); serialize_to_buffer(avm_main_sel_op_lt, Transcript::proof_data); serialize_to_buffer(avm_main_sel_op_lte, Transcript::proof_data); serialize_to_buffer(avm_main_sel_op_mul, Transcript::proof_data); diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp index 9343f80ba62..70a86ca3414 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp @@ -193,6 +193,7 @@ void AvmProver::execute_wire_commitments_round() witness_commitments.avm_main_sel_op_cast = commitment_key->commit(key->avm_main_sel_op_cast); witness_commitments.avm_main_sel_op_div = commitment_key->commit(key->avm_main_sel_op_div); witness_commitments.avm_main_sel_op_eq = commitment_key->commit(key->avm_main_sel_op_eq); + witness_commitments.avm_main_sel_op_fdiv = commitment_key->commit(key->avm_main_sel_op_fdiv); witness_commitments.avm_main_sel_op_lt = commitment_key->commit(key->avm_main_sel_op_lt); witness_commitments.avm_main_sel_op_lte = commitment_key->commit(key->avm_main_sel_op_lte); witness_commitments.avm_main_sel_op_mul = commitment_key->commit(key->avm_main_sel_op_mul); @@ -403,6 +404,7 @@ void AvmProver::execute_wire_commitments_round() transcript->send_to_verifier(commitment_labels.avm_main_sel_op_cast, witness_commitments.avm_main_sel_op_cast); transcript->send_to_verifier(commitment_labels.avm_main_sel_op_div, witness_commitments.avm_main_sel_op_div); transcript->send_to_verifier(commitment_labels.avm_main_sel_op_eq, witness_commitments.avm_main_sel_op_eq); + transcript->send_to_verifier(commitment_labels.avm_main_sel_op_fdiv, witness_commitments.avm_main_sel_op_fdiv); transcript->send_to_verifier(commitment_labels.avm_main_sel_op_lt, witness_commitments.avm_main_sel_op_lt); transcript->send_to_verifier(commitment_labels.avm_main_sel_op_lte, witness_commitments.avm_main_sel_op_lte); transcript->send_to_verifier(commitment_labels.avm_main_sel_op_mul, witness_commitments.avm_main_sel_op_mul); diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp index 5edd090d1e6..e71a0cf8833 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp @@ -264,6 +264,8 @@ bool AvmVerifier::verify_proof(const HonkProof& proof) transcript->template receive_from_prover(commitment_labels.avm_main_sel_op_div); commitments.avm_main_sel_op_eq = transcript->template receive_from_prover(commitment_labels.avm_main_sel_op_eq); + commitments.avm_main_sel_op_fdiv = + transcript->template receive_from_prover(commitment_labels.avm_main_sel_op_fdiv); commitments.avm_main_sel_op_lt = transcript->template receive_from_prover(commitment_labels.avm_main_sel_op_lt); commitments.avm_main_sel_op_lte = diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_arithmetic.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_arithmetic.test.cpp index 68fb123ad3c..6ae97a8bfd5 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_arithmetic.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_arithmetic.test.cpp @@ -398,17 +398,17 @@ TEST_F(AvmArithmeticTestsFF, multiplicationByZero) } // Test on basic division over finite field type. -TEST_F(AvmArithmeticTestsFF, division) +TEST_F(AvmArithmeticTestsFF, fDivision) { trace_builder.calldata_copy(0, 0, 2, 0, std::vector{ 15, 315 }); - // Memory layout: [15,315,0,0,0,0,....] - trace_builder.op_div(0, 1, 0, 2, AvmMemoryTag::FF); // [15,315,21,0,0,0....] + // Memory layout: [15,315,0,0,0,0,....] + trace_builder.op_fdiv(0, 1, 0, 2); // [15,315,21,0,0,0....] trace_builder.return_op(0, 0, 3); auto trace = trace_builder.finalize(); - // Find the first row enabling the division selector - auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_div == FF(1); }); + // Find the first row enabling the fdiv selector + auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_fdiv == FF(1); }); // Check that the correct result is stored at the expected memory location. EXPECT_TRUE(row != trace.end()); @@ -421,17 +421,17 @@ TEST_F(AvmArithmeticTestsFF, division) } // Test on division with zero numerator over finite field type. -TEST_F(AvmArithmeticTestsFF, divisionNumeratorZero) +TEST_F(AvmArithmeticTestsFF, fDivisionNumeratorZero) { trace_builder.calldata_copy(0, 0, 1, 0, std::vector{ 15 }); - // Memory layout: [15,0,0,0,0,0,....] - trace_builder.op_div(0, 1, 0, 0, AvmMemoryTag::FF); // [0,0,0,0,0,0....] + // Memory layout: [15,0,0,0,0,0,....] + trace_builder.op_fdiv(0, 1, 0, 0); // [0,0,0,0,0,0....] trace_builder.return_op(0, 0, 3); auto trace = trace_builder.finalize(); - // Find the first row enabling the division selector - auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_div == FF(1); }); + // Find the first row enabling the fdiv selector + auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_fdiv == FF(1); }); // Check that the correct result is stored at the expected memory location. EXPECT_TRUE(row != trace.end()); @@ -445,17 +445,17 @@ TEST_F(AvmArithmeticTestsFF, divisionNumeratorZero) // Test on division by zero over finite field type. // We check that the operator error flag is raised. -TEST_F(AvmArithmeticTestsFF, divisionByZeroError) +TEST_F(AvmArithmeticTestsFF, fDivisionByZeroError) { trace_builder.calldata_copy(0, 0, 1, 0, std::vector{ 15 }); - // Memory layout: [15,0,0,0,0,0,....] - trace_builder.op_div(0, 0, 1, 2, AvmMemoryTag::FF); // [15,0,0,0,0,0....] + // Memory layout: [15,0,0,0,0,0,....] + trace_builder.op_fdiv(0, 0, 1, 2); // [15,0,0,0,0,0....] trace_builder.halt(); auto trace = trace_builder.finalize(); - // Find the first row enabling the division selector - auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_div == FF(1); }); + // Find the first row enabling the fdiv selector + auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_fdiv == FF(1); }); // Check that the correct result is stored at the expected memory location. EXPECT_TRUE(row != trace.end()); @@ -470,15 +470,15 @@ TEST_F(AvmArithmeticTestsFF, divisionByZeroError) // Test on division of zero by zero over finite field type. // We check that the operator error flag is raised. -TEST_F(AvmArithmeticTestsFF, divisionZeroByZeroError) +TEST_F(AvmArithmeticTestsFF, fDivisionZeroByZeroError) { - // Memory layout: [0,0,0,0,0,0,....] - trace_builder.op_div(0, 0, 1, 2, AvmMemoryTag::FF); // [0,0,0,0,0,0....] + // Memory layout: [0,0,0,0,0,0,....] + trace_builder.op_fdiv(0, 0, 1, 2); // [0,0,0,0,0,0....] trace_builder.halt(); auto trace = trace_builder.finalize(); - // Find the first row enabling the division selector - auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_div == FF(1); }); + // Find the first row enabling the fdiv selector + auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_fdiv == FF(1); }); // Check that the correct result is stored at the expected memory location. EXPECT_TRUE(row != trace.end()); @@ -506,10 +506,9 @@ TEST_F(AvmArithmeticTestsFF, mixedOperationsWithError) trace_builder.op_add(0, 5, 6, 7, AvmMemoryTag::FF); // [0,0,45,23,68,136,0,136,0....] trace_builder.op_sub(0, 7, 6, 8, AvmMemoryTag::FF); // [0,0,45,23,68,136,0,136,136,0....] trace_builder.op_mul(0, 8, 8, 8, AvmMemoryTag::FF); // [0,0,45,23,68,136,0,136,136^2,0....] - trace_builder.op_div(0, 3, 5, 1, AvmMemoryTag::FF); // [0,23*136^(-1),45,23,68,136,0,136,136^2,0....] - trace_builder.op_div(0, 1, 1, 9, AvmMemoryTag::FF); // [0,23*136^(-1),45,23,68,136,0,136,136^2,1,0....] - trace_builder.op_div( - 0, 9, 0, 4, AvmMemoryTag::FF); // [0,23*136^(-1),45,23,1/0,136,0,136,136^2,1,0....] Error: division by 0 + trace_builder.op_fdiv(0, 3, 5, 1); // [0,23*136^(-1),45,23,68,136,0,136,136^2,0....] + trace_builder.op_fdiv(0, 1, 1, 9); // [0,23*136^(-1),45,23,68,136,0,136,136^2,1,0....] + trace_builder.op_fdiv(0, 9, 0, 4); // [0,23*136^(-1),45,23,1/0,136,0,136,136^2,1,0....] Error: division by 0 trace_builder.halt(); auto trace = trace_builder.finalize(); @@ -1668,34 +1667,34 @@ TEST_F(AvmArithmeticNegativeTestsFF, multiplication) } // Test on basic incorrect division over finite field type. -TEST_F(AvmArithmeticNegativeTestsFF, divisionFF) +TEST_F(AvmArithmeticNegativeTestsFF, fDivision) { trace_builder.calldata_copy(0, 0, 2, 0, std::vector{ 15, 315 }); - // Memory layout: [15,315,0,0,0,0,....] - trace_builder.op_div(0, 1, 0, 2, AvmMemoryTag::FF); // [15,315,21,0,0,0....] + // Memory layout: [15,315,0,0,0,0,....] + trace_builder.op_fdiv(0, 1, 0, 2); // [15,315,21,0,0,0....] trace_builder.halt(); auto trace = trace_builder.finalize(); - auto select_row = [](Row r) { return r.avm_main_sel_op_div == FF(1); }; + auto select_row = [](Row r) { return r.avm_main_sel_op_fdiv == FF(1); }; mutate_ic_in_trace(trace, std::move(select_row), FF(0)); - EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "SUBOP_DIVISION_FF"); + EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "SUBOP_FDIV"); } // Test where division is not by zero but an operation error is wrongly raised // in the trace. -TEST_F(AvmArithmeticNegativeTestsFF, divisionNoZeroButError) +TEST_F(AvmArithmeticNegativeTestsFF, fDivisionNoZeroButError) { trace_builder.calldata_copy(0, 0, 2, 0, std::vector{ 15, 315 }); - // Memory layout: [15,315,0,0,0,0,....] - trace_builder.op_div(0, 1, 0, 2, AvmMemoryTag::FF); // [15,315,21,0,0,0....] + // Memory layout: [15,315,0,0,0,0,....] + trace_builder.op_fdiv(0, 1, 0, 2); // [15,315,21,0,0,0....] trace_builder.halt(); auto trace = trace_builder.finalize(); - // Find the first row enabling the division selector - auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_div == FF(1); }); + // Find the first row enabling the fdiv selector + auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_fdiv == FF(1); }); size_t const index = static_cast(row - trace.begin()); @@ -1703,47 +1702,83 @@ TEST_F(AvmArithmeticNegativeTestsFF, divisionNoZeroButError) trace[index].avm_main_op_err = FF(1); auto trace2 = trace; - EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "SUBOP_DIVISION_ZERO_ERR1"); + EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "SUBOP_FDIV_ZERO_ERR1"); // Even more malicious, one makes the first relation passes by setting the inverse to zero. trace2[index].avm_main_inv = FF(0); - EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace2)), "SUBOP_DIVISION_ZERO_ERR2"); + EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace2)), "SUBOP_FDIV_ZERO_ERR2"); } -// Test with division by zero occurs and no error is raised (remove error flag) -TEST_F(AvmArithmeticNegativeTestsFF, divisionByZeroNoError) +// Test with finite field division by zero occurs and no error is raised (remove error flag) +TEST_F(AvmArithmeticNegativeTestsFF, fDivisionByZeroNoError) { trace_builder.calldata_copy(0, 0, 1, 0, std::vector{ 15 }); - // Memory layout: [15,0,0,0,0,0,....] - trace_builder.op_div(0, 0, 1, 2, AvmMemoryTag::FF); // [15,0,0,0,0,0....] + // Memory layout: [15,0,0,0,0,0,....] + trace_builder.op_fdiv(0, 0, 1, 2); // [15,0,0,0,0,0....] trace_builder.halt(); auto trace = trace_builder.finalize(); - // Find the first row enabling the division selector - auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_div == FF(1); }); + // Find the first row enabling the fdiv selector + auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_fdiv == FF(1); }); // Remove the operator error flag row->avm_main_op_err = FF(0); - EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "SUBOP_DIVISION_FF"); + EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "SUBOP_FDIV"); } -// Test with division of zero by zero occurs and no error is raised (remove error flag) -TEST_F(AvmArithmeticNegativeTestsFF, divisionZeroByZeroNoError) +// Test with finite field division of zero by zero occurs and no error is raised (remove error flag) +TEST_F(AvmArithmeticNegativeTestsFF, fDivisionZeroByZeroNoError) { - // Memory layout: [0,0,0,0,0,0,....] - trace_builder.op_div(0, 0, 1, 2, AvmMemoryTag::FF); // [0,0,0,0,0,0....] + // Memory layout: [0,0,0,0,0,0,....] + trace_builder.op_fdiv(0, 0, 1, 2); // [0,0,0,0,0,0....] trace_builder.halt(); auto trace = trace_builder.finalize(); - // Find the first row enabling the division selector - auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_div == FF(1); }); + // Find the first row enabling the fdiv selector + auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_fdiv == FF(1); }); // Remove the operator error flag row->avm_main_op_err = FF(0); - EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "SUBOP_DIVISION_ZERO_ERR1"); + EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "SUBOP_FDIV_ZERO_ERR1"); +} + +// Test with finite field division using a wrong read instruction tag +TEST_F(AvmArithmeticNegativeTestsFF, fDivisionWrongRInTag) +{ + trace_builder.calldata_copy(0, 0, 1, 0, std::vector{ 18, 6 }); + // Memory layout: [18,6,0,0,0,0,....] + trace_builder.op_fdiv(0, 0, 1, 2); // [18,6,3,0,0,0....] + trace_builder.halt(); + auto trace = trace_builder.finalize(); + + // Find the first row enabling the fdiv selector + auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_fdiv == FF(1); }); + + // Change read instruction tag + row->avm_main_r_in_tag = FF(3); + + EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "SUBOP_FDIV_R_IN_TAG_FF"); +} + +// Test with finite field division using a wrong write instruction tag +TEST_F(AvmArithmeticNegativeTestsFF, fDivisionWrongWInTag) +{ + trace_builder.calldata_copy(0, 0, 1, 0, std::vector{ 18, 6 }); + // Memory layout: [18,6,0,0,0,0,....] + trace_builder.op_fdiv(0, 0, 1, 2); // [18,6,3,0,0,0....] + trace_builder.halt(); + auto trace = trace_builder.finalize(); + + // Find the first row enabling the fdiv selector + auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_fdiv == FF(1); }); + + // Change write instruction tag + row->avm_main_w_in_tag = FF(3); + + EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "SUBOP_FDIV_W_IN_TAG_FF"); } // Test that error flag cannot be raised for a non-relevant operation such as diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_execution.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_execution.test.cpp index 2639e9fb979..f7aec7b173a 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_execution.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_execution.test.cpp @@ -382,9 +382,9 @@ TEST_F(AvmExecutionTests, nestedInternalCalls) // Positive test with JUMP and CALLDATACOPY // We test bytecode which first invoke CALLDATACOPY on a FF array of two values. -// Then, a JUMP call skips a SUB opcode to land to a DIV operation and RETURN. +// Then, a JUMP call skips a SUB opcode to land to a FDIV operation and RETURN. // Calldata: [13, 156] -// Bytecode layout: CALLDATACOPY JUMP SUB DIV RETURN +// Bytecode layout: CALLDATACOPY JUMP SUB FDIV RETURN // 0 1 2 3 4 TEST_F(AvmExecutionTests, jumpAndCalldatacopy) { @@ -394,16 +394,15 @@ TEST_F(AvmExecutionTests, jumpAndCalldatacopy) "00000002" // copy_size "0000000A" // dst_offset // M[10] = 13, M[11] = 156 + to_hex(OpCode::JUMP) + // opcode JUMP - "00000003" // jmp_dest (DIV located at 3) + "00000003" // jmp_dest (FDIV located at 3) + to_hex(OpCode::SUB) + // opcode SUB "00" // Indirect flag "06" // FF "0000000B" // addr 11 "0000000A" // addr 10 "00000001" // addr c 1 (If executed would be 156 - 13 = 143) - + to_hex(OpCode::DIV) + // opcode DIV + + to_hex(OpCode::FDIV) + // opcode FDIV "00" // Indirect flag - "06" // FF "0000000B" // addr 11 "0000000A" // addr 10 "00000001" // addr c 1 (156 / 13 = 12) @@ -443,8 +442,8 @@ TEST_F(AvmExecutionTests, jumpAndCalldatacopy) EXPECT_EQ(trace.at(i + 1).avm_main_pc, pc_sequence.at(i)); } - // Find the first row enabling the division selector. - auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_div == 1; }); + // Find the first row enabling the fdiv selector. + auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_fdiv == 1; }); EXPECT_EQ(row->avm_main_ic, 12); // Find the first row enabling the subtraction selector. diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_memory.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_memory.test.cpp index 0b365104e16..95c364acd05 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_memory.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_memory.test.cpp @@ -258,18 +258,18 @@ TEST_F(AvmMemoryTests, consistentTagNoErrorViolation) { trace_builder.calldata_copy(0, 0, 2, 0, std::vector{ 84, 7 }); - trace_builder.op_div(0, 0, 1, 4, AvmMemoryTag::FF); + trace_builder.op_fdiv(0, 0, 1, 4); trace_builder.halt(); auto trace = trace_builder.finalize(); - // Find the first row enabling the division selector - auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_div == FF(1); }); + // Find the first row enabling the fdiv selector + auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_fdiv == FF(1); }); EXPECT_TRUE(row != trace.end()); auto clk = row->avm_main_clk; - // Find the memory trace position corresponding to the div sub-operation of register ia. + // Find the memory trace position corresponding to the fdiv sub-operation of register ia. row = std::ranges::find_if(trace.begin(), trace.end(), [clk](Row r) { return r.avm_mem_clk == clk && r.avm_mem_sub_clk == AvmMemTraceBuilder::SUB_CLK_LOAD_A; }); @@ -284,18 +284,18 @@ TEST_F(AvmMemoryTests, noErrorTagWriteViolation) { trace_builder.calldata_copy(0, 0, 2, 0, std::vector{ 84, 7 }); - trace_builder.op_div(0, 0, 1, 4, AvmMemoryTag::FF); + trace_builder.op_fdiv(0, 0, 1, 4); trace_builder.halt(); auto trace = trace_builder.finalize(); - // Find the first row enabling the division selector - auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_div == FF(1); }); + // Find the first row enabling the fdiv selector + auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_fdiv == FF(1); }); ASSERT_TRUE(row != trace.end()); auto clk = row->avm_main_clk; - // Find the memory trace position corresponding to the div sub-operation of register ic. + // Find the memory trace position corresponding to the fdiv sub-operation of register ic. row = std::ranges::find_if(trace.begin(), trace.end(), [clk](Row r) { return r.avm_mem_clk == clk && r.avm_mem_sub_clk == AvmMemTraceBuilder::SUB_CLK_STORE_C; }); From a07425184d08d647588e3778221740e724b1b052 Mon Sep 17 00:00:00 2001 From: Santiago Palladino Date: Tue, 23 Apr 2024 12:49:20 -0300 Subject: [PATCH 089/102] chore: Run flakey e2e tests on CI but allow failure (#5937) So we can keep an eye on why they are failing. --- yarn-project/end-to-end/Earthfile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/yarn-project/end-to-end/Earthfile b/yarn-project/end-to-end/Earthfile index b546dbf84a3..59403a2400c 100644 --- a/yarn-project/end-to-end/Earthfile +++ b/yarn-project/end-to-end/Earthfile @@ -86,6 +86,10 @@ e2e-tests: FROM ../+end-to-end RUN yarn test ./src/e2e +flakey-e2e-tests: + FROM ../+end-to-end + RUN yarn test --passWithNoTests ./src/flakey || true + e2e-sandbox-example: ARG e2e_mode=local DO +E2E_TEST --test=e2e_sandbox_example.test.ts --e2e_mode=$e2e_mode From 8f73f18f3c07de0fd5e247ade5a48109c37c1bc5 Mon Sep 17 00:00:00 2001 From: Aztec Bot <49558828+AztecBot@users.noreply.github.com> Date: Tue, 23 Apr 2024 16:57:07 +0100 Subject: [PATCH 090/102] feat: Sync from noir (#5955) Automated pull of development from the [noir](https://github.com/noir-lang/noir) programming language, a dependency of Aztec. BEGIN_COMMIT_OVERRIDE chore: Delete unused brillig methods (https://github.com/noir-lang/noir/pull/4887) feat(acir_gen): Brillig stdlib (https://github.com/noir-lang/noir/pull/4848) END_COMMIT_OVERRIDE --------- Co-authored-by: vezenovm --- .noir-sync-commit | 2 +- .../acvm-repo/acir/src/circuit/brillig.rs | 2 +- .../src/ssa/acir_gen/acir_ir/acir_variable.rs | 107 +---- .../ssa/acir_gen/acir_ir/generated_acir.rs | 91 ++-- .../noirc_evaluator/src/ssa/acir_gen/mod.rs | 392 +++++++++++++++++- .../noir_js_backend_barretenberg/package.json | 2 +- noir/noir-repo/yarn.lock | 13 +- 7 files changed, 465 insertions(+), 144 deletions(-) diff --git a/.noir-sync-commit b/.noir-sync-commit index 2863ab07e89..2a6270fb774 100644 --- a/.noir-sync-commit +++ b/.noir-sync-commit @@ -1 +1 @@ -1969ce39378f633e88adedf43b747724b89ed7d7 +9704bd0abfe2dba1e7a4aef6cdb6cc83d70b929e diff --git a/noir/noir-repo/acvm-repo/acir/src/circuit/brillig.rs b/noir/noir-repo/acvm-repo/acir/src/circuit/brillig.rs index e75d335d52b..7f87aabf9d5 100644 --- a/noir/noir-repo/acvm-repo/acir/src/circuit/brillig.rs +++ b/noir/noir-repo/acvm-repo/acir/src/circuit/brillig.rs @@ -33,7 +33,7 @@ pub struct Brillig { /// This is purely a wrapper struct around a list of Brillig opcode's which represents /// a full Brillig function to be executed by the Brillig VM. /// This is stored separately on a program and accessed through a [BrilligPointer]. -#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Default)] +#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Default, Debug)] pub struct BrilligBytecode { pub bytecode: Vec, } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs index b94e02e5119..3f5e4129dd0 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs @@ -1,5 +1,5 @@ use super::big_int::BigIntContext; -use super::generated_acir::GeneratedAcir; +use super::generated_acir::{BrilligStdlibFunc, GeneratedAcir, PLACEHOLDER_BRILLIG_INDEX}; use crate::brillig::brillig_gen::brillig_directive; use crate::brillig::brillig_ir::artifact::GeneratedBrillig; use crate::errors::{InternalError, RuntimeError, SsaReport}; @@ -326,13 +326,15 @@ impl AcirContext { // Compute the inverse with brillig code let inverse_code = brillig_directive::directive_invert(); - let results = self.brillig( + let results = self.brillig_call( predicate, - inverse_code, + &inverse_code, vec![AcirValue::Var(var, AcirType::field())], vec![AcirType::field()], true, false, + PLACEHOLDER_BRILLIG_INDEX, + Some(BrilligStdlibFunc::Inverse), )?; let inverted_var = Self::expect_one_var(results); @@ -711,9 +713,9 @@ impl AcirContext { } let [q_value, r_value]: [AcirValue; 2] = self - .brillig( + .brillig_call( predicate, - brillig_directive::directive_quotient(bit_size + 1), + &brillig_directive::directive_quotient(bit_size + 1), vec![ AcirValue::Var(lhs, AcirType::unsigned(bit_size)), AcirValue::Var(rhs, AcirType::unsigned(bit_size)), @@ -721,6 +723,8 @@ impl AcirContext { vec![AcirType::unsigned(max_q_bits), AcirType::unsigned(max_rhs_bits)], true, false, + PLACEHOLDER_BRILLIG_INDEX, + Some(BrilligStdlibFunc::Quotient(bit_size + 1)), )? .try_into() .expect("quotient only returns two values"); @@ -1464,97 +1468,6 @@ impl AcirContext { id } - // TODO: Delete this method once we remove the `Brillig` opcode - pub(crate) fn brillig( - &mut self, - predicate: AcirVar, - generated_brillig: GeneratedBrillig, - inputs: Vec, - outputs: Vec, - attempt_execution: bool, - unsafe_return_values: bool, - ) -> Result, RuntimeError> { - let b_inputs = try_vecmap(inputs, |i| -> Result<_, InternalError> { - match i { - AcirValue::Var(var, _) => Ok(BrilligInputs::Single(self.var_to_expression(var)?)), - AcirValue::Array(vars) => { - let mut var_expressions: Vec = Vec::new(); - for var in vars { - self.brillig_array_input(&mut var_expressions, var)?; - } - Ok(BrilligInputs::Array(var_expressions)) - } - AcirValue::DynamicArray(AcirDynamicArray { block_id, .. }) => { - Ok(BrilligInputs::MemoryArray(block_id)) - } - } - })?; - - // Optimistically try executing the brillig now, if we can complete execution they just return the results. - // This is a temporary measure pending SSA optimizations being applied to Brillig which would remove constant-input opcodes (See #2066) - // - // We do _not_ want to do this in the situation where the `main` function is unconstrained, as if execution succeeds - // the entire program will be replaced with witness constraints to its outputs. - if attempt_execution { - if let Some(brillig_outputs) = - self.execute_brillig(&generated_brillig.byte_code, &b_inputs, &outputs) - { - return Ok(brillig_outputs); - } - } - - // Otherwise we must generate ACIR for it and execute at runtime. - let mut b_outputs = Vec::new(); - let outputs_var = vecmap(outputs, |output| match output { - AcirType::NumericType(_) => { - let witness_index = self.acir_ir.next_witness_index(); - b_outputs.push(BrilligOutputs::Simple(witness_index)); - let var = self.add_data(AcirVarData::Witness(witness_index)); - AcirValue::Var(var, output.clone()) - } - AcirType::Array(element_types, size) => { - let (acir_value, witnesses) = self.brillig_array_output(&element_types, size); - b_outputs.push(BrilligOutputs::Array(witnesses)); - acir_value - } - }); - let predicate = self.var_to_expression(predicate)?; - self.acir_ir.brillig(Some(predicate), generated_brillig, b_inputs, b_outputs); - - fn range_constraint_value( - context: &mut AcirContext, - value: &AcirValue, - ) -> Result<(), RuntimeError> { - match value { - AcirValue::Var(var, typ) => { - let numeric_type = match typ { - AcirType::NumericType(numeric_type) => numeric_type, - _ => unreachable!("`AcirValue::Var` may only hold primitive values"), - }; - context.range_constrain_var(*var, numeric_type, None)?; - } - AcirValue::Array(values) => { - for value in values { - range_constraint_value(context, value)?; - } - } - AcirValue::DynamicArray(_) => { - unreachable!("Brillig opcodes cannot return dynamic arrays") - } - } - Ok(()) - } - - // This is a hack to ensure that if we're compiling a brillig entrypoint function then - // we don't also add a number of range constraints. - if !unsafe_return_values { - for output_var in &outputs_var { - range_constraint_value(self, output_var)?; - } - } - Ok(outputs_var) - } - #[allow(clippy::too_many_arguments)] pub(crate) fn brillig_call( &mut self, @@ -1565,6 +1478,7 @@ impl AcirContext { attempt_execution: bool, unsafe_return_values: bool, brillig_function_index: u32, + brillig_stdlib_func: Option, ) -> Result, RuntimeError> { let brillig_inputs = try_vecmap(inputs, |i| -> Result<_, InternalError> { match i { @@ -1618,6 +1532,7 @@ impl AcirContext { brillig_inputs, brillig_outputs, brillig_function_index, + brillig_stdlib_func, ); fn range_constraint_value( diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs index 999ff2ddb5d..0b04d1b63ab 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs @@ -10,7 +10,7 @@ use crate::{ use acvm::acir::{ circuit::{ - brillig::{Brillig as AcvmBrillig, BrilligInputs, BrilligOutputs}, + brillig::{BrilligInputs, BrilligOutputs}, opcodes::{BlackBoxFuncCall, FunctionInput, Opcode as AcirOpcode}, OpcodeLocation, }, @@ -24,6 +24,12 @@ use acvm::{ use iter_extended::vecmap; use num_bigint::BigUint; +/// Brillig calls such as for the Brillig std lib are resolved only after code generation is finished. +/// This index should be used when adding a Brillig call during code generation. +/// Code generation should then keep track of that unresolved call opcode which will be resolved with the +/// correct function index after code generation. +pub(crate) const PLACEHOLDER_BRILLIG_INDEX: u32 = 0; + #[derive(Debug, Default)] /// The output of the Acir-gen pass, which should only be produced for entry point Acir functions pub(crate) struct GeneratedAcir { @@ -62,6 +68,29 @@ pub(crate) struct GeneratedAcir { /// Name for the corresponding entry point represented by this Acir-gen output. /// Only used for debugging and benchmarking purposes pub(crate) name: String, + + /// Maps the opcode index to a Brillig std library function call. + /// As to avoid passing the ACIR gen shared context into each individual ACIR + /// we can instead keep this map and resolve the Brillig calls at the end of code generation. + pub(crate) brillig_stdlib_func_locations: BTreeMap, +} + +#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)] +pub(crate) enum BrilligStdlibFunc { + Inverse, + // The Brillig quotient code is different depending upon the bit size. + Quotient(u32), +} + +impl BrilligStdlibFunc { + pub(crate) fn get_generated_brillig(&self) -> GeneratedBrillig { + match self { + BrilligStdlibFunc::Inverse => brillig_directive::directive_invert(), + BrilligStdlibFunc::Quotient(bit_size) => { + brillig_directive::directive_quotient(*bit_size) + } + } + } } impl GeneratedAcir { @@ -456,7 +485,14 @@ impl GeneratedAcir { let inverse_code = brillig_directive::directive_invert(); let inputs = vec![BrilligInputs::Single(expr)]; let outputs = vec![BrilligOutputs::Simple(inverted_witness)]; - self.brillig(Some(Expression::one()), inverse_code, inputs, outputs); + self.brillig_call( + Some(Expression::one()), + &inverse_code, + inputs, + outputs, + PLACEHOLDER_BRILLIG_INDEX, + Some(BrilligStdlibFunc::Inverse), + ); inverted_witness } @@ -589,35 +625,6 @@ impl GeneratedAcir { Ok(()) } - // TODO: Delete this method once we remove the `Brillig` opcode - pub(crate) fn brillig( - &mut self, - predicate: Option, - generated_brillig: GeneratedBrillig, - inputs: Vec, - outputs: Vec, - ) { - let opcode = AcirOpcode::Brillig(AcvmBrillig { - inputs, - outputs, - bytecode: generated_brillig.byte_code, - predicate, - }); - self.push_opcode(opcode); - for (brillig_index, call_stack) in generated_brillig.locations { - self.locations.insert( - OpcodeLocation::Brillig { acir_index: self.opcodes.len() - 1, brillig_index }, - call_stack, - ); - } - for (brillig_index, message) in generated_brillig.assert_messages { - self.assert_messages.insert( - OpcodeLocation::Brillig { acir_index: self.opcodes.len() - 1, brillig_index }, - message, - ); - } - } - pub(crate) fn brillig_call( &mut self, predicate: Option, @@ -625,10 +632,16 @@ impl GeneratedAcir { inputs: Vec, outputs: Vec, brillig_function_index: u32, + stdlib_func: Option, ) { let opcode = AcirOpcode::BrilligCall { id: brillig_function_index, inputs, outputs, predicate }; self.push_opcode(opcode); + if let Some(stdlib_func) = stdlib_func { + self.brillig_stdlib_func_locations + .insert(self.last_acir_opcode_location(), stdlib_func); + } + for (brillig_index, call_stack) in generated_brillig.locations.iter() { self.locations.insert( OpcodeLocation::Brillig { @@ -649,6 +662,22 @@ impl GeneratedAcir { } } + // We can only resolve the Brillig stdlib after having processed the entire ACIR + pub(crate) fn resolve_brillig_stdlib_call( + &mut self, + opcode_location: OpcodeLocation, + brillig_function_index: u32, + ) { + let acir_index = match opcode_location { + OpcodeLocation::Acir(index) => index, + _ => panic!("should not have brillig index"), + }; + match &mut self.opcodes[acir_index] { + AcirOpcode::BrilligCall { id, .. } => *id = brillig_function_index, + _ => panic!("expected brillig call opcode"), + } + } + pub(crate) fn last_acir_opcode_location(&self) -> OpcodeLocation { OpcodeLocation::Acir(self.opcodes.len() - 1) } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs index 8b16ad51ca1..ee236df8eac 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs @@ -5,6 +5,7 @@ use std::collections::{BTreeMap, HashSet}; use std::fmt::Debug; use self::acir_ir::acir_variable::{AcirContext, AcirType, AcirVar}; +use self::acir_ir::generated_acir::BrilligStdlibFunc; use super::function_builder::data_bus::DataBus; use super::ir::dfg::CallStack; use super::ir::function::FunctionId; @@ -30,6 +31,7 @@ use crate::ssa::ir::function::InlineType; pub(crate) use acir_ir::generated_acir::GeneratedAcir; use acvm::acir::circuit::brillig::BrilligBytecode; +use acvm::acir::circuit::OpcodeLocation; use acvm::acir::native_types::Witness; use acvm::acir::BlackBoxFunc; use acvm::{ @@ -55,6 +57,14 @@ struct SharedContext { /// This uses the brillig parameters in the map since using slices with different lengths /// needs to create different brillig entrypoints brillig_generated_func_pointers: BTreeMap<(FunctionId, Vec), u32>, + + /// Maps a Brillig std lib function (a handwritten primitive such as for inversion) -> Final generated Brillig artifact index. + /// A separate mapping from normal Brillig calls is necessary as these methods do not have an associated function id from SSA. + brillig_stdlib_func_pointer: HashMap, + + /// Keeps track of Brillig std lib calls per function that need to still be resolved + /// with the correct function pointer from the `brillig_stdlib_func_pointer` map. + brillig_stdlib_calls_to_resolve: HashMap>, } impl SharedContext { @@ -84,6 +94,47 @@ impl SharedContext { fn new_generated_pointer(&self) -> u32 { self.generated_brillig.len() as u32 } + + fn generate_brillig_calls_to_resolve( + &mut self, + brillig_stdlib_func: &BrilligStdlibFunc, + func_id: FunctionId, + opcode_location: OpcodeLocation, + ) { + if let Some(generated_pointer) = + self.brillig_stdlib_func_pointer.get(brillig_stdlib_func).copied() + { + self.add_call_to_resolve(func_id, (opcode_location, generated_pointer)); + } else { + let code = brillig_stdlib_func.get_generated_brillig(); + let generated_pointer = self.new_generated_pointer(); + self.insert_generated_brillig_stdlib( + *brillig_stdlib_func, + generated_pointer, + func_id, + opcode_location, + code, + ); + } + } + + /// Insert a newly generated Brillig stdlib function + fn insert_generated_brillig_stdlib( + &mut self, + brillig_stdlib_func: BrilligStdlibFunc, + generated_pointer: u32, + func_id: FunctionId, + opcode_location: OpcodeLocation, + code: GeneratedBrillig, + ) { + self.brillig_stdlib_func_pointer.insert(brillig_stdlib_func, generated_pointer); + self.add_call_to_resolve(func_id, (opcode_location, generated_pointer)); + self.generated_brillig.push(code); + } + + fn add_call_to_resolve(&mut self, func_id: FunctionId, call_to_resolve: (OpcodeLocation, u32)) { + self.brillig_stdlib_calls_to_resolve.entry(func_id).or_default().push(call_to_resolve); + } } /// Context struct for the acir generation pass. @@ -240,6 +291,35 @@ impl Ssa { if let Some(mut generated_acir) = context.convert_ssa_function(&self, function, brillig)? { + // We want to be able to insert Brillig stdlib functions anywhere during the ACIR generation process (e.g. such as on the `GeneratedAcir`). + // As we don't want a reference to the `SharedContext` on the generated ACIR itself, + // we instead store the opcode location at which a Brillig call to a std lib function occurred. + // We then defer resolving the function IDs of those Brillig functions to when we have generated Brillig + // for all normal Brillig calls. + for (opcode_location, brillig_stdlib_func) in + &generated_acir.brillig_stdlib_func_locations + { + shared_context.generate_brillig_calls_to_resolve( + brillig_stdlib_func, + function.id(), + *opcode_location, + ); + } + + // Fetch the Brillig stdlib calls to resolve for this function + if let Some(calls_to_resolve) = + shared_context.brillig_stdlib_calls_to_resolve.get(&function.id()) + { + // Resolve the Brillig stdlib calls + // We have to do a separate loop as the generated ACIR cannot be borrowed as mutable after an immutable borrow + for (opcode_location, brillig_function_pointer) in calls_to_resolve { + generated_acir.resolve_brillig_stdlib_call( + *opcode_location, + *brillig_function_pointer, + ); + } + } + generated_acir.name = function.name().to_owned(); acirs.push(generated_acir); } @@ -376,6 +456,7 @@ impl<'a> Context<'a> { true, // We are guaranteed to have a Brillig function pointer of `0` as main itself is marked as unconstrained 0, + None, )?; self.shared_context.insert_generated_brillig(main_func.id(), arguments, 0, code); @@ -687,6 +768,7 @@ impl<'a> Context<'a> { true, false, *generated_pointer, + None, )? } else { let code = @@ -701,6 +783,7 @@ impl<'a> Context<'a> { true, false, generated_pointer, + None, )?; self.shared_context.insert_generated_brillig( *id, @@ -2518,14 +2601,20 @@ fn can_omit_element_sizes_array(array_typ: &Type) -> bool { #[cfg(test)] mod test { + use std::collections::BTreeMap; + use acvm::{ - acir::{circuit::Opcode, native_types::Witness}, + acir::{ + circuit::{Opcode, OpcodeLocation}, + native_types::Witness, + }, FieldElement, }; use crate::{ brillig::Brillig, ssa::{ + acir_gen::acir_ir::generated_acir::BrilligStdlibFunc, function_builder::FunctionBuilder, ir::{ function::{FunctionId, InlineType}, @@ -2848,10 +2937,12 @@ mod test { fn multiple_brillig_calls_one_bytecode() { // acir(inline) fn main f0 { // b0(v0: Field, v1: Field): - // v3 = call f1(v0, v1) // v4 = call f1(v0, v1) // v5 = call f1(v0, v1) // v6 = call f1(v0, v1) + // v7 = call f2(v0, v1) + // v8 = call f1(v0, v1) + // v9 = call f2(v0, v1) // return // } // brillig fn foo f1 { @@ -2898,11 +2989,7 @@ mod test { .expect("Should compile manually written SSA into ACIR"); assert_eq!(acir_functions.len(), 1, "Should only have a `main` ACIR function"); - assert_eq!( - brillig_functions.len(), - 2, - "Should only have generated a single Brillig function" - ); + assert_eq!(brillig_functions.len(), 2, "Should only have generated two Brillig functions"); let main_acir = &acir_functions[0]; let main_opcodes = main_acir.opcodes(); @@ -2919,4 +3006,295 @@ mod test { } } } + + // Test that given multiple primitive operations that are represented by Brillig directives (e.g. invert/quotient), + // we will only generate one bytecode and the appropriate Brillig call opcodes are generated. + #[test] + fn multiple_brillig_stdlib_calls() { + // acir(inline) fn main f0 { + // b0(v0: u32, v1: u32, v2: u32): + // v3 = div v0, v1 + // constrain v3 == v2 + // v4 = div v1, v2 + // constrain v4 == u32 1 + // return + // } + let foo_id = Id::test_new(0); + let mut builder = FunctionBuilder::new("main".into(), foo_id); + let main_v0 = builder.add_parameter(Type::unsigned(32)); + let main_v1 = builder.add_parameter(Type::unsigned(32)); + let main_v2 = builder.add_parameter(Type::unsigned(32)); + + // Call a primitive operation that uses Brillig + let v0_div_v1 = builder.insert_binary(main_v0, BinaryOp::Div, main_v1); + builder.insert_constrain(v0_div_v1, main_v2, None); + + // Call the same primitive operation again + let v1_div_v2 = builder.insert_binary(main_v1, BinaryOp::Div, main_v2); + let one = builder.numeric_constant(1u128, Type::unsigned(32)); + builder.insert_constrain(v1_div_v2, one, None); + + builder.terminate_with_return(vec![]); + + let ssa = builder.finish(); + println!("{}", ssa); + + // The Brillig bytecode we insert for the stdlib is hardcoded so we do not need to provide any + // Brillig artifacts to the ACIR gen pass. + let (acir_functions, brillig_functions) = ssa + .into_acir(&Brillig::default(), noirc_frontend::ast::Distinctness::Distinct) + .expect("Should compile manually written SSA into ACIR"); + + assert_eq!(acir_functions.len(), 1, "Should only have a `main` ACIR function"); + // We expect two brillig functions: + // - Quotient (shared between both divisions) + // - Inversion, caused by division-by-zero check (shared between both divisions) + assert_eq!(brillig_functions.len(), 2, "Should only have generated two Brillig functions"); + + let main_acir = &acir_functions[0]; + let main_opcodes = main_acir.opcodes(); + check_brillig_calls( + &acir_functions[0].brillig_stdlib_func_locations, + main_opcodes, + 0, + 4, + 0, + ); + } + + // Test that given both hardcoded Brillig directives and calls to normal Brillig functions, + // we generate a single bytecode for the directives and a single bytecode for the normal Brillig calls. + #[test] + fn brillig_stdlib_calls_with_regular_brillig_call() { + // acir(inline) fn main f0 { + // b0(v0: u32, v1: u32, v2: u32): + // v4 = div v0, v1 + // constrain v4 == v2 + // v5 = call f1(v0, v1) + // v6 = call f1(v0, v1) + // v7 = div v1, v2 + // constrain v7 == u32 1 + // return + // } + // brillig fn foo f1 { + // b0(v0: Field, v1: Field): + // v2 = eq v0, v1 + // constrain v2 == u1 0 + // return v0 + // } + let foo_id = Id::test_new(0); + let mut builder = FunctionBuilder::new("main".into(), foo_id); + let main_v0 = builder.add_parameter(Type::unsigned(32)); + let main_v1 = builder.add_parameter(Type::unsigned(32)); + let main_v2 = builder.add_parameter(Type::unsigned(32)); + + let foo_id = Id::test_new(1); + let foo = builder.import_function(foo_id); + + // Call a primitive operation that uses Brillig + let v0_div_v1 = builder.insert_binary(main_v0, BinaryOp::Div, main_v1); + builder.insert_constrain(v0_div_v1, main_v2, None); + + // Insert multiple calls to the same Brillig function + builder.insert_call(foo, vec![main_v0, main_v1], vec![Type::field()]).to_vec(); + builder.insert_call(foo, vec![main_v0, main_v1], vec![Type::field()]).to_vec(); + + // Call the same primitive operation again + let v1_div_v2 = builder.insert_binary(main_v1, BinaryOp::Div, main_v2); + let one = builder.numeric_constant(1u128, Type::unsigned(32)); + builder.insert_constrain(v1_div_v2, one, None); + + builder.terminate_with_return(vec![]); + + build_basic_foo_with_return(&mut builder, foo_id, true); + + let ssa = builder.finish(); + // We need to generate Brillig artifacts for the regular Brillig function and pass them to the ACIR generation pass. + let brillig = ssa.to_brillig(false); + println!("{}", ssa); + + let (acir_functions, brillig_functions) = ssa + .into_acir(&brillig, noirc_frontend::ast::Distinctness::Distinct) + .expect("Should compile manually written SSA into ACIR"); + + assert_eq!(acir_functions.len(), 1, "Should only have a `main` ACIR function"); + // We expect 3 brillig functions: + // - Quotient (shared between both divisions) + // - Inversion, caused by division-by-zero check (shared between both divisions) + // - Custom brillig function `foo` + assert_eq!( + brillig_functions.len(), + 3, + "Should only have generated three Brillig functions" + ); + + let main_acir = &acir_functions[0]; + let main_opcodes = main_acir.opcodes(); + check_brillig_calls( + &acir_functions[0].brillig_stdlib_func_locations, + main_opcodes, + 1, + 4, + 2, + ); + } + + // Test that given both normal Brillig calls, Brillig stdlib calls, and non-inlined ACIR calls, that we accurately generate ACIR. + #[test] + fn brillig_stdlib_calls_with_multiple_acir_calls() { + // acir(inline) fn main f0 { + // b0(v0: u32, v1: u32, v2: u32): + // v4 = div v0, v1 + // constrain v4 == v2 + // v5 = call f1(v0, v1) + // v6 = call f2(v0, v1) + // v7 = div v1, v2 + // constrain v7 == u32 1 + // return + // } + // brillig fn foo f1 { + // b0(v0: Field, v1: Field): + // v2 = eq v0, v1 + // constrain v2 == u1 0 + // return v0 + // } + // acir(fold) fn foo f2 { + // b0(v0: Field, v1: Field): + // v2 = eq v0, v1 + // constrain v2 == u1 0 + // return v0 + // } + // } + let foo_id = Id::test_new(0); + let mut builder = FunctionBuilder::new("main".into(), foo_id); + let main_v0 = builder.add_parameter(Type::unsigned(32)); + let main_v1 = builder.add_parameter(Type::unsigned(32)); + let main_v2 = builder.add_parameter(Type::unsigned(32)); + + let foo_id = Id::test_new(1); + let foo = builder.import_function(foo_id); + let bar_id = Id::test_new(2); + let bar = builder.import_function(bar_id); + + // Call a primitive operation that uses Brillig + let v0_div_v1 = builder.insert_binary(main_v0, BinaryOp::Div, main_v1); + builder.insert_constrain(v0_div_v1, main_v2, None); + + // Insert multiple calls to the same Brillig function + builder.insert_call(foo, vec![main_v0, main_v1], vec![Type::field()]).to_vec(); + builder.insert_call(foo, vec![main_v0, main_v1], vec![Type::field()]).to_vec(); + builder.insert_call(bar, vec![main_v0, main_v1], vec![Type::field()]).to_vec(); + + // Call the same primitive operation again + let v1_div_v2 = builder.insert_binary(main_v1, BinaryOp::Div, main_v2); + let one = builder.numeric_constant(1u128, Type::unsigned(32)); + builder.insert_constrain(v1_div_v2, one, None); + + builder.terminate_with_return(vec![]); + + build_basic_foo_with_return(&mut builder, foo_id, true); + build_basic_foo_with_return(&mut builder, bar_id, false); + + let ssa = builder.finish(); + // We need to generate Brillig artifacts for the regular Brillig function and pass them to the ACIR generation pass. + let brillig = ssa.to_brillig(false); + println!("{}", ssa); + + let (acir_functions, brillig_functions) = ssa + .into_acir(&brillig, noirc_frontend::ast::Distinctness::Distinct) + .expect("Should compile manually written SSA into ACIR"); + + assert_eq!(acir_functions.len(), 2, "Should only have two ACIR functions"); + // We expect 3 brillig functions: + // - Quotient (shared between both divisions) + // - Inversion, caused by division-by-zero check (shared between both divisions) + // - Custom brillig function `foo` + assert_eq!( + brillig_functions.len(), + 3, + "Should only have generated three Brillig functions" + ); + + let main_acir = &acir_functions[0]; + let main_opcodes = main_acir.opcodes(); + check_brillig_calls( + &acir_functions[0].brillig_stdlib_func_locations, + main_opcodes, + 1, + 4, + 2, + ); + + let foo_acir = &acir_functions[1]; + let foo_opcodes = foo_acir.opcodes(); + check_brillig_calls(&acir_functions[1].brillig_stdlib_func_locations, foo_opcodes, 1, 1, 0); + } + + fn check_brillig_calls( + brillig_stdlib_function_locations: &BTreeMap, + opcodes: &[Opcode], + num_normal_brillig_functions: u32, + expected_num_stdlib_calls: u32, + expected_num_normal_calls: u32, + ) { + // First we check calls to the Brillig stdlib + let mut num_brillig_stdlib_calls = 0; + for (i, (opcode_location, brillig_stdlib_func)) in + brillig_stdlib_function_locations.iter().enumerate() + { + // We can take just modulo 2 to determine the expected ID as we only code generated two Brillig stdlib function + let stdlib_func_index = (i % 2) as u32; + if stdlib_func_index == 0 { + assert!(matches!(brillig_stdlib_func, BrilligStdlibFunc::Inverse)); + } else { + assert!(matches!(brillig_stdlib_func, BrilligStdlibFunc::Quotient(_))); + } + + match opcode_location { + OpcodeLocation::Acir(acir_index) => { + match opcodes[*acir_index] { + Opcode::BrilligCall { id, .. } => { + // Brillig stdlib function calls are only resolved at the end of ACIR generation so their + // IDs are expected to always reference Brillig bytecode at the end of the Brillig functions list. + // We have one normal Brillig call so we add one here to the std lib function's index within the std lib. + let expected_id = stdlib_func_index + num_normal_brillig_functions; + assert_eq!(id, expected_id, "Expected {expected_id} but got {id}"); + num_brillig_stdlib_calls += 1; + } + _ => panic!("Expected BrilligCall opcode"), + } + } + _ => panic!("Expected OpcodeLocation::Acir"), + } + } + + assert_eq!( + num_brillig_stdlib_calls, expected_num_stdlib_calls, + "Should have {expected_num_stdlib_calls} BrilligCall opcodes to stdlib functions but got {num_brillig_stdlib_calls}" + ); + + // Check the normal Brillig calls + // This check right now expects to only call one Brillig function. + let mut num_normal_brillig_calls = 0; + for (i, opcode) in opcodes.iter().enumerate() { + match opcode { + Opcode::BrilligCall { id, .. } => { + if brillig_stdlib_function_locations.get(&OpcodeLocation::Acir(i)).is_some() { + // We should have already checked Brillig stdlib functions and only want to check normal Brillig calls here + continue; + } + // We only generate one normal Brillig call so we should expect a function ID of `0` + let expected_id = 0u32; + assert_eq!(*id, expected_id, "Expected an id of {expected_id} but got {id}"); + num_normal_brillig_calls += 1; + } + _ => {} + } + } + + assert_eq!( + num_normal_brillig_calls, expected_num_normal_calls, + "Should have {expected_num_normal_calls} BrilligCall opcodes to normal Brillig functions but got {num_normal_brillig_calls}" + ); + } } diff --git a/noir/noir-repo/tooling/noir_js_backend_barretenberg/package.json b/noir/noir-repo/tooling/noir_js_backend_barretenberg/package.json index af9e47a8e63..438e91ff302 100644 --- a/noir/noir-repo/tooling/noir_js_backend_barretenberg/package.json +++ b/noir/noir-repo/tooling/noir_js_backend_barretenberg/package.json @@ -42,7 +42,7 @@ "lint": "NODE_NO_WARNINGS=1 eslint . --ext .ts --ignore-path ./.eslintignore --max-warnings 0" }, "dependencies": { - "@aztec/bb.js": "0.35.1", + "@aztec/bb.js": "portal:../../../../barretenberg/ts", "@noir-lang/types": "workspace:*", "fflate": "^0.8.0" }, diff --git a/noir/noir-repo/yarn.lock b/noir/noir-repo/yarn.lock index e9915882fac..b45678f5d8b 100644 --- a/noir/noir-repo/yarn.lock +++ b/noir/noir-repo/yarn.lock @@ -221,19 +221,18 @@ __metadata: languageName: node linkType: hard -"@aztec/bb.js@npm:0.35.1": - version: 0.35.1 - resolution: "@aztec/bb.js@npm:0.35.1" +"@aztec/bb.js@portal:../../../../barretenberg/ts::locator=%40noir-lang%2Fbackend_barretenberg%40workspace%3Atooling%2Fnoir_js_backend_barretenberg": + version: 0.0.0-use.local + resolution: "@aztec/bb.js@portal:../../../../barretenberg/ts::locator=%40noir-lang%2Fbackend_barretenberg%40workspace%3Atooling%2Fnoir_js_backend_barretenberg" dependencies: comlink: ^4.4.1 commander: ^10.0.1 debug: ^4.3.4 tslib: ^2.4.0 bin: - bb.js: dest/node/main.js - checksum: 8e3551f059523d9494af4721a9219e2c6e63c8ed1df447a2d0daa9f8526a794758ae708bd1d9c9b1fbfb89c56dc867d9f0b87250dbabfcde23ec02dabbb5a32a + bb.js: ./dest/node/main.js languageName: node - linkType: hard + linkType: soft "@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.12.11, @babel/code-frame@npm:^7.16.0, @babel/code-frame@npm:^7.22.13, @babel/code-frame@npm:^7.23.5, @babel/code-frame@npm:^7.8.3": version: 7.23.5 @@ -4396,7 +4395,7 @@ __metadata: version: 0.0.0-use.local resolution: "@noir-lang/backend_barretenberg@workspace:tooling/noir_js_backend_barretenberg" dependencies: - "@aztec/bb.js": 0.35.1 + "@aztec/bb.js": "portal:../../../../barretenberg/ts" "@noir-lang/types": "workspace:*" "@types/node": ^20.6.2 "@types/prettier": ^3 From ae183960a96d14d1eac2876bc070ed09f75b8f25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Tue, 23 Apr 2024 13:03:51 -0300 Subject: [PATCH 091/102] feat!: delete field note (#5959) `TestContract` was its sole user, so I just created `TestNote` inside that crate to replace it. Closes https://github.com/AztecProtocol/aztec-packages/issues/5932 --- docs/docs/developers/contracts/main.md | 2 +- docs/docs/misc/migration_notes.md | 6 ++++++ noir-projects/aztec-nr/Nargo.toml | 1 - noir-projects/aztec-nr/field-note/Nargo.toml | 8 -------- noir-projects/aztec-nr/field-note/src/lib.nr | 1 - .../import_test_contract/src/main.nr | 1 - .../contracts/test_contract/Nargo.toml | 1 - .../contracts/test_contract/src/main.nr | 19 ++++++++++--------- .../contracts/test_contract/src/test_note.nr} | 18 +++++++++--------- .../token_blacklist_contract/Nargo.toml | 3 +-- .../token_blacklist_contract/src/main.nr | 2 -- .../src/e2e_non_contract_account.test.ts | 4 ++-- 12 files changed, 29 insertions(+), 37 deletions(-) delete mode 100644 noir-projects/aztec-nr/field-note/Nargo.toml delete mode 100644 noir-projects/aztec-nr/field-note/src/lib.nr rename noir-projects/{aztec-nr/field-note/src/field_note.nr => noir-contracts/contracts/test_contract/src/test_note.nr} (63%) diff --git a/docs/docs/developers/contracts/main.md b/docs/docs/developers/contracts/main.md index 2507154c6ba..b2ac8781286 100644 --- a/docs/docs/developers/contracts/main.md +++ b/docs/docs/developers/contracts/main.md @@ -2,7 +2,7 @@ title: Smart Contracts --- -This section is a collection of how-to guides and references for building smart contracts with Aztec.nr. +This section is a collection of how-to guides and references for building smart contracts with Aztec.nr. If you are looking for an overview of how smart contracts work, head to the [Concepts section](../../learn/concepts/smart_contracts/main.md). diff --git a/docs/docs/misc/migration_notes.md b/docs/docs/misc/migration_notes.md index ed02683b00b..9848ff58b55 100644 --- a/docs/docs/misc/migration_notes.md +++ b/docs/docs/misc/migration_notes.md @@ -8,6 +8,12 @@ Aztec is in full-speed development. Literally every version breaks compatibility ## 0.36.0 +## `FieldNote` removed + +`FieldNote` only existed for testing purposes, and was not a note type that should be used in any real application. Its name unfortunately led users to think that it was a note type suitable to store a `Field` value, which it wasn't. + +If using `FieldNote`, you most likely want to use `ValueNote` instead, which has both randomness for privacy and an owner for proper nullification. + ## `SlowUpdatesTree` replaced for `SharedMutable` The old `SlowUpdatesTree` contract and libraries have been removed from the codebase, use the new `SharedMutable` library instead. This will require that you add a global variable specifying a delay in blocks for updates, and replace the slow updates tree state variable with `SharedMutable` variables. diff --git a/noir-projects/aztec-nr/Nargo.toml b/noir-projects/aztec-nr/Nargo.toml index e3d50c4968d..144579450f1 100644 --- a/noir-projects/aztec-nr/Nargo.toml +++ b/noir-projects/aztec-nr/Nargo.toml @@ -5,7 +5,6 @@ members = [ "aztec", "compressed-string", "easy-private-state", - "field-note", "value-note", "tests", ] diff --git a/noir-projects/aztec-nr/field-note/Nargo.toml b/noir-projects/aztec-nr/field-note/Nargo.toml deleted file mode 100644 index 908a532b295..00000000000 --- a/noir-projects/aztec-nr/field-note/Nargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[package] -name = "field_note" -authors = ["aztec-labs"] -compiler_version = ">=0.18.0" -type = "lib" - -[dependencies] -aztec = { path = "../aztec" } \ No newline at end of file diff --git a/noir-projects/aztec-nr/field-note/src/lib.nr b/noir-projects/aztec-nr/field-note/src/lib.nr deleted file mode 100644 index 71523fc462b..00000000000 --- a/noir-projects/aztec-nr/field-note/src/lib.nr +++ /dev/null @@ -1 +0,0 @@ -mod field_note; diff --git a/noir-projects/noir-contracts/contracts/import_test_contract/src/main.nr b/noir-projects/noir-contracts/contracts/import_test_contract/src/main.nr index 9224c0c2a3e..92636928014 100644 --- a/noir-projects/noir-contracts/contracts/import_test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/import_test_contract/src/main.nr @@ -5,7 +5,6 @@ contract ImportTest { use dep::test::{Test, Test::DeepStruct, Test::DummyNote}; - use dep::test::Test::FieldNote; use dep::test::Test::ValueNote; // Calls the test_code_gen on the Test contract at the target address diff --git a/noir-projects/noir-contracts/contracts/test_contract/Nargo.toml b/noir-projects/noir-contracts/contracts/test_contract/Nargo.toml index c1e9abeb6a9..8ddc423b451 100644 --- a/noir-projects/noir-contracts/contracts/test_contract/Nargo.toml +++ b/noir-projects/noir-contracts/contracts/test_contract/Nargo.toml @@ -6,6 +6,5 @@ type = "contract" [dependencies] aztec = { path = "../../../aztec-nr/aztec" } -field_note = { path = "../../../aztec-nr/field-note" } value_note = { path = "../../../aztec-nr/value-note" } token_portal_content_hash_lib = { path = "../token_portal_content_hash_lib" } diff --git a/noir-projects/noir-contracts/contracts/test_contract/src/main.nr b/noir-projects/noir-contracts/contracts/test_contract/src/main.nr index a7e897ad564..f7a40cf41a8 100644 --- a/noir-projects/noir-contracts/contracts/test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/test_contract/src/main.nr @@ -1,5 +1,8 @@ +mod test_note; + // A contract used for testing a random hodgepodge of small features from simulator and end-to-end tests. contract Test { + use dep::aztec::prelude::{ AztecAddress, EthAddress, FunctionSelector, NoteHeader, NoteGetterOptions, NoteViewerOptions, PrivateContext, PrivateImmutable, PrivateSet, SharedImmutable @@ -25,9 +28,10 @@ contract Test { oracle::{get_public_key::get_public_key as get_public_key_oracle, unsafe_rand::unsafe_rand} }; use dep::token_portal_content_hash_lib::{get_mint_private_content_hash, get_mint_public_content_hash}; - use dep::field_note::field_note::FieldNote; use dep::value_note::value_note::ValueNote; + use crate::test_note::TestNote; + #[aztec(event)] struct ExampleEvent { value: Field, @@ -35,8 +39,8 @@ contract Test { #[aztec(storage)] struct Storage { - example_constant: PrivateImmutable, - example_set: PrivateSet, + example_constant: PrivateImmutable, + example_set: PrivateSet, } #[aztec(private)] @@ -122,10 +126,7 @@ contract Test { opt_notes[0].unwrap().value } - unconstrained fn call_view_notes_many( - storage_slot: Field, - active_or_nullified: bool - ) -> pub [Field; 2] { + unconstrained fn call_view_notes_many(storage_slot: Field, active_or_nullified: bool) -> pub [Field; 2] { assert( storage_slot != storage.example_constant.get_storage_slot(), "this storage slot is reserved for example_constant" ); @@ -298,7 +299,7 @@ contract Test { #[aztec(private)] fn set_constant(value: Field) { - let mut note = FieldNote::new(value); + let mut note = TestNote::new(value); storage.example_constant.initialize(&mut note, false); } @@ -352,7 +353,7 @@ contract Test { let notes_set = storage.example_set; let secret_hash = compute_secret_hash(secret); let mut options = NoteGetterOptions::new(); - options = options.select(FieldNote::properties().value, secret_hash, Option::none()).set_limit(1); + options = options.select(TestNote::properties().value, secret_hash, Option::none()).set_limit(1); let notes = notes_set.get_notes(options); let note = notes[0].unwrap_unchecked(); notes_set.remove(note); diff --git a/noir-projects/aztec-nr/field-note/src/field_note.nr b/noir-projects/noir-contracts/contracts/test_contract/src/test_note.nr similarity index 63% rename from noir-projects/aztec-nr/field-note/src/field_note.nr rename to noir-projects/noir-contracts/contracts/test_contract/src/test_note.nr index f6350ddd613..17f2d2d244d 100644 --- a/noir-projects/aztec-nr/field-note/src/field_note.nr +++ b/noir-projects/noir-contracts/contracts/test_contract/src/test_note.nr @@ -3,17 +3,18 @@ use dep::aztec::{ context::PrivateContext }; -global FIELD_NOTE_LEN: Field = 1; +global TEST_NOTE_LEN: Field = 1; // A note which stores a field and is expected to be passed around using the `addNote` function. -// WARNING: This Note is not private as it does not contain randomness and hence it can be easy to perform serialized_note -// attack on it. +// WARNING: This Note is not private as it does not contain randomness and hence it can be easy to perform +// serialized_note attack on it. This note has been developed purely for testing purposes so that it can easily be +// manually added to PXE. Do not use for real applications. #[aztec(note)] -struct FieldNote { +struct TestNote { value: Field, } -impl NoteInterface for FieldNote { +impl NoteInterface for TestNote { fn compute_nullifier(self, _context: &mut PrivateContext) -> Field { // This note is expected to be shared between users and for this reason can't be nullified using a secret. @@ -27,14 +28,13 @@ impl NoteInterface for FieldNote { fn broadcast(self, context: &mut PrivateContext, slot: Field) { assert( - false, "FieldNote does not support broadcast. Add it to PXE directly using the `.addNote` function." + false, "TestNote does not support broadcast. Add it to PXE directly using the `.addNote` function." ); } } -impl FieldNote { +impl TestNote { pub fn new(value: Field) -> Self { - FieldNote { value, header: NoteHeader::empty() } + TestNote { value, header: NoteHeader::empty() } } } - diff --git a/noir-projects/noir-contracts/contracts/token_blacklist_contract/Nargo.toml b/noir-projects/noir-contracts/contracts/token_blacklist_contract/Nargo.toml index ee4f8aa622b..f5800913173 100644 --- a/noir-projects/noir-contracts/contracts/token_blacklist_contract/Nargo.toml +++ b/noir-projects/noir-contracts/contracts/token_blacklist_contract/Nargo.toml @@ -6,5 +6,4 @@ type = "contract" [dependencies] aztec = { path = "../../../aztec-nr/aztec" } -field_note = { path = "../../../aztec-nr/field-note" } -authwit = { path = "../../../aztec-nr/authwit" } \ No newline at end of file +authwit = { path = "../../../aztec-nr/authwit" } diff --git a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr index 5ec01d4f26a..a6572b4e54c 100644 --- a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr @@ -18,8 +18,6 @@ contract TokenBlacklist { state_vars::{Map, PublicMutable, PrivateSet, SharedMutable, SharedImmutable} }; - use dep::field_note::field_note::FieldNote; - use dep::authwit::{auth::{assert_current_call_valid_authwit, assert_current_call_valid_authwit_public}}; use crate::types::{transparent_note::TransparentNote, token_note::TokenNote, balances_map::BalancesMap, roles::UserFlags}; diff --git a/yarn-project/end-to-end/src/e2e_non_contract_account.test.ts b/yarn-project/end-to-end/src/e2e_non_contract_account.test.ts index 100ad4c7646..8b08c8fa4fc 100644 --- a/yarn-project/end-to-end/src/e2e_non_contract_account.test.ts +++ b/yarn-project/end-to-end/src/e2e_non_contract_account.test.ts @@ -65,7 +65,7 @@ describe('e2e_non_contract_account', () => { }, 120_000); // Note: This test doesn't really belong here as it doesn't have anything to do with non-contract accounts. I needed - // to test the FieldNote functionality and it doesn't really fit anywhere else. Creating a separate e2e test for this + // to test the TestNote functionality and it doesn't really fit anywhere else. Creating a separate e2e test for this // seems wasteful. Move this test if a better place is found. it('can set and get a constant', async () => { const value = 123n; @@ -86,7 +86,7 @@ describe('e2e_non_contract_account', () => { wallet.getCompleteAddress().address, contract.address, TestContract.storage.example_constant.slot, - TestContract.notes.FieldNote.id, + TestContract.notes.TestNote.id, txHash, ); await wallet.addNote(extendedNote); From d8fcfb590f788b911111010e20458797d76f5779 Mon Sep 17 00:00:00 2001 From: ledwards2225 <98505400+ledwards2225@users.noreply.github.com> Date: Tue, 23 Apr 2024 09:16:39 -0700 Subject: [PATCH 092/102] feat: Keshas skipping plus conditions for grand prod relations (#5766) Adds Kesha's relation skipping approach for Sumcheck only (i.e. full proof construction / decider), not for folding. My only addition is a condition for skipping the permutation relation. (I added a condition for skipping the lookup relation but it leads to erratic failures in acir tests that I couldn't explain. Details written into an [issue](https://github.com/AztecProtocol/barretenberg/issues/952)). Closes: https://github.com/AztecProtocol/barretenberg/issues/870 (Taking advantage of sorted trace in sumcheck) Master bench: ``` --------------------------------------------------------------------------------------- Benchmark Time CPU Iterations --------------------------------------------------------------------------------------- construct_proof_ultrahonk/sha256 426 ms 397 ms 2 construct_proof_ultrahonk/keccak 1627 ms 1517 ms 1 construct_proof_ultrahonk/ecdsa_verification 2974 ms 2754 ms 1 construct_proof_ultrahonk/merkle_membership 237 ms 219 ms 3 construct_proof_ultrahonk_power_of_2/15 249 ms 231 ms 3 construct_proof_ultrahonk_power_of_2/16 455 ms 427 ms 2 construct_proof_ultrahonk_power_of_2/17 886 ms 831 ms 1 construct_proof_ultrahonk_power_of_2/18 1762 ms 1657 ms 1 construct_proof_ultrahonk_power_of_2/19 3428 ms 3211 ms 1 construct_proof_ultrahonk_power_of_2/20 6752 ms 6344 ms 1 ``` Branch: ``` --------------------------------------------------------------------------------------- Benchmark Time CPU Iterations --------------------------------------------------------------------------------------- construct_proof_ultrahonk/sha256 330 ms 262 ms 3 construct_proof_ultrahonk/keccak 1212 ms 1036 ms 1 construct_proof_ultrahonk/ecdsa_verification 2311 ms 1980 ms 1 construct_proof_ultrahonk/merkle_membership 191 ms 158 ms 4 construct_proof_ultrahonk_power_of_2/15 191 ms 176 ms 4 construct_proof_ultrahonk_power_of_2/16 342 ms 316 ms 2 construct_proof_ultrahonk_power_of_2/17 664 ms 614 ms 1 construct_proof_ultrahonk_power_of_2/18 1271 ms 1174 ms 1 construct_proof_ultrahonk_power_of_2/19 2542 ms 2332 ms 1 construct_proof_ultrahonk_power_of_2/20 4944 ms 4540 ms 1 ``` --- .../arithmetization/arithmetization.hpp | 2 -- .../library/grand_product_library.hpp | 2 ++ .../relations/auxiliary_relation.hpp | 9 +++++++++ .../delta_range_constraint_relation.hpp | 9 +++++++++ .../relations/elliptic_relation.hpp | 9 +++++++++ .../barretenberg/relations/lookup_relation.hpp | 12 ++++++++++++ .../relations/permutation_relation.hpp | 12 ++++++++++++ .../relations/poseidon2_external_relation.hpp | 9 +++++++++ .../relations/poseidon2_internal_relation.hpp | 9 +++++++++ .../barretenberg/relations/relation_types.hpp | 15 +++++++++++++++ .../relations/ultra_arithmetic_relation.hpp | 9 +++++++++ .../barretenberg/sumcheck/sumcheck_round.hpp | 17 +++++++++++++++-- 12 files changed, 110 insertions(+), 4 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/arithmetization.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/arithmetization.hpp index eed7d43370d..21490b283cf 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/arithmetization.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/arithmetization.hpp @@ -259,8 +259,6 @@ template class UltraHonkArith { UltraHonkTraceBlock ecc_op; UltraHonkTraceBlock pub_inputs; UltraHonkTraceBlock arithmetic; - // TODO(https://github.com/AztecProtocol/barretenberg/issues/919): Change: DeltaRangeConstraint --> - // DeltaRangeConstraint UltraHonkTraceBlock delta_range; UltraHonkTraceBlock elliptic; UltraHonkTraceBlock aux; diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp index 5d2675649bf..78899bc1a22 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp @@ -71,6 +71,8 @@ void compute_grand_product(const size_t circuit_size, const size_t end = (thread_idx + 1) * block_size; typename Flavor::AllValues evaluations; auto evaluations_view = evaluations.get_all(); + // TODO(https://github.com/AztecProtocol/barretenberg/issues/940): construction of evaluations is equivalent to + // calling get_row which creates full copies. avoid? for (size_t i = start; i < end; ++i) { for (auto [eval, full_poly] : zip_view(evaluations_view, full_polynomials_view)) { eval = full_poly.size() > i ? full_poly[i] : 0; diff --git a/barretenberg/cpp/src/barretenberg/relations/auxiliary_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/auxiliary_relation.hpp index 144ebdf9808..ea8e4b40e73 100644 --- a/barretenberg/cpp/src/barretenberg/relations/auxiliary_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/auxiliary_relation.hpp @@ -49,6 +49,15 @@ template class AuxiliaryRelationImpl { 1 // RAM consistency sub-relation 3 }; + /** + * @brief Returns true if the contribution from all subrelations for the provided inputs is identically zero + * + */ + template inline static bool skip(const AllEntities& in) + { + return (in.q_aux.value_at(0).is_zero() && in.q_aux.value_at(1).is_zero()); + } + /** * @brief Expression for the generalized permutation sort gate. * @details The following explanation is reproduced from the Plonk analog 'plookup_auxiliary_widget': diff --git a/barretenberg/cpp/src/barretenberg/relations/delta_range_constraint_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/delta_range_constraint_relation.hpp index dee7759db07..25429fbc002 100644 --- a/barretenberg/cpp/src/barretenberg/relations/delta_range_constraint_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/delta_range_constraint_relation.hpp @@ -14,6 +14,15 @@ template class DeltaRangeConstraintRelationImpl { 6 // range constrain sub-relation 4 }; + /** + * @brief Returns true if the contribution from all subrelations for the provided inputs is identically zero + * + */ + template inline static bool skip(const AllEntities& in) + { + return (in.q_delta_range.value_at(0).is_zero() && in.q_delta_range.value_at(1).is_zero()); + } + /** * @brief Expression for the generalized permutation sort gate. * @details The relation is defined as C(in(X)...) = diff --git a/barretenberg/cpp/src/barretenberg/relations/elliptic_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/elliptic_relation.hpp index f6201145fba..2c0b2a85062 100644 --- a/barretenberg/cpp/src/barretenberg/relations/elliptic_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/elliptic_relation.hpp @@ -14,6 +14,15 @@ template class EllipticRelationImpl { 6, // y-coordinate sub-relation }; + /** + * @brief Returns true if the contribution from all subrelations for the provided inputs is identically zero + * + */ + template inline static bool skip(const AllEntities& in) + { + return (in.q_elliptic.value_at(0).is_zero() && in.q_elliptic.value_at(1).is_zero()); + } + // TODO(@zac-williamson #2609 find more generic way of doing this) static constexpr FF get_curve_b() { diff --git a/barretenberg/cpp/src/barretenberg/relations/lookup_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/lookup_relation.hpp index a9a4bd3fb47..337469bd5c8 100644 --- a/barretenberg/cpp/src/barretenberg/relations/lookup_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/lookup_relation.hpp @@ -31,6 +31,18 @@ template class LookupRelationImpl { 4, // grand product construction sub-relation 0 // left-shiftable polynomial sub-relation }; + + /** + * @brief Returns true if the contribution from all subrelations for the provided inputs is identically zero + * + */ + template inline static bool skip([[maybe_unused]] const AllEntities& in) + { + // TODO(https://github.com/AztecProtocol/barretenberg/issues/952): figure out why skip condition described in + // issue causes failures in acir tests. + return false; + } + /** * @brief Get the grand product polynomial object (either from the proving key or AllEntities depending on context) * diff --git a/barretenberg/cpp/src/barretenberg/relations/permutation_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/permutation_relation.hpp index d52fe2951eb..8ff08be35d2 100644 --- a/barretenberg/cpp/src/barretenberg/relations/permutation_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/permutation_relation.hpp @@ -17,6 +17,18 @@ template class UltraPermutationRelationImpl { 0 // left-shiftable polynomial sub-relation }; + /** + * @brief Returns true if the contribution from all subrelations for the provided inputs is identically zero + * + */ + template inline static bool skip(const AllEntities& in) + { + // If z_perm == z_perm_shift, this implies that none of the wire values for the present input are involved in + // non-trivial copy constraints. + return (in.z_perm.value_at(0) == in.z_perm_shift.value_at(0) && + in.z_perm.value_at(1) == in.z_perm_shift.value_at(1)); + } + inline static auto& get_grand_product_polynomial(auto& in) { return in.z_perm; } inline static auto& get_shifted_grand_product_polynomial(auto& in) { return in.z_perm_shift; } diff --git a/barretenberg/cpp/src/barretenberg/relations/poseidon2_external_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/poseidon2_external_relation.hpp index 274b644db9c..29d082b4a4e 100644 --- a/barretenberg/cpp/src/barretenberg/relations/poseidon2_external_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/poseidon2_external_relation.hpp @@ -13,6 +13,15 @@ template class Poseidon2ExternalRelationImpl { 7, // external poseidon2 round sub-relation for fourth value }; + /** + * @brief Returns true if the contribution from all subrelations for the provided inputs is identically zero + * + */ + template inline static bool skip(const AllEntities& in) + { + return (in.q_poseidon2_external.value_at(0).is_zero() && in.q_poseidon2_external.value_at(1).is_zero()); + } + /** * @brief Expression for the poseidon2 external round relation, based on E_i in Section 6 of * https://eprint.iacr.org/2023/323.pdf. diff --git a/barretenberg/cpp/src/barretenberg/relations/poseidon2_internal_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/poseidon2_internal_relation.hpp index db4d4b02576..e2199935868 100644 --- a/barretenberg/cpp/src/barretenberg/relations/poseidon2_internal_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/poseidon2_internal_relation.hpp @@ -15,6 +15,15 @@ template class Poseidon2InternalRelationImpl { 7, // internal poseidon2 round sub-relation for fourth value }; + /** + * @brief Returns true if the contribution from all subrelations for the provided inputs is identically zero + * + */ + template inline static bool skip(const AllEntities& in) + { + return (in.q_poseidon2_internal.value_at(0).is_zero() && in.q_poseidon2_internal.value_at(1).is_zero()); + } + /** * @brief Expression for the poseidon2 internal round relation, based on I_i in Section 6 of * https://eprint.iacr.org/2023/323.pdf. diff --git a/barretenberg/cpp/src/barretenberg/relations/relation_types.hpp b/barretenberg/cpp/src/barretenberg/relations/relation_types.hpp index be4b8732254..aa4ba8820b7 100644 --- a/barretenberg/cpp/src/barretenberg/relations/relation_types.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/relation_types.hpp @@ -111,6 +111,21 @@ consteval std::array compute_composed_subrelation_part * */ +/** + * @brief Check if the relation has a static skip method to determine if accumulation of its result can be + * optimised away based on a single check + * + * @details The skip function should return true if relation can be skipped and false if it can't + * @tparam Relation The relation type + * @tparam AllEntities The type containing UnivariateViews with witness and selector values + */ +template +concept isSkippable = requires(const AllEntities& input) { + { + Relation::is_active(input) + } -> std::same_as; + }; + /** * @brief A wrapper for Relations to expose methods used by the Sumcheck prover or verifier to add the * contribution of a given relation to the corresponding accumulator. diff --git a/barretenberg/cpp/src/barretenberg/relations/ultra_arithmetic_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/ultra_arithmetic_relation.hpp index 898e3a7d144..7a5a1e0d917 100644 --- a/barretenberg/cpp/src/barretenberg/relations/ultra_arithmetic_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/ultra_arithmetic_relation.hpp @@ -12,6 +12,15 @@ template class UltraArithmeticRelationImpl { 5 // secondary arithmetic sub-relation }; + /** + * @brief Returns true if the contribution from all subrelations for the provided inputs is identically zero + * + */ + template inline static bool skip(const AllEntities& in) + { + return (in.q_arith.value_at(0).is_zero() && in.q_arith.value_at(1).is_zero()); + } + /** * @brief Expression for the Ultra Arithmetic gate. * @details This relation encapsulates several idenitities, toggled by the value of q_arith in [0, 1, 2, 3, ...]. diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp index b3129797af4..de237e915de 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp @@ -237,8 +237,21 @@ template class SumcheckProverRound { const FF& scaling_factor) { using Relation = std::tuple_element_t; - Relation::accumulate( - std::get(univariate_accumulators), extended_edges, relation_parameters, scaling_factor); + + // Check if the relation is skippable to speed up accumulation + if constexpr (!isSkippable) { + // If not, accumulate normally + Relation::accumulate( + std::get(univariate_accumulators), extended_edges, relation_parameters, scaling_factor); + } else { + // If so, only compute the contribution if the relation is active + if (!Relation::skip(extended_edges, relation_parameters)) { + Relation::accumulate(std::get(univariate_accumulators), + extended_edges, + relation_parameters, + scaling_factor); + } + } // Repeat for the next relation. if constexpr (relation_idx + 1 < NUM_RELATIONS) { From 6cd3ed879abf30e17416e60e3967bebeb29152a4 Mon Sep 17 00:00:00 2001 From: AztecBot Date: Wed, 24 Apr 2024 02:10:03 +0000 Subject: [PATCH 093/102] git subrepo push --branch=master barretenberg subrepo: subdir: "barretenberg" merged: "40fdf900b" upstream: origin: "https://github.com/AztecProtocol/barretenberg" branch: "master" commit: "40fdf900b" git-subrepo: version: "0.4.6" origin: "???" commit: "???" [skip ci] --- barretenberg/.gitrepo | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/barretenberg/.gitrepo b/barretenberg/.gitrepo index 9a0026683b9..51be7b3baa8 100644 --- a/barretenberg/.gitrepo +++ b/barretenberg/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = https://github.com/AztecProtocol/barretenberg branch = master - commit = 9f614992fee549b4e3bd90d208faf2c68ea2cbcc - parent = 1d3af93f26d7b09389debe4b7046ae3359ff1893 + commit = 40fdf900bf687d93bd2eb7e54ee39d336346097a + parent = d8fcfb590f788b911111010e20458797d76f5779 method = merge cmdver = 0.4.6 From 41d6e81426090c5b8c50787123bac826a732204d Mon Sep 17 00:00:00 2001 From: AztecBot Date: Wed, 24 Apr 2024 02:10:33 +0000 Subject: [PATCH 094/102] chore: replace relative paths to noir-protocol-circuits --- noir-projects/aztec-nr/aztec/Nargo.toml | 2 +- noir-projects/aztec-nr/tests/Nargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/Nargo.toml b/noir-projects/aztec-nr/aztec/Nargo.toml index 7a1f1af5863..2cbb43ab278 100644 --- a/noir-projects/aztec-nr/aztec/Nargo.toml +++ b/noir-projects/aztec-nr/aztec/Nargo.toml @@ -5,4 +5,4 @@ compiler_version = ">=0.18.0" type = "lib" [dependencies] -protocol_types = { path = "../../noir-protocol-circuits/crates/types" } +protocol_types = { git="https://github.com/AztecProtocol/aztec-packages", tag="aztec-packages-v0.35.1", directory="noir-projects/noir-protocol-circuits/crates/types" } diff --git a/noir-projects/aztec-nr/tests/Nargo.toml b/noir-projects/aztec-nr/tests/Nargo.toml index 13404b37324..dfed895aad0 100644 --- a/noir-projects/aztec-nr/tests/Nargo.toml +++ b/noir-projects/aztec-nr/tests/Nargo.toml @@ -6,4 +6,4 @@ type = "lib" [dependencies] aztec = { path = "../aztec" } -protocol_types = { path = "../../noir-protocol-circuits/crates/types" } +protocol_types = { git="https://github.com/AztecProtocol/aztec-packages", tag="aztec-packages-v0.35.1", directory="noir-projects/noir-protocol-circuits/crates/types" } From 83bbfa04c2b474444f63439e11f7f50b06c4e5bc Mon Sep 17 00:00:00 2001 From: AztecBot Date: Wed, 24 Apr 2024 02:10:33 +0000 Subject: [PATCH 095/102] git_subrepo.sh: Fix parent in .gitrepo file. [skip ci] --- noir-projects/aztec-nr/.gitrepo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noir-projects/aztec-nr/.gitrepo b/noir-projects/aztec-nr/.gitrepo index d4ca16357d6..23a65cc16df 100644 --- a/noir-projects/aztec-nr/.gitrepo +++ b/noir-projects/aztec-nr/.gitrepo @@ -9,4 +9,4 @@ commit = ae7ae61940773b35fe5ed5cfa0c00e0efe3aa3f7 method = merge cmdver = 0.4.6 - parent = fc6676ce51fb25463bb32c35575232ca151f89cb + parent = f5e9efabbdaf03e6b16506c8e50e5c4b46284a3e From 51321430205f47581d7ebd17b8138d64c787da42 Mon Sep 17 00:00:00 2001 From: AztecBot Date: Wed, 24 Apr 2024 02:10:37 +0000 Subject: [PATCH 096/102] git subrepo push --branch=master noir-projects/aztec-nr subrepo: subdir: "noir-projects/aztec-nr" merged: "d4be027d4" upstream: origin: "https://github.com/AztecProtocol/aztec-nr" branch: "master" commit: "d4be027d4" git-subrepo: version: "0.4.6" origin: "???" commit: "???" [skip ci] --- noir-projects/aztec-nr/.gitrepo | 4 ++-- noir-projects/aztec-nr/aztec/Nargo.toml | 2 +- noir-projects/aztec-nr/tests/Nargo.toml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/noir-projects/aztec-nr/.gitrepo b/noir-projects/aztec-nr/.gitrepo index 23a65cc16df..67d3d4a8106 100644 --- a/noir-projects/aztec-nr/.gitrepo +++ b/noir-projects/aztec-nr/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = https://github.com/AztecProtocol/aztec-nr branch = master - commit = ae7ae61940773b35fe5ed5cfa0c00e0efe3aa3f7 + commit = d4be027d470ca2faf8795043b5c91bbe37990b96 method = merge cmdver = 0.4.6 - parent = f5e9efabbdaf03e6b16506c8e50e5c4b46284a3e + parent = 6bd644f98bae8e23c4e0de99edc12f5361c3d160 diff --git a/noir-projects/aztec-nr/aztec/Nargo.toml b/noir-projects/aztec-nr/aztec/Nargo.toml index 2cbb43ab278..7a1f1af5863 100644 --- a/noir-projects/aztec-nr/aztec/Nargo.toml +++ b/noir-projects/aztec-nr/aztec/Nargo.toml @@ -5,4 +5,4 @@ compiler_version = ">=0.18.0" type = "lib" [dependencies] -protocol_types = { git="https://github.com/AztecProtocol/aztec-packages", tag="aztec-packages-v0.35.1", directory="noir-projects/noir-protocol-circuits/crates/types" } +protocol_types = { path = "../../noir-protocol-circuits/crates/types" } diff --git a/noir-projects/aztec-nr/tests/Nargo.toml b/noir-projects/aztec-nr/tests/Nargo.toml index dfed895aad0..13404b37324 100644 --- a/noir-projects/aztec-nr/tests/Nargo.toml +++ b/noir-projects/aztec-nr/tests/Nargo.toml @@ -6,4 +6,4 @@ type = "lib" [dependencies] aztec = { path = "../aztec" } -protocol_types = { git="https://github.com/AztecProtocol/aztec-packages", tag="aztec-packages-v0.35.1", directory="noir-projects/noir-protocol-circuits/crates/types" } +protocol_types = { path = "../../noir-protocol-circuits/crates/types" } From 348b34f868e98c1e6dc388b164b0df6ee131ae6c Mon Sep 17 00:00:00 2001 From: ludamad Date: Wed, 24 Apr 2024 00:36:56 -0500 Subject: [PATCH 097/102] chore(ci): reenable spot We will have to move back to on-demand if spot keeps getting taken down. --- .github/workflows/setup-runner.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/setup-runner.yml b/.github/workflows/setup-runner.yml index 80d3bd59056..b0b4139d8bf 100644 --- a/.github/workflows/setup-runner.yml +++ b/.github/workflows/setup-runner.yml @@ -30,7 +30,7 @@ on: default: sg-0ccd4e5df0dcca0c9 type: string ec2_spot_instance_strategy: - default: None + default: BestEffort type: string aws_region: default: "us-east-2" From 3a10e5e75b8053dfea13a4901873d42ca01ca7c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Bene=C5=A1?= Date: Wed, 24 Apr 2024 11:11:42 +0200 Subject: [PATCH 098/102] refactor: using poseidon2 when computing a nullifier (#5906) Fixes #5832 Fixes #1205 --- .../references/portals/data_structures.md | 2 +- .../contracts/references/portals/inbox.md | 2 +- .../portals/communicate_with_portal.md | 4 +- .../tutorials/writing_dapp/testing.md | 2 +- .../aztec-nr/address-note/src/address_note.nr | 18 ++++---- noir-projects/aztec-nr/aztec/src/hash.nr | 7 ++- .../aztec-nr/aztec/src/note/utils.nr | 11 +++-- noir-projects/aztec-nr/aztec/src/prelude.nr | 2 +- .../aztec-nr/value-note/src/value_note.nr | 19 ++++---- .../src/subscription_note.nr | 23 +++++----- .../src/types/card_note.nr | 12 +++--- .../src/ecdsa_public_key_note.nr | 22 +++++----- .../contracts/gas_token_contract/src/main.nr | 2 +- .../src/public_key_note.nr | 25 +++++------ .../token_blacklist_contract/src/main.nr | 5 +-- .../src/types/token_note.nr | 22 +++++----- .../src/types/transparent_note.nr | 12 +++--- .../token_bridge_contract/src/main.nr | 2 - .../contracts/token_contract/src/main.nr | 6 ++- .../token_contract/src/types/token_note.nr | 25 ++++++----- .../src/types/transparent_note.nr | 12 +++--- .../crates/types/src/constants.nr | 7 ++- .../src/transforms/note_interface.rs | 6 +-- .../src/fee/private_fee_payment_method.ts | 4 +- yarn-project/aztec.js/src/index.ts | 2 +- yarn-project/aztec/src/examples/token.ts | 4 +- yarn-project/circuits.js/src/constants.gen.ts | 7 ++- .../circuits.js/src/hash/hash.test.ts | 8 ++-- yarn-project/circuits.js/src/hash/hash.ts | 43 ++++++++++++++----- .../src/composed/e2e_persistence.test.ts | 23 +++------- .../src/composed/e2e_sandbox_example.test.ts | 6 +-- .../src/e2e_account_init_fees.test.ts | 6 +-- .../src/e2e_blacklist_token_contract.test.ts | 6 +-- .../end-to-end/src/e2e_cheat_codes.test.ts | 4 +- .../src/e2e_crowdfunding_and_claim.test.ts | 4 +- .../src/e2e_escrow_contract.test.ts | 6 +-- yarn-project/end-to-end/src/e2e_fees.test.ts | 16 +++---- .../src/e2e_lending_contract.test.ts | 4 +- .../e2e_multiple_accounts_1_enc_key.test.ts | 4 +- .../e2e_public_cross_chain_messaging.test.ts | 4 +- .../src/e2e_token_contract/minting.test.ts | 4 +- .../src/e2e_token_contract/shielding.test.ts | 4 +- .../e2e_token_contract/token_contract_test.ts | 4 +- .../end-to-end/src/flakey_e2e_2_pxes.test.ts | 4 +- .../src/guides/dapp_testing.test.ts | 8 ++-- .../writing_an_account_contract.test.ts | 4 +- .../end-to-end/src/sample-dapp/index.mjs | 4 +- .../end-to-end/src/sample-dapp/index.test.mjs | 12 +----- yarn-project/end-to-end/src/shared/browser.ts | 4 +- .../src/shared/cross_chain_test_harness.ts | 9 +++- .../src/shared/gas_portal_test_harness.ts | 4 +- .../src/client/client_execution_context.ts | 4 +- .../src/client/private_execution.test.ts | 13 +++--- .../simulator/src/client/simulator.test.ts | 24 +++++++---- .../simulator/src/public/index.test.ts | 6 +-- yarn-project/simulator/src/test/utils.ts | 4 +- 56 files changed, 274 insertions(+), 237 deletions(-) diff --git a/docs/docs/developers/contracts/references/portals/data_structures.md b/docs/docs/developers/contracts/references/portals/data_structures.md index ba97bfd5272..f7a87619edb 100644 --- a/docs/docs/developers/contracts/references/portals/data_structures.md +++ b/docs/docs/developers/contracts/references/portals/data_structures.md @@ -40,7 +40,7 @@ A message that is sent from L1 to L2. | `sender` | `L1Actor` | The actor on L1 that is sending the message. | | `recipient` | `L2Actor` | The actor on L2 that is to receive the message. | | `content` | `field (~254 bits)` | The field element containing the content to be sent to L2. | -| `secretHash` | `field (~254 bits)` | The hash of a secret pre-image that must be known to consume the message on L2. Use the [`computeMessageSecretHash`](https://github.com/AztecProtocol/aztec-packages/blob/master/yarn-project/aztec.js/src/utils/secrets.ts) to compute it from a secret. | +| `secretHash` | `field (~254 bits)` | The hash of a secret pre-image that must be known to consume the message on L2. Use [`computeSecretHash`](https://github.com/AztecProtocol/aztec-packages/blob/master/yarn-project/aztec.js/src/utils/secrets.ts) to compute it from a secret. | ## `L2ToL1Message` diff --git a/docs/docs/developers/contracts/references/portals/inbox.md b/docs/docs/developers/contracts/references/portals/inbox.md index 73b18fc8888..3a33a1dbf06 100644 --- a/docs/docs/developers/contracts/references/portals/inbox.md +++ b/docs/docs/developers/contracts/references/portals/inbox.md @@ -17,7 +17,7 @@ Sends a message from L1 to L2. | -------------- | ------- | ----------- | | Recipient | `L2Actor` | The recipient of the message. This **MUST** match the rollup version and an Aztec contract that is **attached** to the contract making this call. If the recipient is not attached to the caller, the message cannot be consumed by it. | | Content | `field` (~254 bits) | The content of the message. This is the data that will be passed to the recipient. The content is limited to be a single field for rollup purposes. If the content is small enough it can just be passed along, otherwise it should be hashed and the hash passed along (you can use our [`Hash`](https://github.com/AztecProtocol/aztec-packages/blob/master/l1-contracts/src/core/libraries/Hash.sol) utilities with `sha256ToField` functions) | -| Secret Hash | `field` (~254 bits) | A hash of a secret that is used when consuming the message on L2. Keep this preimage a secret to make the consumption private. To consume the message the caller must know the pre-image (the value that was hashed) - so make sure your app keeps track of the pre-images! Use the [`computeMessageSecretHash`](https://github.com/AztecProtocol/aztec-packages/blob/master/yarn-project/aztec.js/src/utils/secrets.ts) to compute it from a secret. | +| Secret Hash | `field` (~254 bits) | A hash of a secret that is used when consuming the message on L2. Keep this preimage a secret to make the consumption private. To consume the message the caller must know the pre-image (the value that was hashed) - so make sure your app keeps track of the pre-images! Use [`computeSecretHash`](https://github.com/AztecProtocol/aztec-packages/blob/master/yarn-project/aztec.js/src/utils/secrets.ts) to compute it from a secret. | | ReturnValue | `bytes32` | The message hash, used as an identifier | #### Edge cases diff --git a/docs/docs/developers/contracts/writing_contracts/portals/communicate_with_portal.md b/docs/docs/developers/contracts/writing_contracts/portals/communicate_with_portal.md index 8d559abe6f0..f84fa3b80ba 100644 --- a/docs/docs/developers/contracts/writing_contracts/portals/communicate_with_portal.md +++ b/docs/docs/developers/contracts/writing_contracts/portals/communicate_with_portal.md @@ -17,7 +17,7 @@ When sending messages, we need to specify quite a bit of information beyond just | Name | Type | Description | | ----------- | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Recipient | `L2Actor` | The message recipient. This **MUST** match the rollup version and an Aztec contract that is **attached** to the contract making this call. If the recipient is not attached to the caller, the message cannot be consumed by it. | -| Secret Hash | `field` (~254 bits) | A hash of a secret that is used when consuming the message on L2. Keep this preimage a secret to make the consumption private. To consume the message the caller must know the pre-image (the value that was hashed) - so make sure your app keeps track of the pre-images! Use the [`computeMessageSecretHash`](https://github.com/AztecProtocol/aztec-packages/blob/master/yarn-project/aztec.js/src/utils/secrets.ts) to compute it from a secret. | +| Secret Hash | `field` (~254 bits) | A hash of a secret that is used when consuming the message on L2. Keep this preimage a secret to make the consumption private. To consume the message the caller must know the pre-image (the value that was hashed) - so make sure your app keeps track of the pre-images! Use [`computeSecretHash`](https://github.com/AztecProtocol/aztec-packages/blob/master/yarn-project/aztec.js/src/utils/secrets.ts) to compute it from a secret. | | Content | `field` (~254 bits) | The content of the message. This is the data that will be passed to the recipient. The content is limited to be a single field. If the content is small enough it can just be passed along, otherwise it should be hashed and the hash passed along (you can use our [`Hash`](https://github.com/AztecProtocol/aztec-packages/blob/master/l1-contracts/src/core/libraries/Hash.sol) utilities with `sha256ToField` functions) With all that information at hand, we can call the `sendL2Message` function on the Inbox. The function will return a `field` (inside `bytes32`) that is the hash of the message. This hash can be used as an identifier to spot when your message has been included in a rollup block. @@ -56,7 +56,7 @@ In Solidity, you can use our `Hash.sha256ToField()` method: #include_code deposit_public l1-contracts/test/portals/TokenPortal.sol solidity -The `secret_hash` uses the pederson hash which fits in a field element. You can use the utility method `computeMessageSecretHash()`in `@aztec/aztec.js` npm package to generate a secret and its corresponding hash. +The `secret_hash` uses the pederson hash which fits in a field element. You can use the utility method `computeSecretHash()`in `@aztec/aztec.js` npm package to generate a secret and its corresponding hash. After the transaction has been mined, the message is consumed, a nullifier is emitted and the tokens have been minted on Aztec and are ready for claiming. diff --git a/docs/docs/developers/tutorials/writing_dapp/testing.md b/docs/docs/developers/tutorials/writing_dapp/testing.md index 8aea22e1de0..3917c059625 100644 --- a/docs/docs/developers/tutorials/writing_dapp/testing.md +++ b/docs/docs/developers/tutorials/writing_dapp/testing.md @@ -26,7 +26,7 @@ import { ExtendedNote, Fr, Note, - computeMessageSecretHash, + computeSecretHash, createPXEClient, waitForPXE, } from "@aztec/aztec.js"; diff --git a/noir-projects/aztec-nr/address-note/src/address_note.nr b/noir-projects/aztec-nr/address-note/src/address_note.nr index 440cfdf3b6f..982b9ba0053 100644 --- a/noir-projects/aztec-nr/address-note/src/address_note.nr +++ b/noir-projects/aztec-nr/address-note/src/address_note.nr @@ -2,10 +2,10 @@ use dep::aztec::log::emit_encrypted_log; // docs:end:encrypted_import use dep::aztec::{ - protocol_types::{address::AztecAddress, traits::Empty}, + protocol_types::{address::AztecAddress, traits::Empty, constants::GENERATOR_INDEX__NOTE_NULLIFIER}, note::{note_header::NoteHeader, note_interface::NoteInterface, utils::compute_note_hash_for_consumption}, oracle::{unsafe_rand::unsafe_rand, nullifier_key::get_app_nullifier_secret_key, get_public_key::get_public_key}, - hash::pedersen_hash, context::PrivateContext + context::PrivateContext, hash::poseidon2_hash }; global ADDRESS_NOTE_LEN: Field = 3; @@ -19,26 +19,26 @@ struct AddressNote { randomness: Field, } -impl NoteInterface for AddressNote { +impl NoteInterface for AddressNote { fn compute_nullifier(self, context: &mut PrivateContext) -> Field { let note_hash_for_nullify = compute_note_hash_for_consumption(self); let secret = context.request_app_nullifier_secret_key(self.owner); - // TODO(#1205) Should use a non-zero generator index. - pedersen_hash([ + poseidon2_hash([ note_hash_for_nullify, secret, - ],0) + GENERATOR_INDEX__NOTE_NULLIFIER as Field, + ]) } fn compute_nullifier_without_context(self) -> Field { let note_hash_for_nullify = compute_note_hash_for_consumption(self); let secret = get_app_nullifier_secret_key(self.owner); - // TODO(#1205) Should use a non-zero generator index. - pedersen_hash([ + poseidon2_hash([ note_hash_for_nullify, secret, - ],0) + GENERATOR_INDEX__NOTE_NULLIFIER as Field, + ]) } // Broadcasts the note as an encrypted log on L1. diff --git a/noir-projects/aztec-nr/aztec/src/hash.nr b/noir-projects/aztec-nr/aztec/src/hash.nr index 8406cf8c298..435df049fa2 100644 --- a/noir-projects/aztec-nr/aztec/src/hash.nr +++ b/noir-projects/aztec-nr/aztec/src/hash.nr @@ -1,15 +1,14 @@ use dep::protocol_types::{ address::{AztecAddress, EthAddress}, constants::{ - GENERATOR_INDEX__L1_TO_L2_MESSAGE_SECRET, GENERATOR_INDEX__NULLIFIER, ARGS_HASH_CHUNK_COUNT, + GENERATOR_INDEX__SECRET_HASH, GENERATOR_INDEX__MESSAGE_NULLIFIER, ARGS_HASH_CHUNK_COUNT, GENERATOR_INDEX__FUNCTION_ARGS, ARGS_HASH_CHUNK_LENGTH }, traits::Hash, hash::{pedersen_hash, poseidon2_hash, silo_nullifier, sha256_to_field} }; pub fn compute_secret_hash(secret: Field) -> Field { - // TODO(#1205) This is probably not the right index to use - pedersen_hash([secret], GENERATOR_INDEX__L1_TO_L2_MESSAGE_SECRET) + pedersen_hash([secret], GENERATOR_INDEX__SECRET_HASH) } pub fn compute_message_hash( @@ -45,7 +44,7 @@ pub fn compute_message_hash( pub fn compute_message_nullifier(message_hash: Field, secret: Field, leaf_index: Field) -> Field { pedersen_hash( [message_hash, secret, leaf_index], - GENERATOR_INDEX__NULLIFIER + GENERATOR_INDEX__MESSAGE_NULLIFIER ) } diff --git a/noir-projects/aztec-nr/aztec/src/note/utils.nr b/noir-projects/aztec-nr/aztec/src/note/utils.nr index 49311d794af..c5c06b46bcb 100644 --- a/noir-projects/aztec-nr/aztec/src/note/utils.nr +++ b/noir-projects/aztec-nr/aztec/src/note/utils.nr @@ -2,7 +2,10 @@ use crate::{context::PrivateContext, note::{note_header::NoteHeader, note_interf use dep::protocol_types::{ address::AztecAddress, - constants::{GENERATOR_INDEX__OUTER_NULLIFIER, GENERATOR_INDEX__UNIQUE_NOTE_HASH, GENERATOR_INDEX__SILOED_NOTE_HASH}, + constants::{ + GENERATOR_INDEX__OUTER_NULLIFIER, GENERATOR_INDEX__UNIQUE_NOTE_HASH, + GENERATOR_INDEX__SILOED_NOTE_HASH, GENERATOR_INDEX__INNER_NOTE_HASH +}, hash::pedersen_hash, utils::arr_copy_slice }; @@ -20,8 +23,10 @@ fn compute_inner_note_hash(note: Note) -> Field where Note: NoteInterfa let header = note.get_header(); let note_hash = note.compute_note_content_hash(); - // TODO(#1205) Do we need a generator index here? - pedersen_hash([header.storage_slot, note_hash], 0) + pedersen_hash( + [header.storage_slot, note_hash], + GENERATOR_INDEX__INNER_NOTE_HASH + ) } fn compute_siloed_note_hash(note_with_header: Note) -> Field where Note: NoteInterface { diff --git a/noir-projects/aztec-nr/aztec/src/prelude.nr b/noir-projects/aztec-nr/aztec/src/prelude.nr index 08177f65e7d..8a9809fa2b1 100644 --- a/noir-projects/aztec-nr/aztec/src/prelude.nr +++ b/noir-projects/aztec-nr/aztec/src/prelude.nr @@ -7,7 +7,7 @@ use crate::{ state_vars::{ map::Map, private_immutable::PrivateImmutable, private_mutable::PrivateMutable, public_immutable::PublicImmutable, public_mutable::PublicMutable, private_set::PrivateSet, - shared_immutable::SharedImmutable, storage::Storable + shared_immutable::SharedImmutable, shared_mutable::SharedMutable, storage::Storable }, log::emit_encrypted_log, context::{PrivateContext, PackedReturns, FunctionReturns}, note::{ diff --git a/noir-projects/aztec-nr/value-note/src/value_note.nr b/noir-projects/aztec-nr/value-note/src/value_note.nr index 8875209b9de..b67cd8a98dc 100644 --- a/noir-projects/aztec-nr/value-note/src/value_note.nr +++ b/noir-projects/aztec-nr/value-note/src/value_note.nr @@ -1,8 +1,11 @@ use dep::aztec::{ - protocol_types::{address::AztecAddress, traits::{Deserialize, Serialize}}, + protocol_types::{ + address::AztecAddress, traits::{Deserialize, Serialize}, + constants::GENERATOR_INDEX__NOTE_NULLIFIER +}, note::{note_header::NoteHeader, note_interface::NoteInterface, utils::compute_note_hash_for_consumption}, oracle::{unsafe_rand::unsafe_rand, nullifier_key::get_app_nullifier_secret_key, get_public_key::get_public_key}, - log::emit_encrypted_log, hash::pedersen_hash, context::PrivateContext + log::emit_encrypted_log, hash::poseidon2_hash, context::PrivateContext }; global VALUE_NOTE_LEN: Field = 3; // 3 plus a header. @@ -22,11 +25,11 @@ impl NoteInterface for ValueNote { fn compute_nullifier(self, context: &mut PrivateContext) -> Field { let note_hash_for_nullify = compute_note_hash_for_consumption(self); let secret = context.request_app_nullifier_secret_key(self.owner); - // TODO(#1205) Should use a non-zero generator index. - pedersen_hash([ + poseidon2_hash([ note_hash_for_nullify, secret, - ],0) + GENERATOR_INDEX__NOTE_NULLIFIER as Field, + ]) } // docs:end:nullifier @@ -34,11 +37,11 @@ impl NoteInterface for ValueNote { fn compute_nullifier_without_context(self) -> Field { let note_hash_for_nullify = compute_note_hash_for_consumption(self); let secret = get_app_nullifier_secret_key(self.owner); - // TODO(#1205) Should use a non-zero generator index. - pedersen_hash([ + poseidon2_hash([ note_hash_for_nullify, secret, - ],0) + GENERATOR_INDEX__NOTE_NULLIFIER as Field, + ]) } // Broadcasts the note as an encrypted log on L1. diff --git a/noir-projects/noir-contracts/contracts/app_subscription_contract/src/subscription_note.nr b/noir-projects/noir-contracts/contracts/app_subscription_contract/src/subscription_note.nr index dc984c37338..435f61191b3 100644 --- a/noir-projects/noir-contracts/contracts/app_subscription_contract/src/subscription_note.nr +++ b/noir-projects/noir-contracts/contracts/app_subscription_contract/src/subscription_note.nr @@ -1,6 +1,7 @@ use dep::aztec::prelude::{AztecAddress, PrivateContext, NoteHeader, emit_encrypted_log, NoteInterface}; use dep::aztec::{ - note::utils::compute_note_hash_for_consumption, hash::pedersen_hash, + protocol_types::constants::GENERATOR_INDEX__NOTE_NULLIFIER, note::utils::compute_note_hash_for_consumption, + hash::poseidon2_hash, oracle::{nullifier_key::get_app_nullifier_secret_key, get_public_key::get_public_key} }; @@ -17,23 +18,23 @@ struct SubscriptionNote { impl NoteInterface for SubscriptionNote { fn compute_nullifier(self, context: &mut PrivateContext) -> Field { - let unique_siloed_note_hash = compute_note_hash_for_consumption(self); + let note_hash_for_nullify = compute_note_hash_for_consumption(self); let secret = context.request_app_nullifier_secret_key(self.owner); - // TODO(#1205) Should use a non-zero generator index. - pedersen_hash([ - unique_siloed_note_hash, + poseidon2_hash([ + note_hash_for_nullify, secret, - ],0) + GENERATOR_INDEX__NOTE_NULLIFIER as Field, + ]) } fn compute_nullifier_without_context(self) -> Field { - let unique_siloed_note_hash = compute_note_hash_for_consumption(self); + let note_hash_for_nullify = compute_note_hash_for_consumption(self); let secret = get_app_nullifier_secret_key(self.owner); - // TODO(#1205) Should use a non-zero generator index. - pedersen_hash([ - unique_siloed_note_hash, + poseidon2_hash([ + note_hash_for_nullify, secret, - ],0) + GENERATOR_INDEX__NOTE_NULLIFIER as Field, + ]) } // Broadcasts the note as an encrypted log on L1. diff --git a/noir-projects/noir-contracts/contracts/docs_example_contract/src/types/card_note.nr b/noir-projects/noir-contracts/contracts/docs_example_contract/src/types/card_note.nr index 617b24ef025..efab4af4892 100644 --- a/noir-projects/noir-contracts/contracts/docs_example_contract/src/types/card_note.nr +++ b/noir-projects/noir-contracts/contracts/docs_example_contract/src/types/card_note.nr @@ -2,7 +2,7 @@ use dep::aztec::prelude::{AztecAddress, NoteInterface, NoteHeader, PrivateContex use dep::aztec::{ note::{utils::compute_note_hash_for_consumption}, oracle::{nullifier_key::get_app_nullifier_secret_key, get_public_key::get_public_key}, - hash::pedersen_hash, protocol_types::traits::Empty + hash::poseidon2_hash, protocol_types::{traits::Empty, constants::GENERATOR_INDEX__NOTE_NULLIFIER}, }; // Shows how to create a custom note @@ -28,19 +28,21 @@ impl NoteInterface for CardNote { fn compute_nullifier(self, context: &mut PrivateContext) -> Field { let note_hash_for_nullify = compute_note_hash_for_consumption(self); let secret = context.request_app_nullifier_secret_key(self.owner); - pedersen_hash([ + poseidon2_hash([ note_hash_for_nullify, secret, - ],0) + GENERATOR_INDEX__NOTE_NULLIFIER as Field, + ]) } fn compute_nullifier_without_context(self) -> Field { let note_hash_for_nullify = compute_note_hash_for_consumption(self); let secret = get_app_nullifier_secret_key(self.owner); - pedersen_hash([ + poseidon2_hash([ note_hash_for_nullify, secret, - ],0) + GENERATOR_INDEX__NOTE_NULLIFIER as Field, + ]) } // Broadcasts the note as an encrypted log on L1. diff --git a/noir-projects/noir-contracts/contracts/ecdsa_account_contract/src/ecdsa_public_key_note.nr b/noir-projects/noir-contracts/contracts/ecdsa_account_contract/src/ecdsa_public_key_note.nr index 22144f965af..b97ff8bad97 100644 --- a/noir-projects/noir-contracts/contracts/ecdsa_account_contract/src/ecdsa_public_key_note.nr +++ b/noir-projects/noir-contracts/contracts/ecdsa_account_contract/src/ecdsa_public_key_note.nr @@ -6,7 +6,7 @@ use dep::aztec::prelude::{ use dep::aztec::{ note::utils::compute_note_hash_for_consumption, oracle::{nullifier_key::get_app_nullifier_secret_key, get_public_key::get_public_key}, - hash::pedersen_hash + hash::poseidon2_hash, protocol_types::constants::GENERATOR_INDEX__NOTE_NULLIFIER, }; global ECDSA_PUBLIC_KEY_NOTE_LEN: Field = 5; @@ -67,23 +67,23 @@ impl NoteInterface for EcdsaPublicKeyNote { } fn compute_nullifier(self, context: &mut PrivateContext) -> Field { - let unique_siloed_note_hash = compute_note_hash_for_consumption(self); + let note_hash_for_nullify = compute_note_hash_for_consumption(self); let secret = context.request_app_nullifier_secret_key(self.owner); - // TODO(#1205) Should use a non-zero generator index. - pedersen_hash([ - unique_siloed_note_hash, + poseidon2_hash([ + note_hash_for_nullify, secret, - ],0) + GENERATOR_INDEX__NOTE_NULLIFIER as Field, + ]) } fn compute_nullifier_without_context(self) -> Field { - let unique_siloed_note_hash = compute_note_hash_for_consumption(self); + let note_hash_for_nullify = compute_note_hash_for_consumption(self); let secret = get_app_nullifier_secret_key(self.owner); - // TODO(#1205) Should use a non-zero generator index. - pedersen_hash([ - unique_siloed_note_hash, + poseidon2_hash([ + note_hash_for_nullify, secret, - ],0) + GENERATOR_INDEX__NOTE_NULLIFIER as Field, + ]) } // Broadcasts the note as an encrypted log on L1. diff --git a/noir-projects/noir-contracts/contracts/gas_token_contract/src/main.nr b/noir-projects/noir-contracts/contracts/gas_token_contract/src/main.nr index cc19bf9f5f2..fd2bb0356ec 100644 --- a/noir-projects/noir-contracts/contracts/gas_token_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/gas_token_contract/src/main.nr @@ -2,7 +2,7 @@ mod lib; contract GasToken { use dep::aztec::protocol_types::{abis::function_selector::FunctionSelector, address::{AztecAddress, EthAddress}}; - use dep::aztec::{hash::compute_secret_hash, state_vars::{SharedImmutable, PublicMutable, Map}}; + use dep::aztec::state_vars::{SharedImmutable, PublicMutable, Map}; use crate::lib::{calculate_fee, get_bridge_gas_msg_hash}; diff --git a/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/public_key_note.nr b/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/public_key_note.nr index 39d25636db7..c0031833c26 100644 --- a/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/public_key_note.nr +++ b/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/public_key_note.nr @@ -1,7 +1,8 @@ use dep::aztec::prelude::{AztecAddress, NoteHeader, NoteInterface, PrivateContext, emit_encrypted_log}; use dep::aztec::{ - note::utils::compute_note_hash_for_consumption, hash::pedersen_hash, - oracle::{nullifier_key::get_app_nullifier_secret_key, get_public_key::get_public_key} + note::utils::compute_note_hash_for_consumption, hash::poseidon2_hash, + oracle::{nullifier_key::get_app_nullifier_secret_key, get_public_key::get_public_key}, + protocol_types::constants::GENERATOR_INDEX__NOTE_NULLIFIER, }; global PUBLIC_KEY_NOTE_LEN: Field = 3; @@ -17,23 +18,23 @@ struct PublicKeyNote { impl NoteInterface for PublicKeyNote { fn compute_nullifier(self, context: &mut PrivateContext) -> Field { - let unique_siloed_note_hash = compute_note_hash_for_consumption(self); + let note_hash_for_nullify = compute_note_hash_for_consumption(self); let secret = context.request_app_nullifier_secret_key(self.owner); - // TODO(#1205) Should use a non-zero generator index. - pedersen_hash([ - unique_siloed_note_hash, + poseidon2_hash([ + note_hash_for_nullify, secret, - ],0) + GENERATOR_INDEX__NOTE_NULLIFIER as Field, + ]) } fn compute_nullifier_without_context(self) -> Field { - let unique_siloed_note_hash = compute_note_hash_for_consumption(self); + let note_hash_for_nullify = compute_note_hash_for_consumption(self); let secret = get_app_nullifier_secret_key(self.owner); - // TODO(#1205) Should use a non-zero generator index. - pedersen_hash([ - unique_siloed_note_hash, + poseidon2_hash([ + note_hash_for_nullify, secret, - ],0) + GENERATOR_INDEX__NOTE_NULLIFIER as Field, + ]) } // Broadcasts the note as an encrypted log on L1. diff --git a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr index a6572b4e54c..4fc172d63fc 100644 --- a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr @@ -10,12 +10,9 @@ mod types; contract TokenBlacklist { // Libs - - use dep::aztec::protocol_types::{abis::function_selector::FunctionSelector, address::AztecAddress}; use dep::aztec::{ - note::{note_getter_options::NoteGetterOptions, note_header::NoteHeader}, hash::compute_secret_hash, - state_vars::{Map, PublicMutable, PrivateSet, SharedMutable, SharedImmutable} + prelude::{AztecAddress, FunctionSelector, Map, NoteGetterOptions, PrivateSet, PublicMutable, SharedMutable} }; use dep::authwit::{auth::{assert_current_call_valid_authwit, assert_current_call_valid_authwit_public}}; diff --git a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr index 3bd6b23d854..5f6edf94d5f 100644 --- a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr +++ b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr @@ -1,6 +1,9 @@ -use dep::aztec::prelude::{AztecAddress, NoteHeader, NoteInterface, PrivateContext, emit_encrypted_log}; -use dep::aztec::{note::utils::compute_note_hash_for_consumption, hash::pedersen_hash}; -use dep::aztec::oracle::{unsafe_rand::unsafe_rand, nullifier_key::get_app_nullifier_secret_key, get_public_key::get_public_key}; +use dep::aztec::{ + prelude::{AztecAddress, NoteHeader, NoteInterface, PrivateContext, emit_encrypted_log}, + protocol_types::constants::GENERATOR_INDEX__NOTE_NULLIFIER, + note::utils::compute_note_hash_for_consumption, hash::poseidon2_hash, + oracle::{unsafe_rand::unsafe_rand, nullifier_key::get_app_nullifier_secret_key, get_public_key::get_public_key} +}; trait OwnedNote { fn new(amount: U128, owner: AztecAddress) -> Self; @@ -27,22 +30,22 @@ impl NoteInterface for TokenNote { fn compute_nullifier(self, context: &mut PrivateContext) -> Field { let note_hash_for_nullify = compute_note_hash_for_consumption(self); let secret = context.request_app_nullifier_secret_key(self.owner); - // TODO(#1205) Should use a non-zero generator index. - pedersen_hash([ + poseidon2_hash([ note_hash_for_nullify, secret, - ],0) + GENERATOR_INDEX__NOTE_NULLIFIER as Field, + ]) } // docs:end:nullifier fn compute_nullifier_without_context(self) -> Field { let note_hash_for_nullify = compute_note_hash_for_consumption(self); let secret = get_app_nullifier_secret_key(self.owner); - // TODO(#1205) Should use a non-zero generator index. - pedersen_hash([ + poseidon2_hash([ note_hash_for_nullify, secret, - ],0) + GENERATOR_INDEX__NOTE_NULLIFIER as Field, + ]) } // Broadcasts the note as an encrypted log on L1. @@ -79,5 +82,4 @@ impl OwnedNote for TokenNote { fn get_owner(self) -> AztecAddress { self.owner } - } diff --git a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/transparent_note.nr b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/transparent_note.nr index 3e722a207f8..d5cf7197cef 100644 --- a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/transparent_note.nr +++ b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/transparent_note.nr @@ -1,8 +1,8 @@ // docs:start:token_types_all -use dep::aztec::prelude::{NoteHeader, NoteInterface, PrivateContext}; use dep::aztec::{ note::{note_getter_options::PropertySelector, utils::compute_note_hash_for_consumption}, - hash::{compute_secret_hash, pedersen_hash} + hash::poseidon2_hash, prelude::{NoteHeader, NoteInterface, PrivateContext}, + protocol_types::constants::GENERATOR_INDEX__NOTE_NULLIFIER }; global TRANSPARENT_NOTE_LEN: Field = 2; @@ -52,9 +52,11 @@ impl NoteInterface for TransparentNote { // circuit. // This achieves that the note can only be spent by the party that knows the secret. fn compute_nullifier_without_context(self) -> Field { - let siloed_note_hash = compute_note_hash_for_consumption(self); - // TODO(#1205) Should use a non-zero generator index. - pedersen_hash([siloed_note_hash], 0) + let note_hash_for_nullify = compute_note_hash_for_consumption(self); + poseidon2_hash([ + note_hash_for_nullify, + GENERATOR_INDEX__NOTE_NULLIFIER as Field, + ]) } fn broadcast(self, context: &mut PrivateContext, slot: Field) { diff --git a/noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr b/noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr index 7cb053fb512..e503e3f691a 100644 --- a/noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr @@ -8,8 +8,6 @@ contract TokenBridge { use dep::aztec::prelude::{FunctionSelector, AztecAddress, EthAddress, PublicMutable, SharedImmutable}; - use dep::aztec::{context::Context, hash::compute_secret_hash}; - use dep::token_portal_content_hash_lib::{get_mint_public_content_hash, get_mint_private_content_hash, get_withdraw_content_hash}; use dep::token::Token; diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/main.nr b/noir-projects/noir-contracts/contracts/token_contract/src/main.nr index cc892421ece..e488c5f4f43 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/main.nr @@ -14,8 +14,10 @@ contract Token { use dep::compressed_string::FieldCompressedString; - use dep::aztec::prelude::{NoteGetterOptions, Map, PublicMutable, SharedImmutable, PrivateSet, AztecAddress}; - use dep::aztec::hash::compute_secret_hash; + use dep::aztec::{ + hash::compute_secret_hash, + prelude::{NoteGetterOptions, Map, PublicMutable, SharedImmutable, PrivateSet, AztecAddress} + }; // docs:start:import_authwit use dep::authwit::{auth::{assert_current_call_valid_authwit, assert_current_call_valid_authwit_public}}; diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr b/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr index cd76d49659c..5f6edf94d5f 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr @@ -1,9 +1,9 @@ -use dep::aztec::prelude::{ - AztecAddress, NoteInterface, NoteGetterOptions, NoteViewerOptions, NoteHeader, PrivateContext, - PrivateSet, Map, emit_encrypted_log +use dep::aztec::{ + prelude::{AztecAddress, NoteHeader, NoteInterface, PrivateContext, emit_encrypted_log}, + protocol_types::constants::GENERATOR_INDEX__NOTE_NULLIFIER, + note::utils::compute_note_hash_for_consumption, hash::poseidon2_hash, + oracle::{unsafe_rand::unsafe_rand, nullifier_key::get_app_nullifier_secret_key, get_public_key::get_public_key} }; -use dep::aztec::{note::utils::compute_note_hash_for_consumption, hash::pedersen_hash}; -use dep::aztec::oracle::{unsafe_rand::unsafe_rand, nullifier_key::get_app_nullifier_secret_key, get_public_key::get_public_key}; trait OwnedNote { fn new(amount: U128, owner: AztecAddress) -> Self; @@ -30,22 +30,22 @@ impl NoteInterface for TokenNote { fn compute_nullifier(self, context: &mut PrivateContext) -> Field { let note_hash_for_nullify = compute_note_hash_for_consumption(self); let secret = context.request_app_nullifier_secret_key(self.owner); - // TODO(#1205) Should use a non-zero generator index. - pedersen_hash([ + poseidon2_hash([ note_hash_for_nullify, secret, - ],0) + GENERATOR_INDEX__NOTE_NULLIFIER as Field, + ]) } // docs:end:nullifier fn compute_nullifier_without_context(self) -> Field { let note_hash_for_nullify = compute_note_hash_for_consumption(self); let secret = get_app_nullifier_secret_key(self.owner); - // TODO(#1205) Should use a non-zero generator index. - pedersen_hash([ + poseidon2_hash([ note_hash_for_nullify, secret, - ],0) + GENERATOR_INDEX__NOTE_NULLIFIER as Field, + ]) } // Broadcasts the note as an encrypted log on L1. @@ -63,7 +63,7 @@ impl NoteInterface for TokenNote { ); } } - } +} impl OwnedNote for TokenNote { fn new(amount: U128, owner: AztecAddress) -> Self { @@ -82,5 +82,4 @@ impl OwnedNote for TokenNote { fn get_owner(self) -> AztecAddress { self.owner } - } diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/types/transparent_note.nr b/noir-projects/noir-contracts/contracts/token_contract/src/types/transparent_note.nr index 3e722a207f8..9fc1d0737fc 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/types/transparent_note.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/types/transparent_note.nr @@ -1,8 +1,8 @@ // docs:start:token_types_all -use dep::aztec::prelude::{NoteHeader, NoteInterface, PrivateContext}; use dep::aztec::{ note::{note_getter_options::PropertySelector, utils::compute_note_hash_for_consumption}, - hash::{compute_secret_hash, pedersen_hash} + hash::poseidon2_hash, prelude::{NoteHeader, NoteInterface, PrivateContext}, + protocol_types::constants::GENERATOR_INDEX__NOTE_NULLIFIER, }; global TRANSPARENT_NOTE_LEN: Field = 2; @@ -52,9 +52,11 @@ impl NoteInterface for TransparentNote { // circuit. // This achieves that the note can only be spent by the party that knows the secret. fn compute_nullifier_without_context(self) -> Field { - let siloed_note_hash = compute_note_hash_for_consumption(self); - // TODO(#1205) Should use a non-zero generator index. - pedersen_hash([siloed_note_hash], 0) + let note_hash_for_nullify = compute_note_hash_for_consumption(self); + poseidon2_hash([ + note_hash_for_nullify, + GENERATOR_INDEX__NOTE_NULLIFIER as Field, + ]) } fn broadcast(self, context: &mut PrivateContext, slot: Field) { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr index e324d2d231d..10649ef22cf 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr @@ -199,7 +199,7 @@ global GENERATOR_INDEX__NOTE_HASH = 1; global GENERATOR_INDEX__NOTE_HASH_NONCE = 2; global GENERATOR_INDEX__UNIQUE_NOTE_HASH = 3; global GENERATOR_INDEX__SILOED_NOTE_HASH = 4; -global GENERATOR_INDEX__NULLIFIER = 5; +global GENERATOR_INDEX__MESSAGE_NULLIFIER = 5; global GENERATOR_INDEX__INITIALIZATION_NULLIFIER = 6; global GENERATOR_INDEX__OUTER_NULLIFIER = 7; global GENERATOR_INDEX__PUBLIC_DATA_READ = 8; @@ -214,7 +214,7 @@ global GENERATOR_INDEX__CONTRACT_LEAF = 16; global GENERATOR_INDEX__CALL_CONTEXT = 17; global GENERATOR_INDEX__CALL_STACK_ITEM = 18; global GENERATOR_INDEX__CALL_STACK_ITEM_2 = 19; -global GENERATOR_INDEX__L1_TO_L2_MESSAGE_SECRET = 20; +global GENERATOR_INDEX__SECRET_HASH = 20; global GENERATOR_INDEX__L2_TO_L1_MSG = 21; global GENERATOR_INDEX__TX_CONTEXT = 22; global GENERATOR_INDEX__PUBLIC_LEAF_INDEX = 23; @@ -242,3 +242,6 @@ global GENERATOR_INDEX__IVSK_M = 48; global GENERATOR_INDEX__OVSK_M = 49; global GENERATOR_INDEX__TSK_M = 50; global GENERATOR_INDEX__PUBLIC_KEYS_HASH = 51; +global GENERATOR_INDEX__NOTE_NULLIFIER = 52; +global GENERATOR_INDEX__INNER_NOTE_HASH = 53; +global GENERATOR_INDEX__NOTE_CONTENT_HASH = 54; diff --git a/noir/noir-repo/aztec_macros/src/transforms/note_interface.rs b/noir/noir-repo/aztec_macros/src/transforms/note_interface.rs index 70db1ebd336..f183c69b27a 100644 --- a/noir/noir-repo/aztec_macros/src/transforms/note_interface.rs +++ b/noir/noir-repo/aztec_macros/src/transforms/note_interface.rs @@ -418,8 +418,7 @@ fn generate_note_properties_fn( // Automatically generate the method to compute the note's content hash as: // fn compute_note_content_hash(self: NoteType) -> Field { -// // TODO(#1205) Should use a non-zero generator index. -// dep::aztec::hash::pedersen_hash(self.serialize_content(), 0) +// dep::aztec::hash::pedersen_hash(self.serialize_content(), dep::aztec::protocol_types::constants::GENERATOR_INDEX__NOTE_CONTENT_HASH) // } // fn generate_compute_note_content_hash( @@ -429,8 +428,7 @@ fn generate_compute_note_content_hash( let function_source = format!( " fn compute_note_content_hash(self: {}) -> Field {{ - // TODO(#1205) Should use a non-zero generator index. - dep::aztec::hash::pedersen_hash(self.serialize_content(), 0) + dep::aztec::hash::pedersen_hash(self.serialize_content(), dep::aztec::protocol_types::constants::GENERATOR_INDEX__NOTE_CONTENT_HASH) }} ", note_type diff --git a/yarn-project/aztec.js/src/fee/private_fee_payment_method.ts b/yarn-project/aztec.js/src/fee/private_fee_payment_method.ts index e6abb694172..f3298ed09ef 100644 --- a/yarn-project/aztec.js/src/fee/private_fee_payment_method.ts +++ b/yarn-project/aztec.js/src/fee/private_fee_payment_method.ts @@ -1,6 +1,6 @@ import { type FunctionCall } from '@aztec/circuit-types'; import { FunctionData, type GasSettings } from '@aztec/circuits.js'; -import { computeMessageSecretHash } from '@aztec/circuits.js/hash'; +import { computeSecretHash } from '@aztec/circuits.js/hash'; import { FunctionSelector } from '@aztec/foundation/abi'; import { type AztecAddress } from '@aztec/foundation/aztec-address'; import { Fr } from '@aztec/foundation/fields'; @@ -71,7 +71,7 @@ export class PrivateFeePaymentMethod implements FeePaymentMethod { ); await this.wallet.createAuthWit(messageHash); - const secretHashForRebate = computeMessageSecretHash(this.rebateSecret); + const secretHashForRebate = computeSecretHash(this.rebateSecret); return [ { diff --git a/yarn-project/aztec.js/src/index.ts b/yarn-project/aztec.js/src/index.ts index fc91aa829b5..cb9179a84a7 100644 --- a/yarn-project/aztec.js/src/index.ts +++ b/yarn-project/aztec.js/src/index.ts @@ -75,7 +75,7 @@ export { INITIAL_L2_BLOCK_NUM, } from '@aztec/circuits.js'; -export { computeMessageSecretHash } from '@aztec/circuits.js/hash'; +export { computeSecretHash } from '@aztec/circuits.js/hash'; export { computeAppNullifierSecretKey, diff --git a/yarn-project/aztec/src/examples/token.ts b/yarn-project/aztec/src/examples/token.ts index 01702d9d5d1..323d32310ad 100644 --- a/yarn-project/aztec/src/examples/token.ts +++ b/yarn-project/aztec/src/examples/token.ts @@ -1,5 +1,5 @@ import { getSingleKeyAccount } from '@aztec/accounts/single_key'; -import { type AccountWallet, Fr, Note, computeMessageSecretHash, createPXEClient } from '@aztec/aztec.js'; +import { type AccountWallet, Fr, Note, computeSecretHash, createPXEClient } from '@aztec/aztec.js'; import { ExtendedNote } from '@aztec/circuit-types'; import { createDebugLogger } from '@aztec/foundation/log'; import { TokenContract } from '@aztec/noir-contracts.js/Token'; @@ -45,7 +45,7 @@ async function main() { // Create a secret and a corresponding hash that will be used to mint funds privately const aliceSecret = Fr.random(); - const aliceSecretHash = computeMessageSecretHash(aliceSecret); + const aliceSecretHash = computeSecretHash(aliceSecret); const receipt = await tokenAlice.methods.mint_private(ALICE_MINT_BALANCE, aliceSecretHash).send().wait(); // Add the newly created "pending shield" note to PXE diff --git a/yarn-project/circuits.js/src/constants.gen.ts b/yarn-project/circuits.js/src/constants.gen.ts index 1ebe97036c4..f141aa31070 100644 --- a/yarn-project/circuits.js/src/constants.gen.ts +++ b/yarn-project/circuits.js/src/constants.gen.ts @@ -163,7 +163,7 @@ export enum GeneratorIndex { NOTE_HASH_NONCE = 2, UNIQUE_NOTE_HASH = 3, SILOED_NOTE_HASH = 4, - NULLIFIER = 5, + MESSAGE_NULLIFIER = 5, INITIALIZATION_NULLIFIER = 6, OUTER_NULLIFIER = 7, PUBLIC_DATA_READ = 8, @@ -178,7 +178,7 @@ export enum GeneratorIndex { CALL_CONTEXT = 17, CALL_STACK_ITEM = 18, CALL_STACK_ITEM_2 = 19, - L1_TO_L2_MESSAGE_SECRET = 20, + SECRET_HASH = 20, L2_TO_L1_MSG = 21, TX_CONTEXT = 22, PUBLIC_LEAF_INDEX = 23, @@ -202,4 +202,7 @@ export enum GeneratorIndex { OVSK_M = 49, TSK_M = 50, PUBLIC_KEYS_HASH = 51, + NOTE_NULLIFIER = 52, + INNER_NOTE_HASH = 53, + NOTE_CONTENT_HASH = 54, } diff --git a/yarn-project/circuits.js/src/hash/hash.test.ts b/yarn-project/circuits.js/src/hash/hash.test.ts index ce91f4c10d7..477990a388b 100644 --- a/yarn-project/circuits.js/src/hash/hash.test.ts +++ b/yarn-project/circuits.js/src/hash/hash.test.ts @@ -6,11 +6,11 @@ import { makeAztecAddress, makeVerificationKey } from '../tests/factories.js'; import { computeCommitmentNonce, computeCommitmentsHash, - computeMessageSecretHash, computeNullifierHash, computePublicDataTreeLeafSlot, computePublicDataTreeValue, - computeUniqueCommitment, + computeSecretHash, + computeUniqueNoteHash, computeVarArgsHash, hashVK, siloNoteHash, @@ -35,7 +35,7 @@ describe('hash', () => { it('computes unique commitment', () => { const nonce = new Fr(123n); const innerCommitment = new Fr(456); - const res = computeUniqueCommitment(nonce, innerCommitment); + const res = computeUniqueNoteHash(nonce, innerCommitment); expect(res).toMatchSnapshot(); }); @@ -85,7 +85,7 @@ describe('hash', () => { it('compute secret message hash', () => { const value = new Fr(8n); - const hash = computeMessageSecretHash(value); + const hash = computeSecretHash(value); expect(hash).toMatchSnapshot(); }); diff --git a/yarn-project/circuits.js/src/hash/hash.ts b/yarn-project/circuits.js/src/hash/hash.ts index b5496f75713..7f3d489b7ba 100644 --- a/yarn-project/circuits.js/src/hash/hash.ts +++ b/yarn-project/circuits.js/src/hash/hash.ts @@ -76,13 +76,33 @@ export function siloNoteHash(contract: AztecAddress, innerNoteHash: Fr): Fr { } /** - * Computes a unique commitment. It includes a nonce which contains data that guarantees the commitment will be unique. + * Computes a note content hash. + * @param noteContent - The note content (e.g. note.items). + * @returns A note content hash. + */ +export function computeNoteContentHash(noteContent: Fr[]): Fr { + return pedersenHash(noteContent, GeneratorIndex.NOTE_CONTENT_HASH); +} + +/** + * Computes an inner note hash, given a storage slot and a note hash. + * @param storageSlot - The storage slot. + * @param noteHash - The note hash. + * @returns An inner note hash. + */ +export function computeInnerNoteHash(storageSlot: Fr, noteHash: Fr): Fr { + return pedersenHash([storageSlot, noteHash], GeneratorIndex.INNER_NOTE_HASH); +} + +/** + * Computes a unique note hash. + * @dev Includes a nonce which contains data that guarantees the resulting note hash will be unique. * @param nonce - The contract address. - * @param siloedCommitment - An siloed commitment. - * @returns A unique commitment. + * @param siloedNoteHash - An siloed note hash. + * @returns A unique note hash. */ -export function computeUniqueCommitment(nonce: Fr, siloedCommitment: Fr): Fr { - return pedersenHash([nonce, siloedCommitment], GeneratorIndex.UNIQUE_NOTE_HASH); +export function computeUniqueNoteHash(nonce: Fr, siloedNoteHash: Fr): Fr { + return pedersenHash([nonce, siloedNoteHash], GeneratorIndex.UNIQUE_NOTE_HASH); } /** @@ -157,12 +177,13 @@ export function computeNullifierHash(input: SideEffectLinkedToNoteHash) { } /** - * Given a secret, it computes its pedersen hash - used to send l1 to l2 messages - * @param secret - the secret to hash - secret could be generated however you want e.g. `Fr.random()` - * @returns the hash + * Computes a hash of a secret. + * @dev This function is used to generate secrets for the L1 to L2 message flow and for the TransparentNote. + * @param secret - The secret to hash (could be generated however you want e.g. `Fr.random()`) + * @returns The hash */ -export function computeMessageSecretHash(secretMessage: Fr) { - return pedersenHash([secretMessage], GeneratorIndex.L1_TO_L2_MESSAGE_SECRET); +export function computeSecretHash(secret: Fr) { + return pedersenHash([secret], GeneratorIndex.SECRET_HASH); } export function computeL1ToL2MessageNullifier( @@ -171,6 +192,6 @@ export function computeL1ToL2MessageNullifier( secret: Fr, messageIndex: bigint, ) { - const innerMessageNullifier = pedersenHash([messageHash, secret, messageIndex], GeneratorIndex.NULLIFIER); + const innerMessageNullifier = pedersenHash([messageHash, secret, messageIndex], GeneratorIndex.MESSAGE_NULLIFIER); return siloNullifier(contract, innerMessageNullifier); } diff --git a/yarn-project/end-to-end/src/composed/e2e_persistence.test.ts b/yarn-project/end-to-end/src/composed/e2e_persistence.test.ts index 15bb02259a3..14fa82a73fe 100644 --- a/yarn-project/end-to-end/src/composed/e2e_persistence.test.ts +++ b/yarn-project/end-to-end/src/composed/e2e_persistence.test.ts @@ -5,7 +5,7 @@ import { ExtendedNote, Note, type TxHash, - computeMessageSecretHash, + computeSecretHash, waitForAccountSynch, } from '@aztec/aztec.js'; import { type Salt } from '@aztec/aztec.js/account'; @@ -72,13 +72,13 @@ describe('Aztec persistence', () => { const secret = Fr.random(); - const mintTxReceipt = await contract.methods.mint_private(1000n, computeMessageSecretHash(secret)).send().wait(); + const mintTxReceipt = await contract.methods.mint_private(1000n, computeSecretHash(secret)).send().wait(); await addPendingShieldNoteToPXE( ownerWallet, contractAddress, 1000n, - computeMessageSecretHash(secret), + computeSecretHash(secret), mintTxReceipt.txHash, ); @@ -130,12 +130,12 @@ describe('Aztec persistence', () => { const balance = await contract.methods.balance_of_private(ownerWallet.getAddress()).simulate(); const secret = Fr.random(); - const mintTxReceipt = await contract.methods.mint_private(1000n, computeMessageSecretHash(secret)).send().wait(); + const mintTxReceipt = await contract.methods.mint_private(1000n, computeSecretHash(secret)).send().wait(); await addPendingShieldNoteToPXE( ownerWallet, contractAddress, 1000n, - computeMessageSecretHash(secret), + computeSecretHash(secret), mintTxReceipt.txHash, ); @@ -269,10 +269,7 @@ describe('Aztec persistence', () => { // mint some tokens with a secret we know and redeem later on a separate PXE secret = Fr.random(); mintAmount = 1000n; - const mintTxReceipt = await contract.methods - .mint_private(mintAmount, computeMessageSecretHash(secret)) - .send() - .wait(); + const mintTxReceipt = await contract.methods.mint_private(mintAmount, computeSecretHash(secret)).send().wait(); mintTxHash = mintTxReceipt.txHash; // publicly reveal that I have 1000 tokens @@ -307,13 +304,7 @@ describe('Aztec persistence', () => { it('allows consuming transparent note created on another PXE', async () => { // this was created in the temporary PXE in `beforeAll` - await addPendingShieldNoteToPXE( - ownerWallet, - contractAddress, - mintAmount, - computeMessageSecretHash(secret), - mintTxHash, - ); + await addPendingShieldNoteToPXE(ownerWallet, contractAddress, mintAmount, computeSecretHash(secret), mintTxHash); const balanceBeforeRedeem = await contract.methods.balance_of_private(ownerWallet.getAddress()).simulate(); diff --git a/yarn-project/end-to-end/src/composed/e2e_sandbox_example.test.ts b/yarn-project/end-to-end/src/composed/e2e_sandbox_example.test.ts index bbc794b8096..1ae3c9362f6 100644 --- a/yarn-project/end-to-end/src/composed/e2e_sandbox_example.test.ts +++ b/yarn-project/end-to-end/src/composed/e2e_sandbox_example.test.ts @@ -7,7 +7,7 @@ import { GrumpkinScalar, Note, type PXE, - computeMessageSecretHash, + computeSecretHash, createDebugLogger, createPXEClient, waitForPXE, @@ -69,7 +69,7 @@ describe('e2e_sandbox_example', () => { // Create a secret and a corresponding hash that will be used to mint funds privately const aliceSecret = Fr.random(); - const aliceSecretHash = computeMessageSecretHash(aliceSecret); + const aliceSecretHash = computeSecretHash(aliceSecret); logger.info(`Minting tokens to Alice...`); // Mint the initial supply privately "to secret hash" @@ -144,7 +144,7 @@ describe('e2e_sandbox_example', () => { await tokenContractAlice.methods.set_minter(bob, true).send().wait(); const bobSecret = Fr.random(); - const bobSecretHash = computeMessageSecretHash(bobSecret); + const bobSecretHash = computeSecretHash(bobSecret); // Bob now has a secret 🥷 const mintQuantity = 10_000n; diff --git a/yarn-project/end-to-end/src/e2e_account_init_fees.test.ts b/yarn-project/end-to-end/src/e2e_account_init_fees.test.ts index d8acec1c0d5..75c225f4d52 100644 --- a/yarn-project/end-to-end/src/e2e_account_init_fees.test.ts +++ b/yarn-project/end-to-end/src/e2e_account_init_fees.test.ts @@ -12,7 +12,7 @@ import { type TxHash, TxStatus, type Wallet, - computeMessageSecretHash, + computeSecretHash, deriveKeys, } from '@aztec/aztec.js'; import { type AztecAddress, CompleteAddress, Fq, GasSettings } from '@aztec/circuits.js'; @@ -173,7 +173,7 @@ describe('e2e_fees_account_init', () => { await bobsAccountManager.register(); const secret = Fr.random(); - const secretHash = computeMessageSecretHash(secret); + const secretHash = computeSecretHash(secret); const mintTx = await bananaCoin.methods.mint_private(mintedPrivateBananas, secretHash).send().wait(); await addTransparentNoteToPxe(sequencersAddress, mintedPrivateBananas, secretHash, mintTx.txHash); @@ -219,7 +219,7 @@ describe('e2e_fees_account_init', () => { // the new account should have received a refund await expect( // this rejects if note can't be added - addTransparentNoteToPxe(bobsAddress, maxFee - actualFee, computeMessageSecretHash(rebateSecret), tx.txHash), + addTransparentNoteToPxe(bobsAddress, maxFee - actualFee, computeSecretHash(rebateSecret), tx.txHash), ).resolves.toBeUndefined(); // and it can redeem the refund diff --git a/yarn-project/end-to-end/src/e2e_blacklist_token_contract.test.ts b/yarn-project/end-to-end/src/e2e_blacklist_token_contract.test.ts index a10290d717c..05c2b994a91 100644 --- a/yarn-project/end-to-end/src/e2e_blacklist_token_contract.test.ts +++ b/yarn-project/end-to-end/src/e2e_blacklist_token_contract.test.ts @@ -9,7 +9,7 @@ import { type TxHash, type Wallet, computeAuthWitMessageHash, - computeMessageSecretHash, + computeSecretHash, } from '@aztec/aztec.js'; import { TokenBlacklistContract, type TokenContract } from '@aztec/noir-contracts.js'; @@ -246,7 +246,7 @@ describe('e2e_blacklist_token_contract', () => { let txHash: TxHash; beforeAll(() => { - secretHash = computeMessageSecretHash(secret); + secretHash = computeSecretHash(secret); }); describe('Mint flow', () => { @@ -641,7 +641,7 @@ describe('e2e_blacklist_token_contract', () => { let secretHash: Fr; beforeAll(() => { - secretHash = computeMessageSecretHash(secret); + secretHash = computeSecretHash(secret); }); it('on behalf of self', async () => { diff --git a/yarn-project/end-to-end/src/e2e_cheat_codes.test.ts b/yarn-project/end-to-end/src/e2e_cheat_codes.test.ts index 01127055f91..4fd2e8d6d6f 100644 --- a/yarn-project/end-to-end/src/e2e_cheat_codes.test.ts +++ b/yarn-project/end-to-end/src/e2e_cheat_codes.test.ts @@ -7,7 +7,7 @@ import { Note, type PXE, type Wallet, - computeMessageSecretHash, + computeSecretHash, } from '@aztec/aztec.js'; import { RollupAbi } from '@aztec/l1-artifacts'; import { TestContract, TokenContract } from '@aztec/noir-contracts.js'; @@ -218,7 +218,7 @@ describe('e2e_cheat_codes', () => { // docs:start:load_private_cheatcode const mintAmount = 100n; const secret = Fr.random(); - const secretHash = computeMessageSecretHash(secret); + const secretHash = computeSecretHash(secret); const receipt = await token.methods.mint_private(mintAmount, secretHash).send().wait(); // docs:start:pxe_add_note diff --git a/yarn-project/end-to-end/src/e2e_crowdfunding_and_claim.test.ts b/yarn-project/end-to-end/src/e2e_crowdfunding_and_claim.test.ts index f697a02251f..ca9f711bf2d 100644 --- a/yarn-project/end-to-end/src/e2e_crowdfunding_and_claim.test.ts +++ b/yarn-project/end-to-end/src/e2e_crowdfunding_and_claim.test.ts @@ -8,7 +8,7 @@ import { Note, type PXE, type TxHash, - computeMessageSecretHash, + computeSecretHash, deriveKeys, } from '@aztec/aztec.js'; import { computePartialAddress } from '@aztec/circuits.js'; @@ -134,7 +134,7 @@ describe('e2e_crowdfunding_and_claim', () => { const mintDNTToDonors = async () => { const secret = Fr.random(); - const secretHash = computeMessageSecretHash(secret); + const secretHash = computeSecretHash(secret); const [txReceipt1, txReceipt2] = await Promise.all([ donationToken.withWallet(operatorWallet).methods.mint_private(1234n, secretHash).send().wait(), diff --git a/yarn-project/end-to-end/src/e2e_escrow_contract.test.ts b/yarn-project/end-to-end/src/e2e_escrow_contract.test.ts index de4f2f48152..12017b84bb8 100644 --- a/yarn-project/end-to-end/src/e2e_escrow_contract.test.ts +++ b/yarn-project/end-to-end/src/e2e_escrow_contract.test.ts @@ -7,7 +7,7 @@ import { Fr, Note, type PXE, - computeMessageSecretHash, + computeSecretHash, deriveKeys, } from '@aztec/aztec.js'; import { computePartialAddress } from '@aztec/circuits.js'; @@ -58,7 +58,7 @@ describe('e2e_escrow_contract', () => { const mintAmount = 100n; const secret = Fr.random(); - const secretHash = computeMessageSecretHash(secret); + const secretHash = computeSecretHash(secret); const receipt = await token.methods.mint_private(mintAmount, secretHash).send().wait(); @@ -110,7 +110,7 @@ describe('e2e_escrow_contract', () => { logger.info(`Minting funds in token contract to ${owner}`); const mintAmount = 50n; const secret = Fr.random(); - const secretHash = computeMessageSecretHash(secret); + const secretHash = computeSecretHash(secret); const receipt = await token.methods.mint_private(mintAmount, secretHash).send().wait(); diff --git a/yarn-project/end-to-end/src/e2e_fees.test.ts b/yarn-project/end-to-end/src/e2e_fees.test.ts index 1d4ecce5e3d..795fa7719cf 100644 --- a/yarn-project/end-to-end/src/e2e_fees.test.ts +++ b/yarn-project/end-to-end/src/e2e_fees.test.ts @@ -14,7 +14,7 @@ import { TxStatus, type Wallet, computeAuthWitMessageHash, - computeMessageSecretHash, + computeSecretHash, } from '@aztec/aztec.js'; import { FunctionData, GasSettings } from '@aztec/circuits.js'; import { type ContractArtifact, decodeFunctionSignature } from '@aztec/foundation/abi'; @@ -298,7 +298,7 @@ describe('e2e_fees', () => { await expect( // this rejects if note can't be added - addPendingShieldNoteToPXE(0, RefundAmount, computeMessageSecretHash(RefundSecret), tx.txHash), + addPendingShieldNoteToPXE(0, RefundAmount, computeSecretHash(RefundSecret), tx.txHash), ).resolves.toBeUndefined(); }); @@ -361,7 +361,7 @@ describe('e2e_fees', () => { await expect( // this rejects if note can't be added - addPendingShieldNoteToPXE(0, RefundAmount, computeMessageSecretHash(RefundSecret), tx.txHash), + addPendingShieldNoteToPXE(0, RefundAmount, computeSecretHash(RefundSecret), tx.txHash), ).resolves.toBeUndefined(); }); @@ -393,7 +393,7 @@ describe('e2e_fees', () => { */ const shieldedBananas = 1n; const shieldSecret = Fr.random(); - const shieldSecretHash = computeMessageSecretHash(shieldSecret); + const shieldSecretHash = computeSecretHash(shieldSecret); const tx = await bananaCoin.methods .shield(aliceAddress, shieldedBananas, shieldSecretHash, 0n) .send({ @@ -428,7 +428,7 @@ describe('e2e_fees', () => { await expect(addPendingShieldNoteToPXE(0, shieldedBananas, shieldSecretHash, tx.txHash)).resolves.toBeUndefined(); await expect( - addPendingShieldNoteToPXE(0, RefundAmount, computeMessageSecretHash(RefundSecret), tx.txHash), + addPendingShieldNoteToPXE(0, RefundAmount, computeSecretHash(RefundSecret), tx.txHash), ).resolves.toBeUndefined(); }); @@ -436,7 +436,7 @@ describe('e2e_fees', () => { const privateTransfer = 1n; const shieldedBananas = 1n; const shieldSecret = Fr.random(); - const shieldSecretHash = computeMessageSecretHash(shieldSecret); + const shieldSecretHash = computeSecretHash(shieldSecret); /** * PRIVATE SETUP @@ -505,7 +505,7 @@ describe('e2e_fees', () => { await expect(addPendingShieldNoteToPXE(0, shieldedBananas, shieldSecretHash, tx.txHash)).resolves.toBeUndefined(); await expect( - addPendingShieldNoteToPXE(0, RefundAmount, computeMessageSecretHash(RefundSecret), tx.txHash), + addPendingShieldNoteToPXE(0, RefundAmount, computeSecretHash(RefundSecret), tx.txHash), ).resolves.toBeUndefined(); }); @@ -646,7 +646,7 @@ describe('e2e_fees', () => { const mintPrivate = async (amount: bigint, address: AztecAddress) => { // Mint bananas privately const secret = Fr.random(); - const secretHash = computeMessageSecretHash(secret); + const secretHash = computeSecretHash(secret); logger.debug(`Minting ${amount} bananas privately for ${address} with secret ${secretHash.toString()}`); const receipt = await bananaCoin.methods.mint_private(amount, secretHash).send().wait(); diff --git a/yarn-project/end-to-end/src/e2e_lending_contract.test.ts b/yarn-project/end-to-end/src/e2e_lending_contract.test.ts index 738887cdd42..2dd4614f80e 100644 --- a/yarn-project/end-to-end/src/e2e_lending_contract.test.ts +++ b/yarn-project/end-to-end/src/e2e_lending_contract.test.ts @@ -6,7 +6,7 @@ import { Fr, Note, computeAuthWitMessageHash, - computeMessageSecretHash, + computeSecretHash, } from '@aztec/aztec.js'; import { LendingContract, PriceFeedContract, TokenContract } from '@aztec/noir-contracts.js'; @@ -96,7 +96,7 @@ describe('e2e_lending_contract', () => { const mintAmount = 10000n; for (const asset of assets) { const secret = Fr.random(); - const secretHash = computeMessageSecretHash(secret); + const secretHash = computeSecretHash(secret); const a = asset.methods.mint_public(lendingAccount.address, mintAmount).send(); const b = asset.methods.mint_private(mintAmount, secretHash).send(); diff --git a/yarn-project/end-to-end/src/e2e_multiple_accounts_1_enc_key.test.ts b/yarn-project/end-to-end/src/e2e_multiple_accounts_1_enc_key.test.ts index 599a69d8956..cf239abd44f 100644 --- a/yarn-project/end-to-end/src/e2e_multiple_accounts_1_enc_key.test.ts +++ b/yarn-project/end-to-end/src/e2e_multiple_accounts_1_enc_key.test.ts @@ -10,7 +10,7 @@ import { Note, type PXE, type Wallet, - computeMessageSecretHash, + computeSecretHash, deriveKeys, } from '@aztec/aztec.js'; import { TokenContract } from '@aztec/noir-contracts.js/Token'; @@ -59,7 +59,7 @@ describe('e2e_multiple_accounts_1_enc_key', () => { logger.info(`Token deployed at ${tokenAddress}`); const secret = Fr.random(); - const secretHash = computeMessageSecretHash(secret); + const secretHash = computeSecretHash(secret); const receipt = await token.methods.mint_private(initialBalance, secretHash).send().wait(); diff --git a/yarn-project/end-to-end/src/e2e_public_cross_chain_messaging.test.ts b/yarn-project/end-to-end/src/e2e_public_cross_chain_messaging.test.ts index e8aa0bacee3..6108e156ed3 100644 --- a/yarn-project/end-to-end/src/e2e_public_cross_chain_messaging.test.ts +++ b/yarn-project/end-to-end/src/e2e_public_cross_chain_messaging.test.ts @@ -13,7 +13,7 @@ import { L2Actor, type PXE, computeAuthWitMessageHash, - computeMessageSecretHash, + computeSecretHash, } from '@aztec/aztec.js'; import { sha256ToField } from '@aztec/foundation/crypto'; import { InboxAbi, OutboxAbi } from '@aztec/l1-artifacts'; @@ -341,7 +341,7 @@ describe('e2e_public_cross_chain_messaging', () => { new L1Actor(crossChainTestHarness.ethAccount, crossChainTestHarness.publicClient.chain.id), new L2Actor(testContract.address, 1), Fr.random(), // content - computeMessageSecretHash(secret), // secretHash + computeSecretHash(secret), // secretHash ); await sendL2Message(message); diff --git a/yarn-project/end-to-end/src/e2e_token_contract/minting.test.ts b/yarn-project/end-to-end/src/e2e_token_contract/minting.test.ts index 2fa48998dcb..7a833d6a157 100644 --- a/yarn-project/end-to-end/src/e2e_token_contract/minting.test.ts +++ b/yarn-project/end-to-end/src/e2e_token_contract/minting.test.ts @@ -1,4 +1,4 @@ -import { Fr, type TxHash, computeMessageSecretHash } from '@aztec/aztec.js'; +import { Fr, type TxHash, computeSecretHash } from '@aztec/aztec.js'; import { BITSIZE_TOO_BIG_ERROR, U128_OVERFLOW_ERROR } from '../fixtures/fixtures.js'; import { TokenContractTest } from './token_contract_test.js'; @@ -71,7 +71,7 @@ describe('e2e_token_contract minting', () => { let txHash: TxHash; beforeAll(() => { - secretHash = computeMessageSecretHash(secret); + secretHash = computeSecretHash(secret); }); describe('Mint flow', () => { diff --git a/yarn-project/end-to-end/src/e2e_token_contract/shielding.test.ts b/yarn-project/end-to-end/src/e2e_token_contract/shielding.test.ts index 99fcd3c1336..b0cee961f35 100644 --- a/yarn-project/end-to-end/src/e2e_token_contract/shielding.test.ts +++ b/yarn-project/end-to-end/src/e2e_token_contract/shielding.test.ts @@ -1,4 +1,4 @@ -import { Fr, computeMessageSecretHash } from '@aztec/aztec.js'; +import { Fr, computeSecretHash } from '@aztec/aztec.js'; import { U128_UNDERFLOW_ERROR } from '../fixtures/fixtures.js'; import { TokenContractTest } from './token_contract_test.js'; @@ -15,7 +15,7 @@ describe('e2e_token_contract shield + redeem shield', () => { await t.setup(); // Have to destructure again to ensure we have latest refs. ({ asset, accounts, tokenSim, wallets } = t); - secretHash = computeMessageSecretHash(secret); + secretHash = computeSecretHash(secret); }); afterAll(async () => { diff --git a/yarn-project/end-to-end/src/e2e_token_contract/token_contract_test.ts b/yarn-project/end-to-end/src/e2e_token_contract/token_contract_test.ts index 9e6fb3f110c..6325ead8df7 100644 --- a/yarn-project/end-to-end/src/e2e_token_contract/token_contract_test.ts +++ b/yarn-project/end-to-end/src/e2e_token_contract/token_contract_test.ts @@ -7,7 +7,7 @@ import { Fr, Note, type TxHash, - computeMessageSecretHash, + computeSecretHash, createDebugLogger, } from '@aztec/aztec.js'; import { DocsExampleContract, TokenContract } from '@aztec/noir-contracts.js'; @@ -141,7 +141,7 @@ export class TokenContractTest { this.logger.verbose(`Minting ${amount} privately...`); const secret = Fr.random(); - const secretHash = computeMessageSecretHash(secret); + const secretHash = computeSecretHash(secret); const receipt = await asset.methods.mint_private(amount, secretHash).send().wait(); await this.addPendingShieldNoteToPXE(0, amount, secretHash, receipt.txHash); diff --git a/yarn-project/end-to-end/src/flakey_e2e_2_pxes.test.ts b/yarn-project/end-to-end/src/flakey_e2e_2_pxes.test.ts index ce6e676d3ad..ea0b055b11a 100644 --- a/yarn-project/end-to-end/src/flakey_e2e_2_pxes.test.ts +++ b/yarn-project/end-to-end/src/flakey_e2e_2_pxes.test.ts @@ -8,7 +8,7 @@ import { Note, type PXE, type Wallet, - computeMessageSecretHash, + computeSecretHash, retryUntil, } from '@aztec/aztec.js'; import { ChildContract, TokenContract } from '@aztec/noir-contracts.js'; @@ -93,7 +93,7 @@ describe('e2e_2_pxes', () => { const mintTokens = async (contract: TokenContract, recipient: AztecAddress, balance: bigint, pxe: PXE) => { const secret = Fr.random(); - const secretHash = computeMessageSecretHash(secret); + const secretHash = computeSecretHash(secret); const receipt = await contract.methods.mint_private(balance, secretHash).send().wait(); diff --git a/yarn-project/end-to-end/src/guides/dapp_testing.test.ts b/yarn-project/end-to-end/src/guides/dapp_testing.test.ts index 8cde4b58e96..78267af530f 100644 --- a/yarn-project/end-to-end/src/guides/dapp_testing.test.ts +++ b/yarn-project/end-to-end/src/guides/dapp_testing.test.ts @@ -7,7 +7,7 @@ import { Note, type PXE, TxStatus, - computeMessageSecretHash, + computeSecretHash, createPXEClient, waitForPXE, } from '@aztec/aztec.js'; @@ -47,7 +47,7 @@ describe('guides/dapp/testing', () => { const mintAmount = 20n; const secret = Fr.random(); - const secretHash = computeMessageSecretHash(secret); + const secretHash = computeSecretHash(secret); const receipt = await token.methods.mint_private(mintAmount, secretHash).send().wait(); const note = new Note([new Fr(mintAmount), secretHash]); @@ -88,7 +88,7 @@ describe('guides/dapp/testing', () => { const recipientAddress = recipient.getAddress(); const mintAmount = 20n; const secret = Fr.random(); - const secretHash = computeMessageSecretHash(secret); + const secretHash = computeSecretHash(secret); const receipt = await token.methods.mint_private(mintAmount, secretHash).send().wait(); const note = new Note([new Fr(mintAmount), secretHash]); @@ -150,7 +150,7 @@ describe('guides/dapp/testing', () => { const ownerAddress = owner.getAddress(); const mintAmount = 100n; const secret = Fr.random(); - const secretHash = computeMessageSecretHash(secret); + const secretHash = computeSecretHash(secret); const receipt = await token.methods.mint_private(100n, secretHash).send().wait(); const note = new Note([new Fr(mintAmount), secretHash]); diff --git a/yarn-project/end-to-end/src/guides/writing_an_account_contract.test.ts b/yarn-project/end-to-end/src/guides/writing_an_account_contract.test.ts index d708dc1fc69..2072a7ddda5 100644 --- a/yarn-project/end-to-end/src/guides/writing_an_account_contract.test.ts +++ b/yarn-project/end-to-end/src/guides/writing_an_account_contract.test.ts @@ -10,7 +10,7 @@ import { GrumpkinScalar, Note, Schnorr, - computeMessageSecretHash, + computeSecretHash, } from '@aztec/aztec.js'; import { SchnorrHardcodedAccountContractArtifact } from '@aztec/noir-contracts.js/SchnorrHardcodedAccount'; import { TokenContract } from '@aztec/noir-contracts.js/Token'; @@ -68,7 +68,7 @@ describe('guides/writing_an_account_contract', () => { logger.info(`Deployed token contract at ${token.address}`); const secret = Fr.random(); - const secretHash = computeMessageSecretHash(secret); + const secretHash = computeSecretHash(secret); const mintAmount = 50n; const receipt = await token.methods.mint_private(mintAmount, secretHash).send().wait(); diff --git a/yarn-project/end-to-end/src/sample-dapp/index.mjs b/yarn-project/end-to-end/src/sample-dapp/index.mjs index 861c6f2cc03..6f421f61f3a 100644 --- a/yarn-project/end-to-end/src/sample-dapp/index.mjs +++ b/yarn-project/end-to-end/src/sample-dapp/index.mjs @@ -1,5 +1,5 @@ import { getInitialTestAccountsWallets } from '@aztec/accounts/testing'; -import { ExtendedNote, Fr, Note, computeMessageSecretHash, createPXEClient } from '@aztec/aztec.js'; +import { ExtendedNote, Fr, Note, computeSecretHash, createPXEClient } from '@aztec/aztec.js'; import { fileURLToPath } from '@aztec/foundation/url'; import { getToken } from './contracts.mjs'; @@ -34,7 +34,7 @@ async function mintPrivateFunds(pxe) { const mintAmount = 20n; const secret = Fr.random(); - const secretHash = await computeMessageSecretHash(secret); + const secretHash = await computeSecretHash(secret); const receipt = await token.methods.mint_private(mintAmount, secretHash).send().wait(); const storageSlot = new Fr(5); diff --git a/yarn-project/end-to-end/src/sample-dapp/index.test.mjs b/yarn-project/end-to-end/src/sample-dapp/index.test.mjs index 837c5386c97..9508ab1631b 100644 --- a/yarn-project/end-to-end/src/sample-dapp/index.test.mjs +++ b/yarn-project/end-to-end/src/sample-dapp/index.test.mjs @@ -1,13 +1,5 @@ import { createAccount } from '@aztec/accounts/testing'; -import { - Contract, - ExtendedNote, - Fr, - Note, - computeMessageSecretHash, - createPXEClient, - waitForPXE, -} from '@aztec/aztec.js'; +import { Contract, ExtendedNote, Fr, Note, computeSecretHash, createPXEClient, waitForPXE } from '@aztec/aztec.js'; import { TokenContractArtifact } from '@aztec/noir-contracts.js/Token'; const { PXE_URL = 'http://localhost:8080', ETHEREUM_HOST = 'http://localhost:8545' } = process.env; @@ -27,7 +19,7 @@ describe('token', () => { const initialBalance = 20n; const secret = Fr.random(); - const secretHash = await computeMessageSecretHash(secret); + const secretHash = await computeSecretHash(secret); const receipt = await token.methods.mint_private(initialBalance, secretHash).send().wait(); const storageSlot = new Fr(5); diff --git a/yarn-project/end-to-end/src/shared/browser.ts b/yarn-project/end-to-end/src/shared/browser.ts index 516bd3aa87e..370a7698337 100644 --- a/yarn-project/end-to-end/src/shared/browser.ts +++ b/yarn-project/end-to-end/src/shared/browser.ts @@ -221,7 +221,7 @@ export const browserTestSuite = ( Fr, ExtendedNote, Note, - computeMessageSecretHash, + computeSecretHash, getDeployedTestAccountsWallets, INITIAL_TEST_SECRET_KEYS, INITIAL_TEST_SIGNING_KEYS, @@ -261,7 +261,7 @@ export const browserTestSuite = ( console.log(`Contract Deployed: ${token.address}`); const secret = Fr.random(); - const secretHash = computeMessageSecretHash(secret); + const secretHash = computeSecretHash(secret); const mintPrivateReceipt = await token.methods.mint_private(initialBalance, secretHash).send().wait(); const storageSlot = new Fr(5); diff --git a/yarn-project/end-to-end/src/shared/cross_chain_test_harness.ts b/yarn-project/end-to-end/src/shared/cross_chain_test_harness.ts index 5da650d74d4..994d41e7d21 100644 --- a/yarn-project/end-to-end/src/shared/cross_chain_test_harness.ts +++ b/yarn-project/end-to-end/src/shared/cross_chain_test_harness.ts @@ -13,7 +13,7 @@ import { type TxHash, type TxReceipt, type Wallet, - computeMessageSecretHash, + computeSecretHash, deployL1Contract, retryUntil, } from '@aztec/aztec.js'; @@ -223,10 +223,15 @@ export class CrossChainTestHarness { public ownerAddress: AztecAddress, ) {} + /** + * Used to generate a claim secret using pedersen's hash function. + * @dev Used for both L1 to L2 messages and transparent note (pending shields) secrets. + * @returns A tuple of the secret and its hash. + */ generateClaimSecret(): [Fr, Fr] { this.logger.debug("Generating a claim secret using pedersen's hash function"); const secret = Fr.random(); - const secretHash = computeMessageSecretHash(secret); + const secretHash = computeSecretHash(secret); this.logger.info('Generated claim secret: ' + secretHash.toString()); return [secret, secretHash]; } diff --git a/yarn-project/end-to-end/src/shared/gas_portal_test_harness.ts b/yarn-project/end-to-end/src/shared/gas_portal_test_harness.ts index ff3a4dc4389..dee68998224 100644 --- a/yarn-project/end-to-end/src/shared/gas_portal_test_harness.ts +++ b/yarn-project/end-to-end/src/shared/gas_portal_test_harness.ts @@ -6,7 +6,7 @@ import { Fr, type PXE, type Wallet, - computeMessageSecretHash, + computeSecretHash, } from '@aztec/aztec.js'; import { GasPortalAbi, OutboxAbi, PortalERC20Abi } from '@aztec/l1-artifacts'; import { GasTokenContract } from '@aztec/noir-contracts.js'; @@ -153,7 +153,7 @@ class GasBridgingTestHarness implements IGasBridgingTestHarness { generateClaimSecret(): [Fr, Fr] { this.logger.debug("Generating a claim secret using pedersen's hash function"); const secret = Fr.random(); - const secretHash = computeMessageSecretHash(secret); + const secretHash = computeSecretHash(secret); this.logger.info('Generated claim secret: ' + secretHash.toString()); return [secret, secretHash]; } diff --git a/yarn-project/simulator/src/client/client_execution_context.ts b/yarn-project/simulator/src/client/client_execution_context.ts index 88720fba6f8..0ec755281cc 100644 --- a/yarn-project/simulator/src/client/client_execution_context.ts +++ b/yarn-project/simulator/src/client/client_execution_context.ts @@ -22,7 +22,7 @@ import { type TxContext, } from '@aztec/circuits.js'; import { type Grumpkin } from '@aztec/circuits.js/barretenberg'; -import { computePublicDataTreeLeafSlot, computeUniqueCommitment, siloNoteHash } from '@aztec/circuits.js/hash'; +import { computePublicDataTreeLeafSlot, computeUniqueNoteHash, siloNoteHash } from '@aztec/circuits.js/hash'; import { type FunctionAbi, type FunctionArtifact, countArgumentsSize } from '@aztec/foundation/abi'; import { type AztecAddress } from '@aztec/foundation/aztec-address'; import { Fr, type Point } from '@aztec/foundation/fields'; @@ -257,7 +257,7 @@ export class ClientExecutionContext extends ViewDataOracle { notes.forEach(n => { if (n.index !== undefined) { const siloedNoteHash = siloNoteHash(n.contractAddress, n.innerNoteHash); - const uniqueSiloedNoteHash = computeUniqueCommitment(n.nonce, siloedNoteHash); + const uniqueSiloedNoteHash = computeUniqueNoteHash(n.nonce, siloedNoteHash); // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1386) // Should always be uniqueSiloedNoteHash when publicly created notes include nonces. const noteHashForReadRequest = n.nonce.isZero() ? siloedNoteHash : uniqueSiloedNoteHash; diff --git a/yarn-project/simulator/src/client/private_execution.test.ts b/yarn-project/simulator/src/client/private_execution.test.ts index 7156422a39b..ecff905aea0 100644 --- a/yarn-project/simulator/src/client/private_execution.test.ts +++ b/yarn-project/simulator/src/client/private_execution.test.ts @@ -5,6 +5,7 @@ import { CompleteAddress, FunctionData, GasSettings, + GeneratorIndex, type GrumpkinPrivateKey, Header, L1_TO_L2_MSG_TREE_HEIGHT, @@ -20,7 +21,7 @@ import { nonEmptySideEffects, sideEffectArrayToValueArray, } from '@aztec/circuits.js'; -import { computeCommitmentNonce, computeMessageSecretHash, computeVarArgsHash } from '@aztec/circuits.js/hash'; +import { computeCommitmentNonce, computeSecretHash, computeVarArgsHash } from '@aztec/circuits.js/hash'; import { makeHeader } from '@aztec/circuits.js/testing'; import { type FunctionArtifact, @@ -32,7 +33,7 @@ import { import { asyncMap } from '@aztec/foundation/async-map'; import { AztecAddress } from '@aztec/foundation/aztec-address'; import { times } from '@aztec/foundation/collection'; -import { pedersenHash, randomInt } from '@aztec/foundation/crypto'; +import { pedersenHash, poseidon2Hash, randomInt } from '@aztec/foundation/crypto'; import { EthAddress } from '@aztec/foundation/eth-address'; import { Fr } from '@aztec/foundation/fields'; import { type DebugLogger, createDebugLogger } from '@aztec/foundation/log'; @@ -726,7 +727,7 @@ describe('Private Execution test suite', () => { it('Should be able to consume a dummy public to private message', async () => { const artifact = getFunctionArtifact(TestContractArtifact, 'consume_note_from_secret'); const secret = new Fr(1n); - const secretHash = computeMessageSecretHash(secret); + const secretHash = computeSecretHash(secret); const note = new Note([secretHash]); const storageSlot = new Fr(5); oracle.getNotes.mockResolvedValue([ @@ -878,9 +879,10 @@ describe('Private Execution test suite', () => { expect(result.returnValues).toEqual([new Fr(amountToTransfer)]); const nullifier = result.callStackItem.publicInputs.newNullifiers[0]; - const expectedNullifier = pedersenHash([ + const expectedNullifier = poseidon2Hash([ innerNoteHash, computeAppNullifierSecretKey(ownerMasterNullifierSecretKey, contractAddress), + GeneratorIndex.NOTE_NULLIFIER, ]); expect(nullifier.value).toEqual(expectedNullifier); }); @@ -946,9 +948,10 @@ describe('Private Execution test suite', () => { expect(execGetThenNullify.returnValues).toEqual([new Fr(amountToTransfer)]); const nullifier = execGetThenNullify.callStackItem.publicInputs.newNullifiers[0]; - const expectedNullifier = pedersenHash([ + const expectedNullifier = poseidon2Hash([ innerNoteHash, computeAppNullifierSecretKey(ownerMasterNullifierSecretKey, contractAddress), + GeneratorIndex.NOTE_NULLIFIER, ]); expect(nullifier.value).toEqual(expectedNullifier); }); diff --git a/yarn-project/simulator/src/client/simulator.test.ts b/yarn-project/simulator/src/client/simulator.test.ts index c22244d2881..62bb0c13b07 100644 --- a/yarn-project/simulator/src/client/simulator.test.ts +++ b/yarn-project/simulator/src/client/simulator.test.ts @@ -1,13 +1,18 @@ import { type AztecNode, CompleteAddress, Note } from '@aztec/circuit-types'; -import { computeAppNullifierSecretKey, deriveKeys } from '@aztec/circuits.js'; -import { computeUniqueCommitment, siloNoteHash } from '@aztec/circuits.js/hash'; +import { GeneratorIndex, computeAppNullifierSecretKey, deriveKeys } from '@aztec/circuits.js'; +import { + computeInnerNoteHash, + computeNoteContentHash, + computeUniqueNoteHash, + siloNoteHash, +} from '@aztec/circuits.js/hash'; import { ABIParameterVisibility, type FunctionArtifactWithDebugMetadata, getFunctionArtifact, } from '@aztec/foundation/abi'; import { AztecAddress } from '@aztec/foundation/aztec-address'; -import { pedersenHash } from '@aztec/foundation/crypto'; +import { poseidon2Hash } from '@aztec/foundation/crypto'; import { Fr } from '@aztec/foundation/fields'; import { TokenContractArtifact } from '@aztec/noir-contracts.js/Token'; @@ -63,12 +68,15 @@ describe('Simulator', () => { oracle.getFunctionArtifactByName.mockResolvedValue(artifact); const note = createNote(); - const tokenNoteHash = pedersenHash(note.items); - const innerNoteHash = pedersenHash([storageSlot, tokenNoteHash]); + const tokenNoteHash = computeNoteContentHash(note.items); + const innerNoteHash = computeInnerNoteHash(storageSlot, tokenNoteHash); const siloedNoteHash = siloNoteHash(contractAddress, innerNoteHash); - const uniqueSiloedNoteHash = computeUniqueCommitment(nonce, siloedNoteHash); - // TODO(#5832): all the pedersen hashes in notes should be replaced with poseidon2 - const innerNullifier = pedersenHash([uniqueSiloedNoteHash, appNullifierSecretKey]); + const uniqueSiloedNoteHash = computeUniqueNoteHash(nonce, siloedNoteHash); + const innerNullifier = poseidon2Hash([ + uniqueSiloedNoteHash, + appNullifierSecretKey, + GeneratorIndex.NOTE_NULLIFIER, + ]); const result = await simulator.computeNoteHashAndNullifier(contractAddress, nonce, storageSlot, noteTypeId, note); diff --git a/yarn-project/simulator/src/public/index.test.ts b/yarn-project/simulator/src/public/index.test.ts index 04568e3a46a..886ebf355fb 100644 --- a/yarn-project/simulator/src/public/index.test.ts +++ b/yarn-project/simulator/src/public/index.test.ts @@ -12,7 +12,7 @@ import { NullifierLeaf, NullifierLeafPreimage, } from '@aztec/circuits.js'; -import { siloNullifier } from '@aztec/circuits.js/hash'; +import { computeInnerNoteHash, computeNoteContentHash, siloNullifier } from '@aztec/circuits.js/hash'; import { makeHeader } from '@aztec/circuits.js/testing'; import { type FunctionArtifact, FunctionSelector, encodeArguments } from '@aztec/foundation/abi'; import { AztecAddress } from '@aztec/foundation/aztec-address'; @@ -334,9 +334,9 @@ describe('ACIR public execution simulator', () => { // Assert the note hash was created expect(result.newNoteHashes.length).toEqual(1); - const expectedNoteHash = pedersenHash([amount, secretHash]); + const expectedNoteHash = computeNoteContentHash([amount, secretHash]); const storageSlot = new Fr(5); // for pending_shields - const expectedInnerNoteHash = pedersenHash([storageSlot, expectedNoteHash]); + const expectedInnerNoteHash = computeInnerNoteHash(storageSlot, expectedNoteHash); expect(result.newNoteHashes[0].value).toEqual(expectedInnerNoteHash); }); diff --git a/yarn-project/simulator/src/test/utils.ts b/yarn-project/simulator/src/test/utils.ts index 56231284d8e..69769b28c7b 100644 --- a/yarn-project/simulator/src/test/utils.ts +++ b/yarn-project/simulator/src/test/utils.ts @@ -1,6 +1,6 @@ import { L1Actor, L1ToL2Message, L2Actor } from '@aztec/circuit-types'; import { type AztecAddress, EthAddress, type Fr } from '@aztec/circuits.js'; -import { computeMessageSecretHash } from '@aztec/circuits.js/hash'; +import { computeSecretHash } from '@aztec/circuits.js/hash'; import { sha256ToField } from '@aztec/foundation/crypto'; /** @@ -21,7 +21,7 @@ export const buildL1ToL2Message = ( const selectorBuf = Buffer.from(selector, 'hex'); const content = sha256ToField([selectorBuf, ...contentPreimage]); - const secretHash = computeMessageSecretHash(secret); + const secretHash = computeSecretHash(secret); return new L1ToL2Message(new L1Actor(EthAddress.random(), 1), new L2Actor(targetContract, 1), content, secretHash); }; From 190813911c5e4fc7533525478ceca4162170fa6b Mon Sep 17 00:00:00 2001 From: Alex Gherghisan Date: Wed, 24 Apr 2024 11:07:07 +0100 Subject: [PATCH 099/102] fix: deploy L1 contracts before starting node (#5969) First deploy L1 contracts before starting node/archiver/pxe --- yarn-project/aztec/src/cli/cmds/start_node.ts | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/yarn-project/aztec/src/cli/cmds/start_node.ts b/yarn-project/aztec/src/cli/cmds/start_node.ts index d9a28ced7a2..3b29bb8ee4b 100644 --- a/yarn-project/aztec/src/cli/cmds/start_node.ts +++ b/yarn-project/aztec/src/cli/cmds/start_node.ts @@ -29,6 +29,17 @@ export const startNode = async ( // merge env vars and cli options let nodeConfig = mergeEnvVarsAndCliOptions(aztecNodeConfigEnvVars, nodeCliOptions); + // Deploy contracts if needed + if (nodeCliOptions.deployAztecContracts || DEPLOY_AZTEC_CONTRACTS === 'true') { + let account; + if (nodeConfig.publisherPrivateKey === NULL_KEY) { + account = mnemonicToAccount(MNEMONIC); + } else { + account = privateKeyToAccount(nodeConfig.publisherPrivateKey); + } + await deployContractsToL1(nodeConfig, account); + } + // if no publisher private key, then use MNEMONIC if (!options.archiver) { // expect archiver url in node config @@ -40,18 +51,7 @@ export const startNode = async ( nodeConfig.archiverUrl = archiverUrl; } else { const archiverCliOptions = parseModuleOptions(options.archiver); - nodeConfig = mergeEnvVarsAndCliOptions(aztecNodeConfigEnvVars, archiverCliOptions, true); - } - - // Deploy contracts if needed - if (nodeCliOptions.deployAztecContracts || DEPLOY_AZTEC_CONTRACTS === 'true') { - let account; - if (nodeConfig.publisherPrivateKey === NULL_KEY) { - account = mnemonicToAccount(MNEMONIC); - } else { - account = privateKeyToAccount(nodeConfig.publisherPrivateKey); - } - await deployContractsToL1(nodeConfig, account); + nodeConfig = mergeEnvVarsAndCliOptions(nodeConfig, archiverCliOptions, true); } if (!options.sequencer) { From b3fdb3b59e887974b89db0eb209e16b0630b1360 Mon Sep 17 00:00:00 2001 From: Alex Gherghisan Date: Wed, 24 Apr 2024 11:42:37 +0100 Subject: [PATCH 100/102] chore: yarn build:dev don't clear terminal (#5970) Small QoL improvement to not clear the console when running `yarn build:dev` in the root of the workspace --- yarn-project/watch.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/yarn-project/watch.sh b/yarn-project/watch.sh index 88cf51e6b60..d52f682f692 100755 --- a/yarn-project/watch.sh +++ b/yarn-project/watch.sh @@ -13,7 +13,7 @@ debounce() { local run_id=$(uuidgen) echo "$run_id" > ".debounce-$group_id" ( - sleep $DEBOUNCE_DURATION; + sleep $DEBOUNCE_DURATION; local current_id=$(cat ".debounce-$group_id"); if [ "$run_id" = "${current_id}" ]; then "$@" @@ -24,7 +24,7 @@ debounce() { # Start typescript watch process in the background and store process ID in a file start_tsc_watch() { local tsc_bin=$(yarn bin tsc) - $tsc_bin -b tsconfig.json --watch & + $tsc_bin -b tsconfig.json --watch --preserveWatchOutput & TSC_PID=$! echo "$TSC_PID" > .tsc.pid } From 616a8f328f893ab563b1d90c5c627572cf838968 Mon Sep 17 00:00:00 2001 From: James Zaki Date: Wed, 24 Apr 2024 12:30:39 +0100 Subject: [PATCH 101/102] docs: update emit_event.md (#5964) --- .../developers/contracts/writing_contracts/events/emit_event.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/docs/developers/contracts/writing_contracts/events/emit_event.md b/docs/docs/developers/contracts/writing_contracts/events/emit_event.md index 0c461c6317d..5ff18cce72e 100644 --- a/docs/docs/developers/contracts/writing_contracts/events/emit_event.md +++ b/docs/docs/developers/contracts/writing_contracts/events/emit_event.md @@ -93,6 +93,7 @@ They can be emitted by both public and private functions. :::danger - Emitting unencrypted events from private function is a significant privacy leak and it should be considered by the developer whether it is acceptable. - Unencrypted events are currently **NOT** linked to the contract emitting them, so it is practically a [`debug_log`](../oracles/main.md#a-few-useful-inbuilt-oracles). + ::: ### Call emit_unencrypted_log From 1801db88640b0e012fa32650bf8074587709ef83 Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Wed, 24 Apr 2024 13:25:13 +0100 Subject: [PATCH 102/102] chore(ci): make syncing out to Noir manual (#5997) Most of the sync PRs being pushed into Noir are massive and revert significant amounts of Noir development. In order to sync from aztec-packages without having to manually separate out all of these reversions, it's required to do a manual sync from the main noir repo into aztec-packages first and then sync out again. We should then make this second sync manual as well. --- .github/workflows/mirror-noir-subrepo.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.github/workflows/mirror-noir-subrepo.yml b/.github/workflows/mirror-noir-subrepo.yml index fb6968cc940..abcae31ac0a 100644 --- a/.github/workflows/mirror-noir-subrepo.yml +++ b/.github/workflows/mirror-noir-subrepo.yml @@ -9,12 +9,6 @@ concurrency: cancel-in-progress: false on: workflow_dispatch: {} - push: - branches: - - master - paths: - - "noir/noir-repo/**" - - "!noir/noir-repo/.gitrepo" jobs: mirror_repo: