@@ -12,7 +12,9 @@ new_user_setup=0
12
12
new_network=0
13
13
network_status_url=" "
14
14
network_identifier=" "
15
+ staking_url=" "
15
16
container_id=" "
17
+ latest_key_end_block=" "
16
18
17
19
voi_logo="[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m
18
20
[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m[38;2;255;255;255mM[0m
@@ -297,7 +299,7 @@ get_node_status() {
297
299
fi
298
300
}
299
301
300
- set_network_url () {
302
+ set_network_status_url () {
301
303
case ${VOINETWORK_NETWORK} in
302
304
"mainnet")
303
305
network_status_url="https://mainnet-api.voi.nodly.io/v2/status"
@@ -314,6 +316,23 @@ set_network_url() {
314
316
esac
315
317
}
316
318
319
+ set_staking_url() {
320
+ case ${VOINETWORK_NETWORK} in
321
+ "mainnet")
322
+ staking_url="https://mainnet-idx.nautilus.sh/v1/scs/accounts"
323
+ ;;
324
+ "betanet")
325
+ staking_url="https://betanet-idx.nautilus.sh/v1/scs/accounts"
326
+ ;;
327
+ "testnet")
328
+ staking_url="https://arc72-idx.nautilus.sh/v1/scs/accounts"
329
+ ;;
330
+ *)
331
+ abort "Unable to find staking URL. Exiting the program."
332
+ ;;
333
+ esac
334
+ }
335
+
317
336
set_network_identifier() {
318
337
case ${VOINETWORK_NETWORK} in
319
338
"mainnet")
@@ -331,9 +350,26 @@ set_network_identifier() {
331
350
esac
332
351
}
333
352
353
+ get_network_identifier() {
354
+ case $1 in
355
+ "mainnet")
356
+ echo "voimain-v1.0"
357
+ ;;
358
+ "betanet")
359
+ echo "voibeta-v1.0"
360
+ ;;
361
+ "testnet")
362
+ echo "voitest-v1"
363
+ ;;
364
+ *)
365
+ echo "voitest-v1"
366
+ ;;
367
+ esac
368
+ }
369
+
334
370
catchup_node() {
335
371
display_banner "Catching up with the network... This might take some time, and numbers might briefly increase"
336
- set_network_url
372
+ set_network_status_url
337
373
338
374
get_node_status
339
375
@@ -484,11 +520,20 @@ get_last_committed_block() {
484
520
}
485
521
486
522
get_account_addresses() {
487
- if execute_sudo " test ! -f \" /var/lib/voi/algod/data/${network_identifier} /accountList.json\" " ; then
523
+ local network_identifier_override
524
+ local local_network_identifier
525
+ network_identifier_override=$1
526
+ local_network_identifier=${network_identifier}
527
+
528
+ if [[ -n ${network_identifier_override} ]]; then
529
+ local_network_identifier=${network_identifier_override}
530
+ fi
531
+
532
+ if execute_sudo " test ! -f \" /var/lib/voi/algod/data/${local_network_identifier} /accountList.json\" " ; then
488
533
abort " Account list not found. Exiting the program."
489
534
fi
490
535
491
- accounts_json=$( execute_sudo " cat /var/lib/voi/algod/data/${network_identifier } /accountList.json" )
536
+ accounts_json=$( execute_sudo " cat /var/lib/voi/algod/data/${local_network_identifier } /accountList.json" )
492
537
number_of_accounts=$( echo " ${accounts_json} " | jq ' .Accounts | length' )
493
538
494
539
if [[ $number_of_accounts -eq 0 ]]; then
@@ -509,13 +554,16 @@ generate_new_key() {
509
554
end_block=$(( start_block + 2000000 ))
510
555
expiration_date=$( get_participation_expiration_eta " ${end_block} " " ${start_block} " )
511
556
address=$1
512
- echo " Generating participation key for account ${address} with start block ${start_block} and end block ${end_block} "
557
+ latest_key_end_block=${end_block}
558
+ echo " Generating participation key for ${address} with start block ${start_block} and end block ${end_block} "
513
559
echo " New key is expected to be valid until: ${expiration_date} "
514
560
execute_interactive_docker_command " /node/bin/goal account addpartkey -a ${address} --roundFirstValid ${start_block} --roundLastValid ${end_block} "
515
561
}
516
562
517
563
ensure_accounts_are_offline() {
518
- account_addresses=$( get_account_addresses)
564
+ local local_network_identifier
565
+ local_network_identifier=$( get_network_identifier " $1 " )
566
+ account_addresses=$( get_account_addresses " ${local_network_identifier} " )
519
567
520
568
if [[ -z ${account_addresses} ]]; then
521
569
return
@@ -545,6 +593,48 @@ ensure_accounts_are_offline() {
545
593
done
546
594
}
547
595
596
+ get_participation_key_id_from_vote_key() {
597
+ local vote_key
598
+ local output
599
+ vote_key=$1
600
+
601
+ output=$( execute_docker_command " /node/bin/goal account partkeyinfo" )
602
+ echo " ${output} " | grep -B 10 " ${vote_key} " | grep 'Participation ID:' | head -n 1 | cut -d ':' -f2- | xargs
603
+ }
604
+
605
+ get_most_recent_participation_key_details() {
606
+ local address=$1
607
+ local output
608
+
609
+ output=$( execute_docker_command " /node/bin/goal account partkeyinfo" )
610
+
611
+ local first_round
612
+ first_round=$( echo " $output " | grep -A 4 -B 5 " ${latest_key_end_block} " | grep ' First round:' | head -n 1 | cut -d ' :' -f2- | xargs)
613
+ local last_round
614
+ last_round=$( echo " $output " | grep -A 4 -B 5 " ${latest_key_end_block} " | grep ' Last round:' | head -n 1 | cut -d ' :' -f2- | xargs)
615
+ local key_dilution
616
+ key_dilution=$( echo " $output " | grep -A 4 -B 5 " ${latest_key_end_block} " | grep ' Key dilution:' | head -n 1 | cut -d ' :' -f2- | xargs)
617
+ local selection_key
618
+ selection_key=$( echo " $output " | grep -A 4 -B 5 " ${latest_key_end_block} " | grep ' Selection key:' | head -n 1 | cut -d ' :' -f2- | xargs)
619
+ local voting_key
620
+ voting_key=$( echo " $output " | grep -A 4 -B 5 " ${latest_key_end_block} " | grep ' Voting key:' | head -n 1 | cut -d ' :' -f2- | xargs)
621
+ local stateproof_key
622
+ # shellcheck disable=SC2034
623
+ stateproof_key=$( echo " $output " | grep -A 4 -B 5 " ${latest_key_end_block} " | grep ' State proof key:' | head -n 1 | cut -d ' :' -f2- | xargs)
624
+
625
+ key_info_json=$( jq --null-input --arg address " $address " --arg first_round " $first_round " --arg last_round " $last_round " --arg key_dilution " $key_dilution " --arg selection_key " $selection_key " --arg voting_key " $voting_key " --arg stateproof_key " $stateproof_key " ' {
626
+ "address": $address,
627
+ "first_round": $first_round,
628
+ "last_valid": $last_round,
629
+ "key_dilution": $key_dilution,
630
+ "selection_key": $selection_key,
631
+ "voting_key": $voting_key,
632
+ "stateproof_key": $stateproof_key
633
+ }' )
634
+
635
+ echo " ${key_info_json} "
636
+ }
637
+
548
638
generate_participation_key() {
549
639
display_banner " Generating/Updating participation key"
550
640
@@ -622,7 +712,9 @@ generate_participation_key() {
622
712
echo " You will be asked to enter your password to activate the new key."
623
713
624
714
execute_interactive_docker_command " /node/bin/goal account renewpartkey -a ${account} --roundLastValid ${end_block} "
625
- execute_interactive_docker_command " /node/bin/goal account deletepartkey --partkeyid ${current_key_id} "
715
+ if [[ -n ${current_key_id} ]]; then
716
+ execute_interactive_docker_command " /node/bin/goal account deletepartkey --partkeyid ${current_key_id} "
717
+ fi
626
718
else
627
719
local existing_expiration_date
628
720
existing_expiration_date=$( get_participation_expiration_eta " ${active_key_last_valid_round} " " ${last_committed_block} " )
@@ -738,6 +830,136 @@ joined_network_instructions() {
738
830
fi
739
831
}
740
832
833
+ check_staking_accounts () {
834
+ account_addresses=$( get_account_addresses)
835
+ if [[ $? -eq 1 ]]; then
836
+ return
837
+ else
838
+ set_staking_url
839
+
840
+ for account in ${account_addresses} ; do
841
+ local staking_endpoint
842
+ local response
843
+ local http_code
844
+ local json_response
845
+
846
+ staking_endpoint=" ${staking_url} ?owner=${account} &deleted=0"
847
+ response=$( curl -s --max-time 5 -w " %{http_code}" " ${staking_endpoint} " )
848
+ http_code=$( echo " ${response} " | awk ' {print substr($0, length($0) - 2)}' )
849
+ json_response=$( echo " ${response} " | awk ' {print substr($0, 1, length($0) - 3)}' )
850
+
851
+ if [[ " ${http_code} " -eq 200 ]]; then
852
+ accounts_length=$( jq ' .accounts | length' <<< " ${json_response}" )
853
+ if [[ " ${accounts_length} " -gt 0 ]]; then
854
+ display_banner " Staking contract detected"
855
+
856
+ echo " Staking contract has been detected for owner ${account} "
857
+ echo " "
858
+
859
+ local balance
860
+ balance=$( get_account_balance " ${account_addr} " )
861
+
862
+ if [[ ${balance} -lt " 1000" ]]; then
863
+ echo " Balance is below 1,000 microVoi. Skipping staking account setup."
864
+ continue
865
+ fi
866
+
867
+ local staking_accounts
868
+ staking_accounts=$( jq -c ' .accounts[]' <<< " ${json_response}" )
869
+ for staking_account in ${staking_accounts} ; do
870
+ local last_committed_block
871
+ local contract_address
872
+ local contract_id
873
+ local part_vote_k
874
+ local part_vote_lst
875
+ local participation_key_id
876
+
877
+ contract_id=$( jq -r ' .contractId' <<< " ${staking_account}" )
878
+ contract_address=$( jq -r ' .contractAddress' <<< " ${staking_account}" )
879
+ last_committed_block=$( get_last_committed_block)
880
+
881
+ part_vote_k=$( jq -r ' .part_vote_k' <<< " ${staking_account}" )
882
+ part_vote_lst=$( jq -r ' .part_vote_lst' <<< " ${staking_account}" )
883
+
884
+ # shellcheck disable=SC2046
885
+ participation_key_id=$( get_participation_key_id_from_vote_key " ${part_vote_k} " )
886
+
887
+ if [[ " ${part_vote_k} " == " null" || $(( part_vote_lst- last_committed_block)) -le 417104 || -z " ${participation_key_id} " ]]; then
888
+
889
+ if [[ " ${part_vote_k} " == " null" ]]; then
890
+ echo " No staking participation key detected."
891
+ elif [[ -z ${participation_key_id} ]]; then
892
+ echo " Registered staking participation key is not installed locally."
893
+ else
894
+ local existing_expiration_date
895
+ existing_expiration_date=$( get_participation_expiration_eta " ${part_vote_lst} " " ${last_committed_block} " )
896
+
897
+ echo " Current participation key for account ${account} is expected to expire at: ${existing_expiration_date} "
898
+ echo " Currently the network is at block: ${last_committed_block} "
899
+ echo " Current participation key expires at block: ${part_vote_lst} "
900
+ echo " "
901
+ echo " This is below the required threshold of 417,104 blocks / ~14 days."
902
+ fi
903
+
904
+ echo " "
905
+ echo " Generating new key for owner ${account} and contract address ${contract_address} "
906
+
907
+ generate_new_key " ${contract_address} "
908
+
909
+ local partkey_info
910
+ local voting_key
911
+ local selection_key
912
+ local first_round
913
+ local last_round
914
+ local key_dilution
915
+ local stateproof_key
916
+
917
+ partkey_info=$( get_most_recent_participation_key_details " ${contract_address} " )
918
+ voting_key=$( jq -r ' .voting_key' <<< " ${partkey_info}" )
919
+ selection_key=$( jq -r ' .selection_key' <<< " ${partkey_info}" )
920
+ first_round=$( jq -r ' .first_round' <<< " ${partkey_info}" )
921
+ last_round=$( jq -r ' .last_valid' <<< " ${partkey_info}" )
922
+ key_dilution=$( jq -r ' .key_dilution' <<< " ${partkey_info}" )
923
+ stateproof_key=$( jq -r ' .stateproof_key' <<< " ${partkey_info}" )
924
+
925
+ execute_interactive_docker_command " /node/bin/goal clerk send -a 1000 -f ${account} -t ${contract_address} --out=/tmp/payment.txn"
926
+ execute_interactive_docker_command " /node/bin/goal app call --app-id ${contract_id} --from ${account} --app-arg 'b64:zSTeiA==' --app-arg 'b64:${voting_key} ' --app-arg 'b64:${selection_key} ' --app-arg 'int:${first_round} ' --app-arg 'int:${last_round} ' --app-arg 'int:${key_dilution} ' --app-arg 'b64:${stateproof_key} ' --out=/tmp/app_call.txn"
927
+
928
+ execute_docker_command " cat /tmp/{payment,app_call}.txn > /tmp/combined.txn"
929
+ execute_interactive_docker_command " /node/bin/goal clerk group -i /tmp/combined.txn -o /tmp/grouped.txn > /dev/null"
930
+ execute_interactive_docker_command " /node/bin/goal clerk split -i /tmp/grouped.txn -o /tmp/split.txn > /dev/null"
931
+ execute_interactive_docker_command " /node/bin/goal clerk sign -i /tmp/split-0.txn -o /tmp/signed-0.txn"
932
+ execute_interactive_docker_command " /node/bin/goal clerk sign -i /tmp/split-1.txn -o /tmp/signed-1.txn"
933
+ execute_docker_command " cat /tmp/signed-{0,1}.txn > /tmp/signed-combined.txn"
934
+ execute_interactive_docker_command " /node/bin/goal clerk rawsend -f /tmp/signed-combined.txn"
935
+
936
+ if [[ -n ${participation_key_id} ]]; then
937
+ execute_interactive_docker_command " /node/bin/goal account deletepartkey --partkeyid ${participation_key_id} "
938
+ fi
939
+ else
940
+ local existing_expiration_date
941
+ existing_expiration_date=$( get_participation_expiration_eta " ${part_vote_lst} " " ${last_committed_block} " )
942
+
943
+ echo " Current staking participation key for owner ${account} , and"
944
+ echo " contract address ${contract_address} is expected to expire at: ${existing_expiration_date} "
945
+ echo " This is above the required threshold of 417,104 blocks / ~14 days."
946
+ echo " No new staking participation key will be generated."
947
+ echo " "
948
+ fi
949
+ done
950
+
951
+ echo " "
952
+ echo " ${bold} To learn how to use your staking contract visit: https://staking.voi.network${normal} "
953
+ else
954
+ display_banner " No staking contract detected"
955
+
956
+ echo " No staking contracts found for owner ${account} . To learn more visit: https://staking.voi.network"
957
+ fi
958
+ fi
959
+ done
960
+ fi
961
+ }
962
+
741
963
change_account_online_status () {
742
964
local account
743
965
account=$1
@@ -770,6 +992,8 @@ join_as_new_user() {
770
992
771
993
account_status=$( execute_docker_command " /node/bin/goal account dump -a ${account} " | jq -r .onl)
772
994
995
+ check_staking_accounts
996
+
773
997
# # This step is late in the process and does require a restart of the service to take effect.
774
998
# # Container ID from verify_node_running will have to be re-fetched if any use of the node is to be done after this point.
775
999
# # Intentionally not doing this here to avoid confusion.
@@ -1171,7 +1395,7 @@ check_minimum_requirements
1171
1395
1172
1396
if [[ ${new_network} -eq 1 ]]; then
1173
1397
get_container_id
1174
- ensure_accounts_are_offline
1398
+ ensure_accounts_are_offline " ${existing_network} "
1175
1399
fi
1176
1400
1177
1401
get_telemetry_name
@@ -1322,6 +1546,8 @@ else
1322
1546
join_as_new_user
1323
1547
fi
1324
1548
1549
+ check_staking_accounts
1550
+
1325
1551
migrate_host_based_voi_setup
1326
1552
1327
1553
display_banner " Welcome to Voi!"
0 commit comments