Skip to content

Commit

Permalink
New features - Mnemonic wallet, Messages, Metadata
Browse files Browse the repository at this point in the history
Generating Base/Staking-Keys with/from Mnemonics has been added to the script:

- 03a_genStakingPaymentAddr.sh

So you can now generate a set of Base(Payment)- and Staking-Keys derived from 24-Word Mnemonics. If Mnemonics are provided they are used, otherwise new ones are created. This makes it easier to use keys across the CLI and other wallets like Daedalus, Eternl, Typhoon, ...

---

Sending transaction messages including the option to encrypt the messages (CIP-0083) has been added to the following scripts:

- 03b_regStakingAddrCert.sh
- 05c_regStakepoolCert.sh
- 05d_poolWitness.sh
- 06_regDelegationCert.sh
- 07b_deregStakepoolCert.sh
- 08b_deregStakingAddrCert.sh

---

Attaching transaction metadata as *.json and *.cbor file has been added to the following scripts:

- 03b_regStakingAddrCert.sh
- 05c_regStakepoolCert.sh
- 05d_poolWitness.sh
- 06_regDelegationCert.sh
- 07b_deregStakepoolCert.sh
- 08b_deregStakingAddrCert.sh

So you can now add a comment or an encrypted message or metadata to every transaction that is possible via the StakepoolOperatorScripts.
  • Loading branch information
gitmachtl committed Oct 4, 2023
1 parent 97bdc70 commit 46040b7
Show file tree
Hide file tree
Showing 8 changed files with 1,048 additions and 100 deletions.
4 changes: 2 additions & 2 deletions cardano/mainnet/00_common.sh
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ case "${network,,}" in
_transactionExplorer="https://preview.cardanoscan.io/transaction"
_koiosAPI="https://preview.koios.rest/api/v0"
_adahandlePolicyID="f0ff48bbb7bbe9d59a40f1ce90e9e9d0ff5002ec48f232b49ca0fb9a" #PolicyIDs for the adaHandles -> autoresolve into ${adahandlePolicyID}
_catalystAPI="https://api.testnet.projectcatalyst.io/api/v1" #Catalyst-API URLs -> autoresolve into ${catalystAPI}
_catalystAPI= #Catalyst-API URLs -> autoresolve into ${catalystAPI}
;;


Expand All @@ -203,7 +203,7 @@ case "${network,,}" in
_addrformat="--testnet-magic 1097911063"
_byronToShelleyEpochs=74
_tokenMetaServer="https://metadata.cardano-testnet.iohkdev.io/metadata"
_transactionExplorer="https://testnet.cexplorer.io/tx"
_transactionExplorer=
_koiosAPI=
_adahandlePolicyID="8d18d786e92776c824607fd8e193ec535c79dc61ea2405ddf3b09fe3"
_catalystAPI= #Catalyst-API URLs -> autoresolve into ${catalystAPI}
Expand Down
192 changes: 166 additions & 26 deletions cardano/mainnet/03a_genStakingPaymentAddr.sh

Large diffs are not rendered by default.

164 changes: 152 additions & 12 deletions cardano/mainnet/03b_regStakingAddrCert.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,31 +6,160 @@
. "$(dirname "$0")"/00_common.sh


case $# in
2 ) stakeAddr="$(dirname $1)/$(basename $1 .staking).staking"; stakeAddr=${stakeAddr/#.\//};
fromAddr="$(dirname $2)/$(basename $2 .addr)"; fromAddr=${fromAddr/#.\//};;
* ) cat >&2 <<EOF
#Check command line parameter
if [ $# -lt 2 ]; then
cat >&2 <<EOF
Usage: $(basename $0) <StakeAddressName> <Base/PaymentAddressName (paying for the registration fees)>
Example: $(basename $0) atada.staking atada.payment
[Opt: Message comment, starting with "msg: ...", | is the separator]
[Opt: encrypted message mode "enc:basic". Currently only 'basic' mode is available.]
[Opt: passphrase for encrypted message mode "pass:<passphrase>", the default passphrase if 'cardano' is not provided]
Optional parameters:
- If you wanna attach a Transaction-Message like a short comment, invoice-number, etc with the transaction:
You can just add one or more Messages in quotes starting with "msg: ..." as a parameter. Max. 64chars / Message
"msg: This is a short comment for the transaction" ... that would be a one-liner comment
"msg: This is a the first comment line|and that is the second one" ... that would be a two-liner comment, | is the separator !
If you also wanna encrypt it, set the encryption mode to basic by adding "enc: basic" to the parameters.
To change the default passphrase 'cardano' to you own, add the passphrase via "pass:<passphrase>"
- If you wanna attach a Metadata JSON:
You can add a Metadata.json (Auxilierydata) filename as a parameter to send it alone with the transaction.
There will be a simple basic check that the transaction-metadata.json file is valid.
- If you wanna attach a Metadata CBOR:
You can add a Metadata.cbor (Auxilierydata) filename as a parameter to send it along with the transaction.
Catalyst-Voting for example is done via the voting_metadata.cbor file.
Examples:
$(basename $0) myWallet.staking myWallet.payment
-> Register the myWallet StakeKey on Chain, Payment via the myWallet.paymet wallet
$(basename $0) myWallet.staking myWallet.payment "msg: StakeKey Registration for myWallet"
-> Register the myWallet StakeKey on Chain, Payment via the myWallet.paymet wallet, Adding a Transaction-Message
EOF
exit 1;; esac
exit 1;
fi

#At least 2 parameters were provided, use them
stakeAddr="$(dirname $1)/$(basename $1 .staking).staking"; stakeAddr=${stakeAddr/#.\//};
fromAddr="$(dirname $2)/$(basename $2 .addr)"; fromAddr=${fromAddr/#.\//};

#Check about required files: Registration Certificate, Signing Key and Address of the payment Account
#For StakeKeyRegistration
if [ ! -f "${stakeAddr}.cert" ]; then echo -e "\n\e[35mERROR - \"${stakeAddr}.cert\" Registration Certificate does not exist! Please create it first with script 03a.\e[0m"; exit 2; fi
if [ ! -f "${stakeAddr}.addr" ]; then echo -e "\n\e[35mERROR - \"${stakeAddr}.addr\" Stake Address file does not exist! Please create it first with script 03a.\e[0m"; exit 2; fi
#if ! [[ -f "${stakeAddr}.skey" || -f "${stakeAddr}.hwsfile" ]]; then echo -e "\n\e[35mERROR - \"${stakeAddr}.skey/hwsfile\" Staking Signing Key or HardwareFile does not exist! Please create it first with script 03a.\e[0m"; exit 2; fi

#For payment
if [ ! -f "${fromAddr}.addr" ]; then echo -e "\n\e[35mERROR - \"${fromAddr}.addr\" does not exist! Please create it first with script 03a or 02.\e[0m"; exit 1; fi
if ! [[ -f "${fromAddr}.skey" || -f "${fromAddr}.hwsfile" ]]; then echo -e "\n\e[35mERROR - \"${fromAddr}.skey/hwsfile\" does not exist! Please create it first with script 03a or 02.\e[0m"; exit 1; fi




#Setting default variables
metafileParameter=""; metafile=""; transactionMessage="{}"; enc=""; passphrase="cardano" #Setting defaults

#Check all optional parameters about there types and set the corresponding variables
#Starting with the 3th parameter (index=2) up to the last parameter
paramCnt=$#;
allParameters=( "$@" )
for (( tmpCnt=2; tmpCnt<${paramCnt}; tmpCnt++ ))
do
paramValue=${allParameters[$tmpCnt]}
#echo -n "${tmpCnt}: ${paramValue} -> "

#Check if an additional metadata.json/.cbor was set as parameter (not a Message, not a UTXO#IDX, not empty, not a number)
if [[ ! "${paramValue,,}" =~ ^msg:(.*)$ ]] && [[ ! "${paramValue,,}" =~ ^enc:(.*)$ ]] && [[ ! "${paramValue,,}" =~ ^pass:(.*)$ ]] && [[ ! "${paramValue,,}" =~ ^utxolimit:(.*)$ ]] && [[ ! "${paramValue,,}" =~ ^onlyutxowithasset:(.*)$ ]] && [[ ! "${paramValue,,}" =~ ^skiputxowithasset:(.*)$ ]] && [[ ! "${paramValue}" =~ ^([[:xdigit:]]+#[[:digit:]]+(\|?)){1,}$ ]] && [[ ! ${paramValue} == "" ]] && [ -z "${paramValue##*[!0-9]*}" ]; then

metafile=${paramValue}; metafileExt=${metafile##*.}
if [[ -f "${metafile}" && "${metafileExt^^}" == "JSON" ]]; then #its a json file
#Do a simple basic check if the metadatum is in the 0..65535 range
metadatum=$(jq -r "keys_unsorted[0]" "${metafile}" 2> /dev/null)
if [[ $? -ne 0 ]]; then echo -e "\n\e[35mERROR - '${metafile}' is not a valid JSON file!\n\e[0m"; exit 1; fi
#Check if it is null, a number, lower then zero, higher then 65535, otherwise exit with an error
if [ "${metadatum}" == null ] || [ -z "${metadatum##*[!0-9]*}" ] || [ "${metadatum}" -lt 0 ] || [ "${metadatum}" -gt 65535 ]; then
echo -e "\n\e[35mERROR - MetaDatum Value '${metadatum}' in '${metafile}' must be in the range of 0..65535!\n\e[0m"; exit 1; fi
metafileParameter="${metafileParameter}--metadata-json-file ${metafile} "; metafileList="${metafileList}'${metafile}' "
elif [[ -f "${metafile}" && "${metafileExt^^}" == "CBOR" ]]; then #its a cbor file
metafileParameter="${metafileParameter}--metadata-cbor-file ${metafile} "; metafileList="${metafileList}'${metafile}' "
else echo -e "\n\e[35mERROR - The specified Metadata JSON/CBOR-File '${metafile}' does not exist. Fileextension must be '.json' or '.cbor' Please try again.\n\e[0m"; exit 1;
fi

#Check it its a MessageComment. Adding it to the JSON array if the length is <= 64 chars
elif [[ "${paramValue,,}" =~ ^msg:(.*)$ ]]; then #if the parameter starts with "msg:" then add it
msgString=$(trimString "${paramValue:4}");

#Split the messages within the parameter at the "|" char
IFS='|' read -ra allMessages <<< "${msgString}"

#Add each message to the transactionMessage JSON
for (( tmpCnt2=0; tmpCnt2<${#allMessages[@]}; tmpCnt2++ ))
do
tmpMessage=${allMessages[tmpCnt2]}
if [[ $(byteLength "${tmpMessage}") -le 64 ]]; then
transactionMessage=$( jq ".\"674\".msg += [ \"${tmpMessage}\" ]" <<< ${transactionMessage} 2> /dev/null);
if [ $? -ne 0 ]; then echo -e "\n\e[35mMessage-Adding-ERROR: \"${tmpMessage}\" contain invalid chars for a JSON!\n\e[0m"; exit 1; fi
else echo -e "\n\e[35mMessage-Adding-ERROR: \"${tmpMessage}\" is too long, max. 64 bytes allowed, yours is $(byteLength "${tmpMessage}") bytes long!\n\e[0m"; exit 1;
fi
done

#Check if its a transaction message encryption type
elif [[ "${paramValue,,}" =~ ^enc:(.*)$ ]]; then #if the parameter starts with "enc:" then set the encryption variable
encryption=$(trimString "${paramValue:4}");

#Check if its a transaction message encryption passphrase
elif [[ "${paramValue,,}" =~ ^pass:(.*)$ ]]; then #if the parameter starts with "pass:" then set the passphrase variable
passphrase="${paramValue:5}"; #don't do a trimstring here, because also spaces are a valid passphrase !

fi #end of different parameters check

done

#Check if there are transactionMessages, if so, save the messages to a xxx.transactionMessage.json temp-file and add it to the list. Encrypt it if enabled.
if [[ ! "${transactionMessage}" == "{}" ]]; then

transactionMessageMetadataFile="${tempDir}/$(basename ${fromAddr}).transactionMessage.json";
tmp=$( jq . <<< ${transactionMessage} 2> /dev/null)
if [ $? -eq 0 ]; then #json is valid, so no bad chars found

#Check if encryption is enabled, encrypt the msg part
if [[ "${encryption,,}" == "basic" ]]; then
#check openssl
if ! exists openssl; then echo -e "\e[33mYou need 'openssl', its needed to encrypt the transaction messages !\n\nInstall it on Ubuntu/Debian like:\n\e[97msudo apt update && sudo apt -y install openssl\n\n\e[33mThx! :-)\e[0m\n"; exit 2; fi
msgPart=$( jq -crM ".\"674\".msg" <<< ${transactionMessage} 2> /dev/null )
checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi
encArray=$( openssl enc -e -aes-256-cbc -pbkdf2 -iter 10000 -a -k "${passphrase}" <<< ${msgPart} | awk {'print "\""$1"\","'} | sed '$ s/.$//' )
checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi
#compose new transactionMessage by using the encArray as the msg and also add the encryption mode 'basic' entry
tmp=$( jq ".\"674\".msg = [ ${encArray} ]" <<< '{"674":{"enc":"basic"}}' )
checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi

elif [[ "${encryption}" != "" ]]; then #another encryption method provided
echo -e "\n\e[35mERROR - The given encryption mode '${encryption,,}' is not on the supported list of encryption methods. Only 'basic' from CIP-0083 is currently supported\n\n\e[0m"; exit 1;
fi

echo "${tmp}" > ${transactionMessageMetadataFile}; metafileParameter="${metafileParameter}--metadata-json-file ${transactionMessageMetadataFile} "; #add it to the list of metadata.jsons to attach

else
echo -e "\n\e[35mERROR - Additional Transaction Message-Metafile is not valid:\n\n$${transactionMessage}\n\nPlease check your added Message-Paramters.\n\e[0m"; exit 1;
fi

fi




echo
echo -e "\e[0mRegister Staking Address\e[32m ${stakeAddr}.addr\e[0m with funds from Address\e[32m ${fromAddr}.addr\e[0m"
echo



checkAddr=$(cat ${stakeAddr}.addr)
typeOfAddr=$(get_addressType "${checkAddr}")

Expand Down Expand Up @@ -63,7 +192,6 @@ fi
#get live values
currentTip=$(get_currentTip)
ttl=$(get_currentTTL)
currentEPOCH=$(get_currentEpoch)

echo -e "Current Slot-Height:\e[32m ${currentTip}\e[0m (setting TTL[invalid_hereafter] to ${ttl})"

Expand Down Expand Up @@ -119,7 +247,6 @@ echo
utxoHashIndex=${utxoHashIndexArray[${tmpCnt}]}
utxoAmount=${utxoLovelaceArray[${tmpCnt}]} #Lovelaces
totalLovelaces=$(bc <<< "${totalLovelaces} + ${utxoAmount}" )
# echo -e "Hash#Index: ${utxoHashIndex}\tAmount: ${utxoAmount}";
echo -e "Hash#Index: ${utxoHashIndex}\tADA: $(convertToADA ${utxoAmount}) \e[90m(${utxoAmount} lovelaces)\e[0m";
if [[ ! "${utxoDatumHashArray[${tmpCnt}]}" == null ]]; then echo -e " DatumHash: ${utxoDatumHashArray[${tmpCnt}]}"; fi
assetsEntryCnt=${assetsEntryCntArray[${tmpCnt}]}
Expand Down Expand Up @@ -207,6 +334,19 @@ echo

echo

#There are metadata file(s) attached, list them:
if [[ ! "${metafileList}" == "" ]]; then echo -e "\e[0mInclude Metadata-File(s):\e[32m ${metafileList}\e[0m\n"; fi

#There are transactionMessages attached, show the metadatafile:
if [[ ! "${transactionMessage}" == "{}" ]]; then
if [[ "${encArray}" ]]; then #if there is an encryption, show the original Metadata first with the encryption paramteters
echo -e "\e[0mOriginal Transaction-Message:\n\e[90m"; jq -rM <<< ${transactionMessage}; echo -e "\e[0m";
echo -e "\e[0mEncrypted Transaction-Message mode \e[32m${encryption,,}\e[0m with Passphrase '\e[32m${passphrase}\e[0m'";
echo
fi
echo -e "\e[0mInclude Transaction-Message-Metadata-File:\e[32m ${transactionMessageMetadataFile}\n\e[90m"; cat ${transactionMessageMetadataFile}; echo -e "\e[0m";
fi

#Read ProtocolParameters
if ${onlineMode}; then
protocolParametersJSON=$(${cardanocli} query protocol-parameters ${magicparam} ); #onlinemode
Expand All @@ -222,7 +362,7 @@ minOutUTXO=$(calc_minOutUTXO "${protocolParametersJSON}" "${sendToAddr}+1000000$
txBodyFile="${tempDir}/dummy.txbody"; rm ${txBodyFile} 2> /dev/null
rm ${txBodyFile} 2> /dev/null
#echo -e "${cardanocli} transaction build-raw ${nodeEraParam} ${txInString} --tx-out "${sendToAddr}+1000000${assetsOutString}" --invalid-hereafter ${ttl} --fee 100 --certificate ${stakeAddr}.cert --out-file ${txBodyFile}"
${cardanocli} transaction build-raw ${nodeEraParam} ${txInString} --tx-out "${sendToAddr}+1000000${assetsOutString}" --invalid-hereafter ${ttl} --fee 100 --certificate ${stakeAddr}.cert --out-file ${txBodyFile}
${cardanocli} transaction build-raw ${nodeEraParam} ${txInString} --tx-out "${sendToAddr}+1000000${assetsOutString}" --invalid-hereafter ${ttl} --fee 100 ${metafileParameter} --certificate ${stakeAddr}.cert --out-file ${txBodyFile}
checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi

fee=$(${cardanocli} transaction calculate-min-fee --tx-body-file ${txBodyFile} --protocol-params-file <(echo ${protocolParametersJSON}) --tx-in-count ${txcnt} --tx-out-count ${rxcnt} ${magicparam} --witness-count 1 --byron-witness-count 0 | awk '{ print $1 }')
Expand Down Expand Up @@ -255,7 +395,7 @@ echo

#Building unsigned transaction body
rm ${txBodyFile} 2> /dev/null
${cardanocli} transaction build-raw ${nodeEraParam} ${txInString} --tx-out "${sendToAddr}+${lovelacesToSend}${assetsOutString}" --invalid-hereafter ${ttl} --fee ${fee} --certificate ${stakeAddr}.cert --out-file ${txBodyFile}
${cardanocli} transaction build-raw ${nodeEraParam} ${txInString} --tx-out "${sendToAddr}+${lovelacesToSend}${assetsOutString}" --invalid-hereafter ${ttl} --fee ${fee} ${metafileParameter} --certificate ${stakeAddr}.cert --out-file ${txBodyFile}
checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi

dispFile=$(cat ${txBodyFile}); if ${cropTxOutput} && [[ ${#dispFile} -gt 4000 ]]; then echo "${dispFile:0:4000} ... (cropped)"; else echo "${dispFile}"; fi
Expand Down
Loading

0 comments on commit 46040b7

Please sign in to comment.