Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 19 You must be signed in to star a gist
  • Fork 7 You must be signed in to fork a gist
  • Save ilap/8efdaa9e8e3ae737e303ac51469acb67 to your computer and use it in GitHub Desktop.
Save ilap/8efdaa9e8e3ae737e303ac51469acb67 to your computer and use it in GitHub Desktop.
The Hitchhikers Guide To The Shelley - Chapter 3 - The Staking

The Hitchhiker's Guide To The Shelley - Chapter 3 - The Staking

This guide's chapter targets the pool operators for getting their head around of Shelley staking. To fully understand the staking mechanism we need to define and interpret the following key concepts:

Keys, Addresses and Certifications

The following picture helps to understand the relations between keys, addresses and certificates.

ShelleyKeyAndAddresses

Key Types and their functions

Keys are just simply asymmetric cryptography key pairs (private/public, signing/verifying) that are used for signing and validating payments and staking related certificates and identifying, defining addresses on the Cardano blockchain.

As it can be seen in the picture there are two main type of keys in Shelley:

  • Node keys and
  • Address keys.

The node keys are relevant to the security of the blockchain while the address keys are relevant to the functions of the addresses derived from the keys for identifying funds on the blockchain. See details below and above in the picture.

  1. Node Keys
    • Operator/operatioanl key: operator's offline key pair with cert counter for new certificates.
    • Hot KES key: operator's hot KES key pair.
    • Block signing key: operational VRF key pair, it participates in the "lottery" i.e. right to create and sign the block for the specific slot.
  2. Address (Payment, Staking etc.) keys
    • Payment key: single address key pair (usually for generating UtxO addresses)
    • Staking key: stake/reward address key pair (usually generating account/reward addresses)

Addresses and their functions

The addresses, as of now, are just a simple blake2b-256 hash of the relevant veryifying/public keys contatenated with some metadata that are or can be stored on the Cardano blockchain.

Addresses in this context are only relevant to the ledger specification and not to any wallet addresses. So, the wallets m/44'/1852'/0'/{0,1,2} bech32 addresses (e.g. ca1hg9...) are irrelevant here.

Currently there are three main type of addresses and a reserved address space for future use:

  1. Payment addresses:
    • base addresses (can participate in staking, a.k.a goup addresses in ITN jorm terminology)
    • pointer addresses (need to check whether it can or cannot participate in staking)
    • enterprise addresses (cannot participate in staking a.k.a UtxO address)
  2. Reward addresses: Reward/account addresses (can participate in staking)
  3. Byron addresses: The legacy addresses, for backward compatibility (cannot participate in staking)
  4. Future addresses: possible 5 main /w 16 subtypes or 80 additional address types)

Therefore addresses, in Cardano Shelley (only in Haskell code), are some serialised data specified in the ledger specification that are stored in the blockhain's blocks (e.g. an UtxO address).

The serialised data (address) contains two parts the metadata and payload (i.e. address = metadata + payload):

  • metadata: is for interpreting the
  • payload: the raw or encoded bytes. For example the verifying/public keys or their hashes or even scripts (e.g. plutus smart contract) hashes.

Therefore, in layman definition (by removing some complexity for easy understanding): Addresses are serialised public/verifying keys

See,the detailed address specification here.

Pls, keep in mind, that it does not mean that the specification is currently is used, implemented and/or finalised.

Certificates

Shelley's PoS protocol requires different certificates posted to the blockhain; which will be pulbicyl available for all participants. Those are valids until explicitly overwritten or revoked.

There are four main type of certificates are in Shelley:

  1. Operational key certificates (off chain),
  2. Stake Key registration certificates (on chain),
  3. Delegation certificates (on chain) and
  4. Stake pool certificates (on chain).

Operational key certificates

The operational key certificate's is created from a operator key used by stake pool operators for protecting their pool(s) and keys, signing bocke, participating in the lottery and not for delegating staking rights. This certificate needs for operating a node as a stake pool.

See detailed exameple here

Stake Key registration certificates

All participants, who want to participate in staking, need to register a stake key on the blockchain by posting a stake key registration certificate. The registration requires a key deposit specified in the genesis (400K lovelace for FnF), but do not require any signature signed by the corresponding stake signing key.

The registration is revoked when a de-registration certificate signed by the account's stake signing key is posted to the blockchain, causing the account to be deleted (Ask what is the impact of this).

See detailed example here

Delegation certificates

Delegation certificates uses a staking key to grant the right to sign blocks to another key.

See detailed example here

Stake pool certificates

A node for operating as a stake pool must post a stake pool registration certificate signed by all the owners' staking signing key and the pool operator's operational signing key.

To revoke the certificate a stake pool retirement certificate must be posted to the chain signed by only the pool's operational signing key.

No owner(s) is/are required to sign the retirement certificate.

See detailed example here

The Stake Holders

Tha stake holders in simple words are those who are participating in stakings, namely:

  1. Operators, who operate staking pools,
  2. Owners, who own a pool, in some extent, by pledging their stakes to pools and the
  3. Delegates, who delegate their staking rights to stake pools.

For participating in staking, every stake holder must have some form of different type of address keys:

  • payment keys, which can or cannot participate in staking and
  • staking keys for receiving staking (stake or pool) rewards.

Owners

The owners are the stake holders who have some funds deposited and want to own, in some extent, a staking pool. The owner's objectives are the following:

  • Create payment key(s) for generating base payment addresses.
  • Create stake key(s) for generating pool reward address.
  • Create and submit the owner's delegation certificate for pledging.

Note: In this example the operator's stake and payment keys will be used for pledging. That means the the operator is the owner. See details below

Operators

The operator(s) is/are the stake holder(s) who operating a pools. The operators can define their operational costs in the pool certificate, that can be deducted from the rewards.

The objectives are the following:

  • Understand off-chain operational key certificates,
  • the required keys and addresses,
    • payment key(s) for generating base payment addresses,
    • stake key(s) for generating pool reward address(es),
  • the stake address registration process with key deposit and
  • the stake pool registration procedure /w pledge and other params.

Detailed steps are:

  • Run a node with an operational key certificate
  • Create stake key registration certificate for registering the operator's stake key (staking.key) on the chain, then
  • Create a pool registration certificate for the node to became a stake pool (pool.cert),
  • Create a delegation certificate for the owner (operator in our exercise) to delegate its stake as pledge to the newly creating pool (deleg.cert).
  • Sends the on-chain certificates to the blockchain in one or more transactions.

Run a node with Operational Key Certificate

The operational key certificates use an operational key (cold) key to grant the right to sign blocks to another key (KES) that will expire after some epochs, that is based on the genesis parameters.

It uses a similar mechanism to the forward secure signature scheme where the signing key (KES) changes over time period and the end of each time period a new signing key is computed for the next peried and the old one is erased.

The mechanism used for running a node with operational key certificates are the following:

  1. KES (Key Evolving Signatures) that creates new (hot) KES keys periodically from the cold key
    • Create the cold (offline) key pair,
    • Create the hot KES key pairs (periodically), for signing blocks.
    • Create the operational key certificate
  2. Generate VRF key pair for leader selection (lottery).
  3. Run stake pool that is using the
  • non expired Operational certificate
  • non expired KES (hot) signing key
  • VRF signing key

Before the old hot (KES) key pair is expiring, a new operational key certificate needs to be created by using a newly generated hot (KES) key pair and the off-line cold signing key.

In production environment, it is expected that the cold key is generated by some seed generation mechanism (BIP39 or similar) and stored on computer that does not have access to the Internet and when the time arrives, the operational certificates with the hot (KES) key pairs are transferred, by some mechanism (USB stick, air gapped QR etc.) to the stake pool.

# 1.1 Create cold key pair
##########################################
pushd  /opt/cardano/fnf && mkdir -p ~/cold-keys && pushd ~/cold-keys || exit 127

# Generate the cold offline key pair
cardano-cli shelley node key-gen \
    --verification-key-file cold.vkey \
    --signing-key-file cold.skey \
    --operational-certificate-issue-counter cold.counter
popd

# 1.2 Generate a new hot KES keypair 
cardano-cli shelley node key-gen-KES --verification-key-file priv/kes.vkey --signing-key-file priv/kes.skey

# 1.3 Generate the ops cert based on 
# - the `cold signing key`
# - the hot KES key and
# - the cold key's counter
# New periodic cert is based on the new hot KES key.
# kes-period tells how long the ops cert therefrore the hot KES keys are valid
#
cardano-cli shelley node issue-op-cert \
    --cold-signing-key-file ~/cold-keys/cold.skey \
    --operational-certificate-issue-counter ~/cold-keys/cold.counter \
    --hot-kes-verification-key-file priv/kes.vkey \
    --kes-period 0 \
    --out-file priv/op.cert

# 2. Generate VRF key pair for leader selection
#########################################################
cardano-cli shelley node key-gen-VRF --verification-key-file priv/vrf.vkey --signing-key-file priv/vrf.skey

# 3. Run node /w these new keys generated
#########################################################

cardano-node run \
  --config                          files/config.json \
  --topology                        files/topology.json \
  --database-path                   db \
  --socket-path                     sockets/nodes.socket \
  --shelley-kes-key                 priv/kes.skey \
  --shelley-vrf-key                 priv/vrf.skey \
  --shelley-operational-certificate priv/op.cert \
  --port                            6000 

I will use the initial genesis address as input for registering the:

  • delegate registration certificate and
  • pool registration certificate

Keep in mind the operator also need to have its stake key registered onn the chain.

Create stake key registration certificate

First we need to create the operator's key in order to register the key on the chain.

The delegate's staking key needs to be registered on the blockchain in order to participating in staking, which just need a simple transaction using any payment address.

This is the pool operators's stake key, and not the delegate's one. Therefore I prefixed them it differently i.e. staking, to distuinguish between the delegate's (stake) prefix.

mkdir operator && pushd operator

# Generate the operator's stake keys
cardano-cli shelley stake-address key-gen --verification-key-file staking.vkey --signing-key-file staking.skey

# crate teh reward (staking) address from the operator's stake keys
cardano-cli shelley stake-address build --staking-verification-key-file staking.vkey > staking.addr

# Generate the operator's payment keys
cardano-cli shelley address key-gen --verification-key-file op_pay.vkey --signing-key-file op_pay.skey

# Generate an `enterprise` address for the operator.
cardano-cli shelley address build --payment-verification-key-file op_pay.vkey > op_pay.addr

# Generate the base address  i.e. compount `enterprise || reward` address
cardano-cli shelley address build \
    --payment-verification-key-file op_pay.vkey \
    --staking-verification-key-file staking.vkey \
    > base.addr

The next step is creating a stake address registration certificate.

For registering an stake key on the chain a key deposit1 fee must be paid. The amount can be optained from the genesis for the params file e.g.:

grep keyDep ../params.json
    "keyDeposit": 400000,

Generate the operator's stake key registration certificate

Keep, in mind that the a key registration certificates needs a deposit (keyDeposit in genesis) for the costs of tracking the key and the corresponding reward account. Also, it does not require any witness to register the certificate, but only the witness for the fees from the input of the transaction.

# Keep in mind that this certificates needs a `keyDeposit` specified in the genesis.
cardano-cli shelley stake-address registration-certificate \
    --staking-verification-key-file staking.vkey \
    --out-file staking.cert
# The certificate contains the `blake2b-256` hash of the stake verifying key

# Calculate the min fee for the following outputs:
# 1. the base address that will contain the funds for pledge
# 2. And the change address.
# Keep in mind just one signing key is required, the paying signing key,
# as stake key reg cert does not need t obe witnessed
cardano-cli shelley transaction calculate-min-fee \
    --tx-in-count 1 \
    --tx-out-count 2 \
    --ttl 500000 \
    --testnet-magic 42 \
    --signing-key-file /opt/cardano/fnf/addresses/genesis.skey \
    --certificate staking.cert \
    --protocol-params-file params.json
# 
# runTxCalculateMinFee: 174169

# INPUT will be based on the genesis addres (FROM)
# but any pay address is fine.
FROM="617190446876aed298ee207c6b5a335e832e2169a060b8167ef3ba9caff6fa3393"

cardano-cli shelley query utxo --testnet-magic 42 --address "$FROM"
#                           TxHash                                 TxIx        Lovelace
#----------------------------------------------------------------------------------------
#c85b72ee021915f5a8349209db54a51334ad9dfcec2f0fa2619a707556017bb3     0      499999825831

INPUT="c85b72ee021915f5a8349209db54a51334ad9dfcec2f0fa2619a707556017bb3#0"
BALANCE=499999825831
# The amount will be 400K and I will pladge all of it to the pool
AMOUNT=400000000000
KEYDEP=400000
FEE=174169
CHANGE="$FROM+$(( 499999825831 - $FEE - $KEYDEP - $AMOUNT ))"


# So, I used the genesis UtxO to move to some staking (group) address and 500K back to it.
cardano-cli shelley transaction build-raw \
    --tx-in "$INPUT" \
    --tx-out $(cat base.addr)+$AMOUNT \
    --tx-out "$CHANGE" \
    --ttl 500000 \
    --fee "$FEE" \
    --tx-body-file staking-cert.tx \
    --certificate staking.cert

# Sign it
cardano-cli shelley transaction sign \
    --tx-body-file staking-cert.tx \
    --signing-key-file /opt/cardano/fnf/addresses/genesis.skey \
    --testnet-magic 42 \
    --tx-file signed-staking-cert.tx

# Submit it
cardano-cli shelley transaction submit \
    --tx-file signed-staking-cert.tx \
    --testnet-magic 42

Create a pool registration certificate

A node needs a pool certificate registered on the blockchain for the operator to became a stake pool (pool.cert),

Now we have a 400K on the operator's base address and the stake key (staking.key) is registered.

cardano-cli shelley query utxo --testnet-magic 42 --address $(cat base.addr)
                           TxHash                                 TxIx        Lovelace
----------------------------------------------------------------------------------------
863506d0e7d1afcdb558ac4b021f2e7746f3c3178faecd11e1f0349ded141a74     0      400000000000

In the operator's PoV, for registering a pool, the pool certificate must contain:

  • a node operational verifying key a.k.a. cold key, for generating the pool id.
  • the VRF verifyig key a.k.a hot key, for lottery, to prove that the node has the right to create and sign a block,
  • an operator stake verifying keys for generating the reward address, where the pool rewards would be sent and
  • owner's stake verifying keys generating the pledge staking address, that has enough fund for pledging.

Note: the reward account verification key and the owner staking verification key can be the same is, see below example, if the operator is the owner too.

Also, for registering a pool certificate a pool deposit must be paid too.

# Createing a pools cert with
# - 400K of the owner's (operator in this example) 400K pledge, 
# - 1k as cost /w 
# - 5% margin
cardano-cli shelley stake-pool registration-certificate \
    --stake-pool-verification-key-file ~/cold-keys/pool.vkey \
    --vrf-verification-key-file /opt/cardano/fnf/priv/vrf.vkey \
    --pool-pledge 400000000000 \
    --pool-cost 1000000000 \
    --pool-margin 0.05 \
    --reward-account-verification-key-file staking.vkey \
    --pool-owner-staking-verification-key staking.vkey \
    --out-file pool.cert

Create (the stake owner's) delegation certificate

For pledging, the owner (in our example the operator) must create a stake delegation certificate for delegating at least a pledge amount of stake from the owner's staking key specified in the pool certificate.

In simple words, the owner is delegating its funds (pledge) to the pool he/she owns.

cardano-cli shelley stake-address delegation-certificate \
    --staking-verification-key-file staking.vkey \
    --stake-pool-verification-key-file ~/cold-keys/pool.vkey \
    --out-file owner-delegation.cert

Submit the certificate to the chain

The certificates can be sent in one transaction.

Please, keep in mind that the registering a pool the operator's must pay a (decaying) pool deposit fee.

# grep -i poolDeposit params.json
#  "poolDeposit": 500000000,
# or 
# cardano-cli shelley query  protocol-parameters --testnet-magic 42 | jq '.poolDeposit'
# 500000000


# Calculate the fee for sending the both certificates the
# - pool registration certificate and the
# - owner's (in our case the operator's) delegating certificate.
#
# Also, it will be paid by my genesis key, but any valid `payment` signing key would do that 
# has the fee and the deposit
cardano-cli shelley transaction calculate-min-fee \
    --tx-in-count 1 \
    --tx-out-count 1 \
    --ttl 500000 \
    --testnet-magic 42 \
    --signing-key-file /opt/cardano/fnf/addresses/genesis.skey \
    --signing-key-file staking.skey \
    --signing-key-file ~/cold-keys/pool.skey \
    --certificate pool.cert \
    --certificate owner-delegation.cert \
    --protocol-params-file ../params.json
# runTxCalculateMinFee: 184377

FEE=184377
POOLDEP=500000000

cardano-cli shelley query utxo --testnet-magic 42 --address "$FROM"
#                           TxHash                                 TxIx        Lovelace
#----------------------------------------------------------------------------------------
#863506d0e7d1afcdb558ac4b021f2e7746f3c3178faecd11e1f0349ded141a74     1       99999251662

BALANCE=99999251662
INPUT="863506d0e7d1afcdb558ac4b021f2e7746f3c3178faecd11e1f0349ded141a74#1"
CHANGE="$FROM+$(( $BALANCE - $FEE - $POOLDEP ))"

# Build
cardano-cli shelley transaction build-raw \
     --tx-in "$INPUT" \
     --tx-out "$CHANGE" \
     --ttl 500000 \
     --fee "$FEE" \
     --tx-body-file pool-cert.tx \
     --certificate pool.cert \
     --certificate owner-delegation.cert 

# Sign
# - the `genesis.skey` needs for signing the payment from the $FROM address.
# - the `staking.skey` needs for signing the owner's delegation certificate.
# - the `pool.skey` needs for signing the pool's registration certificate.
cardano-cli shelley transaction sign \
    --tx-body-file pool-cert.tx \
    --signing-key-file /opt/cardano/fnf/addresses/genesis.skey \
    --signing-key-file staking.skey \
    --signing-key-file ~/cold-keys/pool.skey \
    --testnet-magic 42 \
    --tx-file signed-pool-cert.tx

# Submit:
cardano-cli shelley transaction submit \
    --tx-file signed-pool-cert.tx \
    --testnet-magic 42

Done your pool is registered.

To check it you can you the following command:

# Get the Pool Id whihc is in the owner-delegation.cert
POOL_ID=$( tail -1 owner-delegation.cert | cut -c 6- )
echo $POOL_ID
# 5820d07e860c52860d92373893b27d6926e6610c925f905eba40d8e930004bf2dc44
shelley query ledger-state  --testnet-magic 42 | grep "poolPubKey" | grep  "$POOL_ID"
#                    "_poolPubKey": "d07e860c52860d92373893b27d6926e6610c925f905eba40d8e930004bf2dc44",

Delegates

The delegates are the stake holders who have some funds deposited and want to participate in staking. Therefore the steps for delegating stakes are the following:

  • Create stake key(s) for generating the delegate's reward address(es) for collecting their stake rewards.
  • Create payment key(s) for generating the delegate's payment address(es) for payments that will participate in stake delegation and also deposititing some funds.
  • Register stake address on the blockhain, with key deposit, which is required for participatin in staking and
  • Create and submit the stake delegation certificate for the selected pool.

Create delegate's staking keys and addresses

Stake address, derived from a stake verification key, is a simple reward (account) address which is not a payment address therefore it cannot be used as an output of a transaction. In the cardano-cli they use a CBOR format for preventing it to be added as the input into a transaction.

Keep in mind, that only the reward addresses and the base_, pointer and some script (not available yet) addresses can participate in the staking.

First, we need to create the relevant payment and stake keys and the related addresses for the delegate. The payment address for paying the transactions for sending the registration certificate (which is just simply the reward account address in some CBOR encoded format) to the chain.

# Delegate's staking/acount key, then Staking/Account address
############################################################
mkdir delegate && pushd delegate
cardano-cli shelley stake-address key-gen --verification-key-file stake.vkey --signing-key-file stake.skey

cardano-cli shelley stake-address build --staking-verification-key-file stake.vkey > stake.addr
cat stake.addr
#-------v 32 bytes key starts from here
8200582032a8c3f17ae5dafc3e947f82b0b418483f0a8680def9418c87397f2bd3d35efb
# It's a CBOR representation of the vkey
#82                                      # array(2)
#   00                                   # unsigned(0)
#   58 20                                # bytes(32)
#      32A8C3F17AE5DAFC3E947F82B0B418483F0A8680DEF9418C87397F2BD3D35EFB # 
# "2\xA8\xC3\xF1z\xE5\xDA\xFC>\x94\x7F\x82\xB0\xB4\x18H?\n\x86\x80\xDE\xF9A\x8C\x879\x7F+\xD3\xD3^\xFB"


# Delegates payment key -> payment address (a.k.a legacy UtxO a.k.a enterprise address).
# Ur use some address that already has some fund on it.
############################################################
cardano-cli shelley address build --payment-verification-key-file pay.vkey > pay.addr
cat pay.addr
# As a single Shelley UtXO address and (no CBOR repr)
# header(1) | address(32), so no hash224
# 0x61 = 0110 0001 || 0x47eb...2907 therefore an UtXO enterprise address
6147ebc8bf8714dcf6700ac482a5d42624ffca6afb51ae23930ea6591119a12907

####################################################################
# Generate the delegate's base address (0x01...) from 
# 1. the `pay.vkey` (used for enterprise address `0x61...`)
# 2. and from the `stake.key`
# It's a combination of the payment and reward address, with
# the 0b0000 0b0001, as a base address prefix
####################################################################
cardano-cli shelley address build \
    --payment-verification-key-file pay.vkey \
    --staking-verification-key-file stake.vkey \
    > stake.base

Generating the Staking key certificate

# First we need to generate the stake address registration
# certificate using the stake verification key
############################################################
cardano-cli shelley stake-address registration-certificate \
--staking-verification-key-file stake.vkey \
--out-file stake.cert

cat stake.cert
cbor-hex:
 18b482008200582032a8c3f17ae5dafc3e947f82b0b418483f0a8680def9418c87397f2bd3d35efb
# 18 B4 # unsigned(180)
# 
#82                                      # array(2)
#   00                                   # unsigned(0)
#   82                                   # array(2)
#      00                                # unsigned(0)
#      58 20                             # bytes(32)
#         32A8C3F17AE5DAFC3E947F82B0B418483F0A8680DEF9418C87397F2BD3D35EFB  
# "2\xA8\xC3\xF1z\xE5\xDA\xFC>\x94\x7F\x82\xB0\xB4\x18H?\n\x86\x80\xDE\xF9A\x8C\x879\x7F+\xD3\xD3^\xFB"

Registering the delegate's staking key on chain

The delegate's staking key needs to be registered in the blockchain, which just need a simple transaction using any payment address.

Keep, in mind that the any stake key registration certificates needs a deposit for the costs of tracking the key and the corresponding reward account. Also, it does not require any witness to register the certificate, but only the witness for the fees from the input of the transaction.

# Get param files
export CARDANO_NODE_SOCKET_PATH=/opt/cardano/fnf/sockets/node0.socket
cardano-cli shelley query protocol-parameters \
--testnet-magic 42 \
--out-file params.json

# 3. Calc tx fee
# You need only one singing keys included in fee calculation:
# 1. the `payment` address signing key of the input
# as the stake key reg cert does not need witness
# One UtxO is enough for the change, but I will move some fund from genesis to the delegates address
FEE=$(cardano-cli shelley transaction calculate-min-fee \
--protocol-params-file params.json \
--certificate stake.cert \
--tx-in-count 1 \
--tx-out-count 2 \
--ttl 500000 \
--testnet-magic 42 \
--signing-key-file /opt/cardano/fnf/addresses/genesis.skey \
| awk '{ print $2}')

# I will use the the genesis address as input for paying the fee.
#################################################################
FROM=$( cat /opt/cardano/fnf/addresses/genesis.addr )
# i.e. FROM=617190446876aed298ee207c6b5a335e832e2169a060b8167ef3ba9caff6fa3393


TX=$(cardano-cli shelley query utxo --testnet-magic 42 --address "$FROM"  | grep "^[^- ]" | sort -k 2n | tail -1)
UTXO=$( echo "$TX" | awk '{ print $1 }')
ID=$( echo "$TX" | awk '{ print $2 }')
BALANCE=$( echo "$TX" | awk '{ print $3 }')
INPUT="${UTXO}#${ID}"

# This 500K ADA amount is going to the delegates UtxO style address for its delegated stakes
TO=$(cat pay.addr)
AMOUNT=500000000000

OUTPUT1="${FROM}+${CHANGE}"
OUTPUT2="${TO}+${AMOUNT}"
# It also needs a key deposit specified in the genesis e.g.
# grep keyD
#    "keyDeposit": 400000,
#    "keyDecayRate": 0, Means the key won't decay, i.e. all money will
# get back when  the key is de0registered from the chain
KEYDEP=400000

# This means that change will less by 400K Lovelace that will be 
# probably (need to check) taken by the treasury 
CHANGE=$(( $BALANCE -  $FEE - $AMOUNT - $KEYDEP ))

echo "Balance: $BALANCE, Amount: "$AMOUNT",  Change: $CHANGE, runTxCalculateMinFee: $FEE"
echo "Input  : $INPUT"
echo "Output1: $OUTPUT1"
echo "Output2: $OUTPUT2"

# Build
cardano-cli shelley transaction build-raw \
	--tx-in "$INPUT" \
	--tx-out "${FROM}+${CHANGE}" \
	--tx-out "${TO}+${AMOUNT}" \
	--ttl 500000 \
	--fee "$FEE" \
	--tx-body-file stake-cert-tx
# Sign
cardano-cli shelley transaction sign \
    --tx-body-file stake-cert-tx \
    --signing-key-file /opt/cardano/fnf/addresses/genesis.skey \
    --signing-key-file stake.skey \
    --tx-file stake-cert-tx \
    --testnet-magic 42

# Submit
# Wait some minutes
# Get the stake address
# cut -c 9-  stake.addr 
# 32a8c3f17ae5dafc3e947f82b0b418483f0a8680def9418c87397f2bd3d35efb
STAKE_ADDR=$( cut -c 9-  stake.addr )

# Before 
export CARDANO_NODE_SOCKET_PATH=/opt/cardano/fnf/sockets/node0.socket 
cardano-cli shelley query ledger-state  --testnet-magic 42 | grep "$STAKE_ADDR"


cardano-cli shelley transaction submit \
    --tx-file signed-stake-key-registration.tx \
    --testnet-magic 42

# After 
cardano-cli shelley query ledger-state  --testnet-magic 42 | grep "$STAKE_ADDR"
#                        "contents": "32a8c3f17ae5dafc3e947f82b0b418483f0a8680def9418c87397f2bd3d35efb"
#                        "contents": "32a8c3f17ae5dafc3e947f82b0b418483f0a8680def9418c87397f2bd3d35efb"
#                        "contents": "32a8c3f17ae5dafc3e947f82b0b418483f0a8680def9418c87397f2bd3d35efb"

# Ready to delegate now.

Create a delegation certificate and submit to the network

# You can use aither some pool from the google's spreadsheet 
echo "type: Node operator verification key
title: Stake pool operator key
cbor-hex:
 5820<the 32 bytes length of the pool's operational verification key from the google sheet without the 5820 CBOR tag.>
 " > pool.vkey

# or delegate to your own pool by getting its `operational verifycation key` (the cold key)
# !! BE AWARE!! that the `stake.key` must have been already registered on the chain.
cardano-cli shelley stake-address delegation-certificate \
    --staking-verification-key-file stake.vkey \
    --stake-pool-verification-key-file ~/cold-keys/pool.vkey \
    --out-file pool-delegation.cert

####################################################################
####################################################################

# Calculate the minimum fee.
cardano-cli shelley transaction calculate-min-fee \
    --tx-in-count 1 \
    --tx-out-count 1 \
    --ttl 500000 \
    --testnet-magic 42 \
    --signing-key-file pay.skey \
    --signing-key-file stake.skey \
    --certificate pool-delegation.cert \
    --protocol-params-file params.json
# runTxCalculateMinFee: 172805
FEE=172805
# Get the intput and balance
cardano-cli shelley query utxo --testnet-magic 42 --address $(cat stake.base)
#                           TxHash                                 TxIx        Lovelace
#----------------------------------------------------------------------------------------
#1c089abfd6d56c73ac57aa94c403991041a383956f1f8fd4141a8e03a678a24c     0      499999260330

INPUT="1c089abfd6d56c73ac57aa94c403991041a383956f1f8fd4141a8e03a678a24c#0"
BAL=499999260330
CHANGE=$(( $BAL - $FEE))
# The new `base address`
OUTPUT="$( cat stake.base)+$CHANGE"

# Build
# Input: Your `base` payment address e.g. `stake.base` with "0x01...."
# Output: change back to the base address.
cardano-cli shelley transaction build-raw \
     --tx-in "$INPUT" \
     --tx-out "$OUTPUT" \
     --ttl 500000 \
     --fee "$FEE" \
     --tx-body-file pool-delegation.tx \
     --certificate pool-delegation.cert

# Sign
# You need 2 signing keys
# 1. the `pay.skey` for wittness the input and
# 2. the `staking signing key` for signing the delegation certificate.
cardano-cli shelley transaction sign \
    --tx-body-file pool-delegation.tx \
    --signing-key-file stake.skey \
    --signing-key-file pay.skey \
    --testnet-magic 42 \
    --tx-file signed-pool-delegation.tx

# Before

# Submit:
cardano-cli shelley transaction submit \
    --tx-file signed-pool-delegation.tx \
    --testnet-magic 42

# Done As less money is there.
# you need to wait two epochs to be receiving rewards
cardano-cli shelley query utxo --testnet-magic 42 --address $(cat stake.base)
#                           TxHash                                 TxIx        Lovelace
#----------------------------------------------------------------------------------------
#ba544d056f94e559076c0c7a0406f37ed7182a6d0fdc0cf2569498353f9dd797     0      499999087525
@ItFlyingStart
Copy link

Wow, what a good overview.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment