Sia icon indicating copy to clipboard operation
Sia copied to clipboard

Feature request: Offline transaction signing

Open mtlynch opened this issue 8 years ago • 18 comments

With the increase in the Siacoin's market value, there's a greater need to to manage Siacoins in a way that protects the user from malware infections or active attackers.

I realize that there's an offline wallet generator, but I'm reluctant to use it if I can't verify that I can move coins sent to an address it generates. Right now, the only way to do that is to bring my offline wallet online, potentially compromising the wallet if the online machine is compromised.

Offline transaction signing would allow users to manage their wallets without ever having to connect their wallet-holding system to the Internet.

mtlynch avatar Jun 14 '17 00:06 mtlynch

This sounds like a good project for a third-party dev, or a weekend project for a Sia dev. What sort of API do you have in mind? Would this be part of siad/siac or a standalone binary?

lukechampine avatar Jun 14 '17 00:06 lukechampine

Would this be part of siad/siac or a standalone binary?

Ideal would be if it were possible natively with siad / siac, but I'd be happy with a standalone tool.

mtlynch avatar Jun 14 '17 02:06 mtlynch

@lukechampine I will volunteer to work on this. I am building a web wallet and need this feature.

rmcdaniel avatar Jan 12 '18 04:01 rmcdaniel

@rmcdaniel excellent. DM me on Discord (nemo -- need to Friend Request me first) if you need any pointers.

Can you (and/or @mtlynch) elaborate on what the API for this would look like?

lukechampine avatar Jan 12 '18 07:01 lukechampine

I haven't thought it through to the API level, but here's the functionality I had in mind:

Initiating the offline wallet

Offline machine: User generates an offline wallet and writes a watch-only copy to a USB key.

# Create offline wallet
$ ./siac wallet init

# Create watch-only wallet that does not contain private keys
$ ./siac wallet make-watchonly /media/usb0/watchonly-wallet.wal
Enter the seed to use for the watchonly wallet: <> # User enters seed
Wrote watchonly wallet to: /media/usb0/watchonly-wallet.wal

Online machine: User loads the watchonly wallet on the online machine

# Load the watch-only wallet.
$ ./siac wallet load watchonly /media/usb0/watchonly-wallet.wal

# Online machine can see offline wallet's addresses without access to its private keys.
$ ./siac wallet addresses
<addresses>

# Online machine can see offline wallet's balance without access to its private keys.
$ ./siac wallet balance
<balance information>

Sending a transaction

Online machine: Create unsigned transaction

$ ./siac wallet send siacoins 100SC 480b8e97087ba4dd8f62f02f24575d403a6e62605ae069efa5ef0f94422cb8c7e896b8f7268d --offline /media/usb0
Wrote unsigned transaction to /media/usb0/tx983481.tx.unsigned
Sign the transaction from a node with access to the private keys with the command:
  siac wallet sign-transaction [unsigned tx path]

Offline machine: Sign the transaction

$ ./siac wallet sign-transaction /media/usb0/tx983481.tx.unsigned
Transaction:
  Destination: 480b8e97087ba4dd8f62f02f24575d403a6e62605ae069efa5ef0f94422cb8c7e896b8f7268d 
  Amount: 100SC
  Fee: 1SC
Sign transaction? (y/n): <> # User hits 'y'
Saved signed transaction as /media/usb0/tx983481.tx.signed
Broadcast the transaction from an online node with the command:
  siac wallet broadcast-transaction [unsigned tx path]

Online machine: Broadcast the transaction

$ ./siac wallet broadcast-transaction /media/usb0/tx983481.tx.signed
Sent 100SC to 480b8e97087ba4dd8f62f02f24575d403a6e62605ae069efa5ef0f94422cb8c7e896b8f7268d 

mtlynch avatar Jan 12 '18 14:01 mtlynch

That looks a lot how Electrum works. The first hurdle is being able to have a public master key that can be used to generate addresses and build transactions. You wouldn't want to have to enter your seed into the watch-only wallet. I'm digging into the crypto and wallet packages now to try to understand it all.

rmcdaniel avatar Jan 12 '18 17:01 rmcdaniel

@mtlynch @lukechampine

After doing some digging, I'm not sure having a watch-only wallet is possible without changing how the wallet uses the seed to generate the keys. Maybe someone that understands this better can weigh in?

Here are some references that I found useful:

https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki https://www.cs.cornell.edu/~iddo/detwal.pdf https://cardanolaunch.com/assets/Ed25519_BIP.pdf

Can we create successive public keys knowing only the first public key with just a deterministic wallet like you can do with a hierarchical AND deterministic wallet? Also, how much does secp256k1 vs. ed25519 make a difference?

rmcdaniel avatar Jan 13 '18 17:01 rmcdaniel

@mtlynch @rmcdaniel is this feature also means SPV feature i mean, one could send tx from siac on the phone and broadcast it on the server

tlightsky avatar Jan 19 '18 08:01 tlightsky

@tlightsky That part is easier. I am working on it as well in my spare time. It's just a matter of adding the ability to specify outputs for the transaction builder rather than looking for them in the wallet database.

rmcdaniel avatar Jan 19 '18 16:01 rmcdaniel

Okay, I have gotten pretty far on the code spikes I've done and I am ready to make a design. I am thinking that I could create a new module that will allow for these use cases. Since we can't have (or I don't know how to make) a public watch-only wallet that generates addresses for us using a master public key, the next best thing is to generate a bunch of addresses that can be imported into the watch-only wallet. The rest should operate pretty much the same. You create a transaction in the watch-only wallet and then sign it with the offline wallet.

What should the module be called? My top choices are offline or coldstorage but I would love some input.

rmcdaniel avatar Jan 21 '18 16:01 rmcdaniel

I was thinking along similar lines. 1,000,000 addresses would be more than sufficient for most people and only occupies 32MB -- small enough for an in-memory map. So then it's just a question of design. Do we extend the wallet module to generate + export the addresses? Do we extend it to load+watch a set of addresses? Both? Neither? I can't tell which aspect your suggested module is covering.

lukechampine avatar Jan 22 '18 02:01 lukechampine

Thank you @rmcdaniel. This is an extremely desired functionality. Most important for me is a module which allows the signing of transactions (akin to wallet) but from current, non-synced, consensus. Watch-only wallet is useful, but not as urgent since manual broadcast is possible (and recent blockchain is necessary for signing anyway).

This cold/hot-scheme seems almost possible through the API today but not quite. The API allows /tpool/raw for POSTing a raw (base64 encoded), signed transaction. But /wallet exposes no mechanism to GET a signed transaction. /wallet/siacoins and /wallet/siafunds only returns transaction ID's. I'm assuming a failed broadcast does not count as an unconfirmedtransaction from /wallet/transactions, correct?

Functions SendSiacoins/SendSiafunds creates, signs, broadcasts and returns the full transactions, but only when transactionpool suceeds (otherwise nil). However the API call seems to only extract the ID from these.

In addition to a module (I favor offlinewallet), I would suggest the API to return the transaction when only broadcast fails (instead of nil). Or even better, to expose a broadcast=no which triggers a tx return. Does this break any security model? It would allow software calling the API to save it and broadcast it later via aforementioned /tpool/raw if it so desired (e.g. temporary lack of internet connection).

yngman avatar Jan 26 '18 17:01 yngman

Bump!

Has anyone here made any progress on offline transaction signing?

leevlad avatar Mar 21 '18 18:03 leevlad

yes, made a quick poc but should make a decent one I can share.

robvanmieghem avatar Mar 22 '18 08:03 robvanmieghem

@robvanmieghem that's great, would you be open to sharing it here (or privately with me - see my email on my GH profile page)?

I can have a look, code review, clean up if need be, write tests, etc. Would much rather do that than start my own version from scratch.

leevlad avatar Mar 22 '18 15:03 leevlad

I'm also planning to work on this over the next week.

lukechampine avatar Mar 23 '18 00:03 lukechampine

Is this something the exchanges have requested? I'm just wondering why this feature request was bumped to the front of the priority queue in the middle of all the renter work.

tbenz9 avatar Mar 30 '18 01:03 tbenz9

Partly yes, but for we also need to use an offline wallet for the TSO.

lukechampine avatar Mar 30 '18 05:03 lukechampine