| KIP | 0015 |
|---|---|
| Title | quicksign signing api v1 |
| Author | Jacquin Mininger @jmininger, Doug Beardsley @mightybyte |
| Status | Draft |
| Type | Standard |
| Category | Interface |
| Created | 2022-09-15 |
We propose an additional quicksign endpoint to the kadena-signing-api that allows a wallet to show the user multiple transactions at once for signature approval
The current sign method used by signing-api-v1 contains a number of limitations:
- Only a single txn can be signed at a time. This is painfully inefficient for workflows that require multi-step transactions or for transactions to occur across multiple chains
- Only
exectransactions can be sent and signed;conttransactions have no means of being signed in the current api - The response value returns a
Commandtype which represents a fully-signed transaction. It does not allow for an intermediate state with a partially signed transaction. The latter is a useful workflow given that pact is multisig-native
In addition to the above, we propose an evolution of the SigData type used by the pact command line tool for representing partially-signed payloads (since pact’s Command type can only exist as a fully signed payload), that we call CommandSigData.
- The
SigDatatype includes ahashfield https://github.com/kadena-io/pact/blob/957b8bd7644cebc60d043b33f0d7ffc53c65d783/src/Pact/Types/SigData.hs#L62-L66 . This data can also be derived from thecmdfield ofSigData. Imagine a scenario where a malicious dapp sends aSigDatawhere the hash represents a malicious transaction, while the payload represents an unrelated transaction that the user is expecting. If the wallet does not explicitly check the hash, by recalculating, this becomes a security issue. To avoid this we force the wallet to compute the hash (by omitting it from the newCommandSigDatastructure)
{
"commandSigDatas": [ { "cmd": string, "sigs": [ { "pubKey":string, "sig": string|null }]}]
}
{
"responses": [{
"commandSigData": { "cmd": string, "sigs": [ { "pubKey":string, "sig": string|null }]},
"outcome": { "result": "success|failure|noSig", "hash|message"|null: string } }
}]
}
or
{
"error": { "type": "reject|emptyList|other", "msg": string|null }
}
A quicksign request takes the form of a json-encoded payload matching the following schema:
{
"commandSigDatas": [CommandSigData]
}
- The "cmd" string represents a json-encoded payload type, specified here: https://api.chainweb.com/openapi/pact.html#tag/model-payload
- Here is an example
cmdpayload:
- Here is an example
"{\"networkId\":\"testnet04\",\"payload\":{\"exec\":{\"data\":null,\"code\":\"(+ 1 2)\"}},\"signers\":[{\"pubKey\":\"ae18efd16cbd49e9a92552a2589ac01491b486fbcbb1e3f07980f945597e2033\",\"clist\":[{\"args\":[],\"name\":\"coin.GAS\"}]},{\"pubKey\":\"fa781bdd858cd2380b5e2b654e58035f7189a6e8158686a1bb7eabb585a56e7f\"}],\"meta\":{\"creationTime\":1663085494,\"ttl\":1800,\"gasLimit\":20,\"chainId\":\"0\",\"gasPrice\":1.0e-6,\"sender\":\"ae18efd16cbd49e9a92552a2589ac01491b486fbcbb1e3f07980f945597e2033\"},\"nonce\":\"2022-09-13 16:11:34.678231 UTC\"}"
The schema for a CommandSigData object is:
{
"sigs": [Signer],
"cmd": string
}
Note that this type is an evolved version of SigData which pact currently uses in its command-line tool: https://github.com/kadena-io/pact/blob/957b8bd7644cebc60d043b33f0d7ffc53c65d783/src/Pact/Types/SigData.hs#L62-L66
- The
pubKeyfield is a lowercase base-16 encoded public key - The
sigelement is either a lowercase base-16 encoded signature or a null value (representing a request for signature).
{
"pubKey": string,
"sig": string //optional; its omission represents a signature that has not yet been acquired
}
{
"responses": [Response]
}
or
{
"error": QuicksignError
}
- The
commandSigDatasfield contains the list of requests; some of which contain new signatures attached. Even in the case of an error, it is still useful to have the ordered list ofCommandSigDatasin the response, given that some of them will contain new signatures.
{
"commandSigData": CommandSigData,
"outcome": Outcome
}
The following are the 3 possible forms of the Outcome type
- At least one signature was added
hashis an unpadded Base64URL of Blake2s-256 hash of thecmdfield value of the successfully signedCommandSigData
{ "result": "success", "hash": string }
- An error occurred parsing this particular
CommandSigData
{ "result": "failure", "msg": string }
- Special case for when 0 signatures have been added to the
CommandSigData
{ "result": "noSig" }
For when the user chooses to reject the entire request and not provide any signatures
{
"type": "reject"
}
For when the commandSigDatas field in the request is an empty list
{
"type": "emptyList",
}
A catch-all value for other error cases
{
"type": "other",
"msg": string
}
The signing api has traditionally been exposed via localhost port 9467. The quicksign handler will handle requests to the /quicksign route.
A single commandSigData to unlock a 3-person multisig, with one signature already provided
{
"commandSigDatas":
[
{ //Note that "sig" can either be explicitly null or omitted entirely under this spec
"sigs":
[ {
"pubKey": "ae18efd16cbd49e9a92552a2589ac01491b486fbcbb1e3f07980f945597e2033"
},
{
"pubKey": "fa781bdd858cd2380b5e2b654e58035f7189a6e8158686a1bb7eabb585a56e7f",
"sig": null
},
{
"pubKey": "d61c2b4d8151cd0a7599790a6a905a96dc1028b5e61181e08104e60f28ad8997",
"sig": "a41b1c481414b0a0bac27c1f95f03d058cf1dc7ace571cf7b7a74be34e90116096dac8744adc0b94ffc16241cc87f513ea7f999802b3b6e58a1139c56881f800"
},
]
"cmd":"{\"networkId\":\"testnet04\",\"payload\":{\"exec\":{\"data\":null,\"code\":\"(enforce-keyset (read-keyset 'ks))\"}},\"signers\":[{\"pubKey\":\"ae18efd16cbd49e9a92552a2589ac01491b486fbcbb1e3f07980f945597e2033\"},{\"pubKey\":\"fa781bdd858cd2380b5e2b654e58035f7189a6e8158686a1bb7eabb585a56e7f\"},{\"pubKey\":\"d61c2b4d8151cd0a7599790a6a905a96dc1028b5e61181e08104e60f28ad8997\"}],\"meta\":{\"creationTime\":1664393516,\"ttl\":1800,\"gasLimit\":100,\"chainId\":\"0\",\"gasPrice\":1.0e-6,\"sender\":\"k:ae18efd16cbd49e9a92552a2589ac01491b486fbcbb1e3f07980f945597e2033\"},\"nonce\":\"2022-09-28 19:31:56.965212 UTC\"}"
}
]
}A single signature has been added for “d61c2b4d8151cd0a7599790a6a905a96dc1028b5e61181e08104e60f28ad8997”
{
"responses": [{
"outcome":
{
"result": "success",
"hash": "RKABKR6zLC44vunHHzycRE0JXqbwpvQXztRnzbUKKls"
},
"commandSigData":
{
"sigs":
[
{
"pubKey": "ae18efd16cbd49e9a92552a2589ac01491b486fbcbb1e3f07980f945597e2033",
"sig": "10d3189ee55a34d0f15509c889d1a313c292c1b419244ae2938dd745ab887a45e34183e577ed0ab61fd0c76e8e957922fc467a21ab6d074aa3aa3e742a10390d"
},
{
"pubKey": "fa781bdd858cd2380b5e2b654e58035f7189a6e8158686a1bb7eabb585a56e7f",
},
{
"pubKey": "d61c2b4d8151cd0a7599790a6a905a96dc1028b5e61181e08104e60f28ad8997",
"sig": "a41b1c481414b0a0bac27c1f95f03d058cf1dc7ace571cf7b7a74be34e90116096dac8744adc0b94ffc16241cc87f513ea7f999802b3b6e58a1139c56881f800"
},
]
"cmd":"{\"networkId\":\"testnet04\",\"payload\":{\"exec\":{\"data\":null,\"code\":\"(enforce-keyset (read-keyset 'ks))\"}},\"signers\":[{\"pubKey\":\"ae18efd16cbd49e9a92552a2589ac01491b486fbcbb1e3f07980f945597e2033\"},{\"pubKey\":\"fa781bdd858cd2380b5e2b654e58035f7189a6e8158686a1bb7eabb585a56e7f\"},{\"pubKey\":\"d61c2b4d8151cd0a7599790a6a905a96dc1028b5e61181e08104e60f28ad8997\"}],\"meta\":{\"creationTime\":1664393516,\"ttl\":1800,\"gasLimit\":100,\"chainId\":\"0\",\"gasPrice\":1.0e-6,\"sender\":\"k:ae18efd16cbd49e9a92552a2589ac01491b486fbcbb1e3f07980f945597e2033\"},\"nonce\":\"2022-09-28 19:31:56.965212 UTC\"}"
}
}]
}Alternatively, here is a response where no signature was added to the single commandSigData
{
"responses": [{
"outcome":
{
"result": "noSig",
},
"commandSigData":
{
"sigs":
[ {
"pubKey": "ae18efd16cbd49e9a92552a2589ac01491b486fbcbb1e3f07980f945597e2033"
},
{
"pubKey": "fa781bdd858cd2380b5e2b654e58035f7189a6e8158686a1bb7eabb585a56e7f",
"sig": null
},
{
"pubKey": "d61c2b4d8151cd0a7599790a6a905a96dc1028b5e61181e08104e60f28ad8997",
"sig": "a41b1c481414b0a0bac27c1f95f03d058cf1dc7ace571cf7b7a74be34e90116096dac8744adc0b94ffc16241cc87f513ea7f999802b3b6e58a1139c56881f800"
},
]
"cmd":"{\"networkId\":\"testnet04\",\"payload\":{\"exec\":{\"data\":null,\"code\":\"(enforce-keyset (read-keyset 'ks))\"}},\"signers\":[{\"pubKey\":\"ae18efd16cbd49e9a92552a2589ac01491b486fbcbb1e3f07980f945597e2033\"},{\"pubKey\":\"fa781bdd858cd2380b5e2b654e58035f7189a6e8158686a1bb7eabb585a56e7f\"},{\"pubKey\":\"d61c2b4d8151cd0a7599790a6a905a96dc1028b5e61181e08104e60f28ad8997\"}],\"meta\":{\"creationTime\":1664393516,\"ttl\":1800,\"gasLimit\":100,\"chainId\":\"0\",\"gasPrice\":1.0e-6,\"sender\":\"k:ae18efd16cbd49e9a92552a2589ac01491b486fbcbb1e3f07980f945597e2033\"},\"nonce\":\"2022-09-28 19:31:56.965212 UTC\"}"
}
}]
}Alternatively, the user may indicate to the wallet that they do not approve of the signature:
{
"error":
{
"type": "reject"
}
}- This is an addition to the signing-api and as such, the
signmethod is still supported.
- Quicksign implementation on-top of the Wallet-Connect v2 sign protocol
- Kadena.js implementation
- A quicksign-ui specification for detailing exactly how a wallet should display the many requests in a digestible manner for the user
- A “dynamic” version that allows a user to select gas prices for each transaction. Alternatively, it will be up to the dapp to do this, and we need to provide an easy/pluggable framework that makes it easy for dapps to control this interaction with the user.