#!/usr/bin/env bash

# Trap CTRL-C to avoid background processes running
trap ctrl_c INT
ctrl_c() {
  # Clean the system
  kill -9 "$(pgrep 'sima')" >/dev/null 2>&1
  kill -9 "$(pgrep 'blockchain')" >/dev/null 2>&1
  sync
  exit -2
}
kill -9 "$(pgrep 'sima')" >/dev/null 2>&1
kill -9 "$(pgrep 'blockchain')" >/dev/null 2>&1

# Init vars
HOST="localhost"
# HARDCODED to reduce RAM impact all data is passed by pointers
NLP=1
SLP=1
POSITIONAL=()
while [[ $# -gt 0 ]]; do
  key="$1"

  case $key in
  -n | --nodes)
    TOT_SMH="$2"
    shift # past argument
    shift # past value
    ;;
  -t | --test)
    TEST="$2"
    shift # past argument
    shift # past value
    ;;
  -d | --debug)
    DEBUG="$2"
    echo "Debug value $DEBUG"
    shift
    shift
    ;;
  *) # unknown option
    POSITIONAL+=("$1") # save it in an array for later
    shift              # past argument
    ;;
  esac
done
set -- "${POSITIONAL[@]}" # restore positional parameters

if [[ -n $1 || -z ${TOT_SMH} ]]; then
  echo "Illegal number of parameters"
  echo "USAGE: ./run-blockchain --nodes|-n #SMH [--test|-t TESTNAME] [--debug|-d DEBUGCMD]"
  echo -e "\\t#SMH\\ttotal number of nodes to simulate"
  echo -e "\\t[TESTNAME] name of the test to execute: 51, selfish (optional)"
  echo -e "\\t[DEBUGCMD] used for injecting *trace commands (optional)"
  exit -1
fi

rm ./*.finished

source ./scripts_configuration.sh
cp ${CORPUS_DIRECTORY}/test-graph-cleaned-1.dot ${TRACE_DIRECTORY}/test_btc_test-graph-cleaned.dot
make clean
make

# Set sim parameters
export MIGRATION=0
export MFACTOR=1.2
export LOAD=0
export MAX_TTL=14 # DEFAULT=16
export FREERIDER="0"
export DISSEMINATION=1 # 0 = BROADCAST, 7 = DDF2
export BROADCAST_PROB_THRESHOLD=70
export FIXED_PROB_THRESHOLD=70
export DANDELION_STEPS_FLUFF_PHASE=12
export PROBABILITY_FUNCTION=2DIFFICULTY
export FUNC_COEFF_HIGHER=4
export FUNC_COEFF_LOWER=74
export FUNCTION_COEFFICIENT="$FUNC_COEFF_HIGHER.$FUNC_COEFF_LOWER"
export NUMBER_HEADS=10
export INTERMEDIATE_STEPS=6 #after (INTERMEDIATE_STEPS - 1) steps of the simulation just for receiving messages you try to mine a block, usually slightly larger than diameter
export END_CLOCK=$((5000 * $INTERMEDIATE_STEPS)) #5000 steps in which it's possible to mine a block, the others are just to propagate messages
export MINERS_COUNT=60 # Percentage of miners
export DIFFICULTY=$(http --json https://api.blockchain.info/stats | jq -r '.difficulty')
export GLOBAL_HASHRATE=$(printf %.0f000000000 "$(http --json https://api.blockchain.info/stats | jq -r '.hash_rate')")
# other source: https://bitcoinwisdom.com/bitcoin/difficulty
export DIFFICULTY=6489747252517
export GLOBAL_HASHRATE=43983561622000000000 # in H/s
python -c "print($GLOBAL_HASHRATE * 600 / (pow(2,32) * $DIFFICULTY))"

###########################################################################################
echo "BLOCKCHAIN SIMULATION standard batch..."
echo "NETWORK DIFFICULTY: ${DIFFICULTY}"
echo "NETOWRK HASHRATE: ${GLOBAL_HASHRATE}"

# Partitioning the #SMH among the available LPs
SMH=$((TOT_SMH / NLP))

###########################################################################################
# Find best parameters (throwaway)
###########################################################################################
find_best_params() {
  FUNC_COEFF_HIGHER="1 2 3 4 5 6 7 8 9 10"
  FUNC_COEFF_LOWER="10 20 30 40 50 60 70 80 90"
  TTLS="1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16"
  for fcoeff_higher in $FUNC_COEFF_HIGHER; do
    for fcoeff_lower in $FUNC_COEFF_LOWER; do
      for ttl in $TTLS; do
        export FUNCTION_COEFFICIENT="$fcoeff_higher.$fcoeff_lower"
        export MAX_TTL="${ttl}"
        ./sima "$NLP" /dev/null 2>&1 &
        sleep 1
        $DEBUG ./blockchain "$NLP" $SMH ${TRACE_DIRECTORY}/test_btc_ --attacker "${i}" >"./outputs/$fcoeff_higher.$fcoeff_lower-${ttl}.txt"
        sleep 5
      done
    done
  done
  exit 1
}
###########################################################################################

###########################################################################################
# RUN TEST 51%: 100 runs of increasing attacker's hashrate
###########################################################################################

# Normal Run
if [[ -z "$TEST" ]]; then
  # SImulation MAnager (SIMA) execution
  echo "Start time: $(date)"
  if [ $HOST == "$HOSTNAME" ] || [ $HOST == "localhost" ]; then
    echo "Starting SIMA (waiting for $NLP LPs)..."
    ./sima "$NLP" &
  fi
  $DEBUG ./blockchain "$NLP" $SMH ${TRACE_DIRECTORY}/test_btc_ > "test_normal.txt"
  echo "End time: $(date)"
  exit -1
fi

# Attack 51%
if [[ "${TEST}" == "51" ]]; then
  mkdir -p "./outputs"
  for i in {1..100}; do
    # SImulation MAnager (SIMA) execution
    echo "Start time: $(date)"
    if [ $HOST == "$HOSTNAME" ] || [ $HOST == "localhost" ]; then
      echo "Starting SIMA (waiting for $NLP LPs)..."
      ./sima "$NLP" &
    fi
    echo -e "Testing 51% \\e[33m\\e[5m${i}/100\\e[0m"
    $DEBUG ./blockchain "$NLP" $SMH ${TRACE_DIRECTORY}/test_btc_ --attacker ${i} >"./outputs/test-51-${i}.txt"
    echo "End time: $(date)"
  done
  rm ./*.finished
  exit -1
fi

# Selfish Mining
if [[ "${TEST}" == "selfish" ]]; then
   mkdir -p "./outputs"
   for i in {1..100}; do
  #for i in `seq 1 5 100`; do
    # SImulation MAnager (SIMA) execution
    echo "Start time: $(date)"
    if [ $HOST == "$HOSTNAME" ] || [ $HOST == "localhost" ]; then
      echo "Starting SIMA (waiting for $NLP LPs)..."
      ./sima "$NLP" &
    fi
    echo -e "Testing Selfish Mining \\e[33m\\e[5m${i}/100\\e[0m"
    $DEBUG ./blockchain "$NLP" $SMH ${TRACE_DIRECTORY}/test_btc_ --selfish ${i} > "./outputs/test-Selfish-${i}.txt"
    echo "End time: $(date)"
  done
  rm ./*.finished
  exit -1
fi

#DoS
if [[ "${TEST}" == "dos" ]]; then
	if grep -E '^#define DOS' sim-parameters.h; then
     ./getAttackers.py $TOT_SMH > 'attackers.txt'
	   mkdir -p "./outputs"
	   for i in {1..99}; do
	  # SImulation MAnager (SIMA) execution
	   echo "Start time: $(date)"
	   if [ $HOST == "$HOSTNAME" ] || [ $HOST == "localhost" ]; then
	     echo "Starting SIMA (waiting for $NLP LPs)..."
	     ./sima "$NLP" &
	   fi
	   echo -e "Testing DoS \\e[33m\\e[5m${i}/100\\e[0m"
	   $DEBUG ./blockchain "$NLP" $SMH ${TRACE_DIRECTORY}/test_btc_ --dos "${i}" > "./outputs/test-dos-${i}.txt"
	   echo "End time: $(date)"
	     done
	else
		echo "Please enable DOS in sim-parameters.h"
	fi
  rm ./*.finished
  exit -1
fi

: <<'END'
END
