Files
cyphernode/proxy_docker/app/script/confirmation.sh

151 lines
5.1 KiB
Bash

#!/bin/sh
. ./trace.sh
. ./sql.sh
. ./callbacks_job.sh
. ./sendtobitcoinnode.sh
. ./responsetoclient.sh
. ./computefees.sh
. ./blockchainrpc.sh
confirmation_request()
{
# We are receiving a HTTP request, let's find the TXID from it
trace "Entering confirmation_request()..."
local request=${1}
local txid=$(echo "${request}" | cut -d ' ' -f2 | cut -d '/' -f3)
confirmation "${txid}"
return $?
}
confirmation()
{
trace "Entering confirmation()..."
local txid=${1}
local tx_details=$(get_transaction ${txid})
########################################################################################################
# First of all, let's make sure we're working on watched addresses...
local address
local addresseswhere
local addresses=$(echo ${tx_details} | jq ".result.details[].address")
local notfirst=false
local IFS=$'\n'
for address in ${addresses}
do
trace "[confirmation] address=${address}"
if ${notfirst}; then
addresseswhere="${addresseswhere},${address}"
else
addresseswhere="${address}"
notfirst=true
fi
done
local rows=$(sql "SELECT id, address FROM watching WHERE address IN (${addresseswhere}) AND watching")
if [ ${#rows} -eq 0 ]; then
trace "[confirmation] No watched address in this tx!"
return 0
fi
########################################################################################################
local tx=$(sql "SELECT id FROM tx WHERE txid=\"${txid}\"")
local id_inserted
local tx_raw_details=$(get_rawtransaction ${txid})
local tx_nb_conf=$(echo ${tx_details} | jq '.result.confirmations')
# Sometimes raw tx are too long to be passed as paramater, so let's write
# it to a temp file for it to be read by sqlite3 and then delete the file
echo "${tx_raw_details}" > rawtx-${txid}.blob
if [ -z ${tx} ]; then
# TX not found in our DB.
# 0-conf or missed conf (managed or while spending) or spending an unconfirmed
# (note: spending an unconfirmed TX must be avoided or we'll get here spending an unprocessed watching)
# Let's first insert the tx in our DB
local tx_hash=$(echo ${tx_raw_details} | jq '.result.hash')
local tx_ts_firstseen=$(echo ${tx_details} | jq '.result.timereceived')
local tx_amount=$(echo ${tx_details} | jq '.result.amount')
local tx_size=$(echo ${tx_raw_details} | jq '.result.size')
local tx_vsize=$(echo ${tx_raw_details} | jq '.result.vsize')
local tx_replaceable=$(echo ${tx_details} | jq '.result."bip125-replaceable"')
tx_replaceable=$([ ${tx_replaceable} = "yes" ] && echo 1 || echo 0)
local fees=$(compute_fees "${txid}")
trace "[confirmation] fees=${fees}"
# If we missed 0-conf...
local tx_blockhash=$(echo ${tx_details} | jq '.result.blockhash')
local tx_blockheight=$(echo ${tx_details} | jq '.result.blockheight')
local tx_blocktime=$(echo ${tx_details} | jq '.result.blocktime')
sql "INSERT OR IGNORE INTO tx (txid, hash, confirmations, timereceived, fee, size, vsize, is_replaceable, blockhash, blockheight, blocktime, raw_tx) VALUES (\"${txid}\", ${tx_hash}, ${tx_nb_conf}, ${tx_ts_firstseen}, ${fees}, ${tx_size}, ${tx_vsize}, ${tx_replaceable}, ${tx_blockhash}, ${tx_blockheight}, ${tx_blocktime}, readfile('rawtx-${txid}.blob'))"
trace_rc $?
id_inserted=$(sql "SELECT id FROM tx WHERE txid='${txid}'")
trace_rc $?
else
# TX found in our DB.
# 1-conf or spending watched address (in this case, we probably missed conf)
local tx_blockhash=$(echo ${tx_details} | jq '.result.blockhash')
local tx_blockheight=$(echo ${tx_details} | jq '.result.blockheight')
local tx_blocktime=$(echo ${tx_details} | jq '.result.blocktime')
sql "UPDATE tx SET
confirmations=${tx_nb_conf},
blockhash=${tx_blockhash},
blockheight=${tx_blockheight},
blocktime=${tx_blocktime},
raw_tx=readfile('rawtx-${txid}.blob')
WHERE txid=\"${txid}\""
trace_rc $?
id_inserted=${tx}
fi
# Delete the temp file containing the raw tx (see above)
rm rawtx-${txid}.blob
########################################################################################################
# Let's now insert in the join table if not already done
tx=$(sql "SELECT tx_id FROM watching_tx WHERE tx_id=\"${tx}\"")
if [ -z "${tx}" ]; then
trace "[confirmation] For this tx, there's no watching_tx row, let's create"
local watching_id
# If the tx is batched and pays multiple watched addresses, we have to insert
# those additional addresses in watching_tx!
for row in ${rows}
do
watching_id=$(echo "${row}" | cut -d '|' -f1)
address=$(echo "${row}" | cut -d '|' -f2)
tx_vout_n=$(echo ${tx_details} | jq ".result.details[] | select(.address==\"${address}\") | .vout")
tx_vout_amount=$(echo ${tx_details} | jq ".result.details[] | select(.address==\"${address}\") | .amount")
sql "INSERT OR IGNORE INTO watching_tx (watching_id, tx_id, vout, amount) VALUES (${watching_id}, ${id_inserted}, ${tx_vout_n}, ${tx_vout_amount})"
trace_rc $?
done
else
trace "[confirmation] For this tx, there's already watching_tx rows"
fi
########################################################################################################
do_callbacks
echo '{"result":"confirmed"}'
return 0
}
case "${0}" in *confirmation.sh) confirmation $@;; esac