Skip to content
Snippets Groups Projects

ĞMixer-py

ĞMixer is a Duniter currency mixer to anonymize transactions. This implementation can run in an onion network, guaranteeing a strong anonymity.

How to install it

➤ Debian (Ubuntu, Mint, etc.)

sh install_gmixer.sh

➤ Archlinux

From pacman repo:

sudo pacman -S --needed python python-pip leveldb python-plyvel libsodium python-libnacl python-ubjson python-plyvel python-pysocks

From AUR with python-duniterpy and silkaj:

pikaur -S --needed python-duniterpy silkaj

Not available as PKGBUILD but on pypi:

sudo pip install --upgrade nest_asyncio

➤ Other Linux

Install dependencies:

libleveldb-dev=>1.20 is required for plyvel. If you can only get an older version with your package manager, build it by hand. (currently it it the case for Debian Stretch, not for Archlinux)

Install the following packages: libleveldb-dev libsodium-dev python3 python3-pip

sudo pip3 install libnacl duniterpy silkaj py-ubjson plyvel PySocks nest_asyncio

python3 --version
# If Python < 3.6:
sudo pip3 install python2_secrets

How to use it

Create config & data dir: (change ~/.config/gmixer-g1, so you can run different servers with different configs) (note that each server must have different dir)

python3 server.py -i -d ~/.config/gmixer-g1

Edit config and set your values. If you are not using any proxy, bind_ and public_ addresses should be the same. If salt or password are empty, they will be asked at runtime. For security reasons, it is not a good idea to write them in commandline.

The server must know other nodes on the network. You can find here the list refreshed in real-time and the content to put into your peers file:

Now, start the server:

python3 server.py -s
# Use -d if using a different dir than default
# Use -P for automatic fetch of public IP address

Configure a proxy

To use a SOCKS5 proxy for client connections, set the client.proxy value in config.json as following:

"proxy": ["127.0.0.1", 8080], // ["address", port] or null
"proxy_onion_only": false

To use a proxy only when connecting to a .onion address, set the client.proxy_onion_only value to true:

"proxy": ["127.0.0.1", 9050],
"proxy_onion_only": true

If using a reverse proxy (i.e. Tor hidden service), example:

"bind_host": "127.0.0.1", # local address set in torrc file
"bind_port": 10951,
"public_host": "svetsae7j3usrycn.onion", // other nodes contact me with this address
"public_port": 10951

To unactivate proxy, set client.proxy to null.

Protocols

Documents

Identity signature

A document which explicitly link a ĞMixer node which uses PUBKEY to another member pubkey.

sign(
	ubjson(
		{
			"doctype": "gmixer/idtysig",
			"docver": IDTYSIG_VERSION,
			"pubkey": PUBKEY,
			"sigtime": time()
		}
	)
)

Peer info

A document generated periodically by a node, then sent to other nodes.

{
	"pubkey": PUBKEY,
	"raw": sign(
		ubjson(
			{
				"doctype": "gmixer/peer",
				"docver": PEER_VERSION,
				"currency": CURRENCY,
				"pubkey": PUBKEY,
				"sigtime": time(),
				"host": [PUBLIC_ADDR, PUBLIC_PORT],
				"idty": IDTY_PUBKEY,
				"idtysig": IDTY_SIG,
				"peers": [
					{
						"hash": PEER_HASH,
						"up_in": True|False|None,
						"up_out": True|False|None
					},
					...
				]
			}
		)
	)
}

Peer info file

A peer info file is useful for connecting a node to an existing network. It contains a list of peer infos. Format: UBJSON.

Confirmation

A document generated by a node, to confirm they engage to send a certain tx if they receive another certain tx.

sign(
	ubjson(
		{
			"document": "gmixer-mixconfirm1",
			"sender_pubkey": self.sender_pubkey,
			"receiver_pubkey": keys.pubkey,
			"in_amount": self.in_amount,
			"in_base": self.in_base,
			"in_seeds": self.in_seeds,
			"receiver_pubkey": self.receiver_pubkey,
			"out_amount": self.out_amount,
			"out_base": self.out_base,
			"out_seeds": self.out_seeds,
			"req_date": self.date,
			"expire_date": self.expire
		}
	)
)

HTTP API

URL is used like commandline arguments. Arguments are separated by slashes. Multiple different commands can be set in the same request.

Command: /json send response in JSON instead of default UBJSON if possible (impossible if response contains binary values)

Command: /peers list known peers (excluding itself)

// response:
"peers": [
	{
		"raw": PEER_INFO,
		"up_in": True|False|None,
		"up_out": True|False|None
	},
	...
]

Command: /info give local peer info

// response:
"info": PEER_INFO

Command: /pubkey get peer pubkey

// response:
"pubkey": PUBKEY

Command: /version get peer version

// response:
"version": VERSION

Command: /new tell the peer about a new peer
Content: a peer info document

Command: /getconfirm/sender_pubkey/in_seed1 get mix confirmation

ENCRYPTED_CONFIRM = encrypt( // to client's one-time key
	CONFIRM
)

// response:
"confirm": sign(
	// binary
	IN_SEED_1
	IN_SEED_2
	length(ENCRYPTED_CONFIRM) // unsigned int 32 bits, Big Endian
	ENCRYPTED_CONFIRM
	CONFIRMS // Each confirm is preceded by its length, as above
)

Command: /mix/sender/amount/base[/client] mix a transaction (set "client" option if request is sent to entry node)

  • If "client": sender is the sender pubkey
  • Else: sender is the sender peer hash

base is not used yet, please set it to 0. (it is not fully handled by dependencies)

// response:
"mix_ok": IN_SEED1

TODO: update; translate into English

Avant d'envoyer une requête mix, le client crée plusieurs clés publiques à usage unique (une par nœud mixeur) dont il garde les identifiants.

L'URL contient la clé publique du compte émetteur de la transaction, ainsi que la somme transmise. Ces données seront utilisées par le nœud ĞMix pour vérifier l'existance de la transaction.

Le contenu de la requête est chiffré avec la clé publique du nœud receveur puis signé par la clé publique du compte émetteur. Il est composé de la clé publique (ASCII, 44 caractères) du compte auquel le nœud doit renvoyer la transaction. Si cette clé correspond à un nœud ĞMix faisant partie du chemin prévu de la transaction, elle doit être immédiatement suivie (sans séparateur) d'une des clés à usage unique puis des données qui doivent être envoyées à ce nœud (syntaxe décrite par ce même paragraphe, signature exclue : pour garder l'anonymat de l'émetteur d'origine, les données doivent être signées par le nœud qui envoie le paquet).

Command: /confirm/receiver_hash/out_seed1 confirm a transaction

TODO: finish; translate into English

Quand le dernier nœud du chemin a reçu la requête mix (c-à-d une fois que tous les nœuds ont reçu la commande), celui-ci envoie une requête confirm au nœud qui l'a contacté. La requête va ainsi jusqu'au client d'origine.

L'URL contient la clé publique du nœud qui envoie la requête et le commentaire de la transaction qu'il doit recevoir (pour lui in_comment, pour le nœud qu'il contacte out_comment), qui sert d'ID de transaction entre les deux nœuds.