Commit 45094689 authored by Pascal Engélibert's avatar Pascal Engélibert

Client stores mix confirms in LevelDB

parent e5d34093
......@@ -23,9 +23,15 @@ https://www.ietf.org/rfc/rfc3092.txt <- Very important RFC, please read it
import asyncio, getpass, random
import ubjson
import plyvel
import libnacl.sign
from utils import *
VERSION = "0.1.0"
AUTHORS = ["Pascal Engélibert <tuxmain@zettascript.org>"]
DIR = "~/.gmixer"
class Confirmation():
def __init__(self, client_pubkey, node_pubkey, raw):
self.client_pubkey = client_pubkey
......@@ -44,6 +50,21 @@ class Confirmation():
self.out_comment = data["out_comment"]
self.out_amount = int(data["out_amount"])
self.out_base = int(data["out_base"])
def to_dict(self):
return {
"client_pubkey": self.client_pubkey,
"node_pubkey": self.node_pubkey,
"raw": self.raw,
"sender_pubkey": self.sender_pubkey,
"in_comment": self.in_comment,
"in_amount": self.in_amount,
"in_base": self.in_base,
"receiver_pubkey": self.receiver_pubkey,
"out_comment": self.out_comment,
"out_amount": self.out_amount,
"out_base": self.out_base
}
def get_peers(host, proxy=None, proxy_onion_only=False):
header, content = sdata(host, "GET", "/pubkey/list", proxy=proxy, proxy_onion_only=proxy_onion_only)
......@@ -83,7 +104,7 @@ def build_path(peers, receiver, layers=3):
path.append(receiver)
return host, path
def mix(amount, base, sender, path, host, proxy=None, proxy_onion_only=False):
def mix(db_txs, amount, base, sender, path, host, proxy=None, proxy_onion_only=False, send_tx=True):
start_time = time.time()
onetime_keys = []
......@@ -153,18 +174,19 @@ def mix(amount, base, sender, path, host, proxy=None, proxy_onion_only=False):
print("Bad comment #1")
continue
confirms = []
raw_confirms = []
offset = 64
while offset+4 < len(data):
length = bin_to_int(data[offset:offset+4])
offset += 4
confirms.append(data[offset:offset+length])
raw_confirms.append(data[offset:offset+length])
offset += length
if len(confirms) != len(path)-1:
print("Bad number of confirmations ("+str(len(confirms))+")")
if len(raw_confirms) != len(path)-1:
print("Bad number of confirmations ("+str(len(raw_confirms))+")")
confirms = []
i = 0
for raw in confirms:
for raw in raw_confirms:
raw = onetime_keys[i].decrypt_seal(raw)
try:
confirm = Confirmation(sender.pubkey, path[i], raw)
......@@ -190,16 +212,27 @@ def mix(amount, base, sender, path, host, proxy=None, proxy_onion_only=False):
print("Bad out_comment #"+str(i))
return
confirms.append(confirm)
i += 1
print("OK, total duration = "+str(round(time.time()-start_time, 2))+"s")
if not send_tx:
print("Remind: no-tx mode")
if input("OK? [yn]: ").lower() == "y":
sendTransaction(sender, path[0], amount, out_comment)
exit()
db_txs.put(out_comment.encode(), PublicKey(sender.pubkey).encrypt_seal(ubjson.dumpb({
"sender": sender.pubkey,
"path": path,
"amount": amount,
"onetime_keys": [ot_keys.hex_sk().decode() for ot_keys in onetime_keys],
"confirms": [confirm.to_dict() for confirm in confirms]
})))
if send_tx:
sendTransaction(sender, path[0], amount, out_comment)
return
async def test1(host, receiver, amount=1000, layers=3, proxy=None, proxy_onion_only=False):
async def test1(db_txs, host, receiver, amount=1000, layers=3, proxy=None, proxy_onion_only=False, send_tx=True):
salt = getpass.getpass("Salt: ")
password = getpass.getpass("Psw: ")
keys = SigningKey.from_credentials(salt, password) # sender
......@@ -221,11 +254,11 @@ async def test1(host, receiver, amount=1000, layers=3, proxy=None, proxy_onion_o
if input("OK? [yn]: ").lower() == "y":
break
mix(amount, 0, keys, path, host1, proxy, proxy_onion_only)
mix(db_txs, amount, 0, keys, path, host1, proxy, proxy_onion_only, send_tx)
if __name__ == "__main__":
if "--help" in sys.argv:
print("""ĞMixer-py client v0.1.0
print("ĞMixer-py client "+VERSION+"""
Options:
-r <pubkey> receiver pubkey
......@@ -234,13 +267,20 @@ Options:
-h <host> <port> host for sync peer list
-p <host> <port> SOCKS5 proxy
--onion use proxy only when connecting to .onion
-d <path> config directory (default ~/.gmixer)
--no-tx Do not send transaction (for debug)
Example:
python3 client.py -h 127.0.0.1 10951 -r 78ZwwgpgdH5uLZLbThUQH7LKwPgjMunYfLiCfUCySkM8 -p 127.0.0.1 9050 --onion
python3 client.py -h svetsae7j3usrycn.onion 10951 -r 78ZwwgpgdH5uLZLbThUQH7LKwPgjMunYfLiCfUCySkM8 -p 127.0.0.1 9050 --onion
⤷ send 10Ğ1 to Duniter developers
""")
exit()
DIR = os.path.expanduser(getargv("-d", DIR))
if DIR != "" and DIR[len(DIR)-1] == "/":
DIR = DIR[:len(DIR)-1] # Remove last slash
os.makedirs(DIR, exist_ok=True)
receiver = getargv("-r", "")
if receiver == "":
print("Error: No receiver set (try option --help)")
......@@ -256,5 +296,8 @@ python3 client.py -h 127.0.0.1 10951 -r 78ZwwgpgdH5uLZLbThUQH7LKwPgjMunYfLiCfUCy
if "-p" in sys.argv:
proxy = (getargv("-p", "127.0.0.1", 1), int(getargv("-p", 9050, 2)))
proxy_onion_only = "--onion" in sys.argv
send_tx = not "--no-tx" in sys.argv
db_txs = plyvel.DB(DIR+"/client_db_txs", create_if_missing=True)
asyncio.get_event_loop().run_until_complete(test1((host, port), receiver, amount, layers, proxy, proxy_onion_only))
asyncio.get_event_loop().run_until_complete(test1(db_txs, (host, port), receiver, amount, layers, proxy, proxy_onion_only, send_tx))
......@@ -175,6 +175,7 @@ def readConfig(cdir):
conf["crypto"].setdefault("id_password", ID_PASSWORD)
conf.setdefault("mix", {})
conf["mix"].setdefault("mix_interval", MIX_INTERVAL)
conf["mix"].setdefault("mix_min_txs", MIX_MIN_TXS)
conf["mix"].setdefault("mix_req_age_max", MIX_REQ_AGE_MAX)
with open(cdir+"/config.json", "w") as configfile:
......@@ -752,7 +753,7 @@ if __name__ == "__main__":
elif "-v" in sys.argv:
print(VERSION)
elif "--help" in sys.argv:
print("\
ĞMixer-py Server "+VERSION+"\n\
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment