@@ -58,10 +58,11 @@ function usage {
5858 echo -e " ${BOLD} Usage:${RESET} ${YELLOW} fhevm-cli${RESET} ${CYAN} COMMAND [OPTIONS]${RESET} "
5959 echo
6060 echo -e " ${BOLD}${LIGHT_BLUE} Commands:${RESET} "
61- echo -e " ${YELLOW} deploy${RESET} ${CYAN} [--build] [--local]${RESET} WIP: Deploy the full fhevm stack (optionally rebuild images) "
61+ echo -e " ${YELLOW} deploy${RESET} ${CYAN} [--build] [--local] [--coprocessors N] [--coprocessor-threshold T] ${RESET} Deploy fhevm stack"
6262 echo -e " ${YELLOW} pause${RESET} ${CYAN} [CONTRACTS]${RESET} Pause specific contracts (host|gateway)"
6363 echo -e " ${YELLOW} unpause${RESET} ${CYAN} [CONTRACTS]${RESET} Unpause specific contracts (host|gateway)"
6464 echo -e " ${YELLOW} test${RESET} ${CYAN} [TYPE]${RESET} Run tests (input-proof|user-decryption|public-decryption|delegated-user-decryption|random|random-subset|operators|erc20|debug)"
65+ echo -e " ${YELLOW} smoke${RESET} ${CYAN} [PROFILE]${RESET} Run multicoproc smoke profile (multi-2-2|multi-3-5)"
6566 echo -e " ${YELLOW} upgrade${RESET} ${CYAN} [SERVICE]${RESET} Upgrade specific service (host|gateway|connector|coprocessor|relayer|test-suite)"
6667 echo -e " ${YELLOW} clean${RESET} Remove all containers and volumes"
6768 echo -e " ${YELLOW} logs${RESET} ${CYAN} [SERVICE]${RESET} View logs for a specific service"
@@ -78,6 +79,9 @@ function usage {
7879 echo -e " ${PURPLE} ./fhevm-cli deploy${RESET} "
7980 echo -e " ${PURPLE} ./fhevm-cli deploy --build${RESET} "
8081 echo -e " ${PURPLE} ./fhevm-cli deploy --local${RESET} "
82+ echo -e " ${PURPLE} ./fhevm-cli deploy --coprocessors 2 --coprocessor-threshold 2${RESET} "
83+ echo -e " ${PURPLE} ./fhevm-cli smoke multi-2-2${RESET} "
84+ echo -e " ${PURPLE} ./fhevm-cli smoke multi-3-5${RESET} "
8185 echo -e " ${PURPLE} ./fhevm-cli test input-proof${RESET} "
8286 echo -e " ${PURPLE} ./fhevm-cli test input-proof --no-hardhat-compile${RESET} "
8387 echo -e " ${PURPLE} ./fhevm-cli test user-decryption ${RESET} "
@@ -88,6 +92,77 @@ function usage {
8892 echo -e " ${BLUE} ============================================================${RESET} "
8993}
9094
95+ # Best-effort log dump across all coprocessor instances for quick local triage.
96+ function collect_coprocessor_topology_logs() {
97+ echo -e " ${LIGHT_BLUE}${BOLD} [LOGS] Collecting coprocessor topology logs (last 10m)...${RESET} "
98+ local containers
99+ containers=$( docker ps --format ' {{.Names}}' | rg ' ^coprocessor[0-9-]*-(host-listener|gw-listener|tfhe-worker|sns-worker|transaction-sender)$' || true)
100+ if [ -z " $containers " ]; then
101+ echo -e " ${YELLOW} [WARN]${RESET} No coprocessor containers found"
102+ return
103+ fi
104+
105+ while IFS= read -r container; do
106+ [ -z " $container " ] && continue
107+ echo -e " \n${CYAN} ===== ${container} =====${RESET} "
108+ docker logs --since=10m " $container " | tail -n 160 || true
109+ done <<< " $containers"
110+ }
111+
112+ function wait_for_coprocessor_key_bootstrap() {
113+ local timeout_seconds=300
114+ local poll_interval=5
115+ local elapsed=0
116+ echo -e " ${LIGHT_BLUE}${BOLD} [WAIT] Waiting for coprocessor key bootstrap...${RESET} "
117+ while [ " $elapsed " -lt " $timeout_seconds " ]; do
118+ local ready_count=0
119+ local total_count=0
120+ local pending=" "
121+ local containers
122+ containers=$( docker ps --format ' {{.Names}}' | rg ' ^coprocessor([0-9]+)?-sns-worker$' || true)
123+ if [ -z " $containers " ]; then
124+ echo -e " ${YELLOW} [WARN]${RESET} No sns-worker containers found yet"
125+ sleep " $poll_interval "
126+ elapsed=$(( elapsed + poll_interval))
127+ continue
128+ fi
129+
130+ while IFS= read -r container; do
131+ [ -z " $container " ] && continue
132+ total_count=$(( total_count + 1 ))
133+ if docker logs --since=20m " $container " 2>&1 | rg -q " Fetched keyset" ; then
134+ ready_count=$(( ready_count + 1 ))
135+ else
136+ pending=" ${pending} ${container} "
137+ fi
138+ done <<< " $containers"
139+
140+ local configured_threshold=" "
141+ if [ -f " test-suite/fhevm/env/staging/.env.host-sc.local" ]; then
142+ configured_threshold=$( rg ' ^COPROCESSOR_THRESHOLD=' test-suite/fhevm/env/staging/.env.host-sc.local -N | tail -n1 | cut -d' =' -f2 || true)
143+ fi
144+ if ! [[ " $configured_threshold " =~ ^[0-9]+$ ]] || [ " $configured_threshold " -lt 1 ]; then
145+ configured_threshold=" $total_count "
146+ fi
147+
148+ if [ " $configured_threshold " -gt " $total_count " ]; then
149+ configured_threshold=" $total_count "
150+ fi
151+
152+ if [ " $ready_count " -ge " $configured_threshold " ]; then
153+ echo -e " ${GREEN} [READY]${RESET} Key bootstrap confirmed for ${ready_count} /${total_count} sns-worker containers (threshold=${configured_threshold} )"
154+ return 0
155+ fi
156+
157+ echo -e " ${YELLOW} [WAIT]${RESET} Key bootstrap ready=${ready_count} /${total_count} threshold=${configured_threshold} pending:${pending} "
158+ sleep " $poll_interval "
159+ elapsed=$(( elapsed + poll_interval))
160+ done
161+
162+ echo -e " ${RED} [ERROR]${RESET} Key bootstrap did not reach threshold within ${timeout_seconds} s"
163+ return 1
164+ }
165+
91166COMMAND=$1
92167shift
93168
@@ -112,6 +187,26 @@ case $COMMAND in
112187 DEPLOY_ARGS+=(" --local" )
113188 shift
114189 ;;
190+ --coprocessors)
191+ if [ -n " $2 " ] && [ " ${2: 0: 1} " != " -" ]; then
192+ DEPLOY_ARGS+=(" --coprocessors" " $2 " )
193+ shift 2
194+ else
195+ echo -e " ${RED} [ERROR]${RESET} ${BOLD} Coprocessor count argument missing${RESET} "
196+ usage
197+ exit 1
198+ fi
199+ ;;
200+ --coprocessor-threshold)
201+ if [ -n " $2 " ] && [ " ${2: 0: 1} " != " -" ]; then
202+ DEPLOY_ARGS+=(" --coprocessor-threshold" " $2 " )
203+ shift 2
204+ else
205+ echo -e " ${RED} [ERROR]${RESET} ${BOLD} Coprocessor threshold argument missing${RESET} "
206+ usage
207+ exit 1
208+ fi
209+ ;;
115210 * )
116211 echo -e " ${RED} [ERROR]${RESET} ${BOLD} Unknown argument for deploy: $1 ${RESET} "
117212 usage
@@ -167,6 +262,7 @@ case $COMMAND in
167262 GREP=" "
168263 NO_RELAYER=" "
169264 NO_COMPILE=" "
265+ WAIT_FOR_KEY_BOOTSTRAP=" "
170266
171267 while (( "$# " )) ; do
172268 case " $1 " in
@@ -229,6 +325,7 @@ case $COMMAND in
229325 input-proof)
230326 log_message=" ${LIGHT_BLUE}${BOLD} [TEST] INPUT PROOF (uint64)${RESET} "
231327 docker_args+=(" -g" " test user input uint64" )
328+ WAIT_FOR_KEY_BOOTSTRAP=" 1"
232329 ;;
233330 input-proof-compute-decrypt)
234331 log_message=" ${LIGHT_BLUE}${BOLD} [TEST] INPUT PROOF (uint64)${RESET} "
@@ -291,10 +388,51 @@ case $COMMAND in
291388 fi
292389 if [ " $TEST_TYPE " != " debug" ]; then
293390 echo -e " ${log_message} "
294- docker exec fhevm-test-suite-e2e-debug " ${docker_args[@]} "
391+ if [ -n " $WAIT_FOR_KEY_BOOTSTRAP " ]; then
392+ wait_for_coprocessor_key_bootstrap
393+ fi
394+ test_status=0
395+ if docker exec fhevm-test-suite-e2e-debug " ${docker_args[@]} " ; then
396+ test_status=0
397+ else
398+ test_status=$?
399+ fi
400+ if [ -n " $WAIT_FOR_KEY_BOOTSTRAP " ]; then
401+ collect_coprocessor_topology_logs
402+ fi
403+ if [ " $test_status " -ne 0 ]; then
404+ exit " $test_status "
405+ fi
295406 fi
296407 ;;
297408
409+ smoke)
410+ print_logo
411+ PROFILE=$1
412+ if [[ ! $PROFILE =~ ^(multi-2-2| multi-3-5)$ ]]; then
413+ echo -e " ${RED} [ERROR]${RESET} ${BOLD} Unknown smoke profile: ${PROFILE}${RESET} "
414+ usage
415+ exit 1
416+ fi
417+
418+ coprocessors=" "
419+ threshold=" "
420+ case " $PROFILE " in
421+ multi-2-2)
422+ coprocessors=2
423+ threshold=2
424+ ;;
425+ multi-3-5)
426+ coprocessors=5
427+ threshold=3
428+ ;;
429+ esac
430+
431+ echo -e " ${LIGHT_BLUE}${BOLD} [SMOKE] Running profile ${PROFILE} (n=${coprocessors} , t=${threshold} )...${RESET} "
432+ " ${SCRIPT_DIR} /fhevm-cli" deploy --local --coprocessors " ${coprocessors} " --coprocessor-threshold " ${threshold} "
433+ " ${SCRIPT_DIR} /fhevm-cli" test input-proof
434+ ;;
435+
298436 help|-h|--help)
299437 usage
300438 exit 0
0 commit comments