-
Notifications
You must be signed in to change notification settings - Fork 40
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
Sync / Signing Protocol Enhancement #1
Comments
Can I find somewhere a description of the current protocol? |
We don't have a formalized description of it, unfortunately. In short, the content we sync is very similar, but we just create a JSON and base64 encode it, so something like this:
This results in a much larger payload due to the inclusion of keys and brought us some problems when deserializing the stuff. One of our goals is to include the unsigned transactions in a format "as pure as possible", so only the necessary fields of such a TX in unsigned form (or in the case of aeternity, the unsigned TX is already encoded which makes it even easier) |
How would that be ensured with the described protocol here, if I were to change a function call for an Ethereum contract? For example: I call a token contract at address I assume that would be up to the consumer of the signing request to parse calldata etc? |
Our intended way to solve this is to hash the content that gets signed and display it in form of an identicon, on both devices. Users can visually verify this way, that the data generated on device A is the same as the data signed on device B. |
How RLP encoded request is going to be passed by QR codes? In the Base app, I tried to encode binary (raw) data into QR codes but I was not able to find a Cordova package that able to scan them properly. |
For example, let's compress payload of this const lzma = require('lzma');
const txDataHex = 'cae9ca510000000000000000000000004ecd812b010d9db16b0fb7143a79786b65b89b09000000000000000000000000000000000000000000000000016345785d8a00000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000007400000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000034616b5f7631325066397657634e357453754e325365464c33526d5955447075377a6565557353754159777947444d57394e583342000000000000000000000000'
const txDataBuffer = Buffer.from(txDataHex, 'hex')
const txDataCompressedBuffer = Buffer.from(lzma.compress(txDataBuffer, 9))
console.log(txDataBuffer.length, txDataCompressedBuffer.length)
So, in this case, the compressed call data is two times shorter than uncompressed. |
Amount of data that can be put into single QR code is limited, is this protocol supposed to define a way to split transaction details into several QR codes? I have seen some implementation of data streaming by QR codes in ledger-live-common repository, also they have problems with the encoding of binary data into QR codes. |
@davidyuk We convert the binary data to base64 and write that string into the QR, which works fine with all common QR plugins (see last few lines of the initial post). I think currently there is no vastly better way. We share the concerns about the payload size in QRs. Generally, I think using compression can only solve the problem until a certain degree, where we need to adapt a splitting mechanism anyway, as the resolution of the QR code will simply make it very hard or unable to scan =/ We have added a wrapper object around the proposed protocol above which we could use in the future to split the payload and scan multiple QRs in order to stitch it back together. I'll update everything shortly, we should have an implemention draft ready shortly as well :) |
So, data in QR codes will be also prefixed with |
Yes, though the prefix depends in the end on the app you would like to speak to. The unsigned TX will allow you to include a callback url, which determines the prefix. The part will be included in the serialized data as well.
This is how it currently looks in one of our test cases, so you can simply use
Afterwards to serialize/deserialize it. Names etc. are not yet final of course. |
Do you have any agreement on returning a result to callback url? Can we use something like this? |
base64 should use url-safe charset or special chars ( |
The callback URL can either be a standard link where the serialized content will be appended, lets say The url-safety aspect of base64 is a great input. Do you think it would be better to go with the base64url or simply provide the URL-Encoded base64 string? |
As I see in the example, actually they are not encoded anyhow. Won't it lead to problems with parsing in some cases? |
I guess it depends on how you parse the URL (as always), but we take a look at it as its a very valid concern. |
It depends on the popularity of |
The same with encoding in RLP. In general, this protocol looks similar to EIP-67 that was superseded by EIP-681 as representing payment transactions in a high-level fashion. Representation of call data proposed in Usage of compressing algorithms can lead to similar or even smaller payload sizes as when payload encoded into RLP for generation of QR codes. Also, arguments passing in |
We have looked quite a lot at these EIP/BIP, and while they do solve some of the issues, they lack certain information necessary for signing requests on offline devices (ins/outs in bitcoin, nonce in eth). We think a wallet application can still react to schemes such as BIP-0021, collect the necessary information to build the transaction and then use the Sync-Scheme outlined here to send a signing request to a device capable of doing that. So they rather enhance each other than replace, as the use-case is not exactly identical. Also, most of those schemes are coin-specific while we try to keep our scheme completely coin-agnostic, allowing for arbitrary data to be included in the future (such as new transaction types, new types of coins in general). |
Is it possible to track nonce on the side of offline signer? If the account is generated by AirGap then nonce should be 0 and it can be increased for every signed transaction.
Anyway, support of new coins will require changes in your app at the same time you can implement support of corresponding URL schemas. An ability to define a handler for a specific protocol is enough to support different coins in the future. |
Not really - If you imagine a scenario where a user decides to import an existing mnemonic, we would need to ask for the nonce every time when creating a new ETH/AE Wallet, as we are unable to guess it. Also, scenarios like overriding transactions with higher fees become more complicated as the vault isn't simply a signing device anymore, but holds state apart from the keys.
The idea is that by simply updating the coin-lib in both apps, we are able to incorporate new coins easily. The apps check the supportedProtocols in the library and the whole functionality is generic, there is no coin-specific implementation in the apps currently. As stated, the problem for coins using UTXO instead of an account based model persists - The current standard simply rely on the assumption that the receiving device has an internet connection / connection to a node to complete the missing information. This is not the case for us. I can see however, that our apps will be able to react to those schemes as well in order to be compatible, so our Wallet might be able to receive such a BIP-0021 request, create the Unsigned TX from it and then use our scheme to sign the TX on the Vault. |
The enhancements discussed in this issue have been implemented some time ago and are documented here: https://airgap-it.github.io/airgap-coin-lib/#/serialization?id=getting-started |
Airgap currently uses a very basic protocol to sync wallets, send requests for signing transactions and broadcast signed transactions.
We propose a new protocol that does replace the existing one with the following design goals:
The following data is necessary for a user to verify his transaction properly:
Coins/Protocols might add data that is necessary for proper signing such as
data
in case of Ethereum, orInputs/Outputs
in case of Bitcoin.General Thoughts
This protocol solves a couple of similar use cases such as EIP 681, although not completely the same. We aim to use the protocol to facilitate communicate between cold-storage wallets / devices and internet-connected devices using a one-way method such as cameras (=> QR Codes). This adds another design goal, size-efficiency. EIP 681 or similar protocols in Bitcoin, rely on the receiver having access to the internet in order to fetch necessary properties (fpr example
nonce
orUTXO
).The protocol consists of two layers:
Basic Approach
Serialization - RLP
We chose RLP as our serialization method due to two reasons:
Encoding in URL - Base64
We use base64 to encode the data when embedded in a URL-Scheme to further shorten the amount of characters necessary in comparison to HEX-Data (Base16).
Example of Protocol Payloads
The type of request that is encoded in the protocol is always determined by the scheme / url that the request is sent to. The data itself does not include information about "what" it is, similar to how an ethereum TX does not do that. As we always have to include some kind of URL-Scheme regardless, this information would be redundant anyways.
1. Syncing a Cryptocurrency Wallet
In case of syncing an ETH wallet, this could look sth like this:
Which base64-encoded and embedded in a scheme equals:
2. Transaction Signing Request
Given the following Ethereum TX:
made from the address
0x7461531f581A662C5dF140FD6eA1317641fFcad2
, encoded in RLP this would give us sth like this:Which base64-encoded and embedded in a scheme equals:
Open Questions
The text was updated successfully, but these errors were encountered: