21st of April - Trezor on it’s way!
Christoph (rottenchris) has mailed me one of his spare Trezors - thank you very much! I’ll be flying to Estonia for a week tomorrow. Unless the package reaches me today, I won’t be able to play around with it until I’m back.
Progress This Week
I spent the better part of last week getting to know Monero wallet better: how it works behind the scenes, what is the code like, etc.
What I learned is that view key can only be used to detect outputs in a transaction which belong to the account. It cannot be used to detect when said output was spent.
The way simplewallet detects outgoing payments is by generating a key image for each of the transaction outputs belonging to the account and monitors the blockchain for usage of that key image. The only way to generate such key image is to have access to the private spend key.
Having Trezor generate key images for each of those outputs would defeat the purpose of a hardware security module. Having access to those key images means it is possible to spend that output.
See my notes below on outgoing payment detection for more information about this.
To get spend detection working for Monero I need to extend the public Trezor communication protocol with Monero specific features. This will decrease the chance of this work getting merged back upstream into official Trezor firmware.
After I’ve played around with the Trezor I’ll know more or less what kind of changes I need to do in the firmware. If they are fairly extensive, then it will make more sense to have Monero specific alternative firmware for Trezor.
Adding Trezor support directly to simplewallet would unnecessarily complicate usage of that tool and it would definitely not be a simplewallet anymore. I think the best option is to create a separate wallet tool for Trezor, dealing with just payments (no RPC for instance).
To do that I have three options:
- The easiest would be to copy-paste most of the existing wallet code into a new directory, make changes to add Trezor support and delete code (RPC, etc) that isn’t useful for the new tool. I don’t see such code being merged into Monero upstream nor anybody wanting to maintain this hack in the future. So this option isn’t really an option.
- The better option would be to refactor the existing wallet code extensively, in a way that would make it to be possible to build a second wallet utility with Trezor support on top it. It would be a fairly big undertaking with a lot of swearing involved and a chance of breaking existing simplewallet functionality.
- Or implement the Trezor wallet in Go, from scratch. This would probably take slightly more time, but it wouldn’t break any existing functionality nor would it have to be merged upstream. It would also mean in the future there would be solid building blocks for people wanting to build something on top of Monero using Go.
Out of the three options I prefer the last one as it would mean less swearing and more fun. I’ve started prototyping various required functionality (encoding/decoding Monero binary formats, generation & verification of ring signatures) to see if they can be implemented using the Go standard library & existing 3rd party libraries already out there.
Plan for Next Week
I am going to continue prototyping the Go wallet implementation idea. I will also be taking a more in depth look at trezor-mcu source code to get a better idea about how I would approach adding Monero support there.
Notes
Outgoing Payment Detection
View key only allows us to detect incoming payments for the address. So far I haven’t found a way to detect with view key if the key image was generated by the spend key holder.
That means detecting when the user has spent some of their money is tricky. The official wallet uses spend key to generate key images for each of the incoming payments. Then it compares those with all key images in the blockchain to see if it has been spent. If the spend key is not available this is not an option.
Hashed Key Images
To sign a transaction the user needs to interact with Trezor. We could however, implement a new API in Trezor which would output the hash of the key image. This would allow us to hash all seen key images and see if the users output was spent.
Educated Guessing
We could attempt to guess spend transactions. This would involve checking if all of the inputs in a transactions contain at least one of transaction output we know is ours. If there are change outputs we can be 99% certain this was an outgoing transaction.
There is an edge case which is difficult to detect using this approach: single input and single output, no change outputs. There just isn’t enough information to be 100% certain these outputs were spent by the user.
This also breaks bad when the transaction contains funds from several accounts. Thus the hashed key images would be a more foolproof way to monitor this.