Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions spartan/bootstrap.sh
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ function test_cmds {
echo "$hash timeout -v 30m ./spartan/bootstrap.sh test-kind-4epochs"
echo "$hash timeout -v 30m ./spartan/bootstrap.sh test-kind-upgrade-rollup-version"
echo "$hash timeout -v 30m ./spartan/bootstrap.sh test-prod-deployment"
echo "$hash timeout -v 30m ./spartan/bootstrap.sh test-cli-upgrade-with-lock"
fi
}

Expand Down Expand Up @@ -137,6 +138,11 @@ case "$cmd" in
"test-prod-deployment")
FRESH_INSTALL=false INSTALL_METRICS=false ./scripts/test_prod_deployment.sh
;;
"test-cli-upgrade-with-lock")
OVERRIDES="telemetry.enabled=false" \
FRESH_INSTALL=${FRESH_INSTALL:-true} INSTALL_METRICS=false \
./scripts/test_kind.sh src/spartan/upgrade_via_cli.test.ts 1-validators.yaml upgrade-via-cli${NAME_POSTFIX:-}
;;
"test-local")
# Isolate network stack in docker.
docker_isolate ../scripts/run_native_testnet.sh -i -val 3
Expand Down
19 changes: 9 additions & 10 deletions spartan/scripts/upgrade_rollup_with_lock.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ set -exu
# ETHEREUM_HOST=http://localhost:8545 \
# MNEMONIC="test test test test test test test test test test test junk" \
# ./upgrade_rollup_with_lock.sh \
# --aztec-docker-tag c5e2b43044862882a68de47cac07b7116e74e51e \
# --aztec-docker-image aztecprotocol/aztec:c5e2b43044862882a68de47cac07b7116e74e51e \
# --registry 0x29f815e32efdef19883cf2b92a766b7aebadd326 \
# --address 0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266 \
# --deposit-amount 200000000000000000000000 \
Expand Down Expand Up @@ -47,13 +47,13 @@ MINT=""
SALT=$((RANDOM % 1000000))
# The default path to the aztec binary within the docker image
AZTEC_BIN="/usr/src/yarn-project/aztec/dest/bin/index.js"
AZTEC_DOCKER_TAG=""
AZTEC_DOCKER_IMAGE=""

# Parse command line arguments (these will override env vars if provided)
while [[ $# -gt 0 ]]; do
case $1 in
--aztec-docker-tag)
AZTEC_DOCKER_TAG="$2"
--aztec-docker-image)
AZTEC_DOCKER_IMAGE="$2"
shift 2
;;
--aztec-bin)
Expand Down Expand Up @@ -105,13 +105,12 @@ cleanup() {
}

# if aztec-docker-tag is set, use it
if [ -n "$AZTEC_DOCKER_TAG" ]; then
IMAGE_NAME="aztecprotocol/aztec:${AZTEC_DOCKER_TAG}"
EXE="docker run --rm --network=host --env-file .env.tmp $IMAGE_NAME $AZTEC_BIN"
if [ -n "$AZTEC_DOCKER_IMAGE" ]; then
EXE="docker run --rm --network=host --env-file .env.tmp $AZTEC_DOCKER_IMAGE $AZTEC_BIN"
# Check if the image exists locally before pulling it
if ! docker images $IMAGE_NAME -q; then
echo "Pulling docker image $IMAGE_NAME"
docker pull $IMAGE_NAME
if ! docker images $AZTEC_DOCKER_IMAGE -q; then
echo "Pulling docker image $AZTEC_DOCKER_IMAGE"
docker pull $AZTEC_DOCKER_IMAGE
fi
trap cleanup EXIT INT TERM HUP QUIT
# Create a temporary .env file
Expand Down
2 changes: 1 addition & 1 deletion yarn-project/cli/src/cmds/l1/governance_utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ export async function proposeWithLock({
withdrawAddress: clients.walletClient.account.address,
});
if (json) {
log(JSON.stringify({ proposalId }, null, 2));
log(JSON.stringify({ proposalId: Number(proposalId) }, null, 2));
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Great example of why CLI tests are good haha. Had a "don't know how to serialize bigint" here.

Copy link
Member

Choose a reason for hiding this comment

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

you can also use the jsonStringify function in foundation

} else {
log(`Proposed with lock`);
log(`Proposal ID: ${proposalId}`);
Expand Down
105 changes: 105 additions & 0 deletions yarn-project/end-to-end/src/spartan/upgrade_via_cli.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import { type PXE, createCompatibleClient } from '@aztec/aztec.js';
import { GovernanceContract, RegistryContract, createEthereumChain, createL1Clients } from '@aztec/ethereum';
import { createLogger } from '@aztec/foundation/log';

import type { ChildProcess } from 'child_process';

import { getAztecBin, isK8sConfig, runProjectScript, setupEnvironment, startPortForward } from './utils.js';

const config = setupEnvironment(process.env);

// technically it doesn't require a k8s env, but it doesn't seem we're keeping the "local" versions of the spartan scripts up to date
// and I didn't want to plumb through the config and test this with the local scripts.
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we need the local scripts or would it make sense if anyway stale to kill em?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Good question. @ludamad ?

Copy link
Collaborator

Choose a reason for hiding this comment

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

That's a team call, I asked recently and Sean gave feedback about using them, but I certainly don't right now. I'm a bit surprised that people don't find the interactive usage useful, but again your guy's call

if (!isK8sConfig(config)) {
throw new Error('This test must be run in a k8s environment');
}

const debugLogger = createLogger('e2e:spartan-test:upgrade_via_cli');

describe('upgrade via cli', () => {
let pxe: PXE;
const forwardProcesses: ChildProcess[] = [];
let ETHEREUM_HOSTS: string;
let MNEMONIC: string;
beforeAll(async () => {
let PXE_URL: string;
MNEMONIC = config.L1_ACCOUNT_MNEMONIC;
{
const { process, port } = await startPortForward({
resource: `svc/${config.INSTANCE_NAME}-aztec-network-pxe`,
namespace: config.NAMESPACE,
containerPort: config.CONTAINER_PXE_PORT,
});
forwardProcesses.push(process);
PXE_URL = `http://127.0.0.1:${port}`;
}
{
const { process, port } = await startPortForward({
resource: `svc/${config.INSTANCE_NAME}-aztec-network-eth-execution`,
namespace: config.NAMESPACE,
containerPort: config.CONTAINER_ETHEREUM_PORT,
});
forwardProcesses.push(process);
ETHEREUM_HOSTS = `http://127.0.0.1:${port}`;
}
pxe = await createCompatibleClient(PXE_URL, debugLogger);
Copy link
Contributor

Choose a reason for hiding this comment

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

Unrelated to this pr, but the createCompatibleClient always makes me chuggle because it indicates there is a createIncompatibleClient

});

afterAll(() => {
forwardProcesses.forEach(p => p.kill());
});

it(
'should be able to get node enr',
async () => {
const info = await pxe.getNodeInfo();

const chain = createEthereumChain([ETHEREUM_HOSTS], info.l1ChainId);
const { walletClient: l1WalletClient, publicClient: l1PublicClient } = createL1Clients(
[ETHEREUM_HOSTS],
MNEMONIC,
chain.chainInfo,
);

const governance = new GovernanceContract(
info.l1ContractAddresses.governanceAddress.toString(),
l1PublicClient,
l1WalletClient,
);
const { minimumVotes, proposeConfig } = await governance.getConfiguration();

const depositAmount = proposeConfig.lockAmount + minimumVotes;

const registry = new RegistryContract(l1PublicClient, info.l1ContractAddresses.registryAddress.toString());
const oldNumberOfVersions = await registry.getNumberOfVersions();

const exitCode = await runProjectScript(
'spartan/scripts/upgrade_rollup_with_lock.sh',
[
'--aztec-bin',
getAztecBin(),
'--registry',
info.l1ContractAddresses.registryAddress.toString(),
'--address',
l1WalletClient.account.address,
'--deposit-amount',
depositAmount.toString(),
'--mint',
],
debugLogger,
{
MNEMONIC,
ETHEREUM_HOSTS,
L1_CHAIN_ID: info.l1ChainId.toString(),
LOG_JSON: 'false',
LOG_LEVEL: 'debug',
},
);
expect(exitCode).toBe(0);

const newNumberOfVersions = await registry.getNumberOfVersions();
expect(newNumberOfVersions).toBe(oldNumberOfVersions + 1);
},
6 * config.AZTEC_PROOF_SUBMISSION_WINDOW * config.AZTEC_SLOT_DURATION * 1000,
);
});
60 changes: 59 additions & 1 deletion yarn-project/end-to-end/src/spartan/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,49 @@ export function setupEnvironment(env: unknown): EnvConfig {
return config;
}

/**
* @param path - The path to the script, relative to the project root
* @param args - The arguments to pass to the script
* @param logger - The logger to use
* @returns The exit code of the script
*/
function runScript(path: string, args: string[], logger: Logger, env?: Record<string, string>) {
const childProcess = spawn(path, args, {
stdio: ['ignore', 'pipe', 'pipe'],
env: env ? { ...process.env, ...env } : process.env,
});
return new Promise<number>((resolve, reject) => {
childProcess.on('close', (code: number | null) => resolve(code ?? 0));
childProcess.on('error', reject);
childProcess.stdout?.on('data', (data: Buffer) => {
logger.info(data.toString());
});
childProcess.stderr?.on('data', (data: Buffer) => {
logger.error(data.toString());
});
});
}

export function getAztecBin() {
return path.join(getGitProjectRoot(), 'yarn-project/aztec/dest/bin/index.js');
}

/**
* Runs the Aztec binary
* @param args - The arguments to pass to the Aztec binary
* @param logger - The logger to use
* @param env - Optional environment variables to set for the process
* @returns The exit code of the Aztec binary
*/
export function runAztecBin(args: string[], logger: Logger, env?: Record<string, string>) {
return runScript('node', [getAztecBin(), ...args], logger, env);
}

export function runProjectScript(script: string, args: string[], logger: Logger, env?: Record<string, string>) {
const scriptPath = script.startsWith('/') ? script : path.join(getGitProjectRoot(), script);
return runScript(scriptPath, args, logger, env);
}

export async function startPortForward({
resource,
namespace,
Expand Down Expand Up @@ -128,7 +171,6 @@ export async function startPortForward({
}
const portNumber = parseInt(str.slice(port + 1));
logger.info(`Port forward connected: ${portNumber}`);
logger.info(`Port forward connected: ${portNumber}`);
resolve(portNumber);
} else {
logger.silent(str);
Expand Down Expand Up @@ -580,3 +622,19 @@ export async function rollAztecPods(namespace: string) {
await waitForResourceByLabel({ resource: 'pods', namespace: namespace, label: 'app=validator' });
await waitForResourceByLabel({ resource: 'pods', namespace: namespace, label: 'app=pxe' });
}

/**
* Returns the absolute path to the git repository root
*/
export function getGitProjectRoot(): string {
try {
const rootDir = execSync('git rev-parse --show-toplevel', {
encoding: 'utf-8',
stdio: ['ignore', 'pipe', 'ignore'],
}).trim();

return rootDir;
} catch (error) {
throw new Error(`Failed to determine git project root: ${error}`);
}
}
5 changes: 5 additions & 0 deletions yarn-project/ethereum/src/contracts/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,4 +103,9 @@ export class RegistryContract {
coinIssuerAddress: EthAddress.fromString(coinIssuer),
};
}

public async getNumberOfVersions(): Promise<number> {
const version = await this.registry.read.numberOfVersions();
return Number(version);
}
}