mirror of
https://github.com/EvernodeXRPL/sashimono.git
synced 2026-04-29 15:38:00 +00:00
245 lines
7.6 KiB
Bash
Executable File
245 lines
7.6 KiB
Bash
Executable File
#!/bin/bash
|
|
echo "Sashimono bootstrap contract upgrader."
|
|
echo "Execution lcl $1-$2"
|
|
|
|
archive_name="bundle.zip"
|
|
bootstrap_bin="bootstrap_contract"
|
|
install_script="install.sh"
|
|
patch_cfg="../patch.cfg"
|
|
patch_cfg_bk="../patch.cfg.bk"
|
|
contract_config="contract.config"
|
|
self_original_name="bootstrap_upgrade.sh" # Original name of this script before it was renamed to post_exec.sh
|
|
self_path=$(realpath $0) # Full path of this script.
|
|
self_name=$(basename $self_path) # File name of this script.
|
|
self_dir=$(dirname $self_path) # Parent path of this script.
|
|
|
|
# If field exists, append to patch json.
|
|
function append_string_field() {
|
|
local field=$1
|
|
local req=$2 # '1' if empty value not allowed.
|
|
val=$(jq ".$field" $contract_config)
|
|
if [ "$val" != "null" ] ; then
|
|
if [ "$req" == "1" ] && [ ${#val} -eq 2 ]; then # Empty means "" or ''
|
|
echo "$field cannot be empty."
|
|
return 1
|
|
fi
|
|
[ "${patch_json: -1}" != "{" ] && patch_json="$patch_json,"
|
|
patch_json="$patch_json${field##*.}:$val" # Append last . component field name with value.
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
# If field exists, append to patch json.
|
|
function append_gt0_field() {
|
|
local field=$1
|
|
local val=$(jq ".$field" $contract_config)
|
|
if [ "$val" != "null" ] ; then
|
|
if [ "$val" -lt 0 ]; then
|
|
echo "Invalid $field. Should be greater than zero."
|
|
return 1
|
|
fi
|
|
[ "${patch_json: -1}" != "{" ] && patch_json="$patch_json,"
|
|
patch_json="$patch_json${field##*.}:$val" # Append last . component field name with value.
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
# If field exists, append to patch json.
|
|
function append_range_field() {
|
|
local field=$1
|
|
local min=$2
|
|
local max=$3
|
|
|
|
local val=$(jq ".$field" $contract_config)
|
|
if [ "$val" != "null" ] ; then
|
|
if [ "$val" -le $min ] || [ "$val" -gt $max ]; then
|
|
echo "$field must be between $min and $max inclusive."
|
|
return 1
|
|
fi
|
|
[ "${patch_json: -1}" != "{" ] && patch_json="$patch_json,"
|
|
patch_json="$patch_json${field##*.}:$val" # Append last . component field name with value.
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
function upgrade() {
|
|
|
|
# Check for binary archive availability.
|
|
if [ ! -f "$archive_name" ]; then
|
|
echo "Required $archive_name not found. Exiting.."
|
|
return 1
|
|
fi
|
|
|
|
# Unzipping the archive.
|
|
|
|
# unzip command is used for zip extraction.
|
|
if ! command -v unzip &>/dev/null; then
|
|
echo "unzip utility not found. Exiting.."
|
|
return 1
|
|
fi
|
|
|
|
unzip -o $archive_name >>/dev/null
|
|
|
|
if [ -f "$contract_config" ]; then
|
|
|
|
# jq command is used for json manipulation.
|
|
if ! command -v jq &>/dev/null; then
|
|
echo "jq utility not found. Exiting.."
|
|
return 1
|
|
fi
|
|
|
|
# ********Config check********
|
|
|
|
# bin_path is the only field that we require. Everything else can be ommitted.
|
|
local bin_path=$(jq '.bin_path' $contract_config)
|
|
if [ "$bin_path" == "null" ] || [ ${#bin_path} -eq 2 ]; then # Empty means "" or ''
|
|
echo "bin_path cannot be empty"
|
|
return 1
|
|
elif [ ! -f "${bin_path:1:-1}" ]; then
|
|
echo "Given binary file: $bin_path not found"
|
|
return 1
|
|
else
|
|
patch_json="{bin_path:$bin_path"
|
|
fi
|
|
|
|
if ! append_string_field "bin_args" ; then
|
|
return 1
|
|
fi
|
|
|
|
if ! append_string_field "environment" ; then
|
|
return 1
|
|
fi
|
|
|
|
if ! append_string_field "version" 1 ; then
|
|
return 1
|
|
fi
|
|
|
|
if ! append_range_field "roundtime" 0 3600000 ; then
|
|
return 1
|
|
fi
|
|
|
|
if ! append_range_field "stage_slice" 0 33 ; then
|
|
return 1
|
|
fi
|
|
|
|
if ! append_gt0_field "max_input_ledger_offset" ; then
|
|
return 1
|
|
fi
|
|
|
|
local unl=$(jq '.unl' $contract_config)
|
|
if [ "$unl" != "null" ] ; then
|
|
unl_res=$(jq '.unl? | map(length == 66 and startswith("ed")) | index(false)' $contract_config)
|
|
if [ "$unl_res" != "null" ]; then
|
|
echo "Unl pubkey invalid. Invalid format. Key should be 66 in length with ed prefix"
|
|
return 1
|
|
fi
|
|
patch_json="$patch_json,unl:$unl"
|
|
fi
|
|
|
|
local consensus=$(jq '.consensus' $contract_config)
|
|
if [ "$consensus" != "null" ] ; then
|
|
if [ ${#consensus} -eq 2 ] || { [ "$consensus" != "\"public\"" ] && [ "$consensus" != "\"private\"" ]; }; then
|
|
echo "Invalid consensus flag. Valid values: public|private."
|
|
return 1
|
|
fi
|
|
patch_json="$patch_json,consensus:$consensus"
|
|
fi
|
|
|
|
local npl=$(jq '.npl' $contract_config)
|
|
if [ "$npl" != "null" ] ; then
|
|
if [ ${#npl} -eq 2 ] || { [ "$npl" != "\"public\"" ] && [ "$npl" != "\"private\"" ]; }; then
|
|
echo "Invalid npl flag. Valid values: public|private."
|
|
return 1
|
|
fi
|
|
patch_json="$patch_json,npl:$npl"
|
|
fi
|
|
|
|
local round_limits=$(jq '.round_limits' $contract_config)
|
|
if [ "$round_limits" != "null" ] ; then
|
|
patch_json="$patch_json,round_limits:{"
|
|
|
|
if ! append_gt0_field "round_limits.user_input_bytes" ; then
|
|
return 1
|
|
fi
|
|
if ! append_gt0_field "round_limits.user_output_bytes" ; then
|
|
return 1
|
|
fi
|
|
if ! append_gt0_field "round_limits.npl_output_bytes" ; then
|
|
return 1
|
|
fi
|
|
if ! append_gt0_field "round_limits.proc_cpu_seconds" ; then
|
|
return 1
|
|
fi
|
|
if ! append_gt0_field "round_limits.proc_mem_bytes" ; then
|
|
return 1
|
|
fi
|
|
if ! append_gt0_field "round_limits.proc_ofd_count" ; then
|
|
return 1
|
|
fi
|
|
|
|
patch_json="$patch_json}"
|
|
fi
|
|
|
|
patch_json="$patch_json}"
|
|
|
|
echo "All $contract_config checks passed."
|
|
|
|
echo "Updating $patch_cfg file."
|
|
local new_patch=$(jq -M ". + $patch_json" $patch_cfg) # Merge jsons
|
|
cp $patch_cfg $patch_cfg_bk # Make a backup.
|
|
echo "$new_patch" >$patch_cfg
|
|
|
|
# Remove contract.config after patch file update.
|
|
rm $contract_config
|
|
fi
|
|
|
|
# *****Install Script*****.
|
|
if [ -f "$install_script" ]; then
|
|
echo "$install_script found. Executing..."
|
|
|
|
chmod +x $install_script
|
|
./$install_script
|
|
installcode=$?
|
|
|
|
rm $install_script
|
|
|
|
if [ "$installcode" -eq "0" ]; then
|
|
echo "$install_script executed successfully."
|
|
return 0
|
|
else
|
|
echo "$install_script ended with exit code:$installcode"
|
|
return 1
|
|
fi
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
function rollback() {
|
|
# Restore self-script original name (Because hp requires it to be named post_exec.sh before execution)
|
|
cp $self_name $self_original_name
|
|
# Restore patch.cfg if backup exists
|
|
[ -f $patch_cfg_bk ] && mv $patch_cfg_bk $patch_cfg
|
|
# Remove all files except the ones we need.
|
|
find . -not \( -name $bootstrap_bin -or -name $self_original_name \) -delete
|
|
return 0
|
|
}
|
|
|
|
# Perform upgrade and rollback if failed.
|
|
upgrade
|
|
upgradecode=$?
|
|
|
|
pushd $self_dir > /dev/null 2>&1
|
|
if [ "$upgradecode" -eq "0" ]; then
|
|
# We have upgraded the contract successfully. Cleanup bootstrap contract resources.
|
|
echo "Upgrade successful. Cleaning up."
|
|
rm $archive_name $bootstrap_bin $patch_cfg_bk
|
|
else
|
|
echo "Upgrade failed. Rolling back."
|
|
rollback
|
|
fi
|
|
finalcode=$?
|
|
popd > /dev/null 2>&1
|
|
|
|
exit $finalcode
|