mirror of
https://github.com/alexgo-io/stacks-puppet-node.git
synced 2026-01-12 22:43:42 +08:00
216 lines
5.9 KiB
Bash
216 lines
5.9 KiB
Bash
#!/bin/bash
|
|
# source after $__BIN/start.sh
|
|
|
|
check_chain_quality() {
|
|
local EXPECTED_SORTITION_FRACTION="$1"
|
|
local EXPECTED_FORK_FRACTION="$2"
|
|
local EXPECTED_NUM_BLOCKS="$3"
|
|
|
|
local TOTAL_BLOCKS="$(report "/api/miners" | jq -r ".[].height" | wc -l)"
|
|
local CHAIN_HEIGHT="$(report "/api/miners" | jq -r ".[].height" | head -n 1)"
|
|
|
|
local TOTAL_SORTITIONS="$(report "/api/sortitions" | jq -r '.[].height' | head -n 1)"
|
|
|
|
# find first non-empty sortition
|
|
local LAST_EMPTY_SORTITION="$(report "/api/sortitions" | jq -r '.[] | select(.index_block_hash == "0000000000000000000000000000000000000000000000000000000000000000") | .height' | head -n 1)"
|
|
local FIRST_SORTITION_HEIGHT="$((LAST_EMPTY_SORTITION + 1))"
|
|
|
|
# enough burn blocks had a sortition once mining began
|
|
local EMPTY_SORTITIONS="$(
|
|
report "/api/sortitions" | \
|
|
jq -r '.[] | {height: (.height)|tonumber, index_block_hash: (.index_block_hash)} | select(.height >= '$FIRST_SORTITION_HEIGHT') | select(.index_block_hash == "0000000000000000000000000000000000000000000000000000000000000000")' | \
|
|
wc -l
|
|
)"
|
|
|
|
local SORTITION_FRACTION=$(( (TOTAL_SORTITIONS - EMPTY_SORTITIONS) * 100 / TOTAL_SORTITIONS ))
|
|
if (( $SORTITION_FRACTION < $EXPECTED_SORTITION_FRACTION )); then
|
|
echo >&2 "Resulting chain has $SORTITION_FRACTION percent sortitions"
|
|
return 1
|
|
fi
|
|
|
|
# enough blocks were mined
|
|
if (( $TOTAL_BLOCKS < $EXPECTED_NUM_BLOCKS )); then
|
|
echo >&2 "Resulting chain only has $TOTAL_BLOCKS blocks"
|
|
return 1
|
|
fi
|
|
|
|
local FORK_FRACTION=$((CHAIN_HEIGHT * 100 / TOTAL_BLOCKS))
|
|
|
|
# enough blocks were on the same fork
|
|
if (( $FORK_FRACTION < $EXPECTED_FORK_FRACTION )); then
|
|
echo >&2 "Only $FORK_FRACTION percent of blocks were mined on the same fork"
|
|
return 1
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
# reads tx from stdin
|
|
send_tx() {
|
|
local STACKS_NODE_URL="$1"
|
|
|
|
exec 3>&1
|
|
|
|
read TX
|
|
TXID="$(printf "$TX" | \
|
|
xxd -r -p | \
|
|
curl -s -X POST --data-binary @- -w "%{http_code}" -o >(cat >&3) -H "content-type: application/octet-stream" "$STACKS_NODE_URL"/v2/transactions 2>&1 | ( \
|
|
read HTTP_CODE
|
|
read BODY
|
|
if [ $HTTP_CODE -ne 200 ]; then
|
|
logln "Failed to send to node $STACKS_NODE_URL: server replied $HTTP_CODE. Tx was $TX"
|
|
logln "Error text: $BODY"
|
|
return 1
|
|
fi
|
|
echo "$BODY"
|
|
))"
|
|
|
|
local RC=$?
|
|
if [ $RC -ne 0 ]; then
|
|
return 1
|
|
fi
|
|
|
|
echo "$TXID"
|
|
return 0
|
|
}
|
|
|
|
get_chain_tip() {
|
|
local STACKS_NODE_URL="$1"
|
|
local TIP="$(curl -sf "$STACKS_NODE_URL"/v2/info | jq -r '.stacks_tip' 2>&1)"
|
|
local RC=$?
|
|
|
|
if [ $RC -ne 0 ]; then
|
|
logln "Failed to query chain tip on node $STACKS_NODE_URL: curl exited with code $RC"
|
|
return 1
|
|
fi
|
|
|
|
echo "$TIP"
|
|
return 0
|
|
}
|
|
|
|
get_unconfirmed_chain_tip() {
|
|
local STACKS_NODE_URL="$1"
|
|
local TIP="$(curl -sf "$STACKS_NODE_URL"/v2/info | jq -r '.unanchored_tip' 2>&1)"
|
|
local RC=$?
|
|
|
|
if [ $RC -ne 0 ]; then
|
|
logln "Failed to query unconfirmed chain tip on node $STACKS_NODE_URL: curl exited with code $RC"
|
|
return 1
|
|
fi
|
|
|
|
echo "$TIP"
|
|
return 0
|
|
}
|
|
|
|
get_account_nonce() {
|
|
local STACKS_NODE_URL="$1"
|
|
local ADDR="$2"
|
|
local NONCE="$(curl -sf "$STACKS_NODE_URL"/v2/accounts/"$ADDR""?proof=0" | jq -r '.nonce')"
|
|
local RC=$?
|
|
|
|
if [ $RC -ne 0 ]; then
|
|
logln "Failed to query account $ADDR on node $STACKS_NODE_URL: curl exited with code $RC"
|
|
return 1
|
|
fi
|
|
|
|
echo "$NONCE"
|
|
return 0
|
|
}
|
|
|
|
get_unconfirmed_account_nonce() {
|
|
local STACKS_NODE_URL="$1"
|
|
local ADDR="$2"
|
|
local UNCONFIRMED_TIP="$(get_unconfirmed_chain_tip "$STACKS_NODE_URL")"
|
|
local RC=$?
|
|
if [ $RC -ne 0 ]; then
|
|
logln "Failed to query unconfirmed tip at $STACKS_NODE_URL: curl exited with code $RC"
|
|
return 1
|
|
fi
|
|
|
|
local URL="$STACKS_NODE_URL/v2/accounts/$ADDR?proof=0"
|
|
if [[ "$UNCONFIRMED_TIP" != "0000000000000000000000000000000000000000000000000000000000000000" ]]; then
|
|
# have microblocks applied
|
|
URL="$URL&tip=$UNCONFIRMED_TIP"
|
|
fi
|
|
|
|
local NONCE="$(curl -sf "$URL" | jq -r '.nonce')"
|
|
RC=$?
|
|
|
|
if [ $RC -ne 0 ]; then
|
|
logln "Failed to query account $ADDR on node $STACKS_NODE_URL: curl exited with code $RC"
|
|
return 1
|
|
fi
|
|
|
|
echo "$NONCE"
|
|
return 0
|
|
}
|
|
|
|
wait_for_new_stacks_block() {
|
|
local TIP="$1"
|
|
local STACKS_NODE_URL="$2"
|
|
while true; do
|
|
local CUR_TIP="$(get_chain_tip "$STACKS_NODE_URL")"
|
|
local RC=$?
|
|
if [ $RC -ne 0 ]; then
|
|
return 1
|
|
fi
|
|
|
|
if [[ "$CUR_TIP" != "$TIP" ]]; then
|
|
echo "$CUR_TIP"
|
|
return 0
|
|
fi
|
|
|
|
sleep 5
|
|
done
|
|
}
|
|
|
|
wait_for_confirmations() {
|
|
local CONFS=$1
|
|
local STACKS_NODE_URL="$2"
|
|
local TIP="$(get_chain_tip "$STACKS_NODE_URL")"
|
|
|
|
local CONF=0
|
|
for CONF in $(seq 0 $CONFS); do
|
|
TIP="$(wait_for_new_stacks_block "$TIP" "$STACKS_NODE_URL")"
|
|
RC=$?
|
|
|
|
if [ $RC -ne 0 ]; then
|
|
return 1
|
|
fi
|
|
done
|
|
|
|
echo "$TIP"
|
|
return 0
|
|
}
|
|
|
|
easy_token_transfer() {
|
|
local STACKS_NODE_URL="$1"
|
|
local PRIVKEY="$2"
|
|
local DEST="$3"
|
|
local AMOUNT="$4"
|
|
shift 4
|
|
local OPTS="$@"
|
|
local FEE_RATE=300
|
|
|
|
local ADDR="$(blockstack-cli --testnet addresses "$PRIVKEY" | jq -r '.STX')"
|
|
local NONCE="$(get_unconfirmed_account_nonce "$STACKS_NODE_URL" "$ADDR")"
|
|
local RC=$?
|
|
if [ $RC -ne 0 ] || [ -z "$NONCE" ]; then
|
|
logln "Failed to query unconfirmed account nonce: rc '$RC' nonce '$NONCE'"
|
|
return 1
|
|
fi
|
|
|
|
local MEMO="test $NONCE"
|
|
logln "blockstack-cli --testnet token-transfer '$PRIVKEY' '$FEE_RATE' '$NONCE' '$DEST' '$AMOUNT' '$MEMO' '$OPTS'"
|
|
local TX="$(blockstack-cli --testnet token-transfer "$PRIVKEY" "$FEE_RATE" "$NONCE" "$DEST" "$AMOUNT" "$MEMO" "$OPTS" 2>&1)"
|
|
RC=$?
|
|
if [ $RC -ne 0 ]; then
|
|
logln "Failed to generate tx: blockstack-cli --testnet token-transfer $PRIVKEY $FEE_RATE $NONCE $DEST $AMOUNT \"$MEMO\""
|
|
return 1
|
|
fi
|
|
|
|
logln "Generated tx: $TX"
|
|
printf "$TX"
|
|
return 0
|
|
}
|