Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: native tmux-based network e2e #9036

Merged
merged 36 commits into from
Oct 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
96882cd
start of helm-based native tests
ludamad Oct 5, 2024
21b3925
start of helm-based native tests
ludamad Oct 5, 2024
5ca483e
checkin
ludamad Oct 5, 2024
50f03e0
update
ludamad Oct 5, 2024
aef20d0
commit all files
ludamad Oct 6, 2024
2084456
revert
ludamad Oct 6, 2024
2eaa3b0
ci vs not scripts
ludamad Oct 6, 2024
2fa5e68
better tests
ludamad Oct 6, 2024
4ac2fb2
rename
ludamad Oct 6, 2024
4d601f8
rename
ludamad Oct 6, 2024
3f778ed
go after improper usage
ludamad Oct 6, 2024
64f7ac9
iteration
ludamad Oct 6, 2024
d1da81d
improve script logging
ludamad Oct 6, 2024
15fd463
boot node no deploy redundantly
ludamad Oct 6, 2024
befc67c
iteration on tmux splits
ludamad Oct 6, 2024
ebea082
fixes
ludamad Oct 7, 2024
f9eb2bb
better errors
ludamad Oct 7, 2024
945594f
improve logging
ludamad Oct 7, 2024
8a9f242
Merge branch 'master' into ad/native-tmux-e2e
ludamad Oct 7, 2024
f87078f
try to stabilize network with 0 validators
ludamad Oct 7, 2024
2346ded
Iterative
ludamad Oct 7, 2024
df723cc
proverless fix
ludamad Oct 7, 2024
c1490f9
add waitForProven flag
ludamad Oct 7, 2024
e9a29f3
skip proof wait fix
ludamad Oct 7, 2024
d6a40fe
fix serialization issue with DeployProvenTx
ludamad Oct 7, 2024
09a6168
Merge remote-tracking branch 'origin/ad/native-tmux-e2e' into ad/nati…
ludamad Oct 7, 2024
e386ff2
Update action.yml
ludamad Oct 7, 2024
149c5f9
fix tx bot
ludamad Oct 7, 2024
0ed4ba5
revert
ludamad Oct 7, 2024
9d4b673
Merge remote-tracking branch 'origin/ad/native-tmux-e2e' into ad/nati…
ludamad Oct 7, 2024
65839a7
fix status
ludamad Oct 7, 2024
b52f8a9
Merge branch 'master' into ad/native-tmux-e2e
ludamad Oct 7, 2024
e568c10
Merge branch 'master' into ad/native-tmux-e2e
ludamad Oct 7, 2024
aedb22e
Merge branch 'master' into ad/native-tmux-e2e
ludamad Oct 8, 2024
fc8179d
formatting
ludamad Oct 8, 2024
d75ea98
Merge remote-tracking branch 'origin/ad/native-tmux-e2e' into ad/nati…
ludamad Oct 8, 2024
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
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

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

bundled because useful

# 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());
Copy link
Member

Choose a reason for hiding this comment

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

just checking that this was meant to be in this PR?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes, this is needed to fix serialization. Signed off by grego

})();

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
Loading