KIP | Title | Author | Status | Type | Category | Created |
---|---|---|---|---|---|---|
0015 |
quicksign signing api v1 |
Jacquin Mininger @jmininger, Doug Beardsley @mightybyte |
Draft |
Standard |
Interface |
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
exec
transactions can be sent and signed;cont
transactions have no means of being signed in the current api - The response value returns a
Command
type 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
SigData
type includes ahash
field https://github.com/kadena-io/pact/blob/957b8bd7644cebc60d043b33f0d7ffc53c65d783/src/Pact/Types/SigData.hs#L62-L66 . This data can also be derived from thecmd
field ofSigData
. Imagine a scenario where a malicious dapp sends aSigData
where 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 newCommandSigData
structure)
{
"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
cmd
payload:
- 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
pubKey
field is a lowercase base-16 encoded public key - The
sig
element 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
commandSigDatas
field 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 ofCommandSigDatas
in 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
hash
is an unpadded Base64URL of Blake2s-256 hash of thecmd
field 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
sign
method 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.