-
Notifications
You must be signed in to change notification settings - Fork 320
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-0030: update to api.signData() #148
Changes from all commits
0a0900d
a748442
a3ac380
4dc5beb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,6 +28,10 @@ The API specified in this document will count as version 0.1.0 for version-check | |
|
||
## Data Types | ||
|
||
### Address | ||
|
||
A string represnting an address in either bech32 format, or hex-encoded bytes. All return types containing `Address` must return the bech32 format, but must accept either format for inputs. | ||
|
||
### Bytes | ||
|
||
A hex-encoded string of the corresponding bytes. | ||
|
@@ -37,6 +41,15 @@ A hex-encoded string of the corresponding bytes. | |
A hex-encoded string representing [CBOR](https://tools.ietf.org/html/rfc7049) corresponding to `T` defined via [CDDL](https://tools.ietf.org/html/rfc8610) either inside of the [Shelley Mult-asset binary spec](https://github.com/input-output-hk/cardano-ledger-specs/blob/0738804155245062f05e2f355fadd1d16f04cd56/shelley-ma/shelley-ma-test/cddl-files/shelley-ma.cddl) or, if not present there, from the [CIP-0008 signing spec](https://github.com/cardano-foundation/CIPs/blob/master/CIP-0008/CIP-0008.md). | ||
This representation was chosen when possible as it is consistent across the Cardano ecosystem and widely used by other tools, such as [cardano-serialization-lib](https://github.com/Emurgo/cardano-serialization-lib), which has support to encode every type in the binary spec as CBOR bytes. | ||
|
||
### DataSignature | ||
|
||
``` | ||
type DataSignature = {| | ||
signature:cbor\<COSE_Sign1>, | ||
key: cbor\<COSE_Key>, | ||
|}; | ||
``` | ||
|
||
### TransactionUnspentOutput | ||
|
||
If we have CBOR specified by the following CDDL referencing the Shelley-MA CDDL: | ||
|
@@ -93,7 +106,6 @@ DataSignErrorCode { | |
ProofGeneration: 1, | ||
AddressNotPK: 2, | ||
UserDeclined: 3, | ||
InvalidFormat: 4, | ||
} | ||
type DataSignError = { | ||
code: DataSignErrorCode, | ||
|
@@ -104,7 +116,6 @@ type DataSignError = { | |
* ProofGeneration - Wallet could not sign the data (e.g. does not have the secret key associated with the address) | ||
* AddressNotPK - Address was not a P2PK address and thus had no SK associated with it. | ||
* UserDeclined - User declined to sign the data | ||
* InvalidFormat - If a wallet enforces data format requirements, this error signifies that the data did not conform to valid formats. | ||
|
||
### PaginateError | ||
|
||
|
@@ -203,25 +214,25 @@ Errors: `APIError` | |
|
||
Returns the total balance available of the wallet. This is the same as summing the results of `api.getUtxos()`, but it is both useful to dApps and likely already maintained by the implementing wallet in a more efficient manner so it has been included in the API as well. | ||
|
||
### api.getUsedAddresses(paginate: Paginate = undefined): Promise\<cbor\<address>[]> | ||
### api.getUsedAddresses(paginate: Paginate = undefined): Promise\<Address[]> | ||
|
||
Errors: `APIError` | ||
|
||
Returns a list of all used (included in some on-chain transaction) addresses controlled by the wallet. The results can be further paginated by `paginate` if it is not `undefined`. | ||
|
||
### api.getUnusedAddresses(): Promise\<cbor\<address>[]> | ||
### api.getUnusedAddresses(): Promise\<Address[]> | ||
|
||
Errors: `APIError` | ||
|
||
Returns a list of unused addresses controlled by the wallet. | ||
|
||
### api.getChangeAddress(): Promise\<cbor\<address>> | ||
### api.getChangeAddress(): Promise\<Address> | ||
|
||
Errors: `APIError` | ||
|
||
Returns an address owned by the wallet that should be used as a change address to return leftover assets during transaction creation back to the connected wallet. This can be used as a generic receive address as well. | ||
|
||
### api.getRewardAddresses(): Promise\<cbor\<address>[]> | ||
### api.getRewardAddresses(): Promise\<Address[]> | ||
|
||
Errors: `APIError` | ||
|
||
|
@@ -233,13 +244,25 @@ Errors: `APIError`, `TxSignError` | |
|
||
Requests that a user sign the unsigned portions of the supplied transaction. The wallet should ask the user for permission, and if given, try to sign the supplied body and return a signed transaction. If `partialSign` is true, the wallet only tries to sign what it can. If `partialSign` is false and the wallet could not sign the entire transaction, `TxSignError` shall be returned with the `ProofGeneration` code. Likewise if the user declined in either case it shall return the `UserDeclined` code. Only the portions of the witness set that were signed as a result of this call are returned to encourage dApps to verify the contents returned by this endpoint while building the final transaction. | ||
|
||
### api.signData(addr: cbor\<address>, sigStructure: cbor\<Sig_structure>): Promise\<Bytes> | ||
### api.signData(addr: Address, payload: Bytes): Promise\<DataSignature> | ||
|
||
Errors: `APIError`, `DataSignError` | ||
|
||
This endpoint is due to be updated/finalized soon, see [discussion in the initial PR](https://github.com/cardano-foundation/CIPs/pull/88#issuecomment-954436243). | ||
This endpoint utilizes the [CIP-0008 signing spec](https://github.com/cardano-foundation/CIPs/blob/master/CIP-0008/CIP-0008.md) for standardization/safety reasons. It allows the dApp to request the user to sign a payload conforming to said spec. The user's consent should be requested and the message to sign shown to the user. The payment key from `addr` will be used for base, enterprise and pointer addresses to determine the EdDSA25519 key used. The staking key will be used for reward addresses. This key will be used to sign the `COSE_Sign1`'s `Sig_structure` with the following headers set: | ||
|
||
* `alg` (1) - must be set to `EdDSA` (-8) | ||
* `kid` (4) - Optional, if present must be set to the same value as in the `COSE_key` specified below. It is recommended to be set to the same value as in the `"address"` header. | ||
* `"address"` - must be set to the raw binary bytes of the address as per the binary spec, without the CBOR binary wrapper tag | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @SebastienGllmt this is what I understood from the CIP-8 spec but it doesn't explicitly say which format to use. here's the quote:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What does "without the CBOR binary wrapper tag" mean? So in case of the serialization-lib, when I convert the addres to bytes, would that be correct or does that contain any CBOR tag? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wanted to write it without referring to any specific library. There are a couple crypto-related things in cardano-serialization-lib that have their EDIT: So on that point, with your code like protectedHeaders.set_header(
Loader.Message.Label.new_text('address'),
Loader.Message.CBORValue.new_bytes(Buffer.from(address, 'hex'))
); it would be an issue (CIP-8/CIP-30-wise) as due to how CIP-30 defines let someAddress = Address.from_bech32("addr1u8pcjgmx7962w6hey5hhsd502araxp26kdtgagakhaqtq8sxy9w7g");
protectedHeaders.set_header(
Loader.Message.Label.new_text('address'),
Loader.Message.CBORValue.new_bytes(someAddress.to_bytes())
); It would be fine (CIP-8/CIP-30 wise). We're going to have to take a second look at any hash/address/key in the CIP-30 spec now. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I made an issue in the serialization lib to discus this Emurgo/cardano-serialization-lib#263 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
How is this different? You use to_bytes() here also, which gives you the same result as when just taking the address directly in hex/bytes?
I think many assume here it's simply the address in hex format the cardano ledger takes. If it's not truly cbor, then we should change the definition in CIP-30. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. About addresses: API consistency is better indeed so, if the rest already works with Base16 then let's stick to it. CBOR here is bonkers though. Alternatively, it wouldn't be much more complicated to support multiple encoding, defaulting to Base16 or Bech32, whatever makes the most sense. About the payload: Well, the payload isn't necessarily a valid UTF-8 byte sequence, so it's only waiting for errors to use a plain string here. Of course, wallets will want to present the information to users but I doubt they would present the full payload anyway since it's mostly gibberish from a user standpoint. Rather, wallets can and shall, whenever possible, extract information that are relevant to show for approval. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
What is the value of using CBOR elsewhere besides implicitly referring to ledger specs (and not having to update CIP when the specs are updated)? I think dApp developer UX is extremely important and it would be better with javascript object-based API. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Yeah the CBOR thing was more of that is how it is technically defined right now by nature of referring to the ledger binary spec, but I agree it makes more sense to change to just raw bytes (encoded by hex).
I believe this was a mistake, it was meant to be a hex-encoded string type, to be consistent with CIP-0008 (message signing spec).
What about for returns? It's easier to accept multiple encodings in parameters but it becomes weird for return types. If you're always returning a specific one (bech or hex) so that users can easilly decode it, it would make usage with the other of the two less consistent imo.
CBOR encoding is fairly ubiquitous in the Cardano ecosystem and it has support with various tooling already in a standardized way. If we had our own JSON encoding for everything here (which would amount to a lot of types once you think about how complciated some of these types are) you would still need to code conversions between that and CBOR (or worse, to other tool-specific encodings/constructions) in order to use other libraries together with CIP-30, unless you build some monolithic library that takes care of everything you could possibly need all within this CIP-30 specific format. The way it's defined here you can just call There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Do you have any specific tools in mind? Using json schema for signTx/submitTx would remove dependency on
cardano-js-sdk has types we could use as a reference. It also provides utils for type conversion between those types and There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
..and reduces the application's size by around 2MB |
||
|
||
The payload is not hashed and no `external_aad` is used. | ||
|
||
If the payment key for `addr` is not a P2Pk address then `DataSignError` will be returned with code `AddressNotPK`. `ProofGeneration` shall be returned if the wallet cannot generate a signature (i.e. the wallet does not own the requested payment private key), and `UserDeclined` will be returned if the user refuses the request. The return shall be a `DataSignature` with `signature` set to the hex-encoded CBOR bytes of the `COSE_Sign1` object specified above and `key` shall be the hex-encoded CBOR bytes of a `COSE_Key` structure with the following headers set: | ||
|
||
This endpoint utilizes the [CIP-0008 signing spec](https://github.com/cardano-foundation/CIPs/blob/master/CIP-0008/CIP-0008.md) for standardization/safety reasons. It allows the dApp to request the user to sign data conforming to said spec. The user's consent should be requested and the details of `sig_structure` shown to them in an informative way. The Please refer to the CIP-0008 spec for details on how to construct the sig structure. | ||
* `kty` (1) - must be set to `OKP` (1) | ||
* `kid` (2) - Optional, if present must be set to the same value as in the `COSE_Sign1` specified above. | ||
* `alg` (3) - must be set to `EdDSA` (-8) | ||
* `crv` (-1) - must be set to `Ed25519` (6) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just to double check is There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
You should open an issue in the message signing library if that is the case. It should be serializing it as 6 in the CBOR when converting from the enum to enum definition: https://github.com/Emurgo/message-signing/blob/master/rust/src/builders.rs#L151 I can take a look into this on Monday and maybe change the macro we were using to define those enums. IIRC the idea was you'd be using those enums with the stuff in I would recommend using the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks @rooooooooob
That is very useful, I just tried it out, however it also returns 5 for I opened up an issue here on message-siging lib: Emurgo/message-signing#9 |
||
* `x` (-2) - must be set to the public key bytes of the key used to sign the `Sig_structure` | ||
|
||
### api.submitTx(tx: cbor\<transaction>): Promise\<hash32> | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This shouldn't be necessary anymore as the user only provides the payload, not the entire Sig_structure. Not providing proper hex bytes falls under the broader
APIError.InvalidRequest realm