Skip to content

Commit d9badbd

Browse files
authored
Merge pull request #92 from AztecProtocol/jc/pxe-service
Use independent PXE service instead of the one included in the sandbox
2 parents 971b89c + 6f176a3 commit d9badbd

File tree

17 files changed

+1212
-170
lines changed

17 files changed

+1212
-170
lines changed

.github/workflows/tests.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,4 @@ jobs:
4747
run: script -e -c "NODE_NO_WARNINGS=1 node --experimental-vm-modules $(yarn bin jest) --no-cache --runInBand --config jest.integration.config.json && aztec test"
4848

4949
- name: Run scripts
50-
run: script -e -c "yarn deploy && yarn deploy-account && yarn fees"
50+
run: script -e -c "yarn deploy && yarn deploy-account && yarn fees && yarn multiple-pxe"

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ log/
55
.vscode
66
.DS_Store
77
codegenCache.json
8+
store/

README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ yarn codegen
9292

9393
---
9494

95+
:warning: Tests and scripts set up and run the Private Execution Environment (PXE) and store PXE data in the `./store` directory. If you restart the sandbox, you will need to delete the `./store` directory to avoid errors.
96+
9597
## 🧪 **Test**
9698

9799
**Make sure the sandbox is running before running tests.**
@@ -112,8 +114,19 @@ Note: The Typescript tests spawn an instance of the sandbox to test against, and
112114

113115
---
114116

117+
## Scripts
118+
119+
You can find a handful of scripts in the `./scripts` folder.
120+
121+
- `./scripts/deploy-accounts.ts` is an example of how to deploy a schnorr account.
122+
- `./scripts/deploy.ts` is an example of how to deploy a contract.
123+
- `./scripts/fees.ts` is an example of how to pay for a contract deployment using various fee payment methods.
124+
- `./scripts/multiple_pxe.ts` is an example of how to deploy a contract from one PXE instance and interact with it from another.
125+
115126
## **Error Resolution**
116127

128+
:warning: Tests and scripts set up and run the Private Execution Environment (PXE) and store PXE data in the `./store` directory. If you restart the sandbox, you will need to delete the `./store` directory to avoid errors.
129+
117130
### 🔄 **Update Node.js and Noir Dependencies**
118131

119132
```bash

package.json

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,15 @@
1010
"scripts": {
1111
"fees": "node --loader ts-node/esm scripts/fees.ts",
1212
"clean": "rm -rf ./src/artifacts ./target",
13+
"clear-store": "rm -rf ./store",
1314
"codegen": "aztec codegen target --outdir src/artifacts",
1415
"compile": "${AZTEC_NARGO:-aztec-nargo} compile",
15-
"deploy": "node --loader ts-node/esm scripts/deploy-contract.ts",
16-
"deploy-account": "node --loader ts-node/esm scripts/deploy-account.ts",
17-
"get-block": "node --loader ts-node/esm scripts/getBlock.ts",
16+
"deploy": "node --loader ts-node/esm scripts/deploy_contract.ts",
17+
"deploy-account": "node --loader ts-node/esm scripts/deploy_account.ts",
18+
"multiple-pxe": "node --loader ts-node/esm scripts/multiple_pxe.ts",
19+
"get-block": "node --loader ts-node/esm scripts/get_block.ts",
1820
"test": "yarn test:js && yarn test:nr",
19-
"test:js": "NODE_NO_WARNINGS=1 node --experimental-vm-modules $(yarn bin jest) --no-cache --runInBand --config jest.integration.config.json",
21+
"test:js": "rm -rf store/pxe && NODE_NO_WARNINGS=1 node --experimental-vm-modules $(yarn bin jest) --no-cache --runInBand --config jest.integration.config.json",
2022
"test:nr": "aztec test",
2123
"update": "aztec update --contract . && ./.github/scripts/update_contract.sh $(grep -oP 'tag\\s*=\\s*\"\\K[^\"]+' \"Nargo.toml\" | head -1) && yarn && yarn update-readme-version",
2224
"update-readme-version": "node ./.github/scripts/update-readme-version.js"
@@ -25,6 +27,8 @@
2527
"@aztec/accounts": "0.86.0",
2628
"@aztec/aztec.js": "0.86.0",
2729
"@aztec/noir-contracts.js": "0.86.0",
30+
"@aztec/protocol-contracts": "0.86.0",
31+
"@aztec/pxe": "0.86.0",
2832
"@aztec/stdlib": "0.86.0",
2933
"@types/node": "^22.5.1"
3034
},

scripts/deploy-contract.ts

Lines changed: 0 additions & 28 deletions
This file was deleted.

scripts/deploy_account.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { createLogger, Logger } from "@aztec/aztec.js";
2+
import { setupPXE } from "../src/utils/setup_pxe.js";
3+
import { deploySchnorrAccount } from "../src/utils/deploy_account.js";
4+
5+
export async function deployAccount() {
6+
let logger: Logger;
7+
logger = createLogger('aztec:aztec-starter');
8+
const pxe = await setupPXE()
9+
await deploySchnorrAccount(pxe);
10+
}
11+
12+
deployAccount();

scripts/deploy_contract.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { EasyPrivateVotingContract } from "../src/artifacts/EasyPrivateVoting.js"
2+
import { createLogger, PXE, Logger, SponsoredFeePaymentMethod, Fr } from "@aztec/aztec.js";
3+
import { TokenContract } from "@aztec/noir-contracts.js/Token"
4+
import { setupPXE } from "../src/utils/setup_pxe.js";
5+
import { getSponsoredFPCInstance } from "../src/utils/sponsored_fpc.js";
6+
import { SponsoredFPCContract } from "@aztec/noir-contracts.js/SponsoredFPC";
7+
import { deploySchnorrAccount } from "../src/utils/deploy_account.js";
8+
9+
async function main() {
10+
11+
let pxe: PXE;
12+
let logger: Logger;
13+
14+
logger = createLogger('aztec:aztec-starter');
15+
16+
pxe = await setupPXE();
17+
18+
const sponsoredFPC = await getSponsoredFPCInstance();
19+
await pxe.registerContract({ instance: sponsoredFPC, artifact: SponsoredFPCContract.artifact });
20+
const sponsoredPaymentMethod = new SponsoredFeePaymentMethod(sponsoredFPC.address);
21+
22+
let accountManager = await deploySchnorrAccount(pxe);
23+
const wallet = await accountManager.getWallet();
24+
const address = await accountManager.getAddress();
25+
26+
const votingContract = await EasyPrivateVotingContract.deploy(wallet, address).send({ fee: { paymentMethod: sponsoredPaymentMethod } }).deployed();
27+
logger.info(`Voting Contract deployed at: ${votingContract.address}`);
28+
}
29+
30+
main();

scripts/fees.ts

Lines changed: 44 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,7 @@
1-
import { AccountWallet, CompleteAddress, createLogger, FeeJuicePaymentMethodWithClaim, Fr, L1FeeJuicePortalManager, PXE, waitForPXE , createPXEClient, Logger, FeeJuicePaymentMethod, PrivateFeePaymentMethod, PublicFeePaymentMethod } from "@aztec/aztec.js";
2-
import { getInitialTestAccountsWallets } from "@aztec/accounts/testing";
31
import {
4-
createPublicClient,
52
createWalletClient,
63
http,
74
} from 'viem';
8-
import { getSchnorrAccount } from '@aztec/accounts/schnorr';
9-
import { deriveSigningKey } from '@aztec/stdlib/keys';
105
import { foundry } from 'viem/chains'
116
import { mnemonicToAccount } from 'viem/accounts';
127
import { FeeJuiceContract } from "@aztec/noir-contracts.js/FeeJuice";
@@ -15,46 +10,46 @@ import { EasyPrivateVotingContract } from "../src/artifacts/EasyPrivateVoting.js
1510
import { TokenContract } from "@aztec/noir-contracts.js/Token";
1611
// TODO: replace with import from aztec.js when published
1712
import { SponsoredFeePaymentMethod } from '@aztec/aztec.js/fee/testing'
18-
import { getDeployedSponsoredFPCAddress } from "../src/utils/sponsored_fpc.js";
13+
import { getDeployedSponsoredFPCAddress, getSponsoredFPCInstance } from "../src/utils/sponsored_fpc.js";
1914
import { createEthereumChain, createExtendedL1Client } from "@aztec/ethereum";
20-
21-
const setupSandbox = async () => {
22-
const { PXE_URL = 'http://localhost:8080' } = process.env;
23-
const pxe = await createPXEClient(PXE_URL);
24-
await waitForPXE(pxe);
25-
return pxe;
26-
};
15+
import { deploySchnorrAccount } from "../src/utils/deploy_account.js";
16+
import { setupPXE } from "../src/utils/setup_pxe.js";
17+
import { createLogger, FeeJuicePaymentMethod, FeeJuicePaymentMethodWithClaim, Fr, L1FeeJuicePortalManager, Logger, PrivateFeePaymentMethod, PublicFeePaymentMethod, PXE } from '@aztec/aztec.js';
18+
import { SponsoredFPCContract } from '@aztec/noir-contracts.js/SponsoredFPC';
19+
import { getCanonicalFeeJuice } from '@aztec/protocol-contracts/fee-juice';
20+
import { getSchnorrAccount } from '@aztec/accounts/schnorr';
21+
import { deriveSigningKey } from '@aztec/stdlib/keys';
2722

2823
const MNEMONIC = 'test test test test test test test test test test test junk';
2924
const FEE_FUNDING_FOR_TESTER_ACCOUNT = 1000000000000000000n;
3025

3126
let walletClient = getL1WalletClient(foundry.rpcUrls.default.http[0], 0);
3227
const ownerEthAddress = walletClient.account.address;
3328

34-
3529
async function main() {
3630

3731
let pxe: PXE;
38-
let wallets: AccountWallet[] = [];
3932
let logger: Logger;
4033

4134
logger = createLogger('aztec:aztec-starter');
4235

43-
pxe = await setupSandbox();
44-
wallets = await getInitialTestAccountsWallets(pxe);
36+
pxe = await setupPXE();
37+
// wallets = await getInitialTestAccountsWallets(pxe);
4538
const nodeInfo = (await pxe.getNodeInfo())
4639

4740
const chain = createEthereumChain(['http://localhost:8545'], nodeInfo.l1ChainId);
4841
const l1Client = createExtendedL1Client(chain.rpcUrls, MNEMONIC, chain.chainInfo);
4942

5043
// Setup Schnorr AccountManager
5144

45+
const account1 = await deploySchnorrAccount(pxe);
46+
const wallet1 = await account1.getWallet();
47+
5248
let secretKey = Fr.random();
5349
let salt = Fr.random();
54-
let schnorrAccount = await getSchnorrAccount(pxe, secretKey, deriveSigningKey(secretKey), salt);
55-
56-
const newWallet = await schnorrAccount.getWallet()
57-
const feeJuiceReceipient = schnorrAccount.getAddress()
50+
let account2 = await getSchnorrAccount(pxe, secretKey, deriveSigningKey(secretKey), salt);
51+
const wallet2 = await account2.getWallet();
52+
const feeJuiceRecipient = account2.getAddress();
5853

5954
// Setup and bridge fee asset to L2 to get fee juice
6055

@@ -65,26 +60,30 @@ async function main() {
6560
logger,
6661
);
6762

68-
const claim = await feeJuicePortalManager.bridgeTokensPublic(feeJuiceReceipient, FEE_FUNDING_FOR_TESTER_ACCOUNT, true);
63+
const claim = await feeJuicePortalManager.bridgeTokensPublic(feeJuiceRecipient, FEE_FUNDING_FOR_TESTER_ACCOUNT, true);
64+
65+
logger.info(`Fee Juice minted to ${feeJuiceRecipient} on L2.`)
6966

70-
const feeJuice = await FeeJuiceContract.at(nodeInfo.protocolContractAddresses.feeJuice, wallets[0])
71-
logger.info(`Fee Juice minted to ${feeJuiceReceipient} on L2.`)
67+
// set up sponsored fee payments
68+
const sponseredFPC = await getSponsoredFPCInstance();
69+
await pxe.registerContract({ instance: sponseredFPC, artifact: SponsoredFPCContract.artifact });
70+
const paymentMethod = new SponsoredFeePaymentMethod(sponseredFPC.address);
7271

7372
// Two arbitraty txs to make the L1 message available on L2
74-
const votingContract = await EasyPrivateVotingContract.deploy(wallets[0], wallets[0].getAddress()).send().deployed();
75-
const bananaCoin = await TokenContract.deploy(wallets[0], wallets[0].getAddress(), "bananaCoin", "BNC", 18).send().deployed()
73+
const votingContract = await EasyPrivateVotingContract.deploy(wallet1, wallet1.getAddress()).send({ fee: { paymentMethod } }).deployed();
74+
const bananaCoin = await TokenContract.deploy(wallet1, wallet1.getAddress(), "bananaCoin", "BNC", 18).send({ fee: { paymentMethod } }).deployed()
7675

7776
// Claim Fee Juice & Pay Fees yourself
7877

79-
const claimAndPay = new FeeJuicePaymentMethodWithClaim(newWallet, claim)
80-
await schnorrAccount.deploy({ fee: { paymentMethod: claimAndPay } }).wait()
81-
logger.info(`New account at ${newWallet.getAddress()} deployed using claimed funds for fees.`)
78+
const claimAndPay = new FeeJuicePaymentMethodWithClaim(wallet2, claim)
79+
await account2.deploy({ fee: { paymentMethod: claimAndPay } }).wait()
80+
logger.info(`New account at ${account2.getAddress()} deployed using claimed funds for fees.`)
8281

8382
// Pay fees yourself
8483

8584
// Create a new voting contract instance, interacting from the newWallet
86-
const useFeeJuice = new FeeJuicePaymentMethod(newWallet.getAddress())
87-
await votingContract.withWallet(newWallet).methods.cast_vote(wallets[0].getAddress()).send({ fee: { paymentMethod: useFeeJuice }}).wait()
85+
const useFeeJuice = new FeeJuicePaymentMethod(account2.getAddress())
86+
await votingContract.withWallet(wallet2).methods.cast_vote(wallet1.getAddress()).send({ fee: { paymentMethod: useFeeJuice } }).wait()
8887
logger.info(`Vote cast from new account, paying fees via newWallet.`)
8988

9089
// Private Fee Payments via FPC
@@ -93,38 +92,40 @@ async function main() {
9392
// Need to deploy an FPC to use Private Fee payment methods
9493

9594
// This uses bananaCoin as the fee paying asset that will be exchanged for fee juice
96-
const fpc = await FPCContract.deploy(wallets[0], bananaCoin.address, wallets[0].getAddress()).send().deployed()
95+
const fpc = await FPCContract.deploy(wallet1, bananaCoin.address, wallet1.getAddress()).send({ fee: { paymentMethod } }).deployed()
9796
const fpcClaim = await feeJuicePortalManager.bridgeTokensPublic(fpc.address, FEE_FUNDING_FOR_TESTER_ACCOUNT, true);
9897
// 2 public txs to make the bridged fee juice available
9998
// Mint some bananaCoin and send to the newWallet to pay fees privately
100-
await bananaCoin.methods.mint_to_private(wallets[0].getAddress(), newWallet.getAddress(), FEE_FUNDING_FOR_TESTER_ACCOUNT).send().wait()
99+
await bananaCoin.methods.mint_to_private(wallet1.getAddress(), wallet2.getAddress(), FEE_FUNDING_FOR_TESTER_ACCOUNT).send({ fee: { paymentMethod } }).wait()
101100
// mint some public bananaCoin to the newWallet to pay fees publicly
102-
await bananaCoin.methods.mint_to_public(newWallet.getAddress(), FEE_FUNDING_FOR_TESTER_ACCOUNT).send().wait()
103-
const bananaBalance = await bananaCoin.withWallet(newWallet).methods.balance_of_private(newWallet.getAddress()).simulate()
101+
await bananaCoin.methods.mint_to_public(wallet2.getAddress(), FEE_FUNDING_FOR_TESTER_ACCOUNT).send({ fee: { paymentMethod } }).wait()
102+
const bananaBalance = await bananaCoin.withWallet(wallet2).methods.balance_of_private(wallet2.getAddress()).simulate()
104103

105104
logger.info(`BananaCoin balance of newWallet is ${bananaBalance}`)
106105

106+
const feeJuiceInstance = await getCanonicalFeeJuice();
107+
const feeJuice = await FeeJuiceContract.at(feeJuiceInstance.address, wallet2)
107108
await feeJuice.methods.claim(fpc.address, fpcClaim.claimAmount, fpcClaim.claimSecret, fpcClaim.messageLeafIndex).send().wait()
108109

109110
logger.info(`Fpc fee juice balance ${await feeJuice.methods.balance_of_public(fpc.address).simulate()}`)
110111

111-
const privateFee = new PrivateFeePaymentMethod(fpc.address, newWallet)
112-
await bananaCoin.withWallet(newWallet).methods.transfer_in_private(newWallet.getAddress(), wallets[0].getAddress(), 10, 0).send({ fee: { paymentMethod: privateFee }}).wait()
113-
112+
const privateFee = new PrivateFeePaymentMethod(fpc.address, wallet2)
113+
await bananaCoin.withWallet(wallet2).methods.transfer_in_private(wallet2.getAddress(), wallet1.getAddress(), 10, 0).send({ fee: { paymentMethod: privateFee } }).wait()
114+
114115
logger.info(`Transfer paid with fees via the FPC, privately.`)
115116

116117
// Public Fee Payments via FPC
117118

118-
const publicFee = new PublicFeePaymentMethod(fpc.address, newWallet)
119-
await bananaCoin.withWallet(newWallet).methods.transfer_in_private(newWallet.getAddress(), wallets[0].getAddress(), 10, 0).send({ fee: { paymentMethod: publicFee }}).wait()
119+
const publicFee = new PublicFeePaymentMethod(fpc.address, wallet2)
120+
await bananaCoin.withWallet(wallet2).methods.transfer_in_private(wallet2.getAddress(), wallet1.getAddress(), 10, 0).send({ fee: { paymentMethod: publicFee } }).wait()
120121
logger.info(`Transfer paid with fees via the FPC, publicly.`)
121122

122123
// Sponsored Fee Payment
123124

124125
// This method will only work in environments where there is a sponsored fee contract deployed
125126
const deployedSponseredFPC = await getDeployedSponsoredFPCAddress(pxe);
126127
const sponsoredPaymentMethod = new SponsoredFeePaymentMethod(deployedSponseredFPC);
127-
await bananaCoin.withWallet(newWallet).methods.transfer_in_private(newWallet.getAddress(), wallets[0].getAddress(), 10, 0).send({ fee: { paymentMethod: sponsoredPaymentMethod }}).wait()
128+
await bananaCoin.withWallet(wallet2).methods.transfer_in_private(wallet2.getAddress(), wallet1.getAddress(), 10, 0).send({ fee: { paymentMethod: sponsoredPaymentMethod } }).wait()
128129
logger.info(`Transfer paid with fees from Sponsored FPC.`)
129130
}
130131

@@ -138,4 +139,5 @@ function getL1WalletClient(rpcUrl: string, index: number) {
138139
chain: foundry,
139140
transport: http(rpcUrl),
140141
});
141-
}
142+
}
143+

scripts/getBlock.ts

Lines changed: 0 additions & 20 deletions
This file was deleted.

scripts/get_block.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { PXE } from "@aztec/aztec.js";
2+
import { setupPXE } from "../src/utils/setup_pxe.js";
3+
4+
async function main() {
5+
6+
let pxe: PXE;
7+
pxe = await setupPXE();
8+
9+
let block = await pxe.getBlock(1);
10+
console.log(block)
11+
console.log(await block?.hash())
12+
}
13+
14+
main();

0 commit comments

Comments
 (0)