diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f7cab8933a8..580b46338be 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -161,6 +161,35 @@ jobs: export FORCE_COLOR=1 ../../scripts/earthly-ci -P --no-output +${{ matrix.test }} + # all the network end-to-end tests for aztec (not required to merge) + network-e2e: + needs: [build, changes] + if: ${{ needs.changes.outputs.non-barretenberg-cpp == 'true' }} + runs-on: ubuntu-20.04 + steps: + - uses: actions/checkout@v4 + with: { ref: "${{ env.GIT_COMMIT }}" } + - uses: ./.github/ci-setup-action + - name: Setup and Test + uses: ./.github/ensure-tester-with-images + timeout-minutes: 45 + with: + runner_type: ${{ contains(matrix.test, 'prover') && '64core-tester-x86' || '16core-tester-x86' }} + builder_type: builder-x86 + # these are copied to the tester and expected by the earthly command below + # if they fail to copy, it will try to build them on the tester and fail + builder_images_to_copy: aztecprotocol/aztec:${{ env.GIT_COMMIT }} aztecprotocol/end-to-end:${{ env.GIT_COMMIT }} + # command to produce the images in case they don't exist + builder_command: scripts/earthly-ci ./yarn-project+export-e2e-test-images + tester_ttl: 40 + run: | + set -eux + cd ./yarn-project/end-to-end/ + ./scripts/setup_local_k8s.sh + export FORCE_COLOR=1 + export EARTHLY_BUILD_ARGS="${{ env.EARTHLY_BUILD_ARGS }}" + ../../scripts/earthly-ci --exec-stats -P --no-output ./+network-transfer + # all the benchmarking end-to-end integration tests for aztec (not required to merge) bench-e2e: needs: [build, changes] diff --git a/helm-charts/aztec-network/templates/_helpers.tpl b/helm-charts/aztec-network/templates/_helpers.tpl index 44febac82a7..70cd5c25674 100644 --- a/helm-charts/aztec-network/templates/_helpers.tpl +++ b/helm-charts/aztec-network/templates/_helpers.tpl @@ -57,3 +57,9 @@ http://{{ include "aztec-network.fullname" . }}-ethereum.{{ .Release.Namespace } {{- define "aztec-network.pxeUrl" -}} http://{{ include "aztec-network.fullname" . }}-pxe.{{ .Release.Namespace }}:{{ .Values.pxe.service.port }} {{- end -}} + +{{- define "aztec-network.bootNodeUrl" -}} +http://{{ include "aztec-network.fullname" . }}-boot-node-0.{{ include "aztec-network.fullname" . }}-boot-node.{{ .Release.Namespace }}.svc.cluster.local:{{ .Values.bootNode.service.nodePort }} +{{- end -}} + + diff --git a/helm-charts/aztec-network/templates/boot-node.stateful-set.yaml b/helm-charts/aztec-network/templates/boot-node.stateful-set.yaml index d3132d3a9e9..e2aa461bd78 100644 --- a/helm-charts/aztec-network/templates/boot-node.stateful-set.yaml +++ b/helm-charts/aztec-network/templates/boot-node.stateful-set.yaml @@ -54,7 +54,7 @@ spec: [ "/bin/bash", "-c", - "source /shared/contracts.env && env && node --no-warnings /usr/src/yarn-project/aztec/dest/bin/index.js start --node --archiver --sequencer", + "source /shared/contracts.env && env && node --no-warnings /usr/src/yarn-project/aztec/dest/bin/index.js start --node --archiver --sequencer --pxe", ] volumeMounts: - name: shared-volume @@ -91,8 +91,8 @@ spec: - name: VALIDATOR_PRIVATE_KEY value: "0x47e179ec197488593b187f80a00eb0da91f1b9d0b13f8733639f19c30a34926a" ports: - - containerPort: "{{ .Values.bootNode.service.nodePort }}" - - containerPort: "{{ .Values.bootNode.service.p2pPort }}" + - containerPort: {{ .Values.bootNode.service.nodePort }} + - containerPort: {{ .Values.bootNode.service.p2pPort }} resources: {{- toYaml .Values.bootNode.resources | nindent 12 }} volumes: diff --git a/helm-charts/aztec-network/templates/configure-validator-env.config-map.yaml b/helm-charts/aztec-network/templates/configure-validator-env.config-map.yaml index 28904f5f5b4..47ddeba836c 100644 --- a/helm-charts/aztec-network/templates/configure-validator-env.config-map.yaml +++ b/helm-charts/aztec-network/templates/configure-validator-env.config-map.yaml @@ -10,7 +10,7 @@ data: set -e # Ask the bootnode for l1 contract addresses - output=$(node --no-warnings /usr/src/yarn-project/aztec/dest/bin/index.js get-node-info -u http://{{ include "aztec-network.fullname" . }}-boot-node-0.{{ include "aztec-network.fullname" . }}-boot-node.{{ .Release.Namespace }}.svc.cluster.local:{{ .Values.bootNode.service.nodePort }}) + output=$(node --no-warnings /usr/src/yarn-project/aztec/dest/bin/index.js get-node-info -u {{ include "aztec-network.bootNodeUrl" . }}) echo "$output" diff --git a/helm-charts/aztec-network/templates/deploy-l2-contracts.job.yaml b/helm-charts/aztec-network/templates/deploy-l2-contracts.job.yaml new file mode 100644 index 00000000000..56f2dd3b998 --- /dev/null +++ b/helm-charts/aztec-network/templates/deploy-l2-contracts.job.yaml @@ -0,0 +1,36 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ include "aztec-network.fullname" . }}-deploy-l2-contracts + labels: + {{- include "aztec-network.labels" . | nindent 4 }} +spec: + template: + metadata: + labels: + {{- include "aztec-network.selectorLabels" . | nindent 8 }} + app: deploy-l2-contracts + spec: + restartPolicy: OnFailure + containers: + - name: deploy-l2-contracts + image: {{ .Values.images.aztec.image }} + command: + - /bin/bash + - -c + - | + until curl -s -X POST -H 'content-type: application/json' \ + -d '{"jsonrpc":"2.0","method":"pxe_getNodeInfo","params":[],"id":67}' \ + {{ include "aztec-network.pxeUrl" . }} | grep -q '"enr:-'; do + echo "Waiting for PXE service..." + sleep 5 + done + echo "PXE service is ready!" + node --no-warnings /usr/src/yarn-project/aztec/dest/bin/index.js deploy-protocol-contracts + env: + - name: PXE_URL + value: {{ include "aztec-network.pxeUrl" . | quote }} + - name: DEBUG + value: "aztec:*" + - name: LOG_LEVEL + value: "debug" diff --git a/helm-charts/aztec-network/templates/prover-node.service.yaml b/helm-charts/aztec-network/templates/prover-node.service.yaml new file mode 100644 index 00000000000..1d20ba7cd3e --- /dev/null +++ b/helm-charts/aztec-network/templates/prover-node.service.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "aztec-network.fullname" . }}-prover-node + labels: + {{- include "aztec-network.labels" . | nindent 4 }} +spec: + clusterIP: None + selector: + {{- include "aztec-network.selectorLabels" . | nindent 4 }} + app: prover-node + ports: + - port: {{ .Values.proverNode.service.nodePort }} + name: node \ No newline at end of file diff --git a/helm-charts/aztec-network/templates/prover-node.stateful-set.yaml b/helm-charts/aztec-network/templates/prover-node.stateful-set.yaml new file mode 100644 index 00000000000..79a2da1f581 --- /dev/null +++ b/helm-charts/aztec-network/templates/prover-node.stateful-set.yaml @@ -0,0 +1,87 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: {{ include "aztec-network.fullname" . }}-prover-node + labels: + {{- include "aztec-network.labels" . | nindent 4 }} +spec: + serviceName: {{ include "aztec-network.fullname" . }}-prover-node + replicas: {{ .Values.proverNode.replicas }} + selector: + matchLabels: + {{- include "aztec-network.selectorLabels" . | nindent 6 }} + app: prover-node + template: + metadata: + labels: + {{- include "aztec-network.selectorLabels" . | nindent 8 }} + app: prover-node + spec: + initContainers: + - name: configure-validator-env + image: "{{ .Values.images.aztec.image }}" + imagePullPolicy: {{ .Values.images.aztec.pullPolicy }} + command: + - "/bin/sh" + - "-c" + - "cp /scripts/configure-validator-env.sh /tmp/configure-validator-env.sh && chmod +x /tmp/configure-validator-env.sh && /tmp/configure-validator-env.sh" + volumeMounts: + - name: shared-volume + mountPath: /shared + - name: scripts + mountPath: /scripts + env: + - name: ETHEREUM_HOST + value: {{ include "aztec-network.ethereumHost" . | quote }} + containers: + - name: aztec + image: "{{ .Values.images.aztec.image }}" + imagePullPolicy: {{ .Values.images.aztec.pullPolicy }} + command: + - "/bin/bash" + - "-c" + - "source /shared/contracts.env && env && node --no-warnings /usr/src/yarn-project/aztec/dest/bin/index.js start --prover-node --prover --archiver" + volumeMounts: + - name: shared-volume + mountPath: /shared + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: POD_DNS_NAME + value: "$(POD_NAME).{{ include "aztec-network.fullname" . }}-prover-node.$(POD_NAMESPACE).svc.cluster.local" + - name: PORT + value: "{{ .Values.proverNode.service.nodePort }}" + - name: LOG_LEVEL + value: "{{ .Values.proverNode.logLevel }}" + - name: DEBUG + value: "{{ .Values.proverNode.debug }}" + - name: ETHEREUM_HOST + value: {{ include "aztec-network.ethereumHost" . | quote }} + - name: PROVER_REAL_PROOFS + value: "{{ .Values.proverNode.realProofs }}" + - name: PROVER_AGENT_ENABLED + value: "{{ .Values.proverNode.proverAgentEnabled }}" + - name: PROVER_PUBLISHER_PRIVATE_KEY + value: "0xdbda1821b80551c9d65939329250298aa3472ba22feea921c0cf5d620ea67b97" + # get private proofs from the boot node + - name: TX_PROVIDER_NODE_URL + value: {{ include "aztec-network.bootNodeUrl" . | quote }} + # prover agent gets jobs from itself + - name: AZTEC_NODE_URL + value: "$(POD_DNS_NAME):{{ .Values.proverNode.service.nodePort }}" + ports: + - containerPort: {{ .Values.proverNode.service.nodePort }} + resources: + {{- toYaml .Values.proverNode.resources | nindent 12 }} + volumes: + - name: shared-volume + emptyDir: {} + - name: scripts + configMap: + name: {{ include "aztec-network.fullname" . }}-configure-validator-env \ No newline at end of file diff --git a/helm-charts/aztec-network/templates/pxe.deployment.yaml b/helm-charts/aztec-network/templates/pxe.deployment.yaml index 1dc77d49df2..fefe94987c4 100644 --- a/helm-charts/aztec-network/templates/pxe.deployment.yaml +++ b/helm-charts/aztec-network/templates/pxe.deployment.yaml @@ -26,9 +26,9 @@ spec: node --no-warnings /usr/src/yarn-project/aztec/dest/bin/index.js start --pxe env: - name: ETHEREUM_HOST - value: "http://{{ include "aztec-network.fullname" . }}-ethereum.{{ .Release.Namespace }}:{{ .Values.ethereum.service.port }}" + value: {{ include "aztec-network.ethereumHost" . | quote }} - name: AZTEC_NODE_URL - value: "http://{{ include "aztec-network.fullname" . }}-boot-node-0.{{ include "aztec-network.fullname" . }}-boot-node.{{ .Release.Namespace }}.svc.cluster.local:{{ .Values.bootNode.service.nodePort }}" + value: {{ include "aztec-network.bootNodeUrl" . | quote }} ports: - name: http containerPort: {{ .Values.pxe.service.port }} diff --git a/helm-charts/aztec-network/values.yaml b/helm-charts/aztec-network/values.yaml index 8bc6f9ef73e..55cd0406c26 100644 --- a/helm-charts/aztec-network/values.yaml +++ b/helm-charts/aztec-network/values.yaml @@ -18,7 +18,7 @@ bootNode: p2pPort: 40400 nodePort: 8080 logLevel: "debug" - debug: "discv5:*,aztec:*" + debug: "aztec:*" p2p: enabled: "true" resources: {} @@ -29,11 +29,21 @@ validator: p2pPort: 40400 nodePort: 8080 logLevel: "debug" - debug: "discv5:*,aztec:*" + debug: "aztec:*" p2p: enabled: "true" resources: {} +proverNode: + replicas: 1 + service: + nodePort: 8080 + logLevel: "debug" + debug: "aztec:*" + realProofs: false + proverAgentEnabled: true + resources: {} + pxe: replicas: 1 service: diff --git a/yarn-project/aztec.js/src/contract/deploy_sent_tx.ts b/yarn-project/aztec.js/src/contract/deploy_sent_tx.ts index b645d3dc6d2..e907c6abcb0 100644 --- a/yarn-project/aztec.js/src/contract/deploy_sent_tx.ts +++ b/yarn-project/aztec.js/src/contract/deploy_sent_tx.ts @@ -1,6 +1,5 @@ import { type PXE, type TxHash, type TxReceipt } from '@aztec/circuit-types'; import { type AztecAddress } from '@aztec/circuits.js'; -import { createDebugLogger } from '@aztec/foundation/log'; import { type FieldsOf } from '@aztec/foundation/types'; import { type ContractInstanceWithAddress } from '@aztec/types/contracts'; @@ -25,8 +24,6 @@ export type DeployTxReceipt = FieldsO * A contract deployment transaction sent to the network, extending SentTx with methods to create a contract instance. */ export class DeploySentTx extends SentTx { - private log = createDebugLogger('aztec:js:deploy_sent_tx'); - constructor( wallet: PXE | Wallet, txHashPromise: Promise, @@ -55,7 +52,9 @@ export class DeploySentTx extends SentTx */ public override async wait(opts?: DeployedWaitOpts): Promise> { const receipt = await super.wait(opts); + this.log.debug(`Returned from wait for ${await this.getTxHash()}: final status ${receipt.status}`); const contract = await this.getContractObject(opts?.wallet); + this.log.debug(`Contract instance created for ${this.instance.address.toString()}`); return { ...receipt, contract }; } diff --git a/yarn-project/aztec.js/src/contract/sent_tx.ts b/yarn-project/aztec.js/src/contract/sent_tx.ts index 91b0f5ea2c0..396bfc9be23 100644 --- a/yarn-project/aztec.js/src/contract/sent_tx.ts +++ b/yarn-project/aztec.js/src/contract/sent_tx.ts @@ -6,6 +6,7 @@ import { type TxReceipt, TxStatus, } from '@aztec/circuit-types'; +import { createDebugLogger } from '@aztec/foundation/log'; import { retryUntil } from '@aztec/foundation/retry'; import { type FieldsOf } from '@aztec/foundation/types'; @@ -43,6 +44,7 @@ export const DefaultWaitOpts: WaitOpts = { * its hash, receipt, and mining status. */ export class SentTx { + protected log = createDebugLogger('aztec:js:sent_tx'); constructor(protected pxe: PXE, protected txHashPromise: Promise) {} /** @@ -84,6 +86,7 @@ export class SentTx { ); } if (opts?.proven && receipt.blockNumber !== undefined) { + this.log.info(`Waiting for tx ${await this.getTxHash()} to be proven`); await this.waitForProven(receipt.blockNumber, opts); } if (opts?.debug) { @@ -128,6 +131,7 @@ export class SentTx { return await retryUntil( async () => { const txReceipt = await this.pxe.getTxReceipt(txHash); + this.log.debug(`Got receipt for tx ${txHash}: ${txReceipt.status}`); // If receipt is not yet available, try again if (txReceipt.status === TxStatus.PENDING) { return undefined; @@ -141,10 +145,15 @@ export class SentTx { if (!waitForNotesSync) { return txReceipt; } + this.log.debug(`Waiting for notes to sync for tx ${txHash}`); // Check if all sync blocks on the PXE Service are greater or equal than the block in which the tx was mined const { blocks, notes } = await this.pxe.getSyncStatus(); + + this.log.debug(`Got sync status for tx ${txHash}: ${blocks} ${JSON.stringify(notes)}`); const targetBlock = txReceipt.blockNumber!; + this.log.debug(`Target block for tx ${txHash}: ${targetBlock}`); const areNotesSynced = blocks >= targetBlock && Object.values(notes).every(block => block >= targetBlock); + this.log.debug(`Are notes synced for tx ${txHash}: ${areNotesSynced}`); return areNotesSynced ? txReceipt : undefined; }, 'isMined', diff --git a/yarn-project/aztec/src/cli/cmds/start_prover_node.ts b/yarn-project/aztec/src/cli/cmds/start_prover_node.ts index 21d8a54f3f9..d804a40ff79 100644 --- a/yarn-project/aztec/src/cli/cmds/start_prover_node.ts +++ b/yarn-project/aztec/src/cli/cmds/start_prover_node.ts @@ -38,7 +38,7 @@ export const startProverNode = async ( process.exit(1); } - if (options.prover) { + if (options.prover || options.proverAgentEnabled) { userLog(`Running prover node with local prover agent.`); proverConfig.proverAgentEnabled = true; } else { diff --git a/yarn-project/end-to-end/Earthfile b/yarn-project/end-to-end/Earthfile index 827c50c20bc..4a0f008dbb7 100644 --- a/yarn-project/end-to-end/Earthfile +++ b/yarn-project/end-to-end/Earthfile @@ -73,12 +73,14 @@ NETWORK_TEST: RUN kubectl delete namespace $namespace --ignore-not-found=true --wait=true --now --timeout=10m END - RUN helm install spartan ../../helm-charts/aztec-network \ --namespace $namespace --create-namespace \ --set images.test.image="aztecprotocol/end-to-end:$AZTEC_DOCKER_TAG" \ --set images.aztec.image="aztecprotocol/aztec:$AZTEC_DOCKER_TAG" \ - --set test="$test" + --set test="$test" \ + --wait \ + --wait-for-jobs=true \ + --timeout=10m RUN kubectl wait pod -l app==pxe --for=condition=Ready -n $namespace --timeout=10m @@ -296,4 +298,9 @@ e2e-cli-wallet: DO +E2E_COMPOSE_TEST --test=e2e_cli_wallet --compose_file=scripts/docker-compose-wallet.yml network-smoke: - DO +NETWORK_TEST --fresh_install=true --namespace=smoke --test=./src/spartan/smoke.test.ts + ARG force_build + DO +NETWORK_TEST --force_build=$force_build --fresh_install=true --namespace=smoke --test=./src/spartan/smoke.test.ts + +network-transfer: + ARG force_build + DO +NETWORK_TEST --force_build=$force_build --fresh_install=true --namespace=transfer --test=./src/spartan/transfer.test.ts diff --git a/yarn-project/end-to-end/scripts/create_k8s_dashboard.sh b/yarn-project/end-to-end/scripts/create_k8s_dashboard.sh new file mode 100644 index 00000000000..795ae65fc7a --- /dev/null +++ b/yarn-project/end-to-end/scripts/create_k8s_dashboard.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +# Install the Kubernetes Dashboard +helm repo add kubernetes-dashboard https://kubernetes.github.io/dashboard/ +helm upgrade --install kubernetes-dashboard kubernetes-dashboard/kubernetes-dashboard --create-namespace --namespace kubernetes-dashboard + + +# Create the ServiceAccount for the Kubernetes Dashboard +kubectl apply -f - < /dev/null; then + curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" + chmod +x kubectl + sudo mv kubectl /usr/local/bin/kubectl +fi -# Install kind -[ $(uname -m) = x86_64 ] && curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.23.0/kind-$(uname)-amd64 -chmod +x ./kind -sudo mv ./kind /usr/local/bin/kind +# Install kind if it is not installed +if ! command -v kind &> /dev/null; then + curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.23.0/kind-$(uname)-amd64 + chmod +x ./kind + sudo mv ./kind /usr/local/bin/kind +fi -# Install helm -curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash +# Install helm if it is not installed +if ! command -v helm &> /dev/null; then + curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 + chmod +x get_helm.sh + sudo ./get_helm.sh + rm get_helm.sh +fi kind create cluster - -# Install the Kubernetes Dashboard -helm repo add kubernetes-dashboard https://kubernetes.github.io/dashboard/ -helm upgrade --install kubernetes-dashboard kubernetes-dashboard/kubernetes-dashboard --create-namespace --namespace kubernetes-dashboard - - -# Create the ServiceAccount for the Kubernetes Dashboard -kubectl apply -f - < - async ({ pxe }: SubsystemsContext) => { + async ({ pxe }: { pxe: PXE }) => { // Generate account keys. const accountKeys: [Fr, GrumpkinScalar][] = Array.from({ length: numberOfAccounts }).map(_ => [ Fr.random(), diff --git a/yarn-project/end-to-end/src/spartan/smoke.test.ts b/yarn-project/end-to-end/src/spartan/smoke.test.ts index b003b82ff24..f1a58fa1731 100644 --- a/yarn-project/end-to-end/src/spartan/smoke.test.ts +++ b/yarn-project/end-to-end/src/spartan/smoke.test.ts @@ -5,7 +5,7 @@ const { PXE_URL } = process.env; if (!PXE_URL) { throw new Error('PXE_URL env variable must be set'); } -const debugLogger = createDebugLogger('aztec:spartan-test'); +const debugLogger = createDebugLogger('aztec:spartan-test:smoke'); // const userLog = createConsoleLogger(); describe('sample test', () => { diff --git a/yarn-project/end-to-end/src/spartan/transfer.test.ts b/yarn-project/end-to-end/src/spartan/transfer.test.ts new file mode 100644 index 00000000000..6e13df33ffd --- /dev/null +++ b/yarn-project/end-to-end/src/spartan/transfer.test.ts @@ -0,0 +1,142 @@ +import { getSchnorrAccount } from '@aztec/accounts/schnorr'; +import { + type AccountWallet, + type AccountWalletWithSecretKey, + type AztecAddress, + type CompleteAddress, + ExtendedNote, + Fr, + Note, + type PXE, + type TxHash, + computeSecretHash, + createCompatibleClient, +} from '@aztec/aztec.js'; +import { createDebugLogger } from '@aztec/foundation/log'; +import { TokenContract } from '@aztec/noir-contracts.js'; + +import { addAccounts, publicDeployAccounts } from '../fixtures/snapshot_manager.js'; + +const { PXE_URL } = process.env; +if (!PXE_URL) { + throw new Error('PXE_URL env variable must be set'); +} + +const toString = ({ value }: { value: bigint }) => { + const vals: number[] = Array.from(new Fr(value).toBuffer()); + + let str = ''; + for (let i = 0; i < vals.length; i++) { + if (vals[i] != 0) { + str += String.fromCharCode(Number(vals[i])); + } + } + return str; +}; + +const addPendingShieldNoteToPXE = async (args: { + amount: bigint; + secretHash: Fr; + txHash: TxHash; + accountAddress: AztecAddress; + assetAddress: AztecAddress; + wallet: AccountWallet; +}) => { + const { accountAddress, assetAddress, amount, secretHash, txHash, wallet } = args; + const note = new Note([new Fr(amount), secretHash]); + const extendedNote = new ExtendedNote( + note, + accountAddress, + assetAddress, + TokenContract.storage.pending_shields.slot, + TokenContract.notes.TransparentNote.id, + txHash, + ); + await wallet.addNote(extendedNote); +}; + +describe('token transfer test', () => { + const logger = createDebugLogger(`aztec:spartan-test:transfer`); + const TOKEN_NAME = 'USDC'; + const TOKEN_SYMBOL = 'USD'; + const TOKEN_DECIMALS = 18n; + const MINT_AMOUNT = 1000000n; + let pxe: PXE; + let wallets: AccountWalletWithSecretKey[]; + let completeAddresses: CompleteAddress[]; + let tokenAddress: AztecAddress; + let tokenAtWallet0: TokenContract; + beforeAll(async () => { + pxe = await createCompatibleClient(PXE_URL, logger); + const { accountKeys } = await addAccounts(3, logger)({ pxe }); + const accountManagers = accountKeys.map(ak => getSchnorrAccount(pxe, ak[0], ak[1], 1)); + wallets = await Promise.all(accountManagers.map(a => a.getWallet())); + completeAddresses = await pxe.getRegisteredAccounts(); + wallets.forEach((w, i) => logger.verbose(`Wallet ${i} address: ${w.getAddress()}`)); + await publicDeployAccounts(wallets[0], completeAddresses.slice(0, 2)); + + logger.verbose(`Deploying TokenContract...`); + const tokenContract = await TokenContract.deploy( + wallets[0], + completeAddresses[0], + TOKEN_NAME, + TOKEN_SYMBOL, + TOKEN_DECIMALS, + ) + .send() + .deployed(); + + tokenAddress = tokenContract.address; + tokenAtWallet0 = await TokenContract.at(tokenAddress, wallets[0]); + + logger.verbose(`Minting ${MINT_AMOUNT} publicly...`); + await tokenAtWallet0.methods.mint_public(completeAddresses[0].address, MINT_AMOUNT).send().wait(); + + logger.verbose(`Minting ${MINT_AMOUNT} privately...`); + const secret = Fr.random(); + const secretHash = computeSecretHash(secret); + const receipt = await tokenAtWallet0.methods.mint_private(MINT_AMOUNT, secretHash).send().wait(); + + await addPendingShieldNoteToPXE({ + amount: MINT_AMOUNT, + secretHash, + txHash: receipt.txHash, + accountAddress: completeAddresses[0].address, + assetAddress: tokenAddress, + wallet: wallets[0], + }); + const txClaim = tokenAtWallet0.methods.redeem_shield(completeAddresses[0].address, MINT_AMOUNT, secret).send(); + await txClaim.wait({ debug: true }); + logger.verbose(`Minting complete.`); + }); + + it('can get info', async () => { + const name = toString(await tokenAtWallet0.methods.private_get_name().simulate()); + expect(name).toBe(TOKEN_NAME); + }); + + it('can transfer 1 publicly', async () => { + const transferAmount = 1n; + const balance0 = await tokenAtWallet0.methods.balance_of_public(completeAddresses[0].address).simulate(); + expect(balance0).toBeGreaterThanOrEqual(transferAmount); + await tokenAtWallet0.methods + .transfer_public(completeAddresses[0].address, completeAddresses[1].address, transferAmount, 0) + .send() + .wait(); + const balance0After = await tokenAtWallet0.methods.balance_of_public(completeAddresses[0].address).simulate(); + const balance1After = await tokenAtWallet0.methods.balance_of_public(completeAddresses[1].address).simulate(); + expect(balance0After).toBe(balance0 - transferAmount); + expect(balance1After).toBe(transferAmount); + }); + + it('can transfer 1 privately', async () => { + const transferAmount = 1n; + const balance0 = await tokenAtWallet0.methods.balance_of_private(completeAddresses[0].address).simulate(); + expect(balance0).toBeGreaterThanOrEqual(transferAmount); + await tokenAtWallet0.methods.transfer(completeAddresses[1].address, transferAmount).send().wait(); + const balance0After = await tokenAtWallet0.methods.balance_of_private(completeAddresses[0].address).simulate(); + const balance1After = await tokenAtWallet0.methods.balance_of_private(completeAddresses[1].address).simulate(); + expect(balance0After).toBe(balance0 - transferAmount); + expect(balance1After).toBe(transferAmount); + }); +}); diff --git a/yarn-project/kubectl b/yarn-project/kubectl new file mode 100755 index 00000000000..7cfacd16768 Binary files /dev/null and b/yarn-project/kubectl differ diff --git a/yarn-project/pxe/src/pxe_service/pxe_service.ts b/yarn-project/pxe/src/pxe_service/pxe_service.ts index d35e27808d5..972ef5ce916 100644 --- a/yarn-project/pxe/src/pxe_service/pxe_service.ts +++ b/yarn-project/pxe/src/pxe_service/pxe_service.ts @@ -565,6 +565,7 @@ export class PXEService implements PXE { } this.log.info(`Sending transaction ${txHash}`); await this.node.sendTx(tx); + this.log.info(`Sent transaction ${txHash}`); return txHash; }