-
Notifications
You must be signed in to change notification settings - Fork 99
/
Copy pathsetup_rpc.sh
593 lines (481 loc) · 19.4 KB
/
setup_rpc.sh
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
#!/bin/bash
set -e
FUNCTION="$1"
NEW_IMAGE_VERSION="$2"
CONTAINER_NAME="$3"
HOST_SUPRA_HOME="$4"
NETWORK="$5"
if [ "$FUNCTION" == "setup" ]; then
VALIDATOR_IP="$6"
fi
function basic_usage() {
echo "Usage: ./setup_rpc.sh <function> <[function_args...]>" >&2
echo "Parameters:" >&2
echo " - function: The function to execute. Either 'setup' or 'update'." >&2
echo " - function_args: The arguments required by the function. Run './setup_rpc.sh <function>' for more details." >&2
exit 1
}
function echo_common_parameters() {
echo "Parameters:" >&2
echo " - image_version: The RPC node Docker image version to use. Must be a valid semantic versioning identifier: i.e. 'v<major>.<minor>.<patch>'." >&2
echo " - container_name: The name of your Supra RPC Docker container." >&2
echo " - host_supra_home: The directory on the local host to be mounted as \$SUPRA_HOME in the Docker container." >&2
echo " - network: The network to sync with. Either 'testnet' or 'mainnet'." >&2
}
function setup_usage() {
echo "Usage: ./setup_rpc.sh setup <image_version> <container_name> <host_supra_home> <network> <validator_ip>" >&2
echo_common_parameters
echo " - validator_ip: The IP address of the validator to sync consensus data from." >&2
exit 1
}
function update_usage() {
echo "Usage: ./setup_rpc.sh update <image_version> <container_name> <host_supra_home> <network>" >&2
echo_common_parameters
exit 1
}
function is_semantic_version_id() {
local id="$1"
[[ "$id" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]
}
function verify_network() {
[ "$NETWORK" == "mainnet" ] || [ "$NETWORK" == "testnet" ]
}
function verify_common_arguments() {
is_semantic_version_id "$NEW_IMAGE_VERSION" \
&& [ -n "$CONTAINER_NAME" ] \
&& [ -n "$HOST_SUPRA_HOME" ] \
&& verify_network
}
function verify_setup() {
if ! verify_common_arguments || ! [[ "$VALIDATOR_IP" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
setup_usage
fi
}
function verify_update() {
if ! verify_common_arguments; then
update_usage
fi
}
function verify_args() {
if [ "$FUNCTION" == "setup" ]; then
verify_setup
elif [ "$FUNCTION" == "update" ]; then
verify_update
else
basic_usage
fi
}
verify_args
MAINNET_RCLONE_CONFIG_HEADER="[cloudflare-r2-mainnet]"
MAINNET_RCLONE_CONFIG="$MAINNET_RCLONE_CONFIG_HEADER
type = s3
provider = Cloudflare
access_key_id = c64bed98a85ccd3197169bf7363ce94f
secret_access_key = 0b7f15dbeef4ebe871ee8ce483e3fc8bab97be0da6a362b2c4d80f020cae9df7
region = auto
endpoint = https://4ecc77f16aaa2e53317a19267e3034a4.r2.cloudflarestorage.com
acl = private
no_check_bucket = true
"
MAINNET_RPC_CONFIG_TOML='####################################### PROTOCOL PARAMETERS #######################################
# The below parameters are fixed for the protocol and must be agreed upon by all node operators
# at genesis. They may subsequently be updated via governance decisions.
# Core protocol parameters.
# A unique identifier for this instance of the Supra protocol. Prevents replay attacks across chains.
chain_instance.chain_id = 8
# The length of an epoch in seconds.
chain_instance.epoch_duration_secs = 7200
# The number of seconds that stake locked in a Stake Pool will automatically be locked up for when
# its current lockup expires, if no request is made to unlock it.
#
# 48 hours.
chain_instance.recurring_lockup_duration_secs = 172800
# The number of seconds allocated for voting on governance proposals. Governance will initially be
# controlled by The Supra Foundation.
#
# 46 hours.
chain_instance.voting_duration_secs = 165600
# Determines whether the network will start with a faucet, amongst other things.
chain_instance.is_testnet = false
# Wednesday, Nov 20, 2024 12:00:00.000 AM (UTC).
chain_instance.genesis_timestamp_microseconds = 1732060800000000
######################################### NODE PARAMETERS #########################################
# The below parameters are node-specific and may be configured as required by the operator.
# The port on which the node should listen for incoming RPC requests.
bind_addr = "0.0.0.0:30000"
# If `true` then blocks will not be verified before execution. This value should be `false`
# unless you also control the node from which this RPC node is receiving blocks.
block_provider_is_trusted = false
# The path to the TLS certificate for the connection with the attached validator.
consensus_client_cert_path = "./configs/client_supra_certificate.pem"
# The path to the private key to be used when negotiating TLS connections.
consensus_client_private_key_path = "./configs/client_supra_key.pem"
# The path to the TLS root certificate authority certificate.
consensus_root_ca_cert_path = "./configs/ca_certificate.pem"
# The websocket address of the attached validator.
consensus_rpc = "ws://<VALIDATOR_IP>:26000"
# If true, all components will attempt to load their previous state from disk. Otherwise,
# all components will start in their default state. Should always be `true` for testnet and
# mainnet.
resume = true
# The path to `supra_committees.json`.
supra_committees_config = "./configs/supra_committees.json"
# The number of seconds to wait before retrying a block sync request.
sync_retry_interval_in_secs = 1
# Parameters for the RPC Archive database. This database stores the indexes used to serve RPC API calls.
[database_setup.dbs.archive.rocks_db]
# The path at which the database should be created.
path = "./configs/rpc_archive"
# Whether snapshots should be taken of the database.
enable_snapshots = true
# Parameters for the DKG database.
[database_setup.dbs.ledger.rocks_db]
# The path at which the database should be created.
path = "./configs/rpc_ledger"
# Parameters for the blockchain database.
[database_setup.dbs.chain_store.rocks_db]
# The path at which the database should be created.
path = "./configs/rpc_store"
# Whether snapshots should be taken of the database.
enable_snapshots = true
# Parameters for the database snapshot service.
[database_setup.snapshot_config]
# The number of snapshots to retain, including the latest.
depth = 2
# The interval between snapshots in seconds.
interval_in_seconds = 1800
# The path at which the snapshots should be stored.
path = "./configs/snapshot"
# The number of times to retry a snapshot in the event that it fails unexpectedly.
retry_count = 3
# The interval in seconds to wait before retring a snapshot.
retry_interval_in_seconds = 5
# CORS settings for RPC API requests.
[[allowed_origin]]
url = "https://rpc-mainnet.supra.com"
description = "RPC For Supra"
[[allowed_origin]]
url = "https://rpc-mainnet1.supra.com"
description = "RPC For nodeops group1"
[[allowed_origin]]
url = "https://rpc-mainnet2.supra.com"
description = "RPC For nodeops group2"
[[allowed_origin]]
url = "https://rpc-mainnet3.supra.com"
description = "RPC For nodeops group3"
[[allowed_origin]]
url = "https://rpc-mainnet4.supra.com"
description = "RPC For nodeops group4"
[[allowed_origin]]
url = "https://rpc-mainnet5.supra.com"
description = "RPC For nodeops group5"
[[allowed_origin]]
url = "https://rpc-wallet-mainnet.supra.com"
description = "RPC For Supra Wallet"
[[allowed_origin]]
url = "https://rpc-suprascan-mainnet.supra.com"
description = "RPC For suprascan"
[[allowed_origin]]
url = "http://localhost:27000"
description = "LocalNet"
mode = "Server"
[[allowed_origin]]
url = "https://www.starkey.app"
description = "Starkey domain"
mode = "Cors"
[[allowed_origin]]
url = "chrome-extension://fcpbddmagekkklbcgnjclepnkddbnenp"
description = "Starkey wallet extension"
mode = "Cors"
[[allowed_origin]]
url = "chrome-extension://hcjhpkgbmechpabifbggldplacolbkoh"
description = "Starkey wallet extension"
mode = "Cors"
[[allowed_origin]]
url = "https://supra.com"
description = "Supra domain"
mode = "Cors"
[[allowed_origin]]
url = "https://qa-spa.supra.com"
description = "QA Supra domain"
mode = "Cors"
[[allowed_origin]]
url = "https://qa-api.services.supra.com"
description = "QA API Supra domain"
mode = "Cors"
[[allowed_origin]]
url = "https://prod-api.services.supra.com"
description = "Prod API Supra domain"
mode = "Cors"
[[allowed_origin]]
url = "http://localhost:3000"
description = "Localhost"
mode = "Cors"
[[allowed_origin]]
url = "http://localhost:8080"
description = "Localhost"
mode = "Cors"
'
TESTNET_RCLONE_CONFIG_HEADER="[cloudflare-r2-testnet]"
TESTNET_RCLONE_CONFIG="$TESTNET_RCLONE_CONFIG_HEADER
type = s3
provider = Cloudflare
access_key_id = 229502d7eedd0007640348c057869c90
secret_access_key = 799d15f4fd23c57cd0f182f2ab85a19d885887d745e2391975bb27853e2db949
region = auto
endpoint = https://4ecc77f16aaa2e53317a19267e3034a4.r2.cloudflarestorage.com
acl = private
no_check_bucket = true
"
TESTNET_RPC_CONFIG_TOML='####################################### PROTOCOL PARAMETERS #######################################
# The below parameters are fixed for the protocol and must be agreed upon by all node operators
# at genesis. They may subsequently be updated via governance decisions.
# Core protocol parameters.
# A unique identifier for this instance of the Supra protocol. Prevents replay attacks across chains.
chain_instance.chain_id = 6
# The length of an epoch in seconds.
chain_instance.epoch_duration_secs = 7200
# The number of seconds that stake locked in a Stake Pool will automatically be locked up for when
# its current lockup expires, if no request is made to unlock it.
chain_instance.recurring_lockup_duration_secs = 14400
# The number of seconds allocated for voting on governance proposals. Governance will initially be controlled by The Supra Foundation.
chain_instance.voting_duration_secs = 7200
# Determines whether the network will start with a faucet, amongst other things.
chain_instance.is_testnet = true
# Tuesday, September 17, 2024 12:00:00.000 PM (UTC)
chain_instance.genesis_timestamp_microseconds = 1726574400000000
######################################### NODE PARAMETERS #########################################
# The below parameters are node-specific and may be configured as required by the operator.
# The port on which the node should listen for incoming RPC requests.
bind_addr = "0.0.0.0:26000"
# If `true` then blocks will not be verified before execution. This value should be `false`
# unless you also control the node from which this RPC node is receiving blocks.
block_provider_is_trusted = false
# The path to the TLS certificate for the connection with the attached validator.
consensus_client_cert_path = "./configs/client_supra_certificate.pem"
# The path to the private key to be used when negotiating TLS connections.
consensus_client_private_key_path = "./configs/client_supra_key.pem"
# The path to the TLS root certificate authority certificate.
consensus_root_ca_cert_path = "./configs/ca_certificate.pem"
# The websocket address of the attached validator.
consensus_rpc = "ws://<VALIDATOR_IP>:26000"
# If true, all components will attempt to load their previous state from disk. Otherwise,
# all components will start in their default state. Should always be `true` for testnet and
# mainnet.
resume = true
# The path to `supra_committees.json`.
supra_committees_config = "./configs/supra_committees.json"
# The number of seconds to wait before retrying a block sync request.
sync_retry_interval_in_secs = 5
# Parameters for the RPC Archive database. This database stores the indexes used to serve RPC API calls.
[database_setup.dbs.archive.rocks_db]
# The path at which the database should be created.
path = "./configs/rpc_archive"
# Whether snapshots should be taken of the database.
enable_snapshots = true
# Parameters for the DKG database.
[database_setup.dbs.ledger.rocks_db]
# The path at which the database should be created.
path = "./configs/rpc_ledger"
# Parameters for the blockchain database.
[database_setup.dbs.chain_store.rocks_db]
# The path at which the database should be created.
path = "./configs/rpc_store"
# Whether snapshots should be taken of the database.
enable_snapshots = true
# Parameters for the database snapshot service.
[database_setup.snapshot_config]
# The number of snapshots to retain, including the latest.
depth = 2
# The interval between snapshots in seconds.
interval_in_seconds = 1800
# The path at which the snapshots should be stored.
path = "./configs/snapshot"
# The number of times to retry a snapshot in the event that it fails unexpectedly.
retry_count = 3
# The interval in seconds to wait before retrying a snapshot.
retry_interval_in_seconds = 5
# CORS settings for RPC API requests. The below settings are the default values required for use in RPC nodes run by validator node operators. They are optional for non-validators.
[[allowed_origin]]
url = "https://rpc-testnet.supra.com"
description = "RPC For Supra Scan and Faucet"
[[allowed_origin]]
url = "https://rpc-testnet1.supra.com"
description = "RPC For nodeops group1"
[[allowed_origin]]
url = "https://rpc-testnet2.supra.com"
description = "RPC For nodeops group2"
[[allowed_origin]]
url = "https://rpc-testnet3.supra.com"
description = "RPC For nodeops group3"
[[allowed_origin]]
url = "https://rpc-testnet4.supra.com"
description = "RPC For nodeops group4"
[[allowed_origin]]
url = "https://rpc-testnet5.supra.com"
description = "RPC For nodeops group5"
[[allowed_origin]]
url = "http://localhost:27000"
description = "LocalNet"
mode = "Server"
[[allowed_origin]]
url = "https://www.starkey.app"
description = "Starkey domain"
mode = "Cors"
[[allowed_origin]]
url = "chrome-extension://fcpbddmagekkklbcgnjclepnkddbnenp"
description = "Starkey wallet extension"
mode = "Cors"
[[allowed_origin]]
url = "chrome-extension://hcjhpkgbmechpabifbggldplacolbkoh"
description = "Starkey wallet extension"
mode = "Cors"
'
DOCKER_IMAGE="asia-docker.pkg.dev/supra-devnet-misc/supra-${NETWORK}/rpc-node:${NEW_IMAGE_VERSION}"
if [ "$NETWORK" = "mainnet" ]; then
RCLONE_CONFIG="$MAINNET_RCLONE_CONFIG"
RCLONE_CONFIG_HEADER="$MAINNET_RCLONE_CONFIG_HEADER"
RPC_CONFIG_TOML="$MAINNET_RPC_CONFIG_TOML"
SNAPSHOT_ROOT="mainnet"
STATIC_SOURCE="mainnet-data"
else
RCLONE_CONFIG="$TESTNET_RCLONE_CONFIG"
RCLONE_CONFIG_HEADER="$TESTNET_RCLONE_CONFIG_HEADER"
RPC_CONFIG_TOML="$TESTNET_RPC_CONFIG_TOML"
SNAPSHOT_ROOT="testnet-snapshot"
STATIC_SOURCE="testnet-snapshot"
fi
# Functions
function current_docker_image() {
if ! which jq &>/dev/null; then
echo "Could not locate 'jq'. Please install it and run the script again." >&2
exit 2
fi
docker inspect "$CONTAINER_NAME" | jq -r '.[0].Config.Image' 2>/dev/null
}
function ensure_supra_home_is_absolute_path() {
# Create the directory if it doesn't exist.
mkdir -p "$HOST_SUPRA_HOME"
# Enter it and print the fully-qualified path in case it was given as a relative path.
cd "$HOST_SUPRA_HOME"
HOST_SUPRA_HOME="$(pwd)"
}
function remove_old_docker_container() {
# Stop the Docker container if it's running
echo "Stopping rpc container"
if ! docker stop "$CONTAINER_NAME"; then
echo "Failed to stop rpc container. Exiting..."
fi
echo "RPC container Stopped"
# Remove the Docker container
echo "Removing rpc container"
if ! docker rm "$CONTAINER_NAME"; then
echo "Failed to remove rpc container. Exiting..."
fi
echo "RPC container removed"
}
function remove_old_docker_image() {
local old_image="$1"
echo "Removing old Docker image: $old_image"
if docker rmi "$old_image" &>/dev/null; then
echo "Old Docker image removed successfully."
else
echo "Failed to remove old Docker image. It may not exist."
fi
}
function maybe_update_container() {
local current_image="$(current_docker_image)"
if [ -n "$current_image" ] && [[ "$current_image" != "$DOCKER_IMAGE" ]]; then
remove_old_docker_container
remove_old_docker_image "$current_image"
fi
}
function start_docker_container() {
local user_id="$(id -u)"
local group_id="$(id -g)"
docker start "$CONTAINER_NAME" &>/dev/null \
|| docker run \
--name "$CONTAINER_NAME" \
--user "${user_id}:${group_id}" \
-v "$HOST_SUPRA_HOME:/supra/configs" \
-e "RUST_LOG=debug,sop2p=info,multistream_select=off,libp2p_swarm=off,yamux=off" \
-e "SUPRA_HOME=/supra/configs/" \
-e "SUPRA_LOG_DIR=/supra/configs/rpc_logs" \
-e "SUPRA_MAX_LOG_FILE_SIZE=500000000" \
-e "SUPRA_MAX_UNCOMPRESSED_LOGS=20" \
-e "SUPRA_MAX_LOG_FILES=40" \
--net=host \
-itd "asia-docker.pkg.dev/supra-devnet-misc/supra-${NETWORK}/rpc-node:${NEW_IMAGE_VERSION}"
}
function create_config_toml() {
local config_toml="$HOST_SUPRA_HOME/config.toml"
if ! [ -f "$config_toml" ]; then
echo "$RPC_CONFIG_TOML" | sed "s/<VALIDATOR_IP>/$VALIDATOR_IP/g" > "$config_toml"
fi
}
function download_static_configuration_files() {
local ca_certificate="$HOST_SUPRA_HOME/ca_certificate.pem"
local client_supra_certificate="$HOST_SUPRA_HOME/client_supra_certificate.pem"
local client_supra_key="$HOST_SUPRA_HOME/client_supra_key.pem"
local supra_committees="$HOST_SUPRA_HOME/supra_committees.json"
local genesis_blob="$HOST_SUPRA_HOME/genesis.blob"
# Download the TLS certificates and keys.
if ! [ -f "$ca_certificate" ]; then
wget -nc -O "$ca_certificate" "https://${STATIC_SOURCE}.supra.com/certificates/ca_certificate.pem"
fi
if ! [ -f "$client_supra_certificate" ]; then
wget -nc -O "$client_supra_certificate" "https://${STATIC_SOURCE}.supra.com/certificates/client_supra_certificate.pem"
fi
if ! [ -f "$client_supra_key" ]; then
wget -nc -O "$client_supra_key" "https://${STATIC_SOURCE}.supra.com/certificates/client_supra_key.pem"
fi
# And the Genesis Blob and Genesis Committee files.
if ! [ -f "$supra_committees" ]; then
wget -nc -O "$supra_committees" "https://${STATIC_SOURCE}.supra.com/configs/supra_committees.json"
fi
if ! [ -f "$genesis_blob" ]; then
wget -nc -O "$genesis_blob" "https://${STATIC_SOURCE}.supra.com/configs/genesis.blob"
fi
}
function sync_snapshots() {
docker stop "$CONTAINER_NAME"
if ! which rclone >/dev/null; then
curl https://rclone.org/install.sh | sudo bash
fi
mkdir -p ~/.config/rclone/
if ! grep "$RCLONE_CONFIG_HEADER" ~/.config/rclone/rclone.conf >/dev/null; then
echo "$RCLONE_CONFIG" >> ~/.config/rclone/rclone.conf
fi
rclone sync "cloudflare-r2-${NETWORK}:${SNAPSHOT_ROOT}/snapshots/store" "$HOST_SUPRA_HOME/rpc_store/" --progress
rclone sync "cloudflare-r2-${NETWORK}:${SNAPSHOT_ROOT}/snapshots/archive" "$HOST_SUPRA_HOME/rpc_archive/" --progress
}
function copy_root_config_files() {
# Copy the config files required in the root of the container, to the root.
docker cp "$HOST_SUPRA_HOME"/config.toml "$CONTAINER_NAME:/supra/"
docker cp "$HOST_SUPRA_HOME"/genesis.blob "$CONTAINER_NAME:/supra/configs/"
}
function update_existing_container() {
echo "Updating $CONTAINER_NAME..."
ensure_supra_home_is_absolute_path
maybe_update_container
start_docker_container
sync_snapshots
copy_root_config_files
echo "Container update completed."
}
function setup_new_rpc_node() {
echo "Setting up a new RPC node..."
ensure_supra_home_is_absolute_path
start_docker_container
create_config_toml
download_static_configuration_files
sync_snapshots
copy_root_config_files
echo "RPC node setup completed."
}
# Main execution logic
if [ "$FUNCTION" == "setup" ]; then
setup_new_rpc_node
elif [ "$FUNCTION" == "update" ]; then
update_existing_container
fi