From 641b3b8986ad0ef7abad4abbef79e31b6306c6fc Mon Sep 17 00:00:00 2001 From: tweakch Date: Fri, 16 Jul 2021 14:58:06 +0200 Subject: [PATCH] add guide multi-witness transactions --- .../multi-witness-transactions-cli.md | 391 ++++++++++++++++++ sidebars.js | 1 + .../multi-witness-transaction.png | Bin 0 -> 16099 bytes 3 files changed, 392 insertions(+) create mode 100644 docs/integrate-cardano/multi-witness-transactions-cli.md create mode 100644 static/img/integrate-cardano/multi-witness-transaction.png diff --git a/docs/integrate-cardano/multi-witness-transactions-cli.md b/docs/integrate-cardano/multi-witness-transactions-cli.md new file mode 100644 index 0000000000..3d4be00f04 --- /dev/null +++ b/docs/integrate-cardano/multi-witness-transactions-cli.md @@ -0,0 +1,391 @@ +--- +id: multi-witness-transactions-cli +title: Multi-witness transactions +sidebar_label: Multi-witness transactions +description: This article explains how you can create multi witness transactions using the cardano-cli. +image: ./img/og-developer-portal.png +--- +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +## Overview + +:::note + +This guide assumes that you have completed the [Exploring Cardano Wallets](/docs/integrate-cardano/creating-wallet-faucet) guide. You will need one UTxO sitting at each of the wallets (`payment1.addr` and `payment2.addr`) to complete this guide. + +This guide also assumes that you have `cardano-node` running in the background and connected to the `testnet` network. + +::: + +### Recap + +Let's recap what we did so far. Our goal in the [previous guide](/docs/integrate-cardano/creating-wallet-faucet) was to draw `1000 tADA` from the testnet faucet and send `250 tADA` from **payment1** to **payment2**. + +Make sure we are in the correct folder. + +```bash +$ pwd +/home/user/cardano +``` + + + + + +We drew `1000 tADA` from the Testnet Faucet into our **payment1** wallet. + +```bash +$ cardano-cli query utxo \ +--testnet-magic 1097911063 \ +--address $(cat keys/payment1.addr) + TxHash TxIx Amount +-------------------------------------------------------------------------------------- +264c0aa805652e3607c5ea2b1e8a9f3bf9c3bc8d4d938e1a9035f352083ba703 0 1000000000 lovelace +``` + + + + +We used `protocol-parameters` to draft our transaction and calculated the expected fee. + +```bash +$ cardano-cli query protocol-parameters \ +--testnet-magic 1097911063 \ +--out-file protocol.json +``` + +```bash +$ cardano-cli transaction build-raw \ +--tx-in 264c0aa805652e3607c5ea2b1e8a9f3bf9c3bc8d4d938e1a9035f352083ba703#0 \ +--tx-out $(cat keys/payment2.addr)+0 \ +--tx-out $(cat keys/payment1.addr)+0 \ +--fee 0 \ +--out-file tx.draft +``` + +```bash {8} +$ cardano-cli transaction calculate-min-fee \ +--tx-body-file tx.draft \ +--tx-in-count 1 \ +--tx-out-count 2 \ +--witness-count 1 \ +--testnet-magic 1097911063 \ +--protocol-params-file protocol.json +174169 Lovelace +``` + + + + +From the expected fee of `174169 Lovelace`, we were able to calculate the outputs and build our transaction. + +```bash {3,4,5} +cardano-cli transaction build-raw \ +--tx-in 264c0aa805652e3607c5ea2b1e8a9f3bf9c3bc8d4d938e1a9035f352083ba703#0 \ +--tx-out $(cat keys/payment2.addr)+250000000 \ +--tx-out $(cat keys/payment1.addr)+749825831 \ +--fee 174169 \ +--out-file tx.draft +``` + +:::note + +Your fees might have been different hence you would have different amounts. + +::: + + + + +We used `payment1.skey` to sign our transaction and submitted it to the blockchain. + +```bash {3} +cardano-cli transaction sign \ +--tx-body-file tx.draft \ +--signing-key-file keys/payment1.skey \ +--testnet-magic 1097911063 \ +--out-file tx.signed + +cardano-cli transaction submit \ +--tx-file cardano/tx.signed \ +--testnet-magic 1097911063 +``` + +```bash +Transaction successfully submitted. +``` + + + + +Finally we verified the transaction by querying the **payment1** and **payment2** wallets. + +```bash +$ cardano-cli query utxo \ +--testnet-magic 1097911063 \ +--address $(cat keys/payment1.addr) + TxHash TxIx Amount +-------------------------------------------------------------------------------------- +b73b7503576412219241731230b5b7dd3b64eed62ccfc3ce69eb86822f1db251 1 749825831 lovelace +``` + +```bash +$ cardano-cli query utxo \ +--testnet-magic 1097911063 \ +--address $(cat payment2.addr) + TxHash TxIx Amount +-------------------------------------------------------------------------------------- +b73b7503576412219241731230b5b7dd3b64eed62ccfc3ce69eb86822f1db251 0 250000000 lovelace +``` + + + + +We currently have `749.825831 tADA` in our **payment1** wallet and `250 tADA` in our **payment2** wallet. + +Let's see how we can spend it all at once! + +## Use case + +There are many possible reasons why you would want to have multiple wallets sending their ADA in a single transaction. One is, you own two wallets (**payment1** and **payment2**) and you want to spend it on something that... + +* costs more than you have in any of your two wallets, +* but **both amounts combined** would cover the costs. + +Let's say you are at the **bike store** and you see a nice bike with a price tag of `1100 tADA` on it. You only have `999 tADA` (plus change) left. + +The bike store owner - *a devious blockchain enthusiast* - is willing to give you a 10% discount, if you manage to **pay him in a single transaction** + +> *There has to be no change, buddy!* --Bike Store Owner + +So we need to make sure to spend all our `tADA` from our two wallets in a single transaction. + +:::note + +He can easily verify if we spent all our money by checking if the transaction has more than one output. + +There are ways to optimize the amount you spend. We will leave this for you to figure out yourself. + +::: + +## Technical Flow + +This scenario is pretty straight forward and looks like this. + +![img](../../static/img/integrate-cardano/multi-witness-transaction.png "Multi witness flow") + +As you can see in the diagram above, we will build and submit a **multi-witness transaction**, having *two inputs* and only *one output*. + +:::note + +We can't do this with `cardano-wallet`, or any other wallet like Daedalus or Yoroi because we will need both `signing-keys` from **payment1** and **payment2** to sign the transaction. + +::: + +:::info + +Once available on the mainnet, we will show how to do this using [smart contracts](/docs/get-started/smart-contracts-signpost). + +::: + +## Time to code + +:::note + +As mentioned above, this guide assumes you completed the [Exploring Cardano Wallets](/docs/integrate-cardano/creating-wallet-faucet) guide.
+We also assume you paid `174169 Lovelace` in transaction fees and that your current balances are: + +* **payment1**: `749825831 Lovelace` +* **payment2**: `250000000 Lovelace` + +::: + +### Create a store-owner wallet + +If you don't already have a third wallet to use for this guide, let's create one where we can transfer all our funds to. + +Make sure you are inside the `keys` directory like so: `cd /home/user/cardano/keys` + +Generate a **payment key-pair** using `cardano-cli`: + +```bash +cardano-cli address key-gen \ +--verification-key-file /home/user/cardano/keys/store-owner.vkey \ +--signing-key-file /home/user/cardano/keys/store-owner.skey +``` + +Then generate a **wallet address** for the `testnet` network: + +```bash +cardano-cli address build \ +--payment-verification-key-file /home/user/cardano/keys/store-owner.vkey \ +--out-file /home/user/cardano/keys/store-owner.addr \ +--testnet-magic 1097911063 +``` + +Check your `keys` directory. It should look something like this: + +```bash +/home/user/cardano/keys/ +├── store-owner.addr +├── store-owner.skey +├── store-owner.vkey +├── payment1.addr +├── payment1.skey +├── payment1.vkey +├── payment2.addr +├── payment2.skey +└── payment2.vkey + +0 directories, 9 files +``` + +### Calculate the transaction fee + +Lets create a directory and enter it store our transactions: + +```bash +mkdir -p /home/user/cardano/multi-witness-sample && cd $_; +``` + +We want to send **all our tADA** sitting at the two UTxO we verified [before](#recap) and send it to the `store-owner.addr`. That means we will have **two inputs**. + +What about the outputs? Well, the *devious store-owner* wants us to spend it all, so there will be **one output to the store-owner** and **zero outputs to us**. Remember? *"...no change, buddy!"* + +We can calculate the fees for such a transaction like so. + +```bash +cardano-cli transaction build-raw \ +--tx-in b73b7503576412219241731230b5b7dd3b64eed62ccfc3ce69eb86822f1db251#0 \ +--tx-in b73b7503576412219241731230b5b7dd3b64eed62ccfc3ce69eb86822f1db251#1 \ +--tx-out $(cat ../keys/store-owner.addr)+0 \ +--fee 0 \ +--out-file tx2.draft +``` + +This will create our transaction in `tx2.draft` from which we can calculate the fee + +```bash {8} +cardano-cli transaction calculate-min-fee \ +--tx-body-file tx2.draft \ +--tx-in-count 2 \ +--tx-out-count 1 \ +--witness-count 2 \ +--testnet-magic 1097911063 \ +--protocol-params-file ../protocol.json +179581 Lovelace +``` + +Now we can calculate the amount that the store-owner wallet will receive, if both UTxO are spent during the transaction: + +```text + 749825831 (payment1) ++ 250000000 (payment2) + --------- + 999825831 +- 179581 (fee) + --------- + 999646250 (store-owner) + ========= +``` + +### Build, sign and submit transaction + +Now we can build, sign and submit our tx2.draft transaction to include the output amount and the fee. + +```bash +cardano-cli transaction build-raw \ +--tx-in b73b7503576412219241731230b5b7dd3b64eed62ccfc3ce69eb86822f1db251#0 \ +--tx-in b73b7503576412219241731230b5b7dd3b64eed62ccfc3ce69eb86822f1db251#1 \ +--tx-out $(cat ../keys/store-owner.addr)+999646250 \ +--fee 179581 \ +--out-file tx2.draft + +cardano-cli transaction sign \ +--tx-body-file tx2.draft \ +--signing-key-file ../keys/payment1.skey \ +--signing-key-file ../keys/payment2.skey \ +--testnet-magic 1097911063 \ +--out-file tx2.signed + +cardano-cli transaction submit \ +--tx-file tx2.signed \ +--testnet-magic 1097911063 +``` + +### Verify multi-witness transactions + +The devious store-owner will now verify that everything went according to his plan. + +```bash +cardano-cli query utxo \ +--testnet-magic 1097911063 \ +--address $(cat /home/user/cardano/keys/store-owner.addr) + TxHash TxIx Amount +-------------------------------------------------------------------------------------- +258abd628eef7d6ff0f7b4e6866b4f7c21065f4d6b5e49b51e2ac4ff035ad06f 0 999646250 lovelace +``` + +Verify [258abd628eef7d6ff0f7b4e6866b4f7c21065f4d6b5e49b51e2ac4ff035ad06f](https://explorer.cardano-testnet.iohkdev.io/en/transaction?id=258abd628eef7d6ff0f7b4e6866b4f7c21065f4d6b5e49b51e2ac4ff035ad06f) on the cardano testnet explorer + +:::tip Success! + +He can see that the transaction has one output to his wallet. No other outputs, hence you must have spent all of your `tADA`. + +::: + +Congratulations, you are now able to submit **multi-witness transactions on Cardano**. This should help you bring integrations to your existing or new upcoming applications. 🎉🎉🎉 + + diff --git a/sidebars.js b/sidebars.js index 7ca2171a0d..5f7b48a360 100644 --- a/sidebars.js +++ b/sidebars.js @@ -41,6 +41,7 @@ module.exports = { "Integrate Cardano": [ "integrate-cardano/overview", "integrate-cardano/creating-wallet-faucet", + "integrate-cardano/multi-witness-transactions-cli", "integrate-cardano/listening-for-payments-cli", "integrate-cardano/listening-for-payments-wallet" ], diff --git a/static/img/integrate-cardano/multi-witness-transaction.png b/static/img/integrate-cardano/multi-witness-transaction.png new file mode 100644 index 0000000000000000000000000000000000000000..c26c0626429a0bc832b7d578cc00adebcf92fbf9 GIT binary patch literal 16099 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 literal 0 HcmV?d00001