Skip to content

Commit

Permalink
feat: native tmux-based network e2e (#9036)
Browse files Browse the repository at this point in the history
For debugging
<img width="1798" alt="Screenshot 2024-10-06 at 10 17 30 PM"
src="https://github.com/user-attachments/assets/05b1819f-c117-46f6-a7b7-407d978d122d">
  • Loading branch information
ludamad authored Oct 8, 2024
1 parent 07e4c95 commit f9fc73a
Show file tree
Hide file tree
Showing 26 changed files with 628 additions and 34 deletions.
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,7 @@ terraform.tfstate*
.bb_tmp

# Terraform
*.tfvars
*.tfvars

# tmux
tmux-client-*.log
46 changes: 46 additions & 0 deletions scripts/run_interleaved.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/bin/bash
set -eu

# Usage: run_bg_args.sh <main command> <background commands>...
# Runs the main command with output logging and background commands without logging.
# Finishes when the main command exits.

# Check if at least two commands are provided (otherwise what is the point)
if [ "$#" -lt 2 ]; then
echo "Usage: $0 <main-command> <background commands>..."
exit 1
fi

main_cmd="$1"
shift

# Function to run a command and prefix the output
function run_command() {
local cmd="$1"
while IFS= read -r line; do
echo "[$cmd] $line"
done < <($cmd 2>&1)
}

# Run the main command, piping output through the run_command function
run_command "$main_cmd" &
main_pid=$!

# Run background commands without logging output
declare -a bg_pids
for cmd in "$@"; do
run_command "$cmd" &
bg_pids+=($!)
done

# Wait for the main command to finish and capture its exit code
wait $main_pid
main_exit_code=$?

# Kill any remaining background jobs
for pid in "${bg_pids[@]}"; do
kill "$pid" 2>/dev/null || true
done

# Exit with the same code as the main command
exit $main_exit_code
50 changes: 50 additions & 0 deletions scripts/tmux_split_args.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#!/usr/bin/env bash
set -eu
# Usage: tmux_splits_args.sh <session-name> <main command> <background commands>...
# Runs commands in parallel in a tmux window.
# *Finishes when the main command exits.*

# Check if at least two commands are provided (otherwise what is the point)
if [ "$#" -lt 2 ]; then
echo "Usage: $0 <main-command> <background commands>..."
exit 1
fi

# Launches tmux with 1 window that has as many panes as commands
session_name=$1

# Kill any existing tmux session with the same name
tmux kill-session -t "$session_name" 2>/dev/null || true

# Start a new tmux session
tmux new-session -d -s "$session_name"

shift 1
commands=("$@")

# Set pane-border-status to top and pane-border-format to display pane title
tmux set-option -t "$session_name" pane-border-status top
tmux set-option -t "$session_name" pane-border-format "#{pane_title}"

# Create the necessary number of panes and set titles
num_commands=${#commands[@]}
for ((i=0; i<num_commands; i++)); do
if [[ $i -gt 0 ]]; then
# Split the first pane each time
tmux split-window -t "$session_name:0.0" -h
tmux select-layout -t "$session_name:0" tiled
fi
# Set the pane title
tmux select-pane -t "$session_name:0.$i" -T "${commands[i]}"
done

# Ensure this finishes when pane 0 is finished
tmux set-hook -t "$session_name" pane-exited "if-shell -F '#{==:#{pane_index},0}' 'kill-session -t \"$session_name\"'"

# Now send commands to each pane
for ((i=0; i<num_commands; i++)); do
tmux send-keys -t "$session_name:0.$i" "${commands[$i]}" C-m
done

# Attach to the session
tmux attach-session -t "$session_name"
53 changes: 53 additions & 0 deletions spartan/scripts/k8s_log_interleave.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#!/usr/bin/env python3
import subprocess
import json
import heapq

# Get the list of pods
pods = subprocess.check_output(
['kubectl', 'get', 'pods', '-n', 'transfer', '-o', 'custom-columns=:metadata.name', '--no-headers'],
universal_newlines=True
).splitlines()

# Create a min-heap for sorting logs based on timestamp
heap = []

for pod in pods:
# Get logs for each pod
logs = subprocess.check_output(['kubectl', 'logs', '-n', 'transfer', pod], universal_newlines=True).splitlines()
for line in logs:
# Prefix with pod name
prefixed_line = f'[{pod}] {line}'
try:
# Remove the pod prefix
if line.startswith('['):
closing_bracket_index = line.find(']')
if closing_bracket_index != -1:
# Assume there's a space after the closing bracket
json_part = line[closing_bracket_index + 2:]
else:
json_part = line # No closing bracket found
else:
json_part = line

# Parse the JSON part
log_json = json.loads(json_part)

# Ensure log_json is a dictionary
if isinstance(log_json, dict):
timestamp = log_json.get('timestamp')
if timestamp:
# Use timestamp as the key for sorting
heapq.heappush(heap, (timestamp, prefixed_line))
else:
# log_json is not a dictionary; skip this line
continue
except (json.JSONDecodeError, ValueError, AttributeError) as e:
# Optionally print the error and the problematic line for debugging
# print(f"Error parsing line: {line}\nError: {e}")
continue # Skip lines that are not valid JSON dictionaries

# Extract and print logs in order
while heap:
_, log_line = heapq.heappop(heap)
print(log_line)
2 changes: 1 addition & 1 deletion yarn-project/aztec.js/src/contract/deploy_proven_tx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export class DeployProvenTx<TContract extends Contract = Contract> extends Prove
*/
public override send(): DeploySentTx<TContract> {
const promise = (() => {
return this.wallet.sendTx(this);
return this.wallet.sendTx(this.getPlainDataTx());
})();

return new DeploySentTx(this.wallet, promise, this.postDeployCtor, this.instance);
Expand Down
26 changes: 14 additions & 12 deletions yarn-project/aztec.js/src/contract/proven_tx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,25 @@ export class ProvenTx extends Tx {
);
}

// Clone the TX data to get a serializable object.
protected getPlainDataTx(): Tx {
return new Tx(
this.data,
this.clientIvcProof,
this.noteEncryptedLogs,
this.encryptedLogs,
this.unencryptedLogs,
this.enqueuedPublicFunctionCalls,
this.publicTeardownFunctionCall,
);
}

/**
* Sends the transaction to the network via the provided wallet.
*/
public send(): SentTx {
const promise = (() => {
// Clone the TX data to avoid serializing the ProvenTx object.
return this.wallet.sendTx(
new Tx(
this.data,
this.clientIvcProof,
this.noteEncryptedLogs,
this.encryptedLogs,
this.unencryptedLogs,
this.enqueuedPublicFunctionCalls,
this.publicTeardownFunctionCall,
),
);
return this.wallet.sendTx(this.getPlainDataTx());
})();

return new SentTx(this.wallet, promise);
Expand Down
9 changes: 6 additions & 3 deletions yarn-project/aztec.js/src/rpc_clients/node/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,13 @@ async function axiosFetch(host: string, rpcMethod: string, body: any, useApiEndp
const isOK = resp.status >= 200 && resp.status < 300;
if (isOK) {
return resp.data;
} else if (resp.status >= 400 && resp.status < 500) {
throw new NoRetryError('(JSON-RPC PROPAGATED) ' + resp.data.error.message);
} else {
throw new Error('(JSON-RPC PROPAGATED) ' + resp.data.error.message);
const errorMessage = `(JSON-RPC PROPAGATED) (host ${host}) (method ${rpcMethod}) (code ${resp.status}) ${resp.data.error.message}`;
if (resp.status >= 400 && resp.status < 500) {
throw new NoRetryError(errorMessage);
} else {
throw new Error(errorMessage);
}
}
}

Expand Down
2 changes: 2 additions & 0 deletions yarn-project/aztec/src/sandbox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,8 @@ export async function createSandbox(config: Partial<SandboxConfig> = {}) {
await deployCanonicalL2FeeJuice(
new SignerlessWallet(pxe, new DefaultMultiCallEntrypoint(aztecNodeConfig.l1ChainId, aztecNodeConfig.version)),
aztecNodeConfig.l1Contracts.feeJuicePortalAddress,
undefined,
logger.info,
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,33 @@ import { type LogFn } from '@aztec/foundation/log';

import { deployCanonicalAuthRegistry, deployCanonicalL2FeeJuice } from '../misc/deploy_contracts.js';

const waitOpts: WaitOpts = {
timeout: 180,
interval: 1,
proven: true,
provenTimeout: 600,
};

export async function deployProtocolContracts(rpcUrl: string, l1ChainId: number, json: boolean, log: LogFn) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore - Importing noir-contracts.js even in devDeps results in a circular dependency error. Need to ignore because this line doesn't cause an error in a dev environment
// const { TokenContract } = await import('@aztec/noir-contracts.js');
export async function deployProtocolContracts(
rpcUrl: string,
l1ChainId: number,
json: boolean,
skipProofWait: boolean,
log: LogFn,
) {
const waitOpts: WaitOpts = {
timeout: 180,
interval: 1,
proven: !skipProofWait,
provenTimeout: 600,
};
log('deployProtocolContracts: Wait options for deployments' + JSON.stringify(waitOpts));
log('deployProtocolContracts: Creating PXE client...');
const pxe = createPXEClient(rpcUrl, makeFetch([], true));
const deployer = new SignerlessWallet(pxe, new DefaultMultiCallEntrypoint(l1ChainId, 1));

log('deployProtocolContracts: Deploying canonical auth registry...');
// Deploy Auth Registry
const authRegistryAddress = await deployCanonicalAuthRegistry(deployer, waitOpts);

log('deployProtocolContracts: Getting fee juice portal address...');
// Deploy Fee Juice
const feeJuicePortalAddress = (await deployer.getNodeInfo()).l1ContractAddresses.feeJuicePortalAddress;
const feeJuiceAddress = await deployCanonicalL2FeeJuice(deployer, feeJuicePortalAddress, waitOpts);
log('deployProtocolContracts: Deploying fee juice portal...');
const feeJuiceAddress = await deployCanonicalL2FeeJuice(deployer, feeJuicePortalAddress, waitOpts, log);

if (json) {
log(
Expand Down
3 changes: 2 additions & 1 deletion yarn-project/cli/src/cmds/infrastructure/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ export function injectCommands(program: Command, log: LogFn, debugLogger: DebugL
.addOption(pxeOption)
.addOption(l1ChainIdOption)
.option('--json', 'Output the contract addresses in JSON format')
.option('--skipProofWait', "Don't wait for proofs to land.")
.action(async options => {
const { deployProtocolContracts } = await import('./deploy_protocol_contract.js');
await deployProtocolContracts(options.rpcUrl, options.l1ChainId, options.json, log);
await deployProtocolContracts(options.rpcUrl, options.l1ChainId, options.json, options.skipProofWait, log);
});

program
Expand Down
4 changes: 4 additions & 0 deletions yarn-project/cli/src/cmds/misc/deploy_contracts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS,
} from '@aztec/circuits.js';
import { bufferAsFields } from '@aztec/foundation/abi';
import { type LogFn } from '@aztec/foundation/log';
import { getCanonicalAuthRegistry } from '@aztec/protocol-contracts/auth-registry';
import { getCanonicalFeeJuice } from '@aztec/protocol-contracts/fee-juice';

Expand All @@ -16,6 +17,7 @@ export async function deployCanonicalL2FeeJuice(
deployer: Wallet,
feeJuicePortalAddress: EthAddress,
waitOpts = DefaultWaitOpts,
log: LogFn,
): Promise<AztecAddress> {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore - Importing noir-contracts.js even in devDeps results in a circular dependency error. Need to ignore because this line doesn't cause an error in a dev environment
Expand All @@ -29,8 +31,10 @@ export async function deployCanonicalL2FeeJuice(

const publicBytecode = canonicalFeeJuice.contractClass.packedBytecode;
const encodedBytecode = bufferAsFields(publicBytecode, MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS);
log('deployCanonicalL2FeeJuice: Adding capsule...');
await deployer.addCapsule(encodedBytecode);
const feeJuiceContract = await FeeJuiceContract.at(canonicalFeeJuice.address, deployer);
log('deployCanonicalL2FeeJuice: Calling deploy on fee juice contract...');
await feeJuiceContract.methods
.deploy(
canonicalFeeJuice.contractClass.artifactHash,
Expand Down
3 changes: 3 additions & 0 deletions yarn-project/end-to-end/scripts/native-network/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
l1-contracts.env
l2-contracts.env
*.log
41 changes: 41 additions & 0 deletions yarn-project/end-to-end/scripts/native-network/boot-node.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#!/bin/bash
set -eu

# Get the name of the script without the path and extension
SCRIPT_NAME=$(basename "$0" .sh)

# Redirect stdout and stderr to <script_name>.log while also printing to the console
exec > >(tee -a "$(dirname $0)/logs/${SCRIPT_NAME}.log") 2> >(tee -a "$(dirname $0)/logs/${SCRIPT_NAME}.log" >&2)

# Starts the Boot Node

# Set environment variables
export PORT="8080"
export LOG_LEVEL="debug"
export DEBUG="aztec:*,-aztec:avm_simulator:*"
export ETHEREUM_HOST="http://127.0.0.1:8545"
export P2P_ENABLED="true"
export VALIDATOR_DISABLED="true"
export SEQ_MAX_SECONDS_BETWEEN_BLOCKS="0"
export SEQ_MIN_TX_PER_BLOCK="1"
export P2P_TCP_ANNOUNCE_ADDR="127.0.0.1:40400"
export P2P_UDP_ANNOUNCE_ADDR="127.0.0.1:40400"
export P2P_TCP_LISTEN_ADDR="0.0.0.0:40400"
export P2P_UDP_LISTEN_ADDR="0.0.0.0:40400"
export VALIDATOR_PRIVATE_KEY="0x47e179ec197488593b187f80a00eb0da91f1b9d0b13f8733639f19c30a34926a"
REPO=$(git rev-parse --show-toplevel)

echo "Waiting for l1 contracts to be deployed..."
until [ -f "$REPO"/yarn-project/end-to-end/scripts/native-network/l1-contracts.env ] ; do
sleep 1
done
echo "Done waiting."

source "$REPO"/yarn-project/end-to-end/scripts/native-network/l1-contracts.env

function filter_noise() {
grep -Ev "node_getProvenBlockNumber|getBlocks|Last block mined|Running random nodes query|Not creating block because not enough txs in the pool|Peers to connect"
}

# Start the Aztec node with the sequencer and archiver
node --no-warnings "$REPO"/yarn-project/aztec/dest/bin/index.js start --node --archiver --sequencer --pxe 2>&1 | filter_noise
Loading

0 comments on commit f9fc73a

Please sign in to comment.