#!/bin/bash

set -euo pipefail

function usage() {
cat<<-EOF >&2
	Usage:
	  $(basename "$0") [-h] [-n network] <.so file> <account address> -- Verify that the deployed on-chain bytecode matches the local object file

	  where:
	      -h  show this help text
	      -n  set the network (mainnet, testnet, devnet. defaults to \$NETWORK if set)
EOF
exit 1
}

network=""
if [[ -n $NETWORK ]]; then
  network=$NETWORK
fi
while getopts ':hn:' option; do
  case "$option" in
    h) usage
       ;;
    n) network=$OPTARG
       ;;
    :) printf "missing argument for -%s\n" "$OPTARG" >&2
       usage
       ;;
   \?) printf "illegal option: -%s\n" "$OPTARG" >&2
       usage
       ;;
  esac
done
shift $((OPTIND - 1))

case "$network" in
  mainnet) moniker="m";;
  testnet) moniker="d";;
  devnet)  moniker="l";;
  *) printf "Network not set. Specify with -n\n" >&2
     usage
     ;;
esac

[ $# -ne 2 ] && usage
obj_file=$1
sol_addr=$2

account_json=$(mktemp)
account_dump=$(mktemp)

# Grab account content as JSON
solana account "$sol_addr" -u $moniker --output-file "$account_json" --output json-compact >/dev/null
# decode the base64 account data to binary
jq '.account.data[0]' "$account_json" | sed s/\"//g | base64 -d > "$account_dump"

# The first 37 bytes are irrelevant, the actual ELF object code starts after,
# so we drop these bytes. Presumably those bytes correspond to an encoded rust
# enum constructor?
# Set the block size to 37 bytes and skip the first block.
dd bs=37 skip=1 if="$account_dump" of=/tmp/bytecode.dump 2>/dev/null

hash1=$(sha256sum /tmp/bytecode.dump | cut -f1 -d' ')
hash2=$(sha256sum "$obj_file" | cut -f1 -d' ')

echo "Deployed bytecode hash (on $network):"
echo "$hash1"
echo "$obj_file hash:"
echo "$hash2"

if [ "$hash1" == "$hash2" ]; then
  printf "\033[0;32mSuccessfully verified\033[0m\n";
  exit 0;
else
  printf "\033[0;31mFailed to verify\033[0m\n" >&2;
  echo "JSON: $account_json" >&2;
  echo "Dump: $account_dump" >&2;
  exit 1;
fi
