Skip to content

Commit a858b38

Browse files
committed
Update 2025-07 - Enhanced Treasury Withdrawal Security
- Scripts 24a (generate vote) and 24c (query votes) are now displaying the public key of included author signatures for further verification - Scripts 24a (generate vote) and 24c (query votes) are now doing a check on the special fields `Intersect` inserts into there TreasuryWithdrawals to improve security and find scams. The special fields are within `.body.onChain` of the metadata file. - Scripts 24a (generate vote) and 24b (query votes) is now showing all withdrawal addresses in TreasuryWithdrawal actions that contains multiple payout destinations - Script 25b (register action) now also outputs the CIP-129 governance action bech version in addition to the legacy format. - This update includes cardano-signer 1.26.0
1 parent c218294 commit a858b38

File tree

9 files changed

+126
-79
lines changed

9 files changed

+126
-79
lines changed

cardano/mainnet/00_common.sh

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ minCardanoSignerVersion="1.24.3" #minimum version for the cardano-signer binary
334334
minCatalystToolboxVersion="0.5.0" #minimum version for the catalyst-toolbox binary
335335

336336
#Defaults - Variables and Constants
337-
defEra="" #Era for non era related cardano-cli commands
337+
defEra="latest" #Era for non era related cardano-cli commands
338338
defTTL=100000 #Default seconds for transactions to be valid
339339
addrTypePayment="payment"
340340
addrTypeStake="stake"
@@ -1273,7 +1273,6 @@ IFS='+' read -ra asset_entry <<< "${2}" #split the tx-out string into address, l
12731273
#9+10=conway, 7+8=babbage, 5+6=alonzo, 4=mary, 3=allegra, 2=shelley, 0+1=byron
12741274
local protocolVersionMajor=$(jq -r ".protocolVersion.major | select (.!=null)" <<< ${protocolParam})
12751275

1276-
12771276
### switch the method of the minOutUTXO calculation depending on the current era, starting with protocolVersionMajor>=7 (babbage)
12781277
if [[ ${protocolVersionMajor} -ge 7 ]]; then #7+8=Babbage, 9+10=Conway ..., new since babbage: CIP-0055 -> minOutUTXO depends on the cbor bytes length
12791278

@@ -1423,6 +1422,10 @@ fi
14231422
#preload it with the minUTXOValue from the parameters, will be overwritten at the end if costs are higher
14241423
local minOutUTXO=${minUTXOValue}
14251424

1425+
1426+
1427+
1428+
14261429
if [[ ${#asset_entry[@]} -gt 2 ]]; then #contains assets, do calculations. otherwise leave it at the default value
14271430
local idx=2
14281431
local pidCollector="" #holds the list of individual policyIDs
@@ -1722,19 +1725,24 @@ queryLight_committeeState() { #for filtering, ${1} = committeeHASH
17221725
committeeHashArray=$(jq -r "[ .[0].members[] | select( .cc_cold_hex == \"${committeeHASH}\" or .cc_hot_hex == \"${committeeHASH}\") ]" 2> /dev/null <<< "${jsonJSON}");
17231726
else
17241727
committeeHashArray=$(jq -r "[ .[0].members[] ]" 2> /dev/null <<< "${jsonJSON}");
1725-
fi
1728+
fi
17261729

17271730
#Get the quorum values
17281731
local quorum_numerator; local quorum_denominator; local quorum;
17291732
{ read quorum_numerator; read quorum_denominator; } <<< $(jq -r ".[0].quorum_numerator // \"null\", .[0].quorum_denominator // \"null\"" <<< "${jsonJSON}" 2> /dev/null)
1730-
if [[ "${quorum_numerator}" == "null" || "${quorum_denominator}" == "null" ]]; then echo -e "Query via Koios-API (${koiosAPI}) failed, missin quorum parameters."; exit 1; fi;
1731-
quorum=$(bc <<< "scale=2; ${quorum_numerator}/${quorum_denominator}");
1733+
1734+
#Check if we are in normal state or in NoConfidence state
1735+
if [[ "${quorum_numerator}" == "null" || "${quorum_denominator}" == "null" ]]; then
1736+
quorum=null; #We are in the NoConfidence state
1737+
else
1738+
quorum=$(bc <<< "scale=2; ${quorum_numerator}/${quorum_denominator}"); #We are in a normal state, convert the numerator/denominator into a decimal number
1739+
fi
17321740

17331741
#Generate the same output like the cli does. First step, generate the core structure. This also converts the quorum .xx value to 0.xx
1734-
jsonRet=$(jq -r <<< "{ \"epoch\": $(get_currentEpoch), \"threshold\": ${quorum} }")
1742+
jsonRet=$(jq -r <<< "{ \"epoch\": $(get_currentEpoch), \"threshold\": ${quorum}, \"committee\": {} }")
17351743
17361744
#convert all committee hash entries to the correct format depending on key/script hashes
1737-
committeeEntryCnt=$(jq -r "length" <<< ${committeeHashArray})
1745+
committeeEntryCnt=$(( $(jq -r "length" 2> /dev/null <<< ${committeeHashArray}) + 0 ))
17381746
for (( tmpCnt=0; tmpCnt<${committeeEntryCnt}; tmpCnt++ ))
17391747
do
17401748

cardano/mainnet/03b_regStakingAddrCert.sh

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -551,18 +551,7 @@ if [[ -f "${fromAddr}.hwsfile" && -f "${stakeAddr}.hwsfile" && "${paymentName}"
551551
#Witness and Assemble the TxFile
552552
start_HwWallet; checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi
553553

554-
555-
#only one witness (cardano-hw-cli < 1.14.0) and for pre conway era
556-
# tmp=$(${cardanohwcli} transaction witness --tx-file ${txBodyFile} --hw-signing-file ${fromAddr}.hwsfile --hw-signing-file ${stakeAddr}.hwsfile --change-output-key-file ${fromAddr}.hwsfile --change-output-key-file ${stakeAddr}.hwsfile ${magicparam} --out-file ${txWitnessFile} 2> /dev/stdout)
557-
558-
#txBodyFile="./tmptest.json"
559-
560-
561-
562554
tmp=$(${cardanohwcli} transaction witness --tx-file ${txBodyFile} --hw-signing-file ${fromAddr}.hwsfile --hw-signing-file ${stakeAddr}.hwsfile --change-output-key-file ${fromAddr}.hwsfile --change-output-key-file ${stakeAddr}.hwsfile ${magicparam} --out-file ${txWitnessFile} --out-file ${txWitnessFile2} 2> /dev/stdout)
563-
564-
#echo ${tmp}; exit
565-
566555
checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi
567556
if [[ "${tmp^^}" =~ (ERROR|DISCONNECT) ]]; then echo -e "\e[35m${tmp}\e[0m\n"; exit 1; else echo -ne "\e[0mWitnessed ... "; fi
568557

cardano/mainnet/24a_genVote.sh

Lines changed: 54 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ if ${onlineMode}; then
233233
errorMsg=$(jq -r .errorMsg <<< ${signerJSON} 2> /dev/null)
234234
echo -e "\e[0m Anchor-Data: ${iconYes}\e[32m JSONLD structure is ok\e[0m";
235235
if [[ "${errorMsg}" != "" ]]; then echo -e "\e[0m Notice: ${iconNo} ${errorMsg}\e[0m"; fi
236-
authors=$(jq -r --arg iconYes "${iconYes}" --arg iconNo "${iconNo}" '.authors[] | "\\e[0m Signature: \(if .valid then $iconYes else $iconNo end) \(.name)\\e[0m"' <<< ${signerJSON} 2> /dev/null)
236+
authors=$(jq -r --arg iconYes "${iconYes}" --arg iconNo "${iconNo}" '.authors[] | "\\e[0m Signature: \(if .valid then $iconYes else $iconNo end) \(.name) (PubKey \(.publicKey))\\e[0m"' <<< ${signerJSON} 2> /dev/null)
237237
if [[ "${authors}" != "" ]]; then echo -e "${authors}\e[0m"; fi
238238
fi
239239
echo
@@ -290,7 +290,7 @@ case ${workMode} in
290290
if [[ ${govActionUTXO} != "" && ${govActionIdx} != "" ]]; then
291291
actionStateJSON=$(jq -r ". | select(.actionId.txId == \"${govActionUTXO}\" and .actionId.govActionIx == ${govActionIdx})" 2> /dev/null <<< "${actionStateJSON}")
292292
if [[ "${actionStateJSON}" = "" ]]; then #action-id not on chain
293-
echo -e "\e[0mThe provided Action-ID is\e[33m NOT present on the chain\e[0m!\e[0m\n";
293+
echo -e "\e[0mThe provided Action-ID is\e[33m NOT present (wrong ID or expired) on the chain \e[0m!\e[0m\n";
294294
exit 1;
295295
fi
296296
fi
@@ -627,9 +627,9 @@ do
627627
else
628628
errorMsg=$(jq -r .errorMsg <<< ${signerJSON} 2> /dev/null)
629629
echo -e "\e[0m Anchor-Data: ${iconYes}\e[32m JSONLD structure is ok\e[0m";
630-
govActionTitle=$(jq -r ".body.title // \"\"" ${tmpAnchorContent} 2> /dev/null)
630+
{ read govActionTitle; read proofDepositReturnAddr; read proofWithdrawalAddr; } <<< $(jq -r '.body.title // "-", .body.onChain.depositReturnAddress // "-", .body.onChain.withdrawals[0].withdrawalAddress // "-"' ${tmpAnchorContent} 2> /dev/null)
631631
if [[ "${errorMsg}" != "" ]]; then echo -e "\e[0m Notice: ${iconNo} ${errorMsg}\e[0m"; fi
632-
authors=$(jq -r --arg iconYes "${iconYes}" --arg iconNo "${iconNo}" '.authors[] | "\\e[0m Signature: \(if .valid then $iconYes else $iconNo end) \(.name)\\e[0m"' <<< ${signerJSON} 2> /dev/null)
632+
authors=$(jq -r --arg iconYes "${iconYes}" --arg iconNo "${iconNo}" '.authors[] | "\\e[0m Signature: \(if .valid then $iconYes else $iconNo end) \(.name) (PubKey \(.publicKey))\\e[0m"' <<< ${signerJSON} 2> /dev/null)
633633
if [[ "${authors}" != "" ]]; then echo -e "${authors}\e[0m"; fi
634634
fi
635635
fi
@@ -679,8 +679,17 @@ do
679679
;;
680680
esac
681681

682+
#Show an alert if there is a special proof for the deposit return address and it does not match up with the one in the action
683+
if [[ "${proofDepositReturnAddr}" != "-" ]]; then
684+
if [[ "${proofDepositReturnAddr}" == "${actionDepositAddr}" ]]; then
685+
echo -e "\e[0m${iconYes} The Deposit Return-StakeAddr in the govAction is the same as in the metadata proof!\e[0m\n";
686+
else
687+
echo -e "\e[0m${iconNo} The Deposit Return-StakeAddr in the govAction is not the same as in the metadata proof!\e[0m\n";
688+
fi
689+
fi
690+
682691
#Show governance action title if available
683-
if [[ "${govActionTitle}" != "" ]]; then
692+
if [[ "${govActionTitle}" != "-" ]]; then
684693
echo -e "\e[0mAction-Title: \e[36m${govActionTitle}\e[0m\n"
685694
fi
686695

@@ -946,32 +955,48 @@ do
946955
# ],
947956
# null
948957
#]
949-
{ read withdrawalsAmount; read withdrawalsKeyType; read withdrawalsHash; read withdrawalsNetwork; } <<< $( jq -r '.[0][0][1] // "0", (.[0][0][0].credential|keys[0]) // "-", (.[0][0][0].credential|flatten[0]) // "-", .[0][0][0].network // "-"' 2> /dev/null <<< ${actionContents})
950-
echo -e "\e[0mAction-Content:\e[36m Withdrawal funds from the treasury\n\e[0m"
951-
952-
case "${withdrawalsNetwork,,}${withdrawalsKeyType,,}" in
953-
954-
*"scripthash") echo -e "\e[0mWithdrawal to\e[32m ScriptHash \e[0m► \e[94m${withdrawalsHash}\e[0m"
955-
;;
956958

957-
"mainnet"*) withdrawalsAddr=$(${bech32_bin} "stake" <<< "e1${withdrawalsHash}" 2> /dev/null);
958-
if [[ $? -ne 0 ]]; then echo -e "\n\e[35mERROR - Could not get Withdrawals Stake-Address from KeyHash '${withdrawalsHash}' !\n\e[0m"; exit 1; fi
959-
echo -e "\e[0mWithdrawal to\e[32m StakeAddr \e[0m► \e[94m${withdrawalsAddr}\e[0m"
960-
;;
961-
962-
"testnet"*) withdrawalsAddr=$(${bech32_bin} "stake_test" <<< "e0${withdrawalsHash}" 2> /dev/null);
963-
if [[ $? -ne 0 ]]; then echo -e "\n\e[35mERROR - Could not get Withdrawals Stake-Address from KeyHash '${withdrawalsHash}' !\n\e[0m"; exit 1; fi
964-
echo -e "\e[0mWithdrawal to\e[32m StakeAddr \e[0m► \e[94m${withdrawalsAddr}\e[0m"
965-
;;
966-
967-
"") echo -e "\e[0mWithdrawal \e[32mdirectly\e[0m to the \e[94mDeposit-Return-Address\n\e[0m"
968-
;;
959+
{ read withdrawalEntries; read withdrawalCounts; } <<< $(jq -r '"\(.[0])" // "[]", (.[0]|length) // 0' <<< ${actionContents} 2> /dev/null)
960+
echo -e "\e[0mAction-Content:\e[36m Withdrawal funds from the treasury\n\e[0m"
969961

970-
*) echo -e "\n\e[35mERROR - Unknown network type ${withdrawalsNetwork} for the Withdrawal KeyHash !\n\e[0m"; exit 1;
971-
;;
972-
esac
973-
echo -e "\e[0mWithdrawal the\e[32m Amount \e[0m► \e[94m$(convertToADA ${withdrawalsAmount}) ADA / ${withdrawalsAmount} lovelaces\e[0m"
974-
echo -e "\e[0m"
962+
#Show all found entries
963+
for (( tmpCnt3=0; tmpCnt3<${withdrawalCounts}; tmpCnt3++ ))
964+
do
965+
{ read withdrawalsAmount; read withdrawalsKeyType; read withdrawalsHash; read withdrawalsNetwork; } <<< $( jq -r ".[${tmpCnt3}][1] // 0, (.[${tmpCnt3}][0].credential|keys[0]) // null, (.[${tmpCnt3}][0].credential|flatten[0]) // null, .[${tmpCnt3}][0].network // null" 2> /dev/null <<< ${withdrawalEntries})
966+
case "${withdrawalsNetwork,,}${withdrawalsKeyType,,}" in
967+
968+
*"scripthash") echo -e "\e[0mWithdrawal to\e[32m ScriptHash \e[0m► \e[94m${withdrawalsHash}\e[0m"
969+
;;
970+
971+
"mainnet"*) withdrawalsAddr=$(${bech32_bin} "stake" <<< "e1${withdrawalsHash}" 2> /dev/null);
972+
if [[ $? -ne 0 ]]; then echo -e "\n\e[35mERROR - Could not get Withdrawals Stake-Address from KeyHash '${withdrawalsHash}' !\n\e[0m"; exit 1; fi
973+
echo -e "\e[0mWithdrawal to\e[32m StakeAddr \e[0m► \e[94m${withdrawalsAddr}\e[0m"
974+
;;
975+
976+
"testnet"*) withdrawalsAddr=$(${bech32_bin} "stake_test" <<< "e0${withdrawalsHash}" 2> /dev/null);
977+
if [[ $? -ne 0 ]]; then echo -e "\n\e[35mERROR - Could not get Withdrawals Stake-Address from KeyHash '${withdrawalsHash}' !\n\e[0m"; exit 1; fi
978+
echo -e "\e[0mWithdrawal to\e[32m StakeAddr \e[0m► \e[94m${withdrawalsAddr}\e[0m"
979+
;;
980+
981+
"") echo -e "\e[0mWithdrawal \e[32mdirectly\e[0m to the \e[94mDeposit-Return-Address\n\e[0m"
982+
withdrawalsAddr="${actionDepositAddr}"
983+
;;
984+
985+
*) echo -e "\n\e[35mERROR - Unknown network type ${withdrawalsNetwork} for the Withdrawal KeyHash !\n\e[0m"; exit 1;
986+
;;
987+
esac
988+
echo -e "\e[0mWithdrawal the\e[32m Amount \e[0m► \e[94m$(convertToADA ${withdrawalsAmount}) ADA / ${withdrawalsAmount} lovelaces\e[0m"
989+
echo -e "\e[0m"
990+
done
991+
992+
#Show an alert if there is a special proof for the withdrawal address and it does not match up with the one in the action
993+
if [[ "${proofWithdrawalAddr}" != "-" ]]; then
994+
if [[ "${proofWithdrawalAddr}" == "${withdrawalsAddr}" ]]; then
995+
echo -e "\e[0m${iconYes} The Withdrawal StakeAddr in the govAction is the same as in the metadata proof!\e[0m\n";
996+
else
997+
echo -e "\e[0m${iconNo} The Withdrawal StakeAddr in the govAction is not the same as in the metadata proof!\e[0m\n";
998+
fi
999+
fi
9751000

9761001
#Calculate acceptance: Get the right threshold, make it a nice percentage number, check if threshold is reached
9771002
{ read dRepPowerThreshold; } <<< $(jq -r '.dRepVotingThresholds.treasuryWithdrawal // 0' <<< "${protocolParametersJSON}" 2> /dev/null)

0 commit comments

Comments
 (0)