Grin Wallet URL Format

Greetings all!

Grin payees currently provide IP addresses to payers so that their wallets can rendezvous and complete the payment. We’ll need to switch to a more robust address scheme eventually, and I wanted to create this thread to get the discussion going.

The current scheme has a number of drawbacks:

  • Vulnerable to man-in-the-middle attacks
  • Requires the payee to be publicly reachable, which in practice will require the payee to configure their firewall or NAT
  • Reveals the network location of the participants to one another, and to others who might observe the address, for example if a request for payment is posted in a public forum or on a mailing list
  • May expire unpredictably, since not all IP addresses are static

I’ve written a wiki page outlining a number of possible alternatives. I intend for it to be comprehensive, so do let me know if I’ve left something out!

My personal suggestion, although this shouldn’t carry much weight as I won’t be able to help implement it, is as follows:

I think that first switching to pubkeyhash@ip / pubkeyhash@domain and using the key to authenticate and encrypt the connection is probably prudent. This would fix the current vulnerability to man-in-the-middle attacks. Also, the code to implement this scheme will not be obviated by later improvements, so it won’t be wasted effort, even if we switch to another scheme.

After that, I think that using Tor hidden services is the best longterm solution. This would eliminate firewall and NAT issues, as hidden service clients and servers use outbound connections only, obscure network addresses, and allow a new address to be generated per payment.

However, Tor is a somewhat painful dependency, as it is written in C, and we would need to include a separate Tor binary in standalone Grin distributions, or require that the end user install it with a package manager.

What do y’all think?


Superficial level first: I wouldn’t talk about addresses or address format, that’s going to confuse people. Whatever we come up with will have totally different characteristics and will live at a different stack level compared to say bitcoin addresses. So how about wallet URL?

Otherwise I share your conclusions. Thanks for doing this!

1 Like

“Wallet URL” sounds totally reasonable to me, especially since it might even get its own scheme, like so:


I think that people will call it an address anyway, but that can’t really be helped.

1 Like

Obviously we need vaults, not wallet urls, we can devise a few prefixes (optional) based on weather the address is or is a multiplicate of 2/10,3,4,5,7,11,1/13


Haha vaults! I like it!

It’s good optics anyway to push for calling it something other than an address. It makes it clear that this is not a fork of bitcoin.


For what you are suggesting… we need our own DNS system to provide addresses or wallet URLS as you call them. I’d preffer to call them Vaults that are similar to a bitcoin wallet address in that it is base58 text.

We need a time stamped ledger of peers
We only need keep the most recent location for the peer
This isnt unheard of and is sort of what hashgraph uses
However this information ought to be encrypted and needs a key to decrypt it
The decryption key is packaged in the Vault address

A peers most recent endpoint consists of public key and (encrypted) signed ip/hostname(dns/i2p/tor)

There’s not much we can do about peers that are using things like tor when the sender has no local tor node. So I’d really like us to put i2p and tor on the back burner and just use IP’s and DNS lookups for now.

A Vault is simply a public key and the peer decryption key converted to base58. However I have a new method that I’d like to share with the world for transcoding to base58, so the output is still base58 but how it works is new.

The latest peer endpoint is looked up.

Success = Vault { pub key, peer decryption key } > Peer { decrypted signed IP/Port }

Edit: so yeah DHT sounds like the way to go, I’ll help if I can, I’ve been wanting to get stuck into rust somewhere

I am currently doing research into anonymous communications systems, so ill be following this topic with interest. Since GRIN requires some basic rdv mechanism, it would be pretty nice if this use case could be a motivator for building a scaleable messaging system with real anonymity properties. But I may be dreaming and projecting my own interests a little here :smiley:

As for DHTs, there are some ideas for building in some degree of anonymity, such as Octopus (

The downsides of things such as Tor/I2P, apart from the dependencies, is that they are not really built to withstand an attack from a global passive adversary. Although I think I2P (& Kovri) are probably a little better than Tor.

In the case of Grin, as opposed to Tor+I2P, bandwidth is not a big requirement, so it can be sacrificed for stronger anonymity.

I wouldn’t call them Vaults, as it usually means this (that’s what I thought you were going to talk about first):

If you directly share peer IPs, how do you allow any privacy layer?

Very interesting.

Vaults would be a lovely thing for us to support in the future.

Let’s stick with grin wallet i.e {network name}:{pubkey / peer id}

We could begin by implementing Chord DHT and later convert it to Octopus

Just got Wireguard ( installed on a couple of machines, primarily to test out running a personal VPN. Their “Cryptokey Routing” (WireGuard: fast, modern, secure VPN tunnel) concept got me thinking back to this topic. Specifically the concept of public keys verifying point to point communication (and distributing them out of band somehow).

At the heart of WireGuard is a concept called Cryptokey Routing, which works by associating public keys with a list of tunnel IP addresses that are allowed inside the tunnel. Each network interface has a private key and a list of peers. Each peer has a public key. Public keys are short and simple, and are used by peers to authenticate each other. They can be passed around for use in configuration files by any out-of-band method, similar to how one might send their SSH public key to a friend for access to a shell server.

In other words, when sending packets, the list of allowed IPs behaves as a sort of routing table, and when receiving packets, the list of allowed IPs behaves as a sort of access control list.

Makes me wonder if this might be worth a deeper look - I could imagine a possible world where each Grin wallet endpoint is running an embedded WireGuard and communicates with other endpoints based on an “internal” (to the VPN) IP and a known public key.

Edit: adding some info on the Wireguard protocol and encryption used (mainly a wishlist of modern “best practice”) -

  • ChaCha20 for symmetric encryption, authenticated with Poly1305, using RFC7539’s AEAD construction
  • Curve25519 for ECDH
  • BLAKE2s for hashing and keyed hashing, described in RFC7693
  • SipHash24 for hashtable keys
  • HKDF for key derivation, as described in RFC5869

Wireguard is an implementation of the Noise Protocol

Could his suggestion not be done with ?

i dont know, octopus dht just needs a chord implementation to begin with

Welcome to Matrix
An open network for secure, decentralized communication

@tianshi I’ve been looking at Matrix as well in the context of transaction building. Do you have hands on experience using it? It appeared a bit… unstable and full of friction… last time I checked it out.

Because there are no addresses in Mimblewimble and transacting requires interaction between sender and receiver.


No; the wallet doesn’t care what IP address you use. It scans all new outputs and rangeproofs to see which ones could have been produced from your private keys.

1 Like

You could create outputs in advance if you knew the amount to receive, but you still need interaction with the sender to create the transaction, so there’s no point in doing that.

1 Like

i think its better for grin

1 Like

I am interested in how IPFS protocols and implementations can be used in communication or collaboration between senders and recipients of grin.

To broaden the reference resources, see the following:

And perhaps more specifically regarding URL format: