Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CIP-1856 | Collateral Key derivation #104

Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions CIP-1852/CIP-1852.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,12 @@ Example: `m / 1852' / 1815' / 0' / 0 / 0`

Here, `chain` can be the following

| Name | Value | Description
|----------------|-------|-------------
| External chain | `0` | Same as defined in [BIP44](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki)
| Internal chain | `1` | Same as defined in [BIP44](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki)
| Staking Key | `2` | See [CIP11](../CIP-0011)
| Name | Value | Description
|--------------------|-------|-------------
| External chain | `0` | Same as defined in [BIP44](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki)
| Internal chain | `1` | Same as defined in [BIP44](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki)
| Staking Key | `2` | See [CIP11](../CIP-0011)
| Collateral Account | `3` | See [CIP11](../CIP-???)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tentatively CIP-0027


Wallets **MUST** implement this new scheme using the master node derivation algorithm from Icarus with sequential addressing (see [CIP3](../CIP-0003) for more information)
Copy link
Contributor

@refi93 refi93 Jan 18, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this requirement isn't currently feasible for Ledger (without the Ledger devs updating the firmware which is closed source) as the Cardano app doesn't have control over the master node derivation (and that's why it wasn't compliant with Icarus so far), or is this paragraph just meant to clarify that the collateral account key has to be derived in the same way as the standard account key was derived so far by given wallet type (Ledger/Trezor/Icarus wallets)? The latter would require significantly less effort given it would be consistent with the current status of key derivations

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure this way of treating collateral is relevant any longer. Babbage will come with collateral outputs
https://hydra.iohk.io/build/11759383/download/1/babbage-changes.pdf
and then collateral does not need to be treated separately, any utxos (without datum hashes) would do as collateral inputs, even those including tokens.


Expand Down
106 changes: 106 additions & 0 deletions CollateralAccount/CollateralAccount.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
---
CIP: ?
Copy link
Contributor

@crptmppt crptmppt Aug 11, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tentatively CIP-1856

Title: Collateral Account for HD Wallets
SebastienGllmt marked this conversation as resolved.
Show resolved Hide resolved
Authors: Sebastien Guillemot <seba@dcspark.io>
Comments-URI: https://forum.cardano.org/t/collateral-account-derivation/65879
Status: Draft
Type: Standards
Created: 2021-06-29
License: CC-BY-4.0
---

# Abstract

This document describes using a separate derivation path to ensure there is always sufficient collateral to execute UTXO smart contracts

# Motivation

Collateral input | As of Alonzo, transactions that call non-native smart contracts are required to put up collateral to cover the potential cost of smart contract execution failure. Inputs used as collateral has the following properties:
SebastienGllmt marked this conversation as resolved.
Show resolved Hide resolved

- Cannot contain any tokens (only ADA)
- Cannot be a script address
- Must be a UTXO input
- Must be at least some percentage of the fee in the tx (concrete percentage decided by a protocol parameter)
- Can be the same UTXO entry as used in regular tx input
- Is consumed entirely (no change) if the contract execution fails during phase 2 validation
SebastienGllmt marked this conversation as resolved.
Show resolved Hide resolved

We therefore need a way for the wallet to handle picking which inputs to use for collateral
SebastienGllmt marked this conversation as resolved.
Show resolved Hide resolved

## Naive solution

The naive solution would do the following steps
1. Add any regular input that satisfies the constraints as collateral as well
SebastienGllmt marked this conversation as resolved.
Show resolved Hide resolved
1. If collateral is still insufficient, look at the wallet UTXO for any other entry that can be added as collateral
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Later in this CIP, if I understood correctly, it is implied that light wallets have no way to know how much of collateral is actually needed so they have to select all utxo in collateral account and at best provide some guesses of how much of collateral would be needed - which then means here in the naive solution the step of accessing whether the selected collateral is sufficient or not is impossible at all.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to the specs collateral is a function of the tx fee, so it can be computed beforehand.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Collateral is not an explicit field in transactions -- it's calculated based on the tx fee which depends on the amount you include as part of the witness for each redeemer script.

Copy link
Contributor

@vsubhuman vsubhuman Jun 29, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, but the problem then is that the correct fee would depend on the execution units then as well, so if I'm getting it right, rather than knowing the correct collateral from knowing the correct fee, a wallet that has no access to a local personal full-node would not be able to correctly get neither the fee, nor the collateral 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that's correct. That's why there is talk about trying to get the PAB to run in the browser so it can be included as part of light wallets. Otherwise the best you can do is trust some 3rd party to tell the truth about the cost of running the contract and risk losing collateral if they lied.

Copy link
Contributor

@dcoutts dcoutts Jun 29, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are two independent issues:

  1. A wallet does need some information from the chain to be able to construct a transaction. It needs to know the UTxOs that make up the user's wallet so it can do coin selection. It needs to know the value of a few protocol parameters etc. Based on that it can work out the executions and fees for the transaction it builds. The hash of the relevant parameters (price of execution units etc) is included in the tx body and is checked in phase one, and thus no collateral can be lost.

  2. Collateral needs to be supplied to cover the fees. Note that these are the fees that are actually declared. So again, if you get the fees wrong then the transaction is simply rejected and no collateral is taken.

The only way to arrange to have your collateral taken is to calculate the execution units incorrectly, but to include the correct protocol parameters into the transaction body. That is you cannot get this wrong by 3rd parties lying to you about current protocol parameters. You have to do something really wrong.

Ah, but the problem then is that the correct fee would depend on the execution units then as well,

Yes.

so if I'm getting it right, rather than knowing the correct collateral from knowing the correct fee, a wallet that has no access to a local personal full-node would not be able to correctly get neither the fee, nor the collateral

A wallet needs some information from the chain like the wallet's UTxO, and the values of some of the current protocol parameters. If you're thinking about a light wallet and a compromised server lying to you, then there's no problem: because the hash of the relevant protocol parameters is included in the tx body and checked by the ledger rules in phase 1, you will not loose collateral if you were given the wrong protocol parameter values, or if the values changed before the tx is submitted.

Yes, that's correct. That's why there is talk about trying to get the PAB to run in the browser so it can be included as part of light wallets. Otherwise the best you can do is trust some 3rd party to tell the truth about the cost of running the contract and risk losing collateral if they lied.

No. Unless there's a design mistke here that I am not aware of then I don't think you can lose collateral if the server lies. Provided that your local wallet can run the scripts locally then the only reason to loose collateral is bugs in the wallet. You do not need the whole PAB to be able to run scripts. There are more lightweight libraries that can do that. For example the CLI will do this using the Cardano API library.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dcoutts what other lightweight libraries can do that? by "Cardano API" you mean cardano-wallet?

Provided that your local wallet can run the scripts locally

I must be missing something but I'm not sure how a pure JS wallet like Yoroi will be able to do this. If a light wallet needs to rely on a remote node every time it needs to recompute the fees and re-validate a smart-contract tx, this doesn't translates into a great UX.

I'm also confused because you mention that the wallet only needs to know its UTXO set and some protocol parameters in order to compute the execution units, but then you mention that the wallet needs to run the scripts locally, which sound like a big additional requirement.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so if I'm getting it right, rather than knowing the correct collateral from knowing the correct fee, a wallet that has no access to a local personal full-node would not be able to correctly get neither the fee, nor the collateral

A wallet needs some information from the chain like the wallet's UTxO, and the values of some of the current protocol parameters. If you're thinking about a light wallet and a compromised server lying to you, then there's no problem: because the hash of the relevant protocol parameters is included in the tx body and checked by the ledger rules in phase 1

@dcoutts , yes, but the main point is specifically about whether it is 100% guaranteed already that all wallets will be able to run scripts locally to validate their execution and calculate the execution points?

You do not need the whole PAB to be able to run scripts. There are more lightweight libraries that can do that. For example the CLI will do this using the Cardano API library.

Is this planned to be compatible with light wallets, e.g. allowing to run any script from any user, without having an instance of a wallet created locally?

1. If there are not enough UTXO entries that can be used as collateral, check if we can refactor the wallet UTXO to create enough UTXO entries that match the requirement
1. If refactoring can unblock the wallet, prompt the user to send a transaction to refactor their UTXO (and pay the tx fee associated with it) before sending their transaction. If refactoring can't unblock the wallet, tell the user they will need more ADA to call this smart contract
SebastienGllmt marked this conversation as resolved.
Show resolved Hide resolved

This however, causes the following problems:
1. This may cause users to risk more collateral than they are comfortable with. In general, software should run smart contracts locally to detect if a transaction would fail before sending and alert the user to avoid consuming the collateral, but relying on this is not ideal.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When we were discussing collateral inputs, we were thinking that there might indeed be only one collateral UTxO, and that most transactions would be over-collateralised. I don't think relying on this is particularly risky. Firstly, we expect that most transactions spending from script-locked addresses will be submitted by the PAB, and hence already verified. Secondly, with IntersectMBO/ouroboros-network#3230 we expect the local node to reject submitted transactions that fail phase-2 validation.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unless you are running your own node, there is no guarantee anybody is setting this flag.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't follow.

It's quite simple: if your wallet is working correctly then you will never ever have any collateral taken. The local node that you submit your transaction two is just an extra double-check on this. So it should be really very safe indeed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would put this much more strongly:

Wallets must run scripts locally to determine that they do not fail and how many execution units they need. This is a crucial part of the function of a wallet supporting scripts. They should not construct or submit invalid transactions.

Copy link

@francisluz francisluz Jun 29, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would make sense, have to describe the best practices like you're mentioning about running your own node?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no reason why a good-faith user should ever end up submitting a transaction with failing scripts. So the only people who are ever at risk of losing their collateral are malicious users or people who've inexplicably decided to go to some trouble to not check their transactions before sending them.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about light wallets or hosted APIs, where the operator of the service does not want to consume its computational resources but instead wants to delegate this responsibility to the user?

Copy link
Contributor

@GeorgeFlerovsky GeorgeFlerovsky Jul 7, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we really categorically rule out that wallets and PAB will never send transactions with failing scripts? Should the user pay with an overly large collateral utxo in case of a wallet/PAB bug?

I've lost my fair share of collateral on the Alonzo Blue testnet (using Cardano CLI) :)

Currently, Plutus.evaluateScriptCounting is giving me an Ex Budget that is too low to succeed when submitted in a transaction to the testnet. I've had to multiply it by a factor of ~20X to stop losing collateral in the transaction.

https://github.com/input-output-hk/Alonzo-testnet/blob/8b4e51fb849ffc0fa2801d267a93438ba5f1e0eb/resources/plutus-sources/plutus-alwayssucceeds/app/plutus-alwayssucceeds.hs

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The testnet node currently accepts transactions with failing scripts and posts them to the network as failures. That will be fixed before mainnet.

1. Although the refactor transaction can be created under the hood for in-software wallet, it will confused users when it shows up on their transaction history. For hardware wallets, it will require explicit approval from the user which is also possibly confusing.
1. Altough wallets can try and always pick UTXOs to make sure there is always a valid UTXO entry for collateral, it can't be guaranteed because the wallet state can always be changed by any dApp or other wallet that doesn't use the same logic to guarantee the presence of satisfactory collateral input
1. Multisig wallets don't have any non-script addresses in general and so would need some separate solution

So with this, we can see the naive solution is complicated while still having issues and an unintuitive user experience.



# Specification

Recall that [CIP1852](../CIP-1852) specifies the following derivation path

```
m / purpose' / coin_type' / account' / chain / address_index
```

We set `chain=3` to indicate the *collateral chain*.

## *address_index* value

Wallets MUST only use `address_index=0` for this specification. Since a single address can contain multiple UTXO entries, there is no need to derive other addresses (using more addresses would not provide any privacy benefit and would complicate address discovery).

We will call this specific derivation the *collateral account*.
SebastienGllmt marked this conversation as resolved.
Show resolved Hide resolved

## New solution for managing collateral

Wallets SHOULD only use UTXO entries of the collateral account as collateral in the transaction. If the collateral is insufficient, the wallet should tell the user to send more ADA to their collateral account.

The benefits of this solution are as follows:
1. Transactions in the history to add collateral can be clearly marked as such by wallet software.
1. Prompting the user to add ADA to their collateral account doesn't require explaining users about how UTXO works under the hood compared to the refactoring option.
1. No change required to input selection algorithms
1. Multisig (or other script-based wallets) are handled the same way as regular wallets
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you should elaborate on how this proposal interacts with multi-sig wallets since it is not clear.

Do the collateral addresses just belong to one party? So this is equivalent of the submitting party having a second personal account (which is of course the primary alternative solution).

1. User only risks as much collateral as their are comfortable with
Copy link
Contributor

@refi93 refi93 Aug 17, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have one general concern regarding hw wallets - hw wallets don't have the context to safely assure the user what is the collateral amount of the input(s) included as it isn't part of the collateral field when serialized in the transaction and the hw wallet inherently can't trust the software wallet to not include a collateral input too big or from a non-collateral address. hw wallets neither have the capacity to be able to reasonably validate the script to assure that the collateral wouldn't be spent.

The only possible way I can think of to assure the user that the input they are including as collateral is of a certain amount would be letting the hw wallet parse the transaction from which the collateral input came which would be a significant complication as hw wallets would have to be able to parse all possible tx bodies with forward compatibility in mind


However, this solution also comes with downsides:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should mention the UX downside that this means users have to be aware of a whole new concept: a collateral address, and need to manually move funds into it which are not normally spendable. Are those collateral funds part of your balance or not?

Whereas with the "naive" solution, there are no new concepts for users. There are already rare corner cases where wallets have to rearrange the UTxO to be able to perform certain transactions, and this is visible in the transaction history and for hardware wallet users. Such rearranging transactions are (in principle) already easily identifiable by both software and hardware wallets because all the input and output addresses are within the wallet. So this is already in the UX, but is fortunately rare. There's no clear reason to think that the new corner cases here would be any more problematic.

Copy link
Contributor Author

@SebastienGllmt SebastienGllmt Jun 30, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we decide we don't want to explicitly tell the users about the collateral address existence, that's fine. It can be like how we have external & internal addresses without the user really knowing about their existence.

but is fortunately rare

I don't think this is that rare. When I was working at EMURGO we usually had a few support tickets about this topic per day due to NFTs and the presence of tokens will only increase going forward -- especially with Alonzo


1. Reusing the same collateral account for all your smart contract calls gets rid of any privacy. However, base addresses in Cardano already forgo privacy and so users who want to call smart contracts with privacy will already need to handle things differently.
SebastienGllmt marked this conversation as resolved.
Show resolved Hide resolved
1. The blockchain can't stop people from sending tokens to somebody's collateral account. This doesn't harm the user (since other UTXO entries can still be used) and wallets will already need to implement a way for the user to withdraw from their collateral account so the impact should be minimal.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this happen you would likely have to pay a small fee to transfer from collateral to main account? Whatever the protocol minimum parameters dictate?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that's correct

1. It's possible for the collateral account to contained mangled addresses (same as regular base addresses for the wallet), but empirically mangled addresses are rare and people should not be sending to collateral accounts directly anyway so this is of minimal concern
1. Support for a collateral account needs to be added to hardware wallets
1. If the user doesn't reduce the ADA in their collateral account when calling cheaper smart contracts, they are still be putting up more collateral than necessary

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like there could be simple improvements to handle this, maybe some mechanism to take an average of collateral within the network to help users better 'forecast' what collateral they might need so they can plan ahead and not use more than necessary.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, wallets should also make a suggestions for how much to put in for common use cases. Something like "use DEXs often? Put this much in and you'll usually be fine!". We can warn them before they make a smart contract call to add more collateral, but it's ideal if they just set some amount upfront for their usage pattern and forget about it

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The proposal implies wallets would always select all "pure" UTxO available on the collateral account?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably best not to select more than required because otherwise you're increasing the tx fee for no reason. Additionally, there's a limit on the number of UTXO entries you can add as collateral.


## Test vectors

recovery phrase
```
prevent company field green slot measure chief hero apple task eagle sunset endorse dress seed
```

collateral private key (including chaincode) for `m / 1852' / 1815' / 0' / 3 / 0`
```
40c7f7d3c03c3711e6c03ef828ba244f40f81ec915899483eda006bac0e5974480b77fe9816eb518cb190214b7368e76e3462a0caecfb1d3add8315bfe2e5616647312b7b6d29e0e577b9923594a12be4ded5f5e3a8f7d5249f33c97ecafa620
```

staking private key (including chaincode) for `m / 1852' / 1815' / 0' / 2 / 0`
```
b8ab42f1aacbcdb3ae858e3a3df88142b3ed27a2d3f432024e0d943fc1e597442d57545d84c8db2820b11509d944093bc605350e60c533b8886a405bd59eed6dcf356648fe9e9219d83e989c8ff5b5b337e2897b6554c1ab4e636de791fe5427
```

base address (with `network_id=1`)
```
addr1qy85lw87w0q6xns59y806v37xh6dafnf3w6kkn6x3p4pzsqwfdvw69hjqdklg9x94f8wxwlkldzsd8ycmxsj06904p9skhtxnm
```

## Copyright

This CIP is licensed under [CC-BY-4.0](https://creativecommons.org/licenses/by/4.0/legalcode)