├── .gitmodules ├── Dockerfile ├── Keccak256.php ├── README.md ├── assetchains_balance.sh ├── assetchains_height.sh ├── assetchains_loop.sh ├── assetchains_validate.sh ├── assetchains_walletsize.sh ├── autosplit-3rd.sh ├── autosplit-new.sh ├── bip32-test.php ├── bip32 ├── bip32.py ├── bip32_muun.md ├── bip32_muun.py ├── kdf_internal_key.py ├── muun_address.jpg ├── muun_emergency_kit.jpg └── requirements.txt ├── block_reward.php ├── check-data-folders.sh ├── check-nn-balances-zebra.sh ├── checkseed.sh ├── cleanwallets-mainnet.sh ├── coinsupply.php ├── createrawtx.sh ├── daemons-restart.sh ├── debian_build.sh ├── debian_build_gcc8.sh ├── dns-seeder-update-cloudflare.sh ├── dns-seeder-update-gandi.sh ├── docker_run_php.sh ├── docs ├── creating-a-vm-for-notarizing-3rd-party-on-headless-server.md ├── secure-iguana-password-01.png └── secure-iguana-password.md ├── estimate-blocks.py ├── gen_notaries_json.php ├── genkomodo.php ├── genkomodo.txt ├── genpos64.php ├── get-checkpoints.py ├── get-kmd-address.sh ├── getcheckpoints.sh ├── getnet.sh ├── hf-countdown.html ├── iguana_active.sh ├── iguana_checkio.sh ├── iguana_checkip.sh ├── images ├── autosplit.png └── genkomodo.png ├── lockutxo.sh ├── lockutxo_debug.sh ├── make_bootstrap.sh ├── make_bootstrap_3p.sh ├── notaries.php ├── notaries_addresses.php ├── notaries_pool_s8.php ├── notarizations_count.php ├── notarystats_html.sh ├── report_alive.sh ├── resend_funds.sh ├── resend_funds_all.sh ├── restart_daemons.sh ├── restart_kmd_daemons.sh ├── sendawaynn.sh ├── sendawaynn_auto.sh ├── sendawaynn_fee.sh ├── sendawaynn_subsidy.sh ├── sendfromaddress.sh ├── split_nn.sh ├── split_nn_btc.sh ├── split_nn_sapling.sh ├── subsidy-3p.php ├── tc_ens192.sh ├── transfer_balance.sh ├── update-motd.d ├── 98-mymotd └── 99-whoami-nn ├── wallet_reset_ac.sh ├── z ├── Curve25519.php ├── sha256f.php ├── z.txt └── zkey.php └── zip-0243-test-vector-3.js /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "BitcoinECDSA.php"] 2 | path = BitcoinECDSA.php 3 | url = https://github.com/DeckerSU/BitcoinECDSA.php 4 | branch = master 5 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:16.04 2 | LABEL Description="Install php7.0" 3 | RUN apt -y -qq update && apt -y -qq install php7.0-gmp php7.0 php7.0-mbstring 4 | -------------------------------------------------------------------------------- /Keccak256.php: -------------------------------------------------------------------------------- 1 | > 15)) & (0xFFFF)), 46 | $bc[($i + 4) % 5][1] ^ ((($bc[($i + 1) % 5][1] << 1) | ($bc[($i + 1) % 5][2] >> 15)) & (0xFFFF)), 47 | $bc[($i + 4) % 5][2] ^ ((($bc[($i + 1) % 5][2] << 1) | ($bc[($i + 1) % 5][3] >> 15)) & (0xFFFF)), 48 | $bc[($i + 4) % 5][3] ^ ((($bc[($i + 1) % 5][3] << 1) | ($bc[($i + 1) % 5][0] >> 15)) & (0xFFFF)) 49 | ]; 50 | for ($j = 0; $j < 25; $j += 5) { 51 | $st[$j + $i] = [ 52 | $st[$j + $i][0] ^ $t[0], 53 | $st[$j + $i][1] ^ $t[1], 54 | $st[$j + $i][2] ^ $t[2], 55 | $st[$j + $i][3] ^ $t[3] 56 | ]; 57 | } 58 | } 59 | 60 | // Rho Pi 61 | $t = $st[1]; 62 | for ($i = 0; $i < 24; $i++) { 63 | $j = self::$keccakf_piln[$i]; 64 | $bc[0] = $st[$j]; 65 | $n = self::$keccakf_rotc[$i] >> 4; 66 | $m = self::$keccakf_rotc[$i] % 16; 67 | $st[$j] = [ 68 | ((($t[(0+$n) %4] << $m) | ($t[(1+$n) %4] >> (16-$m))) & (0xFFFF)), 69 | ((($t[(1+$n) %4] << $m) | ($t[(2+$n) %4] >> (16-$m))) & (0xFFFF)), 70 | ((($t[(2+$n) %4] << $m) | ($t[(3+$n) %4] >> (16-$m))) & (0xFFFF)), 71 | ((($t[(3+$n) %4] << $m) | ($t[(0+$n) %4] >> (16-$m))) & (0xFFFF)) 72 | ]; 73 | $t = $bc[0]; 74 | } 75 | 76 | // Chi 77 | for ($j = 0; $j < 25; $j += 5) { 78 | for ($i = 0; $i < 5; $i++) { 79 | $bc[$i] = $st[$j + $i]; 80 | } 81 | for ($i = 0; $i < 5; $i++) { 82 | $st[$j + $i] = [ 83 | $st[$j + $i][0] ^ ~$bc[($i + 1) % 5][0] & $bc[($i + 2) % 5][0], 84 | $st[$j + $i][1] ^ ~$bc[($i + 1) % 5][1] & $bc[($i + 2) % 5][1], 85 | $st[$j + $i][2] ^ ~$bc[($i + 1) % 5][2] & $bc[($i + 2) % 5][2], 86 | $st[$j + $i][3] ^ ~$bc[($i + 1) % 5][3] & $bc[($i + 2) % 5][3] 87 | ]; 88 | } 89 | } 90 | 91 | // Iota 92 | $st[0] = [ 93 | $st[0][0] ^ $keccakf_rndc[$round][0], 94 | $st[0][1] ^ $keccakf_rndc[$round][1], 95 | $st[0][2] ^ $keccakf_rndc[$round][2], 96 | $st[0][3] ^ $keccakf_rndc[$round][3] 97 | ]; 98 | } 99 | } 100 | 101 | private static function keccak32($input, $capacity, $outputlength, $suffix, $raw_output) 102 | { 103 | $capacity /= 8; 104 | $inlen = \mb_strlen($input, '8bit'); 105 | $rsiz = 200 - 2 * $capacity; 106 | $rsizw = $rsiz / 8; 107 | $st = []; 108 | for ($i = 0; $i < 25; $i++) { 109 | $st[] = [0, 0, 0, 0]; 110 | } 111 | for ($in_t = 0; $inlen >= $rsiz; $inlen -= $rsiz, $in_t += $rsiz) { 112 | for ($i = 0; $i < $rsizw; $i++) { 113 | $t = unpack('v*', \mb_substr($input, $i * 8 + $in_t, 8, '8bit')); 114 | $st[$i] = [ 115 | $st[$i][0] ^ $t[4], 116 | $st[$i][1] ^ $t[3], 117 | $st[$i][2] ^ $t[2], 118 | $st[$i][3] ^ $t[1] 119 | ]; 120 | } 121 | self::keccakf32($st, self::KECCAK_ROUNDS); 122 | } 123 | $temp = \mb_substr($input, $in_t, $inlen, '8bit'); 124 | $temp = str_pad($temp, $rsiz, "\x0", STR_PAD_RIGHT); 125 | $temp[$inlen] = chr($suffix); 126 | $temp[$rsiz - 1] = chr(hexdec($temp[$rsiz - 1]) | 0x80); 127 | for ($i = 0; $i < $rsizw; $i++) { 128 | $t = unpack('v*', \mb_substr($temp, $i * 8, 8, '8bit')); 129 | $st[$i] = [ 130 | $st[$i][0] ^ $t[4], 131 | $st[$i][1] ^ $t[3], 132 | $st[$i][2] ^ $t[2], 133 | $st[$i][3] ^ $t[1] 134 | ]; 135 | } 136 | self::keccakf32($st, self::KECCAK_ROUNDS); 137 | $out = ''; 138 | for ($i = 0; $i < 25; $i++) { 139 | $out .= $t = pack('v*', $st[$i][3],$st[$i][2], $st[$i][1], $st[$i][0]); 140 | } 141 | $r = \mb_substr($out, 0, $outputlength / 8, '8bit'); 142 | return $raw_output ? $r: bin2hex($r); 143 | } 144 | 145 | private static function keccak($input, $capacity, $outputlength, $suffix, $raw_output) { 146 | return self::keccak32($input, $capacity, $outputlength, $suffix, $raw_output); 147 | } 148 | 149 | public static function hash($input, $mdlen, $raw_output = false) 150 | { 151 | if( !in_array($mdlen, [224, 256], true) ) { 152 | throw new \Exception('Unsupported Keccak256 Hash output size.'); 153 | } 154 | return self::keccak($input, $mdlen, $mdlen, 0x01, $raw_output); 155 | } 156 | 157 | public static function shake($input, $security_level, $outlen, $raw_output = false) 158 | { 159 | if( !in_array($security_level, [128, 256], true) ) { 160 | throw new \Exception('Unsupported Keccak256 Shake security level.'); 161 | } 162 | return self::keccak($input, $security_level, $outlen, 0x1f, $raw_output); 163 | } 164 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # komodo_scripts 2 | 3 | ## How to install and use genkomodo.php? 4 | 5 | `genkomodo.php` can be used for generate addresses and WIFs (private keys) from Agama / Iguana passphrase for a different coins. Coin params can be taken from `chainparams.cpp` of each coin, for example, for Komodo (KMD) needed params (pubkey_address, script_address, secret_key) located [here](https://github.com/jl777/komodo/blob/master/src/chainparams.cpp#L180). To add new coin in script we just need to fill it [here](https://github.com/DeckerSU/komodo_scripts/blob/411b9036be8dd75ca7ed2460d1c9ba6a0fd599c3/genkomodo.php#L126). 6 | 7 | ### Installation instructions 8 | 9 | Script can be used on any PC, but highly recommended to use separate offline PC for generating WIFs. 10 | 11 | ``` 12 | git clone https://github.com/DeckerSU/komodo_scripts 13 | cd komodo_scripts 14 | git submodule init 15 | git submodule update --init --recursive 16 | sudo apt install php7.2-cli php7.2-gmp php7.2-mbstring 17 | ``` 18 | 19 | ### How to run? 20 | 21 | ``` 22 | 1. edit genkomodo.php and fill your passphrase instead of $passphrase = "myverysecretandstrongpassphrase_noneabletobrute"; 23 | 2. php genkomodo.php 24 | 3. Write down WIFs and/or addresses taken from your passphrase. 25 | 4. Delete your passphrase from genkomodo.php for security purposes. 26 | 5. Import taken WIFs to coin daemons. 27 | ``` 28 | 29 | ### Example of output: 30 | 31 | ![](./images/genkomodo.png) 32 | 33 | 34 | ### FAQ 35 | 36 | - **Q.** Where should i find `Keccak256.php` needed by genkomodo.php script? 37 | **A.** You don't need to search it in other repoes, just clone this one, as described in installation steps. Repo contains all needed for genkomodo.php work. 38 | - **Q.** I have a Desktop version of Linux, is any GUI tool with same functionallity provided? 39 | **A.** Yes, it's called [address_gen](https://github.com/DeckerSU/address_gen) and have similar functionallity. Note, that php script can be used on server and desktop systems as well, but address_gen tool is only for desktop systems. Don't try to run it on server without gui installed. 40 | 41 | ## Run php scripts using docker 42 | 43 | ``` 44 | ./docker_run.sh genkomodo.php 45 | ``` 46 | ## Other scripts short description 47 | 48 | | Script | Description | 49 | | --- | --- | 50 | | ... | ... | -------------------------------------------------------------------------------- /assetchains_balance.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | init_colors() { 4 | RESET="\033[0m" 5 | BLACK="\033[30m" 6 | RED="\033[31m" 7 | GREEN="\033[32m" 8 | YELLOW="\033[33m" 9 | BLUE="\033[34m" 10 | MAGENTA="\033[35m" 11 | CYAN="\033[36m" 12 | WHITE="\033[37m" 13 | BRIGHT="\033[1m" 14 | DARKGREY="\033[90m" 15 | } 16 | 17 | show_balance () { 18 | # Function: show_balance 19 | # Description: Retrieves and displays the balance and UTXO count for a specified coin. 20 | # If no coin is provided, defaults to "KMD". 21 | # If a second parameter is provided, it is added to the komodo-cli command. 22 | # Parameters: 23 | # $1 - (Optional) Coin name (e.g., "KMD" for Komodo main chain or asset chain name) 24 | # $2 - (Optional) Additional parameter to pass to komodo-cli (e.g., account name) 25 | # Usage: 26 | # show_balance # Defaults to "KMD" 27 | # show_balance "XYZ" # For asset chain "XYZ" 28 | # show_balance "XYZ" "account1" # For asset chain "XYZ" with additional parameter "account1" 29 | 30 | # Assign the first argument to 'coin', defaulting to "KMD" if not provided 31 | local coin="${1:-KMD}" 32 | local param="$2" 33 | local ac_option="" 34 | local BALANCE="" 35 | local UTXOS="" 36 | 37 | # Validate coin name (only alphanumeric characters and underscores) 38 | if [[ ! "$coin" =~ ^[A-Za-z0-9_]+$ ]]; then 39 | echo -e "${RED}Error:${RESET} Invalid coin name '$coin'. Only alphanumeric characters and underscores are allowed." >&2 40 | return 1 41 | fi 42 | 43 | # Determine whether to use the -ac_name parameter 44 | if [[ "$coin" != "KMD" ]]; then 45 | ac_option="-ac_name=$coin" 46 | fi 47 | 48 | if [[ "$coin" == "GLEEC_OLD" ]]; then 49 | ac_option="-ac_name=GLEEC" 50 | fi 51 | 52 | # Construct the komodo-cli command for getbalance 53 | BALANCE=$($komodo_cli_binary $ac_option ${param:+$param} getbalance 2> /dev/null) 54 | 55 | # Check if the balance retrieval was successful 56 | if [[ $? -ne 0 ]]; then 57 | echo -e "${RED}Error:${RESET} Failed to retrieve balance for '$coin'. Please ensure the daemon is running and the coin name is correct." >&2 58 | return 1 59 | fi 60 | 61 | # Ensure 'pubkey' is set and properly formatted 62 | if [[ -z "$pubkey" ]]; then 63 | echo -e "${RED}Error:${RESET} 'pubkey' variable is not set. Please source pubkey.txt correctly." >&2 64 | return 1 65 | fi 66 | 67 | # Construct the expected scriptPubKey 68 | local expected_scriptPubKey="21${pubkey}ac" 69 | 70 | # If param is set and not empty, ${param:+$param} expands to the value of param, 71 | # If param is unset or empty, ${param:+$param} expands to nothing (i.e., it omits param). 72 | UTXOS=$($komodo_cli_binary $ac_option ${param:+$param} listunspent | jq --arg script "$expected_scriptPubKey" '[.[] | select(.generated == false and .amount == 0.0001 and .spendable == true and (.scriptPubKey == $script))] | length') 73 | 74 | if [[ $? -ne 0 ]]; then 75 | echo -e "${RED}Error:${RESET} Failed to retrieve UTXOs for '$coin'." >&2 76 | return 1 77 | fi 78 | 79 | # Compare BALANCE using jq 80 | if [[ $(jq -n --arg b "$BALANCE" '$b | tonumber > 10') == "true" ]]; then 81 | # BALANCE is greater than 10; display in green 82 | printf "[%-15s] [${GREEN}%15s${RESET}] [%5d]\n" "$coin" "$BALANCE" "$UTXOS" 83 | else 84 | # BALANCE is 10 or less; display normally 85 | printf "[%-15s] [%15s] [%5d]\n" "$coin" "$BALANCE" "$UTXOS" 86 | fi 87 | } 88 | 89 | # Function to source pubkey.txt from multiple locations 90 | source_pubkey() { 91 | local pubkey_file 92 | local found=0 93 | 94 | # Define the search order 95 | local search_paths=( 96 | "$HOME/komodo/src/pubkey.txt" 97 | "$HOME/KomodoOcean/src/pubkey.txt" 98 | "$HOME/pubkey.txt" 99 | ) 100 | 101 | # Iterate through the search paths 102 | for pubkey_file in "${search_paths[@]}"; do 103 | if [[ -f "$pubkey_file" ]]; then 104 | echo "Found pubkey.txt at: $pubkey_file" >&2 105 | source "$pubkey_file" 106 | found=1 107 | break 108 | fi 109 | done 110 | 111 | # Check if pubkey.txt was found and sourced 112 | if [[ "$found" -ne 1 ]]; then 113 | echo -e "${RED}Error:${RESET} pubkey.txt not found in any of the specified locations." >&2 114 | exit 1 115 | fi 116 | 117 | # Ensure that the pubkey environment variable is set 118 | if [[ -z "$pubkey" ]]; then 119 | echo -e "${RED}Error:${RESET} pubkey environment variable is not set after sourcing pubkey.txt." >&2 120 | exit 1 121 | fi 122 | 123 | echo -e "Pubkey: \"${pubkey}\"" 124 | } 125 | 126 | determine_komodo_cli() { 127 | local cli_path 128 | # Check system-wide installation 129 | cli_path=$(command -v komodo-cli 2>/dev/null) 130 | if [[ -x "$cli_path" ]]; then 131 | echo "Found system-wide komodo-cli at: $cli_path" >&2 132 | echo "$cli_path" 133 | return 0 134 | fi 135 | 136 | # Check in ~/komodo/src 137 | cli_path="$HOME/komodo/src/komodo-cli" 138 | if [[ -x "$cli_path" ]]; then 139 | echo "Found komodo-cli at: $cli_path" >&2 140 | echo "$cli_path" 141 | return 0 142 | fi 143 | 144 | # Check in ~/KomodoOcean/src 145 | cli_path="$HOME/KomodoOcean/src/komodo-cli" 146 | if [[ -x "$cli_path" ]]; then 147 | echo "Found komodo-cli at: $cli_path" >&2 148 | echo "$cli_path" 149 | return 0 150 | fi 151 | 152 | # komodo-cli not found 153 | echo -e "${RED}Error:${RESET} komodo-cli not found in system-wide path, $HOME/komodo/src, or $HOME/KomodoOcean/src." >&2 154 | exit 1 155 | } 156 | 157 | determine_litecoin_cli() { 158 | local cli_path 159 | # Check system-wide installation 160 | cli_path=$(command -v litecoin-cli 2>/dev/null) 161 | if [[ -x "$cli_path" ]]; then 162 | echo "Found system-wide litecoin-cli at: $cli_path" >&2 163 | echo "$cli_path" 164 | return 0 165 | fi 166 | 167 | # Check in ~/litecoin/src 168 | cli_path="$HOME/litecoin/src/litecoin-cli" 169 | if [[ -x "$cli_path" ]]; then 170 | echo "Found litecoin-cli at: $cli_path" >&2 171 | echo "$cli_path" 172 | return 0 173 | fi 174 | 175 | # litecoin-cli not found 176 | echo -e "${RED}Error:${RESET} litecoin-cli not found in system-wide path or $HOME/litecoin/src." >&2 177 | exit 1 178 | } 179 | 180 | init_colors 181 | komodo_cli_binary=$(determine_komodo_cli) 182 | litecoin_cli_binary=$(determine_litecoin_cli) 183 | source_pubkey 184 | 185 | KMD_ADDRESS=$(${komodo_cli_binary} decodescript "21${pubkey}ac" | jq -r .addresses[0]) 186 | LTC_ADDRESS=$(${litecoin_cli_binary} decodescript "21${pubkey}ac" | jq -r .addresses[0]) 187 | printf "KMD Address: ${YELLOW}%-40s${RESET}\n" "$KMD_ADDRESS" 188 | printf "LTC Address: ${YELLOW}%-40s${RESET}\n" "$LTC_ADDRESS" 189 | echo 190 | 191 | # Read assetchains from JSON 192 | readarray -t kmd_coins < <(cat $HOME/dPoW/iguana/assetchains.json | jq -r '[.[].ac_name] | join("\n")') 193 | # printf '%s\n' "${kmd_coins[@]}" 194 | 195 | gleec_count=0 196 | for i in "${kmd_coins[@]}" 197 | do 198 | if [[ "$i" == "GLEEC" ]]; then 199 | ((gleec_count++)) 200 | 201 | if [[ "$gleec_count" -eq 1 ]]; then 202 | show_balance "GLEEC_OLD" "-datadir=$HOME/.komodo/GLEEC_OLD" 203 | elif [[ "$gleec_count" -eq 2 ]]; then 204 | show_balance "GLEEC" 205 | else 206 | echo -e "${YELLOW}GLEEC has been encountered more than twice. No additional actions will be performed.${RESET}" >&2 207 | fi 208 | 209 | continue 210 | fi 211 | show_balance "$i" 212 | done 213 | 214 | # KMD Balance 215 | show_balance 216 | 217 | # LTC Balance with Fixed-Width Formatting 218 | BALANCE=$(${litecoin_cli_binary} getbalance) 219 | UTXOS=$(${litecoin_cli_binary} listunspent | jq '[.[] | select (.amount==0.00010000 and .spendable==true and (.scriptPubKey == "21'"${pubkey}"'ac"))] | length') 220 | if [[ $(jq -n --arg b "$BALANCE" '$b | tonumber > 10') == "true" ]]; then 221 | # BALANCE is greater than 10; display in green 222 | printf "[%-15s] [${GREEN}%15s${RESET}] [%5d]\n" "LTC" "$BALANCE" "$UTXOS" 223 | else 224 | # BALANCE is 10 or less; display normally 225 | printf "[%-15s] [%15s] [%5d]\n" "LTC" "$BALANCE" "$UTXOS" 226 | fi 227 | -------------------------------------------------------------------------------- /assetchains_height.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | komodo_cli_binary="$HOME/komodo/src/komodo-cli" 4 | curtime=$(date +%s) 5 | 6 | function show_height () 7 | { 8 | INFO=$($komodo_cli_binary -ac_name=$1 getinfo) 9 | blocks=$(echo $INFO | jq .blocks) 10 | longestchain=$(echo $INFO | jq .longestchain) 11 | lasttime=$($komodo_cli_binary -ac_name=$1 getblock $blocks | jq .time) 12 | mempool_size=$($komodo_cli_binary -ac_name=$1 getmempoolinfo | jq .size) 13 | getmininginfo=$($komodo_cli_binary -ac_name=$1 getmininginfo) 14 | 15 | generate=$(echo $getmininginfo | jq .generate) 16 | genproclimit=$(echo $getmininginfo | jq .genproclimit) 17 | 18 | delta=$(($curtime-$lasttime)) 19 | 20 | printf "[%8s] %08d %08d " $1 $blocks $longestchain 21 | printf '%02dh:%02dm:%02ds ' $(($delta/3600)) $(($delta%3600/60)) $(($delta%60)) 22 | printf "[%d - %s,%d]" $mempool_size $generate $genproclimit 23 | if [ $blocks != $longestchain ]; then 24 | echo -e -n "\x1B[22;31m [!]\x1B[0m" 25 | fi 26 | echo -e -n "\n" 27 | 28 | } 29 | 30 | show_height REVS 31 | show_height SUPERNET 32 | show_height DEX 33 | show_height PANGEA 34 | show_height JUMBLR 35 | show_height BET 36 | show_height CRYPTO 37 | show_height HODL 38 | show_height MSHARK 39 | show_height BOTS 40 | show_height MGW 41 | show_height COQUI 42 | show_height WLC 43 | show_height KV 44 | show_height CEAL 45 | show_height MESH 46 | show_height MNZ 47 | show_height AXO 48 | show_height ETOMIC 49 | show_height BTCH 50 | #show_height VOTE2018 51 | show_height PIZZA 52 | show_height BEER 53 | show_height NINJA 54 | show_height OOT 55 | show_height BNTN 56 | show_height CHAIN 57 | show_height PRLPAY 58 | show_height DSEC 59 | show_height GLXT 60 | show_height EQL 61 | show_height ZILLA 62 | show_height VRSC 63 | show_height RFOX 64 | show_height SEC 65 | show_height CCL 66 | show_height PIRATE 67 | show_height MGNX 68 | show_height PGT 69 | show_height KMDICE 70 | show_height DION 71 | show_height ZEX 72 | echo ------------ 73 | 74 | INFO=$($komodo_cli_binary getinfo) 75 | blocks=$(echo $INFO | jq .blocks) 76 | longestchain=$(echo $INFO | jq .longestchain) 77 | lasttime=$($komodo_cli_binary getblock $blocks | jq .time) 78 | delta=$(($curtime-$lasttime)) 79 | printf "[%8s] %08d %08d " "KMD" $blocks $longestchain 80 | printf '%02dh:%02dm:%02ds' $(($delta/3600)) $(($delta%3600/60)) $(($delta%60)) 81 | if [ $blocks != $longestchain ]; then 82 | echo -e -n "\x1B[22;31m [!]\x1B[0m" 83 | fi 84 | echo -e -n "\n" -------------------------------------------------------------------------------- /assetchains_loop.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ### 4 | # This is just a template for actions on ALL assetchains (loop via all ACs) 5 | ### 6 | 7 | readarray -t kmd_coins < <(curl -s https://raw.githubusercontent.com/KomodoPlatform/dPoW/master/iguana/assetchains.json | jq -r '[.[].ac_name] | join("\n")') 8 | # printf '%s\n' "${kmd_coins[@]}" 9 | 10 | # Initialize WIF and TO variables 11 | WIF= 12 | TO= 13 | 14 | # Function to source pubkey.txt from multiple locations 15 | source_pubkey() { 16 | local pubkey_file 17 | local found=0 18 | 19 | # Define the search order 20 | local search_paths=( 21 | "$HOME/komodo/src/pubkey.txt" 22 | "$HOME/KomodoOcean/src/pubkey.txt" 23 | "$HOME/pubkey.txt" 24 | ) 25 | 26 | # Iterate through the search paths 27 | for pubkey_file in "${search_paths[@]}"; do 28 | if [[ -f "$pubkey_file" ]]; then 29 | echo "Found pubkey.txt at: $pubkey_file" >&2 30 | source "$pubkey_file" 31 | found=1 32 | break 33 | fi 34 | done 35 | 36 | # Check if pubkey.txt was found and sourced 37 | if [[ "$found" -ne 1 ]]; then 38 | echo "Error: pubkey.txt not found in any of the specified locations." >&2 39 | exit 1 40 | fi 41 | 42 | # Ensure that the pubkey environment variable is set 43 | if [[ -z "$pubkey" ]]; then 44 | echo "Error: pubkey environment variable is not set after sourcing pubkey.txt." >&2 45 | exit 1 46 | fi 47 | 48 | echo "Pubkey: \"${pubkey}\"" 49 | } 50 | 51 | determine_komodo_cli() { 52 | local cli_path 53 | # Check system-wide installation 54 | cli_path=$(command -v komodo-cli 2>/dev/null) 55 | if [[ -x "$cli_path" ]]; then 56 | echo "Found system-wide komodo-cli at: $cli_path" >&2 57 | echo "$cli_path" 58 | return 0 59 | fi 60 | 61 | # Check in ~/komodo/src 62 | cli_path="$HOME/komodo/src/komodo-cli" 63 | if [[ -x "$cli_path" ]]; then 64 | echo "Found komodo-cli at: $cli_path" >&2 65 | echo "$cli_path" 66 | return 0 67 | fi 68 | 69 | # Check in ~/KomodoOcean/src 70 | cli_path="$HOME/KomodoOcean/src/komodo-cli" 71 | if [[ -x "$cli_path" ]]; then 72 | echo "Found komodo-cli at: $cli_path" >&2 73 | echo "$cli_path" 74 | return 0 75 | fi 76 | 77 | # komodo-cli not found 78 | echo "Error: komodo-cli not found in system-wide path, $HOME/komodo/src, or $HOME/KomodoOcean/src." >&2 79 | exit 1 80 | } 81 | 82 | # Set komodo_cli_binary by determining its path 83 | komodo_cli_binary=$(determine_komodo_cli) 84 | # Call the function to source pubkey.txt 85 | source_pubkey 86 | 87 | gleec_count=0 88 | for i in "${kmd_coins[@]}" 89 | do 90 | echo Processing "$i" 1>&2 91 | if [[ "$i" == "GLEEC" ]]; then 92 | ((gleec_count++)) 93 | 94 | if [[ "$gleec_count" -eq 1 ]]; then 95 | echo " ---> action_1" 1>&2 96 | elif [[ "$gleec_count" -eq 2 ]]; then 97 | echo " ---> action_2" 1>&2 98 | else 99 | echo "GLEEC has been encountered more than twice. No additional actions will be performed." 1>&2 100 | fi 101 | fi 102 | done 103 | 104 | # Actions examples: 105 | 106 | #${komodo_cli_binary} -ac_name="$i" importprivkey ${WIF} "" false 107 | #BALANCE=$(${komodo_cli_binary} -ac_name="$i" getbalance) 108 | #echo ${komodo_cli_binary} -ac_name="$i" sendtoaddress ${TO} ${BALANCE} "" "" true 109 | #${komodo_cli_binary} -ac_name="$i" z_mergetoaddress '["ANY_TADDR"]' ${TO} 0.001 0 110 | 111 | #PORT=$(${komodo_cli_binary} -ac_name="$i" getinfo | jq .p2pport) 112 | #echo "# ${i} mangle rules" 113 | #echo sudo /sbin/iptables -t mangle -A OUTPUT -p tcp -m tcp --dport $PORT -j MARK --set-mark 0x2 -m comment --comment "\"${i} IPv4 mark to\"" 114 | #echo sudo /sbin/iptables -t mangle -A OUTPUT -p tcp -m tcp --sport $PORT -j MARK --set-mark 0x2 -m comment --comment "\"${i} IPv4 mark from\"" 115 | #echo sudo /sbin/ip6tables -t mangle -A OUTPUT -p tcp -m tcp --dport $PORT -j MARK --set-mark 0x4 -m comment --comment "\"${i} IPv6 mark to\"" 116 | #echo sudo /sbin/ip6tables -t mangle -A OUTPUT -p tcp -m tcp --sport $PORT -j MARK --set-mark 0x4 -m comment --comment "\"${i} IPv6 mark from\"" 117 | 118 | #echo sudo ufw allow $PORT/tcp comment "'${i} p2p port'" 119 | #${komodo_cli_binary} -ac_name="$i" getinfo | jq .connections 120 | 121 | #BALANCE=$(${komodo_cli_binary} getbalance) 122 | #echo KMD ${BALANCE} -- ${TO} 123 | # ${komodo_cli_binary} sendtoaddress ${TO} ${BALANCE} "" "" true 124 | #${komodo_cli_binary} z_mergetoaddress '["ANY_TADDR"]' ${TO} 0.001 0 125 | -------------------------------------------------------------------------------- /assetchains_validate.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Assetchains Validate Script (c) Decker, 2019 4 | # 5 | # Small script that allows to check privkeys import in all coins (3 season, mainnet). 6 | # You don't need to change anything in this script, if you followed NN guide. It will 7 | # automatically locate your pubkey from pubkey.txt file and will calculate your address 8 | # for BTC and KMD/AC, then it will check IsMine() of this address. Assetchains list 9 | # is automatically parsed from assetchains.json used only JQ. 10 | 11 | # -------------------------------------------------------------------------- 12 | function init_colors() { 13 | RESET="\033[0m" 14 | BLACK="\033[30m" 15 | RED="\033[31m" 16 | GREEN="\033[32m" 17 | YELLOW="\033[33m" 18 | BLUE="\033[34m" 19 | MAGENTA="\033[35m" 20 | CYAN="\033[36m" 21 | WHITE="\033[37m" 22 | BRIGHT="\033[1m" 23 | DARKGREY="\033[90m" 24 | } 25 | 26 | # -------------------------------------------------------------------------- 27 | function validateaddress () 28 | { 29 | ISMINE=$($komodo_cli_binary -ac_name=$1 validateaddress ${KMD_ADDRESS} | jq .ismine) 30 | if [ "$ISMINE" = "true" ]; then 31 | ISMINE=${GREEN}$ISMINE${RESET} 32 | else 33 | ISMINE=${RED}$ISMINE${RESET} 34 | fi 35 | printf '%-10s | %b\n' $1 ${ISMINE} 36 | } 37 | 38 | init_colors 39 | komodo_cli_binary="$HOME/komodo/src/komodo-cli" 40 | source $HOME/komodo/src/pubkey.txt 41 | echo Pub: ${pubkey} 42 | KMD_ADDRESS=$(${komodo_cli_binary} decodescript "21${pubkey}ac" | jq -r .addresses[0]) 43 | BTC_ADDRESS=$(bitcoin-cli decodescript "21${pubkey}ac" | jq -r .addresses[0]) 44 | echo -e KMD: ${YELLOW}${KMD_ADDRESS}${RESET} 45 | echo -e BTC: ${YELLOW}${BTC_ADDRESS}${RESET} 46 | echo 47 | # https://stackoverflow.com/questions/18669756/bash-how-to-extract-data-from-a-column-in-csv-file-and-put-it-in-an-array 48 | readarray -t kmd_coins < <(cat $HOME/komodo/src/assetchains.json | jq -r '[.[].ac_name] | join("\n")') 49 | # printf '%s\n' "${kmd_coins[@]}" 50 | for i in "${kmd_coins[@]}" 51 | do 52 | validateaddress "$i" 53 | done 54 | 55 | # Komodo 56 | ISMINE=$($komodo_cli_binary validateaddress ${KMD_ADDRESS} | jq .ismine) 57 | printf '%-10s | %s\n' "KMD" ${ISMINE} 58 | 59 | # Bitcoin 60 | ISMINE=$(bitcoin-cli validateaddress ${BTC_ADDRESS} | jq .ismine) 61 | printf '%-10s | %s\n' "BTC" ${ISMINE} -------------------------------------------------------------------------------- /assetchains_walletsize.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Find out the size of KMD and other KMD assetchains 3 | 4 | RESET="\033[0m" 5 | BLACK="\033[30m" 6 | RED="\033[31m" 7 | GREEN="\033[32m" 8 | YELLOW="\033[33m" 9 | BLUE="\033[34m" 10 | MAGENTA="\033[35m" 11 | CYAN="\033[36m" 12 | WHITE="\033[37m" 13 | 14 | function show_walletsize () { 15 | if [ "$1" != "KMD" ]; then 16 | if [ -f ~/.komodo/$1/wallet.dat ]; then 17 | 18 | # SIZE=$(stat ~/.komodo/$1/wallet.dat | grep -Po "Size: \d*" | cut -d" " -f2) 19 | # Pattern "Size: " - is only for english locale, so, we won't use it. 20 | 21 | SIZE=$(stat ~/.komodo/$1/wallet.dat | grep -Po "\d+" | head -1) 22 | else 23 | SIZE=0 24 | fi 25 | else 26 | SIZE=$(stat ~/.komodo/wallet.dat | grep -Po "\d+" | head -1) 27 | fi 28 | 29 | OUTSTR=$(echo $SIZE | numfmt --to=si --suffix=B) 30 | 31 | if [ "$SIZE" -gt "19922944" ]; then 32 | OUTSTR=${RED}$OUTSTR${RESET} 33 | else 34 | OUTSTR=${GREEN}$OUTSTR${RESET} 35 | fi 36 | 37 | printf "[%8s] %16b\n" $1 $OUTSTR 38 | } 39 | 40 | ignore_list=( 41 | VOTE2018 42 | PIZZA 43 | BEER 44 | ) 45 | 46 | show_walletsize KMD 47 | 48 | # Only assetchains 49 | ${HOME}/komodo/src/listassetchains | while read list; do 50 | if [[ "${ignore_list[@]}" =~ "${list}" ]]; then 51 | continue 52 | fi 53 | show_walletsize $list 54 | done 55 | -------------------------------------------------------------------------------- /autosplit-3rd.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # 3rd party Splitfund Script (autosplit-3rd.sh) 4 | # Copyright (c) 2018-2021 Decker 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at https://mozilla.org/MPL/2.0/. 8 | 9 | declare -A coins 10 | # mainnet 11 | coins[LTC]=$HOME/litecoin/src/litecoin-cli 12 | # 3rd 13 | # coins[CHIPS]=$HOME/chips/src/chips-cli 14 | # coins[GAME]=$HOME/GameCredits/src/gamecredits-cli 15 | # coins[EMC2]=$HOME/einsteinium/src/einsteinium-cli 16 | # coins[GIN]=$HOME/gincoin-core/src/gincoin-cli 17 | # coins[AYA]=$HOME/AYAv2/src/aryacoin-cli 18 | # coins[GLEEC]=$HOME/GleecBTC-FullNode-Win-Mac-Linux/src/gleecbtc-cli 19 | # coins[SFUSD]=$HOME/sfusd-core/src/smartusd-cli 20 | 21 | # declare -A coins=( [BTC]=/usr/local/bin/bitcoin-cli [GAME]=$HOME/GameCredits/src/gamecredits-cli ) # example of one-line array init 22 | 23 | # we don't need to specify pubkey anymore, as we have it in $HOME/komodo/src/pubkey.txt, 24 | # we will just fill environment variable ${pubkey} from there 25 | source $HOME/komodo/src/pubkey.txt 26 | NN_PUBKEY=21${pubkey}ac 27 | 28 | # script check the condition if utxo_count < utxo_min then append it to utxo_max, 29 | # small example: utxo_min = 100; utxo_max = 100; if you have 90 utxo (90 < utxo_min) 30 | # script will spilt additional 10 utxos to have utxo_max (100). 31 | 32 | # every splitfunds tx is signed and trying to broadcast by iguana, then it checks by daemon, 33 | # if tx failed to broadcast (not in chain) it resigned by daemon and broadcast to network. 34 | # very simple solution until we fix internal iguana splitfund sign. 35 | 36 | utxo_min=5 37 | utxo_max=10 38 | 39 | # -------------------------------------------------------------------------- 40 | function init_colors() { 41 | RESET="\033[0m" 42 | BLACK="\033[30m" 43 | RED="\033[31m" 44 | GREEN="\033[32m" 45 | YELLOW="\033[33m" 46 | BLUE="\033[34m" 47 | MAGENTA="\033[35m" 48 | CYAN="\033[36m" 49 | WHITE="\033[37m" 50 | BRIGHT="\033[1m" 51 | DARKGREY="\033[90m" 52 | } 53 | 54 | # -------------------------------------------------------------------------- 55 | function log_print() { 56 | datetime=$(date '+%Y-%m-%d %H:%M:%S') 57 | echo -e [$datetime] $1 58 | } 59 | 60 | function do_autosplit() { 61 | 62 | if [ ! -z $1 ] && [ ! -z $2 ] 63 | then 64 | 65 | coin=$1; komodo_cli=$2; asset="" 66 | # setting the split amounts 67 | if [ $coin == 'GAME' ] || [ $coin == 'EMC2' ] || [ $coin == 'AYA' ]; then 68 | satoshis=100000; amount=0.001 69 | else 70 | satoshis=10000; amount=0.0001 71 | fi 72 | 73 | # .generated==false and # for most coins generated field doesn't exits in listunspent, so, we shouldn't use it 74 | utxo=$($komodo_cli $asset listunspent | jq '[.[] | select (.amount=='${amount}' and .spendable==true and (.scriptPubKey == "'$NN_PUBKEY'"))] | length') 75 | 76 | # check if result is number (https://stackoverflow.com/questions/806906/how-do-i-test-if-a-variable-is-a-number-in-bash) 77 | 78 | if [ -n "$utxo" ] && [ "$utxo" -eq "$utxo" ] 2>/dev/null; then 79 | if [ $utxo -lt $utxo_min ]; then 80 | need=$(($utxo_max-$utxo)) 81 | log_print "${BRIGHT}\x5b${RESET}${YELLOW}${coin}${RESET}${BRIGHT}\x5d${RESET} have.${utxo} --> add.${need} --> total.${utxo_max}" 82 | # /home/decker/SuperNET/iguana/acsplit $i $need 83 | log_print "${DARKGREY}curl -s --url \"http://127.0.0.1:7776\" --data '{\"coin\":\"${coin}\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"${satoshis}\",\"sendflag\":1,\"duplicates\":\"${need}\"}'${RESET}" 84 | splitres=$(curl -s --url "http://127.0.0.1:7776" --data "{\"coin\":\""${coin}"\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"${satoshis}\",\"sendflag\":1,\"duplicates\":"${need}"}") 85 | #splitres='{"result":"hexdata","txid":"d5aedd61710db60181a1d34fc9a84c9333ec17509f12c1d67b29253f66e7a88c","completed":true,"tag":"5009274800182462270"}' 86 | error=$(echo $splitres | jq -r .error) 87 | txid=$(echo $splitres | jq -r .txid) 88 | signed=$(echo $splitres | jq -r .result) 89 | 90 | if [ -z "$error" ] || [ "$error" = "null" ] && [ ! -z "$splitres" ]; then 91 | # if no errors, continue, otherwise display error 92 | if [ ! -z "$txid" ] && [ "$txid" != "null" ]; then 93 | # we have txid, now we should check is it really exist in blockchain or not 94 | # sleep 3 95 | txidcheck=$($komodo_cli $asset getrawtransaction $txid 1 2>/dev/null | jq -r .txid) 96 | if [ "$txidcheck" = "$txid" ]; then 97 | log_print "txid.${GREEN}$txid${RESET} - OK" 98 | else 99 | log_print "txid.${RED}$txid${RESET} - FAIL" 100 | # tx possible fail, because iguana produced incorrect sign, no problem, let's resign it by daemon and broadcast (perfect solution, isn't it?) 101 | daemonsigned=$($komodo_cli $asset signrawtransaction $signed | jq -r .hex) 102 | newtxid=$($komodo_cli $asset sendrawtransaction $daemonsigned) 103 | log_print "newtxid.$newtxid - BROADCASTED" 104 | 105 | fi 106 | else 107 | log_print "${RED}Iguana doesn't return txid ...${RESET}" 108 | fi 109 | else 110 | if [ ! -z "$splitres" ]; then 111 | log_print "${RED}$error${RESET}" 112 | else 113 | log_print "${RED}Failed to receive curl answer, possible iguana died ...${RESET}" 114 | fi 115 | fi 116 | else 117 | log_print "${BRIGHT}\x5b${RESET}${YELLOW}${coin}${RESET}${BRIGHT}\x5d${RESET} have.${utxo} --> don't need split ..." 118 | fi 119 | else 120 | log_print "${BRIGHT}\x5b${RESET}${YELLOW}${coin}${RESET}${BRIGHT}\x5d${RESET} ${RED}Error: utxo count is not a number, may be daemon dead ... ${RESET}" 121 | fi 122 | fi 123 | } 124 | 125 | init_colors 126 | log_print "Starting autosplit ..." 127 | 128 | for i in "${!coins[@]}" # access the keys with ${!array[@]} 129 | do 130 | # key - $i, value - ${coins[$i]} 131 | do_autosplit $i ${coins[$i]} 132 | done -------------------------------------------------------------------------------- /autosplit-new.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Mainnet Splitfund Script (autosplit-new.sh) 4 | # Copyright (c) 2018-2024 Decker 5 | 6 | # This Source Code Form is subject to the terms of the Mozilla Public 7 | # License, v. 2.0. If a copy of the MPL was not distributed with this 8 | # file, You can obtain one at https://mozilla.org/MPL/2.0/. 9 | 10 | source_pubkey() { 11 | local pubkey_file 12 | local found=0 13 | 14 | # Define the search order 15 | local search_paths=( 16 | "$HOME/komodo/src/pubkey.txt" 17 | "$HOME/KomodoOcean/src/pubkey.txt" 18 | "$HOME/pubkey.txt" 19 | ) 20 | 21 | # Iterate through the search paths 22 | for pubkey_file in "${search_paths[@]}"; do 23 | if [[ -f "$pubkey_file" ]]; then 24 | echo "Found pubkey.txt at: $pubkey_file" >&2 25 | source "$pubkey_file" 26 | found=1 27 | break 28 | fi 29 | done 30 | 31 | # Check if pubkey.txt was found and sourced 32 | if [[ "$found" -ne 1 ]]; then 33 | echo -e "${RED}Error:${RESET} pubkey.txt not found in any of the specified locations." >&2 34 | exit 1 35 | fi 36 | 37 | # Ensure that the pubkey environment variable is set 38 | if [[ -z "$pubkey" ]]; then 39 | echo -e "${RED}Error:${RESET} pubkey environment variable is not set after sourcing pubkey.txt." >&2 40 | exit 1 41 | fi 42 | 43 | echo -e "Pubkey: \"${pubkey}\"" 44 | } 45 | 46 | determine_komodo_cli() { 47 | local cli_path 48 | # Check system-wide installation 49 | cli_path=$(command -v komodo-cli 2>/dev/null) 50 | if [[ -x "$cli_path" ]]; then 51 | echo "Found system-wide komodo-cli at: $cli_path" >&2 52 | echo "$cli_path" 53 | return 0 54 | fi 55 | 56 | # Check in ~/komodo/src 57 | cli_path="$HOME/komodo/src/komodo-cli" 58 | if [[ -x "$cli_path" ]]; then 59 | echo "Found komodo-cli at: $cli_path" >&2 60 | echo "$cli_path" 61 | return 0 62 | fi 63 | 64 | # Check in ~/KomodoOcean/src 65 | cli_path="$HOME/KomodoOcean/src/komodo-cli" 66 | if [[ -x "$cli_path" ]]; then 67 | echo "Found komodo-cli at: $cli_path" >&2 68 | echo "$cli_path" 69 | return 0 70 | fi 71 | 72 | # komodo-cli not found 73 | echo -e "${RED}Error:${RESET} komodo-cli not found in system-wide path, $HOME/komodo/src, or $HOME/KomodoOcean/src." >&2 74 | exit 1 75 | } 76 | 77 | komodo_cli=$(determine_komodo_cli) 78 | 79 | source_pubkey 80 | NN_PUBKEY=21${pubkey}ac 81 | 82 | # if ACs utxos lower than ${ac_utxo_min}, then top up till ${ac_utxo_max} 83 | ac_utxo_min=5 84 | ac_utxo_max=10 85 | # if KMD utxos lower than ${kmd_utxo_min}, then top up till ${kmd_utxo_max} 86 | kmd_utxo_min=25 87 | kmd_utxo_max=50 88 | 89 | # -------------------------------------------------------------------------- 90 | function init_colors() { 91 | RESET="\033[0m" 92 | BLACK="\033[30m" 93 | RED="\033[31m" 94 | GREEN="\033[32m" 95 | YELLOW="\033[33m" 96 | BLUE="\033[34m" 97 | MAGENTA="\033[35m" 98 | CYAN="\033[36m" 99 | WHITE="\033[37m" 100 | BRIGHT="\033[1m" 101 | DARKGREY="\033[90m" 102 | } 103 | 104 | # -------------------------------------------------------------------------- 105 | function log_print() { 106 | datetime=$(date '+%Y-%m-%d %H:%M:%S') 107 | echo -e [$datetime] $1 108 | } 109 | 110 | function do_autosplit() { 111 | 112 | if [ ! -z "$1" ] && [ "$1" != "KMD" ] 113 | then 114 | coin=$1 115 | if [ "$1" == "GLEEC_OLD" ]; then 116 | asset=" -ac_name=GLEEC -datadir=$HOME/.komodo/GLEEC_OLD" 117 | else 118 | asset=" -ac_name=$1" 119 | fi 120 | utxo_min=${ac_utxo_min} 121 | utxo_max=${ac_utxo_max} 122 | else 123 | coin="KMD" 124 | asset="" 125 | utxo_min=${kmd_utxo_min} 126 | utxo_max=${kmd_utxo_max} 127 | fi 128 | 129 | # utxo=$($komodo_cli -ac_name=$1 listunspent | grep .0001 | wc -l) # this is old way p2pk utxo determine (deprecated) 130 | utxo=$($komodo_cli $asset listunspent | jq '[.[] | select (.generated==false and .amount==0.0001 and .spendable==true and (.scriptPubKey == "'$NN_PUBKEY'"))] | length') 131 | 132 | # check if result is number (https://stackoverflow.com/questions/806906/how-do-i-test-if-a-variable-is-a-number-in-bash) 133 | 134 | if [ -n "$utxo" ] && [ "$utxo" -eq "$utxo" ] 2>/dev/null; then 135 | if [ $utxo -lt $utxo_min ]; then 136 | need=$(($utxo_max-$utxo)) 137 | log_print "${BRIGHT}\x5b${RESET}${YELLOW}${coin}${RESET}${BRIGHT}\x5d${RESET} have.${utxo} --> add.${need} --> total.${utxo_max}" 138 | # $HOME/SuperNET/iguana/acsplit $i $need 139 | log_print "${DARKGREY}curl -s --url \"http://127.0.0.1:7776\" --data '{\"coin\":\"${coin}\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"10000\",\"sendflag\":1,\"duplicates\":\"${need}\"}'${RESET}" 140 | splitres=$(curl -s --url "http://127.0.0.1:7776" --data "{\"coin\":\""${coin}"\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"10000\",\"sendflag\":1,\"duplicates\":"${need}"}") 141 | #splitres='{"result":"hexdata","txid":"d5aedd61710db60181a1d34fc9a84c9333ec17509f12c1d67b29253f66e7a88c","completed":true,"tag":"5009274800182462270"}' 142 | error=$(echo $splitres | jq -r .error) 143 | txid=$(echo $splitres | jq -r .txid) 144 | signed=$(echo $splitres | jq -r .result) 145 | 146 | if [ -z "$error" ] || [ "$error" = "null" ] && [ ! -z "$splitres" ]; then 147 | # if no errors, continue, otherwise display error 148 | if [ ! -z "$txid" ] && [ "$txid" != "null" ]; then 149 | # we have txid, now we should check is it really exist in blockchain or not 150 | # sleep 3 151 | txidcheck=$($komodo_cli $asset getrawtransaction $txid 1 2>/dev/null | jq -r .txid) 152 | if [ "$txidcheck" = "$txid" ]; then 153 | log_print "txid.${GREEN}$txid${RESET} - OK" 154 | else 155 | log_print "txid.${RED}$txid${RESET} - FAIL" 156 | # tx possible fail, because iguana produced incorrect sign, no problem, let's resign it by daemon and broadcast (perfect solution, isn't it?) 157 | daemonsigned=$($komodo_cli $asset signrawtransaction $signed | jq -r .hex) 158 | newtxid=$($komodo_cli $asset sendrawtransaction $daemonsigned) 159 | log_print "newtxid.$newtxid - BROADCASTED" 160 | 161 | fi 162 | else 163 | log_print "${RED}Iguana doesn't return txid ...${RESET}" 164 | fi 165 | else 166 | if [ ! -z "$splitres" ]; then 167 | log_print "${RED}$error${RESET}" 168 | else 169 | log_print "${RED}Failed to receive curl answer, possible iguana died ...${RESET}" 170 | fi 171 | fi 172 | else 173 | log_print "${BRIGHT}\x5b${RESET}${YELLOW}${coin}${RESET}${BRIGHT}\x5d${RESET} have.${utxo} --> don't need split ..." 174 | fi 175 | else 176 | log_print "${BRIGHT}\x5b${RESET}${YELLOW}${coin}${RESET}${BRIGHT}\x5d${RESET} ${RED}Error: utxo count is not a number, may be daemon dead ... ${RESET}" 177 | fi 178 | } 179 | 180 | init_colors 181 | log_print "Starting autosplit ..." 182 | 183 | #declare -a kmd_coins=(KMD REVS SUPERNET DEX PANGEA JUMBLR BET CRYPTO HODL MSHARK BOTS MGW COQUI WLC KV CEAL MESH AXO ETOMIC BTCH PIZZA BEER NINJA OOT BNTN CHAIN PRLPAY DSEC GLXT EQL VRSC ZILLA RFOX SEC CCL PIRATE PGT KMDICE DION KSB OUR ILN RICK MORTY VOTE2019 HUSH3 KOIN ZEXO K64) 184 | do_autosplit KMD 185 | #source $(dirname $(readlink -f $0))/kmd-coins.sh 186 | 187 | # mainnet 188 | readarray -t kmd_coins < <(cat $HOME/dPoW/iguana/assetchains.json | jq -r '[.[].ac_name] | join("\n")') 189 | # 3rd 190 | # declare -a kmd_coins=(KMD VRSC MCL) 191 | 192 | gleec_count=0 193 | for i in "${kmd_coins[@]}" 194 | do 195 | if [[ "$i" == "GLEEC" ]]; then 196 | ((gleec_count++)) 197 | 198 | if [[ "$gleec_count" -eq 1 ]]; then 199 | do_autosplit "GLEEC_OLD" 200 | elif [[ "$gleec_count" -eq 2 ]]; then 201 | do_autosplit "GLEEC" 202 | else 203 | echo -e "${YELLOW}GLEEC has been encountered more than twice. No additional actions will be performed.${RESET}" >&2 204 | fi 205 | continue 206 | fi 207 | do_autosplit "$i" 208 | done 209 | 210 | -------------------------------------------------------------------------------- /bip32-test.php: -------------------------------------------------------------------------------- 1 | base58_decode($bip32_root_key); 27 | $xprv_decoded = hex2bin($xprv_decoded); 28 | $xprv_decoded = unpack("H8version/Cdepth/H8fingerprint/H8child/H64chaincode/H66privatekey", $xprv_decoded); 29 | if ($xprv_decoded["version"] == "0488ade4") { 30 | $cc_par = hex2bin($xprv_decoded["chaincode"]); 31 | $k_par = hex2bin(substr($xprv_decoded["privatekey"], 2, 64)); 32 | $depth = $xprv_decoded["depth"]; 33 | // TODO: implement derivation 34 | } 35 | } 36 | return []; 37 | } 38 | 39 | // (NB!) Change zend.assertions to 1 in your php.ini to make assertions work. 40 | 41 | $bitcoinECDSA = new BitcoinECDSA(); 42 | 43 | $seed = pack("H*", "fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542"); 44 | 45 | // hash_hmac(string $algo, string $data, string $key, bool $binary = false): string 46 | 47 | $i = pack("H*", hash_hmac('sha512', $seed, 'Bitcoin seed')); 48 | $il = substr($i, 0, 32); // private key (bin) 49 | $ir = substr($i, 32, 32); // chain code (bin) 50 | 51 | echo "privkey: " . bin2hex($il) . PHP_EOL; 52 | echo "chncode: " . bin2hex($ir) . PHP_EOL; 53 | 54 | $depth = 0; 55 | $fingerprint = 0; 56 | $child_number = 0; 57 | 58 | /* 59 | 4 byte: version bytes (mainnet: 0x0488B21E public, 0x0488ADE4 private; testnet: 0x043587CF public, 0x04358394 private) 60 | 1 byte: depth: 0x00 for master nodes, 0x01 for level-1 derived keys, .... 61 | 4 bytes: the fingerprint of the parent's key (0x00000000 if master key) 62 | 4 bytes: child number. This is ser32(i) for i in xi = xpar/i, with xi the key being serialized. (0x00000000 if master key) 63 | 32 bytes: the chain code 64 | 33 bytes: the public key or private key data (serP(K) for public keys, 0x00 || ser256(k) for private keys) 65 | */ 66 | 67 | $base58data = "0488ade4" . 68 | bin2hex(pack("C", $depth)) . 69 | bin2hex(pack('l', $fingerprint)) . 70 | bin2hex(pack('l', $child_number)) . 71 | bin2hex($ir) . 72 | "00" . 73 | bin2hex($il); 74 | 75 | $checksum = substr(hash('sha256', hash('sha256', hex2bin($base58data), true), true), 0, 4); 76 | 77 | $base58data .= bin2hex($checksum); 78 | 79 | assert($bitcoinECDSA->base58_encode($base58data) == 'xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U'); 80 | 81 | echo 'Chain m' . PHP_EOL; 82 | echo "ext prv: " . $bitcoinECDSA->base58_encode($base58data) . PHP_EOL; 83 | 84 | $k = bin2hex($il); 85 | $bitcoinECDSA->setNetworkPrefix("00"); 86 | $bitcoinECDSA->setPrivateKey($k); 87 | $pubkey = $bitcoinECDSA->getPubKey(); 88 | 89 | $base58data = "0488b21e" . 90 | bin2hex(pack("C", $depth)) . 91 | bin2hex(pack('l', $fingerprint)) . 92 | bin2hex(pack('l', $child_number)) . 93 | bin2hex($ir) . 94 | $pubkey; 95 | 96 | $checksum = substr(hash('sha256', hash('sha256', hex2bin($base58data), true), true), 0, 4); 97 | 98 | $base58data .= bin2hex($checksum); 99 | 100 | assert($base58data == $bitcoinECDSA->base58_decode('xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB')); 101 | echo "ext pub: " . $bitcoinECDSA->base58_encode($base58data) . PHP_EOL; 102 | 103 | $cc_par = $ir; $k_par = $il; 104 | 105 | $depth = 1; 106 | // fingerprint of the parent's key (0x00000000 if master key) 107 | $fingerprint = bin2hex(substr(hash('ripemd160', hash('sha256', hex2bin($pubkey), true), true), 0, 4)); // Hash160 (RIPEMD160 after SHA256) 108 | $fingerprint = unpack("l", hex2bin($fingerprint))[1]; 109 | $child_number = 0; 110 | $hardened = 0; 111 | echo 'Chain m/' . $child_number . ($hardened ? "'" : "") . PHP_EOL; 112 | 113 | // hash_hmac(string $algo, string $data, string $key, bool $binary = false): string 114 | if ($hardened) { 115 | $i = pack("H*", hash_hmac('sha512', pack("C", 0x00) . $k_par . strrev(pack('l', 0x80000000 + $child_number)), $cc_par)); 116 | } else { 117 | $i = pack("H*", hash_hmac('sha512', hex2bin($pubkey) . strrev(pack('l', $child_number)), $cc_par)); 118 | } 119 | 120 | $il = substr($i, 0, 32); // private key (bin) 121 | $ir = substr($i, 32, 32); // chain code (bin) 122 | 123 | 124 | // The order of the curve secp256k1 is 125 | // 2^256 − 2^32 − 2^9 − 2^8 − 2^7 − 2^6 − 2^4 − 1, which is equal to 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141. 126 | // The modulo n of an integer x is therefore x mod n = x (mod 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141). 127 | // https://en.bitcoin.it/wiki/Allprivatekeys 128 | 129 | $order = gmp_init('0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141', 16); 130 | $gmp1 = gmp_init(bin2hex($il), 16); 131 | $gmp2 = gmp_init(bin2hex($k_par), 16); 132 | $add = gmp_add($gmp1, $gmp2); 133 | $add = gmp_mod($add, $order); 134 | $ki = gmp_strval($add,16); 135 | $ki = str_pad($ki, 64, '0', STR_PAD_LEFT); 136 | 137 | $bitcoinECDSA->setPrivateKey($ki); 138 | $wif = $bitcoinECDSA->getWIF(); 139 | $this_pubkey = $bitcoinECDSA->getPubKey(); 140 | echo "privkey: " . $ki . " (" . $wif . ")" . PHP_EOL; 141 | echo " pubkey: " . $this_pubkey . PHP_EOL; 142 | echo "address: " . $bitcoinECDSA->getAddress() . PHP_EOL; 143 | 144 | echo "chncode: " . bin2hex($ir) . PHP_EOL; 145 | 146 | $base58data = "0488ade4" . 147 | bin2hex(pack("C", $depth)) . 148 | bin2hex(pack('l', $fingerprint)) . 149 | bin2hex(strrev(pack('l', ($hardened ? 0x80000000 : 0x0) + $child_number))) . // serialize a 32-bit unsigned integer i as a 4-byte sequence, most significant byte first. 150 | bin2hex($ir) . 151 | "00" . 152 | $ki; 153 | 154 | $checksum = substr(hash('sha256', hash('sha256', hex2bin($base58data), true), true), 0, 4); 155 | $base58data .= bin2hex($checksum); 156 | echo "ext prv: " . $bitcoinECDSA->base58_encode($base58data) . PHP_EOL; 157 | assert($base58data == $bitcoinECDSA->base58_decode('xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt')); 158 | 159 | $k = $ki; 160 | $bitcoinECDSA = new BitcoinECDSA(); 161 | $bitcoinECDSA->setNetworkPrefix("00"); 162 | $bitcoinECDSA->setPrivateKey($k); 163 | $pubkey = $bitcoinECDSA->getPubKey(); 164 | 165 | $base58data = "0488b21e" . 166 | bin2hex(pack("C", $depth)) . 167 | bin2hex(pack('l', $fingerprint)) . 168 | bin2hex(strrev(pack('l', ($hardened ? 0x80000000 : 0x0) + $child_number))) . 169 | bin2hex($ir) . 170 | $pubkey; 171 | 172 | $checksum = substr(hash('sha256', hash('sha256', hex2bin($base58data), true), true), 0, 4); 173 | $base58data .= bin2hex($checksum); 174 | assert($base58data == $bitcoinECDSA->base58_decode('xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH')); 175 | echo "ext pub: " . $bitcoinECDSA->base58_encode($base58data) . PHP_EOL; 176 | 177 | var_dump(bip32_derive("xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt", "m/0")); 178 | 179 | ?> -------------------------------------------------------------------------------- /bip32/bip32.py: -------------------------------------------------------------------------------- 1 | from pycoin.symbols.btc import network 2 | from pycoin.contrib.bech32m import bech32_decode, bech32_encode, decode, encode, Encoding 3 | 4 | def wif_to_bech32_address(private_key_wif): 5 | """ 6 | Convert a WIF private key to a Bech32 address. 7 | 8 | Parameters: 9 | private_key_wif (str): The WIF private key. 10 | 11 | Returns: 12 | str: The Bech32 address. 13 | """ 14 | key = network.parse.wif(private_key_wif) 15 | pubkey_hash160 = key.hash160() 16 | witness_version = 0 17 | bech32_address = encode("bc", witness_version, pubkey_hash160) 18 | return bech32_address 19 | 20 | def main(): 21 | # Replace this with your own xprv key 22 | root_xprv = ( 23 | "xprv9s21ZrQH143K2scgAKadJkpcMHGsjyeYZrmZpHxzHEgyHUH3W8XrL54GpMSPzmhkGYAJEHzANFtdJ6BgkXGt8uAKUzjfVzPBjZnwK7VMHhD" 24 | ) 25 | 26 | # Parse the root key 27 | root_key = network.parse.bip32(root_xprv) 28 | 29 | # Derive the key at m/0 (unhardened) 30 | derived_key = root_key.subkey(0) 31 | m0_key = derived_key 32 | 33 | # Print out information for the derived node 34 | print("=== Derived Keys at m/0 ===") 35 | print("BIP32 Extended Private Key (xprv):", derived_key.hwif(as_private=True)) 36 | print("BIP32 Extended Public Key (xpub):", derived_key.hwif()) 37 | print("Private Key (WIF):", derived_key.wif()) 38 | print("Public Key (sec):", derived_key.sec().hex()) 39 | print("Address:", derived_key.address()) 40 | 41 | # How many child addresses do you want to show? 42 | num_addresses = 5 # for example, we'll show m/0/0 through m/0/4 43 | 44 | print("Path\t\tAddress\t\t\t\tPublic Key (hex)\t\t\t\tPrivate Key (WIF)") 45 | print("---------------------------------------------------------------------------------------------------------") 46 | 47 | # Derive m/0/i and print details 48 | for i in range(num_addresses): 49 | 50 | child_key = m0_key.subkey(i) 51 | path = f"m/0/{i}" 52 | address = child_key.address() 53 | public_key_hex = child_key.sec().hex() 54 | private_key_wif = child_key.wif() 55 | print(f"{path}\t{address}\t{public_key_hex}\t{private_key_wif}") 56 | # print(f"{wif_to_bech32_address(private_key_wif)}") 57 | 58 | child_key = m0_key.subkey(i, is_hardened=True) 59 | path = f"m/0/{i}'" 60 | address = child_key.address() 61 | public_key_hex = child_key.sec().hex() 62 | private_key_wif = child_key.wif() 63 | 64 | print(f"{path}\t{address}\t{public_key_hex}\t{private_key_wif}") 65 | # print(f"{wif_to_bech32_address(private_key_wif)}") 66 | 67 | if __name__ == "__main__": 68 | main() 69 | -------------------------------------------------------------------------------- /bip32/bip32_muun.py: -------------------------------------------------------------------------------- 1 | from pycoin.symbols.btc import network 2 | from pycoin.contrib.bech32m import encode 3 | 4 | # m/1'/1' 5 | # m/1'/1'/0 -- generateChangeAddrs 6 | # m/1'/1'/1 -- generateExternalAddrs 7 | # m/1'/1'/2 -- generateContactAddrs 8 | 9 | # UserKey, MuunKey 10 | 11 | def wif_to_bech32_address(private_key_wif): 12 | """ 13 | Convert a WIF private key to a Bech32 address. 14 | 15 | Parameters: 16 | private_key_wif (str): The WIF private key. 17 | 18 | Returns: 19 | str: The Bech32 address. 20 | """ 21 | key = network.parse.wif(private_key_wif) 22 | pubkey_hash160 = key.hash160() 23 | witness_version = 0 24 | bech32_address = encode("bc", witness_version, pubkey_hash160) 25 | return bech32_address 26 | 27 | def multisig_2of2_address(user_pubkey_hex, muun_pubkey_hex): 28 | # Convert hex public keys to bytes 29 | user_pubkey = bytes.fromhex(user_pubkey_hex) 30 | muun_pubkey = bytes.fromhex(muun_pubkey_hex) 31 | 32 | # Create a 2-of-2 multisig redeem script 33 | # script_for_multisig(m, [pubkey1, pubkey2]) 34 | pay_to_multisig_script = network.contract.for_multisig(2, [user_pubkey, muun_pubkey]) 35 | info = network.contract.info_for_script(pay_to_multisig_script) 36 | # print(f"Script: {pay_to_multisig_script.hex()}\n{info}") 37 | 38 | #multisig_address = network.address.for_p2s(pay_to_multisig_script) 39 | multisig_address = network.address.for_p2s_wit(pay_to_multisig_script) 40 | 41 | return multisig_address 42 | 43 | def multisig_2of2_address_p2tr(user_pubkey_hex, muun_pubkey_hex): 44 | 45 | user_pubkey = bytes.fromhex(user_pubkey_hex) 46 | muun_pubkey = bytes.fromhex(muun_pubkey_hex) 47 | if user_pubkey[0] not in (0x02, 0x03): 48 | raise ValueError("user_pubkey: Not a valid compressed secp256k1 public key") 49 | if muun_pubkey[0] not in (0x02, 0x03): 50 | raise ValueError("muun_pubkey: Not a valid compressed secp256k1 public key") 51 | 52 | user_pubkey_xonly = user_pubkey[1:] 53 | muun_pubkey_xonly = muun_pubkey[1:] 54 | 55 | # TODO ... 56 | 57 | multisig_address = None 58 | return multisig_address 59 | 60 | def main(): 61 | 62 | root_user_xprv = "xprv9s21ZrQH143K2scgAKadJkpcMHGsjyeYZrmZpHxzHEgyHUH3W8XrL54GpMSPzmhkGYAJEHzANFtdJ6BgkXGt8uAKUzjfVzPBjZnwK7VMHhD" 63 | root_muun_xprv = "xprv9s21ZrQH143K3EVNKGfL24khbPNqHxjGmh3YrFY8hyBvhY6oSy699tEQDVqbiXhJXzPNfrKJ41b2N5UNYn33PxXMR9DqWDhF931ZARYfHkx" 64 | 65 | # Parse the root key 66 | user_root_key = network.parse.bip32(root_user_xprv) 67 | muun_root_key = network.parse.bip32(root_muun_xprv) 68 | 69 | 70 | addresses_type = "external" 71 | # Derive the keys 72 | # Change - user "0", muun - "1H/1H/0" 73 | # External - user "1", muun - "1H/1H/1" 74 | 75 | if addresses_type == "change": 76 | user_derived_key = user_root_key.subkey_for_path("0") 77 | muun_derived_key = muun_root_key.subkey_for_path("1H/1H/0") 78 | elif addresses_type == "external": 79 | user_derived_key = user_root_key.subkey_for_path("1") 80 | muun_derived_key = muun_root_key.subkey_for_path("1H/1H/1") 81 | else: 82 | raise ValueError("Invalid addresses_type. Expected 'change' or 'external'.") 83 | 84 | print("User BIP32 Extended Private Key (xprv):", user_derived_key.hwif(as_private=True)) 85 | print("Muun BIP32 Extended Private Key (xprv):", muun_derived_key.hwif(as_private=True)) 86 | 87 | num_addresses = 5 88 | 89 | print("Path\t\tAddress\t\t\t\tPublic Key (hex)\t\t\t\tPrivate Key (WIF)") 90 | print("---------------------------------------------------------------------------------------------------------") 91 | 92 | # Derive m/1'/1'/0/i and print details 93 | for i in range(num_addresses): 94 | 95 | user_child_key = user_derived_key.subkey(i, is_hardened=False) 96 | muun_child_key = muun_derived_key.subkey(i, is_hardened=False) 97 | path = f"{i}" 98 | 99 | user_address = user_child_key.address() 100 | user_public_key_hex =user_child_key.sec().hex() 101 | user_private_key_wif = user_child_key.wif() 102 | # print(f"{path}\t{wif_to_bech32_address(user_private_key_wif)}\t{user_public_key_hex}\t{user_private_key_wif}") 103 | 104 | muun_address = muun_child_key.address() 105 | muun_public_key_hex =muun_child_key.sec().hex() 106 | muun_private_key_wif = muun_child_key.wif() 107 | # print(f"{path}\t{wif_to_bech32_address(muun_private_key_wif)}\t{muun_public_key_hex}\t{muun_private_key_wif}") 108 | 109 | # Get the 2-of-2 multisig address 110 | two_of_two_address = multisig_2of2_address(user_public_key_hex, muun_public_key_hex) 111 | print(f"{path}\t{two_of_two_address}\t({user_public_key_hex},{muun_public_key_hex}\t({user_private_key_wif},{muun_private_key_wif}))") 112 | 113 | # two_of_two_address_p2tr = multisig_2of2_address_p2tr(user_public_key_hex, muun_public_key_hex) 114 | # print(f"{path}\t{two_of_two_address_p2tr}") 115 | 116 | if __name__ == "__main__": 117 | main() 118 | -------------------------------------------------------------------------------- /bip32/kdf_internal_key.py: -------------------------------------------------------------------------------- 1 | from pycoin.symbols.btc import network 2 | from pycoin.networks.bitcoinish import create_bitcoinish_network 3 | from pycoin.encoding.bytes32 import to_bytes_32 4 | import base58 5 | import hashlib 6 | import unicodedata 7 | 8 | # 1. Calculates MarketMaker’s internal purposes public key in the same way as in mm2_internal_der_path. 9 | # 2. Prints the first 20 addresses of the HD wallet. 10 | 11 | # https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki 12 | # https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki 13 | 14 | def mnemonic_to_seed(mnemonic: str, passphrase: str = "") -> bytes: 15 | mnemonic_normalized = unicodedata.normalize("NFKD", mnemonic) 16 | passphrase_normalized = unicodedata.normalize("NFKD", passphrase) 17 | salt = ("mnemonic" + passphrase_normalized).encode("utf-8") 18 | seed = hashlib.pbkdf2_hmac("sha512", mnemonic_normalized.encode("utf-8"), salt, 2048) 19 | return seed 20 | 21 | def base58_check_encode(payload: bytes) -> str: 22 | checksum = hashlib.sha256(hashlib.sha256(payload).digest()).digest()[:4] 23 | return base58.b58encode(payload + checksum).decode('utf-8') 24 | 25 | def get_custom_address(hash160: bytes, custom_prefix: bytes) -> str: 26 | payload = custom_prefix + hash160 27 | return base58_check_encode(payload) 28 | 29 | def main(): 30 | 31 | KMD = create_bitcoinish_network( 32 | symbol="KMD", 33 | network_name="Komodo", 34 | subnet_name="mainnet", 35 | wif_prefix=b'\xbc', 36 | address_prefix=b'\x3c', 37 | pay_to_script_prefix=b'\x55', 38 | bip32_prv_prefix=b'\x04\x88\xad\xe4', 39 | bip32_pub_prefix=b'\x04\x88\xb2\x1e', 40 | magic_header=b'\xdb\xb6\xc0\xfb', 41 | default_port=7771, 42 | bip44_coin_type=141 43 | ) 44 | 45 | mnemonic_bytes = b"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about" 46 | mnemonic_str = mnemonic_bytes.decode("utf-8") 47 | seed_bytes = mnemonic_to_seed(mnemonic_str, passphrase="") 48 | print(f"BIP39 Seed: {seed_bytes.hex()}") 49 | # Obtain the BIP32 Root Key (xprv) from a hex seed 50 | key = network.keys.bip32_seed(seed_bytes) 51 | bip32_root_key = key.hwif(as_private=1) 52 | print(f"BIP32 Root Key: {bip32_root_key}") 53 | 54 | # mm2_internal_der_path 55 | # /// The derivation path generally consists of: 56 | # /// `m/purpose'/coin_type'/account'/change/address_index`. 57 | # /// For MarketMaker internal purposes, we decided to use a pubkey derived from the following path, where: 58 | # /// * `coin_type = 141` - KMD coin; 59 | # /// * `account = (2 ^ 31 - 1) = 2147483647` - latest available account index. 60 | # /// This number is chosen so that it does not cross with real accounts; 61 | # /// * `change = 0` - nothing special. 62 | # /// * `address_index = 0`. 63 | 64 | # m/44'/141'/2147483647/0/0 65 | derivation_path = "44H/141H/2147483647/0/0" 66 | derived_key = key.subkey_for_path(derivation_path) 67 | public_key_hex = derived_key.sec().hex() 68 | hash160 = derived_key.hash160() 69 | print(f"INFO Public key: {public_key_hex}") # 025a3fdcfb4f39c44075c306cf050efeb1311a49694ba606e2abb4d78da428b4e8 70 | print(f"INFO Public key hash: {hash160.hex()}") # e0cbb8142006152cf294b2db527ba421e94a52f3 71 | 72 | # address = derived_key.address() 73 | # kmd_address = get_custom_address(hash160, b'\x3c') 74 | # kmd_address = KMD.address.for_p2pkh(hash160) 75 | # print(f"BTC address: {address}") 76 | # print(f"KMD address:", kmd_address) 77 | 78 | # m/44'/141'/0' 79 | m0_key = key.subkey_for_path("44H/141H/0H/0") 80 | num_addresses = 20 81 | print("Path\t\tAddress\t\t\t\tPublic Key (hex)\t\t\t\tPrivate Key (WIF)") 82 | print("---------------------------------------------------------------------------------------------------------") 83 | 84 | # Derive m/44'/141'/0'/0/i and print details 85 | for i in range(num_addresses): 86 | 87 | child_key = m0_key.subkey(i) 88 | path = f"m/44'/141'/0'/0/{i}" 89 | # address = get_custom_address(child_key.hash160(), b'\x3c') 90 | address = KMD.address.for_p2pkh(child_key.hash160()) 91 | public_key_hex = child_key.sec().hex() 92 | # private_key_wif = child_key.wif() 93 | private_key_wif = KMD.wif_for_blob(to_bytes_32(child_key.secret_exponent()) + b'\01') 94 | print(f"{path}\t{address}\t{public_key_hex}\t{private_key_wif}") 95 | # print(f"{wif_to_bech32_address(private_key_wif)}") 96 | 97 | if __name__ == "__main__": 98 | main() 99 | -------------------------------------------------------------------------------- /bip32/muun_address.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeckerSU/komodo_scripts/883b63347beaae5b59bc2d448144c0cbb4402c5f/bip32/muun_address.jpg -------------------------------------------------------------------------------- /bip32/muun_emergency_kit.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeckerSU/komodo_scripts/883b63347beaae5b59bc2d448144c0cbb4402c5f/bip32/muun_emergency_kit.jpg -------------------------------------------------------------------------------- /bip32/requirements.txt: -------------------------------------------------------------------------------- 1 | ansible==9.4.0 2 | ansible-core==2.16.6 3 | apturl==0.5.2 4 | base58==1.0.3 5 | bcrypt==3.2.0 6 | beautifulsoup4==4.10.0 7 | bitcoin==1.1.42 8 | blinker==1.7.0 9 | Brlapi==0.8.3 10 | bsddb3==6.2.9 11 | build==1.2.2 12 | certifi==2020.6.20 13 | chardet==4.0.0 14 | click==8.1.7 15 | colorama==0.4.4 16 | command-not-found==0.3 17 | configobj==5.0.6 18 | cryptography==3.4.8 19 | cupshelpers==1.0 20 | dbus-python==1.2.18 21 | decorator==5.1.1 22 | defer==1.0.6 23 | Deprecated==1.2.13 24 | distlib==0.3.6 25 | distro==1.7.0 26 | distro-info==1.1+ubuntu0.2 27 | duplicity==0.8.21 28 | fasteners==0.14.1 29 | filelock==3.9.0 30 | Flask==3.0.0 31 | future==0.18.2 32 | gramps==5.2.2 33 | graphtools==1.5.3 34 | gunicorn==21.2.0 35 | html5lib==1.1 36 | httplib2==0.20.2 37 | idna==3.3 38 | img2pdf==0.4.2 39 | importlib-metadata==4.6.4 40 | itsdangerous==2.1.2 41 | jeepney==0.7.1 42 | Jinja2==3.1.3 43 | joblib==1.2.0 44 | keyring==23.5.0 45 | language-selector==0.1 46 | launchpadlib==1.10.16 47 | lazr.restfulclient==0.14.4 48 | lazr.uri==1.0.6 49 | lockfile==0.12.2 50 | louis==3.20.0 51 | lxml==4.8.0 52 | macaroonbakery==1.3.1 53 | Mako==1.1.3 54 | Markdown==3.3.6 55 | MarkupSafe==2.1.3 56 | meld==3.20.4 57 | meson==0.61.2 58 | monotonic==1.6 59 | more-itertools==8.10.0 60 | netifaces==0.11.0 61 | numpy==1.24.1 62 | oauthlib==3.2.0 63 | olefile==0.46 64 | packaging==24.1 65 | pandas==1.3.5 66 | paramiko==2.9.3 67 | pexpect==4.8.0 68 | pikepdf==5.0.1+dfsg 69 | Pillow==9.0.1 70 | pip-tools==7.4.1 71 | pipdeptree==2.23.4 72 | platformdirs==2.6.2 73 | protobuf==3.12.4 74 | psutil==5.9.0 75 | ptyprocess==0.7.0 76 | py==1.10.0 77 | pycairo==1.20.1 78 | pycoin==0.92.20241201 79 | pycryptodome==3.21.0 80 | pycups==2.0.1 81 | pycurl==7.43.0.2 82 | Pygments==2.11.2 83 | PyGObject==3.42.1 84 | PyGSP==0.5.1 85 | PyICU==2.8.1 86 | PyJWT==2.3.0 87 | pymacaroons==0.13.0 88 | PyNaCl==1.5.0 89 | pyparsing==3.2.0 90 | pyproject_hooks==1.2.0 91 | pyRFC3339==1.1 92 | PySocks==1.7.1 93 | python-apt==2.4.0+ubuntu4 94 | python-dateutil==2.8.1 95 | python-debian==0.1.43+ubuntu1.1 96 | pytz==2022.1 97 | pyxdg==0.27 98 | PyYAML==5.4.1 99 | pyzmq==22.3.0 100 | reportlab==3.6.8 101 | requests==2.25.1 102 | resolvelib==1.0.1 103 | scikit-learn==1.2.1 104 | scipy==1.10.0 105 | scprep==1.2.1 106 | screen-resolution-extra==0.0.0 107 | SecretStorage==3.3.1 108 | six==1.12.0 109 | sklearn==0.0.post1 110 | slick-bitcoinrpc==0.1.4 111 | soupsieve==2.3.1 112 | speedtest-cli==2.1.3 113 | ssh-import-id==5.11 114 | systemd-python==234 115 | tasklogger==1.2.0 116 | terminator==2.1.1 117 | threadpoolctl==3.1.0 118 | tomli==2.0.2 119 | ubuntu-drivers-common==0.0.0 120 | ubuntu-pro-client==8001 121 | ufw==0.36.1 122 | ujson==1.35 123 | unattended-upgrades==0.1 124 | urllib3==1.26.5 125 | usb-creator==0.3.7 126 | vboxapi==1.0 127 | virtualenv==20.17.1 128 | wadllib==1.3.6 129 | webencodings==0.5.1 130 | Werkzeug==3.0.1 131 | wrapt==1.14.1 132 | xdg==5 133 | xkit==0.0.0 134 | zipp==1.0.0 135 | -------------------------------------------------------------------------------- /check-data-folders.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Read the kmd_coins array from assetchains.json 4 | readarray -t kmd_coins < <(cat "$HOME/dPoW/iguana/assetchains.json" | jq -r '[.[].ac_name] | join("\n")') 5 | 6 | # Set color variables 7 | GREEN='\033[1;32m' 8 | RED='\033[1;31m' 9 | NC='\033[0m' # No Color 10 | 11 | # Folders to skip 12 | skip_folders=("chainstate" "database" "notarisations" "blocks" "GLEEC_OLD") 13 | 14 | # Scan folders in ~/.komodo and check against kmd_coins array 15 | for folder in "$HOME/.komodo"/*; do 16 | # Only check if it is a directory 17 | if [ -d "$folder" ]; then 18 | folder_name=$(basename "$folder") 19 | 20 | # Skip specific folders 21 | if [[ " ${skip_folders[@]} " =~ " ${folder_name} " ]]; then 22 | continue 23 | fi 24 | 25 | # Check if the folder name exists in the kmd_coins array 26 | if [[ " ${kmd_coins[@]} " =~ " ${folder_name} " ]]; then 27 | echo -e "${GREEN}Ok${NC} - $folder_name" 28 | else 29 | echo -e "${RED}Delete${NC} - $folder_name" 30 | fi 31 | fi 32 | done 33 | -------------------------------------------------------------------------------- /checkseed.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright (c) 2020-2021 Decker 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | 8 | 9 | # seeder=seeds.komodoplatform.com # almost dead seeder, from 16 addresses return just one alive 10 | # seeder=kmd.komodoseeds.com # also almost dead, contains only 2 addresses 11 | # seeder=static.kolo.supernet.org 12 | # seeder=dynamic.kolo.supernet.org 13 | 14 | seeder=seeds1.kmd.sh 15 | 16 | #readarray -t nodeips < <(nslookup ${seeder} | grep "Address: " | awk '{print $2}' | sed 's/:[0-9]*[0-9]*[0-9]*[0-9]*//g' | sort) 17 | readarray -t nodeips < <(host seeds1.kmd.sh | grep -Po "has address [0-9]+\.[0-9]+\.[0-9]+\.[0-9]+" | sed 's/has address//' | sort) 18 | 19 | #nodeips=(5.9.102.210 78.47.196.146 178.63.69.164 88.198.65.74 5.9.122.241 144.76.94.38 89.248.166.91) 20 | 21 | for ip in "${nodeips[@]}" 22 | do 23 | # https://bitcointalk.org/index.php?topic=55852.0 24 | # https://en.bitcoin.it/wiki/Protocol_documentation#Message_structure 25 | # Newer protocol, # 18980200 - 170008 -> 1a980200 - 170010 26 | # Newer protocol, # 1d980200 - 170013 27 | 28 | payload='1d980200010000000000000011b2d05000000000010000000000000000000000000000000000ffff000000000000000000000000000000000000000000000000ffff0000000000003b2eb35d8ce617650f2f5361746f7368693a302e372e322fc03e0300'; 29 | payload_size=$((${#payload} / 2)) 30 | payload_size_hex=$(printf "%08x" $payload_size | dd conv=swab 2> /dev/null | rev) 31 | payload_sha256d=$(echo -n $payload | xxd -r -p | sha256sum --binary | cut -d" " -f1 | xxd -r -p | sha256sum --binary | cut -d" " -f1) 32 | payload_checksum=${payload_sha256d:0:8} 33 | 34 | #message='f9eee48d76657273696f6e0000000000640000005cee709118980200010000000000000011b2d05000000000010000000000000000000000000000000000ffff000000000000000000000000000000000000000000000000ffff0000000000003b2eb35d8ce617650f2f5361746f7368693a302e372e322fc03e0300' 35 | message="f9eee48d76657273696f6e0000000000${payload_size_hex}${payload_checksum}${payload}" 36 | #echo -n "Checking ${ip} - " 37 | printf "Checking %15s - " ${ip} 38 | echo -ne ${message} | xxd -r -p | nc -w 3 ${ip} 7770 > pattern.txt 39 | if [ ! -s pattern.txt ]; then 40 | echo "failed!" 41 | else 42 | len=$(cat pattern.txt | xxd -p -s 0x68 -l 1) 43 | len=$((16#$len)) 44 | 45 | ua=$(cat pattern.txt | xxd -p -s 0x69 -l $len | xxd -r -p) 46 | echo $ua 47 | fi 48 | done 49 | -------------------------------------------------------------------------------- /cleanwallets-mainnet.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | determine_komodo_cli() { 4 | local cli_path 5 | # Check system-wide installation 6 | cli_path=$(command -v komodo-cli 2>/dev/null) 7 | if [[ -x "$cli_path" ]]; then 8 | echo "Found system-wide komodo-cli at: $cli_path" >&2 9 | echo "$cli_path" 10 | return 0 11 | fi 12 | 13 | # Check in ~/komodo/src 14 | cli_path="$HOME/komodo/src/komodo-cli" 15 | if [[ -x "$cli_path" ]]; then 16 | echo "Found komodo-cli at: $cli_path" >&2 17 | echo "$cli_path" 18 | return 0 19 | fi 20 | 21 | # Check in ~/KomodoOcean/src 22 | cli_path="$HOME/KomodoOcean/src/komodo-cli" 23 | if [[ -x "$cli_path" ]]; then 24 | echo "Found komodo-cli at: $cli_path" >&2 25 | echo "$cli_path" 26 | return 0 27 | fi 28 | 29 | # komodo-cli not found 30 | echo -e "${RED}Error:${RESET} komodo-cli not found in system-wide path, $HOME/komodo/src, or $HOME/KomodoOcean/src." >&2 31 | exit 1 32 | } 33 | 34 | # Function to source pubkey.txt from multiple locations 35 | source_pubkey() { 36 | local pubkey_file 37 | local found=0 38 | 39 | # Define the search order 40 | local search_paths=( 41 | "$HOME/komodo/src/pubkey.txt" 42 | "$HOME/KomodoOcean/src/pubkey.txt" 43 | "$HOME/pubkey.txt" 44 | ) 45 | 46 | # Iterate through the search paths 47 | for pubkey_file in "${search_paths[@]}"; do 48 | if [[ -f "$pubkey_file" ]]; then 49 | echo "Found pubkey.txt at: $pubkey_file" >&2 50 | source "$pubkey_file" 51 | found=1 52 | break 53 | fi 54 | done 55 | 56 | # Check if pubkey.txt was found and sourced 57 | if [[ "$found" -ne 1 ]]; then 58 | echo -e "${RED}Error:${RESET} pubkey.txt not found in any of the specified locations." >&2 59 | exit 1 60 | fi 61 | 62 | # Ensure that the pubkey environment variable is set 63 | if [[ -z "$pubkey" ]]; then 64 | echo -e "${RED}Error:${RESET} pubkey environment variable is not set after sourcing pubkey.txt." >&2 65 | exit 1 66 | fi 67 | 68 | echo -e "Pubkey: \"${pubkey}\"" 69 | } 70 | 71 | komodo_cli_binary=$(determine_komodo_cli) 72 | source_pubkey 73 | KMD_ADDRESS=$(${komodo_cli_binary} decodescript "21${pubkey}ac" | jq -r .addresses[0]) 74 | printf "KMD Address: ${YELLOW}%-40s${RESET}\n" "$KMD_ADDRESS" 75 | 76 | #readarray -t kmd_coins < <(curl -s https://raw.githubusercontent.com/KomodoPlatform/dPoW/master/iguana/assetchains.json | jq -r '[.[].ac_name] | join("\n")') 77 | readarray -t kmd_coins < <(cat $HOME/dPoW/iguana/assetchains.json | jq -r '[.[].ac_name] | join("\n")') 78 | 79 | gleec_count=0 80 | for i in "${kmd_coins[@]}" 81 | do 82 | if [[ "$i" == "GLEEC" ]]; then 83 | ((gleec_count++)) 84 | 85 | if [[ "$gleec_count" -eq 1 ]]; then 86 | echo Processing "GLEEC_OLD" 1>&2 87 | ${komodo_cli_binary} -ac_name="GLEEC" -datadir="$HOME/.komodo/GLEEC_OLD" cleanwallettransactions 88 | elif [[ "$gleec_count" -eq 2 ]]; then 89 | echo Processing "GLEEC" 1>&2 90 | ${komodo_cli_binary} -ac_name="GLEEC" cleanwallettransactions 91 | else 92 | echo -e "GLEEC has been encountered more than twice. No additional actions will be performed." >&2 93 | fi 94 | continue 95 | fi 96 | 97 | echo Processing "$i" 1>&2 98 | #time (${komodo_cli_binary} -ac_name="$i" listunspent | jq '. | { "utxos" : length }' && ${komodo_cli_binary} -ac_name="$i" getwalletinfo | jq '{ "txcount" : .txcount }') | jq -s add 99 | #${komodo_cli_binary} -ac_name="$i" z_mergetoaddress '["ANY_TADDR"]' $KMD_ADDRESS 0.001 0 100 | ${komodo_cli_binary} -ac_name="$i" cleanwallettransactions 101 | done 102 | 103 | echo Processing "KMD" 1>&2 104 | #${komodo_cli_binary} z_mergetoaddress '["ANY_TADDR"]' $KMD_ADDRESS 0.001 0 105 | #sleep 5 106 | ${komodo_cli_binary} cleanwallettransactions 107 | echo Processing "LTC" 1>&2 108 | $HOME/litecoin/src/litecoin-cli cleanwallettransactions 109 | 110 | 111 | -------------------------------------------------------------------------------- /coinsupply.php: -------------------------------------------------------------------------------- 1 | $method, "params" => $params ) ); 28 | // var_dump($payload); 29 | curl_setopt( $ch, CURLOPT_POSTFIELDS, $payload ); 30 | curl_setopt( $ch, CURLOPT_HTTPHEADER, array('Content-Type:application/json')); 31 | 32 | 33 | $data["result"] = curl_exec($ch); 34 | $data["http_code"] = curl_getinfo($ch)["http_code"]; 35 | curl_close($ch); 36 | // var_dump($data); 37 | return $data; 38 | 39 | } 40 | 41 | if(php_sapi_name() != "cli") return; 42 | 43 | // https://stackoverflow.com/questions/31888566/bootstrap-how-to-sort-table-columns 44 | 45 | $blocks_res = daemon_request("127.0.0.1", RPCPORT, RPCUSER, RPCPASSWORD, "getblockcount", Array()); 46 | if ($blocks_res["http_code"] == 200) { 47 | $blocks_json_object = json_decode($blocks_res["result"]); 48 | $blocks = $blocks_json_object->result; 49 | 50 | $sumvalueZat = "0"; 51 | for ($block_height = 0; $block_height < $blocks; $block_height++) { 52 | //for ($block_height = 1; $block_height < $blocks; $block_height++) { 53 | if ($block_height % 1000 == 0) 54 | { 55 | fwrite(STDERR, "Parsing block #$block_height (".bcdiv($sumvalueZat, SATOSHIDEN, 8)." KMD)\n"); 56 | } 57 | 58 | $fgetblocksuccess = false; 59 | 60 | while (!$fgetblocksuccess) { 61 | $res = daemon_request("127.0.0.1", RPCPORT, RPCUSER, RPCPASSWORD, "getblock", Array("".$block_height)); 62 | if ($res["http_code"] == 200) { 63 | $fgetblocksuccess = true; 64 | $json_object = json_decode($res["result"]); 65 | $hash = $json_object->result->hash; 66 | $height = $json_object->result->height; 67 | $txs = $json_object->result->tx; 68 | /*foreach ($txs as $tx) { 69 | echo $tx . "\n"; 70 | }*/ 71 | if ($txs[0]) { 72 | $fgettxsuccess = false; 73 | 74 | if ($txs[0] == "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b") $fgettxsuccess = true; 75 | 76 | while (!$fgettxsuccess) { 77 | $tx_res = daemon_request("127.0.0.1", RPCPORT, RPCUSER, RPCPASSWORD, "getrawtransaction", Array($txs[0], 1)); 78 | $value = "0"; $address = ""; 79 | if ($tx_res["http_code"] == 200) { 80 | $fgettxsuccess = true; 81 | $tx_json_object = json_decode($tx_res["result"]); 82 | //var_dump($tx_json_object); 83 | //$value = "".$tx_json_object->result->vout[0]->value; 84 | //$address = "".$tx_json_object->result->vout[0]->scriptPubKey->addresses[0]; 85 | $vouts = $tx_json_object->result->vout; 86 | if (count($vouts) > 0) { 87 | foreach($vouts as $vout) { 88 | $sumvalueZat = bcadd($sumvalueZat, $vout->valueZat); 89 | } 90 | } 91 | } 92 | if (!$fgettxsuccess) { 93 | fwrite(STDERR, "Re-requesting tx #".$block_height."/".$txs[0]."\n"); 94 | sleep(60); 95 | } 96 | 97 | } // while (!$fgettxsuccess) 98 | 99 | } 100 | 101 | } 102 | if (!$fgetblocksuccess) { 103 | fwrite(STDERR, "Re-requesting block #$block_height (".bcdiv($sumvalueZat, SATOSHIDEN, 8)." KMD)\n"); 104 | sleep(60); 105 | } 106 | } // while (!$fgetblocksuccess) 107 | } 108 | } else die("Can't request block count [ERROR ".$blocks_res["http_code"]."] ".var_export($blocks_res["result"],1)); 109 | echo "Coin Supply: " . bcdiv($sumvalueZat, SATOSHIDEN, 8) . " KMD\r\n"; 110 | 111 | ?> -------------------------------------------------------------------------------- /createrawtx.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # (c) Decker, 2018 ;) 3 | 4 | # bash script to create unsigned raw tx from utxos selected via filter 5 | 6 | curdir=$(pwd) 7 | curluser=user 8 | curlpass=pass 9 | curlport=7771 10 | asset= 11 | 12 | curl -s --user $curluser:$curlpass --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "listunspent", "params": [0, 9999999]}' -H 'content-type: text/plain;' http://127.0.0.1:$curlport/ | jq .result > $curdir/createrawtx.txt 13 | # set condition on amount on a next line 14 | transactions=$(cat $curdir/createrawtx.txt | jq '.[] | select (.spendable == true and .amount > 0) | del (.generated, .address, .account, .scriptPubKey, .amount, .interest, .confirmations, .spendable)' | jq -r -s '. | tostring') 15 | 16 | addresses='{"RTCVGuoSNehKG8YYxcoskC7LK1yZhgvQRV":1000.0}' # how to calc sum of amounts of each utxo - is your hometask :) PRs are welcome ) 17 | 18 | echo "{\"jsonrpc\": \"1.0\", \"id\":\"curltest\", \"method\": \"createrawtransaction\", \"params\": [$transactions,$addresses] }" > $curdir/createrawtx.curl 19 | 20 | # we are using curl here to avoid an error "Argument list too long" with long-long list of utxos need to be locked 21 | # if we executing komodo-cli 22 | 23 | curl -s --user $curluser:$curlpass --data-binary "@$curdir/createrawtx.curl" -H 'content-type: text/plain;' http://127.0.0.1:$curlport/ | jq -r .result 24 | 25 | -------------------------------------------------------------------------------- /daemons-restart.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # this script restarts all started komodo daemons with same params 4 | 5 | CUR_DIR=$(pwd) 6 | komodo_cli="$HOME/komodo/src/komodo-cli" 7 | komodo_daemon="$HOME/komodo/src/komodod" 8 | 9 | # NB! path to search assetchains.json will be derived from komodod location, in this example 10 | # assetchains.json should be available in $HOME/komodo/src . 11 | 12 | function init_colors () 13 | { 14 | RESET="\033[0m" 15 | BLACK="\033[30m" 16 | RED="\033[31m" 17 | GREEN="\033[32m" 18 | YELLOW="\033[33m" 19 | BLUE="\033[34m" 20 | MAGENTA="\033[35m" 21 | CYAN="\033[36m" 22 | WHITE="\033[37m" 23 | } 24 | 25 | # -------------------------------------------------------------------------- 26 | function log_print() 27 | { 28 | datetime=$(date '+%Y-%m-%d %H:%M:%S') 29 | echo -e [$datetime] $1 30 | } 31 | 32 | # -------------------------------------------------------------------------- 33 | function wait_for_daemon() 34 | { 35 | #if [[ ! -z $1 && $1 != "KMD" ]] 36 | if [ ! -z $1 ] && [ $1 != "KMD" ] 37 | then 38 | coin=$1 39 | asset=" -ac_name=$1" 40 | else 41 | coin="KMD" 42 | asset="" 43 | fi 44 | 45 | i=0 46 | while ! $komodo_cli $asset getinfo >/dev/null 2>&1 47 | do 48 | i=$((i+1)) 49 | log_print "Waiting for daemon start/active $coin ($i)" 50 | sleep 1 51 | # TODO: in case if daemon start too long, for example, more than 5-7 mins. we should exit from script 52 | done 53 | } 54 | 55 | # -------------------------------------------------------------------------- 56 | function stop_daemon() 57 | { 58 | 59 | #if [[ ! -z $1 && $1 != "KMD" ]] 60 | if [ ! -z $1 ] && [ $1 != "KMD" ] 61 | then 62 | coin=$1 63 | asset=" -ac_name=$1" 64 | else 65 | coin="KMD" 66 | asset="" 67 | fi 68 | 69 | i=0 70 | $komodo_cli $asset stop 71 | 72 | if [ $coin == "KMD" ] 73 | then 74 | ddatadir=$HOME/.komodo 75 | else 76 | ddatadir=$HOME/.komodo/$coin 77 | fi 78 | 79 | while [ -f $ddatadir/komodod.pid ] 80 | do 81 | i=$((i+1)) 82 | log_print "Waiting for daemon $coin stop ($i)" 83 | sleep 1 84 | done 85 | 86 | while [ ! -z $(lsof -Fp $ddatadir/.lock | head -1 | cut -c 2-) ] 87 | do 88 | i=$((i+1)) 89 | log_print "Waiting for .lock release by $coin ($i)" 90 | sleep 1 91 | done 92 | 93 | } 94 | # -------------------------------------------------------------------------- 95 | function restart_daemon() { 96 | 97 | if [ ! -z $1 ] && [ $1 != "KMD" ] 98 | then 99 | coin=$1 100 | asset=" -ac_name=$1" 101 | else 102 | coin="KMD" 103 | asset="" 104 | fi 105 | 106 | log_print "Process ($coin) ..." 107 | wait_for_daemon $coin 108 | 109 | # disable generate to avoid daemon crash during multiple "error adding notary vin" messages 110 | $komodo_cli $asset setgenerate false 111 | 112 | blockhash=$($komodo_cli $asset getbestblockhash) 113 | height=$($komodo_cli $asset getblock $blockhash | jq .height) 114 | 115 | log_print "ht.$height ($blockhash)" 116 | 117 | if [ $coin == "KMD" ] 118 | then 119 | daemon_args=$(ps -fC komodod | grep -v -- "-ac_name=" | grep -Po "komodod .*" | sed 's/komodod//g') 120 | else 121 | daemon_args=$(ps -fC komodod | grep -- "-ac_name=$coin" | grep -Po "komodod .*" | sed 's/komodod//g') 122 | fi 123 | 124 | # if previous time daemon launched with reindex or rescan, we don't need to re-launch daemon with same params, 125 | # so, we just remove them from launch string. 126 | 127 | daemon_args=$(echo $daemon_args | sed -e "s/-reindex//g") 128 | daemon_args=$(echo $daemon_args | sed -e "s/-rescan//g") 129 | 130 | log_print "($coin) Args: \"$daemon_args\"" 131 | 132 | # TODO: check args, if we can't get arg and can't start daemon, don't need to stop it (!) 133 | 134 | log_print "Stopping daemon ... " 135 | stop_daemon $coin 136 | 137 | sleep 5 138 | log_print "Starting daemon ($coin) ... " 139 | 140 | # *** STARTING DAEMON *** 141 | $komodo_daemon $daemon_args & 142 | 143 | wait_for_daemon $coin 144 | 145 | log_print "Done process ($coin)" 146 | 147 | } 148 | 149 | STEP_START='\e[1;47;42m' 150 | STEP_END='\e[0m' 151 | 152 | init_colors 153 | 154 | echo Current directory: $CUR_DIR 155 | #log_print "$STEP_START[ Step 1 ]$STEP_END Daemons re-start" 156 | #cd $CUR_DIR/komodo/src 157 | 158 | # source $CUR_DIR/kmd_coins.sh 159 | readarray -t kmd_coins < <(cat $(dirname ${komodo_daemon})/assetchains.json | jq -r '[.[].ac_name] | join("\n")') 160 | # printf '%s\n' "${kmd_coins[@]}" 161 | for i in "${kmd_coins[@]}" 162 | do 163 | # VRSC uses different daemon, so we don't need to re-start it from komodo repo folder 164 | if [ $i != "VRSC" ] && [ $i != "THC" ]; then 165 | log_print "$STEP_START[ $i ]$STEP_END" 166 | restart_daemon $i 167 | fi 168 | done 169 | 170 | #cd $CUR_DIR 171 | -------------------------------------------------------------------------------- /debian_build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # GameCredits/Chips build script for Ubuntu & Debian 9 v.3 (c) Decker 3 | 4 | # Step 1: Build BDB 4.8 5 | COINDAEMON_ROOT=$(pwd) 6 | COINDAEMON_PREFIX="${COINDAEMON_ROOT}/db4" 7 | mkdir -p $COINDAEMON_PREFIX 8 | wget -N 'http://download.oracle.com/berkeley-db/db-4.8.30.NC.tar.gz' 9 | echo '12edc0df75bf9abd7f82f821795bcee50f42cb2e5f76a6a281b85732798364ef db-4.8.30.NC.tar.gz' | sha256sum -c 10 | tar -xzvf db-4.8.30.NC.tar.gz 11 | cd db-4.8.30.NC/build_unix/ 12 | 13 | ../dist/configure -enable-cxx -disable-shared -with-pic -prefix=$COINDAEMON_PREFIX 14 | 15 | make -j$(nproc) 16 | make install 17 | cd $COINDAEMON_ROOT 18 | 19 | # Step 2: Build OpenSSL (libssl-dev) 1.0.x 20 | version=1.0.2o 21 | mkdir -p openssl_build 22 | wget -qO- http://www.openssl.org/source/openssl-$version.tar.gz | tar xzv 23 | cd openssl-$version 24 | export CFLAGS=-fPIC 25 | ./config no-shared --prefix=$COINDAEMON_ROOT/openssl_build 26 | make -j$(nproc) 27 | make install 28 | cd .. 29 | 30 | export PKG_CONFIG_PATH="$COINDAEMON_ROOT/openssl_build/pkgconfig" 31 | export CXXFLAGS+=" -I$COINDAEMON_ROOT/openssl_build/include/ -I${COINDAEMON_PREFIX}/include/" 32 | export LDFLAGS+=" -L$COINDAEMON_ROOT/openssl_build/lib -L${COINDAEMON_PREFIX}/lib/ -static" 33 | export LIBS+="-ldl" 34 | 35 | # p.s. for Debian added -ldl in LDFLAGS it's enough, but on Ubuntu linker doesn't recognize it, so, 36 | # we moved -ldl to LIBS and added -static to LDFLAGS, because linker on Ubuntu doesn't understan that 37 | # it should link librypto.a statically. 38 | # 39 | # Or we can build OpenSSL 1.0.x as shared (instead of no-shared) and use: 40 | # export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/$USER/$COINDAEMON/openssl_build/lib before 41 | # starting coind. 42 | 43 | # Step 3: Build Coin daemon 44 | ./autogen.sh 45 | ./configure --with-gui=no --disable-tests --disable-bench --without-miniupnpc --enable-experimental-asm --enable-static --disable-shared 46 | make -j$(nproc) 47 | -------------------------------------------------------------------------------- /debian_build_gcc8.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # GameCredits/Chips build script for Ubuntu & Debian 9 v.3 (c) Decker 3 | 4 | # Step 1: Build BDB 4.8 5 | COINDAEMON_ROOT=$(pwd) 6 | COINDAEMON_PREFIX="${COINDAEMON_ROOT}/db4" 7 | mkdir -p $COINDAEMON_PREFIX 8 | wget -N 'http://download.oracle.com/berkeley-db/db-4.8.30.NC.tar.gz' 9 | echo '12edc0df75bf9abd7f82f821795bcee50f42cb2e5f76a6a281b85732798364ef db-4.8.30.NC.tar.gz' | sha256sum -c 10 | tar -xzvf db-4.8.30.NC.tar.gz 11 | 12 | sed -i 's/__atomic_compare_exchange/__atomic_compare_exchange_db/' db-4.8.30.NC/dbinc/atomic.h 13 | 14 | cd db-4.8.30.NC/build_unix/ 15 | 16 | ../dist/configure -enable-cxx -disable-shared -with-pic -prefix=$COINDAEMON_PREFIX 17 | 18 | make -j$(nproc) 19 | make install 20 | cd $COINDAEMON_ROOT 21 | 22 | # Step 2: Build OpenSSL (libssl-dev) 1.0.x 23 | version=1.0.2o 24 | mkdir -p openssl_build 25 | wget -qO- http://www.openssl.org/source/openssl-$version.tar.gz | tar xzv 26 | cd openssl-$version 27 | export CFLAGS=-fPIC 28 | ./config no-shared --prefix=$COINDAEMON_ROOT/openssl_build 29 | make -j$(nproc) 30 | make install 31 | cd .. 32 | 33 | export PKG_CONFIG_PATH="$COINDAEMON_ROOT/openssl_build/pkgconfig" 34 | export CXXFLAGS+=" -I$COINDAEMON_ROOT/openssl_build/include/ -I${COINDAEMON_PREFIX}/include/" 35 | export LDFLAGS+=" -L$COINDAEMON_ROOT/openssl_build/lib -L${COINDAEMON_PREFIX}/lib/ -static" 36 | export LIBS+="-ldl" 37 | 38 | # p.s. for Debian added -ldl in LDFLAGS it's enough, but on Ubuntu linker doesn't recognize it, so, 39 | # we moved -ldl to LIBS and added -static to LDFLAGS, because linker on Ubuntu doesn't understan that 40 | # it should link librypto.a statically. 41 | # 42 | # Or we can build OpenSSL 1.0.x as shared (instead of no-shared) and use: 43 | # export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/$USER/$COINDAEMON/openssl_build/lib before 44 | # starting coind. 45 | 46 | # Step 3: Build Coin daemon 47 | ./autogen.sh 48 | ./configure --with-gui=no --disable-tests --disable-bench --without-miniupnpc --enable-experimental-asm --enable-static --disable-shared 49 | make -j$(nproc) 50 | -------------------------------------------------------------------------------- /dns-seeder-update-gandi.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Coind DNS Seed Updater v0.01 (c) Decker, 2019-2021 4 | 5 | # This script updates A-records for selected zone via Gandi.net API, 6 | # new seeds retrieve from coin daemon outgoing peers. Script updates 7 | # only A (IPv4) records and doesn't check IP in case if it is from 8 | # Bogon/Bogus networks. 9 | 10 | # -------------------------------------------------------------------------- 11 | function init_colors() { 12 | RESET="\033[0m" 13 | BLACK="\033[30m" 14 | RED="\033[31m" 15 | GREEN="\033[32m" 16 | YELLOW="\033[33m" 17 | BLUE="\033[34m" 18 | MAGENTA="\033[35m" 19 | CYAN="\033[36m" 20 | WHITE="\033[37m" 21 | BRIGHT="\033[1m" 22 | DARKGREY="\033[90m" 23 | } 24 | # -------------------------------------------------------------------------- 25 | function log_print() { 26 | datetime=$(date '+%Y-%m-%d %H:%M:%S') 27 | echo -e [$datetime] $1 28 | } 29 | 30 | # -------------------------------------------------------------------------- 31 | # https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html 32 | 33 | function checkconfig() 34 | { 35 | if ! grep -qs '^rpcpassword=' "${KOMODOD_CONFIGFILE}" ; then 36 | log_print "Parsing: ${KOMODOD_CONFIGFILE} - ${RED}FAILED${RESET}" 37 | return 1 38 | fi 39 | if ! grep -qs '^rpcuser=' "${KOMODOD_CONFIGFILE}" ; then 40 | log_print "Parsing: ${KOMODOD_CONFIGFILE} - ${RED}FAILED${RESET}" 41 | return 1 42 | fi 43 | 44 | grep -qs '^rpcpassword=' "${KOMODOD_CONFIGFILE}" 45 | KOMODOD_RPCPASSWORD=$(grep -s '^rpcpassword=' "${KOMODOD_CONFIGFILE}") 46 | KOMODOD_RPCPASSWORD=${KOMODOD_RPCPASSWORD/rpcpassword=/} 47 | 48 | grep -qs '^rpcuser=' "${KOMODOD_CONFIGFILE}" 49 | KOMODOD_RPCUSER=$(grep -s '^rpcuser=' "${KOMODOD_CONFIGFILE}") 50 | KOMODOD_RPCUSER=${KOMODOD_RPCUSER/rpcuser=/} 51 | 52 | if ! grep -qs '^rpcport=' "${KOMODOD_CONFIGFILE}" ; then 53 | KOMODO_RPCPORT=7771 54 | else 55 | KOMODO_RPCPORT=$(grep -s '^rpcport=' "${KOMODOD_CONFIGFILE}") 56 | KOMODO_RPCPORT=${KOMODO_RPCPORT/rpcport=/} 57 | fi 58 | 59 | log_print "Parsing RPC credentials: ${KOMODOD_CONFIGFILE} - ${GREEN}OK${RESET}" 60 | 61 | } 62 | # -------------------------------------------------------------------------- 63 | function getpeerinfo() { 64 | res=$(curl -s --user "${KOMODOD_RPCUSER}:${KOMODOD_RPCPASSWORD}" --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getpeerinfo", "params": [] }' -H 'content-type: text/plain;' http://${KOMODOD_RPCHOST}:${KOMODO_RPCPORT}/) 65 | if [ "$(echo ${res} | jq .error)" == null ]; then 66 | PEERINFO="$(echo ${res} | jq .result)" 67 | else 68 | PEERINFO=[] 69 | log_print "${RED}ERROR $(echo ${res} | jq .error.code) : $(echo ${res} | jq -r .error.message)${RESET}" 70 | return 1 71 | fi 72 | } 73 | # -------------------------------------------------------------------------- 74 | 75 | # daemon config 76 | KOMODOD_DEFAULT_DATADIR=${KOMODOD_DEFAULT_DATADIR:-"$HOME/.komodo"} 77 | KOMODOD_CONFIGFILE=${KOMODOD_CONFIGFILE:-"$KOMODOD_DEFAULT_DATADIR/komodo.conf"} 78 | KOMODOD_RPCHOST=127.0.0.1 79 | 80 | # Gandi API doc: 81 | # https://doc.livedns.gandi.net/ 82 | 83 | # gandi account config 84 | DOMAIN="example.org" 85 | RECORD="seeds" 86 | APIKEY="YOUR_GANDI_API_KEY" 87 | APPLY_CHANGES=true 88 | 89 | init_colors 90 | log_print "Starting ..." 91 | checkconfig || exit 92 | getpeerinfo || exit 93 | 94 | # https://unix.stackexchange.com/questions/296596/how-to-check-if-any-ip-address-is-present-in-a-file-using-shell-scripting 95 | readarray -t nodeips < <(echo ${PEERINFO} | jq -r '.[] | select (.inbound == false) | .addr' | grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b") 96 | 97 | # first we should get zone UUID from API or set it directly 98 | # auto rerieve UUID 99 | UUID=$(curl -s -H "X-Api-Key: $APIKEY" https://dns.api.gandi.net/api/v5/zones | jq -r '.[] | select (.name == "'${DOMAIN}'") | .uuid') 100 | # manual set of UUID 101 | # UUID=00000000-1111-2222-3333-444444444444 102 | 103 | log_print "Zone UUID: ${UUID}" 104 | 105 | # List all records in the zone UUID and filter needed by jq 106 | # SEEDS=$(curl -s -H "X-Api-Key: $APIKEY" https://dns.api.gandi.net/api/v5/zones/${UUID}/records | jq -r '.[] | select (.rrset_type == "A" and .rrset_name == "'${RECORD}'") | .rrset_values') 107 | 108 | # List all records with name "NAME" and type "TYPE" in the zone UUID 109 | SEEDS=$(curl -s -H "X-Api-Key: $APIKEY" "https://dns.api.gandi.net/api/v5/zones/${UUID}/records/${RECORD}/A" | jq -r '.rrset_values') 110 | log_print "Current seeds: ${SEEDS}" 111 | 112 | if [ "${#nodeips[@]}" -gt "0" ]; then 113 | log_print "Retrieved IPs: ${#nodeips[@]}" 114 | 115 | # https://stackoverflow.com/questions/49184557/convert-bash-array-to-json-array-and-insert-to-file-using-jq 116 | # https://stackoverflow.com/questions/26808855/how-to-format-a-bash-array-as-a-json-array 117 | 118 | # convert bash array of strings to json array (variant 1) 119 | # nodeips=(127.0.0.1 127.0.0.2) 120 | # printf '%s\n' "${nodeips[@]}" | jq -R . | jq -s . 121 | 122 | # convert bash array of strings to json array (variant 2) 123 | # nodeips=(127.0.0.1 127.0.0.2) 124 | # for ip in "${nodeips[@]}"; do printf '%s' "${ip}" | jq -R -s .; done | jq -s . 125 | 126 | NEW_SEEDS=$(for ip in "${nodeips[@]}"; do printf '%s' "${ip}" | jq -R -s .; done | jq -s .) 127 | log_print "New seeds: ${NEW_SEEDS}" 128 | 129 | if ${APPLY_CHANGES}; then 130 | # Change all "NAME" records from the zone UUID 131 | MESSAGE=$(curl -s -X PUT -H "Content-Type: application/json" \ 132 | -H "X-Api-Key: $APIKEY" \ 133 | -d '{"items": [{"rrset_type": "A", 134 | "rrset_ttl": 1800, 135 | "rrset_values": '"${NEW_SEEDS}"'}]}' \ 136 | "https://dns.api.gandi.net/api/v5/zones/${UUID}/records/${RECORD}" | jq -r '.message') 137 | log_print "Operation result: ${MESSAGE}" 138 | fi 139 | 140 | fi 141 | 142 | 143 | # record example 144 | # { 145 | # "rrset_type": "A", 146 | # "rrset_ttl": 1800, 147 | # "rrset_name": "seeds1", 148 | # "rrset_href": "https://dns.api.gandi.net/api/v5/zones/UUID/records/seeds1/A", 149 | # "rrset_values": [ 150 | # "78.47.196.146" 151 | # ] 152 | # } 153 | 154 | 155 | -------------------------------------------------------------------------------- /docker_run_php.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | imagename='ubuntu1604:php7' 4 | filename="$1" 5 | docker build -t "${imagename}" . 6 | docker run -v $(pwd):/app -it --rm --name komodoscripts \ 7 | "${imagename}" /bin/bash -c "php /app/${filename}" 8 | -------------------------------------------------------------------------------- /docs/creating-a-vm-for-notarizing-3rd-party-on-headless-server.md: -------------------------------------------------------------------------------- 1 | ## Creating a VM for notarizing 3rd party on a Headless Server 2 | 3 | Use this guide on your own risk! 4 | 5 | ### Installing Virtual Box 6 | 7 | - https://www.virtualbox.org/wiki/Linux_Downloads 8 | 9 | For Ubuntu 16.04: 10 | 11 | ``` 12 | sudo nano /etc/apt/sources.list 13 | # add the following line at the end without initial # 14 | # deb https://download.virtualbox.org/virtualbox/debian xenial contrib 15 | wget -q https://www.virtualbox.org/download/oracle_vbox_2016.asc -O- | sudo apt-key add - 16 | wget -q https://www.virtualbox.org/download/oracle_vbox.asc -O- | sudo apt-key add - 17 | sudo apt-get update 18 | sudo apt install virtualbox-5.2 19 | # add your username to vboxusers group (decker in this example) 20 | sudo usermod -aG vboxusers decker 21 | # check virtualbox kernel modules 22 | sudo systemctl status vboxdrv 23 | # download and install latest (!) extension pack 24 | wget https://download.virtualbox.org/virtualbox/5.2.32/Oracle_VM_VirtualBox_Extension_Pack-5.2.32.vbox-extpack 25 | sudo VBoxManage extpack install Oracle_VM_VirtualBox_Extension_Pack-5.2.32.vbox-extpack 26 | ``` 27 | 28 | ### Creating a VM 29 | 30 | 1. SSH to your server with installed on previous step Virtual Box. 31 | 2. Create a VM following next guide: 32 | ``` 33 | cd $HOME 34 | wget http://releases.ubuntu.com/18.04.2/ubuntu-18.04.2-live-server-amd64.iso 35 | # VBoxManage list ostypes # to get a complete list of supported operating systems 36 | VBoxManage createvm --name "Ubuntu_3rdparty" --ostype Ubuntu_64 --register 37 | VBoxManage modifyvm "Ubuntu_3rdparty" --memory 16384 --cpus 4 --vram 16 --boot1 dvd --nic1 nat 38 | # create IDE & SATA controllers 39 | VBoxManage storagectl "Ubuntu_3rdparty" --name "IDE Controller" --add ide --controller PIIX4 40 | VBoxManage storagectl "Ubuntu_3rdparty" --name "SATA Controller" --add sata --portcount 1 41 | # create & attach disk drives 42 | VBoxManage createhd --filename "Ubuntu_3rdparty.vdi" --size 250000 # 250 Gb Virtual HDD at $HOME directory 43 | VBoxManage storageattach "Ubuntu_3rdparty" --storagectl "IDE Controller" --port 0 --device 1 --type dvddrive --medium "$HOME/ubuntu-18.04.2-live-server-amd64.iso" 44 | VBoxManage storageattach "Ubuntu_3rdparty" --storagectl "SATA Controller" --port 0 --device 0 --type hdd --medium "Ubuntu_3rdparty.vdi" 45 | # enable VRDP server 46 | VBoxManage modifyvm "Ubuntu_3rdparty" --vrde on --vrdeport 5900 --vrdeaddress "127.0.0.1" 47 | # disable audio 48 | VBoxManage modifyvm "Ubuntu_3rdparty" --audio none --audioin off --audioout off 49 | # start the virtual machine (in screen or tmux) 50 | VBoxHeadless --startvm "Ubuntu_3rdparty" 51 | ``` 52 | 53 | 3. Forward port from Virtual Box host server to your local PC: 54 | 55 | ``` 56 | ssh -L 5900:127.0.0.1:5900 57 | rdesktop-vrdp 127.0.0.1:5900 # connect via RDP to VRDE or use Remmina or any other RDP client for that 58 | ``` 59 | 60 | 4. Install Ubuntu standart way. 61 | 62 | 5. Stop the VM and turn off VRDE with: 63 | ``` 64 | VBoxManage controlvm "Ubuntu_3rdparty" poweroff 65 | VBoxManage modifyvm "Ubuntu_3rdparty" --vrde off 66 | 67 | ``` 68 | 69 | 6. Setup port forward from Host to Guest (bcz guest behind a VM NAT): 70 | 71 | ``` 72 | VBoxManage modifyvm "Ubuntu_3rdparty" --natpf1 "guestssh,tcp,,7722,,22" # natfp 73 | ``` 74 | 75 | 7. Start VM again (in screen or tmux) 76 | 77 | ``` 78 | VBoxHeadless --startvm "Ubuntu_3rdparty" 79 | ``` 80 | 81 | Connect to VM via SSH: 82 | ``` 83 | ssh -p 7722 84 | ``` 85 | 86 | Don't forget to allow connection to VM from outside if you use ufw: 87 | 88 | ``` 89 | sudo ufw allow 7722/tcp comment 'vm ssh' 90 | ``` 91 | 92 | 8. Setup 3rd party server in VM. Don't forget to port-forward needed ports from Host -> Guest (VM) machine same way as ssh port. 93 | 94 | ### Useful links 95 | 96 | - https://www.virtualbox.org/manual/ch07.html - 7.1.3. Step by Step: Creating a Virtual Machine on a Headless Server 97 | - https://www.virtualbox.org/manual/ch09.html#otherextpacks - 9.22. Other Extension Packs 98 | - https://superuser.com/questions/322803/how-to-connect-to-virtualbox-remote-desktop-client-using-vnc 99 | - https://forums.virtualbox.org/viewtopic.php?f=7&t=58560 100 | - https://bugs.launchpad.net/ubuntu/+source/virtualbox/+bug/1822996 101 | - https://superuser.com/questions/901422/virtualbox-command-line-setting-up-port-forwarding 102 | - https://blog.regolit.com/2018/03/27/secure-virtualbox-vrde-connection 103 | - https://eax.me/vboxmanage/ 104 | - https://www.ostechnix.com/install-oracle-virtualbox-ubuntu-16-04-headless-server/ 105 | 106 | ### Useful commands 107 | 108 | - `VBoxManage list vms` - list of VMs 109 | - `VBoxManage list runningvms` - list of running VMs 110 | - `VBoxManage controlvm "Ubuntu_3rdparty" acpipowerbutton` or `VBoxManage controlvm "Ubuntu_3rdparty" poweroff` - [safe](https://askubuntu.com/questions/42482/how-to-safely-shutdown-guest-os-in-virtualbox-using-command-line) stop VM 111 | - `VBoxManage showvminfo "Ubuntu_3rdparty" --details` - show VM details 112 | 113 | ### Useful notes 114 | 115 | - Oracle VM VirtualBox Extension Pack needed for support for USB 2.0 devices, **VirtualBox RDP** and PXE boot for Intel cards. 116 | 117 | Switching between RDP and VNC: 118 | 119 | ``` 120 | # setting password for VRDE 121 | # for RDP (in case of Oracle VM VirtualBox Extension Pack installed) 122 | VBoxManage setproperty vrdeextpack "Oracle VM VirtualBox Extension Pack" 123 | VBoxManage setproperty vrdeauthlibrary "VBoxAuthSimple" 124 | VBoxManage internalcommands passwordhash "secret" 125 | VBoxManage modifyvm "Ubuntu_3rdparty" --vrdeauthtype external 126 | VBoxManage setextradata "Ubuntu_3rdparty" "VBoxAuthSimple/users/decker" "2bb80d537b1da3e38bd30361aa855686bde0eacd7162fef6a25fe97bf527a25b" 127 | # for VNC 128 | VBoxManage setproperty vrdeextpack VNC 129 | VBoxManage modifyvm "Ubuntu_3rdparty" --vrdeproperty VNCPassword=secret 130 | ``` 131 | 132 | In case of VNC use `Remmina` to connect to your VRDE server. Note that you should setup 16 bit color depth in VNC connection properties, otherwise you will get `rfbProcessClientNormalMessage: ignoring unsupported encoding type ultraZip` error during connection. 133 | -------------------------------------------------------------------------------- /docs/secure-iguana-password-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeckerSU/komodo_scripts/883b63347beaae5b59bc2d448144c0cbb4402c5f/docs/secure-iguana-password-01.png -------------------------------------------------------------------------------- /docs/secure-iguana-password.md: -------------------------------------------------------------------------------- 1 | ## How to secure iguana seed? ## 2 | 3 | Current manuals, such as [Setup Komodo Notary Node](https://docs.komodoplatform.com/notary/setup-Komodo-Notary-Node.html#setup-iguana) documentation, recommend storing the iguana password (seed) as plain-text in the `wp_7776` file, which can be insecure as any application potentially could read it. In this manual, we will try to secure the password storage using the GnuPG tool. 4 | 5 | 1. First of all create `~/gpgparams` file with following content: 6 | 7 | ``` 8 | %echo Generating a basic OpenPGP key 9 | Key-Type: RSA 10 | Key-Length: 4096 11 | Name-Real: notary-node-pass 12 | Passphrase: abc 13 | Expire-Date: 0 14 | %commit 15 | %echo done 16 | ``` 17 | 18 | Where `abc` will be your passphrase to access the encrypted iguana seed (not the seed itself), you can do so with the following command: 19 | 20 | ``` 21 | cat < ~/gpgparams 22 | %echo Generating a basic OpenPGP key 23 | Key-Type: RSA 24 | Key-Length: 4096 25 | Name-Real: notary-node-pass 26 | Passphrase: abc 27 | Expire-Date: 0 28 | %commit 29 | %echo done 30 | EOF 31 | ``` 32 | 33 | If you don't want to use a password to access a seed (not secure) change `Passphrase: abc` string on `%no-protection`. 34 | 35 | 2. Generate GnuPG key: 36 | ``` 37 | gpg --generate-key --batch ~/gpgparams 38 | ``` 39 | It will generate a basic OpenPGP key and store it in the GnuPG default keyring (`~/.gnupg` directory). You can list stored OpenPGP secret keys with `gpg -K`. Do not launch the generate key command twice, as it will generate a second OpenPGP secret key with the same "name". 40 | 41 | 3. Encrypt your iguana seed with: 42 | ``` 43 | echo -n "YOUR_VERY_SECURE_PASSPHRASE" | gpg --encrypt -o ~/encrypted-pass.gpg -r notary-node-pass 44 | ``` 45 | The encrypted seed will be stored in `~/encrypted-pass.gpg` file. 46 | 47 | 4. Create the `wp_7776` file with the following lines: 48 | ``` 49 | curl --url "http://127.0.0.1:7776" --data "{\"method\":\"walletpassphrase\",\"params\":[\"$(gpg --quiet --for-your-eyes-only --no-tty --decrypt ~/encrypted-pass.gpg)\", 9999999]}" 50 | ``` 51 | 52 | 5. Now when you will start `m_notary_main` or other script which calls `wp_7776` inside, you will see the following password prompt to unlock an iguana seed: 53 | 54 | ![openpgp_password_prompt](secure-iguana-password-01.png) 55 | 56 | Enter the passphrase to continue script execution. 57 | 58 | -------------------------------------------------------------------------------- /estimate-blocks.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Calculates average blocks per day for last MAX_LOOK_BEFORE_DAYS days and estimates future block height. 4 | 5 | import requests 6 | from datetime import datetime, timedelta 7 | import time 8 | 9 | MAX_LOOK_BEFORE_DAYS = 100 10 | FUTURE_TIMESTAMP = 1728049053; # dPoW Season 8, Fri Oct 4 2024 13:37:33 GMT+0000 11 | 12 | def get_block_height(date_str): 13 | url = f"https://kmdexplorer.io/insight-api-komodo/blocks?blockDate={date_str}" 14 | response = requests.get(url) 15 | 16 | if response.status_code == 200: 17 | data = response.json() 18 | blocks = data.get("blocks", []) 19 | 20 | if blocks: 21 | first_block = blocks[0] 22 | height = first_block.get("height") 23 | return height 24 | else: 25 | return None 26 | else: 27 | return None 28 | 29 | def main(): 30 | block_heights = [] 31 | blocks_per_day = [] 32 | 33 | # Start from today 34 | datetime_now = datetime.now() 35 | current_date = datetime_now.strftime("%Y-%m-%d") 36 | 37 | # Get block heights for MAX_LOOK_BEFORE_DAYS 38 | for i in range(MAX_LOOK_BEFORE_DAYS): 39 | # Move to the previous day 40 | current_date = (datetime_now - timedelta(days=i+1)).strftime("%Y-%m-%d") 41 | print(f"Processing: {current_date} [{i}]") 42 | 43 | block_height = get_block_height(current_date) 44 | if block_height is not None: 45 | block_heights.append(block_height) 46 | # Pause for 1 second 47 | time.sleep(1) 48 | 49 | # Calculate blocks per day 50 | for i in range(1, len(block_heights)): 51 | blocks_per_day.append(block_heights[i-1] - block_heights[i]) 52 | 53 | # Calculate the average, min, and max blocks per day 54 | if blocks_per_day: 55 | average_blocks_per_day = sum(blocks_per_day) / len(blocks_per_day) 56 | min_blocks_per_day = min(blocks_per_day) 57 | max_blocks_per_day = max(blocks_per_day) 58 | else: 59 | average_blocks_per_day = 0 60 | min_blocks_per_day = 0 61 | max_blocks_per_day = 0 62 | 63 | # Output the average, min, and max blocks per day 64 | print(f"Average blocks per day: {average_blocks_per_day}") 65 | print(f"Min blocks per day: {min_blocks_per_day}") 66 | print(f"Max blocks per day: {max_blocks_per_day}") 67 | 68 | # Estimate future block height 69 | future_datetime = datetime.utcfromtimestamp(FUTURE_TIMESTAMP) 70 | days_to_future = (future_datetime - datetime_now).days 71 | 72 | if block_heights: 73 | current_height = block_heights[0] # Most recent block height 74 | estimated_future_height = int(current_height + (days_to_future * average_blocks_per_day)) 75 | 76 | print(f"Current height: {current_height}") 77 | print(f"Days to future: {days_to_future}") 78 | print(f"Estimated block height at {future_datetime}: {estimated_future_height}") 79 | else: 80 | print("Insufficient data to estimate future block height.") 81 | 82 | if __name__ == "__main__": 83 | main() 84 | -------------------------------------------------------------------------------- /genkomodo.txt: -------------------------------------------------------------------------------- 1 | How to generate WIF for GAME? 2 | ----------------------------- 3 | 4 | 1. git clone git@github.com:DeckerSU/komodo_scripts.git 5 | 2. git submodule init 6 | 3. git submodule update --init --recursive 7 | 4. edit genkomodo.php and fill your passphrase instead of $passphrase = "myverysecretandstrongpassphrase_noneabletobrute"; 8 | 5. php genkomodo.php 9 | 6. delete your passphrase from genkomodo.php for security purposes 10 | 7. import compressed wif in gamecreditsd using `importprivkey`. 11 | 12 | Other way is to use marketmaker API: 13 | ------------------------------------ 14 | 15 | jl777 [9:52 AM] 16 | yes I had to use calcaddress api in marketmaker to get the GAME wif 17 | 18 | source userpass 19 | curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"calcaddress\",\"passphrase\":\"1234default\"}" 20 | curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"calcaddress\",\"passphrase\":\"$password\",\"coin\":\"GAME\"}" 21 | 22 | Install PHP 23 | ----------- 24 | 25 | sudo apt install php-cli php-gmp php-mbstring -------------------------------------------------------------------------------- /genpos64.php: -------------------------------------------------------------------------------- 1 | base58_decode($address)); 31 | 32 | /* 33 | if(strlen($address) !== 25) 34 | return false; 35 | $checksum = substr($address, 21, 4); 36 | $rawAddress = substr($address, 0, 21); 37 | */ 38 | 39 | $len = strlen($address); 40 | $checksum = substr($address, $len-4, 4); 41 | $rawAddress = substr($address, 0, $len-4); 42 | 43 | if(substr(hex2bin($this->hash256($rawAddress)), 0, 4) === $checksum) 44 | return true; 45 | else 46 | return false; 47 | } 48 | 49 | /** 50 | * Returns the current network prefix for WIF, '80' = main network, 'ef' = test network. 51 | * 52 | * @return string (hexa) 53 | */ 54 | public function getPrivatePrefix($PrivatePrefix = 128){ 55 | 56 | if($this->networkPrefix =='6f') 57 | return 'ef'; 58 | else 59 | return sprintf("%02X",$PrivatePrefix); 60 | } 61 | /*** 62 | * returns the private key under the Wallet Import Format 63 | * 64 | * @return string (base58) 65 | * @throws \Exception 66 | */ 67 | 68 | public function getWIF($compressed = true, $PrivatePrefix = 128) 69 | { 70 | if(!isset($this->k)) 71 | { 72 | throw new \Exception('No Private Key was defined'); 73 | } 74 | 75 | $k = $this->k; 76 | 77 | while(strlen($k) < 64) 78 | $k = '0' . $k; 79 | 80 | $secretKey = $this->getPrivatePrefix($PrivatePrefix) . $k; 81 | 82 | if($compressed) { 83 | $secretKey .= '01'; 84 | } 85 | 86 | $secretKey .= substr($this->hash256(hex2bin($secretKey)), 0, 8); 87 | 88 | return $this->base58_encode($secretKey); 89 | } 90 | } 91 | 92 | function komodo_segid32($address) { 93 | // segid - first byte of sha256(address) and 0x3f 94 | return hexdec(substr(hash ( "sha256" , $address ), 0, 2)) & 0x3f; 95 | } 96 | 97 | function escapeJsonString($value) { # list from www.json.org: (\b backspace, \f formfeed) 98 | $escapers = array("\\", "/", "\"", "\n", "\r", "\t", "\x08", "\x0c"); 99 | $replacements = array("\\\\", "\\/", "\\\"", "\\n", "\\r", "\\t", "\\f", "\\b"); 100 | $result = str_replace($escapers, $replacements, $value); 101 | return $result; 102 | } 103 | 104 | if (php_sapi_name() !== "cli") return; 105 | 106 | $bitcoinECDSA = new BitcoinECDSADecker(); 107 | $bitcoinECDSA->setNetworkPrefix(sprintf("%02X", PUBKEY_ADDRESS)); 108 | 109 | $privkeys = Array(); 110 | 111 | // here we will create random addresses in a loop and fill the 64 addresses array 112 | // until we have 64 different segids. of course we will create more than 64 addresses, 113 | // but actually we will use as result only 64 of them with segids from 0 to 63. 114 | 115 | while (count($privkeys) < 64) { 116 | $bitcoinECDSA->generateRandomPrivateKey(); 117 | $compressed_address = $bitcoinECDSA->getAddress(); 118 | $segid = komodo_segid32($compressed_address); 119 | $privkeys[$segid] = $bitcoinECDSA->getWIF( true, SECRET_KEY); 120 | } 121 | ksort($privkeys); // sort by segid is don't needed, but it's nice ;) 122 | 123 | $addresses = Array(); 124 | foreach($privkeys as $pk) { 125 | $bitcoinECDSA->setPrivateKeyWithWif($pk); 126 | $compressed_address = $bitcoinECDSA->getAddress(); 127 | $segid = komodo_segid32($compressed_address); 128 | // if ($pk == $bitcoinECDSA->getWIF( true, SECRET_KEY)) { 129 | // echo $bitcoinECDSA->getWIF( true, SECRET_KEY) . sprintf(" // [%d] %s", $segid, $compressed_address) . PHP_EOL; 130 | // } 131 | 132 | // echo $pk . sprintf(" // [%d] %s", $segid, $compressed_address) . PHP_EOL; 133 | echo sprintf('./komodo-cli importprivkey "%s" "%s" %s', $pk, "[".$segid."] " . $compressed_address, "false") . PHP_EOL; 134 | 135 | $addresses[$compressed_address] = BALANCE_TO_SEND; 136 | } 137 | 138 | echo PHP_EOL; 139 | echo sprintf('sendmany "" "%s"', escapeJsonString(json_encode($addresses))) . PHP_EOL; 140 | 141 | ?> -------------------------------------------------------------------------------- /get-kmd-address.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # get-kmd-address.sh - Bash Script to get KMD address via OpenSSL 4 | 5 | # Copyright (c) 2021 Decker 6 | # This Source Code Form is subject to the terms of the Mozilla Public 7 | # License, v. 2.0. If a copy of the MPL was not distributed with this 8 | # file, You can obtain one at https://mozilla.org/MPL/2.0/. 9 | 10 | # Requirements: 11 | # sudo apt install base58 or install it manually from https://github.com/keis/base58 12 | 13 | # Docs: 14 | # https://stackoverflow.com/questions/48101258/how-to-convert-an-ecdsa-key-to-pem-format 15 | 16 | # check to avoid unable to write 'random state' error 17 | if [[ -f "$HOME/.rnd" ]]; then 18 | random_owner=$(stat --format '%U' $HOME/.rnd) 19 | if [[ "${random_owner}" == "root" ]]; then 20 | echo "Seems $HOME/.rnd owned by root ... remove it: sudo rm ~/.rnd" 1>&2 21 | exit 22 | fi 23 | fi 24 | 25 | pre_string="30740201010420" 26 | pre_string_other="302e0201010420" 27 | mid_string="a00706052b8104000aa144034200" # identifies secp256k1 28 | secp256k1_oid_string="06052b8104000a" 29 | # 06 05 2B 81 04 00 0A, https://thalesdocs.com/gphsm/luna/7/docs/network/Content/sdk/using/ecc_curve_cross-reference.htm 30 | 31 | # openssl ecparam -genkey -name secp256k1 -rand /dev/urandom -outform DER > privkey.bin 32 | # privkey_hex=$(cat privkey.bin | head -c 64 | xxd -p -c 64) 33 | privkey_hex=$(openssl ecparam -genkey -name secp256k1 -rand /dev/urandom -outform DER 2>/dev/null | head -c 64 | xxd -p -c 64) 34 | 35 | # DER could start from ${secp256k1_oid_string}${pre_string} or with just ${pre_string}, depends 36 | # on OpenSSL version, so just need to extract privkey bettween ${pre_string}${mid_string} 37 | 38 | # https://stackoverflow.com/questions/13242469/how-to-use-sed-grep-to-extract-text-between-two-words 39 | privkey_hex=$(echo ${privkey_hex} | grep -Po "${pre_string}\K.*(?=${mid_string})") 40 | 41 | if [ "${#privkey_hex}" -ne "64" ]; then 42 | echo "Error generating privkey ..." 1>&2 43 | exit 44 | fi 45 | 46 | echo "Privkey (hex): $privkey_hex (${#privkey_hex})" 47 | 48 | # echo "${pre_string_other} ${privkey_hex} ${mid_string:0:18}" | xxd -r -p > privkey-der.bin 49 | # openssl asn1parse -inform DER -in privkey.bin 50 | # openssl ec -inform DER < privkey-der.bin -text -noout -conv_form compressed 51 | # openssl ec -inform DER < privkey-der.bin -pubout -conv_form compressed -outform DER > pubkey-der.bin 52 | # pubkey_hex=$(cat pubkey-der.bin | xxd -p -c 56) 53 | 54 | pubkey_hex=$(openssl ec -inform DER -in <(echo "${pre_string_other} ${privkey_hex} ${mid_string:0:18}" | xxd -r -p) -pubout -conv_form compressed -outform DER 2>/dev/null | xxd -p -c 56) 55 | pubkey_hex=$(echo $pubkey_hex | sed 's/3036301006072a8648ce3d020106052b8104000a032200//') 56 | if [ "${#pubkey_hex}" -ne "66" ]; then 57 | echo "Error obtaining pubkey ..." 1>&2 58 | exit 59 | fi 60 | echo " Pubkey (hex): ${pubkey_hex} (${#pubkey_hex})" 61 | 62 | network_byte_hex="3c" # 60 (dec) KMD (Komodo) 63 | secret_key_hex="bc" # 188 (dec) KMD (Komodo) 64 | 65 | # test the case in which rmd160 ends with 00 (!) 66 | # pubkey=036da5d2956e8fdaee1988aa5957e456e58fcf41793a36cd2db7471cda3a4c5caa, rmd160=bf7fd8eaf542d4578708242010e5feb1c3672900 67 | 68 | hash160_hex=$(echo -n "${pubkey_hex}" | xxd -r -p | openssl dgst -sha256 -binary | openssl dgst -provider=legacy -rmd160 -binary | xxd -p -c 20) 69 | if [ "${#hash160_hex}" -ne "40" ]; then 70 | echo "Error obtaining rmd-160 ..." 1>&2 71 | exit 72 | fi 73 | echo "rmd-160 (hex): $hash160_hex (${#hash160_hex})" 74 | checksum_hex=$(echo -n "${network_byte_hex}${hash160_hex}" | xxd -r -p | openssl dgst -sha256 -binary | openssl dgst -sha256 -binary | xxd -p -c 32) 75 | address=$(echo -n "${network_byte_hex}${hash160_hex}${checksum_hex:0:8}" | xxd -r -p | base58) 76 | echo " Address: ${address}" 77 | 78 | wif_checksum_hex=$(echo -n "${secret_key_hex}${privkey_hex}01" | xxd -r -p | openssl dgst -sha256 -binary | openssl dgst -sha256 -binary | xxd -p -c 32) 79 | wif=$(echo -n "${secret_key_hex}${privkey_hex}01${wif_checksum_hex:0:8}" | xxd -r -p | base58) 80 | echo " WIF: ${wif}" 81 | 82 | # uncomment the lines below if you have qrencode installed and want to generate 83 | # QR code for address as well 84 | # echo 85 | # qrencode -t ANSIUTF8 ${address} 86 | 87 | -------------------------------------------------------------------------------- /getcheckpoints.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 2018-01-26 03:34:38 UpdateTip: new best=0000243296b9b26c040f471fdd9398ef72e57062cf05c19b9ba2fefac8165306 height=681777 log2_work=46.821454 tx=1253783 date=2018-01-26 00:02:07 progress=0.999648 cache=0.8MiB(1525tx) 3 | # 2019-11-13 00:15:04 UpdateTip: new best=049140623cc54a4a3d5868f720611e180ba0cafa21eab1edd0bc9ec2e6b7c374 height=1615921 log2_work=50.75492 log2_stake=-inf tx=7371665 date=2019-11-13 00:15:04 progress=1.000000 cache=5.5MiB(10794tx) 4 | echo ' checkpointData = (Checkpoints::CCheckpointData) 5 | { 6 | boost::assign::map_list_of 7 | ' 8 | for height in {0..3648244..50000} 9 | do 10 | block_hash=$(./komodo-cli getblockhash $height) 11 | block=$(./komodo-cli getblock $block_hash) 12 | #echo $block 13 | time=$(echo $block | grep -Po '"time": \K\w+') 14 | #echo $time 15 | hash=$(echo $block | grep -Po '"hash": "\K\w+') 16 | #echo $hash 17 | bits=$(echo $block | grep -Po '"bits": "\K\w+') 18 | #echo $bits 19 | #echo '{ 0, "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f", 1231006505, 0x1d00ffff },' 20 | #echo -e '{\t'$height',\t "'$hash'", '$time', 0x'$bits' },' 21 | # (15000, uint256S("0x00f0bd236790e903321a2d22f85bd6bf8a505f6ef4eddb20458a65d37e14d142")), 22 | if [ $height == 0 ] 23 | then 24 | echo ' (0, consensus.hashGenesisBlock)' 25 | else 26 | echo -e ' (\t'$height',\tuint256S("0x'$hash'"))' 27 | fi 28 | done 29 | # request last block again 30 | # 31 | height=3648244 32 | 33 | block_hash=$(./komodo-cli getblockhash $height) 34 | block=$(./komodo-cli getblock $block_hash) 35 | #echo $block 36 | time=$(echo $block | grep -Po '"time": \K\w+') 37 | #echo $time 38 | hash=$(echo $block | grep -Po '"hash": "\K\w+') 39 | #echo $hash 40 | bits=$(echo $block | grep -Po '"bits": "\K\w+') 41 | #echo $bits 42 | #echo '{ 0, "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f", 1231006505, 0x1d00ffff },' 43 | #echo -e '{\t'$height',\t "'$hash'", '$time', 0x'$bits' },' 44 | # (15000, uint256S("0x00f0bd236790e903321a2d22f85bd6bf8a505f6ef4eddb20458a65d37e14d142")), 45 | if [ $height == 0 ] 46 | then 47 | echo ' (0, consensus.hashGenesisBlock),' 48 | else 49 | echo -e ' (\t'$height',\tuint256S("0x'$hash'")),' 50 | fi 51 | # 52 | 53 | echo ' '$time', // * UNIX timestamp of last checkpoint block 54 | 21906511, // * total number of transactions between genesis and last checkpoint 55 | // (the tx=... number in the SetBestChain debug.log lines) 56 | 2777 // * estimated number of transactions per day after checkpoint 57 | // total number of tx / (checkpoint block height / (24 * 24)) 58 | }; 59 | ' -------------------------------------------------------------------------------- /getnet.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | sysctl net.ipv4.tcp_congestion_control 3 | sysctl net.ipv4.tcp_available_congestion_control 4 | sysctl net.core.default_qdisc 5 | sysctl net.core.rmem_default 6 | sysctl net.core.wmem_default 7 | sysctl net.core.rmem_max 8 | sysctl net.core.wmem_max 9 | sysctl net.ipv4.tcp_rmem 10 | sysctl net.ipv4.tcp_wmem 11 | sysctl net.ipv4.udp_rmem_min 12 | sysctl net.ipv4.udp_wmem_min 13 | sysctl net.core.netdev_max_backlog 14 | sysctl net.ipv4.tcp_max_orphans 15 | sysctl net.ipv4.tcp_max_syn_backlog 16 | sysctl net.ipv4.tcp_no_metrics_save 17 | sysctl net.ipv4.tcp_tw_reuse 18 | sysctl net.ipv4.tcp_max_tw_buckets 19 | sysctl net.ipv4.tcp_fin_timeout 20 | sysctl net.ipv4.tcp_keepalive_time 21 | sysctl net.ipv4.tcp_keepalive_intvl 22 | sysctl net.ipv4.tcp_keepalive_probes 23 | sysctl net.ipv4.tcp_synack_retries 24 | sysctl net.ipv4.tcp_syn_retries 25 | sysctl net.ipv4.ip_local_port_range 26 | sysctl net.core.somaxconn 27 | sysctl net.ipv4.tcp_low_latency 28 | sysctl net.ipv4.tcp_slow_start_after_idle 29 | sysctl net.ipv4.tcp_mtu_probing 30 | sysctl net.ipv4.tcp_fastopen -------------------------------------------------------------------------------- /iguana_active.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"dpow\",\"method\":\"active\"}" | jq --compact-output -r .[] -------------------------------------------------------------------------------- /iguana_checkio.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # (c) fullmoon 3 | myip=$(curl -s4 checkip.amazonaws.com) 4 | 5 | establishedconnections=$( ss -a | grep ":7775" | grep "ESTAB" | awk '{print $5 " " $6}' ) 6 | 7 | #echo $"$establishedconnections" 8 | outgoing=$( echo $"$establishedconnections" | grep -v "$myip:7775" | awk '{print $2}' | sed 's/:7775//g' | sort ) 9 | #echo $"$outgoing" 10 | ingoing=$( echo $"$establishedconnections" | grep "$myip:7775" | awk '{print $2}' | sed 's/:[0-9]*[0-9]*[0-9]*[0-9]*//g' | sort ) 11 | #echo $"$ingoing" 12 | 13 | echo "# outgoing:" 14 | echo $"$outgoing" | wc -l 15 | echo "" 16 | echo "# ingoing:" 17 | echo $"$ingoing" | wc -l 18 | echo "" 19 | echo "IPs not ingoing:" 20 | comm -23 <(echo "$outgoing") <(echo "$ingoing") 21 | echo "" 22 | echo "IPs not outgoing:" 23 | comm -23 <(echo "$ingoing") <(echo "$outgoing") -------------------------------------------------------------------------------- /iguana_checkip.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | i=0 3 | 4 | RESET="\033[0m" 5 | BLACK="\033[30m" 6 | RED="\033[31m" 7 | GREEN="\033[32m" 8 | YELLOW="\033[33m" 9 | BLUE="\033[34m" 10 | MAGENTA="\033[35m" 11 | CYAN="\033[36m" 12 | WHITE="\033[37m" 13 | 14 | while read -u 3 line; do 15 | i=$((i + 1)) 16 | result=$(nc -w 3 $line 17775 | xxd -p) 17 | if [ "$result" == "0053500000700000" ]; then 18 | echo -e $line - ${GREEN}Success!${RESET} 19 | else 20 | echo -e $line - ${RED}Dead!${RESET} 21 | fi 22 | done 3< <(curl -s --url "http://127.0.0.1:7776/" --data "{\"agent\":\"dpow\",\"method\":\"ipaddrs\"}" | jq -r .[]) 23 | 24 | # https://unix.stackexchange.com/questions/52026/bash-how-to-read-one-line-at-a-time-from-output-of-a-command 25 | # https://stackoverflow.com/questions/26392867/netcat-inside-a-while-read-loop-returning-immediately -------------------------------------------------------------------------------- /images/autosplit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeckerSU/komodo_scripts/883b63347beaae5b59bc2d448144c0cbb4402c5f/images/autosplit.png -------------------------------------------------------------------------------- /images/genkomodo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeckerSU/komodo_scripts/883b63347beaae5b59bc2d448144c0cbb4402c5f/images/genkomodo.png -------------------------------------------------------------------------------- /lockutxo.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # (c) Decker, 2018 ;) 3 | 4 | # Usage instruction: 5 | # 6 | # 1. Download it on your NN in any folder. 7 | # 2. Edit rpc username and pass in script. 8 | # 3. Let's explain we have 450 KMD on balance, including 0.0001 KMD utxos. 9 | # 4. Run the script ... it locks all 0.0001 KMD utxos from sending and shows you locked utxos txid + vout num. 10 | # 5. Send funds from NN via ~/komodo/src/komodo-cli sendtoaddress YOUR_WALLET_ADDRESS 450 "" "" true 11 | # 6. Now we need to unlock (!) 0.0001 KMD utxos, uncomment last line with curl command execution and launch it again. All your utxos will be unlocked. 12 | # 7. Additionally check that you haven't locked utxos: ~/komodo/src/komodo-cli listlockunspent 13 | # ... 14 | # 777. Bingo! ) 15 | # 16 | # @kolo You can call it "utxo protector", komodod will never "eat" your utxos during sendtoaddress if they are all locked. 17 | 18 | curdir=$(pwd) 19 | curluser=user 20 | curlpass=pass 21 | curlport=7771 22 | asset= 23 | 24 | # Lock 25 | curl -s --user $curluser:$curlpass --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "listunspent", "params": [0, 9999999]}' -H 'content-type: text/plain;' http://127.0.0.1:$curlport/ | jq .result > $curdir/listunspent.txt 26 | # set condition on amout on a next line 27 | arg=$(cat $curdir/listunspent.txt | jq '.[] | select (.spendable == true and .amount == 0.0001) | del (.generated, .address, .account, .scriptPubKey, .amount, .interest, .confirmations, .spendable)' | jq -r -s '. | tostring') 28 | echo "{\"jsonrpc\": \"1.0\", \"id\":\"curltest\", \"method\": \"lockunspent\", \"params\": [false, $arg] }" > $curdir/listunspent.curl 29 | 30 | # we are using curl here to avoid an error "Argument list too long" with long-long list of utxos need to be locked 31 | # if we executing komodo-cli 32 | 33 | curl -s --user $curluser:$curlpass --data-binary "@$curdir/listunspent.curl" -H 'content-type: text/plain;' http://127.0.0.1:$curlport/ 34 | 35 | # locked utxos list (and unlock if needed) 36 | 37 | curl -s --user $curluser:$curlpass --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "listlockunspent", "params": []}' -H 'content-type: text/plain;' http://127.0.0.1:$curlport/ | jq .result > $curdir/listlockunspent.txt 38 | arg=$(cat $curdir/listlockunspent.txt | jq '.[]' | jq -r -s '. | tostring') 39 | echo $arg | jq . 40 | echo "{\"jsonrpc\": \"1.0\", \"id\":\"curltest\", \"method\": \"lockunspent\", \"params\": [true, $arg] }" > $curdir/listlockunspent.curl 41 | 42 | # uncomment if u want to unlock locked utxos 43 | 44 | # curl -s --user $curluser:$curlpass --data-binary "@$curdir/listlockunspent.curl" -H 'content-type: text/plain;' http://127.0.0.1:$curlport/ 45 | -------------------------------------------------------------------------------- /lockutxo_debug.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # (c) Decker, 2018 ;) 3 | 4 | # CSV output examples 5 | # ------------------- 6 | 7 | #"\"6ec838e14dff07a6656c534bda8b44d36d1cd07e614a832566d259b1e96680ae\",0,3.50454387" 8 | #cat listunspent.txt | jq '.[] | select (.spendable == true and .amount > 3) | [.txid,.vout,.amount] | @csv' 9 | 10 | # "6ec838e14dff07a6656c534bda8b44d36d1cd07e614a832566d259b1e96680ae",0,3.50454387 11 | #cat listunspent.txt | jq -r '.[] | select (.spendable == true and .amount > 3) | [.txid,.vout,.amount] | @csv' 12 | 13 | # CSV parsing example 14 | # ------------------- 15 | #cat listunspent.txt | jq -r '.[] | select (.spendable == true and .amount > 3) | [.txid,.vout,.amount] | @csv' > listunspent.csv 16 | #i=0 17 | #OLDIFS=$IFS 18 | #IFS="," 19 | #while read txid vout amount; do 20 | # i=$((i + 1)) 21 | # echo "txid: $txid vout: $vout amount: $amount" 22 | #done < listunspent.csv 23 | #IFS=$OLDIFS 24 | 25 | # CURL 26 | 27 | curluser=user 28 | curlpass=pass 29 | curlport=36356 30 | asset=-ac_name=POSTEST64B 31 | 32 | # Lock 33 | if true;then 34 | ./komodo-cli $asset listunspent > listunspent.txt 35 | #arg=$(cat listunspent.txt | jq '.[] | select (.spendable == true and .amount == 3.50454387) | del (.generated, .address, .account, .scriptPubKey, .amount, .interest, .confirmations, .spendable)' | jq -s '. | tostring') 36 | arg=$(cat listunspent.txt | jq '.[] | select (.spendable == true and .amount == 0.0001) | del (.generated, .address, .account, .scriptPubKey, .amount, .interest, .confirmations, .spendable)' | jq -r -s '. | tostring') 37 | 38 | #echo $arg 39 | echo "{\"jsonrpc\": \"1.0\", \"id\":\"curltest\", \"method\": \"lockunspent\", \"params\": [false, $arg] }" > listunspent.curl 40 | #command=$(echo './komodo-cli lockunspent false '$arg) 41 | #echo $command 42 | #eval $command 43 | curl --trace-time -v --user $curluser:$curlpass --data-binary "@listunspent.curl" -H 'content-type: text/plain;' http://127.0.0.1:$curlport/ 44 | fi 45 | 46 | # Unlock example 47 | if false;then 48 | ./komodo-cli $asset listlockunspent > listlockunspent.txt 49 | #arg=$(cat listunspent.txt | jq '.[]' | jq -s '. | tostring') 50 | arg=$(cat listlockunspent.txt | jq '.[]' | jq -r -s '. | tostring') 51 | #command=$(echo './komodo-cli lockunspent true '$arg) 52 | #echo $command 53 | #eval $command 54 | echo "{\"jsonrpc\": \"1.0\", \"id\":\"curltest\", \"method\": \"lockunspent\", \"params\": [true, $arg] }" > listlockunspent.curl 55 | curl --trace-time -v --user $curluser:$curlpass --data-binary "@listlockunspent.curl" -H 'content-type: text/plain;' http://127.0.0.1:$curlport/ 56 | fi -------------------------------------------------------------------------------- /make_bootstrap.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # KMD+AC bootstrap gen (c) Decker, 2019 3 | 4 | # -------------------------------------------------------------------------- 5 | function init_colors() { 6 | RESET="\033[0m" 7 | BLACK="\033[30m" 8 | RED="\033[31m" 9 | GREEN="\033[32m" 10 | YELLOW="\033[33m" 11 | BLUE="\033[34m" 12 | MAGENTA="\033[35m" 13 | CYAN="\033[36m" 14 | WHITE="\033[37m" 15 | BRIGHT="\033[1m" 16 | DARKGREY="\033[90m" 17 | } 18 | # -------------------------------------------------------------------------- 19 | function log_print() { 20 | datetime=$(date '+%Y-%m-%d %H:%M:%S') 21 | echo -e [$datetime] $1 22 | } 23 | # -------------------------------------------------------------------------- 24 | function bootstrap() { 25 | 26 | if [ ! -z $1 ] && [ $1 != "KMD" ] 27 | then 28 | coin=$1 29 | data_folder=${HOME}/.komodo/$coin 30 | transform='s,^.,'${coin}',S' 31 | else 32 | coin="KMD" 33 | data_folder=${HOME}/.komodo 34 | transform='' 35 | fi 36 | 37 | archive_name=bootstrap.${coin,,}.tar.gz 38 | du_files_list="${data_folder}/blocks ${data_folder}/chainstate ${data_folder}/notarisations" # ${data_folder}/komodostate ${data_folder}/komodostate.ind 39 | tar_files_list="./blocks ./chainstate ./notarisations" # ./komodostate ./komodostate.ind 40 | files_size=$(du -cak ${du_files_list} | cut -f1 | tail -1) 41 | checkpoint=$((files_size / 100)) 42 | log_print "Archiving \x5B${YELLOW}$i${RESET}\x5D --> ${archive_name}" 43 | log_print "Directory: ${data_folder}" 44 | log_print "Content: ${tar_files_list}" 45 | log_print "Size: ${files_size} Kb, Checkpoint: ${checkpoint} Kb" 46 | 47 | # --checkpoint-action=ttyout='[%{%Y-%m-%d %H:%M:%S}t] (%d sec): %u Kb, %T%*\r' 48 | GZIP=-9 tar --directory ${data_folder} \ 49 | --record-size=1K --checkpoint="${checkpoint}" --checkpoint-action=ttyout='[%{%Y-%m-%d %H:%M:%S}t] Size: %u Kb, %T Elapsed: %d sec%*\r' \ 50 | --show-transformed-names --transform="${transform}" \ 51 | --exclude={wallet.dat,*.conf,*.bak,db.log,debug.log,fee_estimates.dat,peers.dat,banlist.dat} \ 52 | --exclude={backup_*.dat,.lock,komodod.pid} \ 53 | -czvf $(pwd)/${archive_name} ${tar_files_list} > /dev/null 54 | 55 | } 56 | # -------------------------------------------------------------------------- 57 | function walletbackup_mm() { 58 | 59 | # before use read about multiple members with the same name in tar, each time when you will launch 60 | # backup - it will add each wallet.dat as a new member (!), so in .tar you can possible have multiple 61 | # wallet.dat from each coin. 62 | 63 | if [ ! -z $1 ] && [ $1 != "KMD" ] 64 | then 65 | coin=$1 66 | data_folder=${HOME}/.komodo/$coin 67 | transform='s,^.,'${coin}',S' 68 | else 69 | coin="KMD" 70 | data_folder=${HOME}/.komodo 71 | transform='' 72 | fi 73 | 74 | archive_name=wallets.$(date -u +%Y%m%d).tar # _%H%M%S 75 | tar_files_list="./wallet.dat" 76 | log_print "Backup \x5B${YELLOW}$i${RESET}\x5D wallet.dat --> ${archive_name}" 77 | # https://www.gnu.org/software/tar/manual/html_node/multiple.html#SEC62 - Multiple Members with the Same Name 78 | GZIP=-9 tar --directory ${data_folder} \ 79 | --show-transformed-names --transform="${transform}" \ 80 | -rvf $(pwd)/${archive_name} ${tar_files_list} # > /dev/null 81 | } 82 | # -------------------------------------------------------------------------- 83 | 84 | # --- Variables --- 85 | #komodo_cli_binary="$HOME/komodo/src/komodo-cli" 86 | komodo_cli_binary="/home/decker/ssd_nvme/komodo_src_beta/src/komodo-cli" 87 | # ----------------- 88 | # 89 | # https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html 90 | # https://stackoverflow.com/questions/2264428/how-to-convert-a-string-to-lower-case-in-bash 91 | # https://stackoverflow.com/questions/984204/shell-command-to-tar-directory-excluding-certain-files-folders 92 | # https://stackoverflow.com/questions/18681595/tar-a-directory-but-dont-store-full-absolute-paths-in-the-archive 93 | # https://www.gnu.org/software/tar/manual/html_section/tar_51.html#transform 94 | # https://unix.stackexchange.com/questions/72661/show-sum-of-file-sizes-in-directory-listing 95 | # https://www.gnu.org/software/tar/manual/html_section/tar_26.html#SEC48 96 | # https://stackoverflow.com/questions/1951506/add-a-new-element-to-an-array-without-specifying-the-index-in-bash 97 | # ----------------- 98 | 99 | init_colors 100 | echo "KMD+AC bootstrap gen (c) Decker, 2019" 101 | echo 102 | log_print "Start making bootstrap for KMD/AC ..." 103 | 104 | # https://stackoverflow.com/questions/18669756/bash-how-to-extract-data-from-a-column-in-csv-file-and-put-it-in-an-array 105 | 106 | # you can fill coins array from your local assetchains.json file 107 | # readarray -t kmd_coins < <(cat $HOME/komodo/src/assetchains.json | jq -r '[.[].ac_name] | join("\n")') 108 | # or directly from jl777/komodo beta branch assetchains.json 109 | readarray -t kmd_coins < <(curl -s https://raw.githubusercontent.com/KomodoPlatform/dPoW/master/iguana/assetchains.json | jq -r '[.[].ac_name] | join("\n")') 110 | # you can spectify coins array manually if you want 111 | # declare -a kmd_coins=(BEER PIZZA) 112 | kmd_coins+=(KMD) 113 | # printf '%s\n' "${kmd_coins[@]}" 114 | 115 | # rm wallets.$(date -u +%Y%m%d).tar 116 | for i in "${kmd_coins[@]}" 117 | do 118 | bootstrap $i 119 | # walletbackup_mm $i 120 | done 121 | 122 | -------------------------------------------------------------------------------- /make_bootstrap_3p.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3P bootstrap gen (c) Decker, 2019-2021 3 | 4 | # -------------------------------------------------------------------------- 5 | function init_colors() { 6 | RESET="\033[0m" 7 | BLACK="\033[30m" 8 | RED="\033[31m" 9 | GREEN="\033[32m" 10 | YELLOW="\033[33m" 11 | BLUE="\033[34m" 12 | MAGENTA="\033[35m" 13 | CYAN="\033[36m" 14 | WHITE="\033[37m" 15 | BRIGHT="\033[1m" 16 | DARKGREY="\033[90m" 17 | } 18 | # -------------------------------------------------------------------------- 19 | function log_print() { 20 | datetime=$(date '+%Y-%m-%d %H:%M:%S') 21 | echo -e [$datetime] $1 22 | } 23 | # -------------------------------------------------------------------------- 24 | function bootstrap() { 25 | 26 | if [ -z $1 ]; then 27 | log_print "${RED}\x5BERROR\x5D${RESET} Empty coin name ... " 28 | return 1; 29 | fi 30 | 31 | du_files_list="" 32 | tar_files_list="" 33 | 34 | if [ $1 == "VRSC" ] || [ $1 == "MCL" ] 35 | then 36 | coin=$1 37 | data_folder=${HOME}/.komodo/$coin 38 | transform='s,^.,'${coin}',S' 39 | else 40 | coin=$1 41 | case $coin in 42 | AYA) 43 | data_folder=${HOME}/.aryacoin 44 | # du_files_list+="${data_folder}/example.dat " 45 | # tar_files_list+="./example.dat " 46 | ;; 47 | CHIPS) 48 | data_folder=${HOME}/.chips 49 | ;; 50 | EMC2) 51 | data_folder=${HOME}/.einsteinium 52 | ;; 53 | GAME) 54 | data_folder=${HOME}/.gamecredits 55 | ;; 56 | GLEEC) 57 | data_folder=${HOME}/.gleecbtc 58 | ;; 59 | PBC) 60 | data_folder=${HOME}/.powerblockcoin 61 | ;; 62 | *) 63 | log_print "${RED}\x5BERROR\x5D${RESET} Unknown coin ${coin} ... " 64 | return 1 65 | ;; 66 | esac 67 | # data_folder=${HOME}/.komodo 68 | transform='' 69 | fi 70 | 71 | archive_name=bootstrap.${coin,,}.tar.gz 72 | 73 | du_files_list+="${data_folder}/blocks ${data_folder}/chainstate" # ${data_folder}/notarisations ${data_folder}/komodostate ${data_folder}/komodostate.ind 74 | tar_files_list+="./blocks ./chainstate" # ./notarisations ./komodostate ./komodostate.ind 75 | 76 | files_size=$(du -cak ${du_files_list} 2>/dev/null | cut -f1 | tail -1) 77 | checkpoint=$((files_size / 100)) 78 | log_print "Archiving \x5B${YELLOW}$i${RESET}\x5D --> ${archive_name}" 79 | log_print "Directory: ${data_folder}" 80 | log_print "Content: ${tar_files_list}" 81 | log_print "Size: ${files_size} Kb, Checkpoint: ${checkpoint} Kb" 82 | 83 | # --checkpoint-action=ttyout='[%{%Y-%m-%d %H:%M:%S}t] (%d sec): %u Kb, %T%*\r' 84 | GZIP=-9 tar --directory ${data_folder} \ 85 | --record-size=1K --checkpoint="${checkpoint}" --checkpoint-action=ttyout='[%{%Y-%m-%d %H:%M:%S}t] Size: %u Kb, %T Elapsed: %d sec%*\r' \ 86 | --show-transformed-names --transform="${transform}" \ 87 | --exclude={wallet.dat,*.conf,*.bak,db.log,debug.log,fee_estimates.dat,peers.dat,banlist.dat} \ 88 | --exclude={backup_*.dat,.lock,komodod.pid} \ 89 | -czvf $(pwd)/${archive_name} ${tar_files_list} > /dev/null 90 | 91 | # https://stackoverflow.com/questions/46167772/with-gnu-gzip-environment-variable-deprecated-how-to-control-zlib-compression-v 92 | 93 | # GZIP=-9 tar -zcf ... files to compress ... 94 | # tar -I 'gzip -9' -cf ... files to compress ... 95 | 96 | } 97 | # -------------------------------------------------------------------------- 98 | function walletbackup_mm() { 99 | 100 | # before use read about multiple members with the same name in tar, each time when you will launch 101 | # backup - it will add each wallet.dat as a new member (!), so in .tar you can possible have multiple 102 | # wallet.dat from each coin. 103 | 104 | if [ -z $1 ]; then 105 | log_print "[ERROR] Empty coin name ... " 106 | return 1; 107 | fi 108 | 109 | if [ $1 == "VRSC" ] || [ $1 == "MCL" ] 110 | then 111 | coin=$1 112 | data_folder=${HOME}/.komodo/$coin 113 | transform='s,^.,'${coin}',S' 114 | else 115 | coin=$1 116 | case $coin in 117 | AYA) 118 | data_folder=${HOME}/.aryacoin 119 | ;; 120 | CHIPS) 121 | data_folder=${HOME}/.chips 122 | ;; 123 | EMC2) 124 | data_folder=${HOME}/.einsteinium 125 | ;; 126 | GAME) 127 | data_folder=${HOME}/.gamecredits 128 | ;; 129 | GLEEC) 130 | data_folder=${HOME}/.gleecbtc 131 | ;; 132 | PBC) 133 | data_folder=${HOME}/.powerblockcoin 134 | ;; 135 | *) 136 | log_print "${RED}\x5BERROR\x5D${RESET} Unknown coin ${coin} ... " 137 | return 1 138 | ;; 139 | esac 140 | # data_folder=${HOME}/.komodo 141 | transform='' 142 | fi 143 | 144 | archive_name=wallets.$(date -u +%Y%m%d).tar # _%H%M%S 145 | tar_files_list="./wallet.dat" 146 | log_print "Backup \x5B${YELLOW}$i${RESET}\x5D wallet.dat --> ${archive_name}" 147 | # https://www.gnu.org/software/tar/manual/html_node/multiple.html#SEC62 - Multiple Members with the Same Name 148 | GZIP=-9 tar --directory ${data_folder} \ 149 | --show-transformed-names --transform="${transform}" \ 150 | -rvf $(pwd)/${archive_name} ${tar_files_list} # > /dev/null 151 | } 152 | # -------------------------------------------------------------------------- 153 | 154 | # --- Variables --- 155 | #komodo_cli_binary="$HOME/komodo/src/komodo-cli" 156 | 157 | # ----------------- 158 | # 159 | # https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html 160 | # https://stackoverflow.com/questions/2264428/how-to-convert-a-string-to-lower-case-in-bash 161 | # https://stackoverflow.com/questions/984204/shell-command-to-tar-directory-excluding-certain-files-folders 162 | # https://stackoverflow.com/questions/18681595/tar-a-directory-but-dont-store-full-absolute-paths-in-the-archive 163 | # https://www.gnu.org/software/tar/manual/html_section/tar_51.html#transform 164 | # https://unix.stackexchange.com/questions/72661/show-sum-of-file-sizes-in-directory-listing 165 | # https://www.gnu.org/software/tar/manual/html_section/tar_26.html#SEC48 166 | # https://stackoverflow.com/questions/1951506/add-a-new-element-to-an-array-without-specifying-the-index-in-bash 167 | # ----------------- 168 | 169 | init_colors 170 | echo "3P bootstrap gen (c) Decker, 2019-2020" 171 | echo 172 | log_print "Start making bootstrap for 3P ..." 173 | 174 | # https://stackoverflow.com/questions/18669756/bash-how-to-extract-data-from-a-column-in-csv-file-and-put-it-in-an-array 175 | 176 | # you can fill coins array from your local assetchains.json file 177 | # readarray -t kmd_coins < <(cat $HOME/komodo/src/assetchains.json | jq -r '[.[].ac_name] | join("\n")') 178 | # or directly from jl777/komodo beta branch assetchains.json 179 | # readarray -t kmd_coins < <(curl -s https://raw.githubusercontent.com/KomodoPlatform/dPoW/master/iguana/assetchains.json | jq -r '[.[].ac_name] | join("\n")') 180 | # you can spectify coins array manually if you want 181 | # declare -a kmd_coins=(BEER PIZZA) 182 | 183 | kmd_coins+=(AYA CHIPS EMC2 GLEEC MCL VRSC) 184 | # printf '%s\n' "${kmd_coins[@]}" 185 | 186 | # rm wallets.$(date -u +%Y%m%d).tar 187 | for i in "${kmd_coins[@]}" 188 | do 189 | bootstrap $i 190 | # walletbackup_mm $i 191 | done 192 | 193 | -------------------------------------------------------------------------------- /notaries.php: -------------------------------------------------------------------------------- 1 | "03b7621b44118017a16043f19b30cc8a4cfe068ac4e42417bae16ba460c80f3828" , 5 | "0_jl777_testB" => "02ebfc784a4ba768aad88d44d1045d240d47b26e248cafaf1c5169a42d7a61d344" , 6 | "0_kolo_testA" => "0287aa4b73988ba26cf6565d815786caf0d2c4af704d7883d163ee89cd9977edec" , 7 | "artik_AR" => "029acf1dcd9f5ff9c455f8bb717d4ae0c703e089d16cf8424619c491dff5994c90" , 8 | "artik_EU" => "03f54b2c24f82632e3cdebe4568ba0acf487a80f8a89779173cdb78f74514847ce" , 9 | "artik_NA" => "0224e31f93eff0cc30eaf0b2389fbc591085c0e122c4d11862c1729d090106c842" , 10 | "artik_SH" => "02bdd8840a34486f38305f311c0e2ae73e84046f6e9c3dd3571e32e58339d20937" , 11 | "badass_EU" => "0209d48554768dd8dada988b98aca23405057ac4b5b46838a9378b95c3e79b9b9e" , 12 | "badass_NA" => "02afa1a9f948e1634a29dc718d218e9d150c531cfa852843a1643a02184a63c1a7" , 13 | "badass_SH" => "026b49dd3923b78a592c1b475f208e23698d3f085c4c3b4906a59faf659fd9530b" , 14 | "crackers_EU" => "03bc819982d3c6feb801ec3b720425b017d9b6ee9a40746b84422cbbf929dc73c3" , // 10 15 | "crackers_NA" => "03205049103113d48c7c7af811b4c8f194dafc43a50d5313e61a22900fc1805b45" , 16 | "crackers_SH" => "02be28310e6312d1dd44651fd96f6a44ccc269a321f907502aae81d246fabdb03e" , 17 | "durerus_EU" => "02bcbd287670bdca2c31e5d50130adb5dea1b53198f18abeec7211825f47485d57" , 18 | "etszombi_AR" => "031c79168d15edabf17d9ec99531ea9baa20039d0cdc14d9525863b83341b210e9" , 19 | "etszombi_EU" => "0281b1ad28d238a2b217e0af123ce020b79e91b9b10ad65a7917216eda6fe64bf7" , // 15 20 | "etszombi_SH" => "025d7a193c0757f7437fad3431f027e7b5ed6c925b77daba52a8755d24bf682dde" , 21 | "farl4web_EU" => "0300ecf9121cccf14cf9423e2adb5d98ce0c4e251721fa345dec2e03abeffbab3f" , 22 | "farl4web_SH" => "0396bb5ed3c57aa1221d7775ae0ff751e4c7dc9be220d0917fa8bbdf670586c030" , 23 | "fullmoon_AR" => "0254b1d64840ce9ff6bec9dd10e33beb92af5f7cee628f999cb6bc0fea833347cc" , 24 | "fullmoon_NA" => "031fb362323b06e165231c887836a8faadb96eda88a79ca434e28b3520b47d235b" , // 20 25 | "fullmoon_SH" => "030e12b42ec33a80e12e570b6c8274ce664565b5c3da106859e96a7208b93afd0d" , 26 | "grewal_NA" => "03adc0834c203d172bce814df7c7a5e13dc603105e6b0adabc942d0421aefd2132" , 27 | "grewal_SH" => "03212a73f5d38a675ee3cdc6e82542a96c38c3d1c79d25a1ed2e42fcf6a8be4e68" , 28 | "indenodes_AR" => "02ec0fa5a40f47fd4a38ea5c89e375ad0b6ddf4807c99733c9c3dc15fb978ee147" , 29 | "indenodes_EU" => "0221387ff95c44cb52b86552e3ec118a3c311ca65b75bf807c6c07eaeb1be8303c" , 30 | "indenodes_NA" => "02698c6f1c9e43b66e82dbb163e8df0e5a2f62f3a7a882ca387d82f86e0b3fa988" , 31 | "indenodes_SH" => "0334e6e1ec8285c4b85bd6dae67e17d67d1f20e7328efad17ce6fd24ae97cdd65e" , 32 | "jeezy_EU" => "023cb3e593fb85c5659688528e9a4f1c4c7f19206edc7e517d20f794ba686fd6d6" , 33 | "jsgalt_NA" => "027b3fb6fede798cd17c30dbfb7baf9332b3f8b1c7c513f443070874c410232446" , 34 | "karasugoi_NA" => "02a348b03b9c1a8eac1b56f85c402b041c9bce918833f2ea16d13452309052a982" , // 30 35 | "kashifali_EU" => "033777c52a0190f261c6f66bd0e2bb299d30f012dcb8bfff384103211edb8bb207" , 36 | "kolo_AR" => "03016d19344c45341e023b72f9fb6e6152fdcfe105f3b4f50b82a4790ff54e9dc6" , 37 | "kolo_SH" => "02aa24064500756d9b0959b44d5325f2391d8e95c6127e109184937152c384e185" , 38 | "metaphilibert_AR" => "02adad675fae12b25fdd0f57250b0caf7f795c43f346153a31fe3e72e7db1d6ac6" , 39 | "movecrypto_AR" => "022783d94518e4dc77cbdf1a97915b29f427d7bc15ea867900a76665d3112be6f3" , 40 | "movecrypto_EU" => "021ab53bc6cf2c46b8a5456759f9d608966eff87384c2b52c0ac4cc8dd51e9cc42" , 41 | "movecrypto_NA" => "02efb12f4d78f44b0542d1c60146738e4d5506d27ec98a469142c5c84b29de0a80" , 42 | "movecrypto_SH" => "031f9739a3ebd6037a967ce1582cde66e79ea9a0551c54731c59c6b80f635bc859" , 43 | "muros_AR" => "022d77402fd7179335da39479c829be73428b0ef33fb360a4de6890f37c2aa005e" , 44 | "noashh_AR" => "029d93ef78197dc93892d2a30e5a54865f41e0ca3ab7eb8e3dcbc59c8756b6e355" , // 40 45 | "noashh_EU" => "02061c6278b91fd4ac5cab4401100ffa3b2d5a277e8f71db23401cc071b3665546" , 46 | "noashh_NA" => "033c073366152b6b01535e15dd966a3a8039169584d06e27d92a69889b720d44e1" , 47 | "nxtswe_EU" => "032fb104e5eaa704a38a52c126af8f67e870d70f82977e5b2f093d5c1c21ae5899" , 48 | "polycryptoblog_NA" => "02708dcda7c45fb54b78469673c2587bfdd126e381654819c4c23df0e00b679622" , 49 | "pondsea_AR" => "032e1c213787312099158f2d74a89e8240a991d162d4ce8017d8504d1d7004f735" , 50 | "pondsea_EU" => "0225aa6f6f19e543180b31153d9e6d55d41bc7ec2ba191fd29f19a2f973544e29d" , 51 | "pondsea_NA" => "031bcfdbb62268e2ff8dfffeb9ddff7fe95fca46778c77eebff9c3829dfa1bb411" , 52 | "pondsea_SH" => "02209073bc0943451498de57f802650311b1f12aa6deffcd893da198a544c04f36" , 53 | "popcornbag_AR" => "02761f106fb34fbfc5ddcc0c0aa831ed98e462a908550b280a1f7bd32c060c6fa3" , 54 | "popcornbag_NA" => "03c6085c7fdfff70988fda9b197371f1caf8397f1729a844790e421ee07b3a93e8" , // 50 55 | "ptytrader_NA" => "0328c61467148b207400b23875234f8a825cce65b9c4c9b664f47410b8b8e3c222" , 56 | "ptytrader_SH" => "0250c93c492d8d5a6b565b90c22bee07c2d8701d6118c6267e99a4efd3c7748fa4" , 57 | "rnr_AR" => "029bdb08f931c0e98c2c4ba4ef45c8e33a34168cb2e6bf953cef335c359d77bfcd" , 58 | "rnr_EU" => "03f5c08dadffa0ffcafb8dd7ffc38c22887bd02702a6c9ac3440deddcf2837692b" , 59 | "rnr_NA" => "02e17c5f8c3c80f584ed343b8dcfa6d710dfef0889ec1e7728ce45ce559347c58c" , 60 | "rnr_SH" => "037536fb9bdfed10251f71543fb42679e7c52308bcd12146b2568b9a818d8b8377" , 61 | "titomane_AR" => "03cda6ca5c2d02db201488a54a548dbfc10533bdc275d5ea11928e8d6ab33c2185" , 62 | "titomane_EU" => "02e41feded94f0cc59f55f82f3c2c005d41da024e9a805b41105207ef89aa4bfbd" , 63 | "titomane_SH" => "035f49d7a308dd9a209e894321f010d21b7793461b0c89d6d9231a3fe5f68d9960" , 64 | "vanbreuk_EU" => "024f3cad7601d2399c131fd070e797d9cd8533868685ddbe515daa53c2e26004c3" , // 60 65 | "xrobesx_NA" => "03f0cc6d142d14a40937f12dbd99dbd9021328f45759e26f1877f2a838876709e1" , 66 | "xxspot1_XX" => "02ef445a392fcaf3ad4176a5da7f43580e8056594e003eba6559a713711a27f955" , 67 | "xxspot2_XX" => "03d85b221ea72ebcd25373e7961f4983d12add66a92f899deaf07bab1d8b6f5573"); 68 | 69 | foreach ($notaries_elected as $key => $value) { 70 | //echo $key . " - "."21".$value."ac"."\r\n"; 71 | $res = json_decode(shell_exec("/home/decker/ssd_m2/komodo_src/src/komodo-cli decodescript \"21".$value."ac\"")); 72 | //var_dump($res->addresses[0]); 73 | echo '"'. $res->addresses[0] . '" => "' . $key . '"'.",\r\n"; 74 | 75 | } 76 | 77 | ?> -------------------------------------------------------------------------------- /notarystats_html.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | komodo_cli=/home/decker/komodo/src/komodo-cli 3 | chips_cli=/home/decker/chips3/src/chips-cli 4 | bitcoin_cli=/usr/local/bin/bitcoin-cli 5 | gamecredits_cli=/home/decker/GameCredits/src/gamecredits-cli 6 | 7 | # ---------------------- 8 | function getstats_kmd () 9 | { 10 | 11 | txcount=1000 12 | 13 | # $1 - coin name (empty for KMD) 14 | # -- in grep is for stop processing statements, https://unix.stackexchange.com/questions/11376/what-does-double-dash-mean-also-known-as-bare-double-dash/11382#11382 15 | 16 | if [ "$1" == "KMD" ] || [ "$1" == "" ] 17 | then 18 | name=" " 19 | name_str="KMD" 20 | else 21 | name=" -ac_name=$1" 22 | name_str=$1 23 | fi 24 | 25 | ntrz_count=$($komodo_cli $name listtransactions "" $txcount | grep -- -0.00098800 | wc -l) 26 | utxo_count=$($komodo_cli $name listunspent | grep .0001 | wc -l) 27 | #balance=$($komodo_cli $name getinfo | grep balance) 28 | balance=$($komodo_cli $name getinfo | jq .balance) 29 | height=$($komodo_cli $name getinfo | jq .blocks) 30 | 31 | echo "$name_str$ntrz_count$utxo_count$balance$height" 32 | 33 | } 34 | 35 | function getstats_btc () 36 | { 37 | txcount=1000 38 | ntrz_count=$($bitcoin_cli listtransactions "" $txcount | grep -- -0.00098800 | wc -l) 39 | utxo_count=$($bitcoin_cli listunspent | grep .0001 | wc -l) 40 | #balance=$($bitcoin_cli getinfo | grep balance) 41 | balance=$($bitcoin_cli getinfo | jq .balance) 42 | height=$($bitcoin_cli getinfo | jq .blocks) 43 | echo "BTC$ntrz_count$utxo_count$balance$height" 44 | } 45 | 46 | function getstats_chips () 47 | { 48 | txcount=1000 49 | ntrz_count=$($chips_cli listtransactions "" $txcount | grep -- -0.00098800 | wc -l) 50 | utxo_count=$($chips_cli listunspent | grep .0001 | wc -l) 51 | #balance=$($chips_cli getinfo | grep balance) 52 | balance=$($chips_cli getinfo | jq .balance) 53 | height=$($chips_cli getinfo | jq .blocks) 54 | echo "CHIPS$ntrz_count$utxo_count$balance$height" 55 | } 56 | 57 | function getstats_game () 58 | { 59 | txcount=1000 60 | ntrz_count=$($gamecredits_cli listtransactions "" $txcount | grep -- -0.00988000 | wc -l) 61 | utxo_count=$($gamecredits_cli listunspent | grep .001 | wc -l) 62 | #balance=$($gamecredits_cli getinfo | grep balance) 63 | balance=$($gamecredits_cli getinfo | jq .balance) 64 | height=$($gamecredits_cli getinfo | jq .blocks) 65 | echo "GAME$ntrz_count$utxo_count$balance$height" 66 | } 67 | 68 | 69 | cat < 71 | 74 | 75 | 76 | 77 | 78 | EOF 79 | 80 | getstats_btc 81 | getstats_chips 82 | getstats_game 83 | declare -a kmd_coins=(KMD REVS SUPERNET DEX PANGEA JUMBLR BET CRYPTO HODL MSHARK BOTS MGW COQUI WLC KV CEAL MESH MNZ AXO ETOMIC BTCH PIZZA BEER NINJA OOT BNTN CHAIN PRLPAY DSEC) 84 | for i in "${kmd_coins[@]}" 85 | do 86 | getstats_kmd "$i" 87 | done 88 | 89 | cat < 91 |
NTRZdUTXOsBalanceHeight
92 | EOF 93 | -------------------------------------------------------------------------------- /report_alive.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # this script can be used for check komodo daemon alive on your node 4 | # and report via Telegram bot. 5 | 6 | # (c) Decker 7 | 8 | date=$(date +"%F %T") 9 | token=000000000:aaaaaaa-bbbbbbbbbbbbbbbbbbbbbbbbbbb # your telegram bot token 10 | chat_id=0 # telegram chat_id to report 11 | proxy="-x socks5h://x.x.x.x:1080 --proxy-user user:proxypass" # proxy args for curl, if needed, 12 | 13 | komodo_cli="$HOME/komodo/src/komodo-cli" 14 | 15 | function init_colors () { 16 | RESET="\033[0m" 17 | BLACK="\033[30m" 18 | RED="\033[31m" 19 | GREEN="\033[32m" 20 | YELLOW="\033[33m" 21 | BLUE="\033[34m" 22 | MAGENTA="\033[35m" 23 | CYAN="\033[36m" 24 | WHITE="\033[37m" 25 | } 26 | # -------------------------------------------------------------------------- 27 | function log_print() { 28 | datetime=$(date '+%Y-%m-%d %H:%M:%S') 29 | echo -e [$datetime] $1 30 | } 31 | # -------------------------------------------------------------------------- 32 | function check_for_daemon() { 33 | #if [[ ! -z $1 && $1 != "KMD" ]] 34 | if [ ! -z $1 ] && [ $1 != "KMD" ] 35 | then 36 | coin=$1 37 | asset=" -ac_name=$1" 38 | else 39 | coin="KMD" 40 | asset="" 41 | fi 42 | 43 | # command && echo OK || echo Failed 44 | # http://mywiki.wooledge.org/BashGuide/TestsAndConditionals 45 | # https://www.opennet.ru/docs/RUS/bash_scripting_guide/c2171.html 46 | 47 | #$komodo_cli $asset getinfo >/dev/null 2>&1 48 | 49 | result=$($komodo_cli $asset getinfo 2>&1) # save both stdout and stderr to a variable 50 | error=$? 51 | 52 | if [ $error -eq 0 ]; then 53 | log_print "\x5B${YELLOW}${coin}${RESET}\x5D ${GREEN}OK${RESET}" 54 | else 55 | log_print "\x5B${YELLOW}${coin}${RESET}\x5D ${RED}$result${RESET}" 56 | fi 57 | 58 | if [ $error -ne 0 ]; then 59 | nl=$'\n' 60 | text="node report (${date})${nl}" 61 | text="${text}⚠️ ${coin} ${result}${nl}" 62 | # echo -e "\"$text\"" 63 | curl -X POST -s $proxy "https://api.telegram.org/bot$token/sendMessage" -d "chat_id=$chat_id&parse_mode=HTML&text=$text" > /dev/null 64 | fi 65 | } 66 | 67 | init_colors 68 | # check_for_daemon KMD 69 | readarray -t kmd_coins < <(curl -s https://raw.githubusercontent.com/jl777/komodo/beta/src/assetchains.json | jq -r '[.[].ac_name] | join("\n")') 70 | kmd_coins+=(KMD) 71 | for i in "${kmd_coins[@]}" 72 | do 73 | check_for_daemon $i 74 | done -------------------------------------------------------------------------------- /resend_funds_all.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | komodo_cli_binary="$HOME/komodo/src/komodo-cli" 3 | readarray -t kmd_coins < <(curl -s https://raw.githubusercontent.com/KomodoPlatform/dPoW/master/iguana/assetchains.json | jq -r '[.[].ac_name] | join("\n")') 4 | # printf '%s\n' "${kmd_coins[@]}" 5 | 6 | init_colors() 7 | { 8 | RESET="\033[0m" 9 | BLACK="\033[30m" 10 | RED="\033[31m" 11 | GREEN="\033[32m" 12 | YELLOW="\033[33m" 13 | BLUE="\033[34m" 14 | MAGENTA="\033[35m" 15 | CYAN="\033[36m" 16 | WHITE="\033[37m" 17 | 18 | # Text Color Variables http://misc.flogisoft.com/bash/tip_colors_and_formatting 19 | tcLtG="\033[00;37m" # LIGHT GRAY 20 | tcDkG="\033[01;30m" # DARK GRAY 21 | tcLtR="\033[01;31m" # LIGHT RED 22 | tcLtGRN="\033[01;32m" # LIGHT GREEN 23 | tcLtBL="\033[01;34m" # LIGHT BLUE 24 | tcLtP="\033[01;35m" # LIGHT PURPLE 25 | tcLtC="\033[01;36m" # LIGHT CYAN 26 | tcW="\033[01;37m" # WHITE 27 | tcRESET="\033[0m" 28 | tcORANGE="\033[38;5;209m" 29 | } 30 | 31 | init_colors 32 | 33 | for i in "${kmd_coins[@]}" 34 | do 35 | echo -e "- Cleaning ${GREEN}${i}${RESET}" 36 | (${komodo_cli_binary} -ac_name=${i} listunspent | jq '. | { "utxos" : length }' && ${komodo_cli_binary} -ac_name=${i} getwalletinfo | jq '{ "txcount" : .txcount }') | jq -s add 37 | echo KOMODOD_CONFIGFILE=~/.komodo/$i/$i.conf ./resend_funds.sh 38 | KOMODOD_CONFIGFILE=~/.komodo/$i/$i.conf ./resend_funds.sh 39 | done -------------------------------------------------------------------------------- /restart_daemons.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # sample of daemons restart script for cron 4 | # (c) Decker, 2020-2021 5 | 6 | KOMODOD_PATH=${HOME}/komodo/src/komodod 7 | source ${HOME}/komodo/src/pubkey.txt 8 | 9 | # -------------------------------------------------------------------------- 10 | function init_colors() { 11 | RESET="\033[0m" 12 | BLACK="\033[30m" 13 | RED="\033[31m" 14 | GREEN="\033[32m" 15 | YELLOW="\033[33m" 16 | BLUE="\033[34m" 17 | MAGENTA="\033[35m" 18 | CYAN="\033[36m" 19 | WHITE="\033[37m" 20 | BRIGHT="\033[1m" 21 | DARKGREY="\033[90m" 22 | } 23 | # -------------------------------------------------------------------------- 24 | function log_print() { 25 | datetime=$(date '+%Y-%m-%d %H:%M:%S') 26 | echo -e [$datetime] $1 27 | } 28 | 29 | init_colors 30 | 31 | ASSETCHAINS_FILE=/tmp/assetchains.json 32 | 33 | if [ -z $(command -v jq) ]; then 34 | log_print "${RED}ERROR:${RESET} jq should be installed (sudo apt install jq)" 35 | exit 1 36 | fi 37 | 38 | curl -s https://raw.githubusercontent.com/KomodoPlatform/dPoW/master/iguana/assetchains.json -o ${ASSETCHAINS_FILE} 39 | readarray -t kmd_coins < <(cat ${ASSETCHAINS_FILE} | jq -r '[.[].ac_name] | join("\n")') 40 | 41 | kmd_coins+=("KMD") 42 | 43 | for coin in "${kmd_coins[@]}" 44 | do 45 | if [ ${coin} != "KMD" ] 46 | then 47 | PID_FILE=${HOME}/.komodo/${coin}/komodod.pid 48 | DAEMON_DIR=${HOME}/.komodo/${coin} 49 | 50 | else 51 | PID_FILE=${HOME}/.komodo/komodod.pid 52 | DAEMON_DIR=${HOME}/.komodo 53 | fi 54 | 55 | # https://stackoverflow.com/questions/806906/how-do-i-test-if-a-variable-is-a-number-in-bash 56 | # https://www.gnu.org/software/bash/manual/bash.html#Bash-Conditional-Expressions 57 | 58 | NEED_RESTART=false 59 | if [ -f "${PID_FILE}" ]; then 60 | DAEMON_PID=$(ps -p $(cat ${PID_FILE}) -o pid=) 61 | if [ -n "${DAEMON_PID}" ] && [ "${DAEMON_PID}" -eq "${DAEMON_PID}" ]; then 62 | log_print "\x5B${YELLOW}${coin}${RESET}\x5D ${GREEN}RUNNING${RESET}" 63 | # pid file exists, process exists 64 | else 65 | log_print "\x5B${YELLOW}${coin}${RESET}\x5D ${RED}CRASHED${RESET}" 66 | NEED_RESTART=true 67 | # pid file exists, but such process absent 68 | fi 69 | else 70 | if [ -d "${DAEMON_DIR}" ]; then 71 | log_print "\x5B${YELLOW}${coin}${RESET}\x5D ${RED}STOPPED${RESET}" 72 | NEED_RESTART=true 73 | # coin directory exists, but pid file absent 74 | else 75 | log_print "\x5B${YELLOW}${coin}${RESET}\x5D ${DARKGREY}SKIPPED${RESET}" 76 | # skipped - means, coin directory doesn't exist, this coin never launched on this system, so nothing to restart 77 | fi 78 | fi 79 | 80 | if [ "${NEED_RESTART}" = "true" ]; then 81 | 82 | # set pubkey if defined 83 | PUBKEY= 84 | if [ -n "${pubkey}" ]; then 85 | PUBKEY="-pubkey=${pubkey}" 86 | fi 87 | 88 | # set additional args for KMD 89 | ADDITIONAL_ARGS= 90 | if [ ${coin} = "KMD" ] 91 | then 92 | ADDITIONAL_ARGS="-gen -genproclimit=1 -notary=.litecoin/litecoin.conf -opretmintxfee=0.004 -minrelaytxfee=0.000035" 93 | fi 94 | 95 | # https://stackoverflow.com/questions/25378013/how-to-convert-a-json-object-to-key-value-format-in-jq 96 | # https://jqplay.org/ 97 | 98 | # here we just omit addnode, bcz this is array and it should be handled differently 99 | COMMAND_LINE=$(cat ${ASSETCHAINS_FILE} | jq -r 'map(select(.ac_name | contains ("'${coin}'"))) | map(del(.addnode)) | .[] | to_entries | map("-\(.key)=\(.value|tostring)") | join(" ")') 100 | # and here we process only addnode(s) 101 | ADDNODES=$(cat ${ASSETCHAINS_FILE} | jq -r 'map(select(.ac_name | contains ("'${coin}'"))) | .[].addnode | map("-addnode=" + .) | .[]' 2>/dev/null) 102 | log_print "Command line: ${KOMODOD_PATH} ${COMMAND_LINE} ${ADDNODES} ${ADDITIONAL_ARGS} ${PUBKEY}" 103 | 104 | # https://unix.stackexchange.com/questions/444946/how-can-we-run-a-command-stored-in-a-variable 105 | # https://stackoverflow.com/questions/10586153/how-to-split-a-string-into-an-array-in-bash 106 | # https://stackoverflow.com/questions/3683910/executing-shell-command-in-background-from-script 107 | 108 | #declare -a DAEMON_CMD=(${KOMODOD_PATH} ${COMMAND_LINE} ${ADDNODES} ${ADDITIONAL_ARGS} ${PUBKEY}) 109 | #set -x 110 | #"${DAEMON_CMD[@]}" & 111 | #set +x 112 | 113 | ${KOMODOD_PATH} ${COMMAND_LINE} ${ADDNODES} ${ADDITIONAL_ARGS} ${PUBKEY} & 114 | fi 115 | done 116 | 117 | -------------------------------------------------------------------------------- /restart_kmd_daemons.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # (q) Decker 2023-2024 4 | 5 | # The main purpose of this script is to quickly restart all running Komodo daemon instances. 6 | # To use it, navigate to the Komodo (or KomodoOcean) repository's `./src` directory and then 7 | # launch the script. 8 | 9 | # Don't forget to shut down Iguana using `pkill -9 iguana` before restarting the daemons. 10 | 11 | if [[ ! -x ./komodod || ! -x ./komodo-cli ]]; then 12 | echo "Error: ./komodod and/or ./komodo-cli not found in the current directory." 13 | echo "Please make sure to run this script from the Komodo repo src directory." 14 | exit 1 15 | fi 16 | 17 | ### 1. Check launched 18 | launched_ac=() 19 | while read -r pid args; do 20 | ac_name=$(echo $args | grep -oP '(?<=-ac_name=)[^\s]+') 21 | if [ -n "$ac_name" ]; then 22 | # echo "ac_name: $ac_name" 23 | launched_ac+=("$ac_name") 24 | fi 25 | done < <(ps -eo pid,cmd | grep '[k]omodod' | awk '{$2=""; print $0}') 26 | # echo "Launched: ${launched_ac[@]}" 27 | 28 | assetchains_json=$(curl -s https://raw.githubusercontent.com/KomodoPlatform/dPoW/master/iguana/assetchains.json) 29 | echo -e "\nChecking launched AC komodod instances against dPoW repo:\n" 30 | echo "$assetchains_json" | jq -r '.[].ac_name' | while read -r asset_ac_name; do 31 | # echo "Checking: $asset_ac_name" 32 | if [[ " ${launched_ac[@]} " =~ " $asset_ac_name " ]]; then 33 | echo -e "\e[32m█ $asset_ac_name\e[0m" # launched 34 | else 35 | echo -e "\e[31m█ $asset_ac_name\e[0m" # not launched 36 | fi 37 | done 38 | 39 | # VRSC now uses `verusd` as its daemon name, and TOKEL uses `tokeld`, but let's make sure 40 | # that we're not trying to re-launch third-party chains with the original `komodod`. 41 | 42 | ### 2. Restart 43 | ps -eo pid,cmd | grep '[k]omodod' | awk '{$2=""; print $0}' | while read -r pid args; do 44 | ac_name=$(echo $args | grep -oP '(?<=-ac_name=)[^\s]+') 45 | 46 | if [[ "$ac_name" == "MCL" || "$ac_name" == "VRSC" || "$ac_name" == "TOKEL" ]]; then 47 | echo -e "\e[33mSkipping $ac_name\e[0m [PID: $pid]" 48 | continue 49 | fi 50 | 51 | if [ -n "$ac_name" ]; then 52 | echo -e "\e[33m$ac_name\e[0m [PID: $pid]" 53 | ./komodo-cli -ac_name=$ac_name stop 54 | else 55 | echo -e "\e[33mKMD\e[0m [PID: $pid]" 56 | ./komodo-cli stop 57 | fi 58 | while kill -0 $pid 2>/dev/null; do 59 | echo -n "█" 60 | sleep 1 61 | done 62 | echo -e "\n" 63 | ./komodod $args & 64 | sleep 1 65 | done 66 | -------------------------------------------------------------------------------- /sendawaynn.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # (c) Decker, 2018 3 | 4 | RESET="\033[0m" 5 | BLACK="\033[30m" 6 | RED="\033[31m" 7 | GREEN="\033[32m" 8 | YELLOW="\033[33m" 9 | BLUE="\033[34m" 10 | MAGENTA="\033[35m" 11 | CYAN="\033[36m" 12 | WHITE="\033[37m" 13 | 14 | curdir=$(pwd) 15 | curluser=user 16 | curlpass=pass 17 | curlport=7771 18 | asset= 19 | 20 | echo -e 'SendAway Script v0.01alpha (c) '${GREEN}Decker${RESET}, 2018 21 | echo '-------------------------------------------' 22 | 23 | curl -s --user $curluser:$curlpass --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "listunspent", "params": [0, 9999999]}' -H 'content-type: text/plain;' http://127.0.0.1:$curlport/ | jq .result > $curdir/createrawtx.txt 24 | # we will send all spendable and generated coins 25 | transactions=$(cat $curdir/createrawtx.txt | jq '.[] | select (.spendable == true and .generated == true) | del (.generated, .address, .account, .scriptPubKey, .amount, .interest, .confirmations, .spendable)' | jq -r -s '. | tostring') 26 | balance=$(cat $curdir/createrawtx.txt | jq '.[] | select (.spendable == true and .generated == true) | .amount' | jq -s add) 27 | balance=$(echo "scale=8; $balance/1*1" | bc -l | sed 's/^\./0./') 28 | tosend=$balance 29 | change=$(echo "scale=8; ($balance-$tosend)/1*1" | bc -l | sed 's/^\./0./') 30 | 31 | echo 'Balance: '$balance 32 | echo 'To send: '$tosend 33 | echo ' Change: '$change 34 | 35 | # first address is where you want to send to, second address in your NN address for change (!), if tosend != balance 36 | # don't forget to change it ... 37 | 38 | if (( $(echo "$change > 0" | bc -l) )); then 39 | addresses='{"RTCVGuoSNehKG8YYxcoskC7LK1yZhgvQRV":'$tosend',"RNJmgYaFF5DbnrNUX6pMYz9rcnDKC2tuAc":'$change'}' 40 | else 41 | addresses='{"RTCVGuoSNehKG8YYxcoskC7LK1yZhgvQRV":'$tosend'}' 42 | fi 43 | 44 | echo "{\"jsonrpc\": \"1.0\", \"id\":\"curltest\", \"method\": \"createrawtransaction\", \"params\": [$transactions,$addresses] }" > $curdir/createrawtx.curl 45 | 46 | # we are using curl here to avoid an error "Argument list too long" with long-long list of utxos if we executing komodo-cli 47 | 48 | hex=$(curl -s --user $curluser:$curlpass --data-binary "@$curdir/createrawtx.curl" -H 'content-type: text/plain;' http://127.0.0.1:$curlport/ | jq -r .result) 49 | # setting of nLockTime 50 | nlocktime=$(printf "%08x" $(date +%s) | dd conv=swab 2> /dev/null | rev) 51 | # hex=${hex::-8}$nlocktime # leave it here for non-sapling chains, like ZILLA and OOT 52 | txtail=000000000000000000000000000000 53 | hex=${hex::-38}${nlocktime}${txtail} 54 | signed=$(curl -s --user $curluser:$curlpass --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "signrawtransaction", "params": ["'$hex'"]}' -H 'content-type: text/plain;' http://127.0.0.1:$curlport/ | jq -r .result.hex) 55 | 56 | #curl -s --user $curluser:$curlpass --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "decoderawtransaction", "params": ["'$signed'"]}' -H 'content-type: text/plain;' http://127.0.0.1:$curlport/ | jq 57 | 58 | echo -e '\n' 59 | echo -e ${YELLOW}'Unsigned TX: '${RESET}$hex 60 | echo -e '\n' 61 | echo -e ${YELLOW}'Signed TX: '${RESET}$signed 62 | echo -e '\n' 63 | echo -e 'Now you are able to broadcast your signed tx via "sendrawtransaction" or in any Insight Explorer. '${GREEN}'Verify it before broadcast!'${RESET} 64 | 65 | -------------------------------------------------------------------------------- /sendawaynn_auto.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # (c) Decker, 2018 3 | 4 | RESET="\033[0m" 5 | BLACK="\033[30m" 6 | RED="\033[31m" 7 | GREEN="\033[32m" 8 | YELLOW="\033[33m" 9 | BLUE="\033[34m" 10 | MAGENTA="\033[35m" 11 | CYAN="\033[36m" 12 | WHITE="\033[37m" 13 | 14 | curdir=$(pwd) 15 | curluser=user 16 | curlpass=pass 17 | curlport=7771 18 | asset= 19 | 20 | echo -e 'SendAway Script v0.01alpha (c) '${GREEN}Decker${RESET}, 2018 21 | echo '-------------------------------------------' 22 | 23 | curl -s --user $curluser:$curlpass --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "listunspent", "params": [0, 9999999]}' -H 'content-type: text/plain;' http://127.0.0.1:$curlport/ | jq .result > $curdir/createrawtx.txt 24 | # we will send all spendable and generated coins 25 | transactions=$(cat $curdir/createrawtx.txt | jq '.[] | select (.spendable == true and .generated == true) | del (.generated, .address, .account, .scriptPubKey, .amount, .interest, .confirmations, .spendable)' | jq -r -s '. | tostring') 26 | balance=$(cat $curdir/createrawtx.txt | jq '.[] | select (.spendable == true and .generated == true) | .amount' | jq -s add) 27 | balance=$(echo "scale=8; $balance/1*1" | bc -l | sed 's/^\./0./') 28 | tosend=$balance 29 | change=$(echo "scale=8; ($balance-$tosend)/1*1" | bc -l | sed 's/^\./0./') 30 | 31 | echo 'Balance: '$balance 32 | echo 'To send: '$tosend 33 | echo ' Change: '$change 34 | 35 | # first address is where you want to send to, second address in your NN address for change (!), if tosend != balance 36 | # don't forget to change it ... 37 | 38 | if (( $(echo "$change > 0" | bc -l) )); then 39 | addresses='{"RTCVGuoSNehKG8YYxcoskC7LK1yZhgvQRV":'$tosend',"RNJmgYaFF5DbnrNUX6pMYz9rcnDKC2tuAc":'$change'}' 40 | else 41 | addresses='{"RTCVGuoSNehKG8YYxcoskC7LK1yZhgvQRV":'$tosend'}' 42 | fi 43 | 44 | echo "{\"jsonrpc\": \"1.0\", \"id\":\"curltest\", \"method\": \"createrawtransaction\", \"params\": [$transactions,$addresses] }" > $curdir/createrawtx.curl 45 | 46 | # we are using curl here to avoid an error "Argument list too long" with long-long list of utxos if we executing komodo-cli 47 | 48 | hex=$(curl -s --user $curluser:$curlpass --data-binary "@$curdir/createrawtx.curl" -H 'content-type: text/plain;' http://127.0.0.1:$curlport/ | jq -r .result) 49 | # setting of nLockTime 50 | nlocktime=$(printf "%08x" $(date +%s) | dd conv=swab 2> /dev/null | rev) 51 | # hex=${hex::-8}$nlocktime # leave it here for non-sapling chains, like ZILLA and OOT 52 | txtail=000000000000000000000000000000 53 | hex=${hex::-38}${nlocktime}${txtail} 54 | signed=$(curl -s --user $curluser:$curlpass --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "signrawtransaction", "params": ["'$hex'"]}' -H 'content-type: text/plain;' http://127.0.0.1:$curlport/ | jq -r .result.hex) 55 | 56 | #curl -s --user $curluser:$curlpass --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "decoderawtransaction", "params": ["'$signed'"]}' -H 'content-type: text/plain;' http://127.0.0.1:$curlport/ | jq 57 | 58 | echo -e '\n' 59 | echo -e ${YELLOW}'Unsigned TX: '${RESET}$hex 60 | echo -e '\n' 61 | echo -e ${YELLOW}'Signed TX: '${RESET}$signed 62 | echo -e '\n' 63 | echo -e 'Now you are able to broadcast your signed tx via "sendrawtransaction" or in any Insight Explorer. '${GREEN}'Verify it before broadcast!'${RESET} 64 | 65 | # actually send 66 | echo "{\"jsonrpc\": \"1.0\", \"id\":\"curltest\", \"method\": \"sendrawtransaction\", \"params\": [\"$signed\"] }" > $curdir/createrawtx.curl 67 | curl -s --user $curluser:$curlpass --data-binary "@$curdir/createrawtx.curl" -H 'content-type: text/plain;' http://127.0.0.1:$curlport/ -------------------------------------------------------------------------------- /sendawaynn_fee.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # (c) Decker, 2018-2020 3 | 4 | # -------------------------------------------------------------------------- 5 | function init_colors() { 6 | RESET="\033[0m" 7 | BLACK="\033[30m" 8 | RED="\033[31m" 9 | GREEN="\033[32m" 10 | YELLOW="\033[33m" 11 | BLUE="\033[34m" 12 | MAGENTA="\033[35m" 13 | CYAN="\033[36m" 14 | WHITE="\033[37m" 15 | BRIGHT="\033[1m" 16 | DARKGREY="\033[90m" 17 | } 18 | # -------------------------------------------------------------------------- 19 | function log_print() { 20 | datetime=$(date '+%Y-%m-%d %H:%M:%S') 21 | echo -e [$datetime] $1 22 | } 23 | 24 | # -------------------------------------------------------------------------- 25 | # https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html 26 | 27 | function checkconfig() 28 | { 29 | if ! grep -qs '^rpcpassword=' "${KOMODOD_CONFIGFILE}" ; then 30 | log_print "Parsing: ${KOMODOD_CONFIGFILE} - ${RED}FAILED${RESET}" 31 | return 1 32 | fi 33 | if ! grep -qs '^rpcuser=' "${KOMODOD_CONFIGFILE}" ; then 34 | log_print "Parsing: ${KOMODOD_CONFIGFILE} - ${RED}FAILED${RESET}" 35 | return 1 36 | fi 37 | 38 | grep -qs '^rpcpassword=' "${KOMODOD_CONFIGFILE}" 39 | KOMODOD_RPCPASSWORD=$(grep -s '^rpcpassword=' "${KOMODOD_CONFIGFILE}") 40 | KOMODOD_RPCPASSWORD=${KOMODOD_RPCPASSWORD/rpcpassword=/} 41 | 42 | grep -qs '^rpcuser=' "${KOMODOD_CONFIGFILE}" 43 | KOMODOD_RPCUSER=$(grep -s '^rpcuser=' "${KOMODOD_CONFIGFILE}") 44 | KOMODOD_RPCUSER=${KOMODOD_RPCUSER/rpcuser=/} 45 | 46 | if ! grep -qs '^rpcport=' "${KOMODOD_CONFIGFILE}" ; then 47 | KOMODO_RPCPORT=7771 48 | else 49 | KOMODO_RPCPORT=$(grep -s '^rpcport=' "${KOMODOD_CONFIGFILE}") 50 | KOMODO_RPCPORT=${KOMODO_RPCPORT/rpcport=/} 51 | fi 52 | 53 | log_print "Parsing RPC credentials: ${KOMODOD_CONFIGFILE} - ${GREEN}OK${RESET}" 54 | 55 | } 56 | # -------------------------------------------------------------------------- 57 | 58 | # daemon config 59 | KOMODOD_DEFAULT_DATADIR=${KOMODOD_DEFAULT_DATADIR:-"$HOME/.komodo"} 60 | KOMODOD_CONFIGFILE=${KOMODOD_CONFIGFILE:-"$KOMODOD_DEFAULT_DATADIR/komodo.conf"} 61 | KOMODOD_RPCHOST=127.0.0.1 62 | # addresses config 63 | WITHDRAW_ADDRESS=RTCVGuoSNehKG8YYxcoskC7LK1yZhgvQRV 64 | 65 | echo -e 'SendAway Script v0.02alpha (c) '${GREEN}Decker${RESET}, 2018-2020 66 | echo '-------------------------------------------' 67 | 68 | init_colors 69 | log_print "Starting ..." 70 | checkconfig || exit 71 | 72 | curdir=$(pwd) 73 | 74 | curl -s --user "${KOMODOD_RPCUSER}:${KOMODOD_RPCPASSWORD}" --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "listunspent", "params": [0, 9999999]}' -H 'content-type: text/plain;' http://${KOMODOD_RPCHOST}:${KOMODO_RPCPORT}/ | jq .result > $curdir/createrawtx.txt 75 | 76 | # we will send all spendable and generated coins 77 | UTXOSFILTER=".spendable == true and .generated == true" 78 | #FIXED_FEE=0.00077777 # TODO: add tx fee calculation (!) 79 | FIXED_FEE=0.00001000 80 | 81 | #transactions=$(cat $curdir/createrawtx.txt | jq '.[] | select ('"${UTXOSFILTER}"') | del (.generated, .address, .account, .scriptPubKey, .amount, .interest, .confirmations, .spendable)' | jq -r -s '. | tostring') 82 | transactions=$(cat $curdir/createrawtx.txt | jq '.[] | select ('"${UTXOSFILTER}"') | {"txid": .txid, "vout": .vout}' | jq -r -s '. | tostring') 83 | #echo "${transactions}" 84 | 85 | balance=$(cat $curdir/createrawtx.txt | jq '.[] | select ('"${UTXOSFILTER}"') | .amount' | jq -s add) 86 | balance=$(echo "${balance}" | jq 'def round: tostring | (split(".") + ["0"])[:2] | [.[0], "\(.[1])"[:8]] | join(".") | tonumber; 87 | . | round') 88 | 89 | #balance=$(echo "scale=8; $balance/1*1" | bc -l | sed 's/^\./0./') 90 | 91 | log_print "Balance: ${GREEN}${balance}${RESET}" 92 | log_print " Fee: ${FIXED_FEE}" 93 | 94 | #tosend=$balance 95 | tosend=$(echo "${balance}" | jq 'def round: tostring | (split(".") + ["0"])[:2] | [.[0], "\(.[1])"[:8]] | join(".") | tonumber; 96 | .-'"${FIXED_FEE}"' | round') 97 | 98 | log_print "To send: ${GREEN}${tosend}${RESET}" 99 | 100 | addresses='{"'${WITHDRAW_ADDRESS}'":'$tosend'}' 101 | 102 | echo "{\"jsonrpc\": \"1.0\", \"id\":\"curltest\", \"method\": \"createrawtransaction\", \"params\": [$transactions,$addresses] }" > $curdir/createrawtx.curl 103 | # we are using curl here to avoid an error "Argument list too long" with long-long list of utxos if we executing komodo-cli 104 | 105 | hex=$(curl -s --user "${KOMODOD_RPCUSER}:${KOMODOD_RPCPASSWORD}" --data-binary "@$curdir/createrawtx.curl" -H 'content-type: text/plain;' http://${KOMODOD_RPCHOST}:${KOMODO_RPCPORT}/ | jq -r .result) 106 | # setting of nLockTime 107 | nlocktime=$(printf "%08x" $(date +%s) | dd conv=swab 2> /dev/null | rev) 108 | # hex=${hex::-8}$nlocktime # leave it here for non-sapling chains, like ZILLA and OOT 109 | txtail=000000000000000000000000000000 110 | hex=${hex::-38}${nlocktime}${txtail} 111 | 112 | signed=$(curl -s --user "${KOMODOD_RPCUSER}:${KOMODOD_RPCPASSWORD}" --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "signrawtransaction", "params": ["'$hex'"]}' -H 'content-type: text/plain;' http://${KOMODOD_RPCHOST}:${KOMODO_RPCPORT}/ | jq -r .result.hex) 113 | 114 | #curl -s --user "${KOMODOD_RPCUSER}:${KOMODOD_RPCPASSWORD}" --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "decoderawtransaction", "params": ["'$signed'"]}' -H 'content-type: text/plain;' http://${KOMODOD_RPCHOST}:${KOMODO_RPCPORT}/ | jq 115 | 116 | echo -e '\n' 117 | echo -e ${YELLOW}'Unsigned TX: '${RESET}$hex 118 | echo -e '\n' 119 | echo -e ${YELLOW}'Signed TX: '${RESET}$signed 120 | echo -e '\n' 121 | echo -e 'Now you are able to broadcast your signed tx via "sendrawtransaction" or in any Insight Explorer. '${GREEN}'Verify it before broadcast!'${RESET} 122 | 123 | # actually send 124 | # echo "{\"jsonrpc\": \"1.0\", \"id\":\"curltest\", \"method\": \"sendrawtransaction\", \"params\": [\"$signed\"] }" > $curdir/createrawtx.curl 125 | # curl -s --user "${KOMODOD_RPCUSER}:${KOMODOD_RPCPASSWORD}" --data-binary "@$curdir/createrawtx.curl" -H 'content-type: text/plain;' http://${KOMODOD_RPCHOST}:${KOMODO_RPCPORT}/ -------------------------------------------------------------------------------- /sendawaynn_subsidy.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # (c) Decker, 2024 4 | # 5 | # The main purpose of the sendawaynn_subsidy.sh script is to 6 | # consolidate all funds on the NN pubkey that remain on bech32 7 | # (ltc1) addresses in your wallet (subsidy funds) and send them 8 | # to (which should also be bech32). 9 | # 10 | # Example: 11 | # 12 | # Usage: ./sendawaynn_subsidy.sh 13 | 14 | set -euo pipefail 15 | IFS=$'\n\t' 16 | export LC_ALL=C 17 | 18 | # Configuration 19 | LOG_FILE="$HOME/litecoin_tx.log" 20 | 21 | # Logging function 22 | log() { 23 | echo "$(date '+%Y-%m-%d %H:%M:%S') - $*" | tee -a "$LOG_FILE" 24 | } 25 | 26 | # Error handling 27 | error_exit() { 28 | echo "Error on line $1" | tee -a "$LOG_FILE" 29 | exit 1 30 | } 31 | 32 | trap 'error_exit $LINENO' ERR 33 | 34 | # Function to locate litecoin-cli 35 | find_litecoin_cli() { 36 | local local_path="$HOME/litecoin/src/litecoin-cli" 37 | 38 | if [[ -x "$local_path" ]]; then 39 | echo "$local_path" 40 | elif command -v litecoin-cli >/dev/null 2>&1; then 41 | echo "$(command -v litecoin-cli)" 42 | else 43 | echo "" 44 | fi 45 | } 46 | 47 | # Locate litecoin-cli 48 | LITECOIN_CLI=$(find_litecoin_cli) 49 | 50 | if [[ -z "$LITECOIN_CLI" ]]; then 51 | echo "Error: litecoin-cli not found in ~/litecoin/src or in PATH." 52 | exit 1 53 | fi 54 | 55 | # Check for other required commands 56 | for cmd in jq bc; do 57 | if ! command -v "$cmd" &> /dev/null; then 58 | echo "Error: $cmd is not installed or not in PATH." 59 | exit 1 60 | fi 61 | done 62 | 63 | # Input parameters 64 | if [ $# -lt 1 ]; then 65 | echo "Usage: $0 [fee]" 66 | exit 1 67 | fi 68 | 69 | TARGET_ADDRESS="$1" 70 | 71 | # Validate Litecoin address (basic regex for Bech32) 72 | if ! [[ "$TARGET_ADDRESS" =~ ^ltc1[a-z0-9]{39}$ ]]; then 73 | echo "Error: Invalid Litecoin address format." 74 | exit 1 75 | fi 76 | 77 | FEE="${2:-0.001}" 78 | 79 | # Fetch UTXOs 80 | log "Fetching UTXOs..." 81 | UTXOS=$("$LITECOIN_CLI" listunspent) 82 | 83 | # Parse UTXOs 84 | PARSED_DATA=$(echo "$UTXOS" | jq --arg prefix "ltc1" ' 85 | { 86 | inputs: [.[] | select(.address | startswith($prefix)) | select(.spendable == true) | {txid: .txid, vout: .vout}], 87 | total: ([.[] | select(.address | startswith($prefix)) | select(.spendable == true) | .amount] | add) 88 | }' 89 | ) 90 | 91 | INPUTS=$(echo "$PARSED_DATA" | jq '.inputs') 92 | TOTAL_AMOUNT=$(echo "$PARSED_DATA" | jq '.total') 93 | 94 | log "Inputs for Transaction:" 95 | log "$INPUTS" 96 | log "Total Amount of Selected UTXOs: $TOTAL_AMOUNT LTC" 97 | 98 | # Calculate amount to send 99 | AMOUNT_TO_SEND=$(echo "$TOTAL_AMOUNT - $FEE" | bc -l | tr -d '\n') 100 | AMOUNT_TO_SEND=$(printf "%.8f" "$AMOUNT_TO_SEND") 101 | 102 | # Check if amount to send is positive 103 | if (( $(echo "$AMOUNT_TO_SEND <= 0" | bc -l) )); then 104 | echo "Error: Insufficient funds after deducting the fee of $FEE LTC." 105 | exit 1 106 | fi 107 | 108 | log "Amount to Send (after $FEE LTC fee): $AMOUNT_TO_SEND LTC" 109 | 110 | # Create raw transaction 111 | log "Creating raw transaction..." 112 | RAW_TX=$("$LITECOIN_CLI" createrawtransaction "$INPUTS" "{\"$TARGET_ADDRESS\":$AMOUNT_TO_SEND}") 113 | log "Raw Transaction:" 114 | log "$RAW_TX" 115 | 116 | # Sign the transaction 117 | log "Signing the transaction..." 118 | SIGNED_TX=$("$LITECOIN_CLI" signrawtransaction "$RAW_TX" 2>/dev/null || true) 119 | 120 | # Determine signing command 121 | if [[ -z "$SIGNED_TX" ]] || ! echo "$SIGNED_TX" | jq -e '.complete' >/dev/null; then 122 | log "signrawtransaction was empty or incomplete, falling back to signrawtransactionwithwallet..." 123 | SIGNED_TX=$("$LITECOIN_CLI" signrawtransactionwithwallet "$RAW_TX") 124 | SIGN_CMD="signrawtransactionwithwallet" 125 | else 126 | SIGN_CMD="signrawtransaction" 127 | fi 128 | 129 | log "Signing command used: $SIGN_CMD" 130 | log "Signed Transaction:" 131 | log "$SIGNED_TX" 132 | 133 | # Verify if signing was complete 134 | if ! echo "$SIGNED_TX" | jq -e '.complete' >/dev/null; then 135 | echo "Error: Transaction signing incomplete." 136 | exit 1 137 | fi 138 | 139 | # Prompt for confirmation 140 | read -p "Do you want to send this transaction? (yes/no): " CONFIRMATION 141 | 142 | if [ "$CONFIRMATION" == "yes" ]; then 143 | # Extract hex and send transaction 144 | TX_HEX=$(echo "$SIGNED_TX" | jq -r '.hex') 145 | SEND_RESULT=$("$LITECOIN_CLI" sendrawtransaction "$TX_HEX") 146 | log "Transaction sent! TXID: $SEND_RESULT" 147 | else 148 | log "Transaction not sent." 149 | fi 150 | -------------------------------------------------------------------------------- /sendfromaddress.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Usage Guide: https://techloverhd.com/2020/07/how-to-send-komodo-or-any-smart-chain-funds-from-your-address-without-rescanning-the-wallet/ 3 | 4 | FROM_ADDRESS=RMR3NGjTGjHcEpixpveKXX9L4wTUf3Db2x 5 | curl -s https://kmdexplorer.io/insight-api-komodo/addr/$FROM_ADDRESS/utxo > all.utxos 6 | utxos=$( 100 and .amount != 0.0001 and .amount != 0.00000055) | { txid: .txid, vout: .vout}]") 8 | amount=$(echo "$utxos" | jq -r "[.[] | select (.confirmations > 100 and .amount != 0.0001 and .amount != 0.00000055) | .amount] | add") 9 | # echo $amount 10 | # https://stackoverflow.com/questions/46117049/how-i-can-round-digit-on-the-last-column-to-2-decimal-after-a-dot-using-jq 11 | value=$(echo $amount | jq 'def round: tostring | (split(".") + ["0"])[:2] | [.[0], "\(.[1])"[:8]] | join(".") | tonumber; . | round') 12 | # echo $value 13 | echo "createrawtransaction '$utxo' '{\"RMR3NGjTGjHcEpixpveKXX9L4wTUf3Db2x\": $value}'" 14 | -------------------------------------------------------------------------------- /split_nn.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Split NN script by Decker (c) 2018 4 | 5 | # *** Small how-to: *** 6 | 7 | # This script can be used to fund your notary with SPLIT_COUNT (50) utxos SPLIT_VALUE (0.0001) KMD each, 8 | # same way as in iguana. You don't need to import any privkeys in your komodo daemon. Funds will get 9 | # from FROM_ADDRESS with given FROM_PRIVKEY. Insight explorer API will used for listunspent and 10 | # komodod for signing transaction. If somebody will able to modify this script to use openssl for signing 11 | # tx instead of komodod - it would be nice. PRs are welcome. 12 | 13 | RESET="\033[0m" 14 | BLACK="\033[30m" 15 | RED="\033[31m" 16 | GREEN="\033[32m" 17 | YELLOW="\033[33m" 18 | BLUE="\033[34m" 19 | MAGENTA="\033[35m" 20 | CYAN="\033[36m" 21 | WHITE="\033[37m" 22 | 23 | NN_ADDRESS=RDeckerSubnU8QVgrhj27apzUvbVK3pnTk 24 | NN_PUBKEY=0249eee7a3ad854f1d22c467b42dc73db94af7ce7837e15bfcf82f195cd5490d76 25 | NN_HASH160=2fedd5f73d46db8db8625eb5816dfb21f94529e2 26 | 27 | FROM_ADDRESS=RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPVMY 28 | FROM_HASH160=29cfc6376255a78451eeb4b129ed8eacffa2feef 29 | FROM_PUBKEY=000000000000000000000000000000000000000000000000000000000000000000 30 | FROM_PRIVKEY=Up1YVLk7uuErCHVQyFCtfinZngmdwfyfc47WCQ8oJxgowEbuo6t4 31 | 32 | SPLIT_VALUE=0.0001 33 | SPLIT_VALUE_SATOSHI=$(jq -n "$SPLIT_VALUE*100000000") 34 | SPLIT_COUNT=50 # do not set split count > 252 (!), it's important 35 | SPLIT_TOTAL=$(jq -n "$SPLIT_VALUE*$SPLIT_COUNT") 36 | SPLIT_TOTAL_SATOSHI=$(jq -n "$SPLIT_VALUE*$SPLIT_COUNT*100000000") 37 | 38 | TXFEE_SATOSHI=1000 39 | 40 | # get listunspent from explorer, assumes komodo daemon is not available at this moment 41 | # (restart for example) or we don't have imported FROM privkey in the wallet. 42 | 43 | curl -s https://kmdexplorer.io/insight-api-komodo/addr/$FROM_ADDRESS/utxo > split_nn.utxos 44 | 45 | utxos=$( $SPLIT_TOTAL and .confirmations > 0)][0]") 47 | if [[ $utxo != "null" ]]; then 48 | txid=$(echo "$utxo" | jq -r .txid) 49 | vout=$(echo "$utxo" | jq -r .vout) 50 | amount=$(echo "$utxo" | jq -r .amount) 51 | satoshis=$(echo "$utxo" | jq -r .satoshis) 52 | scriptPubKey=$(echo "$utxo" | jq -r .scriptPubKey) 53 | 54 | #echo $txid $vout $amount $satoshis 55 | echo "Amount:" $amount "("$satoshis")" 56 | echo "2Split: $SPLIT_TOTAL ($SPLIT_TOTAL_SATOSHI)" 57 | 58 | rev_txid=$(echo $txid | dd conv=swab 2> /dev/null | rev) 59 | vout_hex=$(printf "%08x" $vout | dd conv=swab 2> /dev/null | rev) 60 | rawtx="01000000" # tx version 61 | rawtx=$rawtx"01" # number of inputs (1, as we take one utxo from explorer listunspent) 62 | rawtx=$rawtx$rev_txid$vout_hex"00ffffffff" 63 | # outputs 64 | #if [[ $SPLIT_COUNT -lt 253 ]]; then 65 | if [[ $SPLIT_COUNT -lt 252 ]]; then # 253, but 1 output for "change" and we have 252 66 | 67 | oc=$((SPLIT_COUNT+1)) 68 | outputCount=$(printf "%02x" $oc) 69 | 70 | rawtx=$rawtx$outputCount 71 | for (( i=1; i<=$SPLIT_COUNT; i++ )) 72 | do 73 | value=$(printf "%016x" $SPLIT_VALUE_SATOSHI | dd conv=swab 2> /dev/null | rev) 74 | rawtx=$rawtx$value 75 | rawtx=$rawtx"2321"$NN_PUBKEY"ac" 76 | done 77 | 78 | change=$(jq -n "($satoshis-$SPLIT_TOTAL_SATOSHI)/100000000") 79 | change_satoshis=$(jq -n "$satoshis-$SPLIT_TOTAL_SATOSHI") 80 | echo "Change:" $change "("$change_satoshis")" 81 | value=$(printf "%016x" $change_satoshis | dd conv=swab 2> /dev/null | rev) 82 | rawtx=$rawtx$value 83 | rawtx=$rawtx"1976a914"$FROM_HASH160"88ac" # len OP_DUP OP_HASH160 len hash OP_EQUALVERIFY OP_CHECKSIG 84 | else 85 | # more than 252 outputs not handled now (!) TODO 86 | echo -e $RED"Error!"$RESET" More than 252 outputs not handled now!" 87 | exit 88 | rawtx=$rawtx"00" 89 | fi 90 | 91 | nlocktime=$(printf "%08x" $(date +%s) | dd conv=swab 2> /dev/null | rev) 92 | rawtx=$rawtx$nlocktime 93 | 94 | #echo $rawtx 95 | else 96 | echo -e $RED"Error!"$RESET" Nothing to split ... :(" 97 | fi 98 | 99 | # signrawtransaction hex "[]" "[\"privkey\"]" 100 | 101 | curdir=$(pwd) 102 | curluser=user 103 | curlpass=pass 104 | curlport=7771 105 | signed=$(curl -s --user $curluser:$curlpass --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "signrawtransaction", "params": ["'$rawtx'", [], ["'$FROM_PRIVKEY'"]]}' -H 'content-type: text/plain;' http://127.0.0.1:$curlport/ | jq -r .result.hex) 106 | 107 | echo -e '\n' 108 | echo -e ${YELLOW}'Unsigned TX: '${RESET}$rawtx 109 | echo -e '\n' 110 | echo -e ${YELLOW}'Signed TX: '${RESET}$signed 111 | echo -e '\n' 112 | -------------------------------------------------------------------------------- /split_nn_btc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Split NN script by Decker (c) 2019 4 | 5 | # *** Small how-to: *** 6 | 7 | # This script can be used to fund your notary with SPLIT_COUNT (50) utxos SPLIT_VALUE (0.0001) BTC each, 8 | # same way as in iguana. It will produce unsigned tx, you should CHECK and sign it before broadcast. 9 | # Check is MANDATORY, bcz it can contains round errors. Make sure you have needed funds on FROM_ADDRESS (!). 10 | 11 | # p.s. Use it ONLY if you understand the aftermaths and how it works! 12 | 13 | RESET="\033[0m" 14 | BLACK="\033[30m" 15 | RED="\033[31m" 16 | GREEN="\033[32m" 17 | YELLOW="\033[33m" 18 | BLUE="\033[34m" 19 | MAGENTA="\033[35m" 20 | CYAN="\033[36m" 21 | WHITE="\033[37m" 22 | 23 | NN_ADDRESS=12Rqm2rZCfBzAVAL5CCb7DUaMU2VKfvJFL # fill your NN address here 24 | NN_PUBKEY=0287b551ba26f24b792d24aec94f96a72a6f40142717f290b684cab3904d4e095c # fill your pubkey here 25 | NN_HASH160= 0faacf9bf91ba026e7a79eeae26c3bc70dfce19b # take it from https://cryptofrontline.com/Tools/Upload/tool/address-to-hash 26 | 27 | FROM_ADDRESS=12CANsiKa1vjdwKnu2AGPDgqDCGpEpqCsW # address from funds are taken 28 | FROM_HASH160=0d14876d237dbe8d895ce5caf1fe3dadc6a782e0 # it's HASH160 29 | # FROM_PUBKEY=000000000000000000000000000000000000000000000000000000000000000000 30 | # FROM_PRIVKEY=KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73Nd2Mcv1 31 | 32 | SPLIT_VALUE=0.0001 33 | SPLIT_VALUE_SATOSHI=$(jq -n "$SPLIT_VALUE*100000000") 34 | SPLIT_COUNT=50 # do not set split count > 252 (!), it's important 35 | SPLIT_TOTAL=$(jq -n "$SPLIT_VALUE*$SPLIT_COUNT") 36 | SPLIT_TOTAL_SATOSHI=$(jq -n "$SPLIT_VALUE*$SPLIT_COUNT*100000000") 37 | 38 | TXFEE_SATOSHI_VBYTE=120 # take it from https://btc.com/stats/unconfirmed-tx 39 | 40 | curl -s https://blockchain.info/unspent?active=$FROM_ADDRESS > split_nn.utxos 41 | 42 | utxos=$( $SPLIT_TOTAL and .confirmations > 0)][0]") 44 | utxo=$(echo "$utxos" | jq "[.unspent_outputs[] | select (.value > $SPLIT_TOTAL_SATOSHI and .confirmations > 0)][0]") 45 | 46 | if [[ $utxo != "null" ]]; then 47 | txid=$(echo "$utxo" | jq -r .tx_hash_big_endian) 48 | vout=$(echo "$utxo" | jq -r .tx_output_n) 49 | #amount=$(echo "$utxo" | jq -r .amount) 50 | satoshis=$(echo "$utxo" | jq -r .value) 51 | amount=$(jq -n "$satoshis/100000000") 52 | scriptPubKey=$(echo "$utxo" | jq -r .script) 53 | 54 | #echo $txid $vout $amount $satoshis 55 | echo "Amount:" $amount "("$satoshis")" 56 | echo "2Split: $SPLIT_TOTAL ($SPLIT_TOTAL_SATOSHI)" 57 | 58 | rev_txid=$(echo $txid | dd conv=swab 2> /dev/null | rev) 59 | vout_hex=$(printf "%08x" $vout | dd conv=swab 2> /dev/null | rev) 60 | rawtx="01000000" # tx version 61 | rawtx=$rawtx"01" # number of inputs (1, as we take one utxo from explorer listunspent) 62 | rawtx=$rawtx$rev_txid$vout_hex"00ffffffff" 63 | # outputs 64 | #if [[ $SPLIT_COUNT -lt 253 ]]; then 65 | if [[ $SPLIT_COUNT -lt 252 ]]; then # 253, but 1 output for "change" and we have 252 66 | 67 | oc=$((SPLIT_COUNT+1)) 68 | outputCount=$(printf "%02x" $oc) 69 | 70 | rawtx=$rawtx$outputCount 71 | 72 | rawtxsize=$(($(echo -n $rawtx | wc -m) / 2)) 73 | rawtxsize=$((rawtxsize + SPLIT_COUNT * (8 + 1 + 35))) # outputs size 74 | rawtxsize=$((rawtxsize + 8 + 1 + 25)) # change size 75 | rawtxsize=$((rawtxsize + 4)) # nLockTime 76 | echo Size: $rawtxsize 77 | 78 | for (( i=1; i<=$SPLIT_COUNT; i++ )) 79 | do 80 | value=$(printf "%016x" $SPLIT_VALUE_SATOSHI | dd conv=swab 2> /dev/null | rev) 81 | rawtx=$rawtx$value 82 | rawtx=$rawtx"2321"$NN_PUBKEY"ac" 83 | done 84 | 85 | change_satoshis=$(jq -n "$satoshis-$SPLIT_TOTAL_SATOSHI-$rawtxsize*$TXFEE_SATOSHI_VBYTE") 86 | change=$(jq -n "($change_satoshis)/100000000") 87 | 88 | echo "Change:" $change "("$change_satoshis")" 89 | txfee=$(jq -n "($amount - $SPLIT_TOTAL - $change)") 90 | txfee=$(awk -v txfee="$txfee" 'BEGIN { printf("%.8f\n", txfee) }' /dev/null | rev) 96 | rawtx=$rawtx$value 97 | rawtx=$rawtx"1976a914"$FROM_HASH160"88ac" # len OP_DUP OP_HASH160 len hash OP_EQUALVERIFY OP_CHECKSIG 98 | else 99 | # more than 252 outputs not handled now (!) TODO 100 | echo -e $RED"Error!"$RESET" More than 252 outputs not handled now!" 101 | exit 102 | rawtx=$rawtx"00" 103 | fi 104 | 105 | #nlocktime=$(printf "%08x" $(date +%s) | dd conv=swab 2> /dev/null | rev) 106 | nlocktime=$(printf "%08x" 0 | dd conv=swab 2> /dev/null | rev) # for BTC nLockTime is 0 (!) 107 | rawtx=$rawtx$nlocktime 108 | 109 | #echo $rawtx 110 | else 111 | echo -e $RED"Error!"$RESET" Nothing to split ... :(" 112 | fi 113 | 114 | # signrawtransaction hex "[]" "[\"privkey\"]" 115 | 116 | curdir=$(pwd) 117 | curluser=user 118 | curlpass=pass 119 | curlport=8332 120 | 121 | #sign is turned off, you should sign tx manually 122 | #signed=$(curl -s --user $curluser:$curlpass --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "signrawtransaction", "params": ["'$rawtx'", [], ["'$FROM_PRIVKEY'"]]}' -H 'content-type: text/plain;' http://127.0.0.1:$curlport/ | jq -r .result.hex) 123 | 124 | echo -e '\n' 125 | echo -e ${YELLOW}'Unsigned TX: '${RESET}$rawtx 126 | echo -e '\n' 127 | 128 | #echo -e ${YELLOW}'Signed TX: '${RESET}$signed 129 | #echo -e '\n' 130 | -------------------------------------------------------------------------------- /split_nn_sapling.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Split NN script by Decker (c) 2018 4 | 5 | # *** Small how-to: *** 6 | 7 | # This script can be used to fund your notary with SPLIT_COUNT (50) utxos SPLIT_VALUE (0.0001) KMD each, 8 | # same way as in iguana. You don't need to import any privkeys in your komodo daemon. Funds will get 9 | # from FROM_ADDRESS with given FROM_PRIVKEY. Insight explorer API will used for listunspent and 10 | # komodod for signing transaction. If somebody will able to modify this script to use openssl for signing 11 | # tx instead of komodod - it would be nice. PRs are welcome. 12 | 13 | RESET="\033[0m" 14 | BLACK="\033[30m" 15 | RED="\033[31m" 16 | GREEN="\033[32m" 17 | YELLOW="\033[33m" 18 | BLUE="\033[34m" 19 | MAGENTA="\033[35m" 20 | CYAN="\033[36m" 21 | WHITE="\033[37m" 22 | 23 | NN_ADDRESS=RDeckerSubnU8QVgrhj27apzUvbVK3pnTk 24 | NN_PUBKEY=0249eee7a3ad854f1d22c467b42dc73db94af7ce7837e15bfcf82f195cd5490d76 25 | NN_HASH160=2fedd5f73d46db8db8625eb5816dfb21f94529e2 26 | 27 | FROM_ADDRESS=RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPVMY 28 | FROM_HASH160=29cfc6376255a78451eeb4b129ed8eacffa2feef 29 | FROM_PUBKEY=000000000000000000000000000000000000000000000000000000000000000000 30 | FROM_PRIVKEY=Up1YVLk7uuErCHVQyFCtfinZngmdwfyfc47WCQ8oJxgowEbuo6t4 31 | 32 | SPLIT_VALUE=0.0001 33 | SPLIT_VALUE_SATOSHI=$(jq -n "$SPLIT_VALUE*100000000") 34 | SPLIT_COUNT=50 # do not set split count > 252 (!), it's important 35 | SPLIT_TOTAL=$(jq -n "$SPLIT_VALUE*$SPLIT_COUNT") 36 | SPLIT_TOTAL_SATOSHI=$(jq -n "$SPLIT_VALUE*$SPLIT_COUNT*100000000") 37 | 38 | TXFEE_SATOSHI=1000 39 | 40 | # get listunspent from explorer, assumes komodo daemon is not available at this moment 41 | # (restart for example) or we don't have imported FROM privkey in the wallet. 42 | 43 | curl -s https://kmdexplorer.io/insight-api-komodo/addr/$FROM_ADDRESS/utxo > split_nn.utxos 44 | 45 | utxos=$( $SPLIT_TOTAL and .confirmations > 0)][0]") 47 | if [[ $utxo != "null" ]]; then 48 | txid=$(echo "$utxo" | jq -r .txid) 49 | vout=$(echo "$utxo" | jq -r .vout) 50 | amount=$(echo "$utxo" | jq -r .amount) 51 | satoshis=$(echo "$utxo" | jq -r .satoshis) 52 | scriptPubKey=$(echo "$utxo" | jq -r .scriptPubKey) 53 | 54 | #echo $txid $vout $amount $satoshis 55 | echo "Amount:" $amount "("$satoshis")" 56 | echo "2Split: $SPLIT_TOTAL ($SPLIT_TOTAL_SATOSHI)" 57 | 58 | rev_txid=$(echo $txid | dd conv=swab 2> /dev/null | rev) 59 | vout_hex=$(printf "%08x" $vout | dd conv=swab 2> /dev/null | rev) 60 | rawtx="04000080" # tx header 61 | rawtx=$rawtx"85202f89" # versiongroupid 62 | rawtx=$rawtx"01" # number of inputs (1, as we take one utxo from explorer listunspent) 63 | rawtx=$rawtx$rev_txid$vout_hex"00ffffffff" 64 | # outputs 65 | #if [[ $SPLIT_COUNT -lt 253 ]]; then 66 | if [[ $SPLIT_COUNT -lt 252 ]]; then # 253, but 1 output for "change" and we have 252 67 | 68 | oc=$((SPLIT_COUNT+1)) 69 | outputCount=$(printf "%02x" $oc) 70 | 71 | rawtx=$rawtx$outputCount 72 | for (( i=1; i<=$SPLIT_COUNT; i++ )) 73 | do 74 | value=$(printf "%016x" $SPLIT_VALUE_SATOSHI | dd conv=swab 2> /dev/null | rev) 75 | rawtx=$rawtx$value 76 | rawtx=$rawtx"2321"$NN_PUBKEY"ac" 77 | done 78 | 79 | change=$(jq -n "($satoshis-$SPLIT_TOTAL_SATOSHI)/100000000") 80 | change_satoshis=$(jq -n "$satoshis-$SPLIT_TOTAL_SATOSHI") 81 | echo "Change:" $change "("$change_satoshis")" 82 | value=$(printf "%016x" $change_satoshis | dd conv=swab 2> /dev/null | rev) 83 | rawtx=$rawtx$value 84 | rawtx=$rawtx"1976a914"$FROM_HASH160"88ac" # len OP_DUP OP_HASH160 len hash OP_EQUALVERIFY OP_CHECKSIG 85 | else 86 | # more than 252 outputs not handled now (!) TODO 87 | echo -e $RED"Error!"$RESET" More than 252 outputs not handled now!" 88 | exit 89 | rawtx=$rawtx"00" 90 | fi 91 | 92 | nlocktime=$(printf "%08x" $(date +%s) | dd conv=swab 2> /dev/null | rev) 93 | rawtx=$rawtx$nlocktime 94 | rawtx=$rawtx"000000000000000000000000000000" # sapling end of tx 95 | 96 | #echo $rawtx 97 | else 98 | echo -e $RED"Error!"$RESET" Nothing to split ... :(" 99 | fi 100 | 101 | # signrawtransaction hex "[]" "[\"privkey\"]" 102 | 103 | curdir=$(pwd) 104 | curluser=user 105 | curlpass=pass 106 | curlport=7771 107 | signed=$(curl -s --user $curluser:$curlpass --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "signrawtransaction", "params": ["'$rawtx'", [], ["'$FROM_PRIVKEY'"]]}' -H 'content-type: text/plain;' http://127.0.0.1:$curlport/ | jq -r .result.hex) 108 | 109 | echo -e '\n' 110 | echo -e ${YELLOW}'Unsigned TX: '${RESET}$rawtx 111 | echo -e '\n' 112 | echo -e ${YELLOW}'Signed TX: '${RESET}$signed 113 | echo -e '\n' 114 | -------------------------------------------------------------------------------- /transfer_balance.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | komodo_cli_binary="$HOME/komodo/src/komodo-cli" 3 | readarray -t kmd_coins < <(curl -s https://raw.githubusercontent.com/KomodoPlatform/dPoW/master/iguana/assetchains.json | jq -r '[.[].ac_name] | join("\n")') 4 | # printf '%s\n' "${kmd_coins[@]}" 5 | 6 | source ~/pubkey.txt 7 | WIF= 8 | TO= 9 | 10 | for i in "${kmd_coins[@]}" 11 | do 12 | echo Sending "$i" 13 | ${komodo_cli_binary} -ac_name="$i" importprivkey ${WIF} "" false 14 | BALANCE=$(${komodo_cli_binary} -ac_name="$i" getbalance) 15 | #echo ${komodo_cli_binary} -ac_name="$i" sendtoaddress ${TO} ${BALANCE} "" "" true 16 | ${komodo_cli_binary} -ac_name="$i" z_mergetoaddress '["ANY_TADDR"]' ${TO} 0.001 0 17 | done 18 | 19 | BALANCE=$(${komodo_cli_binary} getbalance) 20 | echo KMD ${BALANCE} -- ${TO} 21 | # ${komodo_cli_binary} sendtoaddress ${TO} ${BALANCE} "" "" true 22 | 23 | ${komodo_cli_binary} z_mergetoaddress '["ANY_TADDR"]' ${TO} 0.001 0 24 | -------------------------------------------------------------------------------- /update-motd.d/98-mymotd: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ## 3 | ## 1. Place this file in: /etc/update-motd.d/98-mymotd 4 | ## 2. Set correct access rights: sudo chmod a+x /etc/update-motd.d/98-mymotd 5 | ## 6 | # 7 | # Text Color Variables http://misc.flogisoft.com/bash/tip_colors_and_formatting 8 | tcLtG="\033[00;37m" # LIGHT GRAY 9 | tcDkG="\033[01;30m" # DARK GRAY 10 | tcLtR="\033[01;31m" # LIGHT RED 11 | tcLtGRN="\033[01;32m" # LIGHT GREEN 12 | tcLtBL="\033[01;34m" # LIGHT BLUE 13 | tcLtP="\033[01;35m" # LIGHT PURPLE 14 | tcLtC="\033[01;36m" # LIGHT CYAN 15 | tcW="\033[01;37m" # WHITE 16 | tcRESET="\033[0m" 17 | tcORANGE="\033[38;5;209m" 18 | # 19 | # Time of day 20 | HOUR=$(date +"%H") 21 | if [ $HOUR -lt 12 -a $HOUR -ge 0 ]; then TIME="morning" 22 | elif [ $HOUR -lt 17 -a $HOUR -ge 12 ]; then TIME="afternoon" 23 | else TIME="evening" 24 | fi 25 | # 26 | # System uptime 27 | uptime=`cat /proc/uptime | cut -f1 -d.` 28 | upDays=$((uptime/60/60/24)) 29 | upHours=$((uptime/60/60%24)) 30 | upMins=$((uptime/60%60)) 31 | # 32 | # System + Memory 33 | SYS_LOADS=`cat /proc/loadavg | awk '{print $1}'` 34 | MEMORY_USED=`free -b | grep Mem | awk '{print $3/$2 * 100.0}'` 35 | SWAP_USED=`free -b | grep Swap | awk '{print $3/$2 * 100.0}'` 36 | NUM_PROCS=`ps aux | wc -l` 37 | IPADDRESS=`hostname --all-ip-addresses` 38 | # 39 | echo $tcRESET "" 40 | echo $tcDkG "=================================================================" 41 | echo $tcLtG " Good $TIME ! $tcORANGE Notary Node" 42 | echo $tcDkG "=================================================================" 43 | echo $tcLtG " - Hostname :$tcW `hostname -f`" 44 | echo $tcLtG " - IP Address :$tcW $IPADDRESS" 45 | echo $tcLtG " - Release :$tcW $(lsb_release -s -d)[$(cat /etc/debian_version)]" 46 | echo $tcLtG " - Kernel : `uname -a | awk '{print $1" "$3" "$12}'`" 47 | echo $tcLtG " - Users : Currently `users | wc -w` user(s) logged on ($USER)" 48 | echo $tcLtG " - Server Time : `date`" 49 | echo $tcLtG " - System load : $SYS_LOADS / $NUM_PROCS processes running" 50 | echo $tcLtG " - Memory used % : $MEMORY_USED" 51 | echo $tcLtG " - Swap used % : $SWAP_USED" 52 | echo $tcLtG " - System uptime : $upDays days $upHours hours $upMins minutes" 53 | echo $tcDkG "=================================================================" 54 | echo $tcRESET "" 55 | # 56 | -------------------------------------------------------------------------------- /z/sha256f.php: -------------------------------------------------------------------------------- 1 | , Arpad Ray 10 | * @link http://php.net/function.hash 11 | * @author revulo 12 | * @require PHP 4.0.0 13 | */ 14 | function php_compat_sha256($str, $raw_output = false, $no_padding = false) 15 | { 16 | $h0 = (int)0x6a09e667; 17 | $h1 = (int)0xbb67ae85; 18 | $h2 = (int)0x3c6ef372; 19 | $h3 = (int)0xa54ff53a; 20 | $h4 = (int)0x510e527f; 21 | $h5 = (int)0x9b05688c; 22 | $h6 = (int)0x1f83d9ab; 23 | $h7 = (int)0x5be0cd19; 24 | 25 | $k = array( 26 | (int)0x428a2f98, (int)0x71374491, (int)0xb5c0fbcf, (int)0xe9b5dba5, 27 | (int)0x3956c25b, (int)0x59f111f1, (int)0x923f82a4, (int)0xab1c5ed5, 28 | (int)0xd807aa98, (int)0x12835b01, (int)0x243185be, (int)0x550c7dc3, 29 | (int)0x72be5d74, (int)0x80deb1fe, (int)0x9bdc06a7, (int)0xc19bf174, 30 | (int)0xe49b69c1, (int)0xefbe4786, (int)0x0fc19dc6, (int)0x240ca1cc, 31 | (int)0x2de92c6f, (int)0x4a7484aa, (int)0x5cb0a9dc, (int)0x76f988da, 32 | (int)0x983e5152, (int)0xa831c66d, (int)0xb00327c8, (int)0xbf597fc7, 33 | (int)0xc6e00bf3, (int)0xd5a79147, (int)0x06ca6351, (int)0x14292967, 34 | (int)0x27b70a85, (int)0x2e1b2138, (int)0x4d2c6dfc, (int)0x53380d13, 35 | (int)0x650a7354, (int)0x766a0abb, (int)0x81c2c92e, (int)0x92722c85, 36 | (int)0xa2bfe8a1, (int)0xa81a664b, (int)0xc24b8b70, (int)0xc76c51a3, 37 | (int)0xd192e819, (int)0xd6990624, (int)0xf40e3585, (int)0x106aa070, 38 | (int)0x19a4c116, (int)0x1e376c08, (int)0x2748774c, (int)0x34b0bcb5, 39 | (int)0x391c0cb3, (int)0x4ed8aa4a, (int)0x5b9cca4f, (int)0x682e6ff3, 40 | (int)0x748f82ee, (int)0x78a5636f, (int)0x84c87814, (int)0x8cc70208, 41 | (int)0x90befffa, (int)0xa4506ceb, (int)0xbef9a3f7, (int)0xc67178f2 42 | ); 43 | 44 | $len = strlen($str); 45 | 46 | /* No padding */ 47 | 48 | if (!$no_padding) { 49 | $str .= "\x80"; 50 | $str .= str_repeat("\0", 63 - ($len + 8) % 64); 51 | $str .= pack('N2', $len >> 29, $len << 3); 52 | } 53 | 54 | for ($i = 0; $i < strlen($str); $i += 64) { 55 | 56 | $w = array(); 57 | for ($j = 0; $j < 16; ++$j) { 58 | $index = $i + $j * 4; 59 | $w[$j] = ord($str[$index]) << 24 60 | | ord($str[$index + 1]) << 16 61 | | ord($str[$index + 2]) << 8 62 | | ord($str[$index + 3]); 63 | } 64 | for ($j = 16; $j < 64; ++$j) { 65 | $s0 = php_compat_sha256_rotr_helper($w[$j - 15], 7) 66 | ^ php_compat_sha256_rotr_helper($w[$j - 15], 18) 67 | ^ php_compat_sha256_shr_helper ($w[$j - 15], 3); 68 | 69 | $s1 = php_compat_sha256_rotr_helper($w[$j - 2], 17) 70 | ^ php_compat_sha256_rotr_helper($w[$j - 2], 19) 71 | ^ php_compat_sha256_shr_helper ($w[$j - 2], 10); 72 | 73 | $w[$j] = php_compat_sha256_add32_helper( 74 | php_compat_sha256_add32_helper( 75 | php_compat_sha256_add32_helper($w[$j - 16], $s0), $w[$j - 7]), $s1); 76 | } 77 | 78 | $a = $h0; 79 | $b = $h1; 80 | $c = $h2; 81 | $d = $h3; 82 | $e = $h4; 83 | $f = $h5; 84 | $g = $h6; 85 | $h = $h7; 86 | 87 | for ($j = 0; $j < 64; ++$j) { 88 | $s1 = php_compat_sha256_rotr_helper($e, 6) 89 | ^ php_compat_sha256_rotr_helper($e, 11) 90 | ^ php_compat_sha256_rotr_helper($e, 25); 91 | 92 | $ch = ($e & $f) ^ (~$e & $g); 93 | 94 | $s0 = php_compat_sha256_rotr_helper($a, 2) 95 | ^ php_compat_sha256_rotr_helper($a, 13) 96 | ^ php_compat_sha256_rotr_helper($a, 22); 97 | 98 | $maj = ($a & $b) ^ ($a & $c) ^ ($b & $c); 99 | 100 | $t1 = php_compat_sha256_add32_helper( 101 | php_compat_sha256_add32_helper( 102 | php_compat_sha256_add32_helper( 103 | php_compat_sha256_add32_helper($h, $s1), $ch), $k[$j]), $w[$j]); 104 | 105 | $t2 = php_compat_sha256_add32_helper($s0, $maj); 106 | 107 | $h = $g; 108 | $g = $f; 109 | $f = $e; 110 | $e = php_compat_sha256_add32_helper($d, $t1); 111 | $d = $c; 112 | $c = $b; 113 | $b = $a; 114 | $a = php_compat_sha256_add32_helper($t1, $t2); 115 | } 116 | 117 | $h0 = php_compat_sha256_add32_helper($h0, $a); 118 | $h1 = php_compat_sha256_add32_helper($h1, $b); 119 | $h2 = php_compat_sha256_add32_helper($h2, $c); 120 | $h3 = php_compat_sha256_add32_helper($h3, $d); 121 | $h4 = php_compat_sha256_add32_helper($h4, $e); 122 | $h5 = php_compat_sha256_add32_helper($h5, $f); 123 | $h6 = php_compat_sha256_add32_helper($h6, $g); 124 | $h7 = php_compat_sha256_add32_helper($h7, $h); 125 | } 126 | 127 | $h0 &= (int)0xffffffff; 128 | $h1 &= (int)0xffffffff; 129 | $h2 &= (int)0xffffffff; 130 | $h3 &= (int)0xffffffff; 131 | $h4 &= (int)0xffffffff; 132 | $h5 &= (int)0xffffffff; 133 | $h6 &= (int)0xffffffff; 134 | $h7 &= (int)0xffffffff; 135 | 136 | $hash = sprintf('%08x%08x%08x%08x%08x%08x%08x%08x', $h0, $h1, $h2, $h3, $h4, $h5, $h6, $h7); 137 | 138 | if ($raw_output) { 139 | return pack('H*', $hash); 140 | } else { 141 | return $hash; 142 | } 143 | } 144 | 145 | function php_compat_sha256_add32_helper($x, $y) 146 | { 147 | $lsw = ($x & 0xffff) + ($y & 0xffff); 148 | $msw = ($x >> 16) + ($y >> 16) + ($lsw >> 16); 149 | return ($msw << 16) | ($lsw & 0xffff); 150 | } 151 | 152 | function php_compat_sha256_shr_helper($x, $n) 153 | { 154 | return ($x >> $n) & (0x7fffffff >> ($n - 1)); 155 | } 156 | 157 | function php_compat_sha256_rotr_helper($x, $n) 158 | { 159 | return ($x << (32 - $n)) | ($x >> $n) & (0x7fffffff >> ($n - 1)); 160 | } -------------------------------------------------------------------------------- /z/z.txt: -------------------------------------------------------------------------------- 1 | z_getnewaddress 2 | zc8baYtSaiBaBkDmRQprom8WuaHJJmh246EAYj9jX2p1Zt9riNqZQozJV5sFg9JFjDYhh4cSJ2ycnFa1qeBcCdLhTwZWYXM 3 | z_exportkey zc8baYtSaiBaBkDmRQprom8WuaHJJmh246EAYj9jX2p1Zt9riNqZQozJV5sFg9JFjDYhh4cSJ2ycnFa1qeBcCdLhTwZWYXM 4 | SKxod8tRJtTY9n2HSYyjJ1XAhrF2cSonDEBBWTs9vQAHLD5ZoSsF 5 | z_validateaddress zc8baYtSaiBaBkDmRQprom8WuaHJJmh246EAYj9jX2p1Zt9riNqZQozJV5sFg9JFjDYhh4cSJ2ycnFa1qeBcCdLhTwZWYXM 6 | 7 | { 8 | "isvalid": true, 9 | "address": "zc8baYtSaiBaBkDmRQprom8WuaHJJmh246EAYj9jX2p1Zt9riNqZQozJV5sFg9JFjDYhh4cSJ2ycnFa1qeBcCdLhTwZWYXM", 10 | "payingkey": "c94361c9bcc4eae2dbb1de0d6e727e57ee36bbc6ae467579f60ff0112b46d502", 11 | "transmissionkey": "3867db0c6a6d95d50ae22611c253ca9fd1ca66951d040961dfbbaa8b9fa6afb7", 12 | "ismine": true 13 | } 14 | 15 | z_exportviewingkey zc8baYtSaiBaBkDmRQprom8WuaHJJmh246EAYj9jX2p1Zt9riNqZQozJV5sFg9JFjDYhh4cSJ2ycnFa1qeBcCdLhTwZWYXM 16 | NVsLixb5o89RjwYC2o9JfoBTdWUR2ACHzGVv4FLYGEQyUpWuRTDoMvQxvNimDKwdSFcYwnABKpPx4xZEaN7e8A6FxFD1 17 | 02d5462b11f00ff6797546aec6bb36ee577e726e0ddeb1dbe2eac4bcc96143c9 f8edd872f0cd4fe235c6f56199f1a0d28c408d6992486603d0afcb3514c67955 AB38CB08 18 | 19 | // guarantees the first two characters, when base58 encoded, are "zc" 20 | base58Prefixes[ZCPAYMENT_ADDRRESS] = {22,154}; 21 | // guarantees the first two characters, when base58 encoded, are "SK" 22 | base58Prefixes[ZCSPENDING_KEY] = {171,54}; 23 | 24 | 25 | zc8baYtSaiBaBkDmRQprom8WuaHJJmh246EAYj9jX2p1Zt9riNqZQozJV5sFg9JFjDYhh4cSJ2ycnFa1qeBcCdLhTwZWYXM 26 | 169A 02D5462B11F00FF6797546AEC6BB36EE577E726E0DDEB1DBE2EAC4BCC96143C9B7AFA69F8BAABBDF6109041D9566CAD19FCA53C21126E20AD5956D6A0CDB6738 E4EACC04 27 | 28 | 29 | 169a - {22,154} - network bytes 30 | 02d5462b11f00ff6797546aec6bb36ee577e726e0ddeb1dbe2eac4bcc96143c9b7afa69f8baabbdf6109041d9566cad19fca53c21126e20ad5956d6a0cdb6738 - 64 bytes 31 | e4eacc04 - first four bytes of sha256 twice of (169a02d5462b11f00ff6797546aec6bb36ee577e726e0ddeb1dbe2eac4bcc96143c9b7afa69f8baabbdf6109041d9566cad19fca53c21126e20ad5956d6a0cdb6738) 32 | 33 | 169a - 22,154 34 | 35 | SKxod8tRJtTY9n2HSYyjJ1XAhrF2cSonDEBBWTs9vQAHLD5ZoSsF 36 | AB36 017CF7A3970E85D40261EBC8D1573FA8C43EF2238B5F935ACDA1EDF0BB41E08F A6575016 37 | 38 | AB36 - {171,54} 39 | 017CF7A3970E85D40261EBC8D1573FA8C43EF2238B5F935ACDA1EDF0BB41E08F - (1) ??????????? privkey? 40 | A6575016 - first four bytes of sha256 twice of (ab36 017cf7a3970e85d40261ebc8d1573fa8c43ef2238b5f935acda1edf0bb41e08f) 41 | 42 | 43 | 017cf7a3970e85d40261ebc8d1573fa8c43ef2238b5f935acda1edf0bb41e08f - what's this? privkey? 44 | 02d5462b11f00ff6797546aec6bb36ee577e726e0ddeb1dbe2eac4bcc96143c9b7afa69f8baabbdf6109041d9566cad19fca53c21126e20ad5956d6a0cdb6738 - it's 64 bytes (not a pubkey), what's this? 45 | 46 | payingkey : transmissionkey = 02d5462b11f00ff6797546aec6bb36ee577e726e0ddeb1dbe2eac4bcc96143c9 b7afa69f8baabbdf6109041d9566cad19fca53c21126e20ad5956d6a0cdb6738 - 64 bytes from z-address ... 47 | 02d5462b11f00ff6797546aec6bb36ee577e726e0ddeb1dbe2eac4bcc96143c9 f8edd872f0cd4fe235c6f56199f1a0d28c408d6992486603d0afcb3514c67955 - viewing key 48 | 49 | privkey - 017CF7A3970E85D40261EBC8D1573FA8C43EF2238B5F935ACDA1EDF0BB41E08F 50 | pubkey - 04 CD663D364766390E1BF36E32D62A29B609E6695DEA1D955D72A332E34ADE91E7 9F8A727B9FDFBE39DB64F6AC43F06C605579F1BFF39186435945F25EEAE6D781 51 | 52 | z_validateaddress zc8baYtSaiBaBkDmRQprom8WuaHJJmh246EAYj9jX2p1Zt9riNqZQozJV5sFg9JFjDYhh4cSJ2ycnFa1qeBcCdLhTwZWYXM 53 | 54 | { 55 | "isvalid": true, 56 | "address": "zc8baYtSaiBaBkDmRQprom8WuaHJJmh246EAYj9jX2p1Zt9riNqZQozJV5sFg9JFjDYhh4cSJ2ycnFa1qeBcCdLhTwZWYXM", 57 | "payingkey": "c94361c9bcc4eae2dbb1de0d6e727e57ee36bbc6ae467579f60ff0112b46d502", 58 | "transmissionkey": "3867db0c6a6d95d50ae22611c253ca9fd1ca66951d040961dfbbaa8b9fa6afb7", 59 | "ismine": true 60 | } 61 | 62 | Privkey: 017cf7a3970e85d40261ebc8d1573fa8c43ef2238b5f935acda1edf0bb41e08f 63 | 1. privkey[0] |= 0xc0, privkey[32] = 0 64 | c17cf7a3970e85d40261ebc8d1573fa8c43ef2238b5f935acda1edf0bb41e08f0000000000000000000000000000000000000000000000000000000000000000 65 | -- -- 66 | 67 | 2. After SHA256 (FinalizeNoPadding): 68 | 69 | ``` CSHA256 hasher; 70 | hasher.Write(blob, 64); 71 | hasher.FinalizeNoPadding(res.begin()); 72 | ``` 73 | 74 | 02d5462b11f00ff6797546aec6bb36ee577e726e0ddeb1dbe2eac4bcc96143c9 75 | 76 | This is paying key. 77 | 78 | 3. buf = c17cf7a3970e85d40261ebc8d1573fa8c43ef2238b5f935acda1edf0bb41e08f0100000000000000000000000000000000000000000000000000000000000000 79 | -- -- 80 | 4. After SHA256: 81 | faedd872f0cd4fe235c6f56199f1a0d28c408d6992486603d0afcb3514c679d5 82 | 83 | 4. transmissionkey = 84 | 85 | curve25519.ScalarBaseMult(faedd872f0cd4fe235c6f56199f1a0d28c408d6992486603d0afcb3514c679d5, 0000000000000000000000000000000000000000000000000000000000000000) 86 | = b7afa69f8baabbdf6109041d9566cad19fca53c21126e20ad5956d6a0cdb6738 87 | 88 | // basePoint is the x coordinate of the generator of the curve. 89 | var basePoint = [32]byte{9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} 90 | 91 | // ScalarMult sets dst to the product in*base where dst and base are the x 92 | // coordinates of group points and all values are in little-endian form. 93 | func ScalarMult(dst, in, base *[32]byte) { 94 | scalarMult(dst, in, base) 95 | } 96 | 97 | // ScalarBaseMult sets dst to the product in*base where dst and base are the x 98 | // coordinates of group points, base is the standard generator and all values 99 | // are in little-endian form. 100 | func ScalarBaseMult(dst, in *[32]byte) { 101 | ScalarMult(dst, in, &basePoint) 102 | } 103 | -------------------------------------------------------------------------------- /z/zkey.php: -------------------------------------------------------------------------------- 1 | $element) 27 | { 28 | $reversedTable[$element] = $key; 29 | } 30 | 31 | if(isset($reversedTable[$char])) 32 | return $reversedTable[$char]; 33 | else 34 | return null; 35 | } 36 | 37 | if(isset($table[$char])) 38 | return $table[$char]; 39 | else 40 | return null; 41 | } 42 | 43 | function base58_encode($data, $littleEndian = true) 44 | { 45 | $res = ''; 46 | $dataIntVal = gmp_init($data, 16); 47 | while(gmp_cmp($dataIntVal, gmp_init(0, 10)) > 0) 48 | { 49 | $qr = gmp_div_qr($dataIntVal, gmp_init(58, 10)); 50 | $dataIntVal = $qr[0]; 51 | $reminder = gmp_strval($qr[1]); 52 | if(!base58_permutation($reminder)) 53 | { 54 | throw new \Exception('Something went wrong during base58 encoding'); 55 | } 56 | $res .= base58_permutation($reminder); 57 | } 58 | 59 | //get number of leading zeros 60 | $leading = ''; 61 | $i = 0; 62 | while(substr($data, $i, 1) === '0') 63 | { 64 | if($i!== 0 && $i%2) 65 | { 66 | $leading .= '1'; 67 | } 68 | $i++; 69 | } 70 | 71 | if($littleEndian) 72 | return strrev($res . $leading); 73 | else 74 | return $res.$leading; 75 | } 76 | 77 | // set your privkey here (!!!) 78 | 79 | $privkey = "017cf7a3970e85d40261ebc8d1573fa8c43ef2238b5f935acda1edf0bb41e08f"; 80 | 81 | 82 | //echo " passphrase : `" . $passphrase . "`\n"; 83 | echo " privkey : " . $privkey . "\n"; 84 | $s = $privkey."0000000000000000000000000000000000000000000000000000000000000000"; 85 | $s = pack("H*",$s); 86 | 87 | /* here we should read ZCash sources in src/zcash/ 88 | 89 | Address.hpp 90 | Address.cpp 91 | prf.cpp 92 | prf.h 93 | 94 | */ 95 | 96 | $s[0] = Chr(Ord($s[0]) | 0xc0); $s[32] = Chr(0); 97 | 98 | $payingkey = php_compat_sha256($s,false,true); 99 | echo " payingkey : " . bin2hex(strrev(pack("H*",$payingkey))) . "\n"; 100 | 101 | $s = $privkey."0000000000000000000000000000000000000000000000000000000000000000"; 102 | $s = pack("H*",$s); 103 | $s[0] = Chr(Ord($s[0]) | 0xc0); $s[32] = Chr(1); 104 | 105 | $b = php_compat_sha256($s, false, true); 106 | 107 | $Curve25519 = new Curve25519(); 108 | $transmissionkey = $Curve25519->publicKey(pack("H*",$b)); 109 | $transmissionkey = bin2hex($transmissionkey); 110 | 111 | echo "transmissionkey : " . bin2hex(strrev(pack("H*",$transmissionkey))) . "\n"; 112 | 113 | /* 114 | // viewing key (need to test) 115 | 116 | $viewingkey = pack("H*", "a8abd3" . $payingkey . $b); 117 | $viewingkey[32] = Chr(Ord($viewingkey[32]) & 248); 118 | $viewingkey[63] = Chr(Ord($viewingkey[63]) & 127); 119 | $viewingkey[63] = Chr(Ord($viewingkey[63]) | 64); 120 | $viewingkey = bin2hex($viewingkey); 121 | $viewingkey .= substr(php_compat_sha256(php_compat_sha256(pack("H*",$viewingkey), true), false), 0, 8); // checksum 122 | echo " viewing key : " . base58_encode($viewingkey) . "\n"; 123 | */ 124 | 125 | $address = "169a" . $payingkey . $transmissionkey; 126 | $address .= substr(php_compat_sha256(php_compat_sha256(pack("H*",$address), true), false), 0, 8); // checksum 127 | 128 | $wif = "ab36" . $privkey; 129 | $wif .= substr(php_compat_sha256(php_compat_sha256(pack("H*",$wif), true), false), 0, 8); // checksum 130 | 131 | echo "Address: " . base58_encode($address) . "\n"; 132 | echo " zWIF: " . base58_encode($wif) . "\n"; 133 | 134 | ?> -------------------------------------------------------------------------------- /zip-0243-test-vector-3.js: -------------------------------------------------------------------------------- 1 | /* Node JS Example how to calculate sapling sighash. 2 | 3 | Deps: bitgo-utxo-lib 4 | 5 | In this small example we will calculate sighash for Test Vector 3 - https://github.com/zcash/zips/blob/master/zip-0243.rst#test-vector-3 6 | from zip-0243 : 7 | 8 | Preimage: 9 | 10 | bitgo:utxolib:transaction 0400008085202f89fae31b8dec7b0b77e2c8d6b6eb0e7e4e55abc6574c26dd44464d9408a8e33f116c80d37f12d89b6f17ff198723e7db1247c4811d1a695d74d930f99e98418790d2b04118469b7810a0d1cc59568320aad25a84f407ecac40b4f605a4e686845400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000029b0040048b00400000000000000000001000000a8c685478265f4c14dada651969c45a65e1aeb8cd6791f2f5bb6a1d9952104d9010000001976a914507173527b4c3318a2aecd793bf1cfed705950cf88ac80f0fa0200000000feffffff +0ms 11 | sighash: f3148f80dfab5e573d5edfe7a850f5fd39234f80b5429d3a57edcc11e34c585b 12 | 13 | Also, here is 2 examples, how to import transaction from hex and how to create it manually. 14 | 15 | */ 16 | 17 | // This shows how to denug NodeJS applications: 18 | // https://stackoverflow.com/questions/26112075/express-debug-module-not-working 19 | // https://developer.ibm.com/node/2016/10/12/the-node-js-debug-module-advanced-usage/ 20 | 21 | //process.env['DEBUG'] = 'decker:server,bitgo:utxolib:txbuilder'; 22 | //process.env['DEBUG'] = 'decker:*,bitgo:*'; 23 | process.env['DEBUG'] = '*'; 24 | var debug = require('debug')('decker:server'); 25 | 26 | debug('Nice brain exercise :)') 27 | 28 | // https://github.com/zcash/zips/blob/master/zip-0243.rst - Test Vector 3 29 | // https://explorer.testnet.z.cash/tx/97d8814886d07fc12bbac90c089a10f90906cbb53402ee26e576ef99276c492d 30 | // https://explorer.testnet.z.cash/api/tx/97d8814886d07fc12bbac90c089a10f90906cbb53402ee26e576ef99276c492d 31 | 32 | const bitcoinZcashSapling = require('bitgo-utxo-lib'); 33 | const rawtx = "0400008085202f8901a8c685478265f4c14dada651969c45a65e1aeb8cd6791f2f5bb6a1d9952104d9010000006b483045022100a61e5d557568c2ddc1d9b03a7173c6ce7c996c4daecab007ac8f34bee01e6b9702204d38fdc0bcf2728a69fde78462a10fb45a9baa27873e6a5fc45fb5c76764202a01210365ffea3efa3908918a8b8627724af852fc9b86d7375b103ab0543cf418bcaa7ffeffffff02005a6202000000001976a9148132712c3ff19f3a151234616777420a6d7ef22688ac8b959800000000001976a9145453e4698f02a38abdaa521cd1ff2dee6fac187188ac29b0040048b004000000000000000000000000"; 34 | 35 | /* 36 | 37 | header: 04000080 38 | nVersionGroupId: 85202f89 39 | vin: 01 a8c685478265f4c14dada651969c45a65e1aeb8cd6791f2f5bb6a1d9952104d9 01000000 6b483045022100a61e5d557568c2ddc1d9b03a7173c6ce7c996c4daecab007ac8f34bee01e6b9702204d38fdc0bcf2728a69fde78462a10fb45a9baa27873e6a5fc45fb5c76764202a01210365ffea3efa3908918a8b8627724af852fc9b86d7375b103ab0543cf418bcaa7f feffffff 40 | vout: 02 005a620200000000 1976a9148132712c3ff19f3a151234616777420a6d7ef22688ac // 0.40000000 (40000000) 41 | 8b95980000000000 1976a9145453e4698f02a38abdaa521cd1ff2dee6fac187188ac // 0.09999755 (9999755) 42 | nLockTime: 29b00400 43 | nExpiryHeight: 48b00400 44 | valueBalance: 0000000000000000 45 | vShieldedSpend: 00 46 | vShieldedOutput: 00 47 | vJoinSplit: 00 48 | 49 | Input: 50 | prevout: a8c685478265f4c14dada651969c45a65e1aeb8cd6791f2f5bb6a1d9952104d9 01000000 51 | scriptCode: 1976a914507173527b4c3318a2aecd793bf1cfed705950cf88ac 52 | amount: 80f0fa0200000000 // 0.5 (50000000) 53 | nSequence: feffffff 54 | 55 | */ 56 | 57 | const network = bitcoinZcashSapling.networks.zcashTest; 58 | 59 | // (1) 60 | // tx = new bitcoinZcashSapling.TransactionBuilder.fromTransaction(bitcoinZcashSapling.Transaction.fromHex(rawtx, network), network); 61 | 62 | 63 | // (2) 64 | tx = new bitcoinZcashSapling.TransactionBuilder(network); 65 | 66 | tx.setVersion(4); 67 | tx.setVersionGroupId(bitcoinZcashSapling.Transaction.SAPLING_VERSION_GROUP_ID); 68 | tx.setLockTime(307241); 69 | tx.setExpiryHeight(307272); 70 | 71 | tx.addInput(Buffer.from('a8c685478265f4c14dada651969c45a65e1aeb8cd6791f2f5bb6a1d9952104d9','hex').reverse().toString('hex'), 1, 0xFFFFFFFE); 72 | tx.addOutput(Buffer.from('76a9148132712c3ff19f3a151234616777420a6d7ef22688ac', 'hex'), 40000000); 73 | tx.addOutput(Buffer.from('76a9145453e4698f02a38abdaa521cd1ff2dee6fac187188ac', 'hex'), 9999755); 74 | 75 | console.log(tx.inputs); 76 | 77 | /* 78 | // for (1) 79 | tx.inputs = [ {} ]; // if tx in TransactionBuilder is "copied" from another tx via fromTransaction we should do a small hack to clean inputs array (!), 80 | // if we have just one input tx.inputs = [ {} ], if two - tx.inputs = [ {}, {} ] and and so on. if tx is built "from scratch" - no actions required, 81 | // tx.inputs is already in needed state for sign. 82 | */ 83 | 84 | //debug(tx); 85 | //debug(tx.tx.ins); 86 | //debug(tx.tx.ins.script); 87 | 88 | // cUPJEYuhf9SmBXbu7LbsJUozn6CSsvaKvGb3UZDfyojM4L1abfH1 - cafecafecafecafecafecafecafecafecafecafecafecafecafecafecafecafe 89 | 90 | const keyPair = bitcoinZcashSapling.ECPair.fromWIF("cUPJEYuhf9SmBXbu7LbsJUozn6CSsvaKvGb3UZDfyojM4L1abfH1", network); 91 | console.log(keyPair.getPrivateKeyBuffer().toString('hex')); 92 | console.log(keyPair.getPublicKeyBuffer().toString('hex')); 93 | console.log(keyPair.getAddress()); 94 | console.log(keyPair.toWIF()); 95 | 96 | const hashType = bitcoinZcashSapling.Transaction.SIGHASH_ALL; 97 | 98 | // inIndex, prevOutScript, value, hashType 99 | var sighash = tx.tx.hashForZcashSignature(0, Buffer.from('76a914507173527b4c3318a2aecd793bf1cfed705950cf88ac' , 'hex'), 50000000, hashType).toString('hex'); 100 | console.log("sighash: " + sighash); 101 | 102 | /* Important note: when we actually sign transaction with tx.sign we don't know correct privkey for this 103 | transaction and address tmH3hJCHa9bnVqfx839CupCkyvMY7e8TCUa, so "Calculated ZEC sighash" inside a sign 104 | method will be incorrect. Bcz inside a sign we deternined scriptCode (prevOutScript) as 105 | 106 | prevOutScript = btemplates.pubKeyHash.output.encode(bcrypto.hash160(kpPubKey)) and 107 | kbPubKey in our case equal "02b66ded73ed43c02a7b922eb06908164dca411f98bbe6441a868c8bbf4512124d" and 108 | corresponds our WIF cUPJEYuhf9SmBXbu7LbsJUozn6CSsvaKvGb3UZDfyojM4L1abfH1 and address tmPnse4WukdsLMnZYSs7u1DSZqFSXi3rS6j . 109 | 110 | So, when we call sign method scriptCode (prevOutScript) will be equal "76a9149a6cb99bf5ffd6d4df5ce5832c33440eea4eb1f688ac", 111 | but of course in zip-243 test vector 3 example it should be 1976a914507173527b4c3318a2aecd793bf1cfed705950cf88ac . 112 | 113 | That's why to ensure that sighash in this example is corrent we just call hashForZcashSignature with 114 | needed params above. 115 | 116 | */ 117 | 118 | // vin, keyPair, redeemScript, hashType, witnessValue, witnessScript 119 | tx.sign(0, keyPair, '', hashType, 50000000); 120 | 121 | //const hex = tx.build().toHex(); 122 | const hex = tx.buildIncomplete().toHex(); 123 | console.log(hex); 124 | 125 | 126 | --------------------------------------------------------------------------------