diff --git a/.gitignore b/.gitignore
index 0aae2bb..ce381d7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,6 +6,8 @@
blockchain.cache
env
htmlcov/
+joinmarket.cfg
+joinmarket.cfg.bak
scripts/joinmarket.cfg
scripts/cmttools/commitments.json
scripts/blacklist
@@ -13,6 +15,7 @@ alicekey
alicepubkey
bobkey
commitments_debug.txt
+dummyext
deps/
jmvenv/
logs/
diff --git a/.travis.yml b/.travis.yml
index a4f5026..a122150 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -16,19 +16,31 @@ matrix:
- python-qt4 python-sip
- os: linux
services: docker
- env: DOCKER_IMG_JM=xenial
+ env: DOCKER_IMG_JM=xenial-py2
- os: linux
services: docker
- env: DOCKER_IMG_JM=bionic
+ env: DOCKER_IMG_JM=xenial-py3
- os: linux
services: docker
- env: DOCKER_IMG_JM=stretch
+ env: DOCKER_IMG_JM=bionic-py2
- os: linux
services: docker
- env: DOCKER_IMG_JM=centos7
+ env: DOCKER_IMG_JM=bionic-py3
- os: linux
services: docker
- env: DOCKER_IMG_JM=fedora27
+ env: DOCKER_IMG_JM=stretch-py2
+ - os: linux
+ services: docker
+ env: DOCKER_IMG_JM=stretch-py3
+ - os: linux
+ services: docker
+ env: DOCKER_IMG_JM=centos7-py2
+ - os: linux
+ services: docker
+ env: DOCKER_IMG_JM=fedora27-py2
+ - os: linux
+ services: docker
+ env: DOCKER_IMG_JM=fedora27-py3
before_install:
- do_on(){ if [ "$TRAVIS_OS_NAME" = "$1" ]; then shift; $@ ; fi; }
- on_host(){ if [ -z "$DOCKER_IMG_JM" ]; then $@ ; fi; }
diff --git a/install.sh b/install.sh
index 22b3e41..a24f145 100755
--- a/install.sh
+++ b/install.sh
@@ -14,10 +14,18 @@ sha256_verify ()
deps_install ()
{
if [[ ${install_os} == 'debian' ]]; then
- if deb_deps_install "python-virtualenv curl python-dev python-pip build-essential automake pkg-config libtool libgmp-dev"; then
- return 0
+ if is_python3; then
+ if deb_deps_install "python-virtualenv curl python3-dev python3-pip build-essential automake pkg-config libtool libgmp-dev"; then
+ return 0
+ else
+ return 1
+ fi
else
- return 1
+ if deb_deps_install "python-virtualenv curl python-dev python-pip build-essential automake pkg-config libtool libgmp-dev"; then
+ return 0
+ else
+ return 1
+ fi
fi
else
echo "OS can not be determined. Trying to build."
@@ -360,6 +368,18 @@ os_is_deb ()
( which apt-get && which dpkg-query ) 2>/dev/null 1>&2
}
+is_python3 ()
+{
+ if [[ ${python} == 'python3' ]]; then
+ return 0
+ fi
+ if eval "${python} -c 'import sys; sys.exit(0) if sys.version_info >= (3,0) else sys.exit(1)'"; then
+ return 0
+ else
+ return 1
+ fi
+}
+
install_get_os ()
{
if os_is_deb; then
@@ -372,8 +392,14 @@ install_get_os ()
qt_deps_install ()
{
if [[ ${install_os} == 'debian' ]]; then
- if deb_deps_install "python-qt4 python-sip"; then
- return 0;
+ if is_python3; then
+ if deb_deps_install "python3-pyqt4 python3-sip"; then
+ return 0;
+ fi
+ else
+ if deb_deps_install "python-qt4 python-sip"; then
+ return 0;
+ fi
fi
else
return 1
diff --git a/jmbase/jmbase/__init__.py b/jmbase/jmbase/__init__.py
index 91dbab6..e5a6eb4 100644
--- a/jmbase/jmbase/__init__.py
+++ b/jmbase/jmbase/__init__.py
@@ -3,7 +3,7 @@ from __future__ import (absolute_import, division,
from builtins import *
from .support import (get_log, chunks, debug_silence, debug_dump_object,
- joinmarket_alert, core_alert, get_password, _byteify,
+ joinmarket_alert, core_alert, get_password,
set_logging_level)
-from commands import *
+from .commands import *
diff --git a/jmbase/jmbase/bigstring.py b/jmbase/jmbase/bigstring.py
index dcc90a1..ecfe9cc 100644
--- a/jmbase/jmbase/bigstring.py
+++ b/jmbase/jmbase/bigstring.py
@@ -1,19 +1,25 @@
from __future__ import (absolute_import, division,
print_function, unicode_literals)
from builtins import * # noqa: F401
-try:
- from cStringIO import StringIO
-except ImportError: #pragma: no cover
- from StringIO import StringIO #pragma: no cover
-from itertools import count
+import itertools
from twisted.protocols import amp
-CHUNK_MAX = 0xffff
-class BigString(amp.Argument):
+def split_string(x, size):
+ return list(x[i*size:(i+1)*size] for i in range((len(x)+size-1)//size))
+
+class StringList(amp.Argument):
+ def fromBox(self, name, strings, objects, proto):
+ nk = amp._wireNameToPythonIdentifier(name)
+ objects[nk] = list(itertools.takewhile(bool, (strings.pop(b'%s.%d' % (name, i), None) for i in itertools.count())))
+
+ def toBox(self, name, strings, objects, proto):
+ for i, elem in enumerate(objects.pop(name)):
+ strings[b'%s.%d' % (name, i)] = elem
+
+class BigString(StringList):
"""
A byte-string amp.Argument with no 65,535 length limit.
-
Each value for a key/value pair in an AMP box may not
exceed 65,535 bytes in length. So if we *really* want to
send potentially larger values, this class will implicitly
@@ -22,29 +28,18 @@ class BigString(amp.Argument):
names by prefixing this Argument's key name to a counter.
"""
def fromBox(self, name, strings, objects, proto):
- value = StringIO()
- value.write(strings.get(name))
- for counter in count(2):
- chunk = strings.get("%s.%d" % (name, counter))
- if chunk is None:
- break
- value.write(chunk)
- objects[name] = self.buildvalue(value.getvalue())
-
- def buildvalue(self, value):
- return value
+ nk = amp._wireNameToPythonIdentifier(name)
+ StringList.fromBox(self, name, strings, objects, proto)
+ objects[nk] = b''.join((elem) for elem in objects[nk]).decode('utf-8')
def toBox(self, name, strings, objects, proto):
- value = StringIO(self.fromvalue(objects[name]))
- firstChunk = value.read(CHUNK_MAX)
- strings[name] = firstChunk
- counter = 2
- while True:
- nextChunk = value.read(CHUNK_MAX)
- if not nextChunk:
- break
- strings["{}.{}".format(name, counter).encode('ascii')] = nextChunk
- counter += 1
-
- def fromvalue(self, value):
- return value
+ obj = self.retrieve(objects, amp._wireNameToPythonIdentifier(name), proto).encode('utf-8')
+ objects[name] = split_string(obj, amp.MAX_VALUE_LENGTH)
+ StringList.toBox(self, name, strings, objects, proto)
+
+class BigUnicode(BigString):
+ def toString(self, inObject):
+ return BigString.toString(self, inObject.encode('utf-8'))
+
+ def fromString(self, inString):
+ return BigString.fromString(self, inString).decode('utf-8')
diff --git a/jmbase/jmbase/commands.py b/jmbase/jmbase/commands.py
index 590a1bd..21eb24c 100644
--- a/jmbase/jmbase/commands.py
+++ b/jmbase/jmbase/commands.py
@@ -7,7 +7,7 @@ messaging protocol (*not* Joinmarket p2p protocol).
Used for AMP asynchronous messages.
"""
from twisted.protocols.amp import Boolean, Command, Integer, Unicode
-from .bigstring import BigString
+from .bigstring import BigUnicode
class DaemonNotReady(Exception):
pass
@@ -185,7 +185,7 @@ class JMOffers(JMCommand):
"""Return the entire contents of the
orderbook to TAKER, as a json-ified dict.
"""
- arguments = [(b'orderbook', BigString())]
+ arguments = [(b'orderbook', BigUnicode())]
class JMFillResponse(JMCommand):
"""Returns ioauth data from MAKER if successful.
diff --git a/jmbase/jmbase/support.py b/jmbase/jmbase/support.py
index 0109ce2..d4219b1 100644
--- a/jmbase/jmbase/support.py
+++ b/jmbase/jmbase/support.py
@@ -1,6 +1,7 @@
from __future__ import (absolute_import, division,
print_function, unicode_literals)
from builtins import * # noqa: F401
+from future.utils import iteritems
import sys
@@ -53,13 +54,16 @@ def chunks(d, n):
return [d[x:x + n] for x in range(0, len(d), n)]
def get_password(msg): #pragma: no cover
- return getpass(msg)
+ password = getpass(msg)
+ if not isinstance(password, bytes):
+ password = password.encode('utf-8')
+ return password
def debug_dump_object(obj, skip_fields=None):
if skip_fields is None:
skip_fields = []
log.debug('Class debug dump, name:' + obj.__class__.__name__)
- for k, v in obj.__dict__.iteritems():
+ for k, v in iteritems(obj.__dict__):
if k in skip_fields:
continue
if k == 'password' or k == 'given_password':
@@ -72,20 +76,3 @@ def debug_dump_object(obj, skip_fields=None):
log.debug(pprint.pformat(v))
else:
log.debug(str(v))
-
-def _byteify(data, ignore_dicts = False):
- # if this is a unicode string, return its string representation
- if isinstance(data, unicode):
- return data.encode('utf-8')
- # if this is a list of values, return list of byteified values
- if isinstance(data, list):
- return [ _byteify(item, ignore_dicts=True) for item in data ]
- # if this is a dictionary, return dictionary of byteified keys and values
- # but only if we haven't already byteified it
- if isinstance(data, dict) and not ignore_dicts:
- return {
- _byteify(key, ignore_dicts=True): _byteify(value, ignore_dicts=True)
- for key, value in data.iteritems()
- }
- # if it's anything else, return it in its original form
- return data
diff --git a/jmbitcoin/jmbitcoin/secp256k1_main.py b/jmbitcoin/jmbitcoin/secp256k1_main.py
index c2a698a..3d1dca2 100644
--- a/jmbitcoin/jmbitcoin/secp256k1_main.py
+++ b/jmbitcoin/jmbitcoin/secp256k1_main.py
@@ -2,7 +2,7 @@
from __future__ import (absolute_import, division,
print_function, unicode_literals)
from builtins import * # noqa: F401
-from future.utils import bytes_to_native_str
+from future.utils import native_bytes, bytes_to_native_str
import binascii
import hashlib
import sys
@@ -53,11 +53,8 @@ def bin_to_b58check(inp, magicbyte=b'\x00'):
checksum = bin_dbl_sha256(inp_fmtd)[:4]
return b58encode(inp_fmtd + checksum)
-def bytes_to_hex_string(b):
- return b.encode('hex')
-
def safe_from_hex(s):
- return s.decode('hex')
+ return binascii.unhexlify(s)
def from_int_to_byte(a):
return struct.pack(b'B', a)
@@ -69,7 +66,7 @@ def from_string_to_bytes(a):
return a if isinstance(a, bytes) else bytes(a, 'utf-8')
def safe_hexlify(a):
- return str(binascii.hexlify(a), 'utf-8')
+ return binascii.hexlify(a).decode('ascii')
class SerializationError(Exception):
"""Base class for serialization errors"""
@@ -109,7 +106,7 @@ def b58encode(b):
"""Encode bytes to a base58-encoded string"""
# Convert big-endian bytes to integer
- n = int('0x0' + binascii.hexlify(b).decode('utf8'), 16)
+ n = int('0x0' + binascii.hexlify(b).decode('ascii'), 16)
# Divide that integer into bas58
res = []
@@ -120,7 +117,7 @@ def b58encode(b):
# Encode leading zeros as base58 zeros
czero = b'\x00'
- if sys.version > '3':
+ if sys.version_info >= (3,0):
# In Python3 indexing a bytes returns numbers, not characters.
czero = 0
pad = 0
@@ -252,6 +249,8 @@ def bin_hash160(string):
return hashlib.new('ripemd160', intermed).digest()
def hash160(string):
+ if not isinstance(string, bytes):
+ string = string.encode('utf-8')
return safe_hexlify(bin_hash160(string))
def bin_sha256(string):
@@ -260,9 +259,11 @@ def bin_sha256(string):
return hashlib.sha256(binary_data).digest()
def sha256(string):
- return bytes_to_hex_string(bin_sha256(string))
+ return safe_hexlify(bin_sha256(string))
def bin_dbl_sha256(bytes_to_hash):
+ if not isinstance(bytes_to_hash, bytes):
+ bytes_to_hash = bytes_to_hash.encode('utf-8')
return hashlib.sha256(hashlib.sha256(bytes_to_hash).digest()).digest()
def dbl_sha256(string):
@@ -306,7 +307,7 @@ def hex_to_b58check(inp, magicbyte=b'\x00'):
return bin_to_b58check(binascii.unhexlify(inp), magicbyte)
def b58check_to_hex(inp):
- return binascii.hexlify(b58check_to_bin(inp))
+ return binascii.hexlify(b58check_to_bin(inp)).decode('ascii')
def pubkey_to_address(pubkey, magicbyte=0):
if len(pubkey) in [66, 130]:
@@ -351,20 +352,20 @@ def ecdsa_sign(msg, priv, formsg=False, usehex=True):
hashed_msg = message_sig_hash(msg)
if usehex:
#arguments to raw sign must be consistently hex or bin
- hashed_msg = binascii.hexlify(hashed_msg)
+ hashed_msg = binascii.hexlify(hashed_msg).decode('ascii')
sig = ecdsa_raw_sign(hashed_msg, priv, usehex, rawmsg=True, formsg=formsg)
#note those functions only handles binary, not hex
if usehex:
sig = binascii.unhexlify(sig)
- return base64.b64encode(sig)
+ return base64.b64encode(sig).decode('ascii')
def ecdsa_verify(msg, sig, pub, usehex=True):
hashed_msg = message_sig_hash(msg)
sig = base64.b64decode(sig)
if usehex:
#arguments to raw_verify must be consistently hex or bin
- hashed_msg = binascii.hexlify(hashed_msg)
- sig = binascii.hexlify(sig)
+ hashed_msg = binascii.hexlify(hashed_msg).decode('ascii')
+ sig = binascii.hexlify(sig).decode('ascii')
return ecdsa_raw_verify(hashed_msg, pub, sig, usehex, rawmsg=True)
#Use secp256k1 to handle all EC and ECDSA operations.
@@ -389,7 +390,7 @@ def hexbin(func):
if isinstance(returnval, bool):
return returnval
else:
- return binascii.hexlify(returnval)
+ return binascii.hexlify(returnval).decode('ascii')
else:
return func(*args, **kwargs)
@@ -415,7 +416,10 @@ def privkey_to_pubkey_inner(priv, usehex):
and return compressed/uncompressed public key as appropriate.'''
compressed, priv = read_privkey(priv)
#secp256k1 checks for validity of key value.
- newpriv = secp256k1.PrivateKey(secret=bytes_to_native_str(priv))
+ if sys.version_info >= (3,0):
+ newpriv = secp256k1.PrivateKey(secret=native_bytes(priv))
+ else:
+ newpriv = secp256k1.PrivateKey(secret=bytes_to_native_str(priv))
return newpriv.public_key.format(compressed)
def privkey_to_pubkey(priv, usehex=True):
@@ -440,7 +444,10 @@ def multiply(s, pub, usehex, rawpub=True, return_serialized=True):
'''
newpub = secp256k1.PublicKey(pub)
#see note to "tweak_mul" function in podle.py
- res = newpub.multiply(bytes_to_native_str(s))
+ if sys.version_info >= (3,0):
+ res = newpub.multiply(native_bytes(s))
+ else:
+ res = newpub.multiply(bytes_to_native_str(s))
if not return_serialized:
return res
return res.format()
diff --git a/jmbitcoin/jmbitcoin/secp256k1_transaction.py b/jmbitcoin/jmbitcoin/secp256k1_transaction.py
index e9d0aff..bca5e70 100644
--- a/jmbitcoin/jmbitcoin/secp256k1_transaction.py
+++ b/jmbitcoin/jmbitcoin/secp256k1_transaction.py
@@ -14,7 +14,7 @@ from jmbitcoin.bech32 import *
# Transaction serialization and deserialization
def deserialize(txinp):
- if isinstance(txinp, basestring) and re.match('^[0-9a-fA-F]*$', txinp):
+ if isinstance(txinp, basestring) and not isinstance(txinp, bytes) and re.match('^[0-9a-fA-F]*$', txinp):
tx = BytesIO(binascii.unhexlify(txinp))
hexout = True
else:
@@ -23,7 +23,7 @@ def deserialize(txinp):
def hex_string(scriptbytes, hexout):
if hexout:
- return binascii.hexlify(scriptbytes)
+ return binascii.hexlify(scriptbytes).decode('ascii')
else:
return scriptbytes
@@ -156,7 +156,7 @@ def serialize(tx):
o.write(struct.pack(b'
# Copyright (C) 2014 by phelix / blockchained.com
#
@@ -23,8 +25,9 @@ from __future__ import absolute_import, print_function
import errno
import socket
import base64
-import httplib
+import http.client
import json
+from decimal import Decimal
from jmclient import get_log
jlog = get_log()
@@ -56,8 +59,8 @@ class JsonRpc(object):
def __init__(self, host, port, user, password, wallet_file=""):
self.host = host
- self.port = port
- self.conn = httplib.HTTPConnection(self.host, self.port)
+ self.port = int(port)
+ self.conn = http.client.HTTPConnection(self.host, self.port)
self.authstr = "%s:%s" % (user, password)
if len(wallet_file) > 0:
self.url = "/wallet/" + wallet_file
@@ -76,7 +79,7 @@ class JsonRpc(object):
headers = {"User-Agent": "joinmarket",
"Content-Type": "application/json",
"Accept": "application/json"}
- headers["Authorization"] = "Basic %s" % base64.b64encode(self.authstr)
+ headers["Authorization"] = b"Basic %s" % base64.b64encode(self.authstr.encode('utf-8'))
body = json.dumps(obj)
@@ -97,20 +100,26 @@ class JsonRpc(object):
data = response.read()
- return json.loads(data)
+ return json.loads(data.decode('utf-8'), parse_float=Decimal)
except JsonRpcConnectionError as exc:
raise exc
- except httplib.BadStatusLine:
+ except http.client.BadStatusLine:
return "CONNFAILURE"
except socket.error as e:
- if e.errno != errno.ECONNRESET:
+ if e.errno == errno.ECONNRESET:
+ jlog.warn('Connection was reset, attempting reconnect.')
+ self.conn.close()
+ self.conn.connect()
+ continue
+ elif e.errno == errno.EPIPE:
+ jlog.warn('Connection had broken pipe, attempting reconnect.')
+ self.conn.close()
+ self.conn.connect()
+ continue
+ else:
jlog.error('Unhandled connection error ' + str(e))
raise e
- jlog.warn('Connection was reset, attempting reconnect.')
- self.conn.close()
- self.conn.connect()
- continue
except Exception as exc:
raise JsonRpcConnectionError("JSON-RPC connection failed. Err:" +
repr(exc))
@@ -136,7 +145,7 @@ class JsonRpc(object):
response_received = True
break
#Failure means keepalive timed out, just make a new one
- self.conn = httplib.HTTPConnection(self.host, self.port)
+ self.conn = http.client.HTTPConnection(self.host, self.port)
if not response_received:
raise JsonRpcConnectionError("Unable to connect over RPC")
if response["id"] != currentId:
diff --git a/jmclient/jmclient/maker.py b/jmclient/jmclient/maker.py
index bf1b858..e7c56cf 100644
--- a/jmclient/jmclient/maker.py
+++ b/jmclient/jmclient/maker.py
@@ -1,13 +1,15 @@
#! /usr/bin/env python
-from __future__ import print_function
+from __future__ import (absolute_import, division,
+ print_function, unicode_literals)
+from builtins import * # noqa: F401
import base64
import pprint
import sys
from binascii import unhexlify
-import btc
-from btc import SerializationError, SerializationTruncationError
+from . import btc
+from .btc import SerializationError, SerializationTruncationError
from jmclient.configure import jm_single
from jmbase.support import get_log
from jmclient.support import (calc_cj_fee)
@@ -97,7 +99,7 @@ class Maker(object):
# Need to choose an input utxo pubkey to sign with
# (no longer using the coinjoin pubkey from 0.2.0)
# Just choose the first utxo in self.utxos and retrieve key from wallet.
- auth_address = utxos[utxos.keys()[0]]['address']
+ auth_address = utxos[list(utxos.keys())[0]]['address']
auth_key = self.wallet.get_key_from_addr(auth_address)
auth_pub = btc.privtopub(auth_key)
btc_sig = btc.ecdsa_sign(kphex, auth_key)
@@ -140,7 +142,7 @@ class Maker(object):
#also, the items in witness are not serialize_script-ed.
sigmsg = b''.join(btc.serialize_script_unit(x)
for x in txs['ins'][index]['txinwitness']) + sigmsg
- sigs.append(base64.b64encode(sigmsg))
+ sigs.append(base64.b64encode(sigmsg).decode('ascii'))
return (True, sigs)
def verify_unsigned_tx(self, txd, offerinfo):
diff --git a/jmclient/jmclient/old_mnemonic.py b/jmclient/jmclient/old_mnemonic.py
index 32d6761..df8937c 100644
--- a/jmclient/jmclient/old_mnemonic.py
+++ b/jmclient/jmclient/old_mnemonic.py
@@ -1,4 +1,7 @@
#!/usr/bin/env python
+from __future__ import (absolute_import, division,
+ print_function, unicode_literals)
+from builtins import * # noqa: F401
#
# Electrum - lightweight Bitcoin client
# Copyright (C) 2011 thomasv@gitorious
@@ -244,19 +247,19 @@ n = 1626
def mn_encode(message):
assert len(message) % 8 == 0
out = []
- for i in range(len(message) / 8):
+ for i in range(len(message) // 8):
word = message[8 * i:8 * i + 8]
x = int(word, 16)
w1 = (x % n)
- w2 = ((x / n) + w1) % n
- w3 = ((x / n / n) + w2) % n
+ w2 = ((x // n) + w1) % n
+ w3 = ((x // n // n) + w2) % n
out += [words[w1], words[w2], words[w3]]
return out
def mn_decode(wlist):
out = ''
- for i in range(len(wlist) / 3):
+ for i in range(len(wlist) // 3):
word1, word2, word3 = wlist[3 * i:3 * i + 3]
w1 = words.index(word1)
w2 = (words.index(word2)) % n
diff --git a/jmclient/jmclient/output.py b/jmclient/jmclient/output.py
index 7393064..7457123 100644
--- a/jmclient/jmclient/output.py
+++ b/jmclient/jmclient/output.py
@@ -1,3 +1,6 @@
+from __future__ import (absolute_import, division,
+ print_function, unicode_literals)
+from builtins import * # noqa: F401
from binascii import hexlify
@@ -11,7 +14,7 @@ def fmt_utxos(utxos, wallet, prefix=''):
def fmt_utxo(utxo):
- return '{}:{}'.format(hexlify(utxo[0]), utxo[1])
+ return '{}:{}'.format(hexlify(utxo[0]).decode('ascii'), utxo[1])
def fmt_tx_data(tx_data, wallet):
diff --git a/jmclient/jmclient/podle.py b/jmclient/jmclient/podle.py
index bf2abfe..142e3d3 100644
--- a/jmclient/jmclient/podle.py
+++ b/jmclient/jmclient/podle.py
@@ -1,5 +1,7 @@
#!/usr/bin/env python
-from __future__ import print_function
+from __future__ import (absolute_import, division,
+ print_function, unicode_literals)
+from builtins import * # noqa: F401
#Proof Of Discrete Logarithm Equivalence
#For algorithm steps, see https://gist.github.com/AdamISZ/9cbba5e9408d23813ca8
import os
@@ -7,7 +9,8 @@ import sys
import hashlib
import json
import binascii
-from btc import multiply, add_pubkeys, getG, podle_PublicKey,\
+import struct
+from .btc import multiply, add_pubkeys, getG, podle_PublicKey,\
podle_PrivateKey, encode, decode, N, podle_PublicKey_class
@@ -84,7 +87,7 @@ class PoDLE(object):
if not isinstance(self.P2, podle_PublicKey_class):
raise PoDLEError("Cannot construct commitment, P2 is not a pubkey")
self.commitment = hashlib.sha256(self.P2.format()).digest()
- return binascii.hexlify(self.commitment)
+ return binascii.hexlify(self.commitment).decode('ascii')
def generate_podle(self, index=0, k=None):
"""Given a raw private key, in hex format,
@@ -123,7 +126,7 @@ class PoDLE(object):
KJ = multiply(k, J.format(), False, return_serialized=False)
self.P2 = getP2(self.priv, J)
self.get_commitment()
- self.e = hashlib.sha256(''.join([x.format(
+ self.e = hashlib.sha256(b''.join([x.format(
) for x in [KG, KJ, self.P, self.P2]])).digest()
k_int = decode(k, 256)
priv_int = decode(self.priv.secret, 256)
@@ -141,7 +144,7 @@ class PoDLE(object):
if not self.commitment:
self.get_commitment()
Phex, P2hex, shex, ehex, commit = [
- binascii.hexlify(x)
+ binascii.hexlify(x).decode('ascii')
for x in [self.P.format(), self.P2.format(), self.s, self.e,
self.commitment]
]
@@ -217,14 +220,14 @@ def getNUMS(index=0):
assert index in range(256)
nums_point = None
for G in [getG(True), getG(False)]:
- seed = G + chr(index)
+ seed = G + struct.pack(b'B', index)
for counter in range(256):
- seed_c = seed + chr(counter)
+ seed_c = seed + struct.pack(b'B', counter)
hashed_seed = hashlib.sha256(seed_c).digest()
#Every x-coord on the curve has two y-values, encoded
#in compressed form with 02/03 parity byte. We just
#choose the former.
- claimed_point = "\x02" + hashed_seed
+ claimed_point = b"\x02" + hashed_seed
try:
nums_point = podle_PublicKey(claimed_point)
return nums_point
@@ -242,11 +245,11 @@ def verify_all_NUMS(write=False):
"""
nums_points = {}
for i in range(256):
- nums_points[i] = binascii.hexlify(getNUMS(i).format())
+ nums_points[i] = binascii.hexlify(getNUMS(i).format()).decode('ascii')
if write:
with open("nums_basepoints.txt", "wb") as f:
from pprint import pformat
- f.write(pformat(nums_points))
+ f.write(pformat(nums_points).encode('utf-8'))
assert nums_points == precomp_NUMS, "Precomputed NUMS points are not valid!"
@@ -279,7 +282,7 @@ def get_podle_commitments():
if not os.path.isfile(PODLE_COMMIT_FILE):
return ([], {})
with open(PODLE_COMMIT_FILE, "rb") as f:
- c = json.loads(f.read())
+ c = json.loads(f.read().decode('utf-8'))
if 'used' not in c.keys() or 'external' not in c.keys():
raise PoDLEError("Incorrectly formatted file: " + PODLE_COMMIT_FILE)
return (c['used'], c['external'])
@@ -306,7 +309,7 @@ def update_commitments(commitment=None,
if os.path.isfile(PODLE_COMMIT_FILE):
with open(PODLE_COMMIT_FILE, "rb") as f:
try:
- c = json.loads(f.read())
+ c = json.loads(f.read().decode('utf-8'))
except ValueError: #pragma: no cover
#Exit conditions cannot be included in tests.
print("the file: " + PODLE_COMMIT_FILE + " is not valid json.")
@@ -335,7 +338,7 @@ def update_commitments(commitment=None,
to_write['used'] = commitments
to_write['external'] = external
with open(PODLE_COMMIT_FILE, "wb") as f:
- f.write(json.dumps(to_write, indent=4))
+ f.write(json.dumps(to_write, indent=4).encode('utf-8'))
def get_podle_tries(utxo, priv=None, max_tries=1, external=False):
used_commitments, external_commitments = get_podle_commitments()
diff --git a/jmclient/jmclient/schedule.py b/jmclient/jmclient/schedule.py
index 90287d3..c89edc5 100644
--- a/jmclient/jmclient/schedule.py
+++ b/jmclient/jmclient/schedule.py
@@ -1,5 +1,7 @@
#!/usr/bin/env python
-from __future__ import print_function
+from __future__ import (absolute_import, division,
+ print_function, unicode_literals)
+from builtins import * # noqa: F401
import copy
from jmclient import (validate_address, rand_exp_array,
rand_norm_array, rand_pow_array, jm_single)
@@ -20,6 +22,7 @@ def get_schedule(filename):
schedule = []
schedule_lines = f.readlines()
for sl in schedule_lines:
+ sl = sl.decode('utf-8')
if sl.startswith("#"):
continue
try:
@@ -213,4 +216,4 @@ def human_readable_schedule_entry(se, amt=None, destn=None):
return ", ".join(hrs)
def schedule_to_text(schedule):
- return "\n".join([",".join([str(y) for y in x]) for x in schedule])
+ return "\n".join([",".join([str(y) for y in x]) for x in schedule]).encode('utf-8')
diff --git a/jmclient/jmclient/slowaes.py b/jmclient/jmclient/slowaes.py
index 258694f..1f0d16e 100644
--- a/jmclient/jmclient/slowaes.py
+++ b/jmclient/jmclient/slowaes.py
@@ -11,6 +11,9 @@
# Licensed under the Apache License, Version 2.0
# http://www.apache.org/licenses/
#
+from __future__ import (absolute_import, division,
+ print_function, unicode_literals)
+from builtins import *
import math
import os
diff --git a/jmclient/jmclient/storage.py b/jmclient/jmclient/storage.py
index 573c572..8c427f9 100644
--- a/jmclient/jmclient/storage.py
+++ b/jmclient/jmclient/storage.py
@@ -1,4 +1,7 @@
-from __future__ import print_function, absolute_import, division, unicode_literals
+from __future__ import (absolute_import, division,
+ print_function, unicode_literals)
+from builtins import * # noqa: F401
+from future.utils import native
import os
import shutil
@@ -244,7 +247,7 @@ class Storage(object):
def _encrypt(self, data, iv):
encrypter = pyaes.Encrypter(
- pyaes.AESModeOfOperationCBC(self._hash.hash, iv=iv))
+ pyaes.AESModeOfOperationCBC(self._hash.hash, iv=native(iv)))
enc_data = encrypter.feed(self.MAGIC_DETECT_ENC + data)
enc_data += encrypter.feed()
@@ -252,7 +255,7 @@ class Storage(object):
def _decrypt(self, data, iv):
decrypter = pyaes.Decrypter(
- pyaes.AESModeOfOperationCBC(self._hash.hash, iv=iv))
+ pyaes.AESModeOfOperationCBC(self._hash.hash, iv=native(iv)))
try:
dec_data = decrypter.feed(data)
dec_data += decrypter.feed()
diff --git a/jmclient/jmclient/support.py b/jmclient/jmclient/support.py
index 34fe1cc..8507d1a 100644
--- a/jmclient/jmclient/support.py
+++ b/jmclient/jmclient/support.py
@@ -1,4 +1,7 @@
-from __future__ import absolute_import, print_function
+from __future__ import (absolute_import, division,
+ print_function, unicode_literals)
+from builtins import * # noqa: F401
+from functools import reduce
import random
from jmbase.support import get_log
@@ -25,7 +28,7 @@ def get_random_bytes(num_bytes, cryptographically_secure=False):
generator = random.SystemRandom()
else:
generator = random
- return bytes(bytearray((generator.randrange(256) for b in xrange(num_bytes))))
+ return bytes(bytearray((generator.randrange(256) for b in range(num_bytes))))
def rand_norm_array(mu, sigma, n):
@@ -43,7 +46,7 @@ def rand_pow_array(power, n):
# for basis of formula, see: http://mathworld.wolfram.com/RandomNumber.html
return [y**(1.0 / power)
for y in [x * 0.0001 for x in random.sample(
- xrange(10000), n)]]
+ range(10000), n)]]
def rand_weighted_choice(n, p_arr):
@@ -58,7 +61,7 @@ def rand_weighted_choice(n, p_arr):
raise ValueError("Sum of probabilities must be 1")
if len(p_arr) != n:
raise ValueError("Need: " + str(n) + " probabilities.")
- cum_pr = [sum(p_arr[:i + 1]) for i in xrange(len(p_arr))]
+ cum_pr = [sum(p_arr[:i + 1]) for i in range(len(p_arr))]
r = random.random()
return sorted(cum_pr + [r]).index(r)
diff --git a/jmclient/jmclient/taker.py b/jmclient/jmclient/taker.py
index b8ee1ca..0f13ed1 100644
--- a/jmclient/jmclient/taker.py
+++ b/jmclient/jmclient/taker.py
@@ -1,12 +1,15 @@
#! /usr/bin/env python
-from __future__ import print_function
+from __future__ import (absolute_import, division,
+ print_function, unicode_literals)
+from builtins import * # noqa: F401
+from future.utils import iteritems
import base64
import pprint
import random
from binascii import hexlify, unhexlify
-import btc
+from . import btc
from jmclient.configure import get_p2sh_vbyte, jm_single, validate_address
from jmbase.support import get_log
from jmclient.support import (calc_cj_fee, weighted_order_choose, choose_orders,
@@ -216,7 +219,7 @@ class Taker(object):
#Initialization has been successful. We must set the nonrespondants
#now to keep track of what changed when we receive the utxo data
- self.nonrespondants = self.orderbook.keys()
+ self.nonrespondants = list(self.orderbook.keys())
return (True, self.cjamount, commitment, revelation, self.orderbook)
@@ -324,7 +327,7 @@ class Taker(object):
self.cjamount):
return False
- self.utxos = {None: self.input_utxos.keys()}
+ self.utxos = {None: list(self.input_utxos.keys())}
return True
def receive_utxos(self, ioauth_data):
@@ -338,7 +341,7 @@ class Taker(object):
#Temporary list used to aggregate all ioauth data that must be removed
rejected_counterparties = []
#Need to authorize against the btc pubkey first.
- for nick, nickdata in ioauth_data.iteritems():
+ for nick, nickdata in iteritems(ioauth_data):
utxo_list, auth_pub, cj_addr, change_addr, btc_sig, maker_pk = nickdata
if not self.auth_counterparty(btc_sig, auth_pub, maker_pk):
jlog.debug(
@@ -358,7 +361,7 @@ class Taker(object):
self.maker_utxo_data = {}
- for nick, nickdata in ioauth_data.iteritems():
+ for nick, nickdata in iteritems(ioauth_data):
utxo_list, auth_pub, cj_addr, change_addr, btc_sig, maker_pk = nickdata
self.utxos[nick] = utxo_list
utxo_data = jm_single().bc_interface.query_utxo_set(self.utxos[
@@ -422,7 +425,7 @@ class Taker(object):
#Apply business logic of how many counterparties are enough; note that
#this must occur after the above ioauth data processing, since we only now
#know for sure that the data meets all business-logic requirements.
- if len(self.maker_utxo_data.keys()) < jm_single().config.getint(
+ if len(self.maker_utxo_data) < jm_single().config.getint(
"POLICY", "minimum_makers"):
self.taker_info_callback("INFO", "Not enough counterparties, aborting.")
return (False,
@@ -434,7 +437,7 @@ class Taker(object):
#used to track return of signatures for phase 2
self.nonrespondants = list(self.maker_utxo_data.keys())
- my_total_in = sum([va['value'] for u, va in self.input_utxos.iteritems()
+ my_total_in = sum([va['value'] for u, va in iteritems(self.input_utxos)
])
if self.my_change_addr:
#Estimate fee per choice of next/3/6 blocks targetting.
@@ -494,7 +497,7 @@ class Taker(object):
# placeholders required
ins['script'] = 'deadbeef'
self.taker_info_callback("INFO", "Built tx, sending to counterparties.")
- return (True, self.maker_utxo_data.keys(), tx)
+ return (True, list(self.maker_utxo_data.keys()), tx)
def auth_counterparty(self, btc_sig, auth_pub, maker_pk):
"""Validate the counterpartys claim to own the btc
@@ -522,7 +525,7 @@ class Taker(object):
jlog.debug(('add_signature => nick={} '
'not in nonrespondants {}').format(nick, self.nonrespondants))
return
- sig = base64.b64decode(sigb64).encode('hex')
+ sig = hexlify(base64.b64decode(sigb64)).decode('ascii')
inserted_sig = False
txhex = btc.serialize(self.latest_tx)
@@ -541,7 +544,7 @@ class Taker(object):
1] for x in utxo.values()])
# insert signatures
- for i, u in utxo.iteritems():
+ for i, u in iteritems(utxo):
if utxo_data[i] is None:
continue
#Check if the sender serialize_scripted the witness
@@ -643,10 +646,10 @@ class Taker(object):
#also returns lists "too_old" and "too_small" for any
#utxos that did not satisfy the criteria for debugging.
priv_utxo_pairs = []
- new_utxos, too_old, too_small = filter_by_coin_age_amt(utxos.keys(),
+ new_utxos, too_old, too_small = filter_by_coin_age_amt(list(utxos.keys()),
age, amt)
new_utxos_dict = {k: v for k, v in utxos.items() if k in new_utxos}
- for k, v in new_utxos_dict.iteritems():
+ for k, v in iteritems(new_utxos_dict):
addr = v['address']
priv = self.wallet.get_key_from_addr(addr)
if priv: #can be null from create-unsigned
@@ -684,9 +687,9 @@ class Taker(object):
#Pre-filter the set of external commitments that work for this
#transaction according to its size and age.
dummy, extdict = get_podle_commitments()
- if len(extdict.keys()) > 0:
+ if len(extdict) > 0:
ext_valid, ext_to, ext_ts = filter_by_coin_age_amt(
- extdict.keys(), age, amt)
+ list(extdict.keys()), age, amt)
else:
ext_valid = None
podle_data = generate_podle(priv_utxo_pairs, tries, ext_valid)
@@ -706,10 +709,10 @@ class Taker(object):
jm_single().config.get("POLICY", "taker_utxo_amtpercent"))
with open("commitments_debug.txt", "wb") as f:
- errmsgfileheader = ("THIS IS A TEMPORARY FILE FOR DEBUGGING; "
- "IT CAN BE SAFELY DELETED ANY TIME.\n")
- errmsgfileheader += ("***\n")
- f.write(errmsgfileheader + errmsg)
+ errmsgfileheader = (b"THIS IS A TEMPORARY FILE FOR DEBUGGING; "
+ b"IT CAN BE SAFELY DELETED ANY TIME.\n")
+ errmsgfileheader += (b"***\n")
+ f.write(errmsgfileheader + errmsg.encode('utf-8'))
return (None, (priv_utxo_pairs, to, ts), errmsgheader + errmsg)
@@ -735,7 +738,7 @@ class Taker(object):
tx_bin = btc.deserialize(unhexlify(btc.serialize(self.latest_tx)))
self.wallet.sign_tx(tx_bin, our_inputs)
- self.latest_tx = btc.deserialize(hexlify(btc.serialize(tx_bin)))
+ self.latest_tx = btc.deserialize(hexlify(btc.serialize(tx_bin)).decode('ascii'))
def push(self):
diff --git a/jmclient/jmclient/taker_utils.py b/jmclient/jmclient/taker_utils.py
index b83300a..8d566bf 100644
--- a/jmclient/jmclient/taker_utils.py
+++ b/jmclient/jmclient/taker_utils.py
@@ -1,4 +1,7 @@
-from __future__ import absolute_import, print_function
+from __future__ import (absolute_import, division,
+ print_function, unicode_literals)
+from builtins import * # noqa: F401
+from future.utils import iteritems
import logging
import pprint
import os
@@ -53,7 +56,7 @@ def direct_send(wallet, amount, mixdepth, destaddr, answeryes=False,
log.error(
"There are no utxos in mixdepth: " + str(mixdepth) + ", quitting.")
return
- total_inputs_val = sum([va['value'] for u, va in utxos.iteritems()])
+ total_inputs_val = sum([va['value'] for u, va in iteritems(utxos)])
fee_est = estimate_tx_fee(len(utxos), 1, txtype=txtype)
outs = [{"address": destaddr, "value": total_inputs_val - fee_est}]
else:
@@ -64,7 +67,7 @@ def direct_send(wallet, amount, mixdepth, destaddr, answeryes=False,
fee_est = estimate_tx_fee(len(utxos), 2, txtype=txtype)
else:
fee_est = initial_fee_est
- total_inputs_val = sum([va['value'] for u, va in utxos.iteritems()])
+ total_inputs_val = sum([va['value'] for u, va in iteritems(utxos)])
changeval = total_inputs_val - fee_est - amount
outs = [{"value": amount, "address": destaddr}]
change_addr = wallet.get_internal_addr(mixdepth)
@@ -75,7 +78,7 @@ def direct_send(wallet, amount, mixdepth, destaddr, answeryes=False,
log.info("Using a fee of : " + str(fee_est) + " satoshis.")
if amount != 0:
log.info("Using a change value of: " + str(changeval) + " satoshis.")
- tx = sign_tx(wallet, mktx(utxos.keys(), outs), utxos)
+ tx = sign_tx(wallet, mktx(list(utxos.keys()), outs), utxos)
txsigned = deserialize(tx)
log.info("Got signed transaction:\n")
log.info(tx + "\n")
@@ -84,7 +87,7 @@ def direct_send(wallet, amount, mixdepth, destaddr, answeryes=False,
log.info("Sends: " + str(actual_amount) + " satoshis to address: " + destaddr)
if not answeryes:
if not accept_callback:
- if raw_input('Would you like to push to the network? (y/n):')[0] != 'y':
+ if input('Would you like to push to the network? (y/n):')[0] != 'y':
log.info("You chose not to broadcast the transaction, quitting.")
return False
else:
@@ -112,7 +115,7 @@ def sign_tx(wallet, tx, utxos):
# FIXME: ugly hack
tx_bin = deserialize(unhexlify(serialize(stx)))
wallet.sign_tx(tx_bin, our_inputs)
- return hexlify(serialize(tx_bin))
+ return hexlify(serialize(tx_bin)).decode('ascii')
def import_new_addresses(wallet, addr_list):
@@ -239,7 +242,7 @@ def tumbler_taker_finished_update(taker, schedulefile, tumble_log, options,
print(' for example click the button that gives a new deposit address')
print('\n'.join(['=' * 60] * 1))
while True:
- destaddr = raw_input('insert new address: ')
+ destaddr = input('insert new address: ')
addr_valid, errormsg = validate_address(destaddr)
if addr_valid:
break
diff --git a/jmclient/jmclient/wallet.py b/jmclient/jmclient/wallet.py
index 7fee692..776eaf5 100644
--- a/jmclient/jmclient/wallet.py
+++ b/jmclient/jmclient/wallet.py
@@ -1,6 +1,8 @@
-from __future__ import print_function, absolute_import, division, unicode_literals
+from __future__ import (absolute_import, division,
+ print_function, unicode_literals)
+from builtins import * # noqa: F401
-from ConfigParser import NoOptionError
+from configparser import NoOptionError
import warnings
import functools
import collections
@@ -8,7 +10,7 @@ import numbers
from binascii import hexlify, unhexlify
from datetime import datetime
from copy import deepcopy
-from mnemonic import Mnemonic
+from mnemonic import Mnemonic as MnemonicParent
from hashlib import sha256
from itertools import chain
from decimal import Decimal
@@ -58,6 +60,12 @@ class WalletError(Exception):
pass
+class Mnemonic(MnemonicParent):
+ @classmethod
+ def detect_language(cls, code):
+ return "english"
+
+
def estimate_tx_fee(ins, outs, txtype='p2pkh'):
'''Returns an estimate of the number of satoshis required
for a transaction with the given number of inputs and outputs,
@@ -337,7 +345,7 @@ class BaseWallet(object):
script = self._ENGINE.address_to_script(addr)
path = self.script_to_path(script)
privkey = self._get_priv_from_path(path)[0]
- return hexlify(privkey)
+ return hexlify(privkey).decode('ascii')
def get_external_addr(self, mixdepth):
"""
@@ -439,7 +447,7 @@ class BaseWallet(object):
removed_utxos = {}
for (txid, index), val in ret.items():
val['address'] = self.get_addr_path(val['path'])
- removed_utxos[hexlify(txid) + ':' + str(index)] = val
+ removed_utxos[hexlify(txid).decode('ascii') + ':' + str(index)] = val
return removed_utxos
def remove_old_utxos_(self, tx):
@@ -526,7 +534,7 @@ class BaseWallet(object):
ret_conv = {}
for utxo, data in ret.items():
addr = self.get_addr_path(data['path'])
- utxo_txt = hexlify(utxo[0]) + ':' + str(utxo[1])
+ utxo_txt = hexlify(utxo[0]).decode('ascii') + ':' + str(utxo[1])
ret_conv[utxo_txt] = {'address': addr, 'value': data['value']}
return ret_conv
@@ -580,7 +588,7 @@ class BaseWallet(object):
utxos_conv = collections.defaultdict(dict)
for md, utxos in ret.items():
for utxo, data in utxos.items():
- utxo_str = hexlify(utxo[0]) + ':' + str(utxo[1])
+ utxo_str = hexlify(utxo[0]).decode('ascii') + ':' + str(utxo[1])
addr = self.get_addr_path(data['path'])
data['address'] = addr
utxos_conv[md][utxo_str] = data
@@ -1060,6 +1068,7 @@ class BIP32Wallet(BaseWallet):
_master_entropy = self._create_master_key()
assert _master_entropy
+ assert isinstance(_master_entropy, bytes)
self._master_key = self._derive_bip32_master_key(_master_entropy)
# used to verify paths for sanity checking and for wallet id creation
@@ -1258,7 +1267,7 @@ class BIP32Wallet(BaseWallet):
int_type = self._get_internal_type(internal)
path = self.get_path(mixdepth, int_type, index)
priv = self._ENGINE.derive_bip32_privkey(self._master_key, path)
- return hexlify(priv)
+ return hexlify(priv).decode('ascii')
def get_bip32_priv_export(self, mixdepth=None, internal=None):
path = self._get_bip32_export_path(mixdepth, internal)
@@ -1304,7 +1313,7 @@ class BIP32Wallet(BaseWallet):
return self._index_cache[mixdepth][int_type]
def get_mnemonic_words(self):
- return ' '.join(mn_encode(hexlify(self._entropy))), None
+ return ' '.join(mn_encode(hexlify(self._entropy).decode('ascii'))), None
@classmethod
def entropy_from_mnemonic(cls, seed):
@@ -1315,7 +1324,7 @@ class BIP32Wallet(BaseWallet):
return unhexlify(mn_decode(words))
def get_wallet_id(self):
- return hexlify(self._key_ident)
+ return hexlify(self._key_ident).decode('ascii')
def set_next_index(self, mixdepth, internal, index, force=False):
int_type = self._get_internal_type(internal)
@@ -1334,7 +1343,7 @@ class LegacyWallet(ImportWalletMixin, BIP32Wallet):
_ENGINE = BTC_P2PKH
def _create_master_key(self):
- return hexlify(self._entropy).encode('ascii')
+ return hexlify(self._entropy)
def _get_bip32_base_path(self):
return self._key_ident, 0
diff --git a/jmclient/jmclient/wallet_utils.py b/jmclient/jmclient/wallet_utils.py
index b7032f0..c6e0d0d 100644
--- a/jmclient/jmclient/wallet_utils.py
+++ b/jmclient/jmclient/wallet_utils.py
@@ -1,4 +1,7 @@
-from __future__ import print_function
+from __future__ import (absolute_import, division,
+ print_function, unicode_literals)
+from builtins import * # noqa: F401
+from future.utils import iteritems
import json
import os
import sys
@@ -12,7 +15,7 @@ from jmclient import (get_network, WALLET_IMPLEMENTATIONS, Storage, podle,
VolatileStorage, StoragePasswordError,
is_segwit_mode, SegwitLegacyWallet, LegacyWallet)
from jmbase.support import get_password
-from cryptoengine import TYPE_P2PKH, TYPE_P2SH_P2WPKH
+from .cryptoengine import TYPE_P2PKH, TYPE_P2SH_P2WPKH
import jmclient.btc as btc
@@ -326,7 +329,7 @@ def wallet_showutxos(wallet, showprivkey):
unsp[u]['privkey'] = wallet.get_wif_path(av['path'])
used_commitments, external_commitments = podle.get_podle_commitments()
- for u, ec in external_commitments.iteritems():
+ for u, ec in iteritems(external_commitments):
tries = podle.get_podle_tries(utxo=u, max_tries=max_tries,
external=True)
tries_remaining = max(0, max_tries - tries)
@@ -342,7 +345,7 @@ def wallet_display(wallet, gaplimit, showprivkey, displayall=False,
else return the WalletView object.
"""
acctlist = []
- for m in xrange(wallet.mixdepth + 1):
+ for m in range(wallet.mixdepth + 1):
branchlist = []
for forchange in [0, 1]:
entrylist = []
@@ -353,7 +356,7 @@ def wallet_display(wallet, gaplimit, showprivkey, displayall=False,
xpub_key = ""
unused_index = wallet.get_next_unused_index(m, forchange)
- for k in xrange(unused_index + gaplimit):
+ for k in range(unused_index + gaplimit):
path = wallet.get_path(m, forchange, k)
addr = wallet.get_addr_path(path)
balance = 0
@@ -398,7 +401,7 @@ def cli_get_wallet_passphrase_check():
return password
def cli_get_wallet_file_name():
- return raw_input('Input wallet file name (default: wallet.jmdat): ')
+ return input('Input wallet file name (default: wallet.jmdat): ')
def cli_display_user_words(words, mnemonic_extension):
text = 'Write down this wallet recovery mnemonic\n\n' + words +'\n'
@@ -407,20 +410,20 @@ def cli_display_user_words(words, mnemonic_extension):
print(text)
def cli_user_mnemonic_entry():
- mnemonic_phrase = raw_input("Input mnemonic recovery phrase: ")
- mnemonic_extension = raw_input("Input mnemonic extension, leave blank if there isnt one: ")
+ mnemonic_phrase = input("Input mnemonic recovery phrase: ")
+ mnemonic_extension = input("Input mnemonic extension, leave blank if there isnt one: ")
if len(mnemonic_extension.strip()) == 0:
mnemonic_extension = None
return (mnemonic_phrase, mnemonic_extension)
def cli_get_mnemonic_extension():
- uin = raw_input("Would you like to use a two-factor mnemonic recovery "
+ uin = input("Would you like to use a two-factor mnemonic recovery "
"phrase? write 'n' if you don't know what this is (y/n): ")
if len(uin) == 0 or uin[0] != 'y':
print("Not using mnemonic extension")
return None #no mnemonic extension
print("Note: This will be stored in a reversible way. Do not reuse!")
- return raw_input("Enter mnemonic extension: ")
+ return input("Enter mnemonic extension: ")
def wallet_generate_recover_bip39(method, walletspath, default_wallet_name,
@@ -483,7 +486,7 @@ def wallet_generate_recover(method, walletspath,
entropy = None
if method == 'recover':
- seed = raw_input("Input 12 word recovery seed: ")
+ seed = input("Input 12 word recovery seed: ")
try:
entropy = LegacyWallet.entropy_from_mnemonic(seed)
except WalletError as e:
@@ -510,10 +513,17 @@ def wallet_generate_recover(method, walletspath,
return True
+def dict_factory(cursor, row):
+ d = {}
+ for idx, col in enumerate(cursor.description):
+ d[col[0]] = row[idx]
+ return d
+
+
def wallet_fetch_history(wallet, options):
# sort txes in a db because python can be really bad with large lists
con = sqlite3.connect(":memory:")
- con.row_factory = sqlite3.Row
+ con.row_factory = dict_factory
tx_db = con.cursor()
tx_db.execute("CREATE TABLE transactions(txid TEXT, "
"blockhash TEXT, blocktime INTEGER);")
@@ -665,7 +675,7 @@ def wallet_fetch_history(wallet, options):
amount = cj_amount
delta_balance = out_value - our_input_value
mixdepth_src = wallet.get_script_mixdepth(list(our_input_scripts)[0])
- cj_script = list(set([a for a, v in output_script_values.iteritems()
+ cj_script = list(set([a for a, v in iteritems(output_script_values)
if v == cj_amount]).intersection(our_output_scripts))[0]
mixdepth_dst = wallet.get_script_mixdepth(cj_script)
else:
@@ -781,7 +791,7 @@ def wallet_importprivkey(wallet, mixdepth, key_type):
print("WARNING: Handling of raw ECDSA bitcoin private keys can lead to "
"non-intuitive behaviour and loss of funds.\n Recommended instead "
"is to use the \'sweep\' feature of sendpayment.py.")
- privkeys = raw_input("Enter private key(s) to import: ")
+ privkeys = input("Enter private key(s) to import: ")
privkeys = privkeys.split(',') if ',' in privkeys else privkeys.split()
imported_addr = []
import_failed = 0
diff --git a/jmclient/jmclient/yieldgenerator.py b/jmclient/jmclient/yieldgenerator.py
index d325223..3d9039d 100644
--- a/jmclient/jmclient/yieldgenerator.py
+++ b/jmclient/jmclient/yieldgenerator.py
@@ -1,5 +1,8 @@
#! /usr/bin/env python
-from __future__ import absolute_import, print_function
+from __future__ import (absolute_import, division,
+ print_function, unicode_literals)
+from builtins import * # noqa: F401
+from future.utils import iteritems
import datetime
import os
@@ -79,7 +82,7 @@ class YieldGeneratorBasic(YieldGenerator):
def create_my_orders(self):
mix_balance = self.wallet.get_balance_by_mixdepth(verbose=False)
- if len([b for m, b in mix_balance.iteritems() if b > 0]) == 0:
+ if len([b for m, b in iteritems(mix_balance) if b > 0]) == 0:
jlog.error('do not have any coins left')
return []
@@ -118,7 +121,7 @@ class YieldGeneratorBasic(YieldGenerator):
max_mix = max(mix_balance, key=mix_balance.get)
filtered_mix_balance = [m
- for m in mix_balance.iteritems()
+ for m in iteritems(mix_balance)
if m[1] >= total_amount]
if not filtered_mix_balance:
return None, None, None
diff --git a/jmclient/setup.py b/jmclient/setup.py
index 3a858a9..83e7e71 100644
--- a/jmclient/setup.py
+++ b/jmclient/setup.py
@@ -9,5 +9,5 @@ setup(name='joinmarketclient',
author_email='',
license='GPL',
packages=['jmclient'],
- install_requires=['future', 'joinmarketbase==0.4.2', 'mnemonic', 'qt4reactor', 'argon2_cffi', 'bencoder.pyx', 'pyaes'],
+ install_requires=['future', 'configparser;python_version<"3.2"', 'joinmarketbase==0.4.2', 'mnemonic', 'qt4reactor', 'argon2_cffi', 'bencoder.pyx', 'pyaes'],
zip_safe=False)
diff --git a/jmclient/test/commontest.py b/jmclient/test/commontest.py
index e5795e9..68d5888 100644
--- a/jmclient/test/commontest.py
+++ b/jmclient/test/commontest.py
@@ -1,5 +1,7 @@
#! /usr/bin/env python
-from __future__ import absolute_import, print_function
+from __future__ import (absolute_import, division,
+ print_function, unicode_literals)
+from builtins import * # noqa: F401
'''Some helper functions for testing'''
import os
@@ -131,7 +133,7 @@ def make_sign_and_push(ins_full,
from wallets
"""
total = sum(x['value'] for x in ins_full.values())
- ins = ins_full.keys()
+ ins = list(ins_full.keys())
#random output address and change addr
output_addr = wallet.get_new_addr(1, 1) if not output_addr else output_addr
change_addr = wallet.get_new_addr(1, 0) if not change_addr else change_addr
@@ -149,7 +151,7 @@ def make_sign_and_push(ins_full,
binarize_tx(de_tx)
de_tx = wallet.sign_tx(de_tx, scripts, hashcode=hashcode)
#pushtx returns False on any error
- tx = binascii.hexlify(btc.serialize(de_tx))
+ tx = binascii.hexlify(btc.serialize(de_tx)).decode('ascii')
push_succeed = jm_single().bc_interface.pushtx(tx)
if push_succeed:
return btc.txhash(tx)
@@ -178,7 +180,7 @@ def make_wallets(n,
if len(wallet_structures) != n:
raise Exception("Number of wallets doesn't match wallet structures")
if not fixed_seeds:
- seeds = chunks(binascii.hexlify(os.urandom(BIP32Wallet.ENTROPY_BYTES * n)),
+ seeds = chunks(binascii.hexlify(os.urandom(BIP32Wallet.ENTROPY_BYTES * n)).decode('ascii'),
BIP32Wallet.ENTROPY_BYTES * 2)
else:
seeds = fixed_seeds
diff --git a/jmclient/test/taker_test_data.py b/jmclient/test/taker_test_data.py
index 0ee3c09..7a6195d 100644
--- a/jmclient/test/taker_test_data.py
+++ b/jmclient/test/taker_test_data.py
@@ -1,3 +1,6 @@
+from __future__ import (absolute_import, division,
+ print_function, unicode_literals)
+from builtins import * # noqa: F401
#orderbook
t_orderbook = [{u'counterparty': u'J6FA1Gj7Ln4vSGne', u'ordertype': u'swreloffer', u'oid': 0,
u'minsize': 7500000, u'txfee': 1000, u'maxsize': 599972700, u'cjfee': u'0.0002'},
diff --git a/jmclient/test/test_aes.py b/jmclient/test/test_aes.py
index e093b9e..7f79586 100644
--- a/jmclient/test/test_aes.py
+++ b/jmclient/test/test_aes.py
@@ -1,14 +1,18 @@
+from __future__ import (absolute_import, division,
+ print_function, unicode_literals)
+from builtins import * # noqa: F401
import jmclient.slowaes as sa
"""test general AES operation; probably not needed.
Not included in coverage, but should be included in suite."""
import os
+import sys
import pytest
def test_pkcs7_bad_padding():
#used in seed decryption; check that it throws
#if wrongly padded (this caused a REAL bug before!)
- bad_padded = ['\x07'*14, '\x07'*31, '\x07'*31+'\x11', '\x07'*31+'\x00',
- '\x07'*14+'\x01\x02']
+ bad_padded = [b'\x07'*14, b'\x07'*31, b'\x07'*31+b'\x11', b'\x07'*31+b'\x00',
+ b'\x07'*14+b'\x01\x02']
for b in bad_padded:
with pytest.raises(Exception) as e_info:
fake_unpadded = sa.strip_PKCS7_padding(b)
@@ -19,7 +23,10 @@ def test_aes():
92]
for ks in [16,24,32]:
for mode in ["CFB", "CBC", "OFB"]:
- cypherkey = map(ord, os.urandom(ks))
+ if sys.version_info >= (3,0):
+ cypherkey = list(map(int, os.urandom(ks)))
+ else:
+ cypherkey = list(map(ord, os.urandom(ks)))
moo = sa.AESModeOfOperation()
mode, orig_len, ciph = moo.encrypt(cleartext, moo.modeOfOperation[mode],
cypherkey, ks,
diff --git a/jmclient/test/test_argon2.py b/jmclient/test/test_argon2.py
index 158c084..8ad11c2 100644
--- a/jmclient/test/test_argon2.py
+++ b/jmclient/test/test_argon2.py
@@ -1,4 +1,6 @@
-from __future__ import print_function, absolute_import, division, unicode_literals
+from __future__ import (absolute_import, division,
+ print_function, unicode_literals)
+from builtins import * # noqa: F401
from jmclient import Argon2Hash, get_random_bytes
diff --git a/jmclient/test/test_blockchaininterface.py b/jmclient/test/test_blockchaininterface.py
index f6e6bcf..f092593 100644
--- a/jmclient/test/test_blockchaininterface.py
+++ b/jmclient/test/test_blockchaininterface.py
@@ -1,4 +1,6 @@
-from __future__ import absolute_import, print_function
+from __future__ import (absolute_import, division,
+ print_function, unicode_literals)
+from builtins import * # noqa: F401
"""Blockchaininterface functionality tests."""
diff --git a/jmclient/test/test_client_protocol.py b/jmclient/test/test_client_protocol.py
index 5c58691..c767c2f 100644
--- a/jmclient/test/test_client_protocol.py
+++ b/jmclient/test/test_client_protocol.py
@@ -1,5 +1,7 @@
#! /usr/bin/env python
-from __future__ import absolute_import
+from __future__ import (absolute_import, division,
+ print_function, unicode_literals)
+from builtins import *
'''test client-protocol interfacae.'''
from jmclient import load_program_config, Taker, get_log,\
diff --git a/jmclient/test/test_coinjoin.py b/jmclient/test/test_coinjoin.py
index 5498fac..b7c59a7 100644
--- a/jmclient/test/test_coinjoin.py
+++ b/jmclient/test/test_coinjoin.py
@@ -1,4 +1,6 @@
-from __future__ import print_function, absolute_import, division, unicode_literals
+from __future__ import (absolute_import, division,
+ print_function, unicode_literals)
+from builtins import * # noqa: F401
"""
Test doing full coinjoins, bypassing IRC
diff --git a/jmclient/test/test_commitment_utils.py b/jmclient/test/test_commitment_utils.py
index 32ba4fe..9d0f54c 100644
--- a/jmclient/test/test_commitment_utils.py
+++ b/jmclient/test/test_commitment_utils.py
@@ -1,5 +1,7 @@
#!/usr/bin/env python
-from __future__ import print_function
+from __future__ import (absolute_import, division,
+ print_function, unicode_literals)
+from builtins import * # noqa: F401
from commontest import DummyBlockchainInterface
import pytest
diff --git a/jmclient/test/test_configure.py b/jmclient/test/test_configure.py
index adcfccc..e6401d9 100644
--- a/jmclient/test/test_configure.py
+++ b/jmclient/test/test_configure.py
@@ -1,4 +1,6 @@
-from __future__ import absolute_import
+from __future__ import (absolute_import, division,
+ print_function, unicode_literals)
+from builtins import * # noqa: F401
'''test configure module.'''
import pytest
diff --git a/jmclient/test/test_maker.py b/jmclient/test/test_maker.py
index 58d7667..31daad2 100644
--- a/jmclient/test/test_maker.py
+++ b/jmclient/test/test_maker.py
@@ -1,6 +1,8 @@
#!/usr/bin/env python
-from __future__ import print_function
+from __future__ import (absolute_import, division,
+ print_function, unicode_literals)
+from builtins import * # noqa: F401
from jmclient import Maker, btc, get_p2sh_vbyte, get_p2pk_vbyte, \
load_program_config, jm_single
@@ -46,7 +48,7 @@ def construct_tx_offerlist(cjaddr, changeaddr, maker_utxos, maker_utxos_value,
def create_tx_inputs(count=1):
inp = []
- for i in xrange(count):
+ for i in range(count):
inp.append({'outpoint': {'hash': '0'*64, 'index': i},
'script': '',
'sequence': 4294967295})
@@ -71,9 +73,9 @@ def address_p2sh_generator():
def get_address_generator(script_pre, script_post, vbyte):
counter = 0
while True:
- script = script_pre + struct.pack('=LQQ', 0, 0, counter) + script_post
+ script = script_pre + struct.pack(b'=LQQ', 0, 0, counter) + script_post
addr = btc.script_to_address(script, vbyte)
- yield addr, binascii.hexlify(script)
+ yield addr, binascii.hexlify(script).decode('ascii')
counter += 1
@@ -120,21 +122,21 @@ def test_verify_unsigned_tx_sw_valid(setup_env_nodeps):
# test standard cj
tx, offerlist = create_tx_and_offerlist(cj_addr, changeaddr,
- [next(p2sh_gen)[1] for s in xrange(4)], cj_script, cj_change_script)
+ [next(p2sh_gen)[1] for s in range(4)], cj_script, cj_change_script)
assert maker.verify_unsigned_tx(tx, offerlist) == (True, None), "standard sw cj"
# test cj with mixed outputs
tx, offerlist = create_tx_and_offerlist(cj_addr, changeaddr,
- list(chain((next(p2sh_gen)[1] for s in xrange(3)),
- (next(p2pkh_gen)[1] for s in xrange(1)))),
+ list(chain((next(p2sh_gen)[1] for s in range(3)),
+ (next(p2pkh_gen)[1] for s in range(1)))),
cj_script, cj_change_script)
assert maker.verify_unsigned_tx(tx, offerlist) == (True, None), "sw cj with p2pkh output"
# test cj with only p2pkh outputs
tx, offerlist = create_tx_and_offerlist(cj_addr, changeaddr,
- [next(p2pkh_gen)[1] for s in xrange(4)], cj_script, cj_change_script)
+ [next(p2pkh_gen)[1] for s in range(4)], cj_script, cj_change_script)
assert maker.verify_unsigned_tx(tx, offerlist) == (True, None), "sw cj with only p2pkh outputs"
@@ -153,21 +155,21 @@ def test_verify_unsigned_tx_nonsw_valid(setup_env_nodeps):
# test standard cj
tx, offerlist = create_tx_and_offerlist(cj_addr, changeaddr,
- [next(p2pkh_gen)[1] for s in xrange(4)], cj_script, cj_change_script, 'reloffer')
+ [next(p2pkh_gen)[1] for s in range(4)], cj_script, cj_change_script, 'reloffer')
assert maker.verify_unsigned_tx(tx, offerlist) == (True, None), "standard nonsw cj"
# test cj with mixed outputs
tx, offerlist = create_tx_and_offerlist(cj_addr, changeaddr,
- list(chain((next(p2sh_gen)[1] for s in xrange(1)),
- (next(p2pkh_gen)[1] for s in xrange(3)))),
+ list(chain((next(p2sh_gen)[1] for s in range(1)),
+ (next(p2pkh_gen)[1] for s in range(3)))),
cj_script, cj_change_script, 'reloffer')
assert maker.verify_unsigned_tx(tx, offerlist) == (True, None), "nonsw cj with p2sh output"
# test cj with only p2sh outputs
tx, offerlist = create_tx_and_offerlist(cj_addr, changeaddr,
- [next(p2sh_gen)[1] for s in xrange(4)], cj_script, cj_change_script, 'reloffer')
+ [next(p2sh_gen)[1] for s in range(4)], cj_script, cj_change_script, 'reloffer')
assert maker.verify_unsigned_tx(tx, offerlist) == (True, None), "nonsw cj with only p2sh outputs"
diff --git a/jmclient/test/test_mnemonic.py b/jmclient/test/test_mnemonic.py
index 2c703f5..40772f1 100644
--- a/jmclient/test/test_mnemonic.py
+++ b/jmclient/test/test_mnemonic.py
@@ -1,3 +1,6 @@
+from __future__ import (absolute_import, division,
+ print_function, unicode_literals)
+from builtins import * # noqa: F401
from jmclient import old_mnemonic
import pytest
@@ -43,12 +46,12 @@ def test_old_mnemonic(seedphrase, key, valid):
#Already known error condition: an incorrectly short
#word list will NOT throw an error; this is handled by calling code
if len(seedphrase) < 12:
- print "For known failure case of seedphrase less than 12: "
- print old_mnemonic.mn_decode(seedphrase)
+ print("For known failure case of seedphrase less than 12: ")
+ print(old_mnemonic.mn_decode(seedphrase))
else:
with pytest.raises(Exception) as e_info:
dummy = old_mnemonic.mn_decode(seedphrase)
- print "Got this return value from mn_decode: " + str(dummy)
+ print("Got this return value from mn_decode: " + str(dummy))
diff --git a/jmclient/test/test_podle.py b/jmclient/test/test_podle.py
index c25fc1b..21f6d8d 100644
--- a/jmclient/test/test_podle.py
+++ b/jmclient/test/test_podle.py
@@ -1,9 +1,12 @@
#! /usr/bin/env python
-from __future__ import print_function
+from __future__ import (absolute_import, division,
+ print_function, unicode_literals)
+from builtins import * # noqa: F401
'''Tests of Proof of discrete log equivalence commitments.'''
import os
import jmbitcoin as bitcoin
import binascii
+import struct
import json
import pytest
import copy
@@ -46,7 +49,7 @@ def generate_single_podle_sig(priv, i):
library 'generate_podle' which intelligently searches and updates commitments.
"""
dummy_utxo = bitcoin.sha256(priv) + ":3"
- podle = PoDLE(dummy_utxo, binascii.hexlify(priv))
+ podle = PoDLE(dummy_utxo, binascii.hexlify(priv).decode('ascii'))
r = podle.generate_podle(i)
return (r['P'], r['P2'], r['sig'],
r['e'], r['commit'])
@@ -112,9 +115,9 @@ def test_external_commitments(setup_podle):
known_utxos = []
tries = 3
for i in range(1, 6):
- u = binascii.hexlify(chr(i)*32)
+ u = binascii.hexlify(struct.pack(b'B', i)*32).decode('ascii')
known_utxos.append(u)
- priv = chr(i)*32+"\x01"
+ priv = struct.pack(b'B', i)*32+b"\x01"
ecs[u] = {}
ecs[u]['reveal']={}
for j in range(tries):
@@ -130,20 +133,20 @@ def test_external_commitments(setup_podle):
#this should find the remaining one utxo and return from it
assert generate_podle([], max_tries=tries, allow_external=known_utxos)
#test commitment removal
- to_remove = ecs[binascii.hexlify(chr(3)*32)]
- update_commitments(external_to_remove={binascii.hexlify(chr(3)*32):to_remove})
+ to_remove = ecs[binascii.hexlify(struct.pack(b'B', 3)*32).decode('ascii')]
+ update_commitments(external_to_remove={binascii.hexlify(struct.pack(b'B', 3)*32).decode('ascii'):to_remove})
#test that an incorrectly formatted file raises
with open(get_commitment_file(), "rb") as f:
- validjson = json.loads(f.read())
+ validjson = json.loads(f.read().decode('utf-8'))
corruptjson = copy.deepcopy(validjson)
del corruptjson['used']
with open(get_commitment_file(), "wb") as f:
- f.write(json.dumps(corruptjson, indent=4))
+ f.write(json.dumps(corruptjson, indent=4).encode('utf-8'))
with pytest.raises(PoDLEError) as e_info:
get_podle_commitments()
#clean up
with open(get_commitment_file(), "wb") as f:
- f.write(json.dumps(validjson, indent=4))
+ f.write(json.dumps(validjson, indent=4).encode('utf-8'))
diff --git a/jmclient/test/test_schedule.py b/jmclient/test/test_schedule.py
index 578491d..05a4e61 100644
--- a/jmclient/test/test_schedule.py
+++ b/jmclient/test/test_schedule.py
@@ -1,5 +1,7 @@
#! /usr/bin/env python
-from __future__ import absolute_import
+from __future__ import (absolute_import, division,
+ print_function, unicode_literals)
+from builtins import * # noqa: F401
'''test schedule module.'''
import pytest
@@ -42,7 +44,7 @@ def test_get_schedule():
if os.path.exists(tsf):
os.remove(tsf)
with open(tsf, "wb") as f:
- f.write(s)
+ f.write(s.encode('utf-8'))
result = get_schedule(tsf)
if s== valids:
assert result[0]
diff --git a/jmclient/test/test_storage.py b/jmclient/test/test_storage.py
index 1c54304..1989a69 100644
--- a/jmclient/test/test_storage.py
+++ b/jmclient/test/test_storage.py
@@ -1,4 +1,6 @@
-from __future__ import print_function, absolute_import, division, unicode_literals
+from __future__ import (absolute_import, division,
+ print_function, unicode_literals)
+from builtins import * # noqa: F401
from jmclient import storage
import pytest
diff --git a/jmclient/test/test_support.py b/jmclient/test/test_support.py
index a9b40df..2df4d9f 100644
--- a/jmclient/test/test_support.py
+++ b/jmclient/test/test_support.py
@@ -1,5 +1,7 @@
#! /usr/bin/env python
-from __future__ import absolute_import
+from __future__ import (absolute_import, division,
+ print_function, unicode_literals)
+from builtins import * # noqa: F401
'''support functions for jmclient tests.'''
import pytest
diff --git a/jmclient/test/test_taker.py b/jmclient/test/test_taker.py
index 7656d0c..8fac8f2 100644
--- a/jmclient/test/test_taker.py
+++ b/jmclient/test/test_taker.py
@@ -1,5 +1,8 @@
#!/usr/bin/env python
-from __future__ import print_function
+from __future__ import (absolute_import, division,
+ print_function, unicode_literals)
+from builtins import * # noqa: F401
+from future.utils import iteritems
from commontest import DummyBlockchainInterface
import jmbitcoin as bitcoin
import binascii
@@ -8,6 +11,7 @@ import copy
import shutil
import pytest
import json
+import struct
from base64 import b64encode
from jmclient import load_program_config, jm_single, set_commitment_file,\
get_commitment_file, SegwitLegacyWallet, Taker, VolatileStorage,\
@@ -84,7 +88,7 @@ class DummyWallet(SegwitLegacyWallet):
def get_key_from_addr(self, addr):
"""usable addresses: privkey all 1s, 2s, 3s, ... :"""
- privs = [x*32 + "\x01" for x in [chr(y) for y in range(1,6)]]
+ privs = [x*32 + b"\x01" for x in [struct.pack(b'B', y) for y in range(1,6)]]
addrs = {}
"""
mrcNu71ztWjAQA6ww9kHiW3zBWSQidHXTQ
@@ -95,9 +99,9 @@ class DummyWallet(SegwitLegacyWallet):
"""
for p in privs:
addrs[p] = bitcoin.privkey_to_address(p, False, magicbyte=0x6f)
- for p, a in addrs.iteritems():
+ for p, a in iteritems(addrs):
if a == addr:
- return binascii.hexlify(p)
+ return binascii.hexlify(p).decode('ascii')
raise ValueError("No such keypair")
def _is_my_bip32_path(self, path):
@@ -154,7 +158,7 @@ def test_make_commitment(createcmtdata, failquery, external):
os.remove('dummyext')
old_commitment_file = get_commitment_file()
with open('dummyext', 'wb') as f:
- f.write(json.dumps(t_dummy_ext, indent=4))
+ f.write(json.dumps(t_dummy_ext, indent=4).encode('utf-8'))
if external:
set_commitment_file('dummyext')
old_taker_utxo_age = jm_single().config.get("POLICY", "taker_utxo_age")
@@ -301,7 +305,7 @@ def test_taker_init(createcmtdata, schedule, highfee, toomuchcoins, minmakers,
return clean_up()
if schedule[0][1] == 199599800:
#need to force negative fees to make this feasible
- for k, v in taker.orderbook.iteritems():
+ for k, v in iteritems(taker.orderbook):
v['cjfee'] = '-0.002'
# change_amount = (total_input - self.cjamount -
# self.orderbook[nick]['txfee'] + real_cjfee)
@@ -320,7 +324,7 @@ def test_taker_init(createcmtdata, schedule, highfee, toomuchcoins, minmakers,
#TODO note this test is not adequate, because the code is not;
#the code does not *DO* anything if a condition is unexpected.
taker.input_utxos = copy.deepcopy(t_utxos_by_mixdepth)[0]
- for k,v in taker.input_utxos.iteritems():
+ for k,v in iteritems(taker.input_utxos):
v["value"] = int(0.999805228 * v["value"])
res = taker.receive_utxos(maker_response)
assert res[0]
@@ -389,7 +393,7 @@ def test_on_sig(createcmtdata, dummyaddr, schedule):
#return the right values in query_utxo_set
#create 2 privkey + utxos that are to be ours
- privs = [x*32 + "\x01" for x in [chr(y) for y in range(1,6)]]
+ privs = [x*32 + b"\x01" for x in [struct.pack(b'B', y) for y in range(1,6)]]
utxos = [str(x)*64+":1" for x in range(5)]
fake_query_results = [{'value': 200000000,
'utxo': utxos[x],
@@ -426,12 +430,12 @@ def test_on_sig(createcmtdata, dummyaddr, schedule):
taker.my_cj_addr = dummyaddr
#make signatures for the last 3 fake utxos, considered as "not ours":
tx3 = bitcoin.sign(tx, 2, privs[2])
- sig3 = b64encode(bitcoin.deserialize(tx3)['ins'][2]['script'].decode('hex'))
+ sig3 = b64encode(binascii.unhexlify(bitcoin.deserialize(tx3)['ins'][2]['script']))
taker.on_sig("cp1", sig3)
#try sending the same sig again; should be ignored
taker.on_sig("cp1", sig3)
tx4 = bitcoin.sign(tx, 3, privs[3])
- sig4 = b64encode(bitcoin.deserialize(tx4)['ins'][3]['script'].decode('hex'))
+ sig4 = b64encode(binascii.unhexlify(bitcoin.deserialize(tx4)['ins'][3]['script']))
#try sending junk instead of cp2's correct sig
taker.on_sig("cp2", str("junk"))
taker.on_sig("cp2", sig4)
@@ -440,7 +444,7 @@ def test_on_sig(createcmtdata, dummyaddr, schedule):
#signing, try with an injected failure of query utxo set, which should
#prevent this signature being accepted.
dbci.setQUSFail(True)
- sig5 = b64encode(bitcoin.deserialize(tx5)['ins'][4]['script'].decode('hex'))
+ sig5 = b64encode(binascii.unhexlify(bitcoin.deserialize(tx5)['ins'][4]['script']))
taker.on_sig("cp3", sig5)
#allow it to succeed, and try again
dbci.setQUSFail(False)
diff --git a/jmclient/test/test_tx_creation.py b/jmclient/test/test_tx_creation.py
index 434cff6..5d327a6 100644
--- a/jmclient/test/test_tx_creation.py
+++ b/jmclient/test/test_tx_creation.py
@@ -1,10 +1,13 @@
#! /usr/bin/env python
-from __future__ import absolute_import
+from __future__ import (absolute_import, division,
+ print_function, unicode_literals)
+from builtins import * # noqa: F401
'''Test of unusual transaction types creation and push to
network to check validity.'''
import time
import binascii
+import struct
from commontest import make_wallets, make_sign_and_push
import jmbitcoin as bitcoin
@@ -59,7 +62,7 @@ def test_mktx(setup_tx_creation):
"""Testing exceptional conditions; not guaranteed
to create valid tx objects"""
#outpoint structure must be {"outpoint":{"hash":hash, "index": num}}
- ins = [{'outpoint': {"hash":x*32, "index":0},
+ ins = [{'outpoint': {"hash":x*64, "index":0},
"script": "", "sequence": 4294967295} for x in ["a", "b", "c"]]
pub = vpubs[0]
addr = bitcoin.pubkey_to_address(pub, magicbyte=get_p2pk_vbyte())
@@ -75,7 +78,7 @@ def test_mktx(setup_tx_creation):
def test_bintxhash(setup_tx_creation):
tx = "abcdef1234"
x = bitcoin.bin_txhash(tx)
- assert binascii.hexlify(x) == "121480fc2cccd5103434a9c88b037e08ef6c4f9f95dfb85b56f7043a344613fe"
+ assert binascii.hexlify(x).decode('ascii') == "121480fc2cccd5103434a9c88b037e08ef6c4f9f95dfb85b56f7043a344613fe"
def test_all_same_priv(setup_tx_creation):
#recipient
@@ -88,7 +91,7 @@ def test_all_same_priv(setup_tx_creation):
sync_wallet(wallet, fast=True)
insfull = wallet.select_utxos(0, 110000000)
outs = [{"address": addr, "value": 1000000}]
- ins = insfull.keys()
+ ins = list(insfull.keys())
tx = bitcoin.mktx(ins, outs)
tx = bitcoin.signall(tx, wallet.get_key_from_addr(addrinwallet))
@@ -107,11 +110,11 @@ def test_verify_tx_input(setup_tx_creation, signall, mktxlist):
print(insfull)
if not mktxlist:
outs = [{"address": addr, "value": 1000000}]
- ins = insfull.keys()
+ ins = list(insfull.keys())
tx = bitcoin.mktx(ins, outs)
else:
out1 = addr+":1000000"
- ins0, ins1 = insfull.keys()
+ ins0, ins1 = list(insfull.keys())
print("INS0 is: " + str(ins0))
print("INS1 is: " + str(ins1))
tx = bitcoin.mktx(ins0, ins1, out1)
@@ -134,7 +137,7 @@ def test_verify_tx_input(setup_tx_creation, signall, mktxlist):
tx = binascii.unhexlify(tx)
tx = bitcoin.sign(tx, index, priv)
if index % 2:
- tx = binascii.hexlify(tx)
+ tx = binascii.hexlify(tx).decode('ascii')
desertx2 = bitcoin.deserialize(tx)
print(desertx2)
sig, pub = bitcoin.deserialize_script(desertx2['ins'][0]['script'])
@@ -169,7 +172,7 @@ def test_create_sighash_txs(setup_tx_creation):
sync_wallet(wallet, fast=True)
amount = 350000000
ins_full = wallet.select_utxos(0, amount)
- print "using hashcode: " + str(sighash)
+ print("using hashcode: " + str(sighash))
txid = make_sign_and_push(ins_full, wallet, amount, hashcode=sighash)
assert txid
@@ -180,8 +183,8 @@ def test_create_sighash_txs(setup_tx_creation):
def test_spend_p2sh_utxos(setup_tx_creation):
#make a multisig address from 3 privs
- privs = [chr(x) * 32 + '\x01' for x in range(1, 4)]
- pubs = [bitcoin.privkey_to_pubkey(binascii.hexlify(priv)) for priv in privs]
+ privs = [struct.pack(b'B', x) * 32 + b'\x01' for x in range(1, 4)]
+ pubs = [bitcoin.privkey_to_pubkey(binascii.hexlify(priv).decode('ascii')) for priv in privs]
script = bitcoin.mk_multisig_script(pubs, 2)
msig_addr = bitcoin.scriptaddr(script, magicbyte=196)
#pay into it
@@ -203,7 +206,7 @@ def test_spend_p2sh_utxos(setup_tx_creation):
tx = bitcoin.mktx(ins, outs)
sigs = []
for priv in privs[:2]:
- sigs.append(bitcoin.multisign(tx, 0, script, binascii.hexlify(priv)))
+ sigs.append(bitcoin.multisign(tx, 0, script, binascii.hexlify(priv).decode('ascii')))
tx = bitcoin.apply_multisignatures(tx, 0, script, sigs)
txid = jm_single().bc_interface.pushtx(tx)
assert txid
diff --git a/jmclient/test/test_utxomanager.py b/jmclient/test/test_utxomanager.py
index 2c64e8e..915bb61 100644
--- a/jmclient/test/test_utxomanager.py
+++ b/jmclient/test/test_utxomanager.py
@@ -1,4 +1,6 @@
-from __future__ import print_function, absolute_import, division, unicode_literals
+from __future__ import (absolute_import, division,
+ print_function, unicode_literals)
+from builtins import * # noqa: F401
from jmclient.wallet import UTXOManager
from test_storage import MockStorage
@@ -32,9 +34,9 @@ def test_utxomanager_persist(setup_env_nodeps):
um = UTXOManager(storage, select)
- assert um.have_utxo(txid, index) is mixdepth
- assert um.have_utxo(txid, index+1) is mixdepth + 1
- assert um.have_utxo(txid, index+2) is False
+ assert um.have_utxo(txid, index) == mixdepth
+ assert um.have_utxo(txid, index+1) == mixdepth + 1
+ assert um.have_utxo(txid, index+2) == False
utxos = um.get_utxos_by_mixdepth()
assert len(utxos[mixdepth]) == 1
@@ -46,15 +48,15 @@ def test_utxomanager_persist(setup_env_nodeps):
assert balances[mixdepth+1] == value
um.remove_utxo(txid, index, mixdepth)
- assert um.have_utxo(txid, index) is False
+ assert um.have_utxo(txid, index) == False
um.save()
del um
um = UTXOManager(storage, select)
- assert um.have_utxo(txid, index) is False
- assert um.have_utxo(txid, index+1) is mixdepth + 1
+ assert um.have_utxo(txid, index) == False
+ assert um.have_utxo(txid, index+1) == mixdepth + 1
utxos = um.get_utxos_by_mixdepth()
assert len(utxos[mixdepth]) == 0
diff --git a/jmclient/test/test_valid_addresses.py b/jmclient/test/test_valid_addresses.py
index 70139c6..e76bd60 100644
--- a/jmclient/test/test_valid_addresses.py
+++ b/jmclient/test/test_valid_addresses.py
@@ -1,4 +1,6 @@
-from __future__ import print_function
+from __future__ import (absolute_import, division,
+ print_function, unicode_literals)
+from builtins import * # noqa: F401
from jmclient.configure import validate_address, load_program_config
from jmclient import jm_single
import json
diff --git a/jmclient/test/test_wallet.py b/jmclient/test/test_wallet.py
index 91e5dd6..5f6c40e 100644
--- a/jmclient/test/test_wallet.py
+++ b/jmclient/test/test_wallet.py
@@ -1,4 +1,6 @@
-from __future__ import print_function, absolute_import, division, unicode_literals
+from __future__ import (absolute_import, division,
+ print_function, unicode_literals)
+from builtins import * # noqa: F401
'''Wallet functionality tests.'''
import os
@@ -64,14 +66,14 @@ def get_bip39_vectors():
def test_bip39_seeds(monkeypatch, setup_wallet, entropy, mnemonic, key, xpriv):
jm_single().config.set('BLOCKCHAIN', 'network', 'mainnet')
created_entropy = SegwitLegacyWallet.entropy_from_mnemonic(mnemonic)
- assert entropy == hexlify(created_entropy)
+ assert entropy == hexlify(created_entropy).decode('ascii')
storage = VolatileStorage()
SegwitLegacyWallet.initialize(
storage, get_network(), entropy=created_entropy,
entropy_extension=b'TREZOR', max_mixdepth=4)
wallet = SegwitLegacyWallet(storage)
assert (mnemonic, b'TREZOR') == wallet.get_mnemonic_words()
- assert key == hexlify(wallet._create_master_key())
+ assert key == hexlify(wallet._create_master_key()).decode('ascii')
# need to monkeypatch this, else we'll default to the BIP-49 path
monkeypatch.setattr(SegwitLegacyWallet, '_get_bip32_base_path',
@@ -93,7 +95,7 @@ def test_bip49_seed(monkeypatch, setup_wallet):
wallet = SegwitLegacyWallet(storage)
assert (mnemonic, None) == wallet.get_mnemonic_words()
assert account0_xpriv == wallet.get_bip32_priv_export(0)
- assert addr0_script_hash == hexlify(wallet.get_external_script(0)[2:-1])
+ assert addr0_script_hash == hexlify(wallet.get_external_script(0)[2:-1]).decode('ascii')
# FIXME: is this desired behaviour? BIP49 wallet will not return xpriv for
# the root key but only for key after base path
@@ -298,13 +300,13 @@ def test_signing_imported(setup_wallet, wif, keytype, type_check):
MIXDEPTH = 0
path = wallet.import_private_key(MIXDEPTH, wif, keytype)
utxo = fund_wallet_addr(wallet, wallet.get_addr_path(path))
- tx = btc.deserialize(btc.mktx(['{}:{}'.format(hexlify(utxo[0]), utxo[1])],
+ tx = btc.deserialize(btc.mktx(['{}:{}'.format(hexlify(utxo[0]).decode('ascii'), utxo[1])],
['00'*17 + ':' + str(10**8 - 9000)]))
binarize_tx(tx)
script = wallet.get_script_path(path)
wallet.sign_tx(tx, {0: (script, 10**8)})
type_check(tx)
- txout = jm_single().bc_interface.pushtx(hexlify(btc.serialize(tx)))
+ txout = jm_single().bc_interface.pushtx(hexlify(btc.serialize(tx)).decode('ascii'))
assert txout
@@ -318,13 +320,13 @@ def test_signing_simple(setup_wallet, wallet_cls, type_check):
wallet_cls.initialize(storage, get_network())
wallet = wallet_cls(storage)
utxo = fund_wallet_addr(wallet, wallet.get_internal_addr(0))
- tx = btc.deserialize(btc.mktx(['{}:{}'.format(hexlify(utxo[0]), utxo[1])],
+ tx = btc.deserialize(btc.mktx(['{}:{}'.format(hexlify(utxo[0]).decode('ascii'), utxo[1])],
['00'*17 + ':' + str(10**8 - 9000)]))
binarize_tx(tx)
script = wallet.get_script(0, 1, 0)
wallet.sign_tx(tx, {0: (script, 10**8)})
type_check(tx)
- txout = jm_single().bc_interface.pushtx(hexlify(btc.serialize(tx)))
+ txout = jm_single().bc_interface.pushtx(hexlify(btc.serialize(tx)).decode('ascii'))
assert txout
@@ -381,7 +383,7 @@ def test_add_new_utxos(setup_wallet):
tx_scripts.append(b'\x22'*17)
tx = btc.deserialize(btc.mktx(
- ['0'*64 + ':2'], [{'script': hexlify(s), 'value': 10**8}
+ ['0'*64 + ':2'], [{'script': hexlify(s).decode('ascii'), 'value': 10**8}
for s in tx_scripts]))
binarize_tx(tx)
txid = b'\x01' * 32
@@ -417,7 +419,7 @@ def test_remove_old_utxos(setup_wallet):
tx_inputs.append((b'\x12'*32, 6))
tx = btc.deserialize(btc.mktx(
- ['{}:{}'.format(hexlify(txid), i) for txid, i in tx_inputs],
+ ['{}:{}'.format(hexlify(txid).decode('ascii'), i) for txid, i in tx_inputs],
['0' * 36 + ':' + str(3 * 10**8 - 1000)]))
binarize_tx(tx)
diff --git a/jmclient/test/test_wallets.py b/jmclient/test/test_wallets.py
index c9bce63..049a96f 100644
--- a/jmclient/test/test_wallets.py
+++ b/jmclient/test/test_wallets.py
@@ -1,19 +1,19 @@
#! /usr/bin/env python
-from __future__ import absolute_import
+from __future__ import (absolute_import, division,
+ print_function, unicode_literals)
+from builtins import * # noqa: F401
'''Wallet functionality tests.'''
-import sys
import os
import time
import binascii
-from mnemonic import Mnemonic
from commontest import create_wallet_for_sync, make_sign_and_push
import json
import pytest
from jmclient import (
load_program_config, jm_single, sync_wallet, get_log,
- estimate_tx_fee, BitcoinCoreInterface)
+ estimate_tx_fee, BitcoinCoreInterface, Mnemonic)
from taker_test_data import t_raw_signed_tx
testdir = os.path.dirname(os.path.realpath(__file__))
log = get_log()
@@ -94,9 +94,7 @@ def check_bip39_case(vectors, language="english"):
mnemo = Mnemonic(language)
for v in vectors:
code = mnemo.to_mnemonic(binascii.unhexlify(v[0]))
- seed = binascii.hexlify(Mnemonic.to_seed(code, passphrase=v[4]))
- if sys.version >= '3':
- seed = seed.decode('utf8')
+ seed = binascii.hexlify(Mnemonic.to_seed(code, passphrase=v[4])).decode('ascii')
print('checking this phrase: ' + v[1])
assert mnemo.check(v[1])
assert v[1] == code
diff --git a/jmdaemon/jmdaemon/daemon_protocol.py b/jmdaemon/jmdaemon/daemon_protocol.py
index 8a17261..510a4a8 100644
--- a/jmdaemon/jmdaemon/daemon_protocol.py
+++ b/jmdaemon/jmdaemon/daemon_protocol.py
@@ -2,6 +2,7 @@
from __future__ import (absolute_import, division,
print_function, unicode_literals)
from builtins import *
+from future.utils import iteritems
from .message_channel import MessageChannelCollection
from .orderbookwatch import OrderbookWatch
@@ -13,7 +14,6 @@ from .protocol import (COMMAND_PREFIX, ORDER_KEYS, NICK_HASH_LENGTH,
from .irc import IRCMessageChannel
from jmbase.commands import *
-from jmbase import _byteify
from twisted.protocols import amp
from twisted.internet import reactor, ssl
from twisted.internet.protocol import ServerFactory
@@ -72,7 +72,7 @@ def check_utxo_blacklist(commitment, persist=False):
fname = "commitmentlist"
if os.path.isfile(fname):
with open(fname, "rb") as f:
- blacklisted_commitments = [x.strip() for x in f.readlines()]
+ blacklisted_commitments = [x.decode('ascii').strip() for x in f.readlines()]
else:
blacklisted_commitments = []
if commitment in blacklisted_commitments:
@@ -80,7 +80,7 @@ def check_utxo_blacklist(commitment, persist=False):
elif persist:
blacklisted_commitments += [commitment]
with open(fname, "wb") as f:
- f.write('\n'.join(blacklisted_commitments))
+ f.write('\n'.join(blacklisted_commitments).encode('ascii'))
f.flush()
#If the commitment is new and we are *not* persisting, nothing to do
#(we only add it to the list on sending io_auth, which represents actual
@@ -242,9 +242,9 @@ class JMDaemonServerProtocol(amp.AMP, OrderbookWatch):
#Reset utxo data to null for this new transaction
self.ioauth_data = {}
self.active_orders = json.loads(filled_offers)
- for nick, offer_dict in self.active_orders.iteritems():
- offer_fill_msg = " ".join([str(offer_dict["oid"]), str(amount), str(
- self.kp.hex_pk()), str(commitment)])
+ for nick, offer_dict in iteritems(self.active_orders):
+ offer_fill_msg = " ".join([str(offer_dict["oid"]), str(amount),
+ self.kp.hex_pk().decode('ascii'), str(commitment)])
self.mcc.prepare_privmsg(nick, "fill", offer_fill_msg)
reactor.callLater(self.maker_timeout_sec, self.completeStage1)
self.jm_state = 2
@@ -293,8 +293,6 @@ class JMDaemonServerProtocol(amp.AMP, OrderbookWatch):
channel based on data from Maker. Relevant data (utxos, addresses)
are stored in the active_orders dict keyed by the nick of the Taker.
"""
- nick, utxolist, pubkey, cjaddr, changeaddr, pubkeysig = [_byteify(
- x) for x in (nick, utxolist, pubkey, cjaddr, changeaddr, pubkeysig)]
if not self.role == "MAKER":
return
if not nick in self.active_orders:
@@ -324,7 +322,7 @@ class JMDaemonServerProtocol(amp.AMP, OrderbookWatch):
broadcast one by one. TODO: could shorten this,
have more than one sig per message.
"""
- sigs = _byteify(json.loads(sigs))
+ sigs = json.loads(sigs)
for sig in sigs:
self.mcc.prepare_privmsg(nick, "sig", sig)
return {"accepted": True}
@@ -395,7 +393,7 @@ class JMDaemonServerProtocol(amp.AMP, OrderbookWatch):
"offer": offer,
"amount": amount,
"commit": scommit}
- self.mcc.prepare_privmsg(nick, "pubkey", kp.hex_pk())
+ self.mcc.prepare_privmsg(nick, "pubkey", kp.hex_pk().decode('ascii'))
@maker_only
def on_seen_auth(self, nick, commitment_revelation):
@@ -414,7 +412,7 @@ class JMDaemonServerProtocol(amp.AMP, OrderbookWatch):
commitment=ao["commit"],
revelation=json.dumps(commitment_revelation),
amount=ao["amount"],
- kphex=ao["kp"].hex_pk())
+ kphex=ao["kp"].hex_pk().decode('ascii'))
self.defaultCallbacks(d)
@maker_only
@@ -576,7 +574,7 @@ class JMDaemonServerProtocol(amp.AMP, OrderbookWatch):
).fetchone()
if crow is None:
return
- counterparty = crow[b'counterparty']
+ counterparty = crow['counterparty']
#TODO de-hardcode hp2
log.msg("Sending commitment to: " + str(counterparty))
self.mcc.prepare_privmsg(counterparty, 'hp2', commit)
diff --git a/jmdaemon/jmdaemon/enc_wrapper.py b/jmdaemon/jmdaemon/enc_wrapper.py
index 4866605..d4244b5 100644
--- a/jmdaemon/jmdaemon/enc_wrapper.py
+++ b/jmdaemon/jmdaemon/enc_wrapper.py
@@ -38,7 +38,7 @@ def get_pubkey(kp, as_hex=False):
optionally in hex."""
if not isinstance(kp, public.SecretKey):
raise NaclError("Object is not a nacl keypair")
- return kp.hex_pk() if as_hex else kp.pk
+ return kp.hex_pk().decode('ascii') if as_hex else kp.pk
def init_pubkey(hexpk, fname=None):
@@ -48,7 +48,7 @@ def init_pubkey(hexpk, fname=None):
"""
try:
bin_pk = binascii.unhexlify(hexpk)
- except TypeError:
+ except (TypeError, binascii.Error):
raise NaclError("Invalid hex")
if not len(bin_pk) == 32:
raise NaclError("Public key must be 32 bytes")
@@ -91,7 +91,7 @@ Notes:
# encoding for passing over the wire
def encrypt_encode(msg, box):
encrypted = box.encrypt(msg)
- return base64.b64encode(encrypted)
+ return base64.b64encode(encrypted).decode('ascii')
def decode_decrypt(msg, box):
diff --git a/jmdaemon/jmdaemon/irc.py b/jmdaemon/jmdaemon/irc.py
index 968ecc3..0e6553c 100644
--- a/jmdaemon/jmdaemon/irc.py
+++ b/jmdaemon/jmdaemon/irc.py
@@ -78,7 +78,7 @@ class IRCMessageChannel(MessageChannel):
daemon=None):
MessageChannel.__init__(self, daemon=daemon)
self.give_up = True
- self.serverport = (configdata['host'], configdata['port'])
+ self.serverport = (configdata['host'], int(configdata['port']))
#default hostid for use with miniircd which doesnt send NETWORK
self.hostid = configdata['host'] + str(configdata['port'])
self.socks5 = configdata["socks5"]
@@ -152,7 +152,7 @@ class IRCMessageChannel(MessageChannel):
else:
try:
factory = TxIRCFactory(self)
- wlog('build_irc: ', self.serverport[0], self.serverport[1],
+ wlog('build_irc: ', self.serverport[0], str(self.serverport[1]),
self.channel)
self.tcp_connector = reactor.connectTCP(
self.serverport[0], self.serverport[1], factory)
@@ -198,7 +198,7 @@ class txIRC_Client(irc.IRCClient, object):
def send(self, send_to, msg):
# todo: use proper twisted IRC support (encoding + sendCommand)
omsg = 'PRIVMSG %s :' % (send_to,) + msg
- self.sendLine(omsg.encode('ascii'))
+ self.sendLine(omsg)
def _pubmsg(self, message):
self.send(self.channel, message)
diff --git a/jmdaemon/jmdaemon/message_channel.py b/jmdaemon/jmdaemon/message_channel.py
index 165bb51..1e1c7d6 100644
--- a/jmdaemon/jmdaemon/message_channel.py
+++ b/jmdaemon/jmdaemon/message_channel.py
@@ -2,8 +2,10 @@
from __future__ import (absolute_import, division,
print_function, unicode_literals)
from builtins import * # noqa: F401
+from future.utils import iteritems
import abc
import base64
+import binascii
import threading
from jmdaemon import encrypt_encode, decode_decrypt, COMMAND_PREFIX,\
NICK_HASH_LENGTH, NICK_MAX_ENCODED, plaintext_commands,\
@@ -320,7 +322,7 @@ class MessageChannelCollection(object):
"""
for mc in self.available_channels():
filtered_nick_order_dict = {k: v
- for k, v in nick_order_dict.iteritems()
+ for k, v in iteritems(nick_order_dict)
if mc == self.active_channels[k]}
mc.fill_orders(filtered_nick_order_dict, cj_amount, taker_pubkey,
commitment)
@@ -336,7 +338,7 @@ class MessageChannelCollection(object):
#TODO supporting sending to arbitrary nicks
#adds quite a bit of complexity, not supported
#initially; will fail if nick is not part of TX
- txb64 = base64.b64encode(txhex.decode('hex'))
+ txb64 = base64.b64encode(binascii.unhexlify(txhex)).decode('ascii')
self.prepare_privmsg(nick, "push", txb64)
def send_tx(self, nick_list, txhex):
@@ -356,11 +358,11 @@ class MessageChannelCollection(object):
tx_nick_sets[self.active_channels[nick]] = [nick]
else:
tx_nick_sets[self.active_channels[nick]].append(nick)
- for mc, nl in tx_nick_sets.iteritems():
+ for mc, nl in iteritems(tx_nick_sets):
self.prepare_send_tx(mc, nl, txhex)
def prepare_send_tx(self, mc, nick_list, txhex):
- txb64 = base64.b64encode(txhex.decode('hex'))
+ txb64 = base64.b64encode(binascii.unhexlify(txhex)).decode('ascii')
for nick in nick_list:
self.prepare_privmsg(nick, "tx", txb64, mc=mc)
@@ -790,7 +792,7 @@ class MessageChannel(object):
# Taker callbacks
def fill_orders(self, nick_order_dict, cj_amount, taker_pubkey, commitment):
- for c, order in nick_order_dict.iteritems():
+ for c, order in iteritems(nick_order_dict):
msg = str(order['oid']) + ' ' + str(cj_amount) + ' ' + taker_pubkey
msg += ' ' + commitment
self.privmsg(c, 'fill', msg)
@@ -798,7 +800,7 @@ class MessageChannel(object):
def push_tx(self, nick, txhex):
#Note: not currently used; will require prepare_privmsg call so
#not in this class (see send_error)
- txb64 = base64.b64encode(txhex.decode('hex'))
+ txb64 = base64.b64encode(binascii.unhexlify(txhex)).decode('ascii')
self.privmsg(nick, 'push', txb64)
def send_error(self, nick, errormsg):
@@ -968,7 +970,7 @@ class MessageChannel(object):
elif _chunks[0] == 'tx':
b64tx = _chunks[1]
try:
- txhex = base64.b64decode(b64tx).encode('hex')
+ txhex = binascii.hexlify(base64.b64decode(b64tx)).decode('ascii')
except TypeError as e:
self.send_error(nick, 'bad base64 tx. ' + repr(e))
return
@@ -977,7 +979,7 @@ class MessageChannel(object):
elif _chunks[0] == 'push':
b64tx = _chunks[1]
try:
- txhex = base64.b64decode(b64tx).encode('hex')
+ txhex = binascii.hexlify(base64.b64decode(b64tx)).decode('ascii')
except TypeError as e:
self.send_error(nick, 'bad base64 tx. ' + repr(e))
return
diff --git a/jmdaemon/jmdaemon/orderbookwatch.py b/jmdaemon/jmdaemon/orderbookwatch.py
index 233e464..53e02c6 100644
--- a/jmdaemon/jmdaemon/orderbookwatch.py
+++ b/jmdaemon/jmdaemon/orderbookwatch.py
@@ -14,6 +14,13 @@ from jmbase.support import get_log, joinmarket_alert, DUST_THRESHOLD
log = get_log()
+def dict_factory(cursor, row):
+ d = {}
+ for idx, col in enumerate(cursor.description):
+ d[col[0]] = row[idx]
+ return d
+
+
class JMTakerError(Exception):
pass
@@ -30,11 +37,15 @@ class OrderbookWatch(object):
self.dblock = threading.Lock()
con = sqlite3.connect(":memory:", check_same_thread=False)
- con.row_factory = sqlite3.Row
+ con.row_factory = dict_factory
self.db = con.cursor()
- self.db.execute("CREATE TABLE orderbook(counterparty TEXT, "
- "oid INTEGER, ordertype TEXT, minsize INTEGER, "
- "maxsize INTEGER, txfee INTEGER, cjfee TEXT);")
+ try:
+ self.dblock.acquire(True)
+ self.db.execute("CREATE TABLE orderbook(counterparty TEXT, "
+ "oid INTEGER, ordertype TEXT, minsize INTEGER, "
+ "maxsize INTEGER, txfee INTEGER, cjfee TEXT);")
+ finally:
+ self.dblock.release()
@staticmethod
def on_set_topic(newtopic):
@@ -59,7 +70,11 @@ class OrderbookWatch(object):
txfee, cjfee):
try:
self.dblock.acquire(True)
- if int(oid) < 0 or int(oid) > sys.maxint:
+ if sys.version_info >= (3,0):
+ maxint = sys.maxsize
+ else:
+ maxint = sys.maxint
+ if int(oid) < 0 or int(oid) > maxint:
log.debug("Got invalid order ID: " + oid + " from " +
counterparty)
return
@@ -114,16 +129,25 @@ class OrderbookWatch(object):
self.dblock.release()
def on_order_cancel(self, counterparty, oid):
- with self.dblock:
+ try:
+ self.dblock.acquire(True)
self.db.execute(
("DELETE FROM orderbook WHERE "
"counterparty=? AND oid=?;"), (counterparty, oid))
+ finally:
+ self.dblock.release()
def on_nick_leave(self, nick):
- with self.dblock:
+ try:
+ self.dblock.acquire(True)
self.db.execute('DELETE FROM orderbook WHERE counterparty=?;',
(nick,))
+ finally:
+ self.dblock.release()
def on_disconnect(self):
- with self.dblock:
+ try:
+ self.dblock.acquire(True)
self.db.execute('DELETE FROM orderbook;')
+ finally:
+ self.dblock.release()
diff --git a/jmdaemon/jmdaemon/protocol.py b/jmdaemon/jmdaemon/protocol.py
index 0532cc5..25b5581 100644
--- a/jmdaemon/jmdaemon/protocol.py
+++ b/jmdaemon/jmdaemon/protocol.py
@@ -17,10 +17,10 @@ offertypes = {"reloffer": [(int, "oid"), (int, "minsize"), (int, "maxsize"),
"swabsoffer": [(int, "oid"), (int, "minsize"), (int, "maxsize"),
(int, "txfee"), (int, "cjfee")]}
-offername_list = offertypes.keys()
+offername_list = list(offertypes.keys())
-ORDER_KEYS = [b'counterparty', b'oid', b'ordertype', b'minsize', b'maxsize', b'txfee',
- b'cjfee']
+ORDER_KEYS = ['counterparty', 'oid', 'ordertype', 'minsize', 'maxsize', 'txfee',
+ 'cjfee']
COMMAND_PREFIX = '!'
JOINMARKET_NICK_HEADER = 'J'
@@ -36,5 +36,5 @@ commitment_broadcast_list = ["hp2"]
plaintext_commands += offername_list
plaintext_commands += commitment_broadcast_list
public_commands = commitment_broadcast_list + ["orderbook", "cancel"
- ] + list(offername_list)
+ ] + offername_list
private_commands = encrypted_commands + plaintext_commands
diff --git a/jmdaemon/test/test_daemon_protocol.py b/jmdaemon/test/test_daemon_protocol.py
index 2ea57ca..3190611 100644
--- a/jmdaemon/test/test_daemon_protocol.py
+++ b/jmdaemon/test/test_daemon_protocol.py
@@ -2,6 +2,7 @@
from __future__ import (absolute_import, division,
print_function, unicode_literals)
from builtins import *
+from future.utils import iteritems
'''test daemon-protocol interfacae.'''
from jmdaemon import MessageChannelCollection
@@ -11,6 +12,7 @@ from jmdaemon.protocol import NICK_HASH_LENGTH, NICK_MAX_ENCODED, JM_VERSION,\
JOINMARKET_NICK_HEADER
from jmclient import (load_program_config, get_log, jm_single, get_irc_mchannels)
from twisted.python.log import msg as tmsg
+from twisted.python.log import startLogging
from twisted.internet import protocol, reactor, task
from twisted.internet.protocol import ServerFactory
from twisted.internet.error import (ConnectionLost, ConnectionAborted,
@@ -22,6 +24,7 @@ from jmbase.commands import *
from msgdata import *
import json
import base64
+import sys
from dummy_mc import DummyMessageChannel
test_completed = False
end_early = False
@@ -84,7 +87,7 @@ class JMTestClientProtocol(JMBaseProtocol):
show_receipt("JMUP")
d = self.callRemote(JMSetup,
role="TAKER",
- n_counterparties=4) #TODO this number should be set
+ initdata="none")
self.defaultCallbacks(d)
return {'accepted': True}
@@ -103,7 +106,7 @@ class JMTestClientProtocol(JMBaseProtocol):
def maketx(self, ioauth_data):
ioauth_data = json.loads(ioauth_data)
- nl = ioauth_data.keys()
+ nl = list(ioauth_data.keys())
d = self.callRemote(JMMakeTx,
nick_list= json.dumps(nl),
txhex="deadbeef")
@@ -115,8 +118,8 @@ class JMTestClientProtocol(JMBaseProtocol):
return {'accepted': True}
jlog.debug("JMOFFERS" + str(orderbook))
#Trigger receipt of verified privmsgs, including unverified
- nick = str(t_chosen_orders.keys()[0])
- b64tx = base64.b64encode("deadbeef")
+ nick = str(list(t_chosen_orders.keys())[0])
+ b64tx = base64.b64encode(b"deadbeef").decode('ascii')
d1 = self.callRemote(JMMsgSignatureVerify,
verif_result=True,
nick=nick,
@@ -244,16 +247,16 @@ class JMDaemonTestServerProtocol(JMDaemonServerProtocol):
dummypub = "073732a7ca60470f709f23c602b2b8a6b1ba62ee8f3f83a61e5484ab5cbf9c3d"
#trigger invalid on_pubkey conditions
reactor.callLater(1, self.on_pubkey, "notrealcp", dummypub)
- reactor.callLater(2, self.on_pubkey, tmpfo.keys()[0], dummypub + "deadbeef")
+ reactor.callLater(2, self.on_pubkey, list(tmpfo.keys())[0], dummypub + "deadbeef")
#trigger invalid on_ioauth condition
reactor.callLater(2, self.on_ioauth, "notrealcp", 1, 2, 3, 4, 5)
#trigger msg sig verify request operation for a dummy message
#currently a pass-through
reactor.callLater(1, self.request_signature_verify, "1",
"!push abcd abc def", "3", "4",
- str(tmpfo.keys()[0]), 6, 7, self.mcc.mchannels[0].hostid)
+ str(list(tmpfo.keys())[0]), 6, 7, self.mcc.mchannels[0].hostid)
#send "valid" onpubkey, onioauth messages
- for k, v in tmpfo.iteritems():
+ for k, v in iteritems(tmpfo):
reactor.callLater(1, self.on_pubkey, k, dummypub)
reactor.callLater(2, self.on_ioauth, k, ['a', 'b'], "auth_pub",
"cj_addr", "change_addr", "btc_sig")
@@ -262,7 +265,7 @@ class JMDaemonTestServerProtocol(JMDaemonServerProtocol):
@JMMakeTx.responder
def on_JM_MAKE_TX(self, nick_list, txhex):
- for n in nick_list:
+ for n in json.loads(nick_list):
reactor.callLater(1, self.on_sig, n, "dummytxsig")
return super(JMDaemonTestServerProtocol, self).on_JM_MAKE_TX(nick_list,
txhex)
@@ -289,6 +292,7 @@ class JMDaemonTest2ServerProtocolFactory(ServerFactory):
class TrialTestJMDaemonProto(unittest.TestCase):
def setUp(self):
+ startLogging(sys.stdout)
load_program_config()
jm_single().maker_timeout_sec = 1
self.port = reactor.listenTCP(28184, JMDaemonTestServerProtocolFactory())
diff --git a/jmdaemon/test/test_enc_wrapper.py b/jmdaemon/test/test_enc_wrapper.py
index ef39b93..46d6084 100644
--- a/jmdaemon/test/test_enc_wrapper.py
+++ b/jmdaemon/test/test_enc_wrapper.py
@@ -16,10 +16,10 @@ from jmdaemon import (init_keypair, get_pubkey, init_pubkey, as_init_encryption,
# short ascii
(b"Attack at dawn", b"Not tonight Josephine!", 5),
# long base64 encoded
- (base64.b64encode(''.join(random.choice(
- string.ascii_letters) for _ in range(5000))),
- base64.b64encode(''.join(random.choice(
- string.ascii_letters) for _ in range(5000))),
+ (base64.b64encode(b''.join(random.choice(
+ string.ascii_letters).encode('ascii') for _ in range(5000))),
+ base64.b64encode(b''.join(random.choice(
+ string.ascii_letters).encode('ascii') for _ in range(5000))),
5,),
# large number of messages on the same connection
(b'rand', b'rand', 40000),
diff --git a/jmdaemon/test/test_message_channel.py b/jmdaemon/test/test_message_channel.py
index 9f54beb..12b558b 100644
--- a/jmdaemon/test/test_message_channel.py
+++ b/jmdaemon/test/test_message_channel.py
@@ -15,6 +15,7 @@ from msgdata import *
import time
import hashlib
import base64
+import struct
import traceback
import threading
import jmbitcoin as bitcoin
@@ -24,9 +25,9 @@ from dummy_mc import DummyMessageChannel
jlog = get_log()
def make_valid_nick(i=0):
- nick_priv = hashlib.sha256(chr(i)*16).hexdigest() + '01'
+ nick_priv = hashlib.sha256(struct.pack(b'B', i)*16).hexdigest() + '01'
nick_pubkey = bitcoin.privtopub(nick_priv)
- nick_pkh_raw = hashlib.sha256(nick_pubkey).digest()[:NICK_HASH_LENGTH]
+ nick_pkh_raw = hashlib.sha256(nick_pubkey.encode('ascii')).digest()[:NICK_HASH_LENGTH]
nick_pkh = bitcoin.b58encode(nick_pkh_raw)
#right pad to maximum possible; b58 is not fixed length.
#Use 'O' as one of the 4 not included chars in base58.
@@ -271,8 +272,8 @@ def test_setup_mc():
dmcs[0].on_privmsg(cps[2], "!reloffer sig1 sig2")
#Simulating receipt of encrypted messages:
#ioauth
- dummy_on_ioauth_msg = "deadbeef:0,deadbeef:1 XauthpubX XcjaddrX XchangeaddrX XbtcsigX"
- b64dummyioauth = base64.b64encode(dummy_on_ioauth_msg)
+ dummy_on_ioauth_msg = b"deadbeef:0,deadbeef:1 XauthpubX XcjaddrX XchangeaddrX XbtcsigX"
+ b64dummyioauth = base64.b64encode(dummy_on_ioauth_msg).decode('ascii')
dmcs[0].on_privmsg(cps[3], "!ioauth " + b64dummyioauth + " sig1 sig2")
#Try with a garbage b64 (but decodable); should throw index error at least
dmcs[0].on_privmsg(cps[3], "!ioauth _*_ sig1 sig2")
@@ -282,23 +283,23 @@ def test_setup_mc():
b64dummyioauth = "999"
dmcs[0].on_privmsg(cps[3], "!ioauth " + b64dummyioauth + " sig1 sig2")
#sig
- dummy_on_sig_msg = "dummysig"
- b64dummysig = base64.b64encode(dummy_on_sig_msg)
+ dummy_on_sig_msg = b"dummysig"
+ b64dummysig = base64.b64encode(dummy_on_sig_msg).decode('ascii')
dmcs[0].on_privmsg(cps[3], "!sig " + b64dummysig + " sig1 sig2")
#auth
- dummy_auth_msg = "dummyauth"
- b64dummyauth = base64.b64encode(dummy_auth_msg)
+ dummy_auth_msg = b"dummyauth"
+ b64dummyauth = base64.b64encode(dummy_auth_msg).decode('ascii')
dmcs[0].on_privmsg(cps[2], "!auth " + b64dummyauth + " sig1 sig2")
#invalid auth (only no message is invalid)
- dmcs[0].on_privmsg(cps[3], "!auth " +base64.b64encode("") + " sig1 sig2")
+ dmcs[0].on_privmsg(cps[3], "!auth " +base64.b64encode(b"").decode('ascii') + " sig1 sig2")
#tx
#valid
- dummy_tx = "deadbeefdeadbeef"
+ dummy_tx = b"deadbeefdeadbeef"
b64dummytx = base64.b64encode(dummy_tx)
- b642dummytx = base64.b64encode(b64dummytx)
+ b642dummytx = base64.b64encode(b64dummytx).decode('ascii')
dmcs[0].on_privmsg(cps[2], "!tx " + b642dummytx + " sig1 sig2")
- badbase64tx = "999"
- badbase64tx2 = base64.b64encode(badbase64tx)
+ badbase64tx = b"999"
+ badbase64tx2 = base64.b64encode(badbase64tx).decode('ascii')
#invalid txhex; here the first round will work (msg decryption), second shouldn't
dmcs[0].on_privmsg(cps[2], "!tx " + badbase64tx2 + " sig1 sig2")
#push
diff --git a/scripts/add-utxo.py b/scripts/add-utxo.py
index 5e0959c..263a788 100644
--- a/scripts/add-utxo.py
+++ b/scripts/add-utxo.py
@@ -1,5 +1,8 @@
#! /usr/bin/env python
-from __future__ import absolute_import
+from __future__ import (absolute_import, division,
+ print_function, unicode_literals)
+from builtins import * # noqa: F401
+from future.utils import iteritems
"""A very simple command line tool to import utxos to be used
as commitments into joinmarket's commitments.json file, allowing
users to retry transactions more often without getting banned by
@@ -156,18 +159,18 @@ def main():
if options.delete_ext:
other = options.in_file or options.in_json or options.loadwallet
if len(args) > 0 or other:
- if raw_input("You have chosen to delete commitments, other arguments "
+ if input("You have chosen to delete commitments, other arguments "
"will be ignored; continue? (y/n)") != 'y':
- print "Quitting"
+ print("Quitting")
sys.exit(0)
c, e = get_podle_commitments()
- print pformat(e)
- if raw_input(
+ print(pformat(e))
+ if input(
"You will remove the above commitments; are you sure? (y/n): ") != 'y':
- print "Quitting"
+ print("Quitting")
sys.exit(0)
update_commitments(external_to_remove=e)
- print "Commitments deleted."
+ print("Commitments deleted.")
sys.exit(0)
#Three options (-w, -r, -R) for loading utxo and privkey pairs from a wallet,
@@ -180,7 +183,7 @@ def main():
for md, utxos in wallet.get_utxos_by_mixdepth_().items():
for (txid, index), utxo in utxos.items():
- txhex = binascii.hexlify(txid) + ':' + str(index)
+ txhex = binascii.hexlify(txid).decode('ascii') + ':' + str(index)
wif = wallet.get_wif_path(utxo['path'])
utxo_data.append((txhex, wif))
@@ -196,19 +199,19 @@ def main():
utxo_data.append((u, priv))
elif options.in_json:
if not os.path.isfile(options.in_json):
- print "File: " + options.in_json + " not found."
+ print("File: " + options.in_json + " not found.")
sys.exit(0)
with open(options.in_json, "rb") as f:
try:
utxo_json = json.loads(f.read())
except:
- print "Failed to read json from " + options.in_json
+ print("Failed to read json from " + options.in_json)
sys.exit(0)
- for u, pva in utxo_json.iteritems():
+ for u, pva in iteritems(utxo_json):
utxo_data.append((u, pva['privkey']))
elif len(args) == 1:
u = args[0]
- priv = raw_input(
+ priv = input(
'input private key for ' + u + ', in WIF compressed format : ')
u, priv = get_utxo_info(','.join([u, priv]))
if not u:
diff --git a/scripts/cli_options.py b/scripts/cli_options.py
index 0ae91dd..29f121f 100644
--- a/scripts/cli_options.py
+++ b/scripts/cli_options.py
@@ -1,8 +1,10 @@
#! /usr/bin/env python
-from __future__ import absolute_import, print_function
+from __future__ import (absolute_import, division,
+ print_function, unicode_literals)
+from builtins import * # noqa: F401
import random
from optparse import OptionParser, OptionValueError
-from ConfigParser import NoOptionError
+from configparser import NoOptionError
import jmclient.support
@@ -58,7 +60,7 @@ def add_common_options(parser):
parser.add_option(
'--order-choose-algorithm',
action='callback',
- type=str,
+ type='string',
default=jmclient.support.random_under_max_order_choose,
callback=get_order_choose_algorithm,
help="Set the algorithm to use for selecting orders from the order book.\n"
@@ -113,7 +115,7 @@ def get_max_cj_fee_values(config, parser_options):
except NoOptionError:
pass
- if len(filter(lambda x: x is None, fee_values)):
+ if any(x is None for x in fee_values):
fee_values = prompt_user_for_cj_fee(*fee_values)
return tuple(map(lambda j: fee_types[j](fee_values[j]),
@@ -138,7 +140,7 @@ counterparties are selected."""
def prompt_user_value(m, val, check):
while True:
- data = raw_input(m)
+ data = input(m)
if data == 'y':
return val
try:
@@ -223,7 +225,7 @@ def get_tumbler_parser():
'logs directory, with name TUMBLE.schedule or what is set in the '
'schedulefile option.'))
parser.add_option('--schedulefile',
- type='str',
+ type='string',
dest='schedulefile',
default='TUMBLE.schedule',
help=('Name of schedule file for tumbler, useful for restart, default '
@@ -372,7 +374,7 @@ def get_sendpayment_parser():
default=random.randint(4, 6))
parser.add_option('-S',
'--schedule-file',
- type='str',
+ type='string',
dest='schedule',
help='schedule file name; see file "sample-schedule-for-testnet" for explanation and example',
default='')
diff --git a/scripts/convert_old_wallet.py b/scripts/convert_old_wallet.py
index 23bc5da..76bca6a 100644
--- a/scripts/convert_old_wallet.py
+++ b/scripts/convert_old_wallet.py
@@ -1,5 +1,7 @@
-#!/usr/bin/env python2
-
+#!/usr/bin/env python
+from __future__ import (absolute_import, division,
+ print_function, unicode_literals)
+from builtins import * # noqa: F401
import argparse
import json
import os.path
@@ -35,7 +37,7 @@ def decrypt_entropy_extension(enc_data, key):
if data[-9] != b'\xff':
raise ConvertException("Wrong password.")
chunks = data.split(b'\xff')
- if len(chunks) < 3 or data[-8:] != hexlify(double_sha256(chunks[1])[:4]):
+ if len(chunks) < 3 or data[-8:] != hexlify(double_sha256(chunks[1]).decode('ascii')[:4]):
raise ConvertException("Wrong password.")
return chunks[1]
@@ -92,7 +94,7 @@ def new_wallet_from_data(data, file_name):
for md in data['imported']:
for privkey in data['imported'][md]:
privkey += b'\x01'
- wif = wif_compressed_privkey(hexlify(privkey))
+ wif = wif_compressed_privkey(hexlify(privkey).decode('ascii'))
wallet.import_private_key(md, wif)
wallet.save()
diff --git a/scripts/joinmarket-qt.py b/scripts/joinmarket-qt.py
index dcc5663..ac8cc8d 100644
--- a/scripts/joinmarket-qt.py
+++ b/scripts/joinmarket-qt.py
@@ -1,5 +1,8 @@
#!/usr/bin/env python
-from __future__ import print_function
+from __future__ import (absolute_import, division,
+ print_function, unicode_literals)
+from builtins import *
+from future.utils import iteritems
'''
Joinmarket GUI using PyQt for doing coinjoins.
@@ -707,7 +710,7 @@ class SpendTab(QWidget):
mbinfo.append(" ")
mbinfo.append("Counterparties chosen:")
mbinfo.append('Name, Order id, Coinjoin fee (sat.)')
- for k, o in offers.iteritems():
+ for k, o in iteritems(offers):
if o['ordertype'] in ['swreloffer', 'reloffer']:
display_fee = int(self.taker.cjamount *
float(o['cjfee'])) - int(o['txfee'])
@@ -1256,7 +1259,7 @@ class JMMainWindow(QMainWindow):
mbtype='crit')
return
transaction.writerow(["%34s" % addr, pk])
- except (IOError, os.error), reason:
+ except (IOError, os.error) as reason:
export_error_label = "JoinmarketQt was unable to produce a private key-export."
JMQtMessageBox(None,
export_error_label + "\n" + str(reason),
diff --git a/scripts/joinmarketd.py b/scripts/joinmarketd.py
index 7aa20b8..b392198 100644
--- a/scripts/joinmarketd.py
+++ b/scripts/joinmarketd.py
@@ -1,3 +1,6 @@
+from __future__ import (absolute_import, division,
+ print_function, unicode_literals)
+from builtins import * # noqa: F401
import sys
from twisted.internet import reactor
from twisted.python.log import startLogging
diff --git a/scripts/obwatch/ob-watcher.py b/scripts/obwatch/ob-watcher.py
index 46ffef4..df37f4c 100644
--- a/scripts/obwatch/ob-watcher.py
+++ b/scripts/obwatch/ob-watcher.py
@@ -1,7 +1,11 @@
-from __future__ import absolute_import, print_function
-
-import BaseHTTPServer
-import SimpleHTTPServer
+from __future__ import (absolute_import, division,
+ print_function, unicode_literals)
+from builtins import *
+from future.utils import iteritems
+from past.builtins import cmp
+from functools import cmp_to_key
+
+import http.server
import base64
import io
import json
@@ -10,7 +14,7 @@ import time
import hashlib
import os
import sys
-import urllib2
+from future.moves.urllib.parse import parse_qs
from decimal import Decimal
from optparse import OptionParser
from twisted.internet import reactor
@@ -35,8 +39,8 @@ from jmdaemon.protocol import *
log = get_log()
#Initial state: allow only SW offer types
-swoffers = filter(lambda x: x[0:2] == 'sw', offername_list)
-pkoffers = filter(lambda x: x[0:2] != 'sw', offername_list)
+swoffers = list(filter(lambda x: x[0:2] == 'sw', offername_list))
+pkoffers = list(filter(lambda x: x[0:2] != 'sw', offername_list))
filtered_offername_list = swoffers
shutdownform = ''
@@ -53,73 +57,10 @@ def calc_depth_data(db, value):
pass
-def create_depth_chart(db, cj_amount, args=None):
- if args is None:
- args = {}
- rows = db.execute('SELECT * FROM orderbook;').fetchall()
- sqlorders = [o for o in rows if o["ordertype"] in filtered_offername_list]
- orderfees = sorted([calc_cj_fee(o['ordertype'], o['cjfee'], cj_amount) / 1e8
- for o in sqlorders
- if o['minsize'] <= cj_amount <= o[
- 'maxsize']])
-
- if len(orderfees) == 0:
- return 'No orders at amount ' + str(cj_amount / 1e8)
- fig = plt.figure()
- scale = args.get("scale")
- if (scale is not None) and (scale[0] == "log"):
- orderfees = [float(fee) for fee in orderfees]
- if orderfees[0] > 0:
- ratio = orderfees[-1] / orderfees[0]
- step = ratio ** 0.0333 # 1/30
- bins = [orderfees[0] * (step ** i) for i in range(30)]
- else:
- ratio = orderfees[-1] / 1e-8 # single satoshi placeholder
- step = ratio ** 0.0333 # 1/30
- bins = [1e-8 * (step ** i) for i in range(30)]
- bins[0] = orderfees[0] # replace placeholder
- plt.xscale('log')
- else:
- bins = 30
- if len(orderfees) == 1: # these days we have liquidity, but just in case...
- plt.hist(orderfees, bins, rwidth=0.8, range=(0, orderfees[0] * 2))
- else:
- plt.hist(orderfees, bins, rwidth=0.8)
- plt.grid()
- plt.title('CoinJoin Orderbook Depth Chart for amount=' + str(cj_amount /
- 1e8) + 'btc')
- plt.xlabel('CoinJoin Fee / btc')
- plt.ylabel('Frequency')
- return get_graph_html(fig)
-
-
-def create_size_histogram(db, args):
- rows = db.execute('SELECT maxsize, ordertype FROM orderbook;').fetchall()
- rows = [o for o in rows if o["ordertype"] in filtered_offername_list]
- ordersizes = sorted([r['maxsize'] / 1e8 for r in rows])
-
- fig = plt.figure()
- scale = args.get("scale")
- if (scale is not None) and (scale[0] == "log"):
- ratio = ordersizes[-1] / ordersizes[0]
- step = ratio ** 0.0333 # 1/30
- bins = [ordersizes[0] * (step ** i) for i in range(30)]
- else:
- bins = 30
- plt.hist(ordersizes, bins, histtype='bar', rwidth=0.8)
- if bins is not 30:
- fig.axes[0].set_xscale('log')
- plt.grid()
- plt.xlabel('Order sizes / btc')
- plt.ylabel('Frequency')
- return get_graph_html(fig) + ("
log scale" if
- bins == 30 else "
linear")
-
-
def get_graph_html(fig):
imbuf = io.BytesIO()
fig.savefig(imbuf, format='png')
- b64 = base64.b64encode(imbuf.getvalue())
+ b64 = base64.b64encode(imbuf.getvalue()).decode('utf-8')
return ''
@@ -151,36 +92,6 @@ def order_str(s, order, btc_unit, rel_unit):
return str(s)
-def create_orderbook_table(db, btc_unit, rel_unit):
- result = ''
- rows = db.execute('SELECT * FROM orderbook;').fetchall()
- if not rows:
- return 0, result
- #print("len rows before filter: " + str(len(rows)))
- rows = [o for o in rows if o["ordertype"] in filtered_offername_list]
- order_keys_display = (('ordertype', ordertype_display),
- ('counterparty', do_nothing), ('oid', order_str),
- ('cjfee', cjfee_display), ('txfee', satoshi_to_unit),
- ('minsize', satoshi_to_unit),
- ('maxsize', satoshi_to_unit))
-
- # somewhat complex sorting to sort by cjfee but with swabsoffers on top
-
- def orderby_cmp(x, y):
- if x['ordertype'] == y['ordertype']:
- return cmp(Decimal(x['cjfee']), Decimal(y['cjfee']))
- return cmp(offername_list.index(x['ordertype']),
- offername_list.index(y['ordertype']))
-
- for o in sorted(rows, cmp=orderby_cmp):
- result += '
\n'
- for key, displayer in order_keys_display:
- result += ' \n'
- return len(rows), result
-
-
def create_table_heading(btc_unit, rel_unit):
col = ' ' + displayer(o[key], o, btc_unit,
- rel_unit) + ' \n'
- result += '
| ' + displayer(o[key], o, btc_unit, + rel_unit) + ' | \n' + result += '