verify 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. #!/bin/bash
  2. set -euo pipefail
  3. function usage() {
  4. cat<<-EOF >&2
  5. Usage:
  6. $(basename "$0") [-h] [-n network] [-s svm] <.so file> <account address> -- Verify that the deployed on-chain bytecode matches the local object file
  7. where:
  8. -h show this help text
  9. -n set the network (mainnet, testnet, devnet. defaults to \$NETWORK if set)
  10. -s set the svm (solana, fogo. defaults to \$SVM if set)
  11. EOF
  12. exit 1
  13. }
  14. network=""
  15. if [[ -n "${NETWORK:-}" ]]; then
  16. network="$NETWORK"
  17. fi
  18. svm=""
  19. if [[ -n "${SVM:-}" ]]; then
  20. svm="$SVM"
  21. fi
  22. while getopts ':n:s:h' option; do
  23. case "$option" in
  24. h) usage
  25. ;;
  26. n) network=$OPTARG
  27. ;;
  28. s) svm=$OPTARG
  29. ;;
  30. :) printf "missing argument for -%s\n" "$OPTARG" >&2
  31. usage
  32. ;;
  33. \?) printf "illegal option: -%s\n" "$OPTARG" >&2
  34. usage
  35. ;;
  36. esac
  37. done
  38. shift $((OPTIND - 1))
  39. # Set moniker based on SVM and network
  40. case "$svm" in
  41. solana)
  42. case "$network" in
  43. mainnet) moniker="m";;
  44. testnet) moniker="d";;
  45. devnet) moniker="l";;
  46. *) printf "Network not set. Specify with -n\n" >&2
  47. usage
  48. ;;
  49. esac
  50. ;;
  51. fogo)
  52. case "$network" in
  53. mainnet) moniker="https://mainnet.fogo.io";;
  54. testnet) moniker="https://testnet-alt.fogo.io";;
  55. *) printf "Fogo only supports mainnet and testnet. Specify with -n\n" >&2
  56. usage
  57. ;;
  58. esac
  59. ;;
  60. *) printf "SVM not set. Specify with -s\n" >&2
  61. usage
  62. ;;
  63. esac
  64. [ $# -ne 2 ] && usage
  65. obj_file=$1
  66. sol_addr=$2
  67. account_json=$(mktemp)
  68. account_dump=$(mktemp)
  69. # Grab account content as JSON
  70. solana account "$sol_addr" -u $moniker --output-file "$account_json" --output json-compact >/dev/null
  71. # decode the base64 account data to binary
  72. jq '.account.data[0]' "$account_json" | sed s/\"//g | base64 -d > "$account_dump"
  73. # The first 37 bytes are irrelevant, the actual ELF object code starts after,
  74. # so we drop these bytes. Presumably those bytes correspond to an encoded rust
  75. # enum constructor?
  76. # Set the block size to 37 bytes and skip the first block.
  77. dd bs=37 skip=1 if="$account_dump" of=/tmp/bytecode.dump 2>/dev/null
  78. hash1=$(sha256sum /tmp/bytecode.dump | cut -f1 -d' ')
  79. hash2=$(sha256sum "$obj_file" | cut -f1 -d' ')
  80. echo "Deployed bytecode hash (on $network):"
  81. echo "$hash1"
  82. echo "$obj_file hash:"
  83. echo "$hash2"
  84. if [ "$hash1" == "$hash2" ]; then
  85. printf "\033[0;32mSuccessfully verified\033[0m\n";
  86. exit 0;
  87. else
  88. printf "\033[0;31mFailed to verify\033[0m\n" >&2;
  89. echo "JSON: $account_json" >&2;
  90. echo "Dump: $account_dump" >&2;
  91. exit 1;
  92. fi