Compare commits

...

10 Commits

@ -0,0 +1,8 @@
[bumpversion]
current_version = 0.9.3
[bumpversion:file:README.rst]
[bumpversion:file:monero/__init__.py]
[bumpversion:file:docs/source/conf.py]

1
.gitignore vendored

@ -3,6 +3,7 @@
!.gitignore
!.travis.yml
!.pre-commit-config.yaml
!.bumpversion.cfg
*.py[co]
*~
*.bak

@ -18,6 +18,7 @@ install:
- pip install dist/*.tar.gz # install dependencies as specified in setup.py
- pip install -r test_requirements_py`echo $TRAVIS_PYTHON_VERSION | cut -f 1 -d .`.txt
script:
- black --check .
- pytest
after_success:
- coveralls

@ -14,7 +14,7 @@ Python Monero module
A comprehensive Python module for handling Monero cryptocurrency.
* release 0.9.2
* release 0.9.3
* open source: https://github.com/monero-ecosystem/monero-python
* works with Monero 0.13.x and `the latest source`_ (at least we try to keep up)
* Python 2.x and 3.x compatible
@ -36,17 +36,15 @@ Released under the BSD 3-Clause License. See `LICENSE.txt`_.
Copyright (c) 2017-2018 Michał Sałaban <michal@salaban.info> and Contributors:
`lalanza808`_, `cryptochangements34`_, `atward`_, `rooterkyberian`_, `brucexiu`_,
`lialsoftlab`_, `moneroexamples`_, `massanchik`_, `MrClottom`_, `jeffro256`_.
`lialsoftlab`_, `moneroexamples`_, `massanchik`_, `MrClottom`_, `jeffro256`_,
`sometato`_.
Copyright (c) 2016 The MoneroPy Developers (``monero/base58.py`` taken from `MoneroPy`_)
Copyright (c) 2011-2013 `pyca/ed25519`_ Developers (``monero/ed25519.py``)
Copyright (c) 2011 thomasv@gitorious (``monero/seed.py`` based on `Electrum`_)
.. _`LICENSE.txt`: LICENSE.txt
.. _`MoneroPy`: https://github.com/bigreddmachine/MoneroPy
.. _`pyca/ed25519`: https://github.com/pyca/ed25519
.. _`Electrum`: https://github.com/spesmilo/electrum
.. _`lalanza808`: https://github.com/lalanza808
@ -59,6 +57,7 @@ Copyright (c) 2011 thomasv@gitorious (``monero/seed.py`` based on `Electrum`_)
.. _`massanchik`: https://github.com/massanchik
.. _`MrClottom`: https://github.com/MrClottom
.. _`jeffro256`: https://github.com/jeffro256
.. _`sometato`: https://github.com/sometato
Want to help?
-------------
@ -91,3 +90,9 @@ Development
.. code-block:: bash
.venv/bin/pytest
6. Format your code with black
.. code-block:: bash
.venv/bin/black .

@ -3,8 +3,25 @@ Authors
* Michał Sałaban <michal@salaban.info>
* MoneroPy Developers (``monero/base58.py`` taken from `MoneroPy`_)
* thomasv@gitorious (``monero/seed.py`` based on `Electrum`_)
* and other Contributors: `lalanza808`_, `cryptochangements34`_, `atward`_, `rooterkyberian`_, `brucexiu`_, `lialsoftlab`_, `moneroexamples`_, `massanchik`_, `MrClottom`_, `jeffro256`_, `sometato`_.
.. _MoneroPy: https://github.com/bigreddmachine/MoneroPy
.. _`LICENSE.txt`: LICENSE.txt
.. _`MoneroPy`: https://github.com/bigreddmachine/MoneroPy
.. _`Electrum`: https://github.com/spesmilo/electrum
.. _`lalanza808`: https://github.com/lalanza808
.. _`cryptochangements34`: https://github.com/cryptochangements34
.. _`atward`: https://github.com/atward
.. _`rooterkyberian`: https://github.com/rooterkyberian
.. _`brucexiu`: https://github.com/brucexiu
.. _`lialsoftlab`: https://github.com/lialsoftlab
.. _`moneroexamples`: https://github.com/moneroexamples
.. _`massanchik`: https://github.com/massanchik
.. _`MrClottom`: https://github.com/MrClottom
.. _`jeffro256`: https://github.com/jeffro256
.. _`sometato`: https://github.com/sometato
Acknowledgements
----------------

@ -56,9 +56,9 @@ author = "Michal Salaban"
# built documents.
#
# The short X.Y version.
version = "0.9.2"
version = "0.9.3"
# The full version, including alpha/beta/rc tags.
release = "0.9.2"
release = "0.9.3"
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.

@ -164,6 +164,7 @@ methods in JSONRPCDaemon are designed to be lower-level. As such, the return val
methods reflect the raw JSON objects returned by the daemon. An example:
.. code-block:: python
[In 20]: from monero.backends.jsonrpc import JSONRPCDaemon
[In 21]: daemon = JSONRPCDaemon(host='192.168.0.50')

@ -1,3 +1,3 @@
from . import address, account, const, daemon, wallet, numbers, wordlists, seed
__version__ = "0.9.2"
__version__ = "0.9.3"

@ -95,14 +95,20 @@ class Address(BaseAddress):
:rtype: bool
"""
return ed25519.public_from_secret_hex(key) == self.view_key()
try:
return ed25519.public_from_secret_hex(key) == self.view_key()
except ValueError:
return False
def check_private_spend_key(self, key):
"""Checks if private spend key matches this address.
:rtype: bool
"""
return ed25519.public_from_secret_hex(key) == self.spend_key()
try:
return ed25519.public_from_secret_hex(key) == self.spend_key()
except ValueError:
return False
def with_payment_id(self, payment_id=0):
"""Integrates payment id into the address.

@ -106,8 +106,8 @@ class JSONRPCDaemon(object):
protocol=protocol, host=host, port=port
)
_log.debug("JSONRPC daemon backend URL: {url}".format(url=self.url))
self.user = user
self.password = password
self.auth = requests.auth.HTTPDigestAuth(user, password)
self.session = requests.Session()
self.timeout = timeout
self.verify_ssl_certs = verify_ssl_certs
self.proxies = {protocol: proxy_url}
@ -222,12 +222,11 @@ class JSONRPCDaemon(object):
path=path, data=json.dumps(data, indent=2, sort_keys=True)
)
)
auth = requests.auth.HTTPDigestAuth(self.user, self.password)
rsp = requests.post(
rsp = self.session.post(
self.url + path,
headers=hdr,
data=json.dumps(data) if data else None,
auth=auth,
auth=self.auth,
timeout=self.timeout,
verify=self.verify_ssl_certs,
proxies=self.proxies,
@ -251,12 +250,11 @@ class JSONRPCDaemon(object):
method=method, params=json.dumps(params, indent=2, sort_keys=True)
)
)
auth = requests.auth.HTTPDigestAuth(self.user, self.password)
rsp = requests.post(
rsp = self.session.post(
self.url + "/json_rpc",
headers=hdr,
data=json.dumps(data),
auth=auth,
auth=self.auth,
timeout=self.timeout,
verify=self.verify_ssl_certs,
proxies=self.proxies,

@ -50,8 +50,8 @@ class JSONRPCWallet(object):
protocol=protocol, host=host, port=port
)
_log.debug("JSONRPC wallet backend URL: {url}".format(url=self.url))
self.user = user
self.password = password
self.auth = requests.auth.HTTPDigestAuth(user, password)
self.session = requests.Session()
self.timeout = timeout
self.verify_ssl_certs = verify_ssl_certs
self.proxies = {protocol: proxy_url}
@ -386,12 +386,11 @@ class JSONRPCWallet(object):
method=method, params=json.dumps(params, indent=2, sort_keys=True)
)
)
auth = requests.auth.HTTPDigestAuth(self.user, self.password)
rsp = requests.post(
rsp = self.session.post(
self.url,
headers=hdr,
data=json.dumps(data),
auth=auth,
auth=self.auth,
timeout=self.timeout,
verify=self.verify_ssl_certs,
proxies=self.proxies,

@ -1,127 +1,19 @@
# ed25519.py - Optimized version of the reference implementation of Ed25519
#
# Written in 2011? by Daniel J. Bernstein <djb@cr.yp.to>
# 2013 by Donald Stufft <donald@stufft.io>
# 2013 by Alex Gaynor <alex.gaynor@gmail.com>
# 2013 by Greg Price <price@mit.edu>
# 2019 by Michal Salaban <michal@salaban.info>
#
# To the extent possible under law, the author(s) have dedicated all copyright
# and related and neighboring rights to this software to the public domain
# worldwide. This software is distributed without any warranty.
#
# You should have received a copy of the CC0 Public Domain Dedication along
# with this software. If not, see
# <http://creativecommons.org/publicdomain/zero/1.0/>.
"""
NB: This code is not safe for use with secret keys or secret data.
The only safe use of this code is for verifying signatures on public messages.
Functions for computing the public key of a secret key and for signing
a message are included, namely publickey_unsafe and signature_unsafe,
for testing purposes only.
The root of the problem is that Python's long-integer arithmetic is
not designed for use in cryptography. Specifically, it may take more
or less time to execute an operation depending on the values of the
inputs, and its memory access patterns may also depend on the inputs.
This opens it to timing and cache side-channel attacks which can
disclose data to an attacker. We rely on Python's long-integer
arithmetic, so we cannot handle secrets without risking their disclosure.
"""
import binascii
import six
import nacl.bindings
b = 256
q = 2 ** 255 - 19
l = 2 ** 252 + 27742317777372353535851937790883648493
def bit(h, i):
return (six.indexbytes(h, i // 8) >> (i % 8)) & 1
def encodeint(y):
bits = [(y >> i) & 1 for i in range(b)]
return b"".join(
[
six.int2byte(sum([bits[i * 8 + j] << j for j in range(8)]))
for i in range(b // 8)
]
)
def decodeint(s):
return sum(2 ** i * bit(s, i) for i in range(0, b))
edwards_add = nacl.bindings.crypto_core_ed25519_add
inv = nacl.bindings.crypto_core_ed25519_scalar_invert
public_from_secret = nacl.bindings.crypto_sign_ed25519_sk_to_pk
scalar_reduce = nacl.bindings.crypto_core_ed25519_scalar_reduce
scalar_add = nacl.bindings.crypto_core_ed25519_scalar_add
scalarmult_B = nacl.bindings.crypto_scalarmult_ed25519_base_noclamp
scalarmult = nacl.bindings.crypto_scalarmult_ed25519_noclamp
def scalarmult(P, e):
return nacl.bindings.crypto_scalarmult_ed25519_noclamp(e, P)
d = -121665 * decodeint(inv(encodeint(121666))) % q
I = pow(2, (q - 1) // 4, q)
def xrecover(y):
xx = (y * y - 1) * decodeint(inv(encodeint(d * y * y + 1)))
x = pow(xx, (q + 3) // 8, q)
if (x * x - xx) % q != 0:
x = (x * I) % q
if x % 2 != 0:
x = q - x
return x
By = 4 * decodeint(inv(encodeint(5)))
Bx = xrecover(By)
B = (Bx % q, By % q, 1, (Bx * By) % q)
ident = (0, 1, 1, 0)
def encodepoint(P):
(x, y, z, t) = P
zi = inv(z)
x = (x * zi) % q
y = (y * zi) % q
bits = [(y >> i) & 1 for i in range(b - 1)] + [x & 1]
return b"".join(
[
six.int2byte(sum([bits[i * 8 + j] << j for j in range(8)]))
for i in range(b // 8)
]
)
def decodepoint(s):
y = sum(2 ** i * bit(s, i) for i in range(0, b - 1))
x = xrecover(y)
if x & 1 != bit(s, b - 1):
x = q - x
P = (x, y, 1, (x * y) % q)
return P
def pad_to_64B(v):
return nacl.bindings.utils.sodium_pad(v, 64)
def scalar_reduce(v):
return nacl.bindings.crypto_core_ed25519_scalar_reduce(v + (64 - len(v)) * b"\0")
def public_from_secret_hex(hk):
return binascii.hexlify(
public_from_secret(pad_to_64B(binascii.unhexlify(hk)))
).decode()
try:
return binascii.hexlify(scalarmult_B(binascii.unhexlify(hk))).decode()
except nacl.exceptions.RuntimeError:
raise ValueError("Invalid secret key")

@ -117,9 +117,6 @@ class Seed(object):
return True
raise ValueError("Invalid checksum")
def _sc_reduce(self, input):
return hexlify(ed25519.scalar_reduce(ed25519.pad_to_64B(input))).decode()
def hex_seed(self):
return self.hex
@ -128,7 +125,7 @@ class Seed(object):
def secret_spend_key(self):
a = self._hex_seed_keccak() if self.is_mymonero() else unhexlify(self.hex)
return self._sc_reduce(a)
return hexlify(ed25519.scalar_reduce(a)).decode()
def secret_view_key(self):
b = (
@ -136,7 +133,7 @@ class Seed(object):
if self.is_mymonero()
else unhexlify(self.secret_spend_key())
)
return self._sc_reduce(keccak_256(b).digest())
return hexlify(ed25519.scalar_reduce(keccak_256(b).digest())).decode()
def public_spend_key(self):
if self._ed_pub_spend_key:

@ -142,21 +142,19 @@ class Transaction(object):
def _scan_pubkeys(svk, psk, stealth_address, amount, encamount):
for keyidx, tx_key in enumerate(self.pubkeys):
# precompute
svk_2 = ed25519.scalar_add(svk, svk)
svk_4 = ed25519.scalar_add(svk_2, svk_2)
svk_8 = ed25519.scalar_add(svk_4, svk_4)
#
hsdata = b"".join(
[
ed25519.scalarmult(
tx_key, ed25519.encodeint(ed25519.decodeint(svk) * 8)
),
ed25519.scalarmult(svk_8, tx_key),
varint.encode(idx),
]
)
Hs_ur = keccak_256(hsdata).digest()
# sc_reduce32:
Hsint_ur = ed25519.decodeint(Hs_ur)
Hsint = Hsint_ur % ed25519.l
Hs = ed25519.encodeint(Hsint)
Hs = ed25519.scalar_reduce(Hs_ur)
k = ed25519.edwards_add(
ed25519.scalarmult_B(Hs),
psk,

@ -231,9 +231,11 @@ class Wallet(object):
)
m = keccak_256(hsdata).digest()
# D = master_psk + m * B
D = ed25519.edwards_add(master_psk, ed25519.scalarmult_B(m))
D = ed25519.edwards_add(
master_psk, ed25519.scalarmult_B(ed25519.scalar_reduce(m))
)
# C = master_svk * D
C = ed25519.scalarmult(D, master_svk)
C = ed25519.scalarmult(master_svk, D)
netbyte = bytearray(
[const.SUBADDR_NETBYTES[const.NETS.index(master_address.net)]]
)

@ -1,3 +1,4 @@
black==21.11b1
coverage~=5.3
coveralls~=2.1
pip>=9

@ -1,122 +0,0 @@
{
"2ec46011b23b0c00468946f1d9a64995bf0a89f9ee0bbf4f64058a3acd81a70e": {
"integer": 6628339198216413857236352180108225378148743212953972540346314253902012269614,
"modulo": 6628339198216413857236352180108225378148743212953972540346314253902012269614,
"result": "2ec46011b23b0c00468946f1d9a64995bf0a89f9ee0bbf4f64058a3acd81a70e"
},
"25e0cf207358c6a1347dcba42119c0b695bb7823a0cc6ad856de6d372288d17f": {
"integer": 57813942366592237174432678471109775286345684008086513999063590953232999899173,
"modulo": 7154903325266401676620372529808815600345869492427160757049934385234820142250,
"result": "aa141796baa24539583306300b44a72495bb7823a0cc6ad856de6d372288d10f"
},
"600d3c5022e1844dd2df02f178a074fc2e566793e99d9e1465926adcbfa9b508": {
"integer": 3939473675085984986992368553178981174068994160171572258582957763871603690848,
"modulo": 3939473675085984986992368553178981174068994160171572258582957763871603690848,
"result": "600d3c5022e1844dd2df02f178a074fc2e566793e99d9e1465926adcbfa9b508"
},
"9531701ea6eafeac65a21e62e26e105cbb12b96d682bfc320b4f8ce935e2d323": {
"integer": 16205315679229594349692122491359510638187130104178740652140889924125210980757,
"modulo": 1731304524565069921745749365273522156472897385418925440136988047554302478779,
"result": "bb8984647124dafcb8682f1c257b5232bb12b96d682bfc320b4f8ce935e2d303"
},
"a8e8a30d3638cc4d09d1fa9f4de12ac0096c69a77896774793627c0cc6a28703": {
"integer": 1596586321787417762488266696268089527089621022149808638093194755286593956008,
"modulo": 1596586321787417762488266696268089527089621022149808638093194755286593956008,
"result": "a8e8a30d3638cc4d09d1fa9f4de12ac0096c69a77896774793627c0cc6a28703"
},
"9410478406b82c923cec509bf8e8bf857b8de3b45236c9842cb876212427f1d3": {
"integer": 95864091335870547385163600694014568338142560187395956431101203204900223651988,
"modulo": 1783018830551138603512175374455643207000047515457157553075841007189318389131,
"result": "8b4dcbcbafaf3d195af5bd54aa386d767a8de3b45236c9842cb876212427f103"
},
"597703dd73d0da6b3996b83c3e1e2f602be4f0de453e15846171aa9076901603": {
"integer": 1396806229157654325406612422616318744215090798882912232993621199577392838489,
"modulo": 1396806229157654325406612422616318744215090798882912232993621199577392838489,
"result": "597703dd73d0da6b3996b83c3e1e2f602be4f0de453e15846171aa9076901603"
},
"84dc0b095dfde492abee8087efbd2269b714fac032f1c3dff659ca26ab430f69": {
"integer": 47519818838455871225365520876286444378141740832067494560806350640166365551748,
"modulo": 4097785374462297941526401498028478932999042675788048924794645010453640045814,
"result": "f6e448dbbeaa7682a541b3b5b7e2e8ebb614fac032f1c3dff659ca26ab430f09"
},
"193152abe15c5e0a0ff56e3020229398769cd7c6ca5a4e30e439d6702c4f320a": {
"integer": 4612017275153737097907034112534798197384252782681849631504289240246595498265,
"modulo": 4612017275153737097907034112534798197384252782681849631504289240246595498265,
"result": "193152abe15c5e0a0ff56e3020229398769cd7c6ca5a4e30e439d6702c4f320a"
},
"cdb967c501195827d78a791e1173d4b8826a5ae73b0885984898c84b6c9dd80c": {
"integer": 5810479642822955659735279987239253355362863496018367030298598645652997519821,
"modulo": 5810479642822955659735279987239253355362863496018367030298598645652997519821,
"result": "cdb967c501195827d78a791e1173d4b8826a5ae73b0885984898c84b6c9dd80c"
},
"29c8d9e91c1cb59e059bddd901e011db85f8d4f00f967226ffb5e185bd10e70d": {
"integer": 6288324241017125450135585489376912591668237464955021703284104294893526566953,
"modulo": 6288324241017125450135585489376912591668237464955021703284104294893526566953,
"result": "29c8d9e91c1cb59e059bddd901e011db85f8d4f00f967226ffb5e185bd10e70d"
},
"f9c935bd64b45a34d537814006aa569341030c34f2d1efecc4eb26ea9f838b22": {
"integer": 15625137033897289677611928611975874263404959545762802384938837865992272857593,
"modulo": 1151125879232765249665555485889885781690726827002987172934935989421364355615,
"result": "1f224a0330ee358428fe91fa48b6986941030c34f2d1efecc4eb26ea9f838b02"
},
"a047598095d2ada065af73758f7082900b9b0d721b5f99a541a78bd461ffc607": {
"integer": 3517788241725899011075135813684493241587423920731267486065832167600161376160,
"modulo": 3517788241725899011075135813684493241587423920731267486065832167600161376160,
"result": "a047598095d2ada065af73758f7082900b9b0d721b5f99a541a78bd461ffc607"
},
"080c6135edf93233176d41c8535caef0f13d596dc5093b5a5afa4279339dbc00": {
"integer": 333252210082402815912805449335296231262512726833157454332209494259012799496,
"modulo": 333252210082402815912805449335296231262512726833157454332209494259012799496,
"result": "080c6135edf93233176d41c8535caef0f13d596dc5093b5a5afa4279339dbc00"
},
"482700617ba810f94035d7f4d7ccc1a29878e165b4867872b705204c85406906": {
"integer": 2899841338757337401439250404000262340768069237371615667279145359232485828424,
"modulo": 2899841338757337401439250404000262340768069237371615667279145359232485828424,
"result": "482700617ba810f94035d7f4d7ccc1a29878e165b4867872b705204c85406906"
},
"12b0ee7f6adbd85a7ee6c298527fd805cd25de7842aa0722abeb12697f1719d3": {
"integer": 95482344402833444566475004546782631202940389090036531688630083907873449881618,
"modulo": 1401271897514035784823579227223706071797876418097732810604721710162544618761,
"result": "09ed72c713d3e9e19bef2f5204cf85f6cb25de7842aa0722abeb12697f171903"
},
"0e15b4e0f31c7023f59c07e50bb24676798a2d28b6072091e054238d84591483": {
"integer": 59288937934704856670126753414446243614245232688387735062206342841157186491662,
"modulo": 1392893316046758958341260910102289687388301813348474214190735334873552483750,
"result": "a67505f92004dd6242b64acd16e34ecf788a2d28b6072091e054238d84591403"
},
"6661ba3dc3d75bf15a00890fa99454e38d0d0ed36e38b3c827c4c00370af1aff": {
"integer": 115386925237937118400643168199482218242653593459875731046215557413505242653030,
"modulo": 6831841577953185191045369753837304629796848069177116956186293339223428888195,
"result": "83f652cb370948c8cbcf06839df043aa8c0d0ed36e38b3c827c4c00370af1a0f"
},
"60916cfcb10fa0b2b0648e36ecd7037f5c1972d36b2e6d56c2f4feca613a4200": {
"integer": 117014844056279701262384447223800575458979231802741572058244012970802450784,
"modulo": 117014844056279701262384447223800575458979231802741572058244012970802450784,
"result": "60916cfcb10fa0b2b0648e36ecd7037f5c1972d36b2e6d56c2f4feca613a4200"
},
"2d05fa6dad90f748d7fb364e610b1703041fb501f1f80e0cb3b4b4638b5f7176": {
"integer": 53573229274981178047805367505496460267398966421504169209158271959949458933037,
"modulo": 2914190233655342549993061564195500581399151905844815967144615391951279176114,
"result": "b23941e3f4da76e0fab171d94a36fe70031fb501f1f80e0cb3b4b4638b5f7106"
},
"6dc31f6ebcf834ab375a69006cb19c66fcccfa0732dfb3ea1b0662b455226b0d": {
"integer": 6069356637481544937951349412679035329690355688191943063509197966002018567021,
"modulo": 6069356637481544937951349412679035329690355688191943063509197966002018567021,
"result": "6dc31f6ebcf834ab375a69006cb19c66fcccfa0732dfb3ea1b0662b455226b0d"
},
"8382125d125754da8ddeb8f89cbd5d9591fe31216a9cf6fb2d6b3c78698ce8ba": {
"integer": 84541067443461413931254155152843369596662288304236779390986978391229457400451,
"modulo": 4934006092806529577549102959370432947234008351057795724965518070089460639572,
"result": "5467825ef0148a11582115f80b01c9af90fe31216a9cf6fb2d6b3c78698ce80a"
},
"5973d91299466a9a51ddfcd20d1710c776aa1399279b292b264ab6b7ab608105": {
"integer": 2490154711420054482973427955977087630958526490925203328128860118211022648153,
"modulo": 2490154711420054482973427955977087630958526490925203328128860118211022648153,
"result": "5973d91299466a9a51ddfcd20d1710c776aa1399279b292b264ab6b7ab608105"
},
"3922528967d829c5334978295f4aaa4a24154334a3b43af1da05244ec4cf252d": {
"integer": 20420885481516297805400244677782227685119906340516184899355036869276044763705,
"modulo": 5946874326851773377453871551696239203405673621756369687351134992705136261727,
"result": "5f7a66cf32120515870f89e3a156ec2024154334a3b43af1da05244ec4cf250d"
}
}

@ -1,31 +0,0 @@
from binascii import hexlify, unhexlify
import json
import os
import unittest
from monero import ed25519
class TestEd25519(unittest.TestCase):
base_path = os.path.join(os.path.dirname(__file__), "data", "test_ed25519")
def modulo_python(self, v):
return v % ed25519.l
def test_scalar_reduce(self):
with open(os.path.join(self.base_path, "scalar_reduce.json"), "rb") as jsonfile:
suite = json.load(jsonfile)
for input_, data in suite.items():
input_bin = ed25519.pad_to_64B(unhexlify(input_))
integer = ed25519.decodeint(input_bin)
print(integer)
print(ed25519.l)
self.assertEqual(data["integer"], integer)
modulo_bin = ed25519.scalar_reduce(input_bin)
print(hexlify(modulo_bin).decode())
print(hexlify(ed25519.encodeint(self.modulo_python(integer))).decode())
print(ed25519.decodeint(modulo_bin))
print(data["modulo"])
self.assertEqual(data["modulo"], ed25519.decodeint(modulo_bin))
modulo_hex = hexlify(modulo_bin).decode()
self.assertEqual(data["result"], modulo_hex)

@ -1,6 +1,7 @@
from datetime import datetime
from decimal import Decimal
import responses
import requests
try:
from unittest.mock import patch, Mock
@ -50,7 +51,7 @@ class JSONRPCWalletTestCase(JSONTestCase):
},
}
@patch("monero.backends.jsonrpc.wallet.requests.post")
@patch.object(requests.Session, "post")
def test_seed(self, mock_post):
mock_post.return_value.status_code = 200
mock_post.return_value.json.return_value = self.accounts_result
@ -70,7 +71,7 @@ class JSONRPCWalletTestCase(JSONTestCase):
self.assertIsInstance(seed, Seed)
self.assertEqual(seed.phrase, phrase)
@patch("monero.backends.jsonrpc.wallet.requests.post")
@patch.object(requests.Session, "post")
def test_balance(self, mock_post):
mock_post.return_value.status_code = 200
mock_post.return_value.json.return_value = self.accounts_result
@ -219,7 +220,7 @@ class JSONRPCWalletTestCase(JSONTestCase):
self.assertIsInstance(subaddr, SubAddress)
self.assertIsInstance(index, int)
@patch("monero.backends.jsonrpc.wallet.requests.post")
@patch.object(requests.Session, "post")
def test_incoming_confirmed(self, mock_post):
mock_post.return_value.status_code = 200
mock_post.return_value.json.return_value = self.accounts_result
@ -369,7 +370,7 @@ class JSONRPCWalletTestCase(JSONTestCase):
self.assertIsInstance(pmt.transaction.fee, Decimal)
self.assertIsInstance(pmt.transaction.height, int)
@patch("monero.backends.jsonrpc.wallet.requests.post")
@patch.object(requests.Session, "post")
def test_incoming_confirmed_and_unconfirmed(self, mock_post):
mock_post.return_value.status_code = 200
mock_post.return_value.json.return_value = self.accounts_result
@ -549,7 +550,7 @@ class JSONRPCWalletTestCase(JSONTestCase):
self.assertIsInstance(pmt.transaction.fee, Decimal)
self.assertIsInstance(pmt.transaction.height, (int, type(None)))
@patch("monero.backends.jsonrpc.wallet.requests.post")
@patch.object(requests.Session, "post")
def test_incoming_unconfirmed(self, mock_post):
mock_post.return_value.status_code = 200
mock_post.return_value.json.return_value = self.accounts_result
@ -851,7 +852,7 @@ class JSONRPCWalletTestCase(JSONTestCase):
self.assertEqual(pmts[0].amount, Decimal("0.52"))
self.assertEqual(pmts[1].amount, Decimal("0.0212"))
@patch("monero.backends.jsonrpc.wallet.requests.post")
@patch.object(requests.Session, "post")
def test_incoming_by_payment_ids(self, mock_post):
# These queries will use get_bulk_payments RPC method instead of get_transfers
mock_post.return_value.status_code = 200
@ -962,7 +963,7 @@ class JSONRPCWalletTestCase(JSONTestCase):
self.assertIsInstance(pmt.transaction.height, int)
self.assertIn(pmt.payment_id, ids)
@patch("monero.backends.jsonrpc.wallet.requests.post")
@patch.object(requests.Session, "post")
def test_outgoing(self, mock_post):
mock_post.return_value.status_code = 200
mock_post.return_value.json.return_value = self.accounts_result
@ -1189,7 +1190,7 @@ class JSONRPCWalletTestCase(JSONTestCase):
self.assertIsInstance(pmt.transaction.fee, Decimal)
self.assertIsInstance(pmt.transaction.height, int)
@patch("monero.backends.jsonrpc.wallet.requests.post")
@patch.object(requests.Session, "post")
def test_outgoing_confirmed_and_unconfirmed(self, mock_post):
mock_post.return_value.status_code = 200
mock_post.return_value.json.return_value = self.accounts_result
@ -1432,7 +1433,7 @@ class JSONRPCWalletTestCase(JSONTestCase):
self.assertIsInstance(pmt.transaction.fee, Decimal)
self.assertIsInstance(pmt.transaction.height, (int, type(None)))
@patch("monero.backends.jsonrpc.wallet.requests.post")
@patch.object(requests.Session, "post")
def test_outgoing_unconfirmed_only(self, mock_post):
mock_post.return_value.status_code = 200
mock_post.return_value.json.return_value = self.accounts_result
@ -1493,7 +1494,7 @@ class JSONRPCWalletTestCase(JSONTestCase):
self.assertEqual(len(pmt.destinations), 2)
self.assertEqual(pmt.destinations[0][1] + pmt.destinations[1][1], pmt.amount)
@patch("monero.backends.jsonrpc.wallet.requests.post")
@patch.object(requests.Session, "post")
def test_send_transfer(self, mock_post):
mock_post.return_value.status_code = 200
mock_post.return_value.json.return_value = self.accounts_result
@ -1562,7 +1563,7 @@ class JSONRPCWalletTestCase(JSONTestCase):
self.assertIsInstance(result[0], Transaction)
self.assertEqual(Decimal("111.086545699972"), result[1])
@patch("monero.backends.jsonrpc.wallet.requests.post")
@patch.object(requests.Session, "post")
def test_dynamic_ring_size_deprecation(self, mock_post):
mock_post.return_value.status_code = 200
mock_post.return_value.json.return_value = self.accounts_result
@ -1587,7 +1588,7 @@ class JSONRPCWalletTestCase(JSONTestCase):
},
}
@patch("monero.backends.jsonrpc.wallet.requests.post")
@patch.object(requests.Session, "post")
def test_export_import_outputs(self, mock_post):
mock_post.return_value.status_code = 200
mock_post.return_value.json.return_value = self.accounts_result
@ -1608,7 +1609,7 @@ class JSONRPCWalletTestCase(JSONTestCase):
}
self.assertEqual(self.wallet.import_outputs(outs_hex), 9)
@patch("monero.backends.jsonrpc.wallet.requests.post")
@patch.object(requests.Session, "post")
def test_export_import_key_images(self, mock_post):
mock_post.return_value.status_code = 200
mock_post.return_value.json.return_value = self.accounts_result

@ -9,7 +9,13 @@ from monero.daemon import Daemon
def url_data(url):
gs = re.compile(r"^(?P<host>[^:\s]+)(?::(?P<port>[0-9]+))?$").match(url).groupdict()
gs = (
re.compile(
r"^(?:(?P<user>[a-z0-9_-]+)?(?::(?P<password>[^@]+))?@)?(?P<host>[^:\s]+)(?::(?P<port>[0-9]+))?$"
)
.match(url)
.groupdict()
)
return dict(filter(operator.itemgetter(1), gs.items()))
@ -20,7 +26,7 @@ def get_daemon():
nargs="?",
type=url_data,
default="127.0.0.1:18081",
help="Daemon RPC URL [host[:port]]",
help="Daemon RPC URL [user[:password]@]host[:port]",
)
argsparser.add_argument(
"-p", dest="proxy_url", nargs="?", type=str, default=None, help="Proxy URL"

Loading…
Cancel
Save