hivewallet / discussions

Discussions and issues related to Hive
https://github.com/hivewallet/discussions/issues
3 stars 2 forks source link

Hive transport layer #5

Open javgh opened 10 years ago

javgh commented 10 years ago

This is a rough specification for what I have in mind for a "Hive transport layer" for the Android client. A way for different Hive wallets to talk to each other and exchange payment requests and messages, profile pictures and maybe other stuff down the line (user messages).

The basic idea is: Every wallet has a Jabber account (just some random_identifier@hivewallet.com) over which it receives and sends messages. This account is automatically created (with a random user name and password) on first startup.

I'm currently thinking that the message format should be specified using Google's protocol buffers. Because part of what needs to be communicated will be BIP70 messages and they are already defined as protocol buffers. So I think it makes sense to specify everything as protocol buffer messages which then include BIP70 messages where necessary.

So I imagine there to be a top-level message, which wraps everything and can be used to parse incoming messages:

message HiveMessage {
    required string version = 1

    enum MessageType {
        REQUEST_PROFILE = 1;
        ...
    }
    required MessageType message_type = 2;
    ...
}

All messages are encrypted. So after having serialized everything using protocol buffers, the data is encrypted for the recipient in a final step before sending the data out. Conversely, all incoming messages are dropped unless they are encrypted with the local wallet as the recipient.

This in turn means, that a wallet can only communicate with other wallets where it knows their public key. This exchange of keys happens during an initial invite process, which requires an external communication channel (e-mail, instant messaging, text message, ...).

To start the invite process, the wallet prompts the user to send a message like the following to the person they want to invite. Let's say Alice is inviting Bob:

Hi Bob! I'd like to connect with you via Hive to easily send and receive bitcoins.
Hive is available for free on Google Play: <link to the app> . After installing,
please follow this link to accept my invitation:
https://www.hivewallet.com/inv/kdjfkwec93oqwe

The invite link is a key to a data structure that contains the following things:

Bob's wallet then sends an invite acceptance message to jabber_address_of_alice_s_wallet@hivewallet.com, encrypted with Alice's wallet GPG key, which contains:

From now on, both parties have GPG keys and Jabber addresses of each other and can exchange messages.

The exact format of the protocol buffer messages still needs to be defined, but in the first version I would like to be able to do these things:

Regarding the last point: XMPP has support for avatars as well, but I think it's best to treat XMPP as a dump pipe, not use any of those features and implemented what we need inside our messaging format. That encapsulates things nicely if we later want to support other transport mechanisms besides XMPP.

javgh commented 10 years ago

For Hive Web, it seems this is a good library for protocol buffer support: https://github.com/dcodeIO/ProtoBuf.js .

As far as XMPP is concerned, the question would be whether to do this mostly in the browser (see https://conversejs.org/ ) or do most of the heavy lifting on the server (including login in to the Jabber account) and just forward messages to the Javascript client. Since the messages themselves are encrypted, that should not be a big problem. But the server would need to know the XMPP login credentials.

mikehearn commented 10 years ago

I suggest not doing XMPP but just using GCM directly. GCM is what you get if you start with Jabber and evolve it over time for efficiency and robustness (the original version of the Android cloud push system shipped in Android 1.0 used Jabber/GTalk behind the scenes).

In particular, things GCM gets you for free:

By all means support pluggable backends, but I'd suggest not trying to run your own full-blown push messaging system for now. If you look at TextSecure as an example of another open source project that does end to end crypto, they concluded competing with GCM was way too hard and focus their efforts elsewhere.

The main issue is cross-platform support. GCM is only for Android and (signed in) Chrome. So, to support a unified service across all Hive apps and maybe in future, all wallets, some other kind of server would be indeed needed to bridge the worlds. But at least you would not have to handle all the traffic. I would not suggest using XMPP itself as it's a rather verbose unframed text protocol that's hard to work with - length prefixed protocol buffers would work would be simpler.

But the real question to ask is - to provide features like requesting payments from someone and having profile pictures, is a custom messaging passing network the right approach?

For example, an alternative approach would be to have a site where wallet apps can upload payment requests, kind of like a pastebin for payments (a "paybin"). Then you can have a Facebook app or however it works these days to find someones paybin link from their social network profile. In fact I prototyped steganographically embedding these links into profile pictures, but I'm not sure it's possible to make the UX really excellent with that, so we might want to tolerate a small amount of centralisation for rendezvous purposes and have an "official" Facebook app that just maps userids to URLs of payment requests. You could then add a "sign in with Facebook" button to Hive using their pre-made APIs and then find out which users have published payment request URLs. For now, wallets could upload a fresh batch of payment requests to the same URL whenever the existing one is used up. In future we could extend BIP70 again to support deterministic wallets and allow the paybin site to iterate the keys itself, or something.

javgh commented 10 years ago

Thanks for your feedback! All very good points.

Regarding battery usage: I agree that this is very important. But the Schildbach wallet already wakes up from time to time to open various network connections to the Bitcoin network. From what I can tell, this does actually use quite a bit of battery and ideally I would want to reduce that, but it seems to be tolerated by users so far. So I think adding an extra XMPP connection at that point will not make much of a difference. I agree that it is not a solution to have the app running all the time. Users will have to live with the fact, that their payment requests are delivered with some delay. Although I was thinking that maybe at this point GCM could be used, as a low-energy way of letting the app know, that it needs to wake up and check for XMPP messages.

Like you said, the biggest drawback of GCM is cross-platform support. And we will want to do that pretty much right away, so I'm not sure it's a good idea to pick a solution which we will need to then work around in the next step.

I agree that XMPP is pretty clunky and verbose. But on the other hand there are already libraries available and you can just 'apt-get' ejabberd and have a server up and running, rather than having to implement one yourself for your own lean, but custom protocol.

Regarding your alternative suggestions: I think your idea of using steganography with the profile picture as a way to leverage social networks is a cool trick in theory, but like you said will probably not work in practice ("Why is this app changing my profile picture?! I lost all my likes!"). Both that and your alternative seems to be more about the use case of "how do I pay this particular person where I only know their name/social network account", whereas I'm more interested in "how do I prompt my contact X to pay me some money". I don't see how the paybin solution addresses that.

In general, I'm skeptical about integrating with G+ and Facebook. I wouldn't use it myself (I like to keep things separate) and I'd rather not write software that I wouldn't use myself or have qualms about recommending. I also wonder, if even people who are fine with "sign in with Facebook" feel differently when it comes to money. So for the time being I'd rather stay away from G+ and Facebook, even if leveraging their huge user base sounds attractive.

mikehearn commented 10 years ago

I'm more interested in "how do I prompt my contact X to pay me some money".

But do you really want to try and build what is effectively an IM network, just for this use case? I'm reminded of the emacs joke, about how every app grows until it includes an email client :-)

I'm not sure why my feelings about Facebook would stop me using it for requesting money - it's not like Facebook is going to start defrauding me of funds or anything. The concerns people have about social networks are more about privacy/ads/surveillance/etc rather than worrying about whether money will arrive. Anyway, the question to ask yourself is how many users will want to create Yet Another Profile and keep it up to date? It's kind of a hassle.

The reason I focus on integration with other services (even though some of them may be more centralised than ideal) is that it'd be easy to end up a jack of all trades and master of none. A wallet that's a really, really good wallet and nothing else has more value to me as a user than a wallet that's sort of average at handling money, and is also a mediocre social network and messaging app.

javgh commented 10 years ago

But do you really want to try and build what is effectively an IM network, just for this use case?

Yes, because what are the alternatives? What IM network can we piggyback on and still have a smooth user experience? I mean, I explored that to some extend with - for example - using Whatsapp or Hangouts or text messages as the transport layer and just have the user send a pamyent request through those channels. That led to this ticket: https://github.com/schildbach/bitcoin-wallet/issues/43 ("Feature idea: Bitcoin URIs and payment requests embedded in http links to be clickable in more places"). The conclusion there was, that we should wait for Whatsapp (and Hangouts and text messages) to support Bitcoin-URIs and/or BIP70 files. I think we'll be quicker in building or own IM network then waiting for Whatsapp to support our use case.

I agree that Yet Another Profile is a hassle. That's why it will be minimal. No picking of user names, no "about me" or anything like that. Just a profile picture and even that we might automatically source from the device if possible.

Personally, I don't like to link a bunch of stuff with my Facebook account, because then it becomes a single point of failure/attack for these things. But true, privacy concerns play into it as well for many people. So one might worry, for example, about Facebook knowing from whom I request money. Whether or not that would be the case in practice is irrelevant I think, because the decision will just be made on a vague feeling of "Facebook invades my privacy" and "I like to keep my finances private". That's just my guess though, we probably cannot really settle this for sure.

tgerring commented 10 years ago

A way for different Hive wallets to talk to each other and exchange payment requests and messages, profile pictures and maybe other stuff down the line (user messages).

How will we be handling instances where only 1 of the users is online, both before and after the initial exchange of PGP keys? i.e. Is Hive responsible for holding messages until the other party comes online?

javgh commented 10 years ago

How will we be handling instances where only 1 of the users is online, both before and after the initial exchange of PGP keys? i.e. Is Hive responsible for holding messages until the other party comes online?

Yes, I would just rely on the standard behavior of the (Hive) Jabber server here, to store messages until the user comes back online.

ghost commented 10 years ago

Can we use this layer to help create multisig transactions in a user-friendly way?

javgh commented 10 years ago

Can we use this layer to help create multisig transactions in a user-friendly way?

Yes, I think that should definitely be possible. The UI for that has to be worked out, but as long as the wallets can send messages to each other via the transport layer it should be possible to come up with a reasonable process.

mackuba commented 10 years ago

whereas I'm more interested in "how do I prompt my contact X to pay me some money"

Couldn't this be implemented just by having wallet A create a .bitcoinpaymentrequest file and send it via mail as an attachment to user B, who then clicks the attachment in the email client and gets redirected to their wallet app?

mikehearn commented 10 years ago

Yes indeed. On 15 Apr 2014 21:06, "Jakub Suder" notifications@github.com wrote:

whereas I'm more interested in "how do I prompt my contact X to pay me some money"

Couldn't this be implemented just by having wallet A create a .bitcoinpaymentrequest file and send it via mail as an attachment to user B, who then clicks the attachment in the email client and gets redirected to their wallet app?

— Reply to this email directly or view it on GitHubhttps://github.com/hivewallet/discussions/issues/5#issuecomment-40521121 .

mackuba commented 10 years ago

Hmm, here's an idea: what if we implement this instead as some kind of extremely simple queue-like database with an HTTP endpoint for posting and a websocket URL for reading? E.g.: sender submits a Payment message via HTTP, if receiver is connected then they immediately pull it through the websocket; if they're offline, then it's stored in the queue and they get it next time they start Hive.

Invitations for connecting could be handled in a similar way, and sending Payment Requests should probably be handled by email anyway (see my comment in #10).

Advantage of this over XMPP: you'd be able to accept Payment Protocol payments from any wallet that implements Payment Protocol.

mackuba commented 10 years ago

So basically the server would act as a kind of Payment Protocol proxy for the wallet app, to work around the fact that a desktop wallet can't simply put up a public HTTP payment_url like a merchant does.

mikehearn commented 10 years ago

whois paybin.io ;)

ghost commented 10 years ago

Heh. So @mikehearn What's your timeline on that then, and do you need help building it?