#!/usr/bin/env bash # Masternode announcement helper script #set -o errexit set -o pipefail set -o nounset IMAGE="${IMAGE:-sevenswen/crypticcoinubuntu18.04}" NODE_DIR=${NODE_DIR:-"$HOME/.crypticcoin"} CONFIG_FILE=${CONFIG_FILE:-"$NODE_DIR/crypticcoin.conf"} NETWORK_PATH="" if grep -q "^testnet=1" $CONFIG_FILE 2>/dev/null; then NETWORK_PATH=testnet3/ fi if grep -q "^regtest=1" $CONFIG_FILE 2>/dev/null; then NETWORK_PATH=regtest/ fi DEBUG_LOG=$NODE_DIR/${NETWORK_PATH}debug.log ERRFILE=/tmp/err.$$ MAXCONNECTIONS=64 CONTAINER=cryptic_by_$USER function help { cat << EOF run_d Run docker container in 'detached' mode run_i Run docker container in 'interactive' mode stop_d Stop docker container (just by interrupting 'crypticcoind' process inside) ensure_stopped Ensures container has been stopped completely wait_run Waits until node run ('crypticcoind' process started). Container should be started by 'run_d' or 'run_i' before wait_init Waits until node init and ready for 'cli' commands d_exec [args ...] Execute command in container (for example, 'd_exec ps ax') cli [args ...] Execute 'cli' command mn_announce Try to announce masternode set_autostart Place command in /etc/cron.d/ to start node at system boot EOF } function d_exec { docker exec $CONTAINER "$@" } function cli { if [ "${1:-}" == "mn_announce" ]; then echo "Direct use of './tools cli mn_announce' is FORBIDDEN! Use './tools mn_announce' instead!" && return 1 fi d_exec crypticcoin-cli -datadir=/home/crypticuser/.crypticcoin "$@" } function run_d { docker run -d -e USER_ID=$(id -u $USER) -e GROUP_ID=$(id -g $USER) \ -v $HOME/.crypticcoin/:/home/crypticuser/.crypticcoin:rw \ -v $HOME/.crypticcoin-params/:/home/crypticuser/.crypticcoin-params:rw \ --rm -it --name $CONTAINER $IMAGE "$@" } function run_i { docker run -e USER_ID=$(id -u $USER) -e GROUP_ID=$(id -g $USER) \ -v $HOME/.crypticcoin/:/home/crypticuser/.crypticcoin:rw \ -v $HOME/.crypticcoin-params/:/home/crypticuser/.crypticcoin-params:rw \ --rm -it --name $CONTAINER $IMAGE "$@" } function set_autostart { echo "A password may be requested now to set cryptic node in autostart:" cronfile=/etc/cron.d/$CONTAINER if printf "@reboot $USER docker run -d -e USER_ID=$(id -u $USER) -e GROUP_ID=$(id -g $USER) \ -v $HOME/.crypticcoin/:/home/crypticuser/.crypticcoin:rw \ -v $HOME/.crypticcoin-params/:/home/crypticuser/.crypticcoin-params:rw \ --rm -it --name $CONTAINER $IMAGE\n" | sudo tee ${cronfile} then echo "Autostart set in $cronfile" else echo "Set autostart failed!" fi } function stop_d { d_exec pkill -f "crypticcoind" 2>$ERRFILE } function is_emptynode { if [ -z "$(ls -A $NODE_DIR)" ]; then return 0 else return 1 fi } function ensure_stopped { for run in {1..3} do PSAX=$(d_exec ps ax 2>$ERRFILE) if cat $ERRFILE 2>/dev/null | grep -q "Error: No such container:" ; then return 0 fi if echo "$PSAX" | grep -q crypticcoind; then echo "Trying to stop 'crypticcoind'" stop_d sleep 5 continue else # other process is running, just stop whole container echo "Trying to stop container" docker stop $CONTAINER >/dev/null fi done echo "Can't stop $CONTAINER container, unknown error" return 1 } # Ensure crypticcoind in a container run: function wait_run { started=false for run in {1..10} do if d_exec ps ax >/dev/null 2>$ERRFILE; then started=true break else if cat $ERRFILE 2>/dev/null | grep -q -E "(Error response from daemon: Container .* is not running)|(Error: No such container:)" ; then echo "Waiting for container to start" sleep 2 continue fi fi done if $started; then echo "Check if $CONTAINER container started: OK" else echo "Run docker image $IMAGE failed!" cat $ERRFILE return 1 fi while d_exec ps ax 2>$ERRFILE | grep -q fetch-params.sh do echo "Waiting for initial fetching sprout/sapling params. Keep calm." sleep 2 done while ! d_exec ps ax 2>$ERRFILE | grep -q "crypticcoind" do if cat $ERRFILE 2>/dev/null | grep -q "Error: No such container:"; then echo "Waiting for crypticcoind: unknown error" return 1 fi echo "Waiting for 'crypticcoind' start" sleep 2 done echo "'crypticcoind' started" } function wait_init { # Wait for initial blocks download: ERR_COUNT=0 loading=$(cli isinitialblockdownload 2>$ERRFILE) while [ "${loading}" != "false" ] do if [ "${loading}" == "true" ] ; then blocks=$(cli getblockcount) echo "Waiting initial blocks download... (block: $blocks)" sleep 5 elif cat $ERRFILE 2>/dev/null | grep -q -E "Loading addresses|Verifying wallet|Loading block index|Rewinding blocks if needed|Verifying blocks|Zapping|Loading wallet|Rescanning|Pruning blockstore|Activating best chain" then echo "$(tail -n 1 $ERRFILE)" sleep 2 elif cat $ERRFILE 2>/dev/null | grep -q "Error: No such container:"; then # Everything was fine, but node has exited. Why? Reindex?? if tail -n 20 $DEBUG_LOG | grep -q -E "Aborted block database rebuild|reindex"; then echo "It looks like reindex is needed. Try again please!" else echo "Unknown error!" fi return 1 else if ! cat $ERRFILE 2>/dev/null | grep -q "make sure server is running" ; then echo "$(tail -n 1 $ERRFILE)" fi if [ "$ERR_COUNT" -lt 20 ]; then echo "$(tail -n 1 $ERRFILE)" let ERR_COUNT++ sleep 2 else echo "Unknown error!" cat $ERRFILE return 1 fi fi loading=$(cli isinitialblockdownload 2>$ERRFILE) done } function check_address { eval $1_auto=false warn="" if [[ "${!1}" == "" && "${1}" != "operatorRewardAddress" ]] then if result=$(cli getnewaddress) then eval $1=$result warn="(autogenerated)" eval $1_mine=true fi else # don't check operatorRewardAddress if it is empty if [[ "${!1}" != "" ]] then valjson=$(cli validateaddress ${!1}) if ! $(echo ${valjson} | grep -q -E "\"isvalid\": true") then echo "Invalid $1! (=${!1}) Exit!" return 1 fi if $(echo ${valjson} | grep -q -E "\"ismine\": true") then eval $1_mine=true else eval $1_mine=false warn="(doesn't belong to this wallet)" fi fi fi echo "$1 = ${!1} ${warn}" } function ensure_file_eol { # place "\n" at EOF only if not exist (if empty file - stay empty) # note, that it will be different for OS X sed -i -e '$a\' "$1" 2>/dev/null } function get_random_name { namestemp=$(mktemp) cat << EOF >$namestemp Abin Sur Abra Kadabra Adam Strange Alfred Pennyworth Amanda Waller Amazo Ambush Bug Amethyst Andrew Bennett Animal Man Animal-Vegetable-Mineral Man Aquagirl Aquaman Ares Artemis Atrocitus The Atom Azrael Aqualad Apache Chief Arsenal Archer Bane Batgirl Batman Batwoman Bat-Mite Beast Boy Bizarro Big Barda Billy Numerous Black Adam Black Beetle Black Canary Black Hand Black Lightning Black Manta Black Mask Blok Blue Beetle Blue Devil Booster Gold Bouncing Boy Brain Brainiac Brother Blood Bumblebee B'wana Beast Black Flash Black Vulcan Baby face Batman of Zur-en Arrh Bleez Bookwarm Cain Calendar Man Captain Atom Captain Boomerang Captain Comet Captain Carrot Captain Cold Captain Marvel Carol Ferris Catwoman Chameleon Boy Channel Cheetah Chemo Circe Clayface Cosmic Boy Cosmic King Cyborg Cyborg Superman Copperhead Crazy Quilt Colonel Hardy Condiment King Catman Clocking Darkseid Dawnstar Deadshot Deathstroke Desperaux Dr.Death Dr.Fate Dr.Light Dr.Manhattan Dr.Psycho Dr.Sivana Dolphin Doomsday Dream Girl Duo Damsel Dex-starr Dr.Phosphorus Elasti-Girl Element Lad Elongated Man Etrigan Enchantress Eraser Egghead Flash Fire Firefly The Fly Firestorm Frankenstein False Face Fury 6 Green Lantern Guy Gardner Green Arrow Gorilla Grodd Granny Goodness Giganta General Immortus General Zod Gizmo Great White Shark Gentleman Ghost Hercules Huntress Hawkgirl Hawkman Hawk and Dove Harley-Quinn Hush Heatwave Hellhound Hitman Haggor Humpty Dumpty Hugo Strange Ice Inertia Invisible Boy Jaguar Jimmy Olsen Jinx John Diggle Johnny Thunder John Stewart Joker Joker's Daughter Katana Kilowog Kid Flash Kid Devil Killer Croc Krypto Kryptonite Man Killer Frost Key Karate Kid Kite Man King Tut Killermoth Kabuki Twins Lady Blackhawk Larfleeze Lex Luthor Libra Light Lass Lightning Lightning Lad Lightning Lord Livewire Lobo Louie The Lilac Lagoon Boy Martian Manhunter Mr.Terrific Mon-El Metamorpho Metal Men Man-Bat Metallo Mr.Mxyzsptlk Mirror master Mad Hatter Mongul Mera Mr.Freeze Mr.Mind Miss Martian Madame Rouge Monseiur Mallah Music Meister Mas y Menos Mammoth Mother Mae Eye Mr.Camera Ministrel March Harriet Magpie Mime Maxie Zeus Nightwing Oracle Ocean Master Outsider Orion Omac Brother Eye Orca Power Girl Poison Ivy Penguin Parallax Plastique Parasite Plastic Man Princess Projecta Polka Dot Man Prometheus Question Queen Bee Ragdoll Ra's Al Ghul Ravager Raven Razorsharp Red Bee Red Hood Red Tornado Red X Riddler Rip Hunter Robin Rocket Red Robotman Reverse Flash Ratchet Ratcatcher Ragman Static Shock Sandman Superman Supergirl and Streaky Sinestro Star Girl Scarecrow Steel Spectre Shark King Starfire Superboy Spoiler Solomon Grundy Shazam Simon Shadow Thief Shade Swamp Thing Static Shock See-More Saturn Girl Saturn Queen Sun Boy Shadow Lass Saint Walker Shame Skallox Samurai Sweet tooth Siren Simon the pieman Starfire Thunder Tarzan Two-Face Trickster Trigon Tweedle Dee and Tweedle Dum Toyman Timber Wolf Turtle Tarantula Ultra-Humanite Ultra Boy Vandal Savage Ventriloquist and Scarface Vixen Vibe Veom Vice Weather Wizard Wildcat Wildebeest Wildfire Wonder Girl Wonder Woman White Canary The Wasp Zatanna Zatara Zoom Zarrell Zodiac master Zilius Zox Zebra Man Zod Anatole Bebeck Bolshoi Cassiopea Cossack Creote Fireball Firebird Fusion Hammer KGBeast Molotov Morozko Perun Pozhar Pravda Proletariat Red Star Red Son Superman Rocket Red Brigade Rusalka Anya Savenlovich Sickle Snow Owl Stalnoivolk Tundra Valentina Vostok Vikhor EOF lines=$(cat $namestemp | wc -l) # "lines-1" cause it always ends with extra \n when using cat </dev/null ; then echo "Checks 'docker' installed: OK" else echo "Please install docker and try again" return 1 fi # remember, 1 means 'false' in bash NEED_REINDEX=false if is_emptynode; then echo "Start with empty node" else echo "Start with non-empty node" ensure_stopped || return 1 if grep -q -E "(^masternode_operator)|(^masternode_owner)" $CONFIG_FILE; then echo "It looks like you are a masternode already! Are you sure you want to create new one?" echo "Delete 'masternode_operator' and 'masternode_owner' strings from $CONFIG_FILE and try again!" return 1 fi if grep -q "^maxconnections" $CONFIG_FILE; then sed -i -e "s/^maxconnections=.*$/maxconnections=$MAXCONNECTIONS/" $CONFIG_FILE else ensure_file_eol $CONFIG_FILE printf "maxconnections=$MAXCONNECTIONS\n" >> $CONFIG_FILE fi if grep -q "^txindex" $CONFIG_FILE; then if grep -q "^txindex=0" $CONFIG_FILE; then echo "Changing txindex=0 to txindex=1" sed -i -e 's/^txindex=.*$/txindex=1/' $CONFIG_FILE NEED_REINDEX=true fi else echo "Adding txindex=1" ensure_file_eol $CONFIG_FILE printf "txindex=1\n" >> $CONFIG_FILE NEED_REINDEX=true fi if tail -n 20 $DEBUG_LOG | grep -q "Aborted block database rebuild"; then echo "Forcing reindex" NEED_REINDEX=true fi fi # Starting docker container if $NEED_REINDEX; then run_i fetch-params.sh run_d crypticcoind -reindex else run_d fi wait_run && wait_init || return 1 ############################################################## echo "Trying to announce masternode with this parameters:" echo echo "name = ${name}" check_address ownerAuthAddress || return 1 check_address operatorAuthAddress || return 1 check_address ownerRewardAddress || return 1 # We don't generate operatorRewardAddress, but check it! check_address operatorRewardAddress || return 1 check_address collateralAddress || return 1 echo "operatorRewardRatio = ${operatorRewardRatio}" echo read -p "Double check your addresses! Press [Enter] key to start or [Ctrl+C] to cancel..." # run through 'd_exec' cause 'cli mn_announce' is forbidden if id=$(d_exec crypticcoin-cli -datadir=/home/crypticuser/.crypticcoin mn_announce [] "{\ \"name\":\"${name}\",\ \"ownerAuthAddress\":\"${ownerAuthAddress}\",\ \"operatorAuthAddress\":\"${operatorAuthAddress}\",\ \"ownerRewardAddress\":\"${ownerRewardAddress}\",\ \"operatorRewardAddress\":\"${operatorRewardAddress}\",\ \"operatorRewardRatio\":\"${operatorRewardRatio}\",\ \"collateralAddress\":\"${collateralAddress}\"\ }" 2>$ERRFILE) then echo "Pause for 10 seconds to ensure tx was broadcasted... " sleep 10 echo "Restarting..." ensure_stopped || return 1 ensure_file_eol $CONFIG_FILE # saving config: if ${ownerAuthAddress_mine} then printf "masternode_owner=$ownerAuthAddress\n" >> $CONFIG_FILE fi if ${operatorAuthAddress_mine} then printf "masternode_operator=$operatorAuthAddress\n" >> $CONFIG_FILE fi if ${ownerAuthAddress_mine} || ${operatorRewardAddress_mine} then printf "# This is not nesessary, but handy for lookup:\n" >> $CONFIG_FILE printf "#masternode_id=$id\n" >> $CONFIG_FILE printf "#masternode_name=$name\n" >> $CONFIG_FILE fi run_d echo "Congratulations! You have announced new masternode" echo "with ID = $id" echo "You can get additional info after block will be mined using:" echo "./tools cli mn_list [\\\"$id\\\"] true" echo if ! ${ownerAuthAddress_mine} then echo "Warning: ownerAuthAddress ($ownerAuthAddress) is not yours!" echo "Make sure to add the following statements in your owner's cyrpticcoin.conf file" echo echo " masternode_owner=$ownerAuthAddress" echo " txindex=1" echo echo "Save file and restart the wallet. Next choose settings option 'CHECK' and reindex! (or restart the node with '-reindex' option from console)" echo fi if ! ${operatorAuthAddress_mine} then echo "Warning: operatorAuthAddress ($operatorAuthAddress) is not yours!" echo "Make sure to add the following statements in your operator's cyrpticcoin.conf file" echo echo " masternode_operator=$operatorAuthAddress" echo " txindex=1" echo echo "Save file and restart the wallet. Next choose settings option 'CHECK' and reindex! (or restart the node with '-reindex' option from console)" echo fi echo echo "Operator! Don't forget to KEEP NODE RUNNING, or you'll get dismissed by the quorum!" echo if ${ownerAuthAddress_mine} || ${operatorRewardAddress_mine} then set_autostart fi else if grep "Insufficient funds!" $ERRFILE ; then echo "You should have at least $(cli mn_estimateannouncementfee) for fee + 1000000 CRYP for collateral on transparent addresses to announce a masternode!" echo "Now you have only $(cli getbalance)" else echo "Error: $(tail -n 1 $ERRFILE)" fi ensure_stopped || return 1 echo "Done" fi } "$@"