Ğ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.