mirror of
https://github.com/MAGICGrants/Monero-Dataset-Pipeline.git
synced 2026-01-08 21:17:57 -05:00
171 lines
9.7 KiB
Bash
Executable File
171 lines
9.7 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# Requirements: jq, parallel, xmr2csv, expect, all monero binaries
|
|
# Before running this script first compile and run
|
|
# "./monerod --stagenet" https://github.com/monero-project/monero#compiling-monero-from-source
|
|
# Before running this script first compile xmr2csv
|
|
# also add it to your path https://github.com/moneroexamples/transactions-export
|
|
# Usage: ./collect.sh
|
|
# Usage: This script expects to be placed into a folder that contains wallets. Each wallet should
|
|
# have a Test-Wallet1, Test-Wallet1.keys, and Test-Wallet1.address.txt file.
|
|
# If you use a remote node for the export portion of the script, just note that
|
|
# you will need a local copy of the blockchain for the xmr2csv portion of the script.
|
|
|
|
|
|
# Global variables
|
|
NODE_ADDRESS="127.0.0.1" # testnet.community.rino.io | stagenet.community.rino.io | node.community.rino.io
|
|
NETWORK="stagenet" # Case-sensitive (make all lowercase) (Options: "testnet", "stagenet", or "mainnet")
|
|
num_processors=$(nproc --all)
|
|
|
|
# TODO Pass in a directory
|
|
|
|
#############################################################################
|
|
# You shouldn't need to edit anything below this line #
|
|
#############################################################################
|
|
|
|
if [[ "$NETWORK" == "stagenet" ]];then NODE_RPC_PORT="38081"; LOCAL_RPC_PORT="38088"; fi
|
|
if [[ "$NETWORK" == "testnet" ]];then NODE_RPC_PORT="28081"; LOCAL_RPC_PORT="28088"; fi
|
|
if [[ "$NETWORK" == "mainnet" ]];then NODE_RPC_PORT="18081"; LOCAL_RPC_PORT="18088"; fi
|
|
|
|
parent_dir=$(pwd)
|
|
|
|
# Check to see if the xmr2csv_commands file exists and if it does does ask the user to delete it before preceding
|
|
if [ -f "${parent_dir}/xmr2csv_commands.txt" ];then
|
|
while true; do
|
|
read -p "xmr2csv_commands.txt exists from a previous run. Would you like to proceed with the deletion? " answer
|
|
case $answer in
|
|
[Yy]* ) rm -f "${parent_dir}"/xmr2csv_commands.txt; break;;
|
|
[Nn]* ) exit 1;;
|
|
* ) echo "Please answer yes or no.";;
|
|
esac
|
|
done
|
|
fi
|
|
|
|
while read dir; do # Read in all directories that contain a .keys file in the current directory
|
|
cd "$dir" || exit
|
|
echo "$dir"
|
|
working_dir=$(pwd)
|
|
while read walletAddrFile; do # Loop each .address.txt wallet addr file
|
|
# Gets the name of the current wallet file
|
|
walletName=$(echo $walletAddrFile | cut -f 2 -d "." | cut -f 2 -d "/")
|
|
# Gets the address of the current wallet
|
|
walletAddr=$(cat "$walletAddrFile")
|
|
|
|
if [ "$NETWORK" == "mainnet" ];then
|
|
# Create script to export the current wallet transactions using the monero-wallet-cli
|
|
cat >./Export_Wallet.exp <<EOL
|
|
#!/usr/bin/expect -f
|
|
set timeout -1
|
|
spawn monero-wallet-cli --wallet ./$walletName --daemon-address $NODE_ADDRESS:$NODE_RPC_PORT --log-file /dev/null --trusted-daemon
|
|
match_max 100000
|
|
expect "Wallet password: "
|
|
send -- "\r"
|
|
|
|
expect "wallet*]:*"
|
|
send -- "export_transfers out output=cli_export_$walletAddr.csv\r"
|
|
|
|
expect "wallet*]:*"
|
|
send -- "exit\r"
|
|
|
|
expect eof
|
|
EOL
|
|
else
|
|
# Create script to export the current wallet transactions using the monero-wallet-cli
|
|
cat >./Export_Wallet.exp <<EOL
|
|
#!/usr/bin/expect -f
|
|
set timeout -1
|
|
spawn monero-wallet-cli --$NETWORK --wallet ./$walletName --daemon-address $NODE_ADDRESS:$NODE_RPC_PORT --log-file /dev/null --trusted-daemon
|
|
match_max 100000
|
|
expect "Wallet password: "
|
|
send -- "\r"
|
|
|
|
expect "wallet*]:*"
|
|
send -- "export_transfers out output=cli_export_$walletAddr.csv\r"
|
|
|
|
expect "wallet*]:*"
|
|
send -- "exit\r"
|
|
|
|
expect eof
|
|
EOL
|
|
fi
|
|
|
|
|
|
# Make the script executable and run it
|
|
chmod 777 ./Export_Wallet.exp && ./Export_Wallet.exp
|
|
date
|
|
|
|
# Check if there are any transactions ( if len() = 1 then its just the csv header)
|
|
if [[ $(wc -l < cli_export_"$walletAddr".csv) -gt 1 ]];then
|
|
# Get the minimum block height by sorting the blocks in exported transaction file from the cli
|
|
first_out_block="$(cut -f 1 -d ',' < cli_export_"$walletAddr".csv | awk '{print $1}' | sort -u | head -n 1)"
|
|
min_block_height=$(echo "$first_out_block - 100" | bc)
|
|
|
|
# Kill any monero-wallet-rpc processes that are still lingering
|
|
echo -en '\033[34mKilling monero-wallet-rpc processes... \033[0m';echo;
|
|
procs=$(ps aux | grep "monero-wallet-rpc --rpc-bind-port $LOCAL_RPC_PORT" | grep -v grep | awk '{ print $2 }')
|
|
if [ "$procs" != "" ];then
|
|
echo "$procs" | xargs -I{} kill -9 {}
|
|
fi
|
|
|
|
# Start a new monero-wallet-rpc process for the current wallet
|
|
echo -en '\033[34mStarting a new monero-wallet-rpc process... \033[0m';echo;
|
|
if [ "$NETWORK" == "mainnet" ];then
|
|
monero-wallet-rpc --rpc-bind-port $LOCAL_RPC_PORT --wallet-file "$walletName" --password '' --disable-rpc-login &
|
|
else
|
|
monero-wallet-rpc --rpc-bind-port $LOCAL_RPC_PORT --wallet-file "$walletName" --password '' --$NETWORK --disable-rpc-login &
|
|
fi
|
|
|
|
echo -en '\033[34mWaiting... \033[0m';echo;
|
|
sleep 2 # Give the RPC server time to spin up
|
|
view_key=$(curl http://127.0.0.1:$LOCAL_RPC_PORT/json_rpc -s -d '{"jsonrpc":"2.0","id":"0","method":"query_key","params":{"key_type":"view_key"}}' -H 'Content-Type: application/json' | jq '.result.key' -r)
|
|
spend_key=$(curl http://127.0.0.1:$LOCAL_RPC_PORT/json_rpc -s -d '{"jsonrpc":"2.0","id":"0","method":"query_key","params":{"key_type":"spend_key"}}' -H 'Content-Type: application/json' | jq '.result.key' -r)
|
|
|
|
# Wait until the rpc server is giving a response
|
|
while [ "$view_key" == "" ]; do
|
|
sleep 1
|
|
# Query the monero-wallet-rpc process and collect the view key
|
|
view_key=$(curl http://127.0.0.1:$LOCAL_RPC_PORT/json_rpc -s -d '{"jsonrpc":"2.0","id":"0","method":"query_key","params":{"key_type":"view_key"}}' -H 'Content-Type: application/json' | jq '.result.key' -r)
|
|
done
|
|
while [ "$spend_key" == "" ]; do
|
|
sleep 1
|
|
# Query the monero-wallet-rpc process and collect the spend key
|
|
spend_key=$(curl http://127.0.0.1:$LOCAL_RPC_PORT/json_rpc -s -d '{"jsonrpc":"2.0","id":"0","method":"query_key","params":{"key_type":"spend_key"}}' -H 'Content-Type: application/json' | jq '.result.key' -r)
|
|
done
|
|
|
|
# Kill the wallet rpc wallet
|
|
procs=$(ps aux | grep "monero-wallet-rpc --rpc-bind-port $LOCAL_RPC_PORT" | grep -v grep | awk '{ print $2 }')
|
|
if [ "$procs" != "" ];then
|
|
echo "$procs" | xargs -I{} kill -9 {}
|
|
fi
|
|
echo
|
|
# Save the epoch time of when the scan started since Decoy_Output_Ring_Member_Frequency will depend on it
|
|
date +%s > xmr2csv_start_time_"$walletAddr".csv
|
|
if [ "$NETWORK" == "mainnet" ];then
|
|
# Make xmr2csv command using all the collected values and save the command to a text file to be run in parallel later on
|
|
echo xmr2csv --address "$walletAddr" --viewkey "$view_key" --spendkey "$spend_key" --start-height "$min_block_height" --ring-members --out-csv-file "$working_dir"/xmr_report_"$walletAddr".csv --out-csv-file2 "$working_dir"/xmr_report_ring_members_"$walletAddr".csv --out-csv-file3 "$working_dir"/xmr_report_ring_members_freq_"$walletAddr".csv --out-csv-file4 "$working_dir"/xmr_report_key_images_outputs_"$walletAddr".csv --out-csv-file5 "$working_dir"/xmr_report_outgoing_txs_"$walletAddr".csv >> "$parent_dir"/xmr2csv_commands.txt
|
|
else
|
|
# Make xmr2csv command using all the collected values and save the command to a text file to be run in parallel later on
|
|
echo xmr2csv --address "$walletAddr" --viewkey "$view_key" --spendkey "$spend_key" --"$NETWORK" --start-height "$min_block_height" --ring-members --out-csv-file "$working_dir"/xmr_report_"$walletAddr".csv --out-csv-file2 "$working_dir"/xmr_report_ring_members_"$walletAddr".csv --out-csv-file3 "$working_dir"/xmr_report_ring_members_freq_"$walletAddr".csv --out-csv-file4 "$working_dir"/xmr_report_key_images_outputs_"$walletAddr".csv --out-csv-file5 "$working_dir"/xmr_report_outgoing_txs_"$walletAddr".csv >> "$parent_dir"/xmr2csv_commands.txt
|
|
fi
|
|
|
|
# Echo the commands to stdout
|
|
echo -en "\033[34mXMR2CSV command constructed and saved to ${parent_dir}/xmr2csv_commands.txt\033[0m";echo;
|
|
if [ "$NETWORK" == "mainnet" ];then
|
|
echo -en "\033[34mxmr2csv --address $walletAddr --viewkey $view_key --spendkey $spend_key --start-height $min_block_height --ring-members --out-csv-file $working_dir/xmr_report_$walletAddr.csv --out-csv-file2 $working_dir/xmr_report_ring_members_$walletAddr.csv --out-csv-file3 $working_dir/xmr_report_ring_members_freq_$walletAddr.csv --out-csv-file4 $working_dir/xmr_report_key_images_outputs_$walletAddr.csv --out-csv-file5 $working_dir/xmr_report_outgoing_txs_$walletAddr.csv\033[0m";echo;
|
|
else
|
|
echo -en "\033[34mxmr2csv --address $walletAddr --viewkey $view_key --spendkey $spend_key --$NETWORK --start-height $min_block_height --ring-members --out-csv-file $working_dir/xmr_report_$walletAddr.csv --out-csv-file2 $working_dir/xmr_report_ring_members_$walletAddr.csv --out-csv-file3 $working_dir/xmr_report_ring_members_freq_$walletAddr.csv --out-csv-file4 $working_dir/xmr_report_key_images_outputs_$walletAddr.csv --out-csv-file5 $working_dir/xmr_report_outgoing_txs_$walletAddr.csv\033[0m";echo;
|
|
fi
|
|
|
|
fi # End error check
|
|
|
|
done < <(find ./ -type f -name "*.address.txt" | sort -u) # Find text files in each wallet directory
|
|
cd - || exit
|
|
# Find wallet directories that contain a .keys file and only get the parent dirs
|
|
done < <(find . -mindepth 2 -type f -name '*.keys' | sed -r 's|/[^/]+$||' | sort -u )
|
|
|
|
echo;echo;echo;
|
|
echo -en '\033[34mStarting multiprocessing of xmr2csv exports... \033[0m';echo;
|
|
# https://adamtheautomator.com/how-to-speed-up-bash-scripts-with-multithreading-and-gnu-parallel/
|
|
# Opne the file with all the commands and start the multiprocessing
|
|
cat "$parent_dir"/xmr2csv_commands.txt | parallel --bar --jobs "$num_processors" {}
|