-
Notifications
You must be signed in to change notification settings - Fork 206
/
start
791 lines (676 loc) · 24.7 KB
/
start
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
#! /usr/bin/env bash
set -e
clear=$(echo -e "\e[0m")
green=$(echo -e "\e[32m")
blue=$(echo -e "\e[34m")
purple=$(echo -e "\e[35m")
cyan=$(echo -e "\e[36m")
export STELLAR_HOME="/opt/stellar"
export PGHOME="$STELLAR_HOME/postgresql"
export SUPHOME="$STELLAR_HOME/supervisor"
export COREHOME="$STELLAR_HOME/core"
export HZHOME="$STELLAR_HOME/horizon"
export FBHOME="$STELLAR_HOME/friendbot"
export NXHOME="$STELLAR_HOME/nginx"
export SOROBAN_RPC_HOME="$STELLAR_HOME/soroban-rpc"
export PGBIN="/usr/lib/postgresql/14/bin/"
export PGDATA="$PGHOME/data"
export PGUSER="stellar"
export PGPORT=5432
: "${PROTOCOL_VERSION:=$PROTOCOL_VERSION_DEFAULT}"
: "${ENABLE:=core,horizon,rpc}"
: "${ENABLE_LOGS:=false}"
: "${ENABLE_CORE:=false}"
: "${ENABLE_HORIZON:=false}"
: "${ENABLE_SOROBAN_RPC:=false}"
: "${ENABLE_SOROBAN_DIAGNOSTIC_EVENTS:=false}"
: "${DISABLE_SOROBAN_DIAGNOSTIC_EVENTS:=false}"
: "${ENABLE_SOROBAN_RPC_ADMIN_ENDPOINT:=false}"
: "${ENABLE_CORE_MANUAL_CLOSE:=false}"
: "${LIMITS:=testnet}"
QUICKSTART_INITIALIZED=false
CURRENT_POSTGRES_PID=""
function main() {
process_args $*
validate_before_start
start
}
function validate_before_start() {
if [ "$ENABLE_SOROBAN_RPC" != "true" ] && [ "$ENABLE_SOROBAN_RPC_ADMIN_ENDPOINT" = "true" ]; then
echo "--enable-soroban-rpc-admin-endpoint usage only supported with --enable-soroban-rpc" >&2
exit 1
fi
if [ "$NETWORK" != "local" ] && [ "$RANDOMIZE_NETWORK_PASSPHRASE" = "true" ]; then
echo "--randomize-network-passphrase is only supported in the local network" >&2
exit 1
fi
if [ "$NETWORK" = "local" ] && [ "$DISABLE_SOROBAN_DIAGNOSTIC_EVENTS" = "false" ]; then
ENABLE_SOROBAN_DIAGNOSTIC_EVENTS=true
fi
}
function validate_after_copy_defaults() {
if [ "$NETWORK" = "local" ] && [ "$LIMITS" != "default" ]; then
local config_dir="$COREHOME/etc/config-settings"
local config_path="$config_dir/p$PROTOCOL_VERSION/$LIMITS.json"
if [ ! -f "$config_path" ]; then
echo "--limits '$LIMITS' unknown: must be one of: default "$(ls $config_dir | sed 's/\.json//g')
exit 1
fi
fi
}
function start() {
echo "Starting Stellar Quickstart"
echo "versions:"
echo " quickstart: $REVISION"
echo " stellar-core:"
echo "$(stellar-core version 2>/dev/null | sed 's/^/ /')"
echo " horizon:"
echo "$(stellar-horizon version | sed 's/^/ /')"
echo " soroban-rpc:"
echo "$(stellar-soroban-rpc version | sed 's/^/ /')"
echo "mode: $STELLAR_MODE"
echo "network: $NETWORK"
echo "network passphrase: $NETWORK_PASSPHRASE"
echo "network id: $NETWORK_ID"
echo "network root secret key: $NETWORK_ROOT_SECRET_KEY"
echo "network root account id: $NETWORK_ROOT_ACCOUNT_ID"
copy_defaults
validate_after_copy_defaults
init_db
init_stellar_core
init_horizon
copy_pgpass
init_soroban_rpc
stop_postgres # this gets started in init_db
# launch services
if [ "$ENABLE_LOGS" = "true" ]; then
print_service_logs &
exec_supervisor \
> >(sed "s/^/${cyan}quickstart | $clear/") \
2> >(sed "s/^/${cyan}quickstart | $clear/" >&2)
else
exec_supervisor
fi
}
function process_args() {
while [[ -n "$1" ]]; do
ARG="$1"
shift
case "${ARG}" in
--logs)
ENABLE_LOGS=true
;;
--testnet)
NETWORK="testnet"
;;
--pubnet)
NETWORK="pubnet"
;;
--local)
NETWORK="local"
;;
--standalone)
echo "deprecated: option --standalone has been replaced by --local"
NETWORK="local"
;;
--futurenet)
NETWORK="futurenet"
;;
--protocol-version)
export PROTOCOL_VERSION="$1"
shift
;;
--enable-asset-stats)
export ENABLE_ASSET_STATS="$1"
shift
;;
--limits)
export LIMITS="$1"
shift
;;
--enable)
ENABLE="$1"
shift
;;
--enable-soroban-rpc)
ENABLE_SOROBAN_RPC=true
;;
--enable-soroban-diagnostic-events)
ENABLE_SOROBAN_DIAGNOSTIC_EVENTS=true
;;
--disable-soroban-diagnostic-events)
DISABLE_SOROBAN_DIAGNOSTIC_EVENTS=true
;;
--enable-soroban-rpc-admin-endpoint)
ENABLE_SOROBAN_RPC_ADMIN_ENDPOINT=true
;;
--enable-core-manual-close)
ENABLE_CORE_MANUAL_CLOSE=true
;;
--randomize-network-passphrase)
RANDOMIZE_NETWORK_PASSPHRASE=true
;;
*)
echo "Unknown container arg $ARG" >&2
exit 1
esac
done
# TODO: ask for what network to use
if [ -z "$NETWORK" ]; then
NETWORK="testnet"
fi
if [[ ",$ENABLE," = *",core,"* ]]; then
ENABLE_CORE=true
fi
if [[ ",$ENABLE," = *",horizon,"* ]]; then
ENABLE_HORIZON=true
fi
if [[ ",$ENABLE," = *",rpc,"* ]]; then
ENABLE_SOROBAN_RPC=true
fi
case "$NETWORK" in
testnet)
export NETWORK_PASSPHRASE="Test SDF Network ; September 2015"
export HISTORY_ARCHIVE_URLS="https://history.stellar.org/prd/core-testnet/core_testnet_001"
;;
pubnet)
export NETWORK_PASSPHRASE="Public Global Stellar Network ; September 2015"
export HISTORY_ARCHIVE_URLS="https://history.stellar.org/prd/core-live/core_live_001"
;;
local)
export NETWORK_PASSPHRASE="Standalone Network ; February 2017"
# h1570ry - we'll start a webserver connected to history directory later on
export HISTORY_ARCHIVE_URLS="http://localhost:1570"
ENABLE_CORE=true
if [[ "$ENABLE_SOROBAN_RPC" = "true" ]]; then
ENABLE_HORIZON=true
fi
;;
futurenet)
export NETWORK_PASSPHRASE="Test SDF Future Network ; October 2022"
export HISTORY_ARCHIVE_URLS="http://history-futurenet.stellar.org"
;;
*)
echo "Unknown network: '$NETWORK'" >&2
exit 1
esac
if [ "$RANDOMIZE_NETWORK_PASSPHRASE" = "true" ]; then
NETWORK_PASSPHRASE="${NETWORK_PASSPHRASE} ; $(openssl rand -hex 32)"
fi
export NETWORK_ID=$(printf "$NETWORK_PASSPHRASE" | sha256sum | cut -f 1 -d " ")
local network_id_keys=$(stellar-core convert-id $NETWORK_ID | awk -F': ' '/strKey: /{print $2}' | tail -2)
export NETWORK_ROOT_SECRET_KEY=$(printf "$network_id_keys" | head -1)
export NETWORK_ROOT_ACCOUNT_ID=$(printf "$network_id_keys" | tail -1)
# Are we ephemeral or persistent?
if [ -z "$STELLAR_MODE" ]; then
if [ -f "/opt/stellar/.docker-ephemeral" ]; then
STELLAR_MODE="ephemeral"
else
STELLAR_MODE="persistent"
fi
fi
}
function set_pg_password() {
if [ -n "$POSTGRES_PASSWORD" ]; then
PGPASS=$POSTGRES_PASSWORD
echo "using POSTGRES_PASSWORD"
return 0
fi
# use a random password when ephemeral (or some other unknown mode)
if [ "$STELLAR_MODE" != "persistent" ]; then
PGPASS=$(head /dev/urandom | tr -dc 'a-zA-Z0-9' | head -c 16)
echo "postgres password: $PGPASS"
return 0
fi
if [ -n "$PGPASS" ]; then
echo "postgres password: $PGPASS"
return 0
fi
# ask for a password when persistent
read -s -p "Enter New Postgresql Password: " PGPASS ||
(
echo Postgresql password not supplied. Set the POSTGRES_PASSWORD environment variable, or run the container interactively and provide the password via stdin.
exit 1
)
echo ""
read -s -p "Confirm: " PGPASS_CONFIRMATION
echo ""
if [ -z "$PGPASS" ]; then
echo "Password empty" >&2
exit 1
fi
if [ "$PGPASS" != "$PGPASS_CONFIRMATION" ]; then
echo "Password mistmach" >&2
exit 1
fi
}
function copy_defaults() {
local CP="rsync -a"
if [ -d $PGHOME/etc ]; then
echo "postgres: config directory exists, skipping copy"
else
$CP /opt/stellar-default/common/postgresql/ $PGHOME
fi
if [ -d $SUPHOME/etc ]; then
echo "supervisor: config directory exists, skipping copy"
else
$CP /opt/stellar-default/common/supervisor/ $SUPHOME
if [ "$ENABLE_SOROBAN_RPC" = "true" ]; then
cp /opt/stellar-default/$NETWORK/supervisor/etc/supervisord.conf.d/soroban-rpc.conf $SUPHOME/etc/supervisord.conf.d 2>/dev/null || true
fi
cp /opt/stellar-default/$NETWORK/supervisor/etc/supervisord.conf.d/friendbot.conf $SUPHOME/etc/supervisord.conf.d 2>/dev/null || true
cp /opt/stellar-default/$NETWORK/supervisor/etc/supervisord.conf.d/history-archive.conf $SUPHOME/etc/supervisord.conf.d 2>/dev/null || true
fi
if [ -d $COREHOME/etc ]; then
echo "stellar-core: config directory exists, skipping copy"
else
$CP /opt/stellar-default/common/core/ $COREHOME
$CP /opt/stellar-default/$NETWORK/core/ $COREHOME
fi
if [ -d $HZHOME/etc ]; then
echo "horizon: config directory exists, skipping copy"
else
$CP /opt/stellar-default/common/horizon/ $HZHOME
if [ -d /opt/stellar-default/$NETWORK/horizon/ ]; then
$CP /opt/stellar-default/$NETWORK/horizon/ $HZHOME
fi
fi
if [ -d $SOROBAN_RPC_HOME/etc ]; then
echo "soroban-rpc: config directory exists, skipping copy"
else
$CP /opt/stellar-default/common/soroban-rpc/ $SOROBAN_RPC_HOME
if [ -d /opt/stellar-default/$NETWORK/soroban-rpc/ ]; then
$CP /opt/stellar-default/$NETWORK/soroban-rpc/ $SOROBAN_RPC_HOME
fi
fi
if [ -d $FBHOME/etc ]; then
echo "friendbot: config directory exists, skipping copy"
else
$CP /opt/stellar-default/common/friendbot/ $FBHOME
if [ -d /opt/stellar-default/$NETWORK/friendbot/ ]; then
$CP /opt/stellar-default/$NETWORK/friendbot/ $FBHOME
fi
fi
if [ -d $NXHOME/etc ]; then
echo "nginx: config directory exists, skipping copy"
else
$CP /opt/stellar-default/common/nginx/ $NXHOME
if [ -d /opt/stellar-default/$NETWORK/nginx/ ]; then
$CP /opt/stellar-default/$NETWORK/nginx/ $NXHOME
fi
fi
}
function copy_pgpass() {
local CP="rsync -a"
$CP /opt/stellar/postgresql/.pgpass /root/
chmod 0600 /root/.pgpass
$CP /opt/stellar/postgresql/.pgpass /var/lib/stellar
chmod 0600 /var/lib/stellar/.pgpass
chown stellar:stellar /var/lib/stellar/.pgpass
}
function init_db() {
if [ "$ENABLE_CORE" != "true" ] && [ "$ENABLE_HORIZON" != "true" ]; then
return 0
fi
if [ -f $PGHOME/.quickstart-initialized ]; then
echo "postgres: already initialized"
return 0
fi
pushd $PGHOME
# workaround!!!! from: https://github.com/nimiq/docker-postgresql93/issues/2
mkdir /etc/ssl/private-copy; mv /etc/ssl/private/* /etc/ssl/private-copy/; rm -r /etc/ssl/private; mv /etc/ssl/private-copy /etc/ssl/private; chmod -R 0700 /etc/ssl/private; chown -R postgres /etc/ssl/private
# end workaround
echo "postgres user: $PGUSER"
set_pg_password
run_silent "finalize-pgpass" perl -pi -e "s/__PGPASS__/$PGPASS/g" /opt/stellar/postgresql/.pgpass
mkdir -p $PGDATA
chown postgres:postgres $PGDATA
chmod 0700 $PGDATA
# Create /var/run/postgresql because we are starting postgres manually,
# it is our responsibility to make sure the directory exists for where the
# process files and unix socket will live.
mkdir -p /var/run/postgresql
chown postgres:postgres /var/run/postgresql
run_silent "init-postgres" sudo -u postgres $PGBIN/initdb -D $PGDATA
start_postgres
run_silent "create-horizon-db" sudo -u postgres createdb horizon
run_silent "create-core-db" sudo -u postgres createdb core
run_silent "stellar-postgres-user" sudo -u postgres psql <<-SQL
CREATE USER $PGUSER WITH PASSWORD '$PGPASS';
GRANT ALL PRIVILEGES ON DATABASE horizon to $PGUSER;
GRANT ALL PRIVILEGES ON DATABASE core to $PGUSER;
SQL
touch .quickstart-initialized
popd
}
function init_stellar_core() {
if [ "$ENABLE_CORE" != "true" ]; then
return 0
fi
pushd $COREHOME
run_silent "chown-core" chown -R stellar:stellar .
if [ -f $COREHOME/.quickstart-initialized ]; then
echo "core: already initialized"
if [ "$NETWORK" = "local" ]; then
start_postgres
run_silent "init-core-scp" sudo -u stellar stellar-core force-scp --conf $COREHOME/etc/stellar-core.cfg
fi
return 0
fi
run_silent "finalize-core-config-pgpass" perl -pi -e "s/__PGPASS__/$PGPASS/g" etc/stellar-core.cfg
perl -pi -e "s/__NETWORK__/$NETWORK_PASSPHRASE/g" etc/stellar-core.cfg
run_silent "finalize-core-config-manual-close" perl -pi -e "s/__MANUAL_CLOSE__/$ENABLE_CORE_MANUAL_CLOSE/g" etc/stellar-core.cfg
start_postgres
run_silent "init-core-db" sudo -u stellar stellar-core new-db --conf etc/stellar-core.cfg
if [ "$NETWORK" = "local" ]; then
run_silent "init-core-scp" sudo -u stellar stellar-core force-scp --conf etc/stellar-core.cfg
run_silent "init-history" sudo -u stellar stellar-core new-hist vs --conf $COREHOME/etc/stellar-core.cfg
fi
touch .quickstart-initialized
popd
}
function init_horizon() {
if [ "$ENABLE_HORIZON" != "true" ]; then
return 0
fi
if [ -f $HZHOME/.quickstart-initialized ]; then
echo "horizon: already initialized"
return 0
fi
pushd $HZHOME
mkdir ./captive-core
perl -pi -e "s/__PGPASS__/$PGPASS/g" etc/horizon.env
perl -pi -e "s/__NETWORK__/$NETWORK_PASSPHRASE/g" etc/horizon.env
perl -pi -e "s=__ARCHIVE__=$HISTORY_ARCHIVE_URLS=g" etc/horizon.env
HORIZON_CAPTIVE_CORE_CFG=$HZHOME/etc/stellar-captive-core.cfg
run_silent "finalize-horizon-captivecore-db" perl -pi -e "s*__DATABASE__*sqlite3://$HZHOME/captive-core/stellar.db*g" $HORIZON_CAPTIVE_CORE_CFG
perl -pi -e "s/__NETWORK__/$NETWORK_PASSPHRASE/g" $HORIZON_CAPTIVE_CORE_CFG
run_silent "finalize-horizon-captivecore-config-enable-soroban-diagnostic-events" perl -pi -e "s/__ENABLE_SOROBAN_DIAGNOSTIC_EVENTS__/$ENABLE_SOROBAN_DIAGNOSTIC_EVENTS/g" $HORIZON_CAPTIVE_CORE_CFG
cat << EOF >> etc/horizon.env
export CAPTIVE_CORE_CONFIG_PATH=$HORIZON_CAPTIVE_CORE_CFG
export CAPTIVE_CORE_STORAGE_PATH=$HZHOME/captive-core
EOF
run_silent "chown-horizon" chown -R stellar:stellar .
if [[ "$NETWORK" = "local" || (".$PROTOCOL_VERSION" != ".none" && $PROTOCOL_VERSION -gt 19) ]] ; then
cat << EOF >> etc/horizon.env
export INGEST_DISABLE_STATE_VERIFICATION=True
EOF
fi
start_postgres
run_silent "init-horizon-db" sudo -u stellar ./bin/horizon db init
touch .quickstart-initialized
popd
}
function init_soroban_rpc() {
if [ "$ENABLE_SOROBAN_RPC" != "true" ]; then
return 0
fi
if [ -f $SOROBAN_RPC_HOME/.quickstart-initialized ]; then
echo "soroban rpc: already initialized"
return 0
fi
pushd $SOROBAN_RPC_HOME
mkdir ./captive-core
SOROBAN_RPC_CAPTIVE_CORE_CFG=$SOROBAN_RPC_HOME/etc/stellar-captive-core.cfg
run_silent "finalize-soroban-rpc-captivecore-db" perl -pi -e "s*__DATABASE__*sqlite3://$SOROBAN_RPC_HOME/captive-core/stellar-rpc.db*g" $SOROBAN_RPC_CAPTIVE_CORE_CFG
perl -pi -e "s/__NETWORK__/$NETWORK_PASSPHRASE/g" $SOROBAN_RPC_CAPTIVE_CORE_CFG
run_silent "finalize-soroban-rpc-captivecore-config-enable-soroban-diagnostic-events" perl -pi -e "s/__ENABLE_SOROBAN_DIAGNOSTIC_EVENTS__/$ENABLE_SOROBAN_DIAGNOSTIC_EVENTS/g" $SOROBAN_RPC_CAPTIVE_CORE_CFG
local ADMIN_ENDPOINT=0.0.0.0:6061
if [ "$ENABLE_SOROBAN_RPC_ADMIN_ENDPOINT" != "true" ]; then
ADMIN_ENDPOINT=
fi
perl -pi -e "s/__SOROBAN_RPC_ADMIN_ENDPOINT__/$ADMIN_ENDPOINT/g" etc/soroban-rpc.cfg
perl -pi -e "s/__NETWORK__/$NETWORK_PASSPHRASE/g" etc/soroban-rpc.cfg
perl -pi -e "s=__ARCHIVE__=$HISTORY_ARCHIVE_URLS=g" etc/soroban-rpc.cfg
run_silent "init-soroban-rpc" chown -R stellar:stellar .
touch .quickstart-initialized
popd
}
function kill_supervisor() {
kill -3 $(cat "/var/run/supervisord.pid")
}
function upgrade_local() {
set -eo pipefail
trap kill_supervisor ERR
if [ "$NETWORK" != "local" ]; then
return
fi
# Wait for server
while ! echo "Stellar-core http server listening!" | nc localhost 11626 &> /dev/null; do sleep 1; done
# Default to latest version supported by core if no default or explicit version was set
if [ -z "$PROTOCOL_VERSION" ]; then
export PROTOCOL_VERSION=`curl -s http://localhost:11626/info | jq -r '.info.protocol_version'`
fi
if [ ".$PROTOCOL_VERSION" == ".none" ] ; then
return
fi
# Upgrade local network's protocol version and base reserve to match pubnet/testnet
if [ $PROTOCOL_VERSION -gt 0 ]; then
echo "upgrades: protocolversion=$PROTOCOL_VERSION, basereserve=5000000"
curl -s "http://localhost:11626/upgrades?mode=set&upgradetime=1970-01-01T00:00:00Z&protocolversion=$PROTOCOL_VERSION&basereserve=5000000"
while [ "`curl -s http://localhost:11626/info | jq -r '.info.ledger.version'`" != "$PROTOCOL_VERSION" ]; do sleep 1; done
echo "upgrades: protocolversion done"
fi
# Upgrade local network's soroban config to match testnet, unless the limits
# have been configured with 'default', which will cause the limits to be left
# in their default state.
if [ $PROTOCOL_VERSION -ge 20 ] && [ "$LIMITS" != "default" ]; then
echo "upgrades: soroban config '$LIMITS' limits"
# Generate txs for installing, deploying and executing the contract that
# uploads a new config. Use the network root account to submit the txs.
upgrade_output="$(echo $NETWORK_ROOT_SECRET_KEY \
| stellar-core get-settings-upgrade-txs \
"$NETWORK_ROOT_ACCOUNT_ID" \
0 \
"$NETWORK_PASSPHRASE" \
--xdr `stellar-xdr encode --type ConfigUpgradeSet < "$COREHOME/etc/config-settings/p$PROTOCOL_VERSION/$LIMITS.json"` \
--signtxs)"
let line_count=$(echo "$upgrade_output" | wc -l)
echo "$upgrade_output" | { \
let TX_COUNT=1;
# If the line count is 9 instead of 7, a version of core is being used where the restore op is being returned
if [ $line_count = 9 ] ; then
read tx;
read txid;
echo "upgrades: soroban config: restore contract: $txid .. $(curl -sG 'http://localhost:11626/tx' --data-urlencode "blob=$tx" | jq -r '.status')";
while [ "`curl -s http://localhost:11626/metrics | jq -r '.metrics."ledger.transaction.count".count'`" != "$TX_COUNT" ]; do sleep 1; done
TX_COUNT=$((TX_COUNT+1))
fi
read tx; \
read txid; \
echo "upgrades: soroban config: install contract: $txid .. $(curl -sG 'http://localhost:11626/tx' --data-urlencode "blob=$tx" | jq -r '.status')"; \
while [ "`curl -s http://localhost:11626/metrics | jq -r '.metrics."ledger.transaction.count".count'`" != "$TX_COUNT" ]; do sleep 1; done
TX_COUNT=$((TX_COUNT+1)); \
read tx; \
read txid; \
echo "upgrades: soroban config: deploy contract: $txid .. $(curl -sG 'http://localhost:11626/tx' --data-urlencode "blob=$tx" | jq -r '.status')"; \
while [ "`curl -s http://localhost:11626/metrics | jq -r '.metrics."ledger.transaction.count".count'`" != "$TX_COUNT" ]; do sleep 1; done
TX_COUNT=$((TX_COUNT+1)); \
read tx; \
read txid; \
echo "upgrades: soroban config: upload config: $txid .. $(curl -sG 'http://localhost:11626/tx' --data-urlencode "blob=$tx" | jq -r '.status')"; \
while [ "`curl -s http://localhost:11626/metrics | jq -r '.metrics."ledger.transaction.count".count'`" != "$TX_COUNT" ]; do sleep 1; done
TX_COUNT=$((TX_COUNT+1)); \
read key; \
echo "upgrades: soroban config: set config with key: $key";
OUTPUT="$(curl -sG 'http://localhost:11626/upgrades?mode=set&upgradetime=1970-01-01T00:00:00Z' --data-urlencode "configupgradesetkey=$key")"
echo "$OUTPUT"; \
if [ "$OUTPUT" == "Error setting configUpgradeSet" ]; then
echo "!!!!! Unable to upgrade Soroban Config Settings. Stopping all services. !!!!!"
kill_supervisor
fi
}
echo "upgrades: soroban config done"
fi
# Start friendbot once network upgrades are complete and network is ready.
# Note that friendbot and the config upgrade txs above use the same
# account to submit txs. while friend it is not dependent on the config
# upgrade txs, it must not be started until the config upgrades are
# complete otherwise the txs sequence numbers will conflict.
if [ "$ENABLE_HORIZON" == "true" ]; then
supervisorctl start friendbot
fi
}
function start_optional_services() {
while supervisorctl status > /dev/null; [ $? -eq 4 ]; do
sleep 1
done
if [ "$ENABLE_CORE" == "true" ]; then
supervisorctl start postgresql
supervisorctl start stellar-core
fi
if [ "$ENABLE_HORIZON" == "true" ]; then
supervisorctl start postgresql
supervisorctl start horizon
fi
if [ "$ENABLE_SOROBAN_RPC" == "true" ]; then
supervisorctl start soroban-rpc
fi
}
function exec_supervisor() {
echo "supervisor: starting"
upgrade_local &
service_status &
start_optional_services &
# Run supervisord in a new environment (using `env -i`) because supervisord
# inherits the env vars of its environment for all subprocesses that get
# started. This is problematic for services that use the same environment
# variable name for things that the start script does, like NETWORK.
exec env -i supervisord -n -c $SUPHOME/etc/supervisord.conf \
> >(sed -u 's/^/supervisor: /') \
2> >(sed -u 's/^/supervisor: /' >&2)
}
function print_service_logs() {
# Wait for supervisord to be up.
while ! supervisorctl pid > /dev/null ; do
sleep 1;
done
# Start tailing logs from notable services.
if [ "$ENABLE_CORE" = "true" ]; then
supervisorctl tail -f stellar-core stdout > >(sed "s/^/${purple}stellar-core | $clear/") &
supervisorctl tail -f stellar-core stderr > >(sed "s/^/${purple}stellar-core | $clear/" >&2) &
fi
if [ "$ENABLE_HORIZON" = "true" ]; then
supervisorctl tail -f horizon stdout > >(sed "s/^/${green}horizon | $clear/") &
fi
if [ "$ENABLE_SOROBAN_RPC" = "true" ]; then
supervisorctl tail -f soroban-rpc stdout > >(sed "s/^/${blue}soroban-rpc | $clear/") &
fi
}
# run_silent is a utility function that runs a command with an abbreviated
# output provided it succeeds.
function run_silent() {
local LABEL=$1
shift
local COMMAND=$1
shift
local ARGS=$@
local OUTFILE="/tmp/run_silent.out"
set +e
$COMMAND $ARGS &> $OUTFILE
if [ $? -eq 0 ]; then
echo "$LABEL: ok"
else
echo "$LABEL: failed!"
echo ""
cat $OUTFILE
exit 1
fi
set -e
}
function start_postgres() {
if [ ! -z "$CURRENT_POSTGRES_PID" ]; then
return 0
fi
# Check that postgres can start and load the data successfully. If it can't
# successfully do this, then something is in a bad state. For example, a newer
# a persistent volume may be mounted with postgres data which is incompatible
# with the version of postgres in the container. Log any errors from postgres
# to help the operator debug the situation.
if ! postgres_logs=$(sudo -u postgres sh -c "echo -n | $PGBIN/postgres --single -E -D $PGDATA -c config_file=$PGHOME/etc/postgresql.conf" 2>&1); then
echo "$postgres_logs" | sed -u 's/^/postgres: /'
exit 1
fi
sudo -u postgres $PGBIN/postgres -D $PGDATA -c config_file=$PGHOME/etc/postgresql.conf &> /dev/null &
CURRENT_POSTGRES_PID=$!
while ! sudo -u postgres psql -c 'select 1' &> /dev/null ; do
echo "Waiting for postgres to be available..."
sleep 1
done
echo "postgres: up"
}
function stop_postgres() {
if [ -z "$CURRENT_POSTGRES_PID" ]; then
return 0
fi
killall postgres
# wait for postgres to die
while kill -0 "$CURRENT_POSTGRES_PID" &> /dev/null; do
sleep 0.5
done
echo "postgres: down"
}
pushd() {
command pushd "$@" > /dev/null
}
popd() {
command popd "$@" > /dev/null
}
function service_status() {
if [ "$ENABLE_CORE" = "true" ]; then
stellar_core_status "node" 11626 &
fi
if [ "$ENABLE_HORIZON" = "true" ]; then
stellar_core_status "horizon" 11726 &
horizon_status &
fi
if [ "$ENABLE_SOROBAN_RPC" = "true" ]; then
stellar_core_status "rpc" 11826 &
soroban_rpc_status &
fi
}
function stellar_core_status() {
local name="$1"
local port="$2"
local last_status=""
while true; do
local status="$(curl --silent --location "http://localhost:${port}/info" | jq -r '"\([.info.state] + (.info.status // []) | join("; "))"')"
if [ "$status" != "$last_status" ]; then
echo "stellar-core(${name}): $status"
fi
last_status="$status"
sleep 1
done
}
function soroban_rpc_status() {
echo "soroban-rpc: waiting for ready state..."
COUNTER=1
while ! $(curl --silent --location --request POST 'http://localhost:8003' \
--header 'Content-Type: application/json' \
--data-raw '{ "jsonrpc": "2.0", "id": 10235, "method": "getHealth" }' | \
jq --exit-status '.result.status == "healthy"' 2>/dev/null | grep -o true || echo false);
do
if [ $(expr $COUNTER % 12) -eq 0 ]; then
echo "soroban-rpc: waiting for ready state, $(expr $COUNTER / 12) minutes..."
fi
COUNTER=$[$COUNTER +1]
sleep 5
done
echo "soroban-rpc: up and ready"
}
function horizon_status() {
COUNTER=1
echo "horizon: waiting for ingestion to catch up..."
while ! $(curl --silent --location --request GET 'http://localhost:8001' | \
jq --exit-status '.core_latest_ledger > 5 and .history_latest_ledger > 5' 2>/dev/null | \
grep -o true || echo false);
do
if [ $(expr $COUNTER % 12) -eq 0 ]; then
echo "horizon: waiting for ingestion to catch up, $(expr $COUNTER / 12) minutes..."
fi
COUNTER=$[$COUNTER +1]
sleep 5
done
echo "horizon: ingestion caught up"
}
main $@